fix(tactical): resolve DTO types and TS1272 build error for isolatedModules
This commit is contained in:
@@ -24,9 +24,9 @@ export declare class AdministrativeLinkingService {
|
||||
total_polygons: number;
|
||||
districts_processed: any;
|
||||
}>;
|
||||
linkPlaces(country: 'jordan' | 'syria' | 'egypt'): Promise<{
|
||||
linkPlaces(country: 'jordan' | 'syria' | 'egypt' | 'iraq'): Promise<{
|
||||
status: string;
|
||||
country: "syria" | "jordan" | "egypt";
|
||||
country: "iraq" | "syria" | "jordan" | "egypt";
|
||||
total_places: number;
|
||||
linked_neighborhood: number;
|
||||
linked_district: number;
|
||||
|
||||
+12
-2
@@ -72,8 +72,13 @@ let AdministrativeLinkingService = AdministrativeLinkingService_1 = class Admini
|
||||
this.logger.log(`Found ${elements.length} points in OSM.`);
|
||||
let detectedCountry = country;
|
||||
if (!detectedCountry) {
|
||||
const firstLat = parseFloat(bbox.split(',')[0]);
|
||||
if (firstLat > 32.3)
|
||||
const parts = bbox.split(',').map(parseFloat);
|
||||
const firstLat = parts[0];
|
||||
const lngs = [parts[1], parts[3]].filter(n => !isNaN(n));
|
||||
const maxLng = lngs.length ? Math.max(...lngs) : undefined;
|
||||
if (maxLng !== undefined && maxLng > 42.5)
|
||||
detectedCountry = 'iraq';
|
||||
else if (firstLat > 32.3)
|
||||
detectedCountry = 'syria';
|
||||
else if (firstLat < 31.0)
|
||||
detectedCountry = 'egypt';
|
||||
@@ -106,8 +111,13 @@ let AdministrativeLinkingService = AdministrativeLinkingService_1 = class Admini
|
||||
LIMIT 1
|
||||
),
|
||||
(
|
||||
-- حدّ 50كم إلزامي: بدونه تُسنَد نقطة لا تقع داخل أي حدود إلى أقرب
|
||||
-- مقاطعة في الجدول كله مهما بَعُدت. حين استوردنا العراق قبل حدوده
|
||||
-- الإدارية، رُبطت أحياء بغداد الـ185 بمقاطعات سورية/أردنية على بعد
|
||||
-- ~700كم. عدم الربط أفضل من ربط خاطئ صامت.
|
||||
SELECT id FROM admin_boundaries ab
|
||||
WHERE ab.admin_level IN (6, 8)
|
||||
AND ST_DWithin(ab.geom::geography, np.geometry::geography, 50000)
|
||||
ORDER BY ab.geom::geometry <-> np.geometry::geometry
|
||||
LIMIT 1
|
||||
)
|
||||
|
||||
File diff suppressed because one or more lines are too long
+2
-2
@@ -51,8 +51,8 @@ __decorate([
|
||||
], SearchQueryDto.prototype, "radius", void 0);
|
||||
__decorate([
|
||||
(0, class_validator_1.IsOptional)(),
|
||||
(0, class_validator_1.IsEnum)(['jordan', 'syria', 'egypt']),
|
||||
(0, swagger_1.ApiPropertyOptional)({ description: 'Country filter', enum: ['jordan', 'syria', 'egypt'] }),
|
||||
(0, class_validator_1.IsEnum)(['jordan', 'syria', 'egypt', 'iraq']),
|
||||
(0, swagger_1.ApiPropertyOptional)({ description: 'Country filter', enum: ['jordan', 'syria', 'egypt', 'iraq'] }),
|
||||
__metadata("design:type", String)
|
||||
], SearchQueryDto.prototype, "country", void 0);
|
||||
//# sourceMappingURL=search-query.dto.js.map
|
||||
+1
-1
@@ -1 +1 @@
|
||||
{"version":3,"file":"search-query.dto.js","sourceRoot":"","sources":["../../../src/geocoding/dto/search-query.dto.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,qDAAmF;AACnF,yDAAyC;AACzC,6CAAsD;AAEtD,MAAa,cAAc;IAGzB,CAAC,CAAS;IAMV,GAAG,CAAU;IAMb,GAAG,CAAU;IAQb,MAAM,GAAY,KAAK,CAAC;IAKxB,OAAO,CAAU;CAClB;AA7BD,wCA6BC;AA1BC;IAFC,IAAA,0BAAQ,GAAE;IACV,IAAA,6BAAmB,EAAC,EAAE,WAAW,EAAE,qBAAqB,EAAE,CAAC;;yCAClD;AAMV;IAJC,IAAA,4BAAU,GAAE;IACZ,IAAA,0BAAQ,GAAE;IACV,IAAA,wBAAI,EAAC,GAAG,EAAE,CAAC,MAAM,CAAC;IAClB,IAAA,6BAAmB,EAAC,EAAE,WAAW,EAAE,+BAA+B,EAAE,CAAC;;2CACzD;AAMb;IAJC,IAAA,4BAAU,GAAE;IACZ,IAAA,0BAAQ,GAAE;IACV,IAAA,wBAAI,EAAC,GAAG,EAAE,CAAC,MAAM,CAAC;IAClB,IAAA,6BAAmB,EAAC,EAAE,WAAW,EAAE,gCAAgC,EAAE,CAAC;;2CAC1D;AAQb;IANC,IAAA,4BAAU,GAAE;IACZ,IAAA,0BAAQ,GAAE;IACV,IAAA,qBAAG,EAAC,CAAC,CAAC;IACN,IAAA,qBAAG,EAAC,KAAK,CAAC;IACV,IAAA,wBAAI,EAAC,GAAG,EAAE,CAAC,MAAM,CAAC;IAClB,IAAA,6BAAmB,EAAC,EAAE,WAAW,EAAE,4BAA4B,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;;8CAC3D;AAKxB;IAHC,IAAA,4BAAU,GAAE;IACZ,IAAA,wBAAM,EAAC,CAAC,QAAQ,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;IACpC,IAAA,6BAAmB,EAAC,EAAE,WAAW,EAAE,gBAAgB,EAAE,IAAI,EAAE,CAAC,QAAQ,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,CAAC;;+CAC1E"}
|
||||
{"version":3,"file":"search-query.dto.js","sourceRoot":"","sources":["../../../src/geocoding/dto/search-query.dto.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,qDAAmF;AACnF,yDAAyC;AACzC,6CAAsD;AAEtD,MAAa,cAAc;IAGzB,CAAC,CAAS;IAMV,GAAG,CAAU;IAMb,GAAG,CAAU;IAQb,MAAM,GAAY,KAAK,CAAC;IAKxB,OAAO,CAAU;CAClB;AA7BD,wCA6BC;AA1BC;IAFC,IAAA,0BAAQ,GAAE;IACV,IAAA,6BAAmB,EAAC,EAAE,WAAW,EAAE,qBAAqB,EAAE,CAAC;;yCAClD;AAMV;IAJC,IAAA,4BAAU,GAAE;IACZ,IAAA,0BAAQ,GAAE;IACV,IAAA,wBAAI,EAAC,GAAG,EAAE,CAAC,MAAM,CAAC;IAClB,IAAA,6BAAmB,EAAC,EAAE,WAAW,EAAE,+BAA+B,EAAE,CAAC;;2CACzD;AAMb;IAJC,IAAA,4BAAU,GAAE;IACZ,IAAA,0BAAQ,GAAE;IACV,IAAA,wBAAI,EAAC,GAAG,EAAE,CAAC,MAAM,CAAC;IAClB,IAAA,6BAAmB,EAAC,EAAE,WAAW,EAAE,gCAAgC,EAAE,CAAC;;2CAC1D;AAQb;IANC,IAAA,4BAAU,GAAE;IACZ,IAAA,0BAAQ,GAAE;IACV,IAAA,qBAAG,EAAC,CAAC,CAAC;IACN,IAAA,qBAAG,EAAC,KAAK,CAAC;IACV,IAAA,wBAAI,EAAC,GAAG,EAAE,CAAC,MAAM,CAAC;IAClB,IAAA,6BAAmB,EAAC,EAAE,WAAW,EAAE,4BAA4B,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;;8CAC3D;AAKxB;IAHC,IAAA,4BAAU,GAAE;IACZ,IAAA,wBAAM,EAAC,CAAC,QAAQ,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;IAC5C,IAAA,6BAAmB,EAAC,EAAE,WAAW,EAAE,gBAAgB,EAAE,IAAI,EAAE,CAAC,QAAQ,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,CAAC,EAAE,CAAC;;+CAClF"}
|
||||
@@ -7,7 +7,8 @@ export declare enum CandidateStatus {
|
||||
export declare enum CountryCode {
|
||||
JORDAN = "JORDAN",
|
||||
SYRIA = "SYRIA",
|
||||
EGYPT = "EGYPT"
|
||||
EGYPT = "EGYPT",
|
||||
IRAQ = "IRAQ"
|
||||
}
|
||||
export declare class MapCandidate extends BasePlace {
|
||||
status: CandidateStatus;
|
||||
|
||||
@@ -23,6 +23,7 @@ var CountryCode;
|
||||
CountryCode["JORDAN"] = "JORDAN";
|
||||
CountryCode["SYRIA"] = "SYRIA";
|
||||
CountryCode["EGYPT"] = "EGYPT";
|
||||
CountryCode["IRAQ"] = "IRAQ";
|
||||
})(CountryCode || (exports.CountryCode = CountryCode = {}));
|
||||
let MapCandidate = class MapCandidate extends base_place_entity_1.BasePlace {
|
||||
status;
|
||||
|
||||
@@ -1 +1 @@
|
||||
{"version":3,"file":"map-candidate.entity.js","sourceRoot":"","sources":["../../../src/geocoding/entities/map-candidate.entity.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,qCAAgD;AAChD,2DAAgD;AAEhD,IAAY,eAIX;AAJD,WAAY,eAAe;IACzB,sCAAmB,CAAA;IACnB,wCAAqB,CAAA;IACrB,wCAAqB,CAAA;AACvB,CAAC,EAJW,eAAe,+BAAf,eAAe,QAI1B;AAED,IAAY,WAIX;AAJD,WAAY,WAAW;IACrB,gCAAiB,CAAA;IACjB,8BAAe,CAAA;IACf,8BAAe,CAAA;AACjB,CAAC,EAJW,WAAW,2BAAX,WAAW,QAItB;AAGM,IAAM,YAAY,GAAlB,MAAM,YAAa,SAAQ,6BAAS;IAOzC,MAAM,CAAkB;IAIxB,WAAW,CAAS;IAGpB,eAAe,CAAS;IAQxB,OAAO,CAAc;IAGrB,QAAQ,CAAM;IAGd,aAAa,CAAS;IAGtB,gBAAgB,CAAS;IAGzB,qBAAqB,CAAM;CAC5B,CAAA;AAnCY,oCAAY;AAOvB;IANC,IAAA,gBAAM,EAAC;QACN,IAAI,EAAE,MAAM;QACZ,IAAI,EAAE,eAAe;QACrB,OAAO,EAAE,eAAe,CAAC,OAAO;KACjC,CAAC;IACD,IAAA,eAAK,GAAE;;4CACgB;AAIxB;IAFC,IAAA,gBAAM,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;IAC1B,IAAA,eAAK,GAAE;;iDACY;AAGpB;IADC,IAAA,gBAAM,EAAC,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;;qDACjB;AAQxB;IANC,IAAA,gBAAM,EAAC;QACN,IAAI,EAAE,MAAM;QACZ,IAAI,EAAE,WAAW;QACjB,OAAO,EAAE,WAAW,CAAC,MAAM;KAC5B,CAAC;IACD,IAAA,eAAK,GAAE;;6CACa;AAGrB;IADC,IAAA,gBAAM,EAAC,EAAE,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;;8CAC5B;AAGd;IADC,IAAA,gBAAM,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;;mDACL;AAGtB;IADC,IAAA,gBAAM,EAAC,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC;;sDACX;AAGzB;IADC,IAAA,gBAAM,EAAC,EAAE,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;;2DACf;uBAlChB,YAAY;IADxB,IAAA,gBAAM,EAAC,gBAAgB,CAAC;GACZ,YAAY,CAmCxB"}
|
||||
{"version":3,"file":"map-candidate.entity.js","sourceRoot":"","sources":["../../../src/geocoding/entities/map-candidate.entity.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,qCAAgD;AAChD,2DAAgD;AAEhD,IAAY,eAIX;AAJD,WAAY,eAAe;IACzB,sCAAmB,CAAA;IACnB,wCAAqB,CAAA;IACrB,wCAAqB,CAAA;AACvB,CAAC,EAJW,eAAe,+BAAf,eAAe,QAI1B;AAED,IAAY,WAKX;AALD,WAAY,WAAW;IACrB,gCAAiB,CAAA;IACjB,8BAAe,CAAA;IACf,8BAAe,CAAA;IACf,4BAAa,CAAA;AACf,CAAC,EALW,WAAW,2BAAX,WAAW,QAKtB;AAGM,IAAM,YAAY,GAAlB,MAAM,YAAa,SAAQ,6BAAS;IAOzC,MAAM,CAAkB;IAIxB,WAAW,CAAS;IAGpB,eAAe,CAAS;IAQxB,OAAO,CAAc;IAGrB,QAAQ,CAAM;IAGd,aAAa,CAAS;IAGtB,gBAAgB,CAAS;IAGzB,qBAAqB,CAAM;CAC5B,CAAA;AAnCY,oCAAY;AAOvB;IANC,IAAA,gBAAM,EAAC;QACN,IAAI,EAAE,MAAM;QACZ,IAAI,EAAE,eAAe;QACrB,OAAO,EAAE,eAAe,CAAC,OAAO;KACjC,CAAC;IACD,IAAA,eAAK,GAAE;;4CACgB;AAIxB;IAFC,IAAA,gBAAM,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;IAC1B,IAAA,eAAK,GAAE;;iDACY;AAGpB;IADC,IAAA,gBAAM,EAAC,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;;qDACjB;AAQxB;IANC,IAAA,gBAAM,EAAC;QACN,IAAI,EAAE,MAAM;QACZ,IAAI,EAAE,WAAW;QACjB,OAAO,EAAE,WAAW,CAAC,MAAM;KAC5B,CAAC;IACD,IAAA,eAAK,GAAE;;6CACa;AAGrB;IADC,IAAA,gBAAM,EAAC,EAAE,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;;8CAC5B;AAGd;IADC,IAAA,gBAAM,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;;mDACL;AAGtB;IADC,IAAA,gBAAM,EAAC,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC;;sDACX;AAGzB;IADC,IAAA,gBAAM,EAAC,EAAE,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;;2DACf;uBAlChB,YAAY;IADxB,IAAA,gBAAM,EAAC,gBAAgB,CAAC;GACZ,YAAY,CAmCxB"}
|
||||
@@ -0,0 +1,3 @@
|
||||
import { BasePlace } from './base-place.entity';
|
||||
export declare class PlaceIraq extends BasePlace {
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
"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;
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.PlaceIraq = void 0;
|
||||
const typeorm_1 = require("typeorm");
|
||||
const base_place_entity_1 = require("./base-place.entity");
|
||||
let PlaceIraq = class PlaceIraq extends base_place_entity_1.BasePlace {
|
||||
};
|
||||
exports.PlaceIraq = PlaceIraq;
|
||||
exports.PlaceIraq = PlaceIraq = __decorate([
|
||||
(0, typeorm_1.Entity)('places_iraq')
|
||||
], PlaceIraq);
|
||||
//# sourceMappingURL=place-iraq.entity.js.map
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"place-iraq.entity.js","sourceRoot":"","sources":["../../../src/geocoding/entities/place-iraq.entity.ts"],"names":[],"mappings":";;;;;;;;;AAAA,qCAAiC;AACjC,2DAAgD;AAGzC,IAAM,SAAS,GAAf,MAAM,SAAU,SAAQ,6BAAS;CAAG,CAAA;AAA9B,8BAAS;oBAAT,SAAS;IADrB,IAAA,gBAAM,EAAC,aAAa,CAAC;GACT,SAAS,CAAqB"}
|
||||
+10
-2
@@ -30,7 +30,7 @@ let GeocodingInitService = GeocodingInitService_1 = class GeocodingInitService {
|
||||
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 tables = ['places_jordan', 'places_syria', 'places_egypt', 'places_iraq'];
|
||||
const columnMapping = [
|
||||
{ old: 'admin_level4_id', new: 'governorate_id' },
|
||||
{ old: 'admin_level6_id', new: 'district_id' },
|
||||
@@ -84,12 +84,20 @@ let GeocodingInitService = GeocodingInitService_1 = class GeocodingInitService {
|
||||
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(`
|
||||
DROP TRIGGER IF EXISTS trg_sync_place_location_iraq ON places_iraq;
|
||||
CREATE TRIGGER trg_sync_place_location_iraq
|
||||
BEFORE INSERT OR UPDATE ON places_iraq
|
||||
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_iraq_location ON places_iraq 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.');
|
||||
await this.repo.query('CREATE INDEX IF NOT EXISTS idx_places_iraq_names_trgm ON places_iraq 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, Egypt, and Iraq.');
|
||||
}
|
||||
catch (err) {
|
||||
this.logger.error('Failed to initialize database geocoding triggers:', err);
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
{"version":3,"file":"geocoding-init.service.js","sourceRoot":"","sources":["../../src/geocoding/geocoding-init.service.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AAAA,2CAAkE;AAClE,6CAAmD;AACnD,qCAAqC;AACrC,sEAA2D;AAGpD,IAAM,oBAAoB,4BAA1B,MAAM,oBAAoB;IAKZ;IAJF,MAAM,GAAG,IAAI,eAAM,CAAC,sBAAoB,CAAC,IAAI,CAAC,CAAC;IAEhE,YAEmB,IAA4B;QAA5B,SAAI,GAAJ,IAAI,CAAwB;IAC5C,CAAC;IAEJ,KAAK,CAAC,YAAY;QAChB,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,iDAAiD,CAAC,CAAC;QACnE,IAAI,CAAC;YAEH,MAAM,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,yCAAyC,CAAC,CAAC;YACjE,MAAM,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,yCAAyC,CAAC,CAAC;YAGjE,MAAM,MAAM,GAAG,CAAC,eAAe,EAAE,cAAc,EAAE,cAAc,CAAC,CAAC;YACjE,MAAM,aAAa,GAAG;gBACpB,EAAE,GAAG,EAAE,iBAAiB,EAAE,GAAG,EAAE,gBAAgB,EAAE;gBACjD,EAAE,GAAG,EAAE,iBAAiB,EAAE,GAAG,EAAE,aAAa,EAAE;gBAC9C,EAAE,GAAG,EAAE,iBAAiB,EAAE,GAAG,EAAE,iBAAiB,EAAE;gBAClD,EAAE,GAAG,EAAE,kBAAkB,EAAE,GAAG,EAAE,iBAAiB,EAAE;aACpD,CAAC;YAEF,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;gBAC3B,KAAK,MAAM,OAAO,IAAI,aAAa,EAAE,CAAC;oBACpC,MAAM,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC;;;wFAGwD,KAAK,wBAAwB,OAAO,CAAC,GAAG;8BAClG,KAAK,kBAAkB,OAAO,CAAC,GAAG,OAAO,OAAO,CAAC,GAAG;;;WAGvE,CAAC,CAAC;gBACL,CAAC;YACH,CAAC;YAGD,MAAM,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC;;;;;;;;;;;;;;;;;OAiBrB,CAAC,CAAC;YAEH,MAAM,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC;;;;;OAKrB,CAAC,CAAC;YAGH,MAAM,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC;;;;;OAKrB,CAAC,CAAC;YAEH,MAAM,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC;;;;;OAKrB,CAAC,CAAC;YAGH,MAAM,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,+FAA+F,CAAC,CAAC;YACvH,MAAM,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,6FAA6F,CAAC,CAAC;YAGrH,MAAM,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,qIAAqI,CAAC,CAAC;YAC7J,MAAM,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,mIAAmI,CAAC,CAAC;YAE3J,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,6FAA6F,CAAC,CAAC;QACjH,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,mDAAmD,EAAE,GAAG,CAAC,CAAC;QAC9E,CAAC;IACH,CAAC;CACF,CAAA;AA5FY,oDAAoB;+BAApB,oBAAoB;IADhC,IAAA,mBAAU,GAAE;IAKR,WAAA,IAAA,0BAAgB,EAAC,+BAAU,CAAC,CAAA;yDACN,oBAAU,oBAAV,oBAAU;GALxB,oBAAoB,CA4FhC"}
|
||||
{"version":3,"file":"geocoding-init.service.js","sourceRoot":"","sources":["../../src/geocoding/geocoding-init.service.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AAAA,2CAAkE;AAClE,6CAAmD;AACnD,qCAAqC;AACrC,sEAA2D;AAGpD,IAAM,oBAAoB,4BAA1B,MAAM,oBAAoB;IAKZ;IAJF,MAAM,GAAG,IAAI,eAAM,CAAC,sBAAoB,CAAC,IAAI,CAAC,CAAC;IAEhE,YAEmB,IAA4B;QAA5B,SAAI,GAAJ,IAAI,CAAwB;IAC5C,CAAC;IAEJ,KAAK,CAAC,YAAY;QAChB,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,iDAAiD,CAAC,CAAC;QACnE,IAAI,CAAC;YAEH,MAAM,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,yCAAyC,CAAC,CAAC;YACjE,MAAM,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,yCAAyC,CAAC,CAAC;YAGjE,MAAM,MAAM,GAAG,CAAC,eAAe,EAAE,cAAc,EAAE,cAAc,EAAE,aAAa,CAAC,CAAC;YAChF,MAAM,aAAa,GAAG;gBACpB,EAAE,GAAG,EAAE,iBAAiB,EAAE,GAAG,EAAE,gBAAgB,EAAE;gBACjD,EAAE,GAAG,EAAE,iBAAiB,EAAE,GAAG,EAAE,aAAa,EAAE;gBAC9C,EAAE,GAAG,EAAE,iBAAiB,EAAE,GAAG,EAAE,iBAAiB,EAAE;gBAClD,EAAE,GAAG,EAAE,kBAAkB,EAAE,GAAG,EAAE,iBAAiB,EAAE;aACpD,CAAC;YAEF,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;gBAC3B,KAAK,MAAM,OAAO,IAAI,aAAa,EAAE,CAAC;oBACpC,MAAM,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC;;;wFAGwD,KAAK,wBAAwB,OAAO,CAAC,GAAG;8BAClG,KAAK,kBAAkB,OAAO,CAAC,GAAG,OAAO,OAAO,CAAC,GAAG;;;WAGvE,CAAC,CAAC;gBACL,CAAC;YACH,CAAC;YAGD,MAAM,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC;;;;;;;;;;;;;;;;;OAiBrB,CAAC,CAAC;YAEH,MAAM,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC;;;;;OAKrB,CAAC,CAAC;YAGH,MAAM,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC;;;;;OAKrB,CAAC,CAAC;YAEH,MAAM,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC;;;;;OAKrB,CAAC,CAAC;YAEH,MAAM,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC;;;;;OAKrB,CAAC,CAAC;YAGH,MAAM,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,+FAA+F,CAAC,CAAC;YACvH,MAAM,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,6FAA6F,CAAC,CAAC;YACrH,MAAM,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,2FAA2F,CAAC,CAAC;YAGnH,MAAM,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,qIAAqI,CAAC,CAAC;YAC7J,MAAM,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,mIAAmI,CAAC,CAAC;YAC3J,MAAM,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,iIAAiI,CAAC,CAAC;YAEzJ,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,mGAAmG,CAAC,CAAC;QACvH,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,mDAAmD,EAAE,GAAG,CAAC,CAAC;QAC9E,CAAC;IACH,CAAC;CACF,CAAA;AArGY,oDAAoB;+BAApB,oBAAoB;IADhC,IAAA,mBAAU,GAAE;IAKR,WAAA,IAAA,0BAAgB,EAAC,+BAAU,CAAC,CAAA;yDACN,oBAAU,oBAAV,oBAAU;GALxB,oBAAoB,CAqGhC"}
|
||||
+9
-2
@@ -49,6 +49,13 @@ export declare class GeocodingController {
|
||||
processed: number;
|
||||
created: number;
|
||||
updated: number;
|
||||
failed: number;
|
||||
errors: {
|
||||
index: number;
|
||||
name?: string;
|
||||
reason: string;
|
||||
}[];
|
||||
errorsTruncated: boolean;
|
||||
}>;
|
||||
getPlaces(limit?: string): Promise<any[]>;
|
||||
getGeoJSON(): Promise<{
|
||||
@@ -87,9 +94,9 @@ export declare class GeocodingController {
|
||||
total_polygons: number;
|
||||
districts_processed: any;
|
||||
}>;
|
||||
linkPlaces(country: 'jordan' | 'syria' | 'egypt'): Promise<{
|
||||
linkPlaces(country: 'jordan' | 'syria' | 'egypt' | 'iraq'): Promise<{
|
||||
status: string;
|
||||
country: "syria" | "jordan" | "egypt";
|
||||
country: "iraq" | "syria" | "jordan" | "egypt";
|
||||
total_places: number;
|
||||
linked_neighborhood: number;
|
||||
linked_district: number;
|
||||
|
||||
+4
-4
@@ -135,7 +135,7 @@ __decorate([
|
||||
(0, swagger_1.ApiOperation)({ summary: 'Delete a place by name or ID' }),
|
||||
(0, swagger_1.ApiQuery)({ name: 'name', required: false }),
|
||||
(0, swagger_1.ApiQuery)({ name: 'id', required: false, type: Number }),
|
||||
(0, swagger_1.ApiQuery)({ name: 'country', required: true, enum: ['jordan', 'syria', 'egypt'] }),
|
||||
(0, swagger_1.ApiQuery)({ name: 'country', required: true, enum: ['jordan', 'syria', 'egypt', 'iraq'] }),
|
||||
__param(0, (0, common_1.Query)('country')),
|
||||
__param(1, (0, common_1.Query)('name')),
|
||||
__param(2, (0, common_1.Query)('id')),
|
||||
@@ -200,7 +200,7 @@ __decorate([
|
||||
(0, common_1.UseGuards)(admin_guard_1.AdminGuard),
|
||||
(0, swagger_1.ApiOperation)({ summary: 'Sync neighborhood points from OSM for a bbox' }),
|
||||
(0, swagger_1.ApiQuery)({ name: 'bbox', required: false }),
|
||||
(0, swagger_1.ApiQuery)({ name: 'country', required: false, enum: ['jordan', 'syria', 'egypt'] }),
|
||||
(0, swagger_1.ApiQuery)({ name: 'country', required: false, enum: ['jordan', 'syria', 'egypt', 'iraq'] }),
|
||||
__param(0, (0, common_1.Query)('bbox')),
|
||||
__param(1, (0, common_1.Query)('country')),
|
||||
__metadata("design:type", Function),
|
||||
@@ -211,7 +211,7 @@ __decorate([
|
||||
(0, common_1.Post)('admin/generate-voronoi'),
|
||||
(0, common_1.UseGuards)(admin_guard_1.AdminGuard),
|
||||
(0, swagger_1.ApiOperation)({ summary: 'Generate Voronoi polygons for neighborhoods' }),
|
||||
(0, swagger_1.ApiQuery)({ name: 'country', required: false, enum: ['jordan', 'syria', 'egypt'] }),
|
||||
(0, swagger_1.ApiQuery)({ name: 'country', required: false, enum: ['jordan', 'syria', 'egypt', 'iraq'] }),
|
||||
__param(0, (0, common_1.Query)('country')),
|
||||
__metadata("design:type", Function),
|
||||
__metadata("design:paramtypes", [String]),
|
||||
@@ -221,7 +221,7 @@ __decorate([
|
||||
(0, common_1.Post)('admin/link-places'),
|
||||
(0, common_1.UseGuards)(admin_guard_1.AdminGuard),
|
||||
(0, swagger_1.ApiOperation)({ summary: 'Link places to administrative hierarchy' }),
|
||||
(0, swagger_1.ApiQuery)({ name: 'country', required: true, enum: ['jordan', 'syria', 'egypt'] }),
|
||||
(0, swagger_1.ApiQuery)({ name: 'country', required: true, enum: ['jordan', 'syria', 'egypt', 'iraq'] }),
|
||||
__param(0, (0, common_1.Query)('country')),
|
||||
__metadata("design:type", Function),
|
||||
__metadata("design:paramtypes", [String]),
|
||||
|
||||
+1
-1
File diff suppressed because one or more lines are too long
+2
@@ -48,6 +48,7 @@ const geocoding_controller_1 = require("./geocoding.controller");
|
||||
const place_syria_entity_1 = require("./entities/place-syria.entity");
|
||||
const place_jordan_entity_1 = require("./entities/place-jordan.entity");
|
||||
const place_egypt_entity_1 = require("./entities/place-egypt.entity");
|
||||
const place_iraq_entity_1 = require("./entities/place-iraq.entity");
|
||||
const osm_area_entity_1 = require("./entities/osm-area.entity");
|
||||
const osm_point_with_area_entity_1 = require("./entities/osm-point-with-area.entity");
|
||||
const admin_boundary_entity_1 = require("./entities/admin-boundary.entity");
|
||||
@@ -72,6 +73,7 @@ exports.GeocodingModule = GeocodingModule = __decorate([
|
||||
place_syria_entity_1.PlaceSyria,
|
||||
place_jordan_entity_1.PlaceJordan,
|
||||
place_egypt_entity_1.PlaceEgypt,
|
||||
place_iraq_entity_1.PlaceIraq,
|
||||
osm_area_entity_1.OsmArea,
|
||||
osm_point_with_area_entity_1.OsmPointWithArea,
|
||||
admin_boundary_entity_1.AdminBoundary,
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
{"version":3,"file":"geocoding.module.js","sourceRoot":"","sources":["../../src/geocoding/geocoding.module.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,2CAAwC;AACxC,6CAAgD;AAChD,2DAAuD;AACvD,qEAAgE;AAChE,iEAA6D;AAC7D,sEAA2D;AAC3D,wEAA6D;AAC7D,sEAA2D;AAC3D,gEAAqD;AACrD,sFAAyE;AACzE,4EAAiE;AACjE,yEAAoE;AACpE,uEAAkE;AAClE,qFAAgF;AAChF,oFAAyE;AACzE,wFAA6E;AAC7E,0EAA+D;AAC/D,qEAAgE;AAChE,2EAAsE;AACtE,yDAAoD;AACpD,sEAAwD;AACxD,mEAA8D;AAkCvD,IAAM,eAAe,GAArB,MAAM,eAAe;CAAG,CAAA;AAAlB,0CAAe;0BAAf,eAAe;IAhC3B,IAAA,eAAM,EAAC;QACN,OAAO,EAAE;YACP,uBAAa,CAAC,UAAU,CAAC;gBACvB,+BAAU;gBACV,iCAAW;gBACX,+BAAU;gBACV,yBAAO;gBACP,6CAAgB;gBAChB,qCAAa;gBACb,6CAAiB;gBACjB,iDAAmB;gBACnB,mCAAY;aACb,CAAC;YACF,2BAAW,CAAC,QAAQ,CAAC;gBACnB,KAAK,EAAE,UAAU;gBACjB,IAAI,EAAE,OAAO,CAAC,GAAG,CAAC,UAAU,IAAI,WAAW;gBAC3C,IAAI,EAAE,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,UAAU,IAAI,MAAM,EAAE,EAAE,CAAC;gBACpD,GAAG,EAAE,IAAI;aACV,CAAC;SACH;QACD,WAAW,EAAE,CAAC,0CAAmB,EAAE,mDAAuB,CAAC;QAC3D,SAAS,EAAE;YACT,oCAAgB;YAChB,6CAAoB;YACpB,iDAAsB;YACtB,+CAAqB;YACrB,6DAA4B;YAC5B,6CAAoB;YACpB,2CAAmB;SACpB;QACD,OAAO,EAAE,CAAC,oCAAgB,EAAE,6CAAoB,CAAC;KAClD,CAAC;GACW,eAAe,CAAG"}
|
||||
{"version":3,"file":"geocoding.module.js","sourceRoot":"","sources":["../../src/geocoding/geocoding.module.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,2CAAwC;AACxC,6CAAgD;AAChD,2DAAuD;AACvD,qEAAgE;AAChE,iEAA6D;AAC7D,sEAA2D;AAC3D,wEAA6D;AAC7D,sEAA2D;AAC3D,oEAAyD;AACzD,gEAAqD;AACrD,sFAAyE;AACzE,4EAAiE;AACjE,yEAAoE;AACpE,uEAAkE;AAClE,qFAAgF;AAChF,oFAAyE;AACzE,wFAA6E;AAC7E,0EAA+D;AAC/D,qEAAgE;AAChE,2EAAsE;AACtE,yDAAoD;AACpD,sEAAwD;AACxD,mEAA8D;AAmCvD,IAAM,eAAe,GAArB,MAAM,eAAe;CAAG,CAAA;AAAlB,0CAAe;0BAAf,eAAe;IAjC3B,IAAA,eAAM,EAAC;QACN,OAAO,EAAE;YACP,uBAAa,CAAC,UAAU,CAAC;gBACvB,+BAAU;gBACV,iCAAW;gBACX,+BAAU;gBACV,6BAAS;gBACT,yBAAO;gBACP,6CAAgB;gBAChB,qCAAa;gBACb,6CAAiB;gBACjB,iDAAmB;gBACnB,mCAAY;aACb,CAAC;YACF,2BAAW,CAAC,QAAQ,CAAC;gBACnB,KAAK,EAAE,UAAU;gBACjB,IAAI,EAAE,OAAO,CAAC,GAAG,CAAC,UAAU,IAAI,WAAW;gBAC3C,IAAI,EAAE,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,UAAU,IAAI,MAAM,EAAE,EAAE,CAAC;gBACpD,GAAG,EAAE,IAAI;aACV,CAAC;SACH;QACD,WAAW,EAAE,CAAC,0CAAmB,EAAE,mDAAuB,CAAC;QAC3D,SAAS,EAAE;YACT,oCAAgB;YAChB,6CAAoB;YACpB,iDAAsB;YACtB,+CAAqB;YACrB,6DAA4B;YAC5B,6CAAoB;YACpB,2CAAmB;SACpB;QACD,OAAO,EAAE,CAAC,oCAAgB,EAAE,6CAAoB,CAAC;KAClD,CAAC;GACW,eAAe,CAAG"}
|
||||
+12
-1
@@ -3,6 +3,7 @@ import type { Cache } from 'cache-manager';
|
||||
import { PlaceSyria } from './entities/place-syria.entity';
|
||||
import { PlaceJordan } from './entities/place-jordan.entity';
|
||||
import { PlaceEgypt } from './entities/place-egypt.entity';
|
||||
import { PlaceIraq } from './entities/place-iraq.entity';
|
||||
import { BasePlace } from './entities/base-place.entity';
|
||||
import { OsmArea } from './entities/osm-area.entity';
|
||||
import { OsmPointWithArea } from './entities/osm-point-with-area.entity';
|
||||
@@ -10,12 +11,13 @@ export declare class GeocodingService {
|
||||
private placesSyriaRepository;
|
||||
private placesJordanRepository;
|
||||
private placesEgyptRepository;
|
||||
private placesIraqRepository;
|
||||
private osmAreasRepository;
|
||||
private osmPointsRepository;
|
||||
private cacheManager;
|
||||
private readonly logger;
|
||||
private readonly DB_TIMEOUT_MS;
|
||||
constructor(placesSyriaRepository: Repository<PlaceSyria>, placesJordanRepository: Repository<PlaceJordan>, placesEgyptRepository: Repository<PlaceEgypt>, osmAreasRepository: Repository<OsmArea>, osmPointsRepository: Repository<OsmPointWithArea>, cacheManager: Cache);
|
||||
constructor(placesSyriaRepository: Repository<PlaceSyria>, placesJordanRepository: Repository<PlaceJordan>, placesEgyptRepository: Repository<PlaceEgypt>, placesIraqRepository: Repository<PlaceIraq>, osmAreasRepository: Repository<OsmArea>, osmPointsRepository: Repository<OsmPointWithArea>, cacheManager: Cache);
|
||||
private getRepositoryForCoords;
|
||||
private identifyRegion;
|
||||
private getTableNameForRepo;
|
||||
@@ -42,7 +44,9 @@ export declare class GeocodingService {
|
||||
results: any;
|
||||
source?: undefined;
|
||||
}>;
|
||||
private findIraqiAddress;
|
||||
reverseGeocode(lat: number, lng: number): Promise<any[]>;
|
||||
private extractCoords;
|
||||
addPlace(data: Partial<BasePlace>): Promise<any>;
|
||||
upsertPlace(data: Partial<BasePlace>): Promise<{
|
||||
id: any;
|
||||
@@ -53,6 +57,13 @@ export declare class GeocodingService {
|
||||
processed: number;
|
||||
created: number;
|
||||
updated: number;
|
||||
failed: number;
|
||||
errors: {
|
||||
index: number;
|
||||
name?: string;
|
||||
reason: string;
|
||||
}[];
|
||||
errorsTruncated: boolean;
|
||||
}>;
|
||||
getRecentPlaces(limit?: number): Promise<any[]>;
|
||||
getAllPlacesGeoJSON(): Promise<{
|
||||
|
||||
+127
-16
@@ -12,7 +12,7 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
|
||||
return function (target, key) { decorator(target, key, paramIndex); }
|
||||
};
|
||||
var GeocodingService_1;
|
||||
var _a, _b, _c, _d, _e;
|
||||
var _a, _b, _c, _d, _e, _f;
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.GeocodingService = void 0;
|
||||
const common_1 = require("@nestjs/common");
|
||||
@@ -22,26 +22,32 @@ const cache_manager_1 = require("@nestjs/cache-manager");
|
||||
const place_syria_entity_1 = require("./entities/place-syria.entity");
|
||||
const place_jordan_entity_1 = require("./entities/place-jordan.entity");
|
||||
const place_egypt_entity_1 = require("./entities/place-egypt.entity");
|
||||
const place_iraq_entity_1 = require("./entities/place-iraq.entity");
|
||||
const osm_area_entity_1 = require("./entities/osm-area.entity");
|
||||
const osm_point_with_area_entity_1 = require("./entities/osm-point-with-area.entity");
|
||||
let GeocodingService = GeocodingService_1 = class GeocodingService {
|
||||
placesSyriaRepository;
|
||||
placesJordanRepository;
|
||||
placesEgyptRepository;
|
||||
placesIraqRepository;
|
||||
osmAreasRepository;
|
||||
osmPointsRepository;
|
||||
cacheManager;
|
||||
logger = new common_1.Logger(GeocodingService_1.name);
|
||||
DB_TIMEOUT_MS = 1100;
|
||||
constructor(placesSyriaRepository, placesJordanRepository, placesEgyptRepository, osmAreasRepository, osmPointsRepository, cacheManager) {
|
||||
constructor(placesSyriaRepository, placesJordanRepository, placesEgyptRepository, placesIraqRepository, osmAreasRepository, osmPointsRepository, cacheManager) {
|
||||
this.placesSyriaRepository = placesSyriaRepository;
|
||||
this.placesJordanRepository = placesJordanRepository;
|
||||
this.placesEgyptRepository = placesEgyptRepository;
|
||||
this.placesIraqRepository = placesIraqRepository;
|
||||
this.osmAreasRepository = osmAreasRepository;
|
||||
this.osmPointsRepository = osmPointsRepository;
|
||||
this.cacheManager = cacheManager;
|
||||
}
|
||||
getRepositoryForCoords(lat, lng) {
|
||||
if (lat >= 29 && lat <= 37.5 && lng >= 38.7 && lng <= 48.8) {
|
||||
return this.placesIraqRepository;
|
||||
}
|
||||
if (lat >= 29 && lat <= 37.5 && lng >= 34.5 && lng <= 42.5) {
|
||||
if (lat > 32.5 && lng > 35.8)
|
||||
return this.placesSyriaRepository;
|
||||
@@ -55,6 +61,9 @@ let GeocodingService = GeocodingService_1 = class GeocodingService {
|
||||
identifyRegion(lat, lng) {
|
||||
if (lat === undefined || lng === undefined)
|
||||
return undefined;
|
||||
if (lat >= 29 && lat <= 37.5 && lng >= 38.7 && lng <= 48.8) {
|
||||
return 'iraq';
|
||||
}
|
||||
if (lat >= 29 && lat <= 37.5 && lng >= 34.5 && lng <= 42.5) {
|
||||
if (lat > 32.5 && lng > 35.8)
|
||||
return 'syria';
|
||||
@@ -70,6 +79,8 @@ let GeocodingService = GeocodingService_1 = class GeocodingService {
|
||||
return 'places_jordan';
|
||||
if (repo === this.placesEgyptRepository)
|
||||
return 'places_egypt';
|
||||
if (repo === this.placesIraqRepository)
|
||||
return 'places_iraq';
|
||||
return 'places_syria';
|
||||
}
|
||||
async searchPlaces(query, lat, lon, radius = 20000, country) {
|
||||
@@ -100,7 +111,7 @@ let GeocodingService = GeocodingService_1 = class GeocodingService {
|
||||
queryParams.push(lat, lon, radius);
|
||||
}
|
||||
let regionCondition = '';
|
||||
if (targetRegion && ['syria', 'jordan', 'egypt'].includes(targetRegion)) {
|
||||
if (targetRegion && ['syria', 'jordan', 'egypt', 'iraq'].includes(targetRegion)) {
|
||||
regionCondition = `AND (region = '${targetRegion}' OR region = 'global')`;
|
||||
}
|
||||
const sqlQuery = `
|
||||
@@ -227,6 +238,8 @@ let GeocodingService = GeocodingService_1 = class GeocodingService {
|
||||
getRepoByTableName(tableName) {
|
||||
if (tableName === 'places_egypt')
|
||||
return this.placesEgyptRepository;
|
||||
if (tableName === 'places_iraq')
|
||||
return this.placesIraqRepository;
|
||||
if (tableName === 'places_jordan')
|
||||
return this.placesJordanRepository;
|
||||
return this.placesSyriaRepository;
|
||||
@@ -263,7 +276,7 @@ let GeocodingService = GeocodingService_1 = class GeocodingService {
|
||||
const normalizedQuery = normalizedQueryRes?.nq || cleanQuery.toLowerCase();
|
||||
let queryParams = [`${normalizedQuery}%`];
|
||||
let regionCondition = '';
|
||||
if (targetRegion && ['syria', 'jordan', 'egypt'].includes(targetRegion)) {
|
||||
if (targetRegion && ['syria', 'jordan', 'egypt', 'iraq'].includes(targetRegion)) {
|
||||
regionCondition = `AND (region = '${targetRegion}' OR region = 'global')`;
|
||||
}
|
||||
const sqlQuery = `
|
||||
@@ -297,10 +310,44 @@ let GeocodingService = GeocodingService_1 = class GeocodingService {
|
||||
return { results: [] };
|
||||
}
|
||||
}
|
||||
async findIraqiAddress(lat, lng) {
|
||||
const MAX_DISTANCE_M = 150;
|
||||
try {
|
||||
const rows = await this.osmPointsRepository.query(`
|
||||
WITH p AS (
|
||||
SELECT ST_Transform(ST_SetSRID(ST_MakePoint($1::float, $2::float), 4326), 3857) AS g3857,
|
||||
ST_SetSRID(ST_MakePoint($1::float, $2::float), 4326)::geography AS geog
|
||||
)
|
||||
SELECT l.name,
|
||||
ST_Distance(ST_Transform(l.way, 4326)::geography, p.geog) AS distance
|
||||
FROM planet_osm_line l, p
|
||||
WHERE l.name ~ '^[0-9]{2,4}-[0-9]{1,3}$'
|
||||
ORDER BY l.way <-> p.g3857
|
||||
LIMIT 1
|
||||
`, [lng, lat]);
|
||||
const row = rows?.[0];
|
||||
if (!row || Number(row.distance) > MAX_DISTANCE_M)
|
||||
return null;
|
||||
const [mahalla, zuqaq] = String(row.name).split('-');
|
||||
return {
|
||||
mahalla,
|
||||
zuqaq,
|
||||
distance: Number(row.distance),
|
||||
text: `محلة ${mahalla}، زقاق ${zuqaq}`,
|
||||
};
|
||||
}
|
||||
catch (e) {
|
||||
this.logger.warn(`Iraqi address lookup failed: ${e.message}`);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
async reverseGeocode(lat, lng) {
|
||||
try {
|
||||
const repo = this.getRepositoryForCoords(lat, lng);
|
||||
const tableName = this.getTableNameForRepo(repo);
|
||||
const iraqiAddressPromise = this.identifyRegion(lat, lng) === 'iraq'
|
||||
? this.findIraqiAddress(lat, lng)
|
||||
: Promise.resolve(null);
|
||||
const queryPromises = [];
|
||||
queryPromises.push(repo.query(`
|
||||
SELECT
|
||||
@@ -357,7 +404,20 @@ let GeocodingService = GeocodingService_1 = class GeocodingService {
|
||||
WHERE location IS NOT NULL AND (names->>'primary' IS NOT NULL OR names->>'common' IS NOT NULL)
|
||||
ORDER BY location <-> ST_SetSRID(ST_MakePoint($1::float, $2::float), 4326) ASC LIMIT 5
|
||||
`, [lng, lat]));
|
||||
const results = await Promise.allSettled(queryPromises);
|
||||
queryPromises.push(repo.query(`
|
||||
SELECT
|
||||
id::text, COALESCE(name, 'Street') as name, COALESCE(name, 'طريق معتمد') as name_ar, 'street' as category,
|
||||
'' as neighbourhood, '' as district, '' as governorate,
|
||||
ST_Y(ST_Centroid(geometry::geometry))::text as latitude, ST_X(ST_Centroid(geometry::geometry))::text as longitude, '' as address, 'approved_road' as source,
|
||||
ST_DistanceSphere(geometry::geometry, ST_SetSRID(ST_MakePoint($1::float, $2::float), 4326)) as distance
|
||||
FROM approved_roads
|
||||
WHERE geometry IS NOT NULL AND name IS NOT NULL AND trim(name) != ''
|
||||
ORDER BY geometry::geometry <-> ST_SetSRID(ST_MakePoint($1::float, $2::float), 4326) ASC LIMIT 5
|
||||
`, [lng, lat]).catch(() => []));
|
||||
const [results, iraqiAddress] = await Promise.all([
|
||||
Promise.allSettled(queryPromises),
|
||||
iraqiAddressPromise,
|
||||
]);
|
||||
let allResults = [];
|
||||
results.forEach(res => {
|
||||
if (res.status === 'fulfilled' && res.value)
|
||||
@@ -368,7 +428,17 @@ let GeocodingService = GeocodingService_1 = class GeocodingService {
|
||||
.slice(0, 5)
|
||||
.map(r => {
|
||||
const distance = Number(r.distance);
|
||||
const fullAddressParts = [r.name_ar || r.name, r.address, r.neighbourhood, r.district, r.governorate].filter(Boolean);
|
||||
const ZUQAQ_NAME_RE = /^[0-9]{2,4}-[0-9]{1,3}$/;
|
||||
const rawName = r.name_ar || r.name;
|
||||
const nameIsZuqaq = typeof rawName === 'string' && ZUQAQ_NAME_RE.test(rawName);
|
||||
const fullAddressParts = [
|
||||
nameIsZuqaq ? null : rawName,
|
||||
r.address,
|
||||
iraqiAddress?.text,
|
||||
r.neighbourhood,
|
||||
r.district,
|
||||
r.governorate,
|
||||
].filter(Boolean);
|
||||
let humanReadable = r.name_ar || r.name;
|
||||
if (distance <= 20) {
|
||||
humanReadable = r.name_ar || r.name;
|
||||
@@ -382,8 +452,14 @@ let GeocodingService = GeocodingService_1 = class GeocodingService {
|
||||
const districtPart = r.neighbourhood || r.district || '';
|
||||
humanReadable = [streetPart, districtPart].filter(Boolean).join('، ');
|
||||
}
|
||||
if (iraqiAddress) {
|
||||
const landmark = distance <= 70 && !nameIsZuqaq ? rawName : null;
|
||||
humanReadable = [iraqiAddress.text, landmark].filter(Boolean).join(' — ');
|
||||
}
|
||||
return {
|
||||
...r,
|
||||
mahalla: iraqiAddress?.mahalla,
|
||||
zuqaq: iraqiAddress?.zuqaq,
|
||||
latitude: parseFloat(r.latitude),
|
||||
longitude: parseFloat(r.longitude),
|
||||
human_readable_address: humanReadable,
|
||||
@@ -396,9 +472,20 @@ let GeocodingService = GeocodingService_1 = class GeocodingService {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
extractCoords(data) {
|
||||
const lat = Number(data?.lat ?? data?.latitude);
|
||||
const lng = Number(data?.lng ?? data?.longitude);
|
||||
if (!Number.isFinite(lat) || !Number.isFinite(lng)) {
|
||||
throw new common_1.HttpException('Invalid coordinates: provide numeric lat/lng (or latitude/longitude)', common_1.HttpStatus.BAD_REQUEST);
|
||||
}
|
||||
if (lat < -90 || lat > 90 || lng < -180 || lng > 180) {
|
||||
throw new common_1.HttpException(`Coordinates out of range: lat=${lat}, lng=${lng}`, common_1.HttpStatus.BAD_REQUEST);
|
||||
}
|
||||
return { lat, lng };
|
||||
}
|
||||
async addPlace(data) {
|
||||
try {
|
||||
const lat = Number(data.latitude), lng = Number(data.longitude);
|
||||
const { lat, lng } = this.extractCoords(data);
|
||||
const repo = this.getRepositoryForCoords(lat, lng), tableName = this.getTableNameForRepo(repo);
|
||||
const newPlace = repo.create({ ...data, latitude: lat, longitude: lng, created_at: new Date(), location: { type: 'Point', coordinates: [lng, lat] } });
|
||||
const savedPlace = await repo.save(newPlace);
|
||||
@@ -406,12 +493,14 @@ let GeocodingService = GeocodingService_1 = class GeocodingService {
|
||||
return { ...savedPlace, latitude: lat, longitude: lng, location: `POINT(${lng} ${lat})` };
|
||||
}
|
||||
catch (error) {
|
||||
if (error instanceof common_1.HttpException)
|
||||
throw error;
|
||||
throw new common_1.HttpException(error.message, common_1.HttpStatus.INTERNAL_SERVER_ERROR);
|
||||
}
|
||||
}
|
||||
async upsertPlace(data) {
|
||||
try {
|
||||
const lat = Number(data.latitude), lng = Number(data.longitude);
|
||||
const { lat, lng } = this.extractCoords(data);
|
||||
const repo = this.getRepositoryForCoords(lat, lng), tableName = this.getTableNameForRepo(repo);
|
||||
const existing = await repo.query(`SELECT id, name FROM ${tableName} WHERE ST_DistanceSphere(location, ST_SetSRID(ST_MakePoint($1::float, $2::float), 4326)) < 15 LIMIT 1`, [lng, lat]);
|
||||
if (existing && existing.length > 0) {
|
||||
@@ -427,20 +516,39 @@ let GeocodingService = GeocodingService_1 = class GeocodingService {
|
||||
}
|
||||
async upsertBatch(places) {
|
||||
const results = [];
|
||||
for (const place of places) {
|
||||
const errors = [];
|
||||
for (const [index, place] of places.entries()) {
|
||||
try {
|
||||
const r = await this.addPlace(place);
|
||||
results.push({ id: r.id, action: 'created' });
|
||||
}
|
||||
catch (e) { }
|
||||
catch (e) {
|
||||
if (errors.length < 50) {
|
||||
errors.push({
|
||||
index,
|
||||
name: place?.name,
|
||||
reason: e instanceof common_1.HttpException ? e.message : (e?.message ?? 'unknown'),
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
return { total: places.length, processed: results.length, created: results.length, updated: 0 };
|
||||
const failed = places.length - results.length;
|
||||
return {
|
||||
total: places.length,
|
||||
processed: results.length,
|
||||
created: results.length,
|
||||
updated: 0,
|
||||
failed,
|
||||
errors,
|
||||
errorsTruncated: failed > errors.length,
|
||||
};
|
||||
}
|
||||
async getRecentPlaces(limit = 50) {
|
||||
const s = await this.placesSyriaRepository.find({ order: { created_at: 'DESC' }, take: limit });
|
||||
const j = await this.placesJordanRepository.find({ order: { created_at: 'DESC' }, take: limit });
|
||||
const e = await this.placesEgyptRepository.find({ order: { created_at: 'DESC' }, take: limit });
|
||||
return [...s, ...j, ...e].sort((a, b) => b.created_at.getTime() - a.created_at.getTime()).slice(0, limit);
|
||||
const i = await this.placesIraqRepository.find({ order: { created_at: 'DESC' }, take: limit });
|
||||
return [...s, ...j, ...e, ...i].sort((a, b) => b.created_at.getTime() - a.created_at.getTime()).slice(0, limit);
|
||||
}
|
||||
async getAllPlacesGeoJSON() {
|
||||
try {
|
||||
@@ -448,6 +556,7 @@ let GeocodingService = GeocodingService_1 = class GeocodingService {
|
||||
SELECT id::text, name_ar as name, category, latitude, longitude, address, 'user' as region FROM places_syria
|
||||
UNION ALL SELECT id::text, name_ar as name, category, latitude, longitude, address, 'user' as region FROM places_jordan
|
||||
UNION ALL SELECT id::text, name_ar as name, category, latitude, longitude, address, 'user' as region FROM places_egypt
|
||||
UNION ALL SELECT id::text, name_ar as name, category, latitude, longitude, address, 'user' as region FROM places_iraq
|
||||
UNION ALL SELECT id::text, COALESCE(names->>'primary', names->>'common', 'Building') as name, 'building' as category, ST_Y(ST_Centroid(location)) as latitude, ST_X(ST_Centroid(location)) as longitude, '' as address, 'overture' as region FROM overture_building WHERE names->>'primary' IS NOT NULL LIMIT 500
|
||||
UNION ALL SELECT id::text, COALESCE(names->>'primary', names->>'common', 'Street') as name, 'street' as category, ST_Y(ST_Centroid(location)) as latitude, ST_X(ST_Centroid(location)) as longitude, '' as address, 'overture' as region FROM overture_segment WHERE names->>'primary' IS NOT NULL LIMIT 500
|
||||
UNION ALL SELECT id::text, COALESCE(names->>'primary', names->>'common', 'Place') as name, 'place' as category, ST_Y(ST_Centroid(location)) as latitude, ST_X(ST_Centroid(location)) as longitude, '' as address, 'overture' as region FROM overture_place WHERE names->>'primary' IS NOT NULL LIMIT 500
|
||||
@@ -478,6 +587,7 @@ let GeocodingService = GeocodingService_1 = class GeocodingService {
|
||||
case 'syria': return this.placesSyriaRepository;
|
||||
case 'jordan': return this.placesJordanRepository;
|
||||
case 'egypt': return this.placesEgyptRepository;
|
||||
case 'iraq': return this.placesIraqRepository;
|
||||
default: throw new common_1.HttpException('Invalid country: ' + country, common_1.HttpStatus.BAD_REQUEST);
|
||||
}
|
||||
}
|
||||
@@ -488,9 +598,10 @@ exports.GeocodingService = GeocodingService = GeocodingService_1 = __decorate([
|
||||
__param(0, (0, typeorm_1.InjectRepository)(place_syria_entity_1.PlaceSyria)),
|
||||
__param(1, (0, typeorm_1.InjectRepository)(place_jordan_entity_1.PlaceJordan)),
|
||||
__param(2, (0, typeorm_1.InjectRepository)(place_egypt_entity_1.PlaceEgypt)),
|
||||
__param(3, (0, typeorm_1.InjectRepository)(osm_area_entity_1.OsmArea)),
|
||||
__param(4, (0, typeorm_1.InjectRepository)(osm_point_with_area_entity_1.OsmPointWithArea)),
|
||||
__param(5, (0, common_1.Inject)(cache_manager_1.CACHE_MANAGER)),
|
||||
__metadata("design:paramtypes", [typeof (_a = typeof typeorm_2.Repository !== "undefined" && typeorm_2.Repository) === "function" ? _a : Object, typeof (_b = typeof typeorm_2.Repository !== "undefined" && typeorm_2.Repository) === "function" ? _b : Object, typeof (_c = typeof typeorm_2.Repository !== "undefined" && typeorm_2.Repository) === "function" ? _c : Object, typeof (_d = typeof typeorm_2.Repository !== "undefined" && typeorm_2.Repository) === "function" ? _d : Object, typeof (_e = typeof typeorm_2.Repository !== "undefined" && typeorm_2.Repository) === "function" ? _e : Object, Object])
|
||||
__param(3, (0, typeorm_1.InjectRepository)(place_iraq_entity_1.PlaceIraq)),
|
||||
__param(4, (0, typeorm_1.InjectRepository)(osm_area_entity_1.OsmArea)),
|
||||
__param(5, (0, typeorm_1.InjectRepository)(osm_point_with_area_entity_1.OsmPointWithArea)),
|
||||
__param(6, (0, common_1.Inject)(cache_manager_1.CACHE_MANAGER)),
|
||||
__metadata("design:paramtypes", [typeof (_a = typeof typeorm_2.Repository !== "undefined" && typeorm_2.Repository) === "function" ? _a : Object, typeof (_b = typeof typeorm_2.Repository !== "undefined" && typeorm_2.Repository) === "function" ? _b : Object, typeof (_c = typeof typeorm_2.Repository !== "undefined" && typeorm_2.Repository) === "function" ? _c : Object, typeof (_d = typeof typeorm_2.Repository !== "undefined" && typeorm_2.Repository) === "function" ? _d : Object, typeof (_e = typeof typeorm_2.Repository !== "undefined" && typeorm_2.Repository) === "function" ? _e : Object, typeof (_f = typeof typeorm_2.Repository !== "undefined" && typeorm_2.Repository) === "function" ? _f : Object, Object])
|
||||
], GeocodingService);
|
||||
//# sourceMappingURL=geocoding.service.js.map
|
||||
+1
-1
File diff suppressed because one or more lines are too long
+3
-1
@@ -3,14 +3,16 @@ import { MapCandidate, CandidateStatus } from './entities/map-candidate.entity';
|
||||
import { PlaceJordan } from './entities/place-jordan.entity';
|
||||
import { PlaceSyria } from './entities/place-syria.entity';
|
||||
import { PlaceEgypt } from './entities/place-egypt.entity';
|
||||
import { PlaceIraq } from './entities/place-iraq.entity';
|
||||
export declare class MapRefinementService {
|
||||
private dataSource;
|
||||
private candidateRepository;
|
||||
private jordanRepository;
|
||||
private syriaRepository;
|
||||
private egyptRepository;
|
||||
private iraqRepository;
|
||||
private readonly logger;
|
||||
constructor(dataSource: DataSource, candidateRepository: Repository<MapCandidate>, jordanRepository: Repository<PlaceJordan>, syriaRepository: Repository<PlaceSyria>, egyptRepository: Repository<PlaceEgypt>);
|
||||
constructor(dataSource: DataSource, candidateRepository: Repository<MapCandidate>, jordanRepository: Repository<PlaceJordan>, syriaRepository: Repository<PlaceSyria>, egyptRepository: Repository<PlaceEgypt>, iraqRepository: Repository<PlaceIraq>);
|
||||
suggestPlace(dto: any, submittedBy: string): Promise<MapCandidate>;
|
||||
runExternalVerification(candidateId: number): Promise<void>;
|
||||
getCandidates(status?: CandidateStatus): Promise<any[]>;
|
||||
|
||||
+10
-3
@@ -12,7 +12,7 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
|
||||
return function (target, key) { decorator(target, key, paramIndex); }
|
||||
};
|
||||
var MapRefinementService_1;
|
||||
var _a, _b, _c, _d, _e;
|
||||
var _a, _b, _c, _d, _e, _f;
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.MapRefinementService = void 0;
|
||||
const common_1 = require("@nestjs/common");
|
||||
@@ -22,19 +22,22 @@ const map_candidate_entity_1 = require("./entities/map-candidate.entity");
|
||||
const place_jordan_entity_1 = require("./entities/place-jordan.entity");
|
||||
const place_syria_entity_1 = require("./entities/place-syria.entity");
|
||||
const place_egypt_entity_1 = require("./entities/place-egypt.entity");
|
||||
const place_iraq_entity_1 = require("./entities/place-iraq.entity");
|
||||
let MapRefinementService = MapRefinementService_1 = class MapRefinementService {
|
||||
dataSource;
|
||||
candidateRepository;
|
||||
jordanRepository;
|
||||
syriaRepository;
|
||||
egyptRepository;
|
||||
iraqRepository;
|
||||
logger = new common_1.Logger(MapRefinementService_1.name);
|
||||
constructor(dataSource, candidateRepository, jordanRepository, syriaRepository, egyptRepository) {
|
||||
constructor(dataSource, candidateRepository, jordanRepository, syriaRepository, egyptRepository, iraqRepository) {
|
||||
this.dataSource = dataSource;
|
||||
this.candidateRepository = candidateRepository;
|
||||
this.jordanRepository = jordanRepository;
|
||||
this.syriaRepository = syriaRepository;
|
||||
this.egyptRepository = egyptRepository;
|
||||
this.iraqRepository = iraqRepository;
|
||||
}
|
||||
async suggestPlace(dto, submittedBy) {
|
||||
const lat = parseFloat(dto.lat || dto.latitude);
|
||||
@@ -178,6 +181,9 @@ let MapRefinementService = MapRefinementService_1 = class MapRefinementService {
|
||||
case map_candidate_entity_1.CountryCode.EGYPT:
|
||||
repo = this.egyptRepository;
|
||||
break;
|
||||
case map_candidate_entity_1.CountryCode.IRAQ:
|
||||
repo = this.iraqRepository;
|
||||
break;
|
||||
default: repo = this.jordanRepository;
|
||||
}
|
||||
const approvedPlace = repo.create(placeData);
|
||||
@@ -203,6 +209,7 @@ exports.MapRefinementService = MapRefinementService = MapRefinementService_1 = _
|
||||
__param(2, (0, typeorm_1.InjectRepository)(place_jordan_entity_1.PlaceJordan)),
|
||||
__param(3, (0, typeorm_1.InjectRepository)(place_syria_entity_1.PlaceSyria)),
|
||||
__param(4, (0, typeorm_1.InjectRepository)(place_egypt_entity_1.PlaceEgypt)),
|
||||
__metadata("design:paramtypes", [typeof (_a = typeof typeorm_2.DataSource !== "undefined" && typeorm_2.DataSource) === "function" ? _a : Object, typeof (_b = typeof typeorm_2.Repository !== "undefined" && typeorm_2.Repository) === "function" ? _b : Object, typeof (_c = typeof typeorm_2.Repository !== "undefined" && typeorm_2.Repository) === "function" ? _c : Object, typeof (_d = typeof typeorm_2.Repository !== "undefined" && typeorm_2.Repository) === "function" ? _d : Object, typeof (_e = typeof typeorm_2.Repository !== "undefined" && typeorm_2.Repository) === "function" ? _e : Object])
|
||||
__param(5, (0, typeorm_1.InjectRepository)(place_iraq_entity_1.PlaceIraq)),
|
||||
__metadata("design:paramtypes", [typeof (_a = typeof typeorm_2.DataSource !== "undefined" && typeorm_2.DataSource) === "function" ? _a : Object, typeof (_b = typeof typeorm_2.Repository !== "undefined" && typeorm_2.Repository) === "function" ? _b : Object, typeof (_c = typeof typeorm_2.Repository !== "undefined" && typeorm_2.Repository) === "function" ? _c : Object, typeof (_d = typeof typeorm_2.Repository !== "undefined" && typeorm_2.Repository) === "function" ? _d : Object, typeof (_e = typeof typeorm_2.Repository !== "undefined" && typeorm_2.Repository) === "function" ? _e : Object, typeof (_f = typeof typeorm_2.Repository !== "undefined" && typeorm_2.Repository) === "function" ? _f : Object])
|
||||
], MapRefinementService);
|
||||
//# sourceMappingURL=map-refinement.service.js.map
|
||||
+1
-1
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user