"use strict"; var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; var __metadata = (this && this.__metadata) || function (k, v) { if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); }; var __param = (this && this.__param) || function (paramIndex, decorator) { return function (target, key) { decorator(target, key, paramIndex); } }; var GeocodingInitService_1; var _a; Object.defineProperty(exports, "__esModule", { value: true }); exports.GeocodingInitService = void 0; const common_1 = require("@nestjs/common"); const typeorm_1 = require("@nestjs/typeorm"); const typeorm_2 = require("typeorm"); const place_syria_entity_1 = require("./entities/place-syria.entity"); let GeocodingInitService = GeocodingInitService_1 = class GeocodingInitService { repo; logger = new common_1.Logger(GeocodingInitService_1.name); constructor(repo) { this.repo = repo; } async onModuleInit() { this.logger.log('Checking for PostGIS extensions and triggers...'); try { await this.repo.query('CREATE EXTENSION IF NOT EXISTS postgis;'); await this.repo.query('CREATE EXTENSION IF NOT EXISTS pg_trgm;'); const tables = ['places_jordan', 'places_syria', 'places_egypt']; const columnMapping = [ { old: 'admin_level4_id', new: 'governorate_id' }, { old: 'admin_level6_id', new: 'district_id' }, { old: 'admin_level8_id', new: 'sub_district_id' }, { old: 'admin_level10_id', new: 'neighborhood_id' } ]; for (const table of tables) { for (const mapping of columnMapping) { await this.repo.query(` DO $$ BEGIN IF EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = '${table}' AND column_name = '${mapping.old}') THEN ALTER TABLE ${table} RENAME COLUMN ${mapping.old} TO ${mapping.new}; END IF; END $$; `); } } await this.repo.query(` CREATE OR REPLACE FUNCTION sync_place_location() RETURNS trigger AS $$ BEGIN IF NEW.latitude IS NOT NULL AND NEW.longitude IS NOT NULL THEN NEW.location := ST_SetSRID(ST_MakePoint(CAST(NEW.longitude AS FLOAT), CAST(NEW.latitude AS FLOAT)), 4326); -- Keep standard admin boundary logic for higher levels NEW.governorate_id := (SELECT id FROM admin_boundaries WHERE admin_level = 4 AND ST_Contains(geom, NEW.location) LIMIT 1); NEW.district_id := (SELECT id FROM admin_boundaries WHERE admin_level = 6 AND ST_Contains(geom, NEW.location) LIMIT 1); NEW.sub_district_id := (SELECT id FROM admin_boundaries WHERE admin_level = 8 AND ST_Contains(geom, NEW.location) LIMIT 1); -- ROOT CAUSE FIX: Use the new Voronoi polygons for neighborhoods! NEW.neighborhood_id := (SELECT id FROM neighborhood_polygons ORDER BY NEW.location::geometry <-> geometry::geometry LIMIT 1); END IF; RETURN NEW; END; $$ LANGUAGE plpgsql; `); await this.repo.query(` DROP TRIGGER IF EXISTS trg_sync_place_location ON places_syria; CREATE TRIGGER trg_sync_place_location BEFORE INSERT OR UPDATE ON places_syria FOR EACH ROW EXECUTE FUNCTION sync_place_location(); `); await this.repo.query(` DROP TRIGGER IF EXISTS trg_sync_place_location_jordan ON places_jordan; CREATE TRIGGER trg_sync_place_location_jordan BEFORE INSERT OR UPDATE ON places_jordan FOR EACH ROW EXECUTE FUNCTION sync_place_location(); `); await this.repo.query(` DROP TRIGGER IF EXISTS trg_sync_place_location_egypt ON places_egypt; CREATE TRIGGER trg_sync_place_location_egypt BEFORE INSERT OR UPDATE ON places_egypt FOR EACH ROW EXECUTE FUNCTION sync_place_location(); `); await this.repo.query('CREATE INDEX IF NOT EXISTS idx_places_jordan_location ON places_jordan USING gist (location);'); await this.repo.query('CREATE INDEX IF NOT EXISTS idx_places_egypt_location ON places_egypt USING gist (location);'); await this.repo.query('CREATE INDEX IF NOT EXISTS idx_places_jordan_names_trgm ON places_jordan USING gist (name_ar gist_trgm_ops, name_en gist_trgm_ops);'); await this.repo.query('CREATE INDEX IF NOT EXISTS idx_places_egypt_names_trgm ON places_egypt USING gist (name_ar gist_trgm_ops, name_en gist_trgm_ops);'); this.logger.log('Geocoding database triggers and optimized indexes initialized for Syria, Jordan, and Egypt.'); } catch (err) { this.logger.error('Failed to initialize database geocoding triggers:', err); } } }; exports.GeocodingInitService = GeocodingInitService; exports.GeocodingInitService = GeocodingInitService = GeocodingInitService_1 = __decorate([ (0, common_1.Injectable)(), __param(0, (0, typeorm_1.InjectRepository)(place_syria_entity_1.PlaceSyria)), __metadata("design:paramtypes", [typeof (_a = typeof typeorm_2.Repository !== "undefined" && typeorm_2.Repository) === "function" ? _a : Object]) ], GeocodingInitService); //# sourceMappingURL=geocoding-init.service.js.map