104 lines
5.7 KiB
JavaScript
104 lines
5.7 KiB
JavaScript
"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;
|
|
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", [typeorm_2.Repository])
|
|
], GeocodingInitService);
|
|
//# sourceMappingURL=geocoding-init.service.js.map
|