diff --git a/4_5767239985799371288.xlsx b/4_5767239985799371288.xlsx new file mode 100644 index 000000000..35cb5744e Binary files /dev/null and b/4_5767239985799371288.xlsx differ diff --git a/EDR-Freight-Priority-Flows-Portal.pdf b/EDR-Freight-Priority-Flows-Portal.pdf new file mode 100644 index 000000000..fe37cc9e8 Binary files /dev/null and b/EDR-Freight-Priority-Flows-Portal.pdf differ diff --git a/EDR-Freight-Priority-Flows.pdf b/EDR-Freight-Priority-Flows.pdf new file mode 100644 index 000000000..621d27995 Binary files /dev/null and b/EDR-Freight-Priority-Flows.pdf differ diff --git a/INV-20260812-00005-QR.png b/INV-20260812-00005-QR.png new file mode 100644 index 000000000..ec1e728d4 Binary files /dev/null and b/INV-20260812-00005-QR.png differ diff --git a/INV-20260812-00005.pdf b/INV-20260812-00005.pdf new file mode 100644 index 000000000..b36573dd2 Binary files /dev/null and b/INV-20260812-00005.pdf differ diff --git a/apps/edr-freight-api/src/config/mor-locations.data.ts b/apps/edr-freight-api/src/config/mor-locations.data.ts index b3b49c843..f55cf4ad5 100644 --- a/apps/edr-freight-api/src/config/mor-locations.data.ts +++ b/apps/edr-freight-api/src/config/mor-locations.data.ts @@ -1,18 +1,1181 @@ /** * GENERATED FILE — do not hand-edit. * - * MoR EIMS location master (`EIMS_COUNTRY_REGION_VW`), the Ministry's own geographic reference - * data. Regenerate from a supplied workbook with: + * MoR EIMS location master (`EIMS_COUNTRY_REGION_VW`), the Ministry's own geographic reference data. + * Regenerate from a supplied workbook with: * * pnpm --filter @edr/freight-api eims:import-locations * * Values are reproduced verbatim from the Ministry sheet — original spelling, original casing, - * original numbering, duplicates included. Nothing here is cleaned up or renumbered: this file is - * the traceable copy of the source. Spelling compatibility between EDR/e-Trade names and MoR names - * belongs in `mor-location.resolver.ts`'s normalization and alias layer, never here. + * original numbering. Nothing here is cleaned up or renumbered: this file is the traceable copy of + * the source. Spelling compatibility between EDR/e-Trade names and MoR names belongs in + * `mor-location.resolver.ts`'s normalization and alias layer, never here. */ /** `[COUNTRY_NO, COUNTRY_NAME, PARISH_NO, PARISH_NAME, CITY_NO, CITY_NAME, LOCALITY_NO, LOCALITY_DESC]` */ export type MorLocationTuple = [number, string, number, string, number, string, number, string]; -export const MOR_LOCATIONS: MorLocationTuple[] = []; +export const MOR_LOCATIONS: MorLocationTuple[] = [ + [70, "Ethiopia", 2, "OROMIA", 1, "DEBUB MIRAB SHOA", 401, "WELISO"], + [70, "Ethiopia", 2, "OROMIA", 1, "DEBUB MIRAB SHOA", 402, "ILLU"], + [70, "Ethiopia", 2, "OROMIA", 1, "DEBUB MIRAB SHOA", 403, "AMMEYA"], + [70, "Ethiopia", 2, "OROMIA", 1, "DEBUB MIRAB SHOA", 404, "WENCHI"], + [70, "Ethiopia", 2, "OROMIA", 1, "DEBUB MIRAB SHOA", 405, "BECHO"], + [70, "Ethiopia", 2, "OROMIA", 1, "DEBUB MIRAB SHOA", 406, "TOLE"], + [70, "Ethiopia", 2, "OROMIA", 1, "DEBUB MIRAB SHOA", 407, "DAWO"], + [70, "Ethiopia", 2, "OROMIA", 1, "DEBUB MIRAB SHOA", 408, "KOKIR"], + [70, "Ethiopia", 2, "OROMIA", 1, "DEBUB MIRAB SHOA", 409, "KERSANA KONDALTIT"], + [70, "Ethiopia", 2, "OROMIA", 1, "DEBUB MIRAB SHOA", 601, "ALEMGENA CITY ADMIN"], + [70, "Ethiopia", 2, "OROMIA", 1, "DEBUB MIRAB SHOA", 602, "WELISO CITY ADMIN"], + [70, "Ethiopia", 2, "OROMIA", 1, "DEBUB MIRAB SHOA", 748, "GORO"], + [70, "Ethiopia", 2, "OROMIA", 1, "DEBUB MIRAB SHOA", 749, "SEDEN SODO"], + [70, "Ethiopia", 2, "OROMIA", 1, "DEBUB MIRAB SHOA", 750, "SODO DACHE"], + [70, "Ethiopia", 2, "OROMIA", 1, "DEBUB MIRAB SHOA", 897, "KERSA MALIMA"], + [70, "Ethiopia", 2, "OROMIA", 2, "SEMEN SHOA", 3, "KUYU"], + [70, "Ethiopia", 2, "OROMIA", 2, "SEMEN SHOA", 410, "WONCHI GIDA"], + [70, "Ethiopia", 2, "OROMIA", 2, "SEMEN SHOA", 411, "SULULTA MULA"], + [70, "Ethiopia", 2, "OROMIA", 2, "SEMEN SHOA", 412, "BEREH ALELTU"], + [70, "Ethiopia", 2, "OROMIA", 2, "SEMEN SHOA", 413, "KIMBIBIT"], + [70, "Ethiopia", 2, "OROMIA", 2, "SEMEN SHOA", 414, "WEREJERSO"], + [70, "Ethiopia", 2, "OROMIA", 2, "SEMEN SHOA", 415, "GRAR JERSO"], + [70, "Ethiopia", 2, "OROMIA", 2, "SEMEN SHOA", 416, "DERA"], + [70, "Ethiopia", 2, "OROMIA", 2, "SEMEN SHOA", 417, "DEGEM"], + [70, "Ethiopia", 2, "OROMIA", 2, "SEMEN SHOA", 418, "HADEBU ABOTE"], + [70, "Ethiopia", 2, "OROMIA", 2, "SEMEN SHOA", 419, "YAYA GULELENA DELI"], + [70, "Ethiopia", 2, "OROMIA", 2, "SEMEN SHOA", 420, "ABICHUNA GNEA"], + [70, "Ethiopia", 2, "OROMIA", 2, "SEMEN SHOA", 614, "FITCHE CITY ADMIN"], + [70, "Ethiopia", 2, "OROMIA", 2, "SEMEN SHOA", 615, "SENDAFA CITY ADMIN"], + [70, "Ethiopia", 2, "OROMIA", 2, "SEMEN SHOA", 751, "ALELTU"], + [70, "Ethiopia", 2, "OROMIA", 2, "SEMEN SHOA", 752, "DEBIRELIBANOS"], + [70, "Ethiopia", 2, "OROMIA", 2, "SEMEN SHOA", 753, "JIDDO"], + [70, "Ethiopia", 2, "OROMIA", 2, "SEMEN SHOA", 754, "WUCHALE"], + [70, "Ethiopia", 2, "OROMIA", 3, "BORENA", 4, "YABELO"], + [70, "Ethiopia", 2, "OROMIA", 3, "BORENA", 422, "TELITELE"], + [70, "Ethiopia", 2, "OROMIA", 3, "BORENA", 424, "ARARO"], + [70, "Ethiopia", 2, "OROMIA", 3, "BORENA", 425, "DIRE"], + [70, "Ethiopia", 2, "OROMIA", 3, "BORENA", 426, "MOYALE"], + [70, "Ethiopia", 2, "OROMIA", 3, "BORENA", 603, "YABELO CITY ADMIN"], + [70, "Ethiopia", 2, "OROMIA", 3, "BORENA", 679, "MIYO"], + [70, "Ethiopia", 2, "OROMIA", 3, "BORENA", 681, "BORBOR"], + [70, "Ethiopia", 2, "OROMIA", 3, "BORENA", 682, "DILLO"], + [70, "Ethiopia", 2, "OROMIA", 3, "BORENA", 1173, "GOMOLE"], + [70, "Ethiopia", 2, "OROMIA", 4, "GUJI", 5, "LIBEN"], + [70, "Ethiopia", 2, "OROMIA", 4, "GUJI", 428, "WADERA"], + [70, "Ethiopia", 2, "OROMIA", 4, "GUJI", 429, "ODO SHAKISO"], + [70, "Ethiopia", 2, "OROMIA", 4, "GUJI", 430, "BORE"], + [70, "Ethiopia", 2, "OROMIA", 4, "GUJI", 431, "URAGA"], + [70, "Ethiopia", 2, "OROMIA", 4, "GUJI", 432, "ADOLA"], + [70, "Ethiopia", 2, "OROMIA", 4, "GUJI", 622, "NEGELE CITY ADMINISTRATION"], + [70, "Ethiopia", 2, "OROMIA", 4, "GUJI", 684, "ANA HAMBELA"], + [70, "Ethiopia", 2, "OROMIA", 4, "GUJI", 685, "DAMA"], + [70, "Ethiopia", 2, "OROMIA", 4, "GUJI", 686, "GIRJA"], + [70, "Ethiopia", 2, "OROMIA", 4, "GUJI", 687, "SEBBA BORU"], + [70, "Ethiopia", 2, "OROMIA", 4, "GUJI", 688, "GORO DOLA"], + [70, "Ethiopia", 2, "OROMIA", 4, "GUJI", 689, "ANA SORA"], + [70, "Ethiopia", 2, "OROMIA", 4, "GUJI", 755, "ADOLA CITY ADMIN"], + [70, "Ethiopia", 2, "OROMIA", 4, "GUJI", 756, "ANNA SORA"], + [70, "Ethiopia", 2, "OROMIA", 4, "GUJI", 757, "GORO DOLO"], + [70, "Ethiopia", 2, "OROMIA", 4, "GUJI", 759, "SABA BORU"], + [70, "Ethiopia", 2, "OROMIA", 5, "MISRAK WOLEGA", 6, "GUTO WAYU"], + [70, "Ethiopia", 2, "OROMIA", 5, "MISRAK WOLEGA", 434, "ABAY CHEMEN"], + [70, "Ethiopia", 2, "OROMIA", 5, "MISRAK WOLEGA", 435, "JIMMA ARJO"], + [70, "Ethiopia", 2, "OROMIA", 5, "MISRAK WOLEGA", 436, "GIDA KIREMU"], + [70, "Ethiopia", 2, "OROMIA", 5, "MISRAK WOLEGA", 437, "SIBU SIRE"], + [70, "Ethiopia", 2, "OROMIA", 5, "MISRAK WOLEGA", 438, "LIMU"], + [70, "Ethiopia", 2, "OROMIA", 5, "MISRAK WOLEGA", 439, "NUNU KUMBA"], + [70, "Ethiopia", 2, "OROMIA", 5, "MISRAK WOLEGA", 440, "WAMA BONEYA"], + [70, "Ethiopia", 2, "OROMIA", 5, "MISRAK WOLEGA", 441, "AMURU"], + [70, "Ethiopia", 2, "OROMIA", 5, "MISRAK WOLEGA", 442, "HORO"], + [70, "Ethiopia", 2, "OROMIA", 5, "MISRAK WOLEGA", 443, "IBENTU"], + [70, "Ethiopia", 2, "OROMIA", 5, "MISRAK WOLEGA", 444, "GUDURU"], + [70, "Ethiopia", 2, "OROMIA", 5, "MISRAK WOLEGA", 445, "DIGA"], + [70, "Ethiopia", 2, "OROMIA", 5, "MISRAK WOLEGA", 446, "GUDEYA BILA"], + [70, "Ethiopia", 2, "OROMIA", 5, "MISRAK WOLEGA", 447, "SASIGA"], + [70, "Ethiopia", 2, "OROMIA", 5, "MISRAK WOLEGA", 448, "JARTE JARDEGA"], + [70, "Ethiopia", 2, "OROMIA", 5, "MISRAK WOLEGA", 449, "JIMMA GENETI"], + [70, "Ethiopia", 2, "OROMIA", 5, "MISRAK WOLEGA", 450, "ABE DONGORO"], + [70, "Ethiopia", 2, "OROMIA", 5, "MISRAK WOLEGA", 451, "LEKA DULECHA"], + [70, "Ethiopia", 2, "OROMIA", 5, "MISRAK WOLEGA", 452, "JIMMA RARE"], + [70, "Ethiopia", 2, "OROMIA", 5, "MISRAK WOLEGA", 591, "BILA SEYO"], + [70, "Ethiopia", 2, "OROMIA", 5, "MISRAK WOLEGA", 616, "NEKEMTE"], + [70, "Ethiopia", 2, "OROMIA", 5, "MISRAK WOLEGA", 705, "WAMA AGELO"], + [70, "Ethiopia", 2, "OROMIA", 5, "MISRAK WOLEGA", 706, "GUTO GIDDA"], + [70, "Ethiopia", 2, "OROMIA", 5, "MISRAK WOLEGA", 707, "EBANTU"], + [70, "Ethiopia", 2, "OROMIA", 5, "MISRAK WOLEGA", 708, "KIRAMU"], + [70, "Ethiopia", 2, "OROMIA", 5, "MISRAK WOLEGA", 709, "GOBBU SEYYO"], + [70, "Ethiopia", 2, "OROMIA", 5, "MISRAK WOLEGA", 710, "WAYYU TUQA"], + [70, "Ethiopia", 2, "OROMIA", 5, "MISRAK WOLEGA", 760, "BONEYYA BOSHE"], + [70, "Ethiopia", 2, "OROMIA", 5, "MISRAK WOLEGA", 761, "GIDA"], + [70, "Ethiopia", 2, "OROMIA", 5, "MISRAK WOLEGA", 762, "HARO LIMMU"], + [70, "Ethiopia", 2, "OROMIA", 5, "MISRAK WOLEGA", 763, "KIRAMU "], + [70, "Ethiopia", 2, "OROMIA", 6, "MIRAB WOLEGA", 7, "SEYYO"], + [70, "Ethiopia", 2, "OROMIA", 6, "MIRAB WOLEGA", 19, "GIMBI"], + [70, "Ethiopia", 2, "OROMIA", 6, "MIRAB WOLEGA", 454, "ANFILO"], + [70, "Ethiopia", 2, "OROMIA", 6, "MIRAB WOLEGA", 455, "AYRA GULISO"], + [70, "Ethiopia", 2, "OROMIA", 6, "MIRAB WOLEGA", 456, "ALEM TEFERI"], + [70, "Ethiopia", 2, "OROMIA", 6, "MIRAB WOLEGA", 457, "LALO ASBI"], + [70, "Ethiopia", 2, "OROMIA", 6, "MIRAB WOLEGA", 458, "NEJO"], + [70, "Ethiopia", 2, "OROMIA", 6, "MIRAB WOLEGA", 459, "BOJI"], + [70, "Ethiopia", 2, "OROMIA", 6, "MIRAB WOLEGA", 460, "LALO KLE"], + [70, "Ethiopia", 2, "OROMIA", 6, "MIRAB WOLEGA", 461, "HARU"], + [70, "Ethiopia", 2, "OROMIA", 6, "MIRAB WOLEGA", 462, "DALE SEDI"], + [70, "Ethiopia", 2, "OROMIA", 6, "MIRAB WOLEGA", 463, "GENJI"], + [70, "Ethiopia", 2, "OROMIA", 6, "MIRAB WOLEGA", 464, "JIMMA HARO"], + [70, "Ethiopia", 2, "OROMIA", 6, "MIRAB WOLEGA", 465, "GAO DALE"], + [70, "Ethiopia", 2, "OROMIA", 6, "MIRAB WOLEGA", 466, "MENESIBU"], + [70, "Ethiopia", 2, "OROMIA", 6, "MIRAB WOLEGA", 467, "NOLEKABA"], + [70, "Ethiopia", 2, "OROMIA", 6, "MIRAB WOLEGA", 468, "BEGI"], + [70, "Ethiopia", 2, "OROMIA", 6, "MIRAB WOLEGA", 469, "GIDAMI"], + [70, "Ethiopia", 2, "OROMIA", 6, "MIRAB WOLEGA", 470, "YUBIDO"], + [70, "Ethiopia", 2, "OROMIA", 6, "MIRAB WOLEGA", 471, "JARISO"], + [70, "Ethiopia", 2, "OROMIA", 6, "MIRAB WOLEGA", 472, "HAWA WELEL"], + [70, "Ethiopia", 2, "OROMIA", 6, "MIRAB WOLEGA", 604, "GIMBI CITY ADMINISTRATION"], + [70, "Ethiopia", 2, "OROMIA", 6, "MIRAB WOLEGA", 764, "AYIRA "], + [70, "Ethiopia", 2, "OROMIA", 6, "MIRAB WOLEGA", 765, "BABBO"], + [70, "Ethiopia", 2, "OROMIA", 6, "MIRAB WOLEGA", 766, "BODJI COQORSA"], + [70, "Ethiopia", 2, "OROMIA", 6, "MIRAB WOLEGA", 767, "BODJI DIRMAJI"], + [70, "Ethiopia", 2, "OROMIA", 6, "MIRAB WOLEGA", 768, "GULLISO"], + [70, "Ethiopia", 2, "OROMIA", 6, "MIRAB WOLEGA", 769, "HOMA"], + [70, "Ethiopia", 2, "OROMIA", 6, "MIRAB WOLEGA", 770, "KILTU KARRA"], + [70, "Ethiopia", 2, "OROMIA", 6, "MIRAB WOLEGA", 771, "KONDALA"], + [70, "Ethiopia", 2, "OROMIA", 6, "MIRAB WOLEGA", 772, "NEJO CITY ADMINISTRATION"], + [70, "Ethiopia", 2, "OROMIA", 7, "MIRAB HARARGE", 8, "CHIRO"], + [70, "Ethiopia", 2, "OROMIA", 7, "MIRAB HARARGE", 453, "TULO"], + [70, "Ethiopia", 2, "OROMIA", 7, "MIRAB HARARGE", 473, "MESO"], + [70, "Ethiopia", 2, "OROMIA", 7, "MIRAB HARARGE", 474, "KUNI"], + [70, "Ethiopia", 2, "OROMIA", 7, "MIRAB HARARGE", 475, "HABRO"], + [70, "Ethiopia", 2, "OROMIA", 7, "MIRAB HARARGE", 476, "DOBA"], + [70, "Ethiopia", 2, "OROMIA", 7, "MIRAB HARARGE", 477, "MESELA"], + [70, "Ethiopia", 2, "OROMIA", 7, "MIRAB HARARGE", 478, "DARO LEBU"], + [70, "Ethiopia", 2, "OROMIA", 7, "MIRAB HARARGE", 479, "GUBA KORCHA"], + [70, "Ethiopia", 2, "OROMIA", 7, "MIRAB HARARGE", 480, "ANCHER"], + [70, "Ethiopia", 2, "OROMIA", 7, "MIRAB HARARGE", 481, "BOKE"], + [70, "Ethiopia", 2, "OROMIA", 7, "MIRAB HARARGE", 605, "CHIRO CITY ADMINISTRATION"], + [70, "Ethiopia", 2, "OROMIA", 7, "MIRAB HARARGE", 773, "BEDDESSA CITY ADMIN"], + [70, "Ethiopia", 2, "OROMIA", 7, "MIRAB HARARGE", 774, "GEMMECHIS"], + [70, "Ethiopia", 2, "OROMIA", 7, "MIRAB HARARGE", 775, "HAWI GUDINA"], + [70, "Ethiopia", 2, "OROMIA", 8, "MISRAK HARARGE", 9, "HAROMAYA"], + [70, "Ethiopia", 2, "OROMIA", 8, "MISRAK HARARGE", 482, "KERSA"], + [70, "Ethiopia", 2, "OROMIA", 8, "MISRAK HARARGE", 483, "META"], + [70, "Ethiopia", 2, "OROMIA", 8, "MISRAK HARARGE", 484, "DEDER"], + [70, "Ethiopia", 2, "OROMIA", 8, "MISRAK HARARGE", 485, "KOMBOLCHA"], + [70, "Ethiopia", 2, "OROMIA", 8, "MISRAK HARARGE", 486, "GURSUM"], + [70, "Ethiopia", 2, "OROMIA", 8, "MISRAK HARARGE", 487, "MELKA BELO"], + [70, "Ethiopia", 2, "OROMIA", 8, "MISRAK HARARGE", 488, "JARSO"], + [70, "Ethiopia", 2, "OROMIA", 8, "MISRAK HARARGE", 489, "GURAWA"], + [70, "Ethiopia", 2, "OROMIA", 8, "MISRAK HARARGE", 490, "FEDISS"], + [70, "Ethiopia", 2, "OROMIA", 8, "MISRAK HARARGE", 491, "GOLE ODA"], + [70, "Ethiopia", 2, "OROMIA", 8, "MISRAK HARARGE", 492, "MAYU"], + [70, "Ethiopia", 2, "OROMIA", 8, "MISRAK HARARGE", 493, "GORO GUTU"], + [70, "Ethiopia", 2, "OROMIA", 8, "MISRAK HARARGE", 494, "BEDENO"], + [70, "Ethiopia", 2, "OROMIA", 8, "MISRAK HARARGE", 495, "BABILE"], + [70, "Ethiopia", 2, "OROMIA", 8, "MISRAK HARARGE", 496, "KORFA CHELE"], + [70, "Ethiopia", 2, "OROMIA", 8, "MISRAK HARARGE", 617, "AWEDAY CITY ADMINISTRATION"], + [70, "Ethiopia", 2, "OROMIA", 8, "MISRAK HARARGE", 696, "HAROMAYA CITY ADMINISTRATION"], + [70, "Ethiopia", 2, "OROMIA", 8, "MISRAK HARARGE", 697, "DEDER CITY ADMINISTRATION"], + [70, "Ethiopia", 2, "OROMIA", 8, "MISRAK HARARGE", 698, "CHINAKSEN"], + [70, "Ethiopia", 2, "OROMIA", 8, "MISRAK HARARGE", 699, "MIDAGA"], + [70, "Ethiopia", 2, "OROMIA", 9, "ROBE", 10, "ASSIGNED IN THE FUTURE"], + [70, "Ethiopia", 2, "OROMIA", 12, "MIRAB ARSII", 632, "ADEBA"], + [70, "Ethiopia", 2, "OROMIA", 12, "MIRAB ARSII", 633, "DODOLA"], + [70, "Ethiopia", 2, "OROMIA", 12, "MIRAB ARSII", 635, "KOKOSA"], + [70, "Ethiopia", 2, "OROMIA", 12, "MIRAB ARSII", 636, "QORE"], + [70, "Ethiopia", 2, "OROMIA", 12, "MIRAB ARSII", 637, "GEDEB ASASA"], + [70, "Ethiopia", 2, "OROMIA", 12, "MIRAB ARSII", 638, "SHALA"], + [70, "Ethiopia", 2, "OROMIA", 12, "MIRAB ARSII", 639, "KOFALE"], + [70, "Ethiopia", 2, "OROMIA", 12, "MIRAB ARSII", 640, "SHASHEMANE"], + [70, "Ethiopia", 2, "OROMIA", 12, "MIRAB ARSII", 641, "ARSI NEGELLE"], + [70, "Ethiopia", 2, "OROMIA", 12, "MIRAB ARSII", 642, "SIRARO"], + [70, "Ethiopia", 2, "OROMIA", 12, "MIRAB ARSII", 778, "DODOLA CITY ADMINISTRATION"], + [70, "Ethiopia", 2, "OROMIA", 12, "MIRAB ARSII", 779, "NENSEBO "], + [70, "Ethiopia", 2, "OROMIA", 12, "MIRAB ARSII", 780, "SHASHEMENE CITY ADM"], + [70, "Ethiopia", 2, "OROMIA", 13, "QELLEM WOLLEGA", 643, "ANFILO"], + [70, "Ethiopia", 2, "OROMIA", 13, "QELLEM WOLLEGA", 644, "DALE SADI"], + [70, "Ethiopia", 2, "OROMIA", 13, "QELLEM WOLLEGA", 645, "DALE WABERA"], + [70, "Ethiopia", 2, "OROMIA", 13, "QELLEM WOLLEGA", 646, "GAWO DALLE"], + [70, "Ethiopia", 2, "OROMIA", 13, "QELLEM WOLLEGA", 647, "GIDAMI"], + [70, "Ethiopia", 2, "OROMIA", 13, "QELLEM WOLLEGA", 648, "HAWA GELAN"], + [70, "Ethiopia", 2, "OROMIA", 13, "QELLEM WOLLEGA", 649, "JIMA HORO"], + [70, "Ethiopia", 2, "OROMIA", 13, "QELLEM WOLLEGA", 650, "LALO KILE"], + [70, "Ethiopia", 2, "OROMIA", 13, "QELLEM WOLLEGA", 651, "SAYO"], + [70, "Ethiopia", 2, "OROMIA", 13, "QELLEM WOLLEGA", 652, "YEMALOGI WELEL"], + [70, "Ethiopia", 2, "OROMIA", 13, "QELLEM WOLLEGA", 781, "DEMBIDOLLO CITY ADMIN"], + [70, "Ethiopia", 2, "OROMIA", 16, "MISRAK SHOA", 21, "ADAMA"], + [70, "Ethiopia", 2, "OROMIA", 16, "MISRAK SHOA", 377, "AKAKI"], + [70, "Ethiopia", 2, "OROMIA", 16, "MISRAK SHOA", 378, "LUME"], + [70, "Ethiopia", 2, "OROMIA", 16, "MISRAK SHOA", 379, "ADA"], + [70, "Ethiopia", 2, "OROMIA", 16, "MISRAK SHOA", 380, "SHASHEMENE"], + [70, "Ethiopia", 2, "OROMIA", 16, "MISRAK SHOA", 381, "ADAMITULU"], + [70, "Ethiopia", 2, "OROMIA", 16, "MISRAK SHOA", 382, "DUGDA BORA"], + [70, "Ethiopia", 2, "OROMIA", 16, "MISRAK SHOA", 383, "ARSI NEGELE"], + [70, "Ethiopia", 2, "OROMIA", 16, "MISRAK SHOA", 384, "BOSET"], + [70, "Ethiopia", 2, "OROMIA", 16, "MISRAK SHOA", 385, "FENTALE"], + [70, "Ethiopia", 2, "OROMIA", 16, "MISRAK SHOA", 386, "SIRARO"], + [70, "Ethiopia", 2, "OROMIA", 16, "MISRAK SHOA", 387, "GMBCHU"], + [70, "Ethiopia", 2, "OROMIA", 16, "MISRAK SHOA", 606, "ADAMA CITY ADMINISTRATION"], + [70, "Ethiopia", 2, "OROMIA", 16, "MISRAK SHOA", 618, "BISHOFTU CITY ADMINISTRATION"], + [70, "Ethiopia", 2, "OROMIA", 16, "MISRAK SHOA", 620, "SHASHEMENE CITY ADMINISTRATION"], + [70, "Ethiopia", 2, "OROMIA", 16, "MISRAK SHOA", 700, "MOJO TOWN ADMINISTRATION"], + [70, "Ethiopia", 2, "OROMIA", 16, "MISRAK SHOA", 701, "BATU TOWN ADMINISTRATION"], + [70, "Ethiopia", 2, "OROMIA", 16, "MISRAK SHOA", 702, "METEHARA CITY ADMINISTRATION"], + [70, "Ethiopia", 2, "OROMIA", 16, "MISRAK SHOA", 703, "BORA"], + [70, "Ethiopia", 2, "OROMIA", 16, "MISRAK SHOA", 704, "GELEAN CITY ADMINISTRATION"], + [70, "Ethiopia", 2, "OROMIA", 16, "MISRAK SHOA", 782, "BORA "], + [70, "Ethiopia", 2, "OROMIA", 16, "MISRAK SHOA", 783, "DUGDA "], + [70, "Ethiopia", 2, "OROMIA", 16, "MISRAK SHOA", 784, "LIBAN CHUKALA"], + [70, "Ethiopia", 2, "OROMIA", 16, "MISRAK SHOA", 785, "METAHARA CITY ADMIN"], + [70, "Ethiopia", 2, "OROMIA", 62, "MIRAB SHOA", 1, "AMBO"], + [70, "Ethiopia", 2, "OROMIA", 62, "MIRAB SHOA", 388, "DANDI"], + [70, "Ethiopia", 2, "OROMIA", 62, "MIRAB SHOA", 389, "CHELIA"], + [70, "Ethiopia", 2, "OROMIA", 62, "MIRAB SHOA", 390, "DIRRE INCHINI"], + [70, "Ethiopia", 2, "OROMIA", 62, "MIRAB SHOA", 391, "JELDU"], + [70, "Ethiopia", 2, "OROMIA", 62, "MIRAB SHOA", 392, "EJERE"], + [70, "Ethiopia", 2, "OROMIA", 62, "MIRAB SHOA", 393, "NONO"], + [70, "Ethiopia", 2, "OROMIA", 62, "MIRAB SHOA", 394, "BAKO"], + [70, "Ethiopia", 2, "OROMIA", 62, "MIRAB SHOA", 395, "MEDAKEY"], + [70, "Ethiopia", 2, "OROMIA", 62, "MIRAB SHOA", 396, "WELMERA"], + [70, "Ethiopia", 2, "OROMIA", 62, "MIRAB SHOA", 397, "DANO"], + [70, "Ethiopia", 2, "OROMIA", 62, "MIRAB SHOA", 398, "GINDEBERT"], + [70, "Ethiopia", 2, "OROMIA", 62, "MIRAB SHOA", 399, "ADA BERGA"], + [70, "Ethiopia", 2, "OROMIA", 62, "MIRAB SHOA", 400, "META ROBI"], + [70, "Ethiopia", 2, "OROMIA", 62, "MIRAB SHOA", 607, "AMBO CITY ADMINISTRATION"], + [70, "Ethiopia", 2, "OROMIA", 62, "MIRAB SHOA", 608, "HOLLETA CITY ADMINISTRATION"], + [70, "Ethiopia", 2, "OROMIA", 62, "MIRAB SHOA", 861, "ABUNA GINDEBERET"], + [70, "Ethiopia", 2, "OROMIA", 62, "MIRAB SHOA", 862, "ILFATA"], + [70, "Ethiopia", 2, "OROMIA", 62, "MIRAB SHOA", 863, "ILU GELAN"], + [70, "Ethiopia", 2, "OROMIA", 62, "MIRAB SHOA", 864, "JIBAT"], + [70, "Ethiopia", 2, "OROMIA", 62, "MIRAB SHOA", 865, "TOKKE KUTAYE"], + [70, "Ethiopia", 2, "OROMIA", 72, "JIMMA ZONE", 497, "DEDO"], + [70, "Ethiopia", 2, "OROMIA", 72, "JIMMA ZONE", 498, "GERA"], + [70, "Ethiopia", 2, "OROMIA", 72, "JIMMA ZONE", 499, "GOMA"], + [70, "Ethiopia", 2, "OROMIA", 72, "JIMMA ZONE", 500, "LIMUKOSA"], + [70, "Ethiopia", 2, "OROMIA", 72, "JIMMA ZONE", 501, "MANA"], + [70, "Ethiopia", 2, "OROMIA", 72, "JIMMA ZONE", 502, "OMO NADA"], + [70, "Ethiopia", 2, "OROMIA", 72, "JIMMA ZONE", 503, "KERSA"], + [70, "Ethiopia", 2, "OROMIA", 72, "JIMMA ZONE", 504, "SEKA CHOKORSA"], + [70, "Ethiopia", 2, "OROMIA", 72, "JIMMA ZONE", 505, "TIRO AFETA"], + [70, "Ethiopia", 2, "OROMIA", 72, "JIMMA ZONE", 506, "LIMU SEKA"], + [70, "Ethiopia", 2, "OROMIA", 72, "JIMMA ZONE", 507, "SOKORU"], + [70, "Ethiopia", 2, "OROMIA", 72, "JIMMA ZONE", 508, "SIGMO"], + [70, "Ethiopia", 2, "OROMIA", 72, "JIMMA ZONE", 509, "SETEMA"], + [70, "Ethiopia", 2, "OROMIA", 72, "JIMMA ZONE", 609, "JIMMA CITY ADMINISTRATION"], + [70, "Ethiopia", 2, "OROMIA", 72, "JIMMA ZONE", 884, "AGARO CITY ADMINISTRATION"], + [70, "Ethiopia", 2, "OROMIA", 72, "JIMMA ZONE", 886, "GUMAY"], + [70, "Ethiopia", 2, "OROMIA", 72, "JIMMA ZONE", 887, "NONNO BENJA"], + [70, "Ethiopia", 2, "OROMIA", 72, "JIMMA ZONE", 888, "SHABE"], + [70, "Ethiopia", 2, "OROMIA", 73, "ILLUBABOR", 510, "METU"], + [70, "Ethiopia", 2, "OROMIA", 73, "ILLUBABOR", 514, "HALU BURE"], + [70, "Ethiopia", 2, "OROMIA", 73, "ILLUBABOR", 516, "DARIMU"], + [70, "Ethiopia", 2, "OROMIA", 73, "ILLUBABOR", 519, "ALLE"], + [70, "Ethiopia", 2, "OROMIA", 73, "ILLUBABOR", 520, "YAYU HURUMU"], + [70, "Ethiopia", 2, "OROMIA", 73, "ILLUBABOR", 521, "SALE NONO"], + [70, "Ethiopia", 2, "OROMIA", 73, "ILLUBABOR", 522, "ALGE SECHI"], + [70, "Ethiopia", 2, "OROMIA", 73, "ILLUBABOR", 610, "METU CITY ADMINISTRATION"], + [70, "Ethiopia", 2, "OROMIA", 73, "ILLUBABOR", 666, "BILO NOPHA"], + [70, "Ethiopia", 2, "OROMIA", 73, "ILLUBABOR", 667, "DORENI"], + [70, "Ethiopia", 2, "OROMIA", 73, "ILLUBABOR", 668, "DIDO"], + [70, "Ethiopia", 2, "OROMIA", 73, "ILLUBABOR", 690, "HURUMU"], + [70, "Ethiopia", 2, "OROMIA", 73, "ILLUBABOR", 691, "BURE"], + [70, "Ethiopia", 2, "OROMIA", 73, "ILLUBABOR", 692, "BECHO"], + [70, "Ethiopia", 2, "OROMIA", 73, "ILLUBABOR", 693, "NONNO"], + [70, "Ethiopia", 2, "OROMIA", 73, "ILLUBABOR", 890, "BURE "], + [70, "Ethiopia", 2, "OROMIA", 73, "ILLUBABOR", 891, "HALU "], + [70, "Ethiopia", 2, "OROMIA", 73, "ILLUBABOR", 892, "YAYU "], + [70, "Ethiopia", 2, "OROMIA", 74, "ARSI", 523, "ROBE"], + [70, "Ethiopia", 2, "OROMIA", 74, "ARSI", 524, "DODOTANA SRE"], + [70, "Ethiopia", 2, "OROMIA", 74, "ARSI", 525, "MERTI"], + [70, "Ethiopia", 2, "OROMIA", 74, "ARSI", 526, "GEDEB"], + [70, "Ethiopia", 2, "OROMIA", 74, "ARSI", 527, "GOLOLICHA"], + [70, "Ethiopia", 2, "OROMIA", 74, "ARSI", 528, "TIYO"], + [70, "Ethiopia", 2, "OROMIA", 74, "ARSI", 529, "LIMUNA BILBILO"], + [70, "Ethiopia", 2, "OROMIA", 74, "ARSI", 530, "MUNESA"], + [70, "Ethiopia", 2, "OROMIA", 74, "ARSI", 531, "TENA"], + [70, "Ethiopia", 2, "OROMIA", 74, "ARSI", 532, "SERU"], + [70, "Ethiopia", 2, "OROMIA", 74, "ARSI", 533, "KOFELE"], + [70, "Ethiopia", 2, "OROMIA", 74, "ARSI", 534, "JEJU"], + [70, "Ethiopia", 2, "OROMIA", 74, "ARSI", 535, "CHOLE"], + [70, "Ethiopia", 2, "OROMIA", 74, "ARSI", 536, "ASAKO"], + [70, "Ethiopia", 2, "OROMIA", 74, "ARSI", 537, "DIKSI"], + [70, "Ethiopia", 2, "OROMIA", 74, "ARSI", 538, "DIGELUNA TIYU"], + [70, "Ethiopia", 2, "OROMIA", 74, "ARSI", 539, "ZWAY DUGDA"], + [70, "Ethiopia", 2, "OROMIA", 74, "ARSI", 540, "HETOSA"], + [70, "Ethiopia", 2, "OROMIA", 74, "ARSI", 541, "LODEHETOSA"], + [70, "Ethiopia", 2, "OROMIA", 74, "ARSI", 542, "SUDE"], + [70, "Ethiopia", 2, "OROMIA", 74, "ARSI", 543, "AMINIYA"], + [70, "Ethiopia", 2, "OROMIA", 74, "ARSI", 544, "SHIRKA"], + [70, "Ethiopia", 2, "OROMIA", 74, "ARSI", 612, "ASSELA CITY ADMINISTRATION"], + [70, "Ethiopia", 2, "OROMIA", 74, "ARSI", 654, "GUNA"], + [70, "Ethiopia", 2, "OROMIA", 74, "ARSI", 669, "BOKOJI CITY ADMINISTRATION"], + [70, "Ethiopia", 2, "OROMIA", 74, "ARSI", 670, "ENKOLO WABE"], + [70, "Ethiopia", 2, "OROMIA", 74, "ARSI", 671, "SIRE"], + [70, "Ethiopia", 2, "OROMIA", 74, "ARSI", 672, "BALE GASARA"], + [70, "Ethiopia", 2, "OROMIA", 74, "ARSI", 893, "DODOTA"], + [70, "Ethiopia", 2, "OROMIA", 74, "ARSI", 1196, "SHENAN KOLU"], + [70, "Ethiopia", 2, "OROMIA", 75, "BALE", 545, "SINANA DINISHO"], + [70, "Ethiopia", 2, "OROMIA", 75, "BALE", 546, "GOBA"], + [70, "Ethiopia", 2, "OROMIA", 75, "BALE", 547, "DODOLA"], + [70, "Ethiopia", 2, "OROMIA", 75, "BALE", 548, "ADABA"], + [70, "Ethiopia", 2, "OROMIA", 75, "BALE", 549, "GINIR"], + [70, "Ethiopia", 2, "OROMIA", 75, "BALE", 550, "BERBERE"], + [70, "Ethiopia", 2, "OROMIA", 75, "BALE", 551, "AGARFA"], + [70, "Ethiopia", 2, "OROMIA", 75, "BALE", 552, "GASERA"], + [70, "Ethiopia", 2, "OROMIA", 75, "BALE", 553, "GORO"], + [70, "Ethiopia", 2, "OROMIA", 75, "BALE", 554, "GOLOLCHA"], + [70, "Ethiopia", 2, "OROMIA", 75, "BALE", 555, "MENA ANGATU"], + [70, "Ethiopia", 2, "OROMIA", 75, "BALE", 556, "KOKOSA"], + [70, "Ethiopia", 2, "OROMIA", 75, "BALE", 557, "NANSEBO"], + [70, "Ethiopia", 2, "OROMIA", 75, "BALE", 558, "SEWENA"], + [70, "Ethiopia", 2, "OROMIA", 75, "BALE", 559, "LEGEHIDA"], + [70, "Ethiopia", 2, "OROMIA", 75, "BALE", 560, "RAYTU"], + [70, "Ethiopia", 2, "OROMIA", 75, "BALE", 561, "GURADAMOLE"], + [70, "Ethiopia", 2, "OROMIA", 75, "BALE", 562, "MEDAWELABU"], + [70, "Ethiopia", 2, "OROMIA", 75, "BALE", 621, "ROBE CITY ADMINISTRATION"], + [70, "Ethiopia", 2, "OROMIA", 75, "BALE", 673, "GOBBA CITY ADMINISTRATION"], + [70, "Ethiopia", 2, "OROMIA", 75, "BALE", 674, "DAWWE SERAR"], + [70, "Ethiopia", 2, "OROMIA", 75, "BALE", 675, "HARENNA BULUK"], + [70, "Ethiopia", 2, "OROMIA", 75, "BALE", 676, "DINSHO"], + [70, "Ethiopia", 2, "OROMIA", 75, "BALE", 677, "DAWWE KACHEN"], + [70, "Ethiopia", 2, "OROMIA", 75, "BALE", 894, "SINANA "], + [70, "Ethiopia", 2, "OROMIA", 83, "MIRAB ARSI", 634, "NANSEBO"], + [70, "Ethiopia", 2, "OROMIA", 84, "Horo guduru Wollegga", 656, "ABBE DONGORO"], + [70, "Ethiopia", 2, "OROMIA", 84, "Horo guduru Wollegga", 657, "SHAMBU CITY ADMINISTRATION"], + [70, "Ethiopia", 2, "OROMIA", 84, "Horo guduru Wollegga", 658, "HORO"], + [70, "Ethiopia", 2, "OROMIA", 84, "Horo guduru Wollegga", 659, "JIMMA RARE"], + [70, "Ethiopia", 2, "OROMIA", 84, "Horo guduru Wollegga", 660, "ABBAY CHOMAN"], + [70, "Ethiopia", 2, "OROMIA", 84, "Horo guduru Wollegga", 661, "GUDURU"], + [70, "Ethiopia", 2, "OROMIA", 84, "Horo guduru Wollegga", 662, "IMBABO"], + [70, "Ethiopia", 2, "OROMIA", 84, "Horo guduru Wollegga", 663, "JIMMA GENET"], + [70, "Ethiopia", 2, "OROMIA", 84, "Horo guduru Wollegga", 664, "AMURU JARTE"], + [70, "Ethiopia", 2, "OROMIA", 84, "Horo guduru Wollegga", 665, "JARTE JARDEGA"], + [70, "Ethiopia", 2, "OROMIA", 86, "FINFINE VIC SPEC", 619, "DUKEM TOWN ADMINISTRATION"], + [70, "Ethiopia", 2, "OROMIA", 86, "FINFINE VIC SPEC", 909, "Akaki woreda "], + [70, "Ethiopia", 2, "OROMIA", 86, "FINFINE VIC SPEC", 910, "BARAH"], + [70, "Ethiopia", 2, "OROMIA", 86, "FINFINE VIC SPEC", 911, "BURAYYU TOWN ADMIN"], + [70, "Ethiopia", 2, "OROMIA", 86, "FINFINE VIC SPEC", 912, "Dukem Town Administration"], + [70, "Ethiopia", 2, "OROMIA", 86, "FINFINE VIC SPEC", 913, "Gelan Town Administration"], + [70, "Ethiopia", 2, "OROMIA", 86, "FINFINE VIC SPEC", 914, "Holleta Town Administration"], + [70, "Ethiopia", 2, "OROMIA", 86, "FINFINE VIC SPEC", 915, "LEGATAFO TOWN ADMIN"], + [70, "Ethiopia", 2, "OROMIA", 86, "FINFINE VIC SPEC", 916, "MULLO"], + [70, "Ethiopia", 2, "OROMIA", 86, "FINFINE VIC SPEC", 971, "Sabeta Hawas"], + [70, "Ethiopia", 2, "OROMIA", 86, "FINFINE VIC SPEC", 972, "Sebeta Town Administration"], + [70, "Ethiopia", 2, "OROMIA", 86, "FINFINE VIC SPEC", 973, "Sendafa Town Administration"], + [70, "Ethiopia", 2, "OROMIA", 86, "FINFINE VIC SPEC", 974, "Sululta "], + [70, "Ethiopia", 2, "OROMIA", 86, "FINFINE VIC SPEC", 975, "SULULTA TOWN ADMIN"], + [70, "Ethiopia", 2, "OROMIA", 86, "FINFINE VIC SPEC", 976, "Wal-Mera"], + [70, "Ethiopia", 2, "OROMIA", 94, "OROMIYA-BUNO-BEDELE-ZONE", 247, "BORICHA"], + [70, "Ethiopia", 2, "OROMIA", 94, "OROMIYA-BUNO-BEDELE-ZONE", 885, "CHORA"], + [70, "Ethiopia", 2, "OROMIA", 95, "OROMIYA-WEST-GUJI-ZONE", 421, "GELANA"], + [70, "Ethiopia", 2, "OROMIA", 95, "OROMIYA-WEST-GUJI-ZONE", 423, "BULAHORA"], + [70, "Ethiopia", 2, "OROMIA", 95, "OROMIYA-WEST-GUJI-ZONE", 427, "ABEYA"], + [70, "Ethiopia", 2, "OROMIA", 95, "OROMIYA-WEST-GUJI-ZONE", 433, "KERRCHA"], + [70, "Ethiopia", 2, "OROMIA", 95, "OROMIYA-WEST-GUJI-ZONE", 678, "DUGDA DAWWA"], + [70, "Ethiopia", 2, "OROMIA", 95, "OROMIYA-WEST-GUJI-ZONE", 680, "MELKA SODDA"], + [70, "Ethiopia", 2, "OROMIA", 95, "OROMIYA-WEST-GUJI-ZONE", 758, "HAMBELA WAMNA"], + [70, "Ethiopia", 2, "OROMIA", 95, "OROMIYA-WEST-GUJI-ZONE", 1194, "SURO BARGUDA"], + [70, "Ethiopia", 2, "OROMIA", 98, "BUNO BEDELE ZONE", 511, "BEDELE"], + [70, "Ethiopia", 2, "OROMIA", 98, "BUNO BEDELE ZONE", 512, "GECHI"], + [70, "Ethiopia", 2, "OROMIA", 98, "BUNO BEDELE ZONE", 513, "BORECHA"], + [70, "Ethiopia", 2, "OROMIA", 98, "BUNO BEDELE ZONE", 515, "CHORA"], + [70, "Ethiopia", 2, "OROMIA", 98, "BUNO BEDELE ZONE", 517, "DIDESSA"], + [70, "Ethiopia", 2, "OROMIA", 98, "BUNO BEDELE ZONE", 518, "DIGA"], + [70, "Ethiopia", 2, "OROMIA", 98, "BUNO BEDELE ZONE", 613, "CHEWAKA"], + [70, "Ethiopia", 2, "OROMIA", 98, "BUNO BEDELE ZONE", 694, "DABO HANA"], + [70, "Ethiopia", 2, "OROMIA", 98, "BUNO BEDELE ZONE", 695, "MEKKO"], + [70, "Ethiopia", 2, "OROMIA", 98, "BUNO BEDELE ZONE", 889, "BEDELLE CITY ADMINISTRATION"], + [70, "Ethiopia", 2, "OROMIA", 100, "WEST GUJI ZONE", 1199, "BIRBIRSA KOJOWA"], + [70, "Ethiopia", 2, "OROMIA", 106, "OROMIA", 2, "ALEMGENA"], + [70, "Ethiopia", 2, "OROMIA", 121, "SHEGER CITY", 1288, "MERTU 1"], + [70, "Ethiopia", 2, "OROMIA", 123, "EAST BORENA ZONE", 1291, "OBORSO"], + [70, "Ethiopia", 2, "OROMIA", 124, "BISHOFTU CITY ADMIN", 1292, "DIBAYU SUBCITY"], + [70, "Ethiopia", 2, "OROMIA", 125, "SHEGER CITY ADMIN", 1293, "MELKA NONO SUB CITY"], + [70, "Ethiopia", 3, "TIGRAY", 56, "MEAKELLAY", 13, "TAHITY MAICHEW"], + [70, "Ethiopia", 3, "TIGRAY", 56, "MEAKELLAY", 342, "DEGUA TENBEN"], + [70, "Ethiopia", 3, "TIGRAY", 56, "MEAKELLAY", 343, "LAILAY MICHEW"], + [70, "Ethiopia", 3, "TIGRAY", 56, "MEAKELLAY", 344, "TANKWA ABERGELE"], + [70, "Ethiopia", 3, "TIGRAY", 56, "MEAKELLAY", 345, "KOLA TENBEN"], + [70, "Ethiopia", 3, "TIGRAY", 56, "MEAKELLAY", 346, "NAIDAR ADAT"], + [70, "Ethiopia", 3, "TIGRAY", 56, "MEAKELLAY", 347, "MEREB LEHE"], + [70, "Ethiopia", 3, "TIGRAY", 56, "MEAKELLAY", 348, "WEREI"], + [70, "Ethiopia", 3, "TIGRAY", 56, "MEAKELLAY", 349, "ADOWA TOWN ADMIN"], + [70, "Ethiopia", 3, "TIGRAY", 56, "MEAKELLAY", 350, "AHIFEROM"], + [70, "Ethiopia", 3, "TIGRAY", 56, "MEAKELLAY", 592, "AXUM TOWN ADMIN"], + [70, "Ethiopia", 3, "TIGRAY", 56, "MEAKELLAY", 626, "GETER ADWA"], + [70, "Ethiopia", 3, "TIGRAY", 56, "MEAKELLAY", 627, "ABIY ADI TOWN ADMIN"], + [70, "Ethiopia", 3, "TIGRAY", 57, "MISRAK", 351, "GULOMECHA"], + [70, "Ethiopia", 3, "TIGRAY", 57, "MISRAK", 352, "SAISI TSAIDA IMBA"], + [70, "Ethiopia", 3, "TIGRAY", 57, "MISRAK", 353, "GANTA AFESHUM"], + [70, "Ethiopia", 3, "TIGRAY", 57, "MISRAK", 354, "ASTIBI WENBERTA"], + [70, "Ethiopia", 3, "TIGRAY", 57, "MISRAK", 355, "HAWZEN"], + [70, "Ethiopia", 3, "TIGRAY", 57, "MISRAK", 356, "WKIRO"], + [70, "Ethiopia", 3, "TIGRAY", 57, "MISRAK", 357, "EROB"], + [70, "Ethiopia", 3, "TIGRAY", 57, "MISRAK", 593, "ADIGRAT TOWN ADMIN"], + [70, "Ethiopia", 3, "TIGRAY", 57, "MISRAK", 628, "KLETE AWLAELO"], + [70, "Ethiopia", 3, "TIGRAY", 58, "MIRABAWI", 358, "KWAFTA HUMERA"], + [70, "Ethiopia", 3, "TIGRAY", 58, "MIRABAWI", 359, "TSEGEDE"], + [70, "Ethiopia", 3, "TIGRAY", 58, "MIRABAWI", 360, "WELKAYIT"], + [70, "Ethiopia", 3, "TIGRAY", 58, "MIRABAWI", 594, "HUMERA TOWN ADMIN"], + [70, "Ethiopia", 3, "TIGRAY", 59, "SEMEN MIRABAWI", 361, "LAILAY ADIYABO"], + [70, "Ethiopia", 3, "TIGRAY", 59, "SEMEN MIRABAWI", 362, "MDEBAY ZANA"], + [70, "Ethiopia", 3, "TIGRAY", 59, "SEMEN MIRABAWI", 363, "TAHITAY ADIYABO"], + [70, "Ethiopia", 3, "TIGRAY", 59, "SEMEN MIRABAWI", 364, "TSELEMTI"], + [70, "Ethiopia", 3, "TIGRAY", 59, "SEMEN MIRABAWI", 365, "ASEGEDE TSIMBLA"], + [70, "Ethiopia", 3, "TIGRAY", 59, "SEMEN MIRABAWI", 595, "SHIRARO TOWN ADMIN"], + [70, "Ethiopia", 3, "TIGRAY", 59, "SEMEN MIRABAWI", 596, "TAHITAY KORARO"], + [70, "Ethiopia", 3, "TIGRAY", 59, "SEMEN MIRABAWI", 597, "INDASILASSIE TOWN ADMIN"], + [70, "Ethiopia", 3, "TIGRAY", 70, "DEBUBAWI ZONE", 366, "INIDAMOHENI"], + [70, "Ethiopia", 3, "TIGRAY", 70, "DEBUBAWI ZONE", 367, "INDERTA"], + [70, "Ethiopia", 3, "TIGRAY", 70, "DEBUBAWI ZONE", 368, "SAMRA SAHARTI"], + [70, "Ethiopia", 3, "TIGRAY", 70, "DEBUBAWI ZONE", 369, "ALAJE"], + [70, "Ethiopia", 3, "TIGRAY", 70, "DEBUBAWI ZONE", 370, "ALAMATA TOWN ADMIN"], + [70, "Ethiopia", 3, "TIGRAY", 70, "DEBUBAWI ZONE", 371, "OFLA"], + [70, "Ethiopia", 3, "TIGRAY", 70, "DEBUBAWI ZONE", 372, "RAYA AZEBO"], + [70, "Ethiopia", 3, "TIGRAY", 70, "DEBUBAWI ZONE", 598, "MAICHEW TOWN ADMIN"], + [70, "Ethiopia", 3, "TIGRAY", 70, "DEBUBAWI ZONE", 599, "KOREM TOWN ADMINISTRATION"], + [70, "Ethiopia", 3, "TIGRAY", 70, "DEBUBAWI ZONE", 629, "GETER ALAMATA"], + [70, "Ethiopia", 3, "TIGRAY", 70, "DEBUBAWI ZONE", 630, "HINTALO WAJRAT"], + [70, "Ethiopia", 3, "TIGRAY", 70, "DEBUBAWI ZONE", 1193, "SAMRE SEHARTI"], + [70, "Ethiopia", 3, "TIGRAY", 71, "MEKELE", 373, "SEMENE WORDA"], + [70, "Ethiopia", 3, "TIGRAY", 71, "MEKELE", 611, "DEBUB WEREDA"], + [70, "Ethiopia", 3, "TIGRAY", 71, "MEKELE", 623, "KUHA WOREDA"], + [70, "Ethiopia", 3, "TIGRAY", 71, "MEKELE", 879, "AIDER"], + [70, "Ethiopia", 3, "TIGRAY", 71, "MEKELE", 880, "ADI HAKI"], + [70, "Ethiopia", 3, "TIGRAY", 71, "MEKELE", 881, "HADNET"], + [70, "Ethiopia", 3, "TIGRAY", 71, "MEKELE", 882, "HAWULTI"], + [70, "Ethiopia", 3, "TIGRAY", 71, "MEKELE", 883, "KEDAMAY WOYANE"], + [70, "Ethiopia", 3, "TIGRAY", 99, "SOUTH EASTERN ZONE", 1192, "SAMRE SEHARTI"], + [70, "Ethiopia", 4, "AFAR", 42, "ZONE 1 (AYSSAITA)", 15, "AYSSAITA"], + [70, "Ethiopia", 4, "AFAR", 42, "ZONE 1 (AYSSAITA)", 22, "AFAMBO"], + [70, "Ethiopia", 4, "AFAR", 42, "ZONE 1 (AYSSAITA)", 23, "DUBTI"], + [70, "Ethiopia", 4, "AFAR", 42, "ZONE 1 (AYSSAITA)", 24, "MILE"], + [70, "Ethiopia", 4, "AFAR", 42, "ZONE 1 (AYSSAITA)", 25, "ELIDAAR"], + [70, "Ethiopia", 4, "AFAR", 42, "ZONE 1 (AYSSAITA)", 26, "CHIFRA"], + [70, "Ethiopia", 4, "AFAR", 42, "ZONE 1 (AYSSAITA)", 816, "ADAER"], + [70, "Ethiopia", 4, "AFAR", 42, "ZONE 1 (AYSSAITA)", 817, "KURI"], + [70, "Ethiopia", 4, "AFAR", 42, "ZONE 1 (AYSSAITA)", 1190, "SEMERA - LOGIA CITY ADMINISTRATION"], + [70, "Ethiopia", 4, "AFAR", 43, "ZONE 2 (ABBALLA)", 27, "BERHALLE"], + [70, "Ethiopia", 4, "AFAR", 43, "ZONE 2 (ABBALLA)", 28, "ABBALLA"], + [70, "Ethiopia", 4, "AFAR", 43, "ZONE 2 (ABBALLA)", 29, "KUNEBBA"], + [70, "Ethiopia", 4, "AFAR", 43, "ZONE 2 (ABBALLA)", 30, "AFFDERA"], + [70, "Ethiopia", 4, "AFAR", 43, "ZONE 2 (ABBALLA)", 31, "IREBTI"], + [70, "Ethiopia", 4, "AFAR", 43, "ZONE 2 (ABBALLA)", 32, "MEGALLE"], + [70, "Ethiopia", 4, "AFAR", 43, "ZONE 2 (ABBALLA)", 33, "DALLOL"], + [70, "Ethiopia", 4, "AFAR", 43, "ZONE 2 (ABBALLA)", 818, "BIDU"], + [70, "Ethiopia", 4, "AFAR", 44, "ZONE 3 (SIDAHAFAGE)", 34, "AMMIBARA"], + [70, "Ethiopia", 4, "AFAR", 44, "ZONE 3 (SIDAHAFAGE)", 35, "GEWANE"], + [70, "Ethiopia", 4, "AFAR", 44, "ZONE 3 (SIDAHAFAGE)", 36, "BUREMUDAYTU"], + [70, "Ethiopia", 4, "AFAR", 44, "ZONE 3 (SIDAHAFAGE)", 37, "AWASH"], + [70, "Ethiopia", 4, "AFAR", 44, "ZONE 3 (SIDAHAFAGE)", 38, "DULECHA"], + [70, "Ethiopia", 4, "AFAR", 44, "ZONE 3 (SIDAHAFAGE)", 39, "GACHENNE"], + [70, "Ethiopia", 4, "AFAR", 44, "ZONE 3 (SIDAHAFAGE)", 819, "ARGOBA"], + [70, "Ethiopia", 4, "AFAR", 44, "ZONE 3 (SIDAHAFAGE)", 1191, "AWASH CITY ADMINISTRATION"], + [70, "Ethiopia", 4, "AFAR", 64, "ZONE4 (KELEWAN)", 40, "KELEWAN"], + [70, "Ethiopia", 4, "AFAR", 64, "ZONE4 (KELEWAN)", 41, "YALLO"], + [70, "Ethiopia", 4, "AFAR", 64, "ZONE4 (KELEWAN)", 42, "AWRRA"], + [70, "Ethiopia", 4, "AFAR", 64, "ZONE4 (KELEWAN)", 43, "TERRU"], + [70, "Ethiopia", 4, "AFAR", 64, "ZONE4 (KELEWAN)", 44, "EWAA"], + [70, "Ethiopia", 4, "AFAR", 64, "ZONE4 (KELEWAN)", 908, "GULINA"], + [70, "Ethiopia", 4, "AFAR", 65, "ZONE 5 (DALLIFAGEA)", 45, "DALLIFAGEA"], + [70, "Ethiopia", 4, "AFAR", 65, "ZONE 5 (DALLIFAGEA)", 46, "ARTUMMA"], + [70, "Ethiopia", 4, "AFAR", 65, "ZONE 5 (DALLIFAGEA)", 47, "SEMUROBI"], + [70, "Ethiopia", 4, "AFAR", 65, "ZONE 5 (DALLIFAGEA)", 48, "DEWWEA"], + [70, "Ethiopia", 4, "AFAR", 65, "ZONE 5 (DALLIFAGEA)", 49, "TELALAK"], + [70, "Ethiopia", 4, "AFAR", 65, "ZONE 5 (DALLIFAGEA)", 866, "HADELE ELA"], + [70, "Ethiopia", 5, "BENSHANGUL GUMUZ", 39, "ASOSA", 16, "ASSOSA"], + [70, "Ethiopia", 5, "BENSHANGUL GUMUZ", 39, "ASOSA", 163, "KURMUK"], + [70, "Ethiopia", 5, "BENSHANGUL GUMUZ", 39, "ASOSA", 164, "BANBASI"], + [70, "Ethiopia", 5, "BENSHANGUL GUMUZ", 39, "ASOSA", 165, "MENGE"], + [70, "Ethiopia", 5, "BENSHANGUL GUMUZ", 39, "ASOSA", 166, "SHERKOLE"], + [70, "Ethiopia", 5, "BENSHANGUL GUMUZ", 39, "ASOSA", 167, "KOMOSHA"], + [70, "Ethiopia", 5, "BENSHANGUL GUMUZ", 39, "ASOSA", 168, "ODABUL DIGLU"], + [70, "Ethiopia", 5, "BENSHANGUL GUMUZ", 39, "ASOSA", 169, "PAWE SPECIAL WORDA"], + [70, "Ethiopia", 5, "BENSHANGUL GUMUZ", 39, "ASOSA", 170, "MAO KOMO SPECIAL WORDA"], + [70, "Ethiopia", 5, "BENSHANGUL GUMUZ", 39, "ASOSA", 1201, "ASOSSA TOWN ADMINISTRATION"], + [70, "Ethiopia", 5, "BENSHANGUL GUMUZ", 40, "KAMSH", 171, "KAMASH"], + [70, "Ethiopia", 5, "BENSHANGUL GUMUZ", 40, "KAMSH", 172, "SEDAL"], + [70, "Ethiopia", 5, "BENSHANGUL GUMUZ", 40, "KAMSH", 173, "BELODJAGANFOY"], + [70, "Ethiopia", 5, "BENSHANGUL GUMUZ", 40, "KAMSH", 174, "AGALOMITI"], + [70, "Ethiopia", 5, "BENSHANGUL GUMUZ", 40, "KAMSH", 175, "YASO"], + [70, "Ethiopia", 5, "BENSHANGUL GUMUZ", 40, "KAMSH", 1202, "KAMASHI TOWN ADMINSTRATION"], + [70, "Ethiopia", 5, "BENSHANGUL GUMUZ", 41, "METEKEL", 176, "MAMDURA"], + [70, "Ethiopia", 5, "BENSHANGUL GUMUZ", 41, "METEKEL", 177, "DANGUR"], + [70, "Ethiopia", 5, "BENSHANGUL GUMUZ", 41, "METEKEL", 178, "WENBERA"], + [70, "Ethiopia", 5, "BENSHANGUL GUMUZ", 41, "METEKEL", 179, "DUBATE"], + [70, "Ethiopia", 5, "BENSHANGUL GUMUZ", 41, "METEKEL", 180, "BULEN"], + [70, "Ethiopia", 5, "BENSHANGUL GUMUZ", 41, "METEKEL", 181, "GUBA"], + [70, "Ethiopia", 5, "BENSHANGUL GUMUZ", 41, "METEKEL", 815, "PAWEIE"], + [70, "Ethiopia", 5, "BENSHANGUL GUMUZ", 41, "METEKEL", 1203, "GELGEL BELES TOWN ADMINSTRATION"], + [70, "Ethiopia", 5, "BENSHANGUL GUMUZ", 89, "NO ZONE/MAO KOMO", 896, "MAO KOMO"], + [70, "Ethiopia", 6, "SOMALI", 30, "SITI ZONE", 12, "SHINELE"], + [70, "Ethiopia", 6, "SOMALI", 30, "SITI ZONE", 197, "DENBEL"], + [70, "Ethiopia", 6, "SOMALI", 30, "SITI ZONE", 198, "ERAR"], + [70, "Ethiopia", 6, "SOMALI", 30, "SITI ZONE", 199, "AYSHA"], + [70, "Ethiopia", 6, "SOMALI", 30, "SITI ZONE", 200, "AFDEM"], + [70, "Ethiopia", 6, "SOMALI", 30, "SITI ZONE", 201, "MIESO"], + [70, "Ethiopia", 6, "SOMALI", 30, "SITI ZONE", 811, "MA'YS"], + [70, "Ethiopia", 6, "SOMALI", 30, "SITI ZONE", 898, "NO WOREDA-1412"], + [70, "Ethiopia", 6, "SOMALI", 30, "SITI ZONE", 899, "NO WOREDA-1413"], + [70, "Ethiopia", 6, "SOMALI", 30, "SITI ZONE", 986, "Hadagale"], + [70, "Ethiopia", 6, "SOMALI", 30, "SITI ZONE", 988, "HADAGALE WOREDA"], + [70, "Ethiopia", 6, "SOMALI", 31, "FAAFAN ZONE", 190, "JIJIGA"], + [70, "Ethiopia", 6, "SOMALI", 31, "FAAFAN ZONE", 191, "KEBRI BEYAH"], + [70, "Ethiopia", 6, "SOMALI", 31, "FAAFAN ZONE", 192, "AWUBERE"], + [70, "Ethiopia", 6, "SOMALI", 31, "FAAFAN ZONE", 193, "HARSHIN"], + [70, "Ethiopia", 6, "SOMALI", 31, "FAAFAN ZONE", 194, "BABILE"], + [70, "Ethiopia", 6, "SOMALI", 31, "FAAFAN ZONE", 195, "GURSUM"], + [70, "Ethiopia", 6, "SOMALI", 31, "FAAFAN ZONE", 196, "EJERSAGORO"], + [70, "Ethiopia", 6, "SOMALI", 31, "FAAFAN ZONE", 980, "Tuli Guled"], + [70, "Ethiopia", 6, "SOMALI", 31, "FAAFAN ZONE", 981, "Goljano"], + [70, "Ethiopia", 6, "SOMALI", 31, "FAAFAN ZONE", 983, "GOLJANO WOREDA"], + [70, "Ethiopia", 6, "SOMALI", 32, "KORAHI", 202, "KEBRIDAHAR"], + [70, "Ethiopia", 6, "SOMALI", 32, "KORAHI", 203, "WEYIN"], + [70, "Ethiopia", 6, "SOMALI", 32, "KORAHI", 204, "SHYKOSH"], + [70, "Ethiopia", 6, "SOMALI", 32, "KORAHI", 205, "SHILABO"], + [70, "Ethiopia", 6, "SOMALI", 32, "KORAHI", 900, "DOBOWEYN"], + [70, "Ethiopia", 6, "SOMALI", 32, "KORAHI", 996, "Marsin"], + [70, "Ethiopia", 6, "SOMALI", 33, "SHABEELE ZONE", 206, "GODE"], + [70, "Ethiopia", 6, "SOMALI", 33, "SHABEELE ZONE", 207, "KELAFO"], + [70, "Ethiopia", 6, "SOMALI", 33, "SHABEELE ZONE", 208, "MUSTEHIL"], + [70, "Ethiopia", 6, "SOMALI", 33, "SHABEELE ZONE", 209, "FERFEF"], + [70, "Ethiopia", 6, "SOMALI", 33, "SHABEELE ZONE", 210, "DANAN"], + [70, "Ethiopia", 6, "SOMALI", 33, "SHABEELE ZONE", 211, "ADADA"], + [70, "Ethiopia", 6, "SOMALI", 33, "SHABEELE ZONE", 212, "EMAYBERE"], + [70, "Ethiopia", 6, "SOMALI", 33, "SHABEELE ZONE", 901, "ADADLEY"], + [70, "Ethiopia", 6, "SOMALI", 33, "SHABEELE ZONE", 902, "EAST EMAY"], + [70, "Ethiopia", 6, "SOMALI", 33, "SHABEELE ZONE", 992, "Elwayn"], + [70, "Ethiopia", 6, "SOMALI", 33, "SHABEELE ZONE", 993, "Ber'ano"], + [70, "Ethiopia", 6, "SOMALI", 33, "SHABEELE ZONE", 1184, "ABAGOROW"], + [70, "Ethiopia", 6, "SOMALI", 34, "JARAR ZONE", 213, "DEGAHABUR"], + [70, "Ethiopia", 6, "SOMALI", 34, "JARAR ZONE", 214, "AWARE"], + [70, "Ethiopia", 6, "SOMALI", 34, "JARAR ZONE", 215, "DGAHMEDOW"], + [70, "Ethiopia", 6, "SOMALI", 34, "JARAR ZONE", 216, "GASHAMO"], + [70, "Ethiopia", 6, "SOMALI", 34, "JARAR ZONE", 812, "GUNAGADO"], + [70, "Ethiopia", 6, "SOMALI", 34, "JARAR ZONE", 982, "Birkod"], + [70, "Ethiopia", 6, "SOMALI", 34, "JARAR ZONE", 984, "Daroor"], + [70, "Ethiopia", 6, "SOMALI", 34, "JARAR ZONE", 985, "Ararso"], + [70, "Ethiopia", 6, "SOMALI", 34, "JARAR ZONE", 1014, "YOALE"], + [70, "Ethiopia", 6, "SOMALI", 35, "NOGOB ZONE", 217, "FIK"], + [70, "Ethiopia", 6, "SOMALI", 35, "NOGOB ZONE", 218, "SEGEG"], + [70, "Ethiopia", 6, "SOMALI", 35, "NOGOB ZONE", 219, "HAMERO"], + [70, "Ethiopia", 6, "SOMALI", 35, "NOGOB ZONE", 220, "DUHUN"], + [70, "Ethiopia", 6, "SOMALI", 35, "NOGOB ZONE", 221, "GERBO"], + [70, "Ethiopia", 6, "SOMALI", 35, "NOGOB ZONE", 222, "LGEHAD"], + [70, "Ethiopia", 6, "SOMALI", 35, "NOGOB ZONE", 223, "SELHAD"], + [70, "Ethiopia", 6, "SOMALI", 35, "NOGOB ZONE", 813, "MAYAMULUKO"], + [70, "Ethiopia", 6, "SOMALI", 35, "NOGOB ZONE", 903, "GAEBO"], + [70, "Ethiopia", 6, "SOMALI", 35, "NOGOB ZONE", 991, "Qubi"], + [70, "Ethiopia", 6, "SOMALI", 35, "NOGOB ZONE", 1168, "CEELWAYNE"], + [70, "Ethiopia", 6, "SOMALI", 36, "DOLLO ZONE", 224, "WARDER"], + [70, "Ethiopia", 6, "SOMALI", 36, "DOLLO ZONE", 225, "GELAD"], + [70, "Ethiopia", 6, "SOMALI", 36, "DOLLO ZONE", 226, "DANOD"], + [70, "Ethiopia", 6, "SOMALI", 36, "DOLLO ZONE", 227, "BOK"], + [70, "Ethiopia", 6, "SOMALI", 36, "DOLLO ZONE", 989, "Daratole"], + [70, "Ethiopia", 6, "SOMALI", 37, "AFDER", 228, "ELKERE"], + [70, "Ethiopia", 6, "SOMALI", 37, "AFDER", 229, "HARGELE"], + [70, "Ethiopia", 6, "SOMALI", 37, "AFDER", 230, "BARE"], + [70, "Ethiopia", 6, "SOMALI", 37, "AFDER", 231, "JERETI"], + [70, "Ethiopia", 6, "SOMALI", 37, "AFDER", 232, "IMAYEGELEBED"], + [70, "Ethiopia", 6, "SOMALI", 37, "AFDER", 233, "GORO BAKAKSA"], + [70, "Ethiopia", 6, "SOMALI", 37, "AFDER", 234, "GURDAMOLE"], + [70, "Ethiopia", 6, "SOMALI", 37, "AFDER", 814, "DOLOBAY"], + [70, "Ethiopia", 6, "SOMALI", 37, "AFDER", 904, "WEST EMAY"], + [70, "Ethiopia", 6, "SOMALI", 37, "AFDER", 994, "Qarsadula"], + [70, "Ethiopia", 6, "SOMALI", 37, "AFDER", 995, "Raso"], + [70, "Ethiopia", 6, "SOMALI", 37, "AFDER", 1186, "GODGOD"], + [70, "Ethiopia", 6, "SOMALI", 38, "LIBON", 235, "FILTU"], + [70, "Ethiopia", 6, "SOMALI", 38, "LIBON", 236, "DOLADEW"], + [70, "Ethiopia", 6, "SOMALI", 38, "LIBON", 237, "MOYALE"], + [70, "Ethiopia", 6, "SOMALI", 38, "LIBON", 238, "KEAHORE/HADAT/"], + [70, "Ethiopia", 6, "SOMALI", 38, "LIBON", 987, "Mubarak"], + [70, "Ethiopia", 6, "SOMALI", 38, "LIBON", 1015, "DEKA SUFTI"], + [70, "Ethiopia", 6, "SOMALI", 38, "LIBON", 1189, "BOQAL-MAY"], + [70, "Ethiopia", 6, "SOMALI", 93, "ERER ZONE", 1171, "FIIQ"], + [70, "Ethiopia", 7, "GAMBELA", 27, "NUER", 17, "GAMBELLA"], + [70, "Ethiopia", 7, "GAMBELA", 27, "NUER", 182, "EITANG"], + [70, "Ethiopia", 7, "GAMBELA", 27, "NUER", 183, "JIKAWO"], + [70, "Ethiopia", 7, "GAMBELA", 27, "NUER", 184, "AKOBO"], + [70, "Ethiopia", 7, "GAMBELA", 27, "NUER", 808, "LARE"], + [70, "Ethiopia", 7, "GAMBELA", 27, "NUER", 809, "MAKUEY"], + [70, "Ethiopia", 7, "GAMBELA", 27, "NUER", 979, "Wantuar"], + [70, "Ethiopia", 7, "GAMBELA", 28, "AGNUWAK", 185, "ABOBO"], + [70, "Ethiopia", 7, "GAMBELA", 28, "AGNUWAK", 186, "GOG"], + [70, "Ethiopia", 7, "GAMBELA", 28, "AGNUWAK", 188, "DIMA"], + [70, "Ethiopia", 7, "GAMBELA", 28, "AGNUWAK", 189, "JOR"], + [70, "Ethiopia", 7, "GAMBELA", 28, "AGNUWAK", 810, "GAMBELA"], + [70, "Ethiopia", 7, "GAMBELA", 87, "MEZENGER", 187, "GODERE"], + [70, "Ethiopia", 7, "GAMBELA", 87, "MEZENGER", 977, "MENGESH"], + [70, "Ethiopia", 7, "GAMBELA", 88, "NO ZONE/ETANG", 895, "ETANG "], + [70, "Ethiopia", 7, "GAMBELA", 90, "GAMBELLA TOWN ADMIN", 978, "GAMBELLA TOWN ADMIN"], + [70, "Ethiopia", 8, "HARARI", 60, "NO ZONE - HARARI", 18, "NO WOREDA-9"], + [70, "Ethiopia", 9, "SNNPRS", 10, "HALABA ZONE", 600, "ALABA CITY ADMINISTRATION"], + [70, "Ethiopia", 9, "SNNPRS", 10, "HALABA ZONE", 1247, "WERA WOREDA"], + [70, "Ethiopia", 9, "SNNPRS", 10, "HALABA ZONE", 1248, "ATOTI OULO WOREDA"], + [70, "Ethiopia", 9, "SNNPRS", 10, "HALABA ZONE", 1249, "WERA DIJO WOREDA"], + [70, "Ethiopia", 9, "SNNPRS", 11, "HAWASSA CITY ADMIN", 624, "NO WOREDA-193"], + [70, "Ethiopia", 9, "SNNPRS", 11, "HAWASSA CITY ADMIN", 776, "HAWASSA CITY ADM"], + [70, "Ethiopia", 9, "SNNPRS", 11, "HAWASSA CITY ADMIN", 777, "TULA SUB TOWN ADMIN"], + [70, "Ethiopia", 9, "SNNPRS", 18, "GEDIO", 248, "WENAGO"], + [70, "Ethiopia", 9, "SNNPRS", 18, "GEDIO", 249, "YIRGACHEFE"], + [70, "Ethiopia", 9, "SNNPRS", 18, "GEDIO", 250, "COCHERE"], + [70, "Ethiopia", 9, "SNNPRS", 18, "GEDIO", 251, "BULE"], + [70, "Ethiopia", 9, "SNNPRS", 18, "GEDIO", 566, "DILLA TOWN ADMIN"], + [70, "Ethiopia", 9, "SNNPRS", 18, "GEDIO", 567, "YIRGACHEFE TOWN ADMIN"], + [70, "Ethiopia", 9, "SNNPRS", 18, "GEDIO", 720, "GEDEB"], + [70, "Ethiopia", 9, "SNNPRS", 18, "GEDIO", 721, "DILLA ZURIA"], + [70, "Ethiopia", 9, "SNNPRS", 18, "GEDIO", 722, "WERABE CITY ADMINISTRATION"], + [70, "Ethiopia", 9, "SNNPRS", 18, "GEDIO", 790, "DILA VICINITY"], + [70, "Ethiopia", 9, "SNNPRS", 18, "GEDIO", 1232, "GEDEB TOWN ADMINSTRATION"], + [70, "Ethiopia", 9, "SNNPRS", 18, "GEDIO", 1233, "CHELELEKTU TOWN ADMINSTRATION"], + [70, "Ethiopia", 9, "SNNPRS", 18, "GEDIO", 1234, "CHORSO MAZORIA WOREDA"], + [70, "Ethiopia", 9, "SNNPRS", 18, "GEDIO", 1235, "RAPE WOREDA"], + [70, "Ethiopia", 9, "SNNPRS", 19, "KENBATA TENBARO", 252, "KEDIDA GAMELA"], + [70, "Ethiopia", 9, "SNNPRS", 19, "KENBATA TENBARO", 253, "QACHA BIRA"], + [70, "Ethiopia", 9, "SNNPRS", 19, "KENBATA TENBARO", 254, "ANGACHA"], + [70, "Ethiopia", 9, "SNNPRS", 19, "KENBATA TENBARO", 255, "TENBARO"], + [70, "Ethiopia", 9, "SNNPRS", 19, "KENBATA TENBARO", 586, "DURAME TOWN ADMIN"], + [70, "Ethiopia", 9, "SNNPRS", 19, "KENBATA TENBARO", 655, "DOYOGENA"], + [70, "Ethiopia", 9, "SNNPRS", 19, "KENBATA TENBARO", 727, "HADERO TOWN"], + [70, "Ethiopia", 9, "SNNPRS", 19, "KENBATA TENBARO", 728, "DEMBOYA"], + [70, "Ethiopia", 9, "SNNPRS", 19, "KENBATA TENBARO", 791, "HADARO & TUNTO"], + [70, "Ethiopia", 9, "SNNPRS", 19, "KENBATA TENBARO", 1036, "SHINSHICHO TOWN"], + [70, "Ethiopia", 9, "SNNPRS", 19, "KENBATA TENBARO", 1226, "ADILO ZURIA WOREDA"], + [70, "Ethiopia", 9, "SNNPRS", 20, "WOLAYTA", 256, "SODO VICINTY"], + [70, "Ethiopia", 9, "SNNPRS", 20, "WOLAYTA", 257, "DAMOT GALE"], + [70, "Ethiopia", 9, "SNNPRS", 20, "WOLAYTA", 258, "DAMOT WOYIDA"], + [70, "Ethiopia", 9, "SNNPRS", 20, "WOLAYTA", 259, "BOLOSO SORE"], + [70, "Ethiopia", 9, "SNNPRS", 20, "WOLAYTA", 260, "OFFA"], + [70, "Ethiopia", 9, "SNNPRS", 20, "WOLAYTA", 261, "KINDO KOYISHA"], + [70, "Ethiopia", 9, "SNNPRS", 20, "WOLAYTA", 262, "HUMBO"], + [70, "Ethiopia", 9, "SNNPRS", 20, "WOLAYTA", 570, "SODO TOWN ADMIN"], + [70, "Ethiopia", 9, "SNNPRS", 20, "WOLAYTA", 579, "BODITY TOWN ADMIN"], + [70, "Ethiopia", 9, "SNNPRS", 20, "WOLAYTA", 580, "ARCKA CITY ADMINISTRATION"], + [70, "Ethiopia", 9, "SNNPRS", 20, "WOLAYTA", 743, "DAMOT SORE"], + [70, "Ethiopia", 9, "SNNPRS", 20, "WOLAYTA", 744, "DAMOT FULASE"], + [70, "Ethiopia", 9, "SNNPRS", 20, "WOLAYTA", 745, "BELESO BONBE"], + [70, "Ethiopia", 9, "SNNPRS", 20, "WOLAYTA", 746, "KINDO DIDAYO"], + [70, "Ethiopia", 9, "SNNPRS", 20, "WOLAYTA", 747, "DIGUNA FANGO"], + [70, "Ethiopia", 9, "SNNPRS", 20, "WOLAYTA", 792, "BULOSO BOMBE"], + [70, "Ethiopia", 9, "SNNPRS", 20, "WOLAYTA", 793, "DAGUNA FANGO"], + [70, "Ethiopia", 9, "SNNPRS", 20, "WOLAYTA", 794, "DAMOT FULAS"], + [70, "Ethiopia", 9, "SNNPRS", 20, "WOLAYTA", 795, "KINDO DEDAYE"], + [70, "Ethiopia", 9, "SNNPRS", 20, "WOLAYTA", 1240, "TEBELA TOWN ADMINSTRATION"], + [70, "Ethiopia", 9, "SNNPRS", 20, "WOLAYTA", 1241, "GUNUNO HAMUS TOWN ADMINSTRATION"], + [70, "Ethiopia", 9, "SNNPRS", 20, "WOLAYTA", 1242, "GESUBA TOWN ADMINSTRATION"], + [70, "Ethiopia", 9, "SNNPRS", 20, "WOLAYTA", 1243, "HOBICHA WOREDA"], + [70, "Ethiopia", 9, "SNNPRS", 20, "WOLAYTA", 1244, "ABELA ABAYA WOREDA"], + [70, "Ethiopia", 9, "SNNPRS", 20, "WOLAYTA", 1245, "BAYIRA KOYISHA WOREDA"], + [70, "Ethiopia", 9, "SNNPRS", 20, "WOLAYTA", 1246, "KAWA KOYISHA WOREDA"], + [70, "Ethiopia", 9, "SNNPRS", 21, "HADYA", 263, "LIMU"], + [70, "Ethiopia", 9, "SNNPRS", 21, "HADYA", 264, "MISHA"], + [70, "Ethiopia", 9, "SNNPRS", 21, "HADYA", 265, "SORO"], + [70, "Ethiopia", 9, "SNNPRS", 21, "HADYA", 266, "BADEWACHO"], + [70, "Ethiopia", 9, "SNNPRS", 21, "HADYA", 267, "GIBE"], + [70, "Ethiopia", 9, "SNNPRS", 21, "HADYA", 268, "SHASHEGO"], + [70, "Ethiopia", 9, "SNNPRS", 21, "HADYA", 269, "DUNA"], + [70, "Ethiopia", 9, "SNNPRS", 21, "HADYA", 585, "HOSAINA TOWN ADMINISTRATION"], + [70, "Ethiopia", 9, "SNNPRS", 21, "HADYA", 724, "MIRAB BADEWACHO"], + [70, "Ethiopia", 9, "SNNPRS", 21, "HADYA", 725, "GOMBORA"], + [70, "Ethiopia", 9, "SNNPRS", 21, "HADYA", 726, "MISRAK BADEWACHO"], + [70, "Ethiopia", 9, "SNNPRS", 21, "HADYA", 796, "ANLEMO"], + [70, "Ethiopia", 9, "SNNPRS", 21, "HADYA", 797, "EAST BADEWACHO"], + [70, "Ethiopia", 9, "SNNPRS", 21, "HADYA", 798, "GONBERA"], + [70, "Ethiopia", 9, "SNNPRS", 21, "HADYA", 1035, "SHONE TOWN"], + [70, "Ethiopia", 9, "SNNPRS", 21, "HADYA", 1250, "GIMIBECHU TOWN ADMINSTRATION"], + [70, "Ethiopia", 9, "SNNPRS", 21, "HADYA", 1251, "JAJURA TOWN ADMINTRATION"], + [70, "Ethiopia", 9, "SNNPRS", 21, "HADYA", 1252, "AMEKA WOREDA"], + [70, "Ethiopia", 9, "SNNPRS", 21, "HADYA", 1253, "SIRARO BADEWACHO WEREDA"], + [70, "Ethiopia", 9, "SNNPRS", 21, "HADYA", 1254, "MIRAB SORO WOREDA "], + [70, "Ethiopia", 9, "SNNPRS", 22, "GAMO ZONE", 270, "ARBAMINCH ZURIA"], + [70, "Ethiopia", 9, "SNNPRS", 22, "GAMO ZONE", 271, "MIRAB ABAYA"], + [70, "Ethiopia", 9, "SNNPRS", 22, "GAMO ZONE", 272, "BONKE"], + [70, "Ethiopia", 9, "SNNPRS", 22, "GAMO ZONE", 273, "KEMBA TWON ADMINSTRATION"], + [70, "Ethiopia", 9, "SNNPRS", 22, "GAMO ZONE", 274, "CHENCHA ZURIA WOREDA"], + [70, "Ethiopia", 9, "SNNPRS", 22, "GAMO ZONE", 275, "DEREMALO"], + [70, "Ethiopia", 9, "SNNPRS", 22, "GAMO ZONE", 276, "KUCHA"], + [70, "Ethiopia", 9, "SNNPRS", 22, "GAMO ZONE", 277, "GOFA ZURIA"], + [70, "Ethiopia", 9, "SNNPRS", 22, "GAMO ZONE", 280, "BOREDA"], + [70, "Ethiopia", 9, "SNNPRS", 22, "GAMO ZONE", 281, "DITA"], + [70, "Ethiopia", 9, "SNNPRS", 22, "GAMO ZONE", 581, "ARBAMINCH TOWN ADMINISTRATION"], + [70, "Ethiopia", 9, "SNNPRS", 22, "GAMO ZONE", 719, "DENBA GOFA"], + [70, "Ethiopia", 9, "SNNPRS", 22, "GAMO ZONE", 800, "GIZE GOFA"], + [70, "Ethiopia", 9, "SNNPRS", 22, "GAMO ZONE", 1218, "CHENCHA TOWN ADMINSTRATION"], + [70, "Ethiopia", 9, "SNNPRS", 22, "GAMO ZONE", 1219, "SELAMBER TOWN ADMINSTRATION"], + [70, "Ethiopia", 9, "SNNPRS", 22, "GAMO ZONE", 1220, "KEMBA ZURIYA WOREDA"], + [70, "Ethiopia", 9, "SNNPRS", 22, "GAMO ZONE", 1221, "GARDA MARTA WOREDA"], + [70, "Ethiopia", 9, "SNNPRS", 22, "GAMO ZONE", 1222, "GERESE WOREDA"], + [70, "Ethiopia", 9, "SNNPRS", 22, "GAMO ZONE", 1223, "GACHO BABA WOREDA"], + [70, "Ethiopia", 9, "SNNPRS", 22, "GAMO ZONE", 1224, "KOGOTA WOREDA"], + [70, "Ethiopia", 9, "SNNPRS", 22, "GAMO ZONE", 1225, "KUCHA ALFA WOREDA"], + [70, "Ethiopia", 9, "SNNPRS", 22, "GAMO ZONE", 1277, "BIRIBIR TOWN ADMINSTRATION"], + [70, "Ethiopia", 9, "SNNPRS", 25, "DEBUB OMO", 300, "BAKO GAZER"], + [70, "Ethiopia", 9, "SNNPRS", 25, "DEBUB OMO", 301, "HAMER"], + [70, "Ethiopia", 9, "SNNPRS", 25, "DEBUB OMO", 302, "GELEB"], + [70, "Ethiopia", 9, "SNNPRS", 25, "DEBUB OMO", 303, "SELAMAGO"], + [70, "Ethiopia", 9, "SNNPRS", 25, "DEBUB OMO", 304, "GELILA"], + [70, "Ethiopia", 9, "SNNPRS", 25, "DEBUB OMO", 305, "BENA TSEMAY WOREDA"], + [70, "Ethiopia", 9, "SNNPRS", 25, "DEBUB OMO", 587, "JINKA CITY ADMINISTRATION"], + [70, "Ethiopia", 9, "SNNPRS", 25, "DEBUB OMO", 714, "DASENECH"], + [70, "Ethiopia", 9, "SNNPRS", 25, "DEBUB OMO", 715, "DEBUB ARI"], + [70, "Ethiopia", 9, "SNNPRS", 25, "DEBUB OMO", 716, "SEMEN ARI"], + [70, "Ethiopia", 9, "SNNPRS", 25, "DEBUB OMO", 802, "GNANGATOM"], + [70, "Ethiopia", 9, "SNNPRS", 25, "DEBUB OMO", 803, "KURAZ"], + [70, "Ethiopia", 9, "SNNPRS", 25, "DEBUB OMO", 804, "MALE"], + [70, "Ethiopia", 9, "SNNPRS", 25, "DEBUB OMO", 805, "NORTH ARI"], + [70, "Ethiopia", 9, "SNNPRS", 25, "DEBUB OMO", 806, "SOUTH ARI"], + [70, "Ethiopia", 9, "SNNPRS", 68, "SILTE", 328, "SANKURA"], + [70, "Ethiopia", 9, "SNNPRS", 68, "SILTE", 329, "AZERNET BERBERE"], + [70, "Ethiopia", 9, "SNNPRS", 68, "SILTE", 330, "ALICHO WERIRO"], + [70, "Ethiopia", 9, "SNNPRS", 68, "SILTE", 331, "DALOCHA"], + [70, "Ethiopia", 9, "SNNPRS", 68, "SILTE", 332, "SILTE"], + [70, "Ethiopia", 9, "SNNPRS", 68, "SILTE", 333, "LANFRO"], + [70, "Ethiopia", 9, "SNNPRS", 68, "SILTE", 739, "MIRAB AZERNET BERBERE"], + [70, "Ethiopia", 9, "SNNPRS", 68, "SILTE", 740, "HULBAREG"], + [70, "Ethiopia", 9, "SNNPRS", 68, "SILTE", 741, "WERABE CITY ADMINISTRATION"], + [70, "Ethiopia", 9, "SNNPRS", 68, "SILTE", 742, "MISRAK AZERNET BERBERE"], + [70, "Ethiopia", 9, "SNNPRS", 68, "SILTE", 874, "EAST AZERNET BERBERE"], + [70, "Ethiopia", 9, "SNNPRS", 68, "SILTE", 875, "WELBAREG"], + [70, "Ethiopia", 9, "SNNPRS", 68, "SILTE", 876, "WERABE TOWN ADM"], + [70, "Ethiopia", 9, "SNNPRS", 68, "SILTE", 877, "WEST AZERNET BERBERE"], + [70, "Ethiopia", 9, "SNNPRS", 68, "SILTE", 1227, "KIBET TOWN ADMINSTRATION"], + [70, "Ethiopia", 9, "SNNPRS", 68, "SILTE", 1228, "TORA TOWN ADMINSTRATION"], + [70, "Ethiopia", 9, "SNNPRS", 68, "SILTE", 1229, "MITO WOREDA"], + [70, "Ethiopia", 9, "SNNPRS", 68, "SILTE", 1230, "MISRAK SILTI WOREDA"], + [70, "Ethiopia", 9, "SNNPRS", 68, "SILTE", 1275, "TEST"], + [70, "Ethiopia", 9, "SNNPRS", 69, "SEGEN AREA PEOPLE ZONE", 334, "AMARO"], + [70, "Ethiopia", 9, "SNNPRS", 69, "SEGEN AREA PEOPLE ZONE", 335, "BURJI"], + [70, "Ethiopia", 9, "SNNPRS", 69, "SEGEN AREA PEOPLE ZONE", 336, "DERASHE"], + [70, "Ethiopia", 9, "SNNPRS", 69, "SEGEN AREA PEOPLE ZONE", 337, "KONSO"], + [70, "Ethiopia", 9, "SNNPRS", 69, "SEGEN AREA PEOPLE ZONE", 341, "ALABA"], + [70, "Ethiopia", 9, "SNNPRS", 69, "SEGEN AREA PEOPLE ZONE", 990, "ALE"], + [70, "Ethiopia", 9, "SNNPRS", 69, "SEGEN AREA PEOPLE ZONE", 1040, "SEGEN TOWN"], + [70, "Ethiopia", 9, "SNNPRS", 91, "SPECIAL WOREDA", 338, "BASKETO"], + [70, "Ethiopia", 9, "SNNPRS", 91, "SPECIAL WOREDA", 339, "KONTA"], + [70, "Ethiopia", 9, "SNNPRS", 91, "SPECIAL WOREDA", 340, "YEM"], + [70, "Ethiopia", 9, "SNNPRS", 91, "SPECIAL WOREDA", 878, "ALABA CITY ADM"], + [70, "Ethiopia", 9, "SNNPRS", 101, "GOFA ZONE", 278, "UBA DEBERSEHAY WOREDA"], + [70, "Ethiopia", 9, "SNNPRS", 101, "GOFA ZONE", 279, "MELO KOZA WOREDA"], + [70, "Ethiopia", 9, "SNNPRS", 101, "GOFA ZONE", 282, "ZALA WOREDA"], + [70, "Ethiopia", 9, "SNNPRS", 101, "GOFA ZONE", 582, "SAWLA CITY ADMINISTRATION"], + [70, "Ethiopia", 9, "SNNPRS", 101, "GOFA ZONE", 717, "OYDA WOREDA"], + [70, "Ethiopia", 9, "SNNPRS", 101, "GOFA ZONE", 718, "GEZE GOFA"], + [70, "Ethiopia", 9, "SNNPRS", 101, "GOFA ZONE", 799, "DEMBA GOFA WOREDA"], + [70, "Ethiopia", 9, "SNNPRS", 101, "GOFA ZONE", 1231, "MELO GADA WOREDA"], + [70, "Ethiopia", 9, "SNNPRS", 101, "GOFA ZONE", 1279, "LEHA TOWN ADMINSTRATION"], + [70, "Ethiopia", 9, "SNNPRS", 103, "KONSO ZONE", 1236, "KARAT TOWN ADMINSTRATION"], + [70, "Ethiopia", 9, "SNNPRS", 103, "KONSO ZONE", 1237, "KENNA WOREDA"], + [70, "Ethiopia", 9, "SNNPRS", 103, "KONSO ZONE", 1238, "SEGEN ZURIYA WOREDA"], + [70, "Ethiopia", 9, "SNNPRS", 103, "KONSO ZONE", 1239, "KARAT ZURIA WOREDA"], + [70, "Ethiopia", 9, "SNNPRS", 109, "SNNPRS", 1286, "AMAYA CITY ADMINSTRATION "], + [70, "Ethiopia", 9, "SNNPRS", 109, "SNNPRS", 1287, "CHIDA CITY ADMINSTRATION "], + [70, "Ethiopia", 10, "DIRE DAWA", 61, "NO ZONE DIRE DAWA", 20, "WOREDA 1"], + [70, "Ethiopia", 10, "DIRE DAWA", 61, "NO ZONE DIRE DAWA", 374, "WOREDA 2"], + [70, "Ethiopia", 10, "DIRE DAWA", 61, "NO ZONE DIRE DAWA", 375, "WOREDA 3"], + [70, "Ethiopia", 10, "DIRE DAWA", 61, "NO ZONE DIRE DAWA", 376, "WOREDA 4"], + [70, "Ethiopia", 10, "DIRE DAWA", 61, "NO ZONE DIRE DAWA", 631, "NO WOREDA-1100"], + [70, "Ethiopia", 11, "AMAHARA", 45, "BAHIDAR SPECIAL", 14, "NO WOREDA-4"], + [70, "Ethiopia", 11, "AMAHARA", 47, "SOUTH WOLLO", 62, "DESSIE KETEMA"], + [70, "Ethiopia", 11, "AMAHARA", 47, "SOUTH WOLLO", 63, "DESSIE ZURIA"], + [70, "Ethiopia", 11, "AMAHARA", 47, "SOUTH WOLLO", 64, "ALBIKO"], + [70, "Ethiopia", 11, "AMAHARA", 47, "SOUTH WOLLO", 65, "KOMBOLCHA"], + [70, "Ethiopia", 11, "AMAHARA", 47, "SOUTH WOLLO", 66, "KALU"], + [70, "Ethiopia", 11, "AMAHARA", 47, "SOUTH WOLLO", 67, "KUTABER"], + [70, "Ethiopia", 11, "AMAHARA", 47, "SOUTH WOLLO", 68, "TEHULEDERIA"], + [70, "Ethiopia", 11, "AMAHARA", 47, "SOUTH WOLLO", 69, "AMBASEL"], + [70, "Ethiopia", 11, "AMAHARA", 47, "SOUTH WOLLO", 70, "WOREBABO"], + [70, "Ethiopia", 11, "AMAHARA", 47, "SOUTH WOLLO", 71, "JAMMA"], + [70, "Ethiopia", 11, "AMAHARA", 47, "SOUTH WOLLO", 72, "WORIELUE"], + [70, "Ethiopia", 11, "AMAHARA", 47, "SOUTH WOLLO", 73, "LEGAMBO"], + [70, "Ethiopia", 11, "AMAHARA", 47, "SOUTH WOLLO", 74, "TENTA"], + [70, "Ethiopia", 11, "AMAHARA", 47, "SOUTH WOLLO", 75, "MEKDELA"], + [70, "Ethiopia", 11, "AMAHARA", 47, "SOUTH WOLLO", 76, "WOGEDIE"], + [70, "Ethiopia", 11, "AMAHARA", 47, "SOUTH WOLLO", 78, "KELALA"], + [70, "Ethiopia", 11, "AMAHARA", 47, "SOUTH WOLLO", 79, "SAINT"], + [70, "Ethiopia", 11, "AMAHARA", 47, "SOUTH WOLLO", 822, "ARGOBA"], + [70, "Ethiopia", 11, "AMAHARA", 47, "SOUTH WOLLO", 823, "BORENA"], + [70, "Ethiopia", 11, "AMAHARA", 47, "SOUTH WOLLO", 824, "LEGEHADI"], + [70, "Ethiopia", 11, "AMAHARA", 47, "SOUTH WOLLO", 825, "MEHAL SAYINT"], + [70, "Ethiopia", 11, "AMAHARA", 47, "SOUTH WOLLO", 1021, "HAIK TOWN ADMINSTRATION"], + [70, "Ethiopia", 11, "AMAHARA", 48, "NORTH GONDER", 84, "GONDER KETMA"], + [70, "Ethiopia", 11, "AMAHARA", 48, "NORTH GONDER", 85, "GONDER ZURIA"], + [70, "Ethiopia", 11, "AMAHARA", 48, "NORTH GONDER", 86, "DEMBIA"], + [70, "Ethiopia", 11, "AMAHARA", 48, "NORTH GONDER", 87, "ALFA TAKUSA"], + [70, "Ethiopia", 11, "AMAHARA", 48, "NORTH GONDER", 88, "METEMA"], + [70, "Ethiopia", 11, "AMAHARA", 48, "NORTH GONDER", 89, "KOLA BELESA"], + [70, "Ethiopia", 11, "AMAHARA", 48, "NORTH GONDER", 90, "DEGA BELESA"], + [70, "Ethiopia", 11, "AMAHARA", 48, "NORTH GONDER", 91, "CHILGA"], + [70, "Ethiopia", 11, "AMAHARA", 48, "NORTH GONDER", 92, "LAI-ARMACHIHO"], + [70, "Ethiopia", 11, "AMAHARA", 48, "NORTH GONDER", 93, "TEGDE"], + [70, "Ethiopia", 11, "AMAHARA", 48, "NORTH GONDER", 94, "ARMACHIHO"], + [70, "Ethiopia", 11, "AMAHARA", 48, "NORTH GONDER", 95, "WEGERA"], + [70, "Ethiopia", 11, "AMAHARA", 48, "NORTH GONDER", 96, "DABAT"], + [70, "Ethiopia", 11, "AMAHARA", 48, "NORTH GONDER", 97, "DEBARK"], + [70, "Ethiopia", 11, "AMAHARA", 48, "NORTH GONDER", 98, "QUARA"], + [70, "Ethiopia", 11, "AMAHARA", 48, "NORTH GONDER", 99, "BEYEDA"], + [70, "Ethiopia", 11, "AMAHARA", 48, "NORTH GONDER", 100, "JANAMORA"], + [70, "Ethiopia", 11, "AMAHARA", 48, "NORTH GONDER", 101, "ADIARKAYI"], + [70, "Ethiopia", 11, "AMAHARA", 48, "NORTH GONDER", 826, "ALEFA"], + [70, "Ethiopia", 11, "AMAHARA", 48, "NORTH GONDER", 827, "DEBARK VICINITY"], + [70, "Ethiopia", 11, "AMAHARA", 48, "NORTH GONDER", 828, "GENDA WEHA"], + [70, "Ethiopia", 11, "AMAHARA", 48, "NORTH GONDER", 829, "TACH ARMACHIHO"], + [70, "Ethiopia", 11, "AMAHARA", 48, "NORTH GONDER", 830, "TAKUSA"], + [70, "Ethiopia", 11, "AMAHARA", 48, "NORTH GONDER", 831, "TELEMET"], + [70, "Ethiopia", 11, "AMAHARA", 48, "NORTH GONDER", 832, "WEST ARMACHIHO"], + [70, "Ethiopia", 11, "AMAHARA", 48, "NORTH GONDER", 905, "EAST BELESA"], + [70, "Ethiopia", 11, "AMAHARA", 48, "NORTH GONDER", 906, "WEST BELESA"], + [70, "Ethiopia", 11, "AMAHARA", 48, "NORTH GONDER", 1019, "METEMA YOHANNES TOWN ADMINISTRATION"], + [70, "Ethiopia", 11, "AMAHARA", 49, "EAST GOJAM", 132, "GOZAMIN"], + [70, "Ethiopia", 11, "AMAHARA", 49, "EAST GOJAM", 133, "D-MARKKOS KETEMA"], + [70, "Ethiopia", 11, "AMAHARA", 49, "EAST GOJAM", 134, "MACHAKEL"], + [70, "Ethiopia", 11, "AMAHARA", 49, "EAST GOJAM", 135, "DEBRE ELIAS"], + [70, "Ethiopia", 11, "AMAHARA", 49, "EAST GOJAM", 136, "BIBUGN"], + [70, "Ethiopia", 11, "AMAHARA", 49, "EAST GOJAM", 137, "AWABEL"], + [70, "Ethiopia", 11, "AMAHARA", 49, "EAST GOJAM", 138, "BASOLIBEN"], + [70, "Ethiopia", 11, "AMAHARA", 49, "EAST GOJAM", 139, "DEJEN"], + [70, "Ethiopia", 11, "AMAHARA", 49, "EAST GOJAM", 140, "EINEMAY"], + [70, "Ethiopia", 11, "AMAHARA", 49, "EAST GOJAM", 141, "DEBAY TILATGEN"], + [70, "Ethiopia", 11, "AMAHARA", 49, "EAST GOJAM", 142, "EINARJ ENAWGA"], + [70, "Ethiopia", 11, "AMAHARA", 49, "EAST GOJAM", 143, "GONCHA-SISO ENESE"], + [70, "Ethiopia", 11, "AMAHARA", 49, "EAST GOJAM", 144, "HULT EIJU EINESIA"], + [70, "Ethiopia", 11, "AMAHARA", 49, "EAST GOJAM", 145, "EINEBSIE SAR MIDER"], + [70, "Ethiopia", 11, "AMAHARA", 49, "EAST GOJAM", 146, "SHEBEL BERENTA"], + [70, "Ethiopia", 11, "AMAHARA", 49, "EAST GOJAM", 833, "ANEDED"], + [70, "Ethiopia", 11, "AMAHARA", 49, "EAST GOJAM", 834, "MOTTA"], + [70, "Ethiopia", 11, "AMAHARA", 49, "EAST GOJAM", 835, "SENAN"], + [70, "Ethiopia", 11, "AMAHARA", 49, "EAST GOJAM", 1029, "DEJEN TOWN ADMINISTRATION"], + [70, "Ethiopia", 11, "AMAHARA", 50, "NORTH SHOA", 77, "DEBRESINA"], + [70, "Ethiopia", 11, "AMAHARA", 50, "NORTH SHOA", 112, "D-BIRHAN KETEMA"], + [70, "Ethiopia", 11, "AMAHARA", 50, "NORTH SHOA", 113, "BASONA WERANA"], + [70, "Ethiopia", 11, "AMAHARA", 50, "NORTH SHOA", 114, "ANGOLALA"], + [70, "Ethiopia", 11, "AMAHARA", 50, "NORTH SHOA", 115, "ASAGRT"], + [70, "Ethiopia", 11, "AMAHARA", 50, "NORTH SHOA", 116, "ANKOBER"], + [70, "Ethiopia", 11, "AMAHARA", 50, "NORTH SHOA", 117, "AGERMARIAM-KETEM"], + [70, "Ethiopia", 11, "AMAHARA", 50, "NORTH SHOA", 118, "BEREHEET"], + [70, "Ethiopia", 11, "AMAHARA", 50, "NORTH SHOA", 119, "EFRATANA GIDME"], + [70, "Ethiopia", 11, "AMAHARA", 50, "NORTH SHOA", 120, "ANTSOKIYANA GEMZ"], + [70, "Ethiopia", 11, "AMAHARA", 50, "NORTH SHOA", 121, "GAIRA-KEYA"], + [70, "Ethiopia", 11, "AMAHARA", 50, "NORTH SHOA", 122, "GESHIE"], + [70, "Ethiopia", 11, "AMAHARA", 50, "NORTH SHOA", 123, "MERAHABETIE"], + [70, "Ethiopia", 11, "AMAHARA", 50, "NORTH SHOA", 124, "KEWET"], + [70, "Ethiopia", 11, "AMAHARA", 50, "NORTH SHOA", 125, "LALO MAMA MEDIR"], + [70, "Ethiopia", 11, "AMAHARA", 50, "NORTH SHOA", 126, "MORETINA -JIRU"], + [70, "Ethiopia", 11, "AMAHARA", 50, "NORTH SHOA", 127, "MINJARINA-SHENKORA"], + [70, "Ethiopia", 11, "AMAHARA", 50, "NORTH SHOA", 128, "MIDANA WOREMO"], + [70, "Ethiopia", 11, "AMAHARA", 50, "NORTH SHOA", 129, "ENSARONA-WAYU"], + [70, "Ethiopia", 11, "AMAHARA", 50, "NORTH SHOA", 130, "TARMA-BER"], + [70, "Ethiopia", 11, "AMAHARA", 50, "NORTH SHOA", 131, "MOJANA WEDERA"], + [70, "Ethiopia", 11, "AMAHARA", 50, "NORTH SHOA", 836, "MENZ GIERA MEDER"], + [70, "Ethiopia", 11, "AMAHARA", 50, "NORTH SHOA", 837, "MENZ LALU MEDER"], + [70, "Ethiopia", 11, "AMAHARA", 50, "NORTH SHOA", 838, "MENZ MAMA MEDER"], + [70, "Ethiopia", 11, "AMAHARA", 50, "NORTH SHOA", 839, "SHOWA ROBIT"], + [70, "Ethiopia", 11, "AMAHARA", 50, "NORTH SHOA", 840, "SIYADBERENA WAYU"], + [70, "Ethiopia", 11, "AMAHARA", 50, "NORTH SHOA", 907, "MENZ KEYA GEBRIEL"], + [70, "Ethiopia", 11, "AMAHARA", 50, "NORTH SHOA", 1016, "MEHALMEDA TOWN ADMINSTRATION"], + [70, "Ethiopia", 11, "AMAHARA", 51, "NORTH WOLLO", 50, "WOLDIA KETEMA"], + [70, "Ethiopia", 11, "AMAHARA", 51, "NORTH WOLLO", 51, "GUBALAFTO"], + [70, "Ethiopia", 11, "AMAHARA", 51, "NORTH WOLLO", 52, "DELANTA DAWINT"], + [70, "Ethiopia", 11, "AMAHARA", 51, "NORTH WOLLO", 53, "KOBO"], + [70, "Ethiopia", 11, "AMAHARA", 51, "NORTH WOLLO", 54, "HABRU"], + [70, "Ethiopia", 11, "AMAHARA", 51, "NORTH WOLLO", 55, "BUGINA"], + [70, "Ethiopia", 11, "AMAHARA", 51, "NORTH WOLLO", 56, "GIDAN"], + [70, "Ethiopia", 11, "AMAHARA", 51, "NORTH WOLLO", 57, "MEKIET"], + [70, "Ethiopia", 11, "AMAHARA", 51, "NORTH WOLLO", 58, "WADELA"], + [70, "Ethiopia", 11, "AMAHARA", 51, "NORTH WOLLO", 841, "DAWUNT"], + [70, "Ethiopia", 11, "AMAHARA", 51, "NORTH WOLLO", 842, "DELANTA"], + [70, "Ethiopia", 11, "AMAHARA", 51, "NORTH WOLLO", 843, "KOBO VICINITY"], + [70, "Ethiopia", 11, "AMAHARA", 51, "NORTH WOLLO", 844, "LALIBELA"], + [70, "Ethiopia", 11, "AMAHARA", 51, "NORTH WOLLO", 845, "LASTA"], + [70, "Ethiopia", 11, "AMAHARA", 51, "NORTH WOLLO", 1020, "MERSA TOWN ADMINISTRATION"], + [70, "Ethiopia", 11, "AMAHARA", 52, "SOUTH GONDER", 102, "DEBRETABOR KETEMA"], + [70, "Ethiopia", 11, "AMAHARA", 52, "SOUTH GONDER", 103, "FARTA"], + [70, "Ethiopia", 11, "AMAHARA", 52, "SOUTH GONDER", 104, "ESTIE"], + [70, "Ethiopia", 11, "AMAHARA", 52, "SOUTH GONDER", 105, "DERRA"], + [70, "Ethiopia", 11, "AMAHARA", 52, "SOUTH GONDER", 106, "LAI-GAINT"], + [70, "Ethiopia", 11, "AMAHARA", 52, "SOUTH GONDER", 107, "TACH-GAINT"], + [70, "Ethiopia", 11, "AMAHARA", 52, "SOUTH GONDER", 108, "SIMADA"], + [70, "Ethiopia", 11, "AMAHARA", 52, "SOUTH GONDER", 109, "FOGERA"], + [70, "Ethiopia", 11, "AMAHARA", 52, "SOUTH GONDER", 110, "LIBOKEMEKEM"], + [70, "Ethiopia", 11, "AMAHARA", 52, "SOUTH GONDER", 111, "EBINAT"], + [70, "Ethiopia", 11, "AMAHARA", 52, "SOUTH GONDER", 846, "EAST ESTIE"], + [70, "Ethiopia", 11, "AMAHARA", 52, "SOUTH GONDER", 847, "WEST ESTIE"], + [70, "Ethiopia", 11, "AMAHARA", 52, "SOUTH GONDER", 848, "WORETA"], + [70, "Ethiopia", 11, "AMAHARA", 52, "SOUTH GONDER", 1023, "ADIS ZEMEN TOWN ADMINISTRATION"], + [70, "Ethiopia", 11, "AMAHARA", 53, "WEST GOJAM", 147, "BAHIRDAR ZURIA"], + [70, "Ethiopia", 11, "AMAHARA", 53, "WEST GOJAM", 148, "YILMANA-DENSA"], + [70, "Ethiopia", 11, "AMAHARA", 53, "WEST GOJAM", 149, "MECHA"], + [70, "Ethiopia", 11, "AMAHARA", 53, "WEST GOJAM", 150, "ACHEFER"], + [70, "Ethiopia", 11, "AMAHARA", 53, "WEST GOJAM", 151, "SEKELA"], + [70, "Ethiopia", 11, "AMAHARA", 53, "WEST GOJAM", 152, "BURIE"], + [70, "Ethiopia", 11, "AMAHARA", 53, "WEST GOJAM", 153, "WONBERMA"], + [70, "Ethiopia", 11, "AMAHARA", 53, "WEST GOJAM", 154, "JABI-TIHNAN"], + [70, "Ethiopia", 11, "AMAHARA", 53, "WEST GOJAM", 155, "QUARIT"], + [70, "Ethiopia", 11, "AMAHARA", 53, "WEST GOJAM", 156, "DENBECHA"], + [70, "Ethiopia", 11, "AMAHARA", 53, "WEST GOJAM", 157, "DEGADAMOT"], + [70, "Ethiopia", 11, "AMAHARA", 53, "WEST GOJAM", 849, "BAHIRDAR TOWN ADMINIS."], + [70, "Ethiopia", 11, "AMAHARA", 53, "WEST GOJAM", 850, "BURIE VICINITY"], + [70, "Ethiopia", 11, "AMAHARA", 53, "WEST GOJAM", 851, "FENOTE SELAM"], + [70, "Ethiopia", 11, "AMAHARA", 53, "WEST GOJAM", 852, "GONJI KOLELA"], + [70, "Ethiopia", 11, "AMAHARA", 53, "WEST GOJAM", 853, "NORTH ACHEFER"], + [70, "Ethiopia", 11, "AMAHARA", 53, "WEST GOJAM", 854, "SOUTH ACHEFER"], + [70, "Ethiopia", 11, "AMAHARA", 53, "WEST GOJAM", 1025, "DEMBECHA TOWN ADMINSTRATION"], + [70, "Ethiopia", 11, "AMAHARA", 54, "OROMIA", 80, "JILIENA TIMUGA"], + [70, "Ethiopia", 11, "AMAHARA", 54, "OROMIA", 81, "ARTUMA FARSI"], + [70, "Ethiopia", 11, "AMAHARA", 54, "OROMIA", 82, "DAWA-CHEFA"], + [70, "Ethiopia", 11, "AMAHARA", 54, "OROMIA", 83, "BATI"], + [70, "Ethiopia", 11, "AMAHARA", 54, "OROMIA", 855, "DEWIHAREWA"], + [70, "Ethiopia", 11, "AMAHARA", 54, "OROMIA", 856, "KEMISIE TOWN ADMINISTRATION"], + [70, "Ethiopia", 11, "AMAHARA", 54, "OROMIA", 1031, "BATI TOWN ADMINISTRATION"], + [70, "Ethiopia", 11, "AMAHARA", 55, "WAGHIMRA", 59, "SEKOTA"], + [70, "Ethiopia", 11, "AMAHARA", 55, "WAGHIMRA", 60, "DEHANA"], + [70, "Ethiopia", 11, "AMAHARA", 55, "WAGHIMRA", 61, "ZIQUALA"], + [70, "Ethiopia", 11, "AMAHARA", 55, "WAGHIMRA", 857, "ABERGELIE"], + [70, "Ethiopia", 11, "AMAHARA", 55, "WAGHIMRA", 858, "GAZIBELA"], + [70, "Ethiopia", 11, "AMAHARA", 55, "WAGHIMRA", 859, "SEHALA"], + [70, "Ethiopia", 11, "AMAHARA", 55, "WAGHIMRA", 860, "SEKOTA VICINITY"], + [70, "Ethiopia", 11, "AMAHARA", 66, "AWI", 158, "BANJA-SHIKUDAD"], + [70, "Ethiopia", 11, "AMAHARA", 66, "AWI", 159, "GUANGUA"], + [70, "Ethiopia", 11, "AMAHARA", 66, "AWI", 160, "DANGILA"], + [70, "Ethiopia", 11, "AMAHARA", 66, "AWI", 161, "ANKESHA-GUAGUSA"], + [70, "Ethiopia", 11, "AMAHARA", 66, "AWI", 162, "FAGTA LEKOMA"], + [70, "Ethiopia", 11, "AMAHARA", 66, "AWI", 867, "ANKESHA "], + [70, "Ethiopia", 11, "AMAHARA", 66, "AWI", 868, "CHAGNI"], + [70, "Ethiopia", 11, "AMAHARA", 66, "AWI", 869, "DANGELA VICINITY"], + [70, "Ethiopia", 11, "AMAHARA", 66, "AWI", 870, "ENJEBARA TOWN ADMIN"], + [70, "Ethiopia", 11, "AMAHARA", 66, "AWI", 871, "GUAGUSA"], + [70, "Ethiopia", 11, "AMAHARA", 66, "AWI", 872, "JAWI"], + [70, "Ethiopia", 11, "AMAHARA", 66, "AWI", 1032, "ZIGEM"], + [70, "Ethiopia", 12, "NO REGION", 76, "NO ZONE REGION", 653, "NO WOREDA REGION"], + [70, "Ethiopia", 13, "ADDIS ABABA", 14, "ARADA", 568, "NO WOREDA-139"], + [70, "Ethiopia", 13, "ADDIS ABABA", 14, "ARADA", 1056, "WOREDA 1"], + [70, "Ethiopia", 13, "ADDIS ABABA", 14, "ARADA", 1057, "WOREDA 2"], + [70, "Ethiopia", 13, "ADDIS ABABA", 14, "ARADA", 1058, "WOREDA 3"], + [70, "Ethiopia", 13, "ADDIS ABABA", 14, "ARADA", 1059, "WOREDA 4"], + [70, "Ethiopia", 13, "ADDIS ABABA", 14, "ARADA", 1060, "WOREDA 5"], + [70, "Ethiopia", 13, "ADDIS ABABA", 14, "ARADA", 1061, "WOREDA 6"], + [70, "Ethiopia", 13, "ADDIS ABABA", 14, "ARADA", 1062, "WOREDA 7"], + [70, "Ethiopia", 13, "ADDIS ABABA", 14, "ARADA", 1063, "WOREDA 9"], + [70, "Ethiopia", 13, "ADDIS ABABA", 14, "ARADA", 1064, "WOREDA 8"], + [70, "Ethiopia", 13, "ADDIS ABABA", 14, "ARADA", 1065, "WOREDA 10"], + [70, "Ethiopia", 13, "ADDIS ABABA", 15, "ADDIS KETEMA", 569, "NO WOREDA-140"], + [70, "Ethiopia", 13, "ADDIS ABABA", 15, "ADDIS KETEMA", 1042, "WOREDA 2"], + [70, "Ethiopia", 13, "ADDIS ABABA", 15, "ADDIS KETEMA", 1048, "WOREDA 3"], + [70, "Ethiopia", 13, "ADDIS ABABA", 15, "ADDIS KETEMA", 1049, "WOREDA 4"], + [70, "Ethiopia", 13, "ADDIS ABABA", 15, "ADDIS KETEMA", 1050, "WOREDA 5"], + [70, "Ethiopia", 13, "ADDIS ABABA", 15, "ADDIS KETEMA", 1051, "WOREDA 6"], + [70, "Ethiopia", 13, "ADDIS ABABA", 15, "ADDIS KETEMA", 1052, "WOREDA 7"], + [70, "Ethiopia", 13, "ADDIS ABABA", 15, "ADDIS KETEMA", 1053, "WOREDA 9"], + [70, "Ethiopia", 13, "ADDIS ABABA", 15, "ADDIS KETEMA", 1054, "WOREDA 10"], + [70, "Ethiopia", 13, "ADDIS ABABA", 15, "ADDIS KETEMA", 1055, "WOREDA 8"], + [70, "Ethiopia", 13, "ADDIS ABABA", 29, "LIDETA", 571, "NO WOREDA-141"], + [70, "Ethiopia", 13, "ADDIS ABABA", 29, "LIDETA", 1066, "WOREDA 1"], + [70, "Ethiopia", 13, "ADDIS ABABA", 29, "LIDETA", 1067, "WOREDA 2"], + [70, "Ethiopia", 13, "ADDIS ABABA", 29, "LIDETA", 1068, "WOREDA 3"], + [70, "Ethiopia", 13, "ADDIS ABABA", 29, "LIDETA", 1069, "WOREDA 4"], + [70, "Ethiopia", 13, "ADDIS ABABA", 29, "LIDETA", 1070, "WOREDA 5"], + [70, "Ethiopia", 13, "ADDIS ABABA", 29, "LIDETA", 1071, "WOREDA 6"], + [70, "Ethiopia", 13, "ADDIS ABABA", 29, "LIDETA", 1072, "WOREDA 7"], + [70, "Ethiopia", 13, "ADDIS ABABA", 29, "LIDETA", 1073, "WOREDA 9"], + [70, "Ethiopia", 13, "ADDIS ABABA", 29, "LIDETA", 1074, "WOREDA 8"], + [70, "Ethiopia", 13, "ADDIS ABABA", 29, "LIDETA", 1075, "WOREDA 10"], + [70, "Ethiopia", 13, "ADDIS ABABA", 63, "KIRKOS", 572, "NO WOREDA-142"], + [70, "Ethiopia", 13, "ADDIS ABABA", 63, "KIRKOS", 1076, "WOREDA 1"], + [70, "Ethiopia", 13, "ADDIS ABABA", 63, "KIRKOS", 1077, "WOREDA 2"], + [70, "Ethiopia", 13, "ADDIS ABABA", 63, "KIRKOS", 1078, "WOREDA 3"], + [70, "Ethiopia", 13, "ADDIS ABABA", 63, "KIRKOS", 1079, "WOREDA 4"], + [70, "Ethiopia", 13, "ADDIS ABABA", 63, "KIRKOS", 1080, "WOREDA 5"], + [70, "Ethiopia", 13, "ADDIS ABABA", 63, "KIRKOS", 1081, "WOREDA 6"], + [70, "Ethiopia", 13, "ADDIS ABABA", 63, "KIRKOS", 1082, "WOREDA 7"], + [70, "Ethiopia", 13, "ADDIS ABABA", 63, "KIRKOS", 1083, "WOREDA 9"], + [70, "Ethiopia", 13, "ADDIS ABABA", 63, "KIRKOS", 1084, "WOREDA 8"], + [70, "Ethiopia", 13, "ADDIS ABABA", 63, "KIRKOS", 1085, "WOREDA 10"], + [70, "Ethiopia", 13, "ADDIS ABABA", 63, "KIRKOS", 1086, "WOREDA 11"], + [70, "Ethiopia", 13, "ADDIS ABABA", 77, "YEKA", 573, "NO WOREDA-143"], + [70, "Ethiopia", 13, "ADDIS ABABA", 77, "YEKA", 1087, "WOREDA 1"], + [70, "Ethiopia", 13, "ADDIS ABABA", 77, "YEKA", 1088, "WOREDA 2"], + [70, "Ethiopia", 13, "ADDIS ABABA", 77, "YEKA", 1089, "WOREDA 3"], + [70, "Ethiopia", 13, "ADDIS ABABA", 77, "YEKA", 1090, "WOREDA 4"], + [70, "Ethiopia", 13, "ADDIS ABABA", 77, "YEKA", 1091, "WOREDA 5"], + [70, "Ethiopia", 13, "ADDIS ABABA", 77, "YEKA", 1092, "WOREDA 6"], + [70, "Ethiopia", 13, "ADDIS ABABA", 77, "YEKA", 1093, "WOREDA 7"], + [70, "Ethiopia", 13, "ADDIS ABABA", 77, "YEKA", 1094, "WOREDA 9"], + [70, "Ethiopia", 13, "ADDIS ABABA", 77, "YEKA", 1095, "WOREDA 8"], + [70, "Ethiopia", 13, "ADDIS ABABA", 77, "YEKA", 1096, "WOREDA 10"], + [70, "Ethiopia", 13, "ADDIS ABABA", 77, "YEKA", 1097, "WOREDA 11"], + [70, "Ethiopia", 13, "ADDIS ABABA", 77, "YEKA", 1098, "WOREDA 12"], + [70, "Ethiopia", 13, "ADDIS ABABA", 77, "YEKA", 1099, "WOREDA 13"], + [70, "Ethiopia", 13, "ADDIS ABABA", 78, "BOLE", 574, "NO WOREDA-144"], + [70, "Ethiopia", 13, "ADDIS ABABA", 78, "BOLE", 1100, "WOREDA 1"], + [70, "Ethiopia", 13, "ADDIS ABABA", 78, "BOLE", 1101, "WOREDA 2"], + [70, "Ethiopia", 13, "ADDIS ABABA", 78, "BOLE", 1102, "WOREDA 3"], + [70, "Ethiopia", 13, "ADDIS ABABA", 78, "BOLE", 1103, "WOREDA 4"], + [70, "Ethiopia", 13, "ADDIS ABABA", 78, "BOLE", 1104, "WOREDA 5"], + [70, "Ethiopia", 13, "ADDIS ABABA", 78, "BOLE", 1105, "WOREDA 6"], + [70, "Ethiopia", 13, "ADDIS ABABA", 78, "BOLE", 1106, "WOREDA 7"], + [70, "Ethiopia", 13, "ADDIS ABABA", 78, "BOLE", 1107, "WOREDA 9"], + [70, "Ethiopia", 13, "ADDIS ABABA", 78, "BOLE", 1108, "WOREDA 8"], + [70, "Ethiopia", 13, "ADDIS ABABA", 78, "BOLE", 1109, "WOREDA 10"], + [70, "Ethiopia", 13, "ADDIS ABABA", 78, "BOLE", 1110, "WOREDA 11"], + [70, "Ethiopia", 13, "ADDIS ABABA", 78, "BOLE", 1111, "WOREDA 12"], + [70, "Ethiopia", 13, "ADDIS ABABA", 78, "BOLE", 1112, "WOREDA 13"], + [70, "Ethiopia", 13, "ADDIS ABABA", 78, "BOLE", 1113, "WOREDA 14"], + [70, "Ethiopia", 13, "ADDIS ABABA", 79, "AKAKI KALITI", 575, "NO WOREDA-145"], + [70, "Ethiopia", 13, "ADDIS ABABA", 79, "AKAKI KALITI", 1114, "WOREDA 1"], + [70, "Ethiopia", 13, "ADDIS ABABA", 79, "AKAKI KALITI", 1115, "WOREDA 2"], + [70, "Ethiopia", 13, "ADDIS ABABA", 79, "AKAKI KALITI", 1116, "WOREDA 3"], + [70, "Ethiopia", 13, "ADDIS ABABA", 79, "AKAKI KALITI", 1117, "WOREDA 4"], + [70, "Ethiopia", 13, "ADDIS ABABA", 79, "AKAKI KALITI", 1118, "WOREDA 5"], + [70, "Ethiopia", 13, "ADDIS ABABA", 79, "AKAKI KALITI", 1119, "WOREDA 6"], + [70, "Ethiopia", 13, "ADDIS ABABA", 79, "AKAKI KALITI", 1120, "WOREDA 7"], + [70, "Ethiopia", 13, "ADDIS ABABA", 79, "AKAKI KALITI", 1121, "WOREDA 8"], + [70, "Ethiopia", 13, "ADDIS ABABA", 80, "NEFAS SILK LAFTO", 576, "NO WOREDA-146"], + [70, "Ethiopia", 13, "ADDIS ABABA", 80, "NEFAS SILK LAFTO", 1046, "WOREDA 1"], + [70, "Ethiopia", 13, "ADDIS ABABA", 80, "NEFAS SILK LAFTO", 1122, "WOREDA 2"], + [70, "Ethiopia", 13, "ADDIS ABABA", 80, "NEFAS SILK LAFTO", 1123, "WOREDA 3"], + [70, "Ethiopia", 13, "ADDIS ABABA", 80, "NEFAS SILK LAFTO", 1124, "WOREDA 4"], + [70, "Ethiopia", 13, "ADDIS ABABA", 80, "NEFAS SILK LAFTO", 1125, "WOREDA 5"], + [70, "Ethiopia", 13, "ADDIS ABABA", 80, "NEFAS SILK LAFTO", 1126, "WOREDA 6"], + [70, "Ethiopia", 13, "ADDIS ABABA", 80, "NEFAS SILK LAFTO", 1127, "WOREDA 7"], + [70, "Ethiopia", 13, "ADDIS ABABA", 80, "NEFAS SILK LAFTO", 1128, "WOREDA 9"], + [70, "Ethiopia", 13, "ADDIS ABABA", 80, "NEFAS SILK LAFTO", 1129, "WOREDA 8"], + [70, "Ethiopia", 13, "ADDIS ABABA", 80, "NEFAS SILK LAFTO", 1130, "WOREDA 10"], + [70, "Ethiopia", 13, "ADDIS ABABA", 80, "NEFAS SILK LAFTO", 1131, "WOREDA 11"], + [70, "Ethiopia", 13, "ADDIS ABABA", 80, "NEFAS SILK LAFTO", 1132, "WOREDA 12"], + [70, "Ethiopia", 13, "ADDIS ABABA", 81, "KOLFIE KERANIYO", 577, "NO WOREDA-147"], + [70, "Ethiopia", 13, "ADDIS ABABA", 81, "KOLFIE KERANIYO", 1133, "WOREDA 1"], + [70, "Ethiopia", 13, "ADDIS ABABA", 81, "KOLFIE KERANIYO", 1134, "WOREDA 2"], + [70, "Ethiopia", 13, "ADDIS ABABA", 81, "KOLFIE KERANIYO", 1135, "WOREDA 3"], + [70, "Ethiopia", 13, "ADDIS ABABA", 81, "KOLFIE KERANIYO", 1136, "WOREDA 4"], + [70, "Ethiopia", 13, "ADDIS ABABA", 81, "KOLFIE KERANIYO", 1137, "WOREDA 5"], + [70, "Ethiopia", 13, "ADDIS ABABA", 81, "KOLFIE KERANIYO", 1138, "WOREDA 6"], + [70, "Ethiopia", 13, "ADDIS ABABA", 81, "KOLFIE KERANIYO", 1139, "WOREDA 7"], + [70, "Ethiopia", 13, "ADDIS ABABA", 81, "KOLFIE KERANIYO", 1140, "WOREDA 9"], + [70, "Ethiopia", 13, "ADDIS ABABA", 81, "KOLFIE KERANIYO", 1141, "WOREDA 8"], + [70, "Ethiopia", 13, "ADDIS ABABA", 81, "KOLFIE KERANIYO", 1142, "WOREDA 10"], + [70, "Ethiopia", 13, "ADDIS ABABA", 81, "KOLFIE KERANIYO", 1143, "WOREDA 11"], + [70, "Ethiopia", 13, "ADDIS ABABA", 81, "KOLFIE KERANIYO", 1144, "WOREDA 12"], + [70, "Ethiopia", 13, "ADDIS ABABA", 81, "KOLFIE KERANIYO", 1145, "WOREDA 13"], + [70, "Ethiopia", 13, "ADDIS ABABA", 81, "KOLFIE KERANIYO", 1146, "WOREDA 14"], + [70, "Ethiopia", 13, "ADDIS ABABA", 81, "KOLFIE KERANIYO", 1147, "WOREDA 15"], + [70, "Ethiopia", 13, "ADDIS ABABA", 82, "GULLELE", 578, "NO WOREDA-148"], + [70, "Ethiopia", 13, "ADDIS ABABA", 82, "GULLELE", 1148, "WOREDA 1"], + [70, "Ethiopia", 13, "ADDIS ABABA", 82, "GULLELE", 1149, "WOREDA 2"], + [70, "Ethiopia", 13, "ADDIS ABABA", 82, "GULLELE", 1150, "WOREDA 3"], + [70, "Ethiopia", 13, "ADDIS ABABA", 82, "GULLELE", 1151, "WOREDA 4"], + [70, "Ethiopia", 13, "ADDIS ABABA", 82, "GULLELE", 1152, "WOREDA 5"], + [70, "Ethiopia", 13, "ADDIS ABABA", 82, "GULLELE", 1153, "WOREDA 6"], + [70, "Ethiopia", 13, "ADDIS ABABA", 82, "GULLELE", 1154, "WOREDA 7"], + [70, "Ethiopia", 13, "ADDIS ABABA", 82, "GULLELE", 1155, "WOREDA 9"], + [70, "Ethiopia", 13, "ADDIS ABABA", 82, "GULLELE", 1156, "WOREDA 8"], + [70, "Ethiopia", 13, "ADDIS ABABA", 82, "GULLELE", 1157, "WOREDA 10"], + [70, "Ethiopia", 14, "SIDAMA", 17, "SIDAMA", 11, "AWASSA VICINITY"], + [70, "Ethiopia", 14, "SIDAMA", 17, "SIDAMA", 239, "SHEBEDINO"], + [70, "Ethiopia", 14, "SIDAMA", 17, "SIDAMA", 240, "DALE"], + [70, "Ethiopia", 14, "SIDAMA", 17, "SIDAMA", 241, "ALETA WONDO"], + [70, "Ethiopia", 14, "SIDAMA", 17, "SIDAMA", 242, "AGERESELAM"], + [70, "Ethiopia", 14, "SIDAMA", 17, "SIDAMA", 243, "BENSSA"], + [70, "Ethiopia", 14, "SIDAMA", 17, "SIDAMA", 244, "ARBEGONA"], + [70, "Ethiopia", 14, "SIDAMA", 17, "SIDAMA", 245, "ARORESSA"], + [70, "Ethiopia", 14, "SIDAMA", 17, "SIDAMA", 246, "DARRA"], + [70, "Ethiopia", 14, "SIDAMA", 17, "SIDAMA", 563, "HAWASSA CITY ADMINISTRATION"], + [70, "Ethiopia", 14, "SIDAMA", 17, "SIDAMA", 564, "ALETAWONDO TOWN ADMIN"], + [70, "Ethiopia", 14, "SIDAMA", 17, "SIDAMA", 565, "YIRGALEM TOWN ADMIN"], + [70, "Ethiopia", 14, "SIDAMA", 17, "SIDAMA", 730, "WENDO GENET"], + [70, "Ethiopia", 14, "SIDAMA", 17, "SIDAMA", 731, "MELGA"], + [70, "Ethiopia", 14, "SIDAMA", 17, "SIDAMA", 732, "GORCHE"], + [70, "Ethiopia", 14, "SIDAMA", 17, "SIDAMA", 733, "WENSHO"], + [70, "Ethiopia", 14, "SIDAMA", 17, "SIDAMA", 734, "LOKA ABAYA"], + [70, "Ethiopia", 14, "SIDAMA", 17, "SIDAMA", 735, "CHUKO"], + [70, "Ethiopia", 14, "SIDAMA", 17, "SIDAMA", 736, "BONA ZURIA"], + [70, "Ethiopia", 14, "SIDAMA", 17, "SIDAMA", 737, "BURSA"], + [70, "Ethiopia", 14, "SIDAMA", 17, "SIDAMA", 738, "CHIRE"], + [70, "Ethiopia", 14, "SIDAMA", 17, "SIDAMA", 786, "ALETA CHUKO"], + [70, "Ethiopia", 14, "SIDAMA", 17, "SIDAMA", 787, "BUNA VICINITY"], + [70, "Ethiopia", 14, "SIDAMA", 17, "SIDAMA", 788, "GORECHIE"], + [70, "Ethiopia", 14, "SIDAMA", 17, "SIDAMA", 789, "WENISHO"], + [70, "Ethiopia", 14, "SIDAMA", 17, "SIDAMA", 1039, "LEKU TOWN"], + [70, "Ethiopia", 14, "SIDAMA", 17, "SIDAMA", 1258, "WONDO GENET TOWN ADMINSTRATION"], + [70, "Ethiopia", 14, "SIDAMA", 17, "SIDAMA", 1259, "ALETA CHUKO TOWN ADMINSTRATION"], + [70, "Ethiopia", 14, "SIDAMA", 17, "SIDAMA", 1260, "HOKO WOREDA"], + [70, "Ethiopia", 14, "SIDAMA", 17, "SIDAMA", 1261, "HAWELA WOREDA"], + [70, "Ethiopia", 14, "SIDAMA", 17, "SIDAMA", 1262, "DA'ELA WOREDA"], + [70, "Ethiopia", 14, "SIDAMA", 17, "SIDAMA", 1263, "DARARA WOREDA"], + [70, "Ethiopia", 14, "SIDAMA", 17, "SIDAMA", 1264, "TETICHA WOREDA"], + [70, "Ethiopia", 14, "SIDAMA", 17, "SIDAMA", 1265, "CHIRONE WOREDA"], + [70, "Ethiopia", 14, "SIDAMA", 17, "SIDAMA", 1266, "BILATE ZURIA WOREDA"], + [70, "Ethiopia", 14, "SIDAMA", 17, "SIDAMA", 1267, "CHEBE WOREDA"], + [70, "Ethiopia", 14, "SIDAMA", 17, "SIDAMA", 1268, "BURA WOREDA"], + [70, "Ethiopia", 14, "SIDAMA", 17, "SIDAMA", 1269, "SHAFAMO WOREDA"], + [70, "Ethiopia", 14, "SIDAMA", 17, "SIDAMA", 1270, "DARA OTILICHO WOREDA"], + [70, "Ethiopia", 15, "SOUTH WEST", 24, "DAWRO", 295, "MAREQA"], + [70, "Ethiopia", 15, "SOUTH WEST", 24, "DAWRO", 296, "LOMA"], + [70, "Ethiopia", 15, "SOUTH WEST", 24, "DAWRO", 297, "TOCHA"], + [70, "Ethiopia", 15, "SOUTH WEST", 24, "DAWRO", 298, "ZABA GAZO WOREDA"], + [70, "Ethiopia", 15, "SOUTH WEST", 24, "DAWRO", 299, "ESERA"], + [70, "Ethiopia", 15, "SOUTH WEST", 24, "DAWRO", 713, "TERCHA CITY ADMINISTRATION"], + [70, "Ethiopia", 15, "SOUTH WEST", 24, "DAWRO", 1205, "GENA WOREDA"], + [70, "Ethiopia", 15, "SOUTH WEST", 24, "DAWRO", 1211, "DISA WOREDA"], + [70, "Ethiopia", 15, "SOUTH WEST", 24, "DAWRO", 1212, "TARCHA ZURIA WOREDA"], + [70, "Ethiopia", 15, "SOUTH WEST", 24, "DAWRO", 1213, "MARI MANSA WOREDA"], + [70, "Ethiopia", 15, "SOUTH WEST", 24, "DAWRO", 1214, "KECHI WOREDA"], + [70, "Ethiopia", 15, "SOUTH WEST", 26, "KEFFA", 306, "GIMBO"], + [70, "Ethiopia", 15, "SOUTH WEST", 26, "KEFFA", 307, "DECHA"], + [70, "Ethiopia", 15, "SOUTH WEST", 26, "KEFFA", 308, "CHENA"], + [70, "Ethiopia", 15, "SOUTH WEST", 26, "KEFFA", 309, "BITA"], + [70, "Ethiopia", 15, "SOUTH WEST", 26, "KEFFA", 310, "TELLO"], + [70, "Ethiopia", 15, "SOUTH WEST", 26, "KEFFA", 311, "MENGEO"], + [70, "Ethiopia", 15, "SOUTH WEST", 26, "KEFFA", 312, "GESHA"], + [70, "Ethiopia", 15, "SOUTH WEST", 26, "KEFFA", 313, "CHETA"], + [70, "Ethiopia", 15, "SOUTH WEST", 26, "KEFFA", 314, "SAYILEM"], + [70, "Ethiopia", 15, "SOUTH WEST", 26, "KEFFA", 315, "GEWATA"], + [70, "Ethiopia", 15, "SOUTH WEST", 26, "KEFFA", 588, "BONGA CITY ADMINISTRATION"], + [70, "Ethiopia", 15, "SOUTH WEST", 26, "KEFFA", 807, "ADIYUO"], + [70, "Ethiopia", 15, "SOUTH WEST", 26, "KEFFA", 1255, "WACHA TOWN ADMINSTRATION"], + [70, "Ethiopia", 15, "SOUTH WEST", 26, "KEFFA", 1256, "GOBA WOREDA"], + [70, "Ethiopia", 15, "SOUTH WEST", 26, "KEFFA", 1257, "SHISHO ENDO WOREDA"], + [70, "Ethiopia", 15, "SOUTH WEST", 26, "KEFFA", 1283, "SHISHO ENDO CITY ADMINSTRATION "], + [70, "Ethiopia", 15, "SOUTH WEST", 26, "KEFFA", 1284, "DAKA CITY ADMINSTRATION "], + [70, "Ethiopia", 15, "SOUTH WEST", 26, "KEFFA", 1285, "AWRADA CITY ADMINSTRATION "], + [70, "Ethiopia", 15, "SOUTH WEST", 46, "BENCH SHEKO ZONE", 316, "BENCH"], + [70, "Ethiopia", 15, "SOUTH WEST", 46, "BENCH SHEKO ZONE", 317, "SHEKO WOREDA"], + [70, "Ethiopia", 15, "SOUTH WEST", 46, "BENCH SHEKO ZONE", 319, "GURA FERDA WOREDA"], + [70, "Ethiopia", 15, "SOUTH WEST", 46, "BENCH SHEKO ZONE", 321, "SHEWA BENCH"], + [70, "Ethiopia", 15, "SOUTH WEST", 46, "BENCH SHEKO ZONE", 589, "MIZANTEFERI CITY ADMINISTRATION"], + [70, "Ethiopia", 15, "SOUTH WEST", 46, "BENCH SHEKO ZONE", 711, "SEMEN BENCH WOREDA"], + [70, "Ethiopia", 15, "SOUTH WEST", 46, "BENCH SHEKO ZONE", 712, "DEBUB BENCH WOREDA"], + [70, "Ethiopia", 15, "SOUTH WEST", 46, "BENCH SHEKO ZONE", 820, "NORTH BENCH"], + [70, "Ethiopia", 15, "SOUTH WEST", 46, "BENCH SHEKO ZONE", 821, "SOUTH BENCH"], + [70, "Ethiopia", 15, "SOUTH WEST", 46, "BENCH SHEKO ZONE", 1209, "GIDI BENCH WOREDA"], + [70, "Ethiopia", 15, "SOUTH WEST", 67, "SHEKA", 325, "MASHA"], + [70, "Ethiopia", 15, "SOUTH WEST", 67, "SHEKA", 326, "YEKI"], + [70, "Ethiopia", 15, "SOUTH WEST", 67, "SHEKA", 327, "ANDERACHA"], + [70, "Ethiopia", 15, "SOUTH WEST", 67, "SHEKA", 590, "TEPPI CITY ADMINISTRATION"], + [70, "Ethiopia", 15, "SOUTH WEST", 67, "SHEKA", 729, "MASHA CITY ADMINISTRATION"], + [70, "Ethiopia", 15, "SOUTH WEST", 67, "SHEKA", 873, "MASHA TOWN ADM"], + [70, "Ethiopia", 15, "SOUTH WEST", 102, "MIRAB OMO ZONE", 318, "MENIT GOLDIA WOREDA"], + [70, "Ethiopia", 15, "SOUTH WEST", 102, "MIRAB OMO ZONE", 320, "SURMA WOREDA"], + [70, "Ethiopia", 15, "SOUTH WEST", 102, "MIRAB OMO ZONE", 322, "MENIT SHASHA WOREDA"], + [70, "Ethiopia", 15, "SOUTH WEST", 102, "MIRAB OMO ZONE", 323, "BERO WOREDA"], + [70, "Ethiopia", 15, "SOUTH WEST", 102, "MIRAB OMO ZONE", 324, "MAJI WOREDA"], + [70, "Ethiopia", 15, "SOUTH WEST", 102, "MIRAB OMO ZONE", 1280, "BACHUMA CITY ADMINSTRATION "], + [70, "Ethiopia", 15, "SOUTH WEST", 102, "MIRAB OMO ZONE", 1281, "JEMU CITY ADMINSTRATION "], + [70, "Ethiopia", 15, "SOUTH WEST", 102, "MIRAB OMO ZONE", 1282, "MAJI TUM CITY ADMINSTRATION "], + [70, "Ethiopia", 17, "CENTERAL ETHIOPIA", 23, "GURAGE", 283, "GORO"], + [70, "Ethiopia", 17, "CENTERAL ETHIOPIA", 23, "GURAGE", 284, "CHEHA"], + [70, "Ethiopia", 17, "CENTERAL ETHIOPIA", 23, "GURAGE", 285, "ENEMOR"], + [70, "Ethiopia", 17, "CENTERAL ETHIOPIA", 23, "GURAGE", 286, "EZA"], + [70, "Ethiopia", 17, "CENTERAL ETHIOPIA", 23, "GURAGE", 287, "GUMER"], + [70, "Ethiopia", 17, "CENTERAL ETHIOPIA", 23, "GURAGE", 288, "KOKIR"], + [70, "Ethiopia", 17, "CENTERAL ETHIOPIA", 23, "GURAGE", 289, "MESKAN"], + [70, "Ethiopia", 17, "CENTERAL ETHIOPIA", 23, "GURAGE", 290, "ABASHEGE"], + [70, "Ethiopia", 17, "CENTERAL ETHIOPIA", 23, "GURAGE", 291, "MAREKO"], + [70, "Ethiopia", 17, "CENTERAL ETHIOPIA", 23, "GURAGE", 292, "SODO"], + [70, "Ethiopia", 17, "CENTERAL ETHIOPIA", 23, "GURAGE", 293, "MIHUR AKLIL"], + [70, "Ethiopia", 17, "CENTERAL ETHIOPIA", 23, "GURAGE", 294, "ENDEGAN"], + [70, "Ethiopia", 17, "CENTERAL ETHIOPIA", 23, "GURAGE", 583, "WOLKITE CITY ADMINISTRATION"], + [70, "Ethiopia", 17, "CENTERAL ETHIOPIA", 23, "GURAGE", 584, "BUTAJERA CITY ADMINISTRATION"], + [70, "Ethiopia", 17, "CENTERAL ETHIOPIA", 23, "GURAGE", 625, "KEBENA"], + [70, "Ethiopia", 17, "CENTERAL ETHIOPIA", 23, "GURAGE", 723, "GETA"], + [70, "Ethiopia", 17, "CENTERAL ETHIOPIA", 23, "GURAGE", 801, "GETO"], + [70, "Ethiopia", 17, "CENTERAL ETHIOPIA", 23, "GURAGE", 1215, "ENDIBIR TOWN ADMINSTRATION"], + [70, "Ethiopia", 17, "CENTERAL ETHIOPIA", 23, "GURAGE", 1216, "BUIE TOWN ADMINSTRATION"], + [70, "Ethiopia", 17, "CENTERAL ETHIOPIA", 23, "GURAGE", 1217, "DEBUB SODO WOREDA"], + [70, "Ethiopia", 17, "CENTERAL ETHIOPIA", 23, "GURAGE", 1272, "ENSENO TOWN ADMINSTRATION"], +]; diff --git a/apps/edr-freight-api/src/modules/billing/eims-invoice.mapper.spec.ts b/apps/edr-freight-api/src/modules/billing/eims-invoice.mapper.spec.ts index a3103ca1c..bcc7fcfc3 100644 --- a/apps/edr-freight-api/src/modules/billing/eims-invoice.mapper.spec.ts +++ b/apps/edr-freight-api/src/modules/billing/eims-invoice.mapper.spec.ts @@ -86,17 +86,16 @@ describe("toEimsInvoice", () => { expect(doc.SellerDetails).toBe(seller); }); - it("maps the buyer from the company row and leaves unmodelled fields null", () => { + it("maps the buyer from the company row and omits Id fields for a TIN-identified buyer", () => { const doc = toEimsInvoice(invoice(), seller, context()); + // MoR rule 7004 rejects an explicit IdType/IdNumber null — the keys must be absent. expect(doc.BuyerDetails).toEqual({ // Resolved by the registration service before the counter was reserved; the mapper copies. City: "31", Country: "70", Email: "buyer@abc.et", HouseNumber: "NEW", - IdNumber: null, - IdType: null, Tin: "0999930000", LegalName: "ABC Trading PLC", Phone: "0912345678", diff --git a/apps/edr-freight-api/src/modules/billing/eims-invoice.mapper.ts b/apps/edr-freight-api/src/modules/billing/eims-invoice.mapper.ts index c1ae4c514..0b9eb9e29 100644 --- a/apps/edr-freight-api/src/modules/billing/eims-invoice.mapper.ts +++ b/apps/edr-freight-api/src/modules/billing/eims-invoice.mapper.ts @@ -35,8 +35,9 @@ export interface EimsBuyerDetails { City: string | null; Email: string | null; HouseNumber: string | null; - IdNumber: string | null; - IdType: string | null; + /** Omitted entirely for a TIN-identified buyer — MoR rule 7004 rejects an explicit null. */ + IdNumber?: string; + IdType?: string; Tin: string; LegalName: string; Phone: string | null; @@ -410,8 +411,8 @@ export function toEimsInvoice( City: context.buyerGeo.City, Email: company.email ?? null, HouseNumber: company.houseNo ?? null, - IdNumber: context.buyerIdNumber ?? null, - IdType: context.buyerIdType ?? null, + ...(context.buyerIdNumber != null ? { IdNumber: context.buyerIdNumber } : {}), + ...(context.buyerIdType != null ? { IdType: context.buyerIdType } : {}), Tin: company.tin, LegalName: company.name, Phone: company.phone ?? null, diff --git a/apps/edr-freight-api/src/modules/bookings/booking-pricing.service.ts b/apps/edr-freight-api/src/modules/bookings/booking-pricing.service.ts index 49732d2df..29104bbce 100644 --- a/apps/edr-freight-api/src/modules/bookings/booking-pricing.service.ts +++ b/apps/edr-freight-api/src/modules/bookings/booking-pricing.service.ts @@ -26,9 +26,18 @@ import { Booking } from './entities/booking.entity'; import { assertBookingStatus } from './booking-status.util'; import { ContainerValidationService } from './container-validation.service'; +/** + * One physical container over its VGM limit. Weight limits are per container, + * so an overloaded box is reported (and billed) on its own tons above the + * limit — a lighter box on the same line never absorbs them. + */ export interface OverweightLine { containerTypeCode: string; + /** Container number when known, else " #2" — identifies the box. */ + containerLabel: string; + /** This container's VGM, not the line total. */ totalVgmTons: number; + /** The per-container limit. */ maxAllowedTons: number; excessTons: number; } @@ -250,9 +259,10 @@ export class BookingPricingService { clearanceBlocked.push(...clearance.blocked); } - // Overweight detail for the customer: map the engine's per-line results back - // to the booking's container lines (same order) for code + weights. maxAllowed - // is derived from the line total minus the excess the engine computed. + // Overweight detail for the customer: one row per over-limit CONTAINER, + // mapped back to the booking's container lines (same order) for the code and + // the physical container numbers. maxAllowed is the per-container limit, + // recovered from that container's weight minus its own excess. const overweightLines: OverweightLine[] = []; const containerLines = (booking.bookingContainers ?? []).filter( (bc) => bc.containerTypeId != null, @@ -261,8 +271,6 @@ export class BookingPricingService { const wr = ruleResult.containerWeightResults[i]; if (!wr?.isOverweight) continue; const line = containerLines[i]; - const totalVgmTons = Number(line?.totalVgmTons ?? 0); - const excessTons = Number(wr.overweightExcessTons ?? 0); let code = line?.containerSize ?? ''; if (line?.containerTypeId) { try { @@ -271,12 +279,32 @@ export class BookingPricingService { // fall back to the container size label } } - overweightLines.push({ - containerTypeCode: code, - totalVgmTons, - maxAllowedTons: Math.max(0, totalVgmTons - excessTons), - excessTons, - }); + const numbers = (line?.units ?? []) + .slice() + .sort((a, b) => (a.sortOrder ?? 0) - (b.sortOrder ?? 0)) + .map((u) => u.containerNumber); + // Legacy weight results carry no per-unit detail (a line total only) — + // report the line as a single row, as before. + const units = wr.overweightUnits?.length + ? wr.overweightUnits + : [ + { + unitIndex: 0, + vgmTons: Number(line?.totalVgmTons ?? 0), + excessTons: Number(wr.overweightExcessTons ?? 0), + }, + ]; + for (const u of units) { + overweightLines.push({ + containerTypeCode: code, + containerLabel: + (u.unitIndex > 0 ? numbers[u.unitIndex - 1] : null) || + (u.unitIndex > 0 ? `${code} #${u.unitIndex}` : code), + totalVgmTons: u.vgmTons, + maxAllowedTons: Math.max(0, u.vgmTons - u.excessTons), + excessTons: u.excessTons, + }); + } } return { @@ -346,6 +374,13 @@ export class BookingPricingService { quantity: qty, vgmPerUnitTons: vgm, totalVgmTons: qty * vgm, + // Real per-box weights when the booking recorded them: weight + // limits are per container, so 22/18/20t is 2t over on the first + // box even though the line total fits a 3x20t allowance. + unitVgmTons: (bc.units ?? []) + .slice() + .sort((a, b) => (a.sortOrder ?? 0) - (b.sortOrder ?? 0)) + .map((u) => Number(u.vgmTons ?? 0)), isReefer: ct.isReefer, // Per-container opt-ins — PER_CONTAINER surcharges bill these. hazardousQuantity: Number(bc.hazardousQuantity ?? 0), diff --git a/apps/edr-freight-api/src/modules/bookings/booking-wagon-cancellation.service.ts b/apps/edr-freight-api/src/modules/bookings/booking-wagon-cancellation.service.ts index e9c85a91c..d3e3edfe5 100644 --- a/apps/edr-freight-api/src/modules/bookings/booking-wagon-cancellation.service.ts +++ b/apps/edr-freight-api/src/modules/bookings/booking-wagon-cancellation.service.ts @@ -383,6 +383,9 @@ export class BookingWagonCancellationService { status: 'CANCELLED', trainScheduleId: null, requestedTrainScheduleId: null, + // A dead booking holds no shipment day — leaving it set lets the + // stranded-PAID day sweep pick the booking up and resurrect it. + scheduledDate: null, }); await this.detachFromSchedule(b); } @@ -568,6 +571,9 @@ export class BookingWagonCancellationService { status: 'CANCELLED', trainScheduleId: null, requestedTrainScheduleId: null, + // A dead booking holds no shipment day — leaving it set lets the + // stranded-PAID day sweep pick the booking up and resurrect it. + scheduledDate: null, }); await this.detachFromSchedule(booking); this.notifyCustomer( diff --git a/apps/edr-freight-api/src/modules/bookings/dto/generate-price-response.dto.ts b/apps/edr-freight-api/src/modules/bookings/dto/generate-price-response.dto.ts index 0ee77aeed..d5e1a0e69 100644 --- a/apps/edr-freight-api/src/modules/bookings/dto/generate-price-response.dto.ts +++ b/apps/edr-freight-api/src/modules/bookings/dto/generate-price-response.dto.ts @@ -27,11 +27,15 @@ export class PriceLineItemDto { currency!: string; } +/** One physical container over its per-container VGM limit. */ export class OverweightLineDto { @ApiProperty() containerTypeCode!: string; - @ApiProperty() + @ApiProperty({ description: 'Container number, or " #2" when unnumbered' }) + containerLabel!: string; + + @ApiProperty({ description: "This container's VGM in tons" }) totalVgmTons!: number; @ApiProperty() diff --git a/apps/edr-freight-api/src/modules/contracts/contract-booking.service.ts b/apps/edr-freight-api/src/modules/contracts/contract-booking.service.ts index f4236ce7f..313364d8c 100644 --- a/apps/edr-freight-api/src/modules/contracts/contract-booking.service.ts +++ b/apps/edr-freight-api/src/modules/contracts/contract-booking.service.ts @@ -2091,6 +2091,7 @@ export class ContractBookingService { ): Promise<{ overweightLines: Array<{ containerTypeCode: string; + containerLabel: string; totalVgmTons: number; maxAllowedTons: number; excessTons: number; @@ -2200,6 +2201,12 @@ export class ContractBookingService { : 0, vgmPerUnitTons: line.units.length ? totalVgmTons / line.units.length : 0, totalVgmTons, + // Per-box weights drive the overweight check — the limit is per + // container, so a heavy box is billed even when the line total fits. + units: (line.units ?? []).map((u, idx) => ({ + vgmTons: Number(u.vgmTons ?? 0), + sortOrder: idx, + })) as BookingContainer['units'], wagonsRequired: Math.ceil(line.quantity * wagonsPerUnitForSize(ct.sizeFt)), }), ), @@ -2233,6 +2240,7 @@ export class ContractBookingService { containerTypeId: ct.id, quantity: line.quantity, totalVgmTons, + unitVgmTons: (line.units ?? []).map((u) => Number(u.vgmTons ?? 0)), })), contract.tradeDirection, ); @@ -2312,7 +2320,12 @@ export class ContractBookingService { (s, u) => s + Number(u.vgmTons ?? 0), 0, ); - return { containerTypeId: ct.id, quantity: line.quantity, totalVgmTons }; + return { + containerTypeId: ct.id, + quantity: line.quantity, + totalVgmTons, + unitVgmTons: (line.units ?? []).map((u) => Number(u.vgmTons ?? 0)), + }; }), ); diff --git a/apps/edr-freight-api/src/modules/contracts/contract-clearance.service.ts b/apps/edr-freight-api/src/modules/contracts/contract-clearance.service.ts index cf253347b..c95eb73b7 100644 --- a/apps/edr-freight-api/src/modules/contracts/contract-clearance.service.ts +++ b/apps/edr-freight-api/src/modules/contracts/contract-clearance.service.ts @@ -14,6 +14,8 @@ import { type ClearanceTrainState, } from '@edr/types'; +import { DataSource } from 'typeorm'; + import { DropdownSettingsService } from '../dropdown-settings/dropdown-settings.service'; import { FileUploadSettingsService } from '../file-upload-settings/file-upload-settings.service'; import { FilesService } from '../files/files.service'; @@ -117,6 +119,18 @@ export interface ContractClearanceView { linkedBookingReviewNote?: string | null; /** Shipment day the booking currently holds — the default when GL resubmits. */ linkedBookingScheduledDate?: string | null; + /** + * Open wagon-cancellation on a CANCELLED linked booking (consolidation + * partner lapsed, staff cut): FEE_PENDING = customer must pay the + * cancellation fee; CREDIT_AVAILABLE = fee settled, GL rebooks the credit. + */ + linkedBookingCancellation?: { + id: string; + status: string; + wagonsCancelled: number; + creditAmount: number; + creditCurrency: string; + } | null; dutyAdvice?: { amount: number; currency: string; @@ -171,6 +185,7 @@ export class ContractClearanceService { private readonly glOperationsService: GlOperationsService, private readonly notifier: ContractNotifierService, private readonly transitAgentsService: TransitAgentsService, + private readonly dataSource: DataSource, ) {} private isPhasedCustoms(contract: Contract): boolean { @@ -369,9 +384,27 @@ export class ContractClearanceService { // without a cycle row), so fall back to the contract's own live booking — // otherwise the clearance page sees no linked booking at all and cannot show // its status or the actions that depend on it. - const booking = cycle?.bookingId + let booking = cycle?.bookingId ? await this.bookingsService.findById(cycle.bookingId) : await this.contractsRepository.findLatestBookingForContract(contractId); + // The fallback skips terminal bookings, but a CANCELLED one with an open + // wagon-cancellation still belongs on this page: the fee gate and the + // rebook-from-credit action live here. Surface the newest such booking. + if (!booking) { + const [open] = await this.dataSource.query<{ booking_id: string }[]>( + `SELECT c.booking_id + FROM freight.booking_wagon_cancellations c + JOIN freight.bookings b ON b.id = c.booking_id + WHERE b.contract_id = $1 + AND b.status = 'CANCELLED' + AND c.status IN ('FEE_PENDING', 'CREDIT_AVAILABLE') + AND c.deleted_at IS NULL + ORDER BY c.created_at DESC + LIMIT 1`, + [contractId], + ); + if (open) booking = await this.bookingsService.findById(open.booking_id); + } if (booking) { linkedBookingId = booking.id ?? null; linkedBookingReference = booking.reference ?? null; @@ -395,6 +428,40 @@ export class ContractClearanceService { } } + // A CANCELLED booking may carry an open wagon-cancellation (consolidation + // partner lapsed, staff cut): FEE_PENDING gates on the customer paying the + // cancellation fee; CREDIT_AVAILABLE lets GL rebook from the credit here. + let linkedBookingCancellation: { + id: string; + status: string; + wagonsCancelled: number; + creditAmount: number; + creditCurrency: string; + } | null = null; + if (booking && linkedBookingStatus === 'CANCELLED') { + const [row] = await this.dataSource.query< + { id: string; status: string; wagons_cancelled: string; credit_amount: string }[] + >( + `SELECT id, status, wagons_cancelled, credit_amount + FROM freight.booking_wagon_cancellations + WHERE booking_id = $1 + AND status IN ('FEE_PENDING', 'CREDIT_AVAILABLE') + AND deleted_at IS NULL + ORDER BY created_at DESC + LIMIT 1`, + [booking.id], + ); + if (row) { + linkedBookingCancellation = { + id: row.id, + status: row.status, + wagonsCancelled: Number(row.wagons_cancelled), + creditAmount: Number(row.credit_amount), + creditCurrency: booking.paymentCurrency ?? 'ETB', + }; + } + } + return { contractId, status: contract.status, @@ -433,6 +500,7 @@ export class ContractClearanceService { linkedBookingStatus, linkedBookingReviewNote, linkedBookingScheduledDate, + linkedBookingCancellation, dutyAdvice, dutyDispute, transitAssignee, diff --git a/apps/edr-freight-api/src/modules/contracts/contract-duty-dispute.spec.ts b/apps/edr-freight-api/src/modules/contracts/contract-duty-dispute.spec.ts index b86b08444..a7bd3cd7d 100644 --- a/apps/edr-freight-api/src/modules/contracts/contract-duty-dispute.spec.ts +++ b/apps/edr-freight-api/src/modules/contracts/contract-duty-dispute.spec.ts @@ -63,6 +63,7 @@ describe('ContractClearanceService — duty dispute', () => { {} as never, // glOperationsService notifier as never, {} as never, // transitAgentsService + {} as never, // dataSource ); build([ milestone('DUTY_TAXES_ADVISED', 'COMPLETED'), diff --git a/apps/edr-freight-api/src/modules/contracts/transit-assignee.spec.ts b/apps/edr-freight-api/src/modules/contracts/transit-assignee.spec.ts index a6c8c8d6f..58c97619a 100644 --- a/apps/edr-freight-api/src/modules/contracts/transit-assignee.spec.ts +++ b/apps/edr-freight-api/src/modules/contracts/transit-assignee.spec.ts @@ -61,6 +61,7 @@ describe('ContractClearanceService — transit assignee', () => { {} as never, notifier as never, transitAgentsService as never, + {} as never, // dataSource ); }); diff --git a/apps/edr-freight-api/src/modules/eims/dto/register-sales-receipt.dto.ts b/apps/edr-freight-api/src/modules/eims/dto/register-sales-receipt.dto.ts index 70681f814..1d3efdf60 100644 --- a/apps/edr-freight-api/src/modules/eims/dto/register-sales-receipt.dto.ts +++ b/apps/edr-freight-api/src/modules/eims/dto/register-sales-receipt.dto.ts @@ -1,4 +1,4 @@ -import { ApiProperty, ApiPropertyOptional } from "@nestjs/swagger"; +import { ApiPropertyOptional } from "@nestjs/swagger"; import { IsIn, IsNumber, IsOptional, IsString, Length } from "class-validator"; import { EIMS_MODE_OF_PAYMENT, EimsModeOfPayment } from "../eims-receipt.types"; @@ -9,9 +9,15 @@ import { EIMS_MODE_OF_PAYMENT, EimsModeOfPayment } from "../eims-receipt.types"; * guessed (payment method, collector, provider references — none of it is modelled on `Invoice`). */ export class RegisterSalesReceiptDto { - @ApiProperty({ enum: EIMS_MODE_OF_PAYMENT, description: "MoR's confirmed ModeOfPayment enum." }) + @ApiPropertyOptional({ + enum: EIMS_MODE_OF_PAYMENT, + description: + "MoR's confirmed ModeOfPayment enum. Optional when the invoice's recorded payment method " + + "maps unambiguously (CASH, CHEQUE, CPO, CARD, BANK_TRANSFER); otherwise required.", + }) + @IsOptional() @IsIn(EIMS_MODE_OF_PAYMENT) - modeOfPayment!: EimsModeOfPayment; + modeOfPayment?: EimsModeOfPayment; @ApiPropertyOptional({ description: 'Defaults to "Payment received".' }) @IsOptional() diff --git a/apps/edr-freight-api/src/modules/eims/eims-receipt.service.spec.ts b/apps/edr-freight-api/src/modules/eims/eims-receipt.service.spec.ts index 93f50e827..55a38480b 100644 --- a/apps/edr-freight-api/src/modules/eims/eims-receipt.service.spec.ts +++ b/apps/edr-freight-api/src/modules/eims/eims-receipt.service.spec.ts @@ -116,6 +116,47 @@ describe("EimsReceiptService.registerSalesReceipt", () => { expect(receipt.qr).toBe("iVBORw0KGgo..."); }); + it("derives mode/date/voucher/amount from the recorded manual payment", async () => { + const db = new FakeDb([ + invoiceRow({ + payments: [ + { amount: 4000, method: "CASH", reference: "CRV-000123", paidAt: "2026-08-20T09:00:00.000Z", metadata: null }, + ], + } as never), + ]); + const postBearer = jest.fn().mockResolvedValue(okResponse()); + + await build(db, postBearer).registerSalesReceipt(INVOICE_ID, {} as never); + + const request = postBearer.mock.calls[0][1]; + expect(request.TransactionDetails.ModeOfPayment).toBe("CASH"); + expect(request.ManualReceiptNumber).toBe("CRV-000123"); + expect(request.ReceiptDate).toBe("2026-08-20T09:00:00.000Z"); + expect(request.CollectedAmount).toBe(4000); + }); + + it("puts a gateway reference in TransactionNumber, never ManualReceiptNumber, and demands an explicit mode", async () => { + const db = new FakeDb([ + invoiceRow({ + payments: [ + { amount: 10000, method: "GATEWAY", reference: "txn-9f8e7d", paidAt: "2026-08-21T10:00:00.000Z", metadata: null }, + ], + } as never), + ]); + const postBearer = jest.fn().mockResolvedValue(okResponse()); + const service = build(db, postBearer); + + // GATEWAY says nothing about the channel — deriving would guess a tax field. + await expect(service.registerSalesReceipt(INVOICE_ID, {} as never)).rejects.toThrow( + BadRequestException, + ); + + await service.registerSalesReceipt(INVOICE_ID, { modeOfPayment: "Card" } as never); + const request = postBearer.mock.calls[0][1]; + expect(request.TransactionDetails.TransactionNumber).toBe("txn-9f8e7d"); + expect(request.ManualReceiptNumber).not.toBe("txn-9f8e7d"); + }); + it("defaults PaymentCoverage to FULL when the invoice balance is 0, PARTIAL otherwise", async () => { const db = new FakeDb([invoiceRow({ balanceAmount: 500 })]); const postBearer = jest.fn().mockResolvedValue(okResponse()); diff --git a/apps/edr-freight-api/src/modules/eims/eims-receipt.service.ts b/apps/edr-freight-api/src/modules/eims/eims-receipt.service.ts index 2bdb6cbe2..f2de2937c 100644 --- a/apps/edr-freight-api/src/modules/eims/eims-receipt.service.ts +++ b/apps/edr-freight-api/src/modules/eims/eims-receipt.service.ts @@ -17,6 +17,8 @@ import { EimsReceipt, EimsReceiptKind, EimsReceiptStatus } from "./entities/eims import { RegisterSalesReceiptDto } from "./dto/register-sales-receipt.dto"; import { RegisterWithholdingReceiptDto } from "./dto/register-withholding-receipt.dto"; import { + EIMS_MODE_OF_PAYMENT, + EimsModeOfPayment, EimsReceiptResponse, EimsSalesReceiptRequest, EimsWithholdReceiptRequest, @@ -41,8 +43,11 @@ const DETERMINISTIC_KINDS = new Set(["SCHEMA_VALIDATION", "RULE_VALIDATION", "AU * double-submission guard the way `/v1/cancel` does ("IRN already Canceled."), so the same caution * applies as an unacknowledged registration: a human must check the MoR portal first. * - * Several request fields have no confirmed source in this codebase (payment method, collector, - * withholding rate/amount) and are never guessed — see the two DTOs. + * Sales receipts derive what the invoice's payment ledger actually records — amount, date, + * finance's voucher number (ManualReceiptNumber), gateway transaction id, and the payment mode + * where the ledger method maps unambiguously to MoR's enum. Fields with no recorded source + * (collector, withholding rate/amount, mobile-money modes) are still asked of the caller, never + * guessed — see the two DTOs. */ @Injectable() export class EimsReceiptService { @@ -68,7 +73,26 @@ export class EimsReceiptService { const session = await this.auth.getSessionContext(); const receiptNumber = this.generateReceiptNumber(invoice); - const collectedAmount = dto.collectedAmount ?? Number(invoice.paidAmount); + + // The newest ledger entry is the payment this receipt vouches for. A gateway settlement's + // `reference` is the provider transaction id; a manual settlement's `reference` is finance's + // own voucher number (CRV) — that one belongs in ManualReceiptNumber so the registered + // receipt matches finance's books. + const lastPayment = invoice.payments?.length + ? invoice.payments[invoice.payments.length - 1] + : null; + const isGateway = (lastPayment?.method ?? "").toUpperCase() === "GATEWAY"; + const modeOfPayment = dto.modeOfPayment ?? deriveModeOfPayment(lastPayment?.method); + if (!modeOfPayment) { + throw new BadRequestException({ + code: "EIMS_MODE_OF_PAYMENT_REQUIRED", + message: + `Recorded payment method "${lastPayment?.method ?? "none"}" has no unambiguous MoR ` + + `ModeOfPayment — pass modeOfPayment (one of ${EIMS_MODE_OF_PAYMENT.join(", ")}).`, + }); + } + const collectedAmount = + dto.collectedAmount ?? (lastPayment ? lastPayment.amount : Number(invoice.paidAmount)); const balance = Number(invoice.balanceAmount); const request: EimsSalesReceiptRequest = { @@ -77,9 +101,9 @@ export class EimsReceiptService { Reason: dto.reason ?? "Payment received", // ISO-8601 UTC — the collection's saved example uses a "+03:00" offset instead; no schema // error for this field was ever observed to confirm which form MoR actually requires. - ReceiptDate: new Date().toISOString(), + ReceiptDate: lastPayment?.paidAt ?? new Date().toISOString(), ReceiptCounter: String(Date.now()), - ManualReceiptNumber: receiptNumber, + ManualReceiptNumber: (!isGateway && lastPayment?.reference) || receiptNumber, SourceSystemType: session.systemType, SourceSystemNumber: session.systemNumber, ReceiptCurrency: currency, @@ -97,7 +121,7 @@ export class EimsReceiptService { }, ], TransactionDetails: { - ModeOfPayment: dto.modeOfPayment, + ModeOfPayment: modeOfPayment, ChequeNumber: dto.chequeNumber ?? null, CPONumber: dto.cpoNumber ?? null, DocumentNumber: dto.documentNumber ?? null, @@ -105,7 +129,7 @@ export class EimsReceiptService { PaymentServiceProvider: dto.paymentServiceProvider ?? null, OtherPaymentServiceProviderName: dto.otherPaymentServiceProviderName ?? null, AccountNumber: dto.accountNumber ?? null, - TransactionNumber: dto.transactionNumber ?? null, + TransactionNumber: dto.transactionNumber ?? (isGateway ? (lastPayment?.reference ?? null) : null), }, }; @@ -286,3 +310,17 @@ export class EimsReceiptService { return `REC-${invoice.invoiceNumber}-${Date.now()}`; } } + +/** + * Recorded ledger method → MoR ModeOfPayment, only where the mapping is unambiguous. Mobile-money + * methods (TELEBIRR, EBIRR, …) have no MoR enum slot, and "GATEWAY" says nothing about the real + * channel — those return undefined and the caller must supply modeOfPayment explicitly. Guessing + * a tax field is worse than asking. + */ +function deriveModeOfPayment(method: string | null | undefined): EimsModeOfPayment | undefined { + if (!method) return undefined; + const normalized = method.toUpperCase().replace(/-/g, "_"); + const direct = EIMS_MODE_OF_PAYMENT.find((m) => m.toUpperCase().replace(/ /g, "_") === normalized); + if (direct) return direct; + return normalized === "BANK_TRANSFER" ? "Local Bank Transfer" : undefined; +} diff --git a/apps/edr-freight-api/src/modules/rule-engine/rule-engine.service.spec.ts b/apps/edr-freight-api/src/modules/rule-engine/rule-engine.service.spec.ts index c530e5314..2d91d2da7 100644 --- a/apps/edr-freight-api/src/modules/rule-engine/rule-engine.service.spec.ts +++ b/apps/edr-freight-api/src/modules/rule-engine/rule-engine.service.spec.ts @@ -169,6 +169,101 @@ describe('RuleEngineService — overweight surcharge by trade direction', () => }); }); +describe('RuleEngineService — overweight is per container, never pooled', () => { + const configuredOverweight: Rate = { + id: 'rate-ow', + rateType: 'OVERWEIGHT_PER_TON', + trigger: 'OVERWEIGHT', + rateValue: 10, + rateUnit: 'PER_TON', + currency: 'USD', + status: 'LIVE', + containerTypeId: null, + cargoTypeId: null, + } as Rate; + + const makeService = (maxCapacityTons: number | null) => + new RuleEngineService( + { findById: jest.fn().mockResolvedValue(null) } as never, + { findById: jest.fn().mockResolvedValue(null) } as never, + { + findActiveByContainerTypeId: jest + .fn() + .mockResolvedValue([{ id: 'wlr-20', maxVgmTons: 20, maxCapacityTons }]), + } as never, + { findAllActive: jest.fn().mockResolvedValue([]) } as never, + { findLiveRates: jest.fn().mockResolvedValue([configuredOverweight]) } as never, + { findById: jest.fn().mockResolvedValue(null) } as never, + {} as never, + ); + + // The reported case: 3 × 20ft at 22 / 18 / 20 t against a 20 t limit. The + // line total (60 t) fits a pooled 3 × 20 t allowance, but the first box is + // 2 t over and must be billed for it. + const input = (unitVgmTons: number[]): BookingEvaluationInput => ({ + serviceTypeId: 'svc-1', + paymentCurrency: 'USD', + tradeDirection: 'EXPORT', + isHazardous: false, + totalWagons: 2, + containers: [ + { + containerTypeId: 'ct-20', + quantity: unitVgmTons.length, + vgmPerUnitTons: unitVgmTons.reduce((s, v) => s + v, 0) / unitVgmTons.length, + totalVgmTons: unitVgmTons.reduce((s, v) => s + v, 0), + unitVgmTons, + }, + ], + }); + + it('bills only the tons the heavy container is over, not the line total', async () => { + const result = await makeService(null).evaluate(input([22, 18, 20])); + const wr = result.containerWeightResults[0]; + expect(wr.isOverweight).toBe(true); + expect(wr.overweightExcessTons).toBe(2); + expect(wr.overweightUnits).toEqual([{ unitIndex: 1, vgmTons: 22, excessTons: 2 }]); + const ow = result.appliedModifiers.filter((m) => m.surchargeCode === 'OVERWEIGHT_PER_TON'); + expect(ow[0].calculatedAmount).toBe(20); // 2 t × 10 USD/t + }); + + it('sums the excess of every over-limit container', async () => { + const result = await makeService(null).evaluate(input([22, 18, 23])); + const wr = result.containerWeightResults[0]; + expect(wr.overweightExcessTons).toBe(5); + expect(wr.overweightUnits?.map((u) => u.unitIndex)).toEqual([1, 3]); + }); + + it('is not overweight when no single container is over the limit', async () => { + const result = await makeService(null).evaluate(input([20, 18, 20])); + expect(result.containerWeightResults[0].isOverweight).toBe(false); + }); + + it('falls back to an even spread when a line carries no per-unit weights', async () => { + const result = await makeService(null).evaluate({ + serviceTypeId: 'svc-1', + paymentCurrency: 'USD', + tradeDirection: 'EXPORT', + isHazardous: false, + totalWagons: 2, + containers: [ + { containerTypeId: 'ct-20', quantity: 3, vgmPerUnitTons: 21, totalVgmTons: 63 }, + ], + }); + // 3 boxes at 21 t each → 1 t over on each. + expect(result.containerWeightResults[0].overweightExcessTons).toBe(3); + }); + + it('blocks on capacity per container, not on the pooled line total', async () => { + const violations = await makeService(30).capacityViolations( + [{ containerTypeId: 'ct-20', quantity: 3, totalVgmTons: 60, unitVgmTons: [35, 5, 20] }], + 'EXPORT', + ); + expect(violations).toHaveLength(1); + expect(violations[0]).toContain('#1'); + }); +}); + describe('RuleEngineService — empty-container return per route + container type', () => { const returnRate20: Rate = { id: 'rate-return-20', diff --git a/apps/edr-freight-api/src/modules/rule-engine/rule-engine.service.ts b/apps/edr-freight-api/src/modules/rule-engine/rule-engine.service.ts index 5c9055415..3fbecc036 100644 --- a/apps/edr-freight-api/src/modules/rule-engine/rule-engine.service.ts +++ b/apps/edr-freight-api/src/modules/rule-engine/rule-engine.service.ts @@ -33,6 +33,32 @@ import { GOVERNMENT_PRIORITY_BONUS } from './government-priority.constants'; // from multipart form-data) and a non-empty "false" string is truthy. const truthy = (v: unknown): boolean => v === true || v === 'true'; +/** Tons carry 3 decimals in the schema; keep derived tonnage on that grid. */ +const round3 = (n: number): number => Math.round(n * 1000) / 1000; + +/** + * The VGM of every physical container on a line. Uses the per-unit weights the + * booking recorded; when a line has none (or fewer than its quantity — legacy + * rows only kept a line total), the remainder is spread evenly, which is the + * uniform load those bookings were entered as. + */ +export const unitWeights = (container: { + quantity: number; + totalVgmTons: number; + unitVgmTons?: number[]; +}): number[] => { + const known = (container.unitVgmTons ?? []) + .slice(0, container.quantity) + .map((v) => Number(v ?? 0)); + const missing = Math.max(0, Number(container.quantity || 0) - known.length); + if (missing === 0) return known; + const rest = Math.max( + 0, + Number(container.totalVgmTons || 0) - known.reduce((s, v) => s + v, 0), + ); + return [...known, ...Array(missing).fill(rest / missing)]; +}; + export interface BookingContainerEvalInput { containerTypeId: string; quantity: number; @@ -41,6 +67,15 @@ export interface BookingContainerEvalInput { isReefer?: boolean; isOverweight?: boolean; overweightExcessTons?: number | null; + /** + * VGM of each physical container on this line, when the booking carries + * per-unit weights. Weight limits are a per-container ceiling: 3x20ft at + * 22/18/20t against a 20t limit is 2t overweight on the first box, not + * zero because the line total happens to fit. Missing/short (legacy lines + * that only carry a line total) falls back to an even spread across + * `quantity`, which is what those bookings actually recorded. + */ + unitVgmTons?: number[]; /** * How many individual containers on this line opted into each handling * service. PER_CONTAINER surcharges bill these counts, not the line @@ -131,11 +166,22 @@ export interface AppliedCargoModifier { billingUnit?: string; } +/** One physical container that broke the per-container VGM limit. */ +export interface OverweightUnit { + /** 1-based position of the container within its line. */ + unitIndex: number; + vgmTons: number; + excessTons: number; +} + export interface ContainerWeightResult { containerTypeId: string; weightLimitRuleId: string | null; isOverweight: boolean; + /** Sum of the per-container excesses on this line. */ overweightExcessTons: number | null; + /** Which containers of the line are over, and by how much. */ + overweightUnits?: OverweightUnit[]; } export interface RuleEvaluationResult { @@ -221,22 +267,37 @@ export class RuleEngineService { lineMaxVgmTons.push(rule ? Number(rule.maxVgmTons) : null); let isOverweight = container.isOverweight ?? false; let excess = container.overweightExcessTons ?? null; + let overweightUnits: OverweightUnit[] | undefined; if (rule) { - const maxTotal = Number(rule.maxVgmTons) * container.quantity; - const totalVgm = container.totalVgmTons; - if (totalVgm > maxTotal) { + const perUnitLimit = Number(rule.maxVgmTons); + // Per-container, never pooled: an underloaded box does not absorb the + // excess of an overloaded one — each container is billed on its own + // tons above the limit. + overweightUnits = unitWeights(container) + .map((vgmTons, i) => ({ + unitIndex: i + 1, + vgmTons, + excessTons: round3(Math.max(0, vgmTons - perUnitLimit)), + })) + .filter((u) => u.excessTons > 0); + if (overweightUnits.length > 0) { isOverweight = true; - excess = Math.max(0, totalVgm - maxTotal); - warnings.push( - `Container type ${container.containerTypeId} VGM ${totalVgm}t exceeds limit ${maxTotal}t`, + excess = round3( + overweightUnits.reduce((sum, u) => sum + u.excessTons, 0), ); + for (const u of overweightUnits) { + warnings.push( + `Container type ${container.containerTypeId} #${u.unitIndex} VGM ${u.vgmTons}t exceeds the ${perUnitLimit}t limit by ${u.excessTons}t`, + ); + } } containerWeightResults.push({ containerTypeId: container.containerTypeId, weightLimitRuleId: rule.id, isOverweight, overweightExcessTons: excess, + overweightUnits, }); } else { containerWeightResults.push({ @@ -719,6 +780,7 @@ export class RuleEngineService { containerTypeId: string; quantity: number; totalVgmTons: number; + unitVgmTons?: number[]; }>, tradeDirection: string, ): Promise { @@ -731,13 +793,17 @@ export class RuleEngineService { const rule = rules[0]; if (!rule || rule.maxCapacityTons == null) continue; const perUnit = Number(rule.maxCapacityTons); - const maxTotal = perUnit * container.quantity; - if (container.totalVgmTons > maxTotal) { - const label = rule.containerType?.code ?? container.containerTypeId; - violations.push( - `${label} total weight ${container.totalVgmTons}t exceeds the maximum capacity of ${maxTotal}t (${perUnit}t per unit) — the booking cannot be created; reduce the cargo weight`, - ); - } + const label = rule.containerType?.code ?? container.containerTypeId; + // Capacity is a physical ceiling on one box, so it is checked per box for + // the same reason the VGM limit is — a light container cannot carry the + // overload of a heavy one. + unitWeights(container).forEach((vgmTons, i) => { + if (vgmTons > perUnit) { + violations.push( + `${label} #${i + 1} weight ${round3(vgmTons)}t exceeds the maximum capacity of ${perUnit}t per container — the booking cannot be created; reduce the cargo weight`, + ); + } + }); } return violations; } diff --git a/apps/edr-freight-api/src/modules/shipping-lines/shipping-line-booking-completion.service.ts b/apps/edr-freight-api/src/modules/shipping-lines/shipping-line-booking-completion.service.ts index ce5a7fad8..c43781c43 100644 --- a/apps/edr-freight-api/src/modules/shipping-lines/shipping-line-booking-completion.service.ts +++ b/apps/edr-freight-api/src/modules/shipping-lines/shipping-line-booking-completion.service.ts @@ -484,6 +484,13 @@ export class ShippingLineBookingCompletionService { returnQuantity: 0, vgmPerUnitTons: figures.vgmPerUnit, totalVgmTons: figures.totalVgm, + // In-memory units so the probe prices the same per-container + // overweight the persisted booking will: the limit applies to each + // box, not to the line's pooled tonnage. + units: (line.units ?? []).map((u, idx) => ({ + vgmTons: Number(u.vgmTons ?? 0), + sortOrder: idx, + })) as BookingContainer['units'], wagonsRequired: Math.ceil( line.quantity * wagonsPerUnitForSize(containerType.sizeFt), ), diff --git a/apps/edr-freight-api/src/modules/train-scheduling/booking-batch.service.spec.ts b/apps/edr-freight-api/src/modules/train-scheduling/booking-batch.service.spec.ts index fa4be32bb..5c76b7803 100644 --- a/apps/edr-freight-api/src/modules/train-scheduling/booking-batch.service.spec.ts +++ b/apps/edr-freight-api/src/modules/train-scheduling/booking-batch.service.spec.ts @@ -195,6 +195,20 @@ describe('BookingBatchService — PAID reconcile', () => { expect(trainSchedulingService.tryAutoWagonAllocation).toHaveBeenCalledTimes(2); }); + it('ensurePaidBookingAllocated never resurrects a CANCELLED booking that is still paymentStatus PAID', async () => { + dataSource.getRepository().findOne.mockResolvedValue({ + ...paidBooking, + status: 'CANCELLED', + trainScheduleId: null, + } as unknown as Booking); + + await service.ensurePaidBookingAllocated(bookingId); + + expect(trainScheduleBookingsRepository.createMany).not.toHaveBeenCalled(); + expect(trainSchedulingService.tryAutoWagonAllocation).not.toHaveBeenCalled(); + expect(dataSource.getRepository().update).not.toHaveBeenCalled(); + }); + it('ensurePaidBookingAllocated holds a wagon-short booking out of the train', async () => { trainSchedulingService.previewPaidBookingWagonShortage.mockResolvedValue({ wagonTypeCodes: 'NW6', diff --git a/apps/edr-freight-api/src/modules/train-scheduling/booking-batch.service.ts b/apps/edr-freight-api/src/modules/train-scheduling/booking-batch.service.ts index 8a348e625..625ccfda7 100644 --- a/apps/edr-freight-api/src/modules/train-scheduling/booking-batch.service.ts +++ b/apps/edr-freight-api/src/modules/train-scheduling/booking-batch.service.ts @@ -571,6 +571,12 @@ export class BookingBatchService implements OnModuleInit { relations: { company: true }, }); if (!booking) return; + // A dead booking keeps payment_status = 'PAID' (it was paid before it died), + // so every rescue path below would happily re-place and re-allocate it — + // that is how a cancelled consolidation-lapse booking came back onto its + // train 30s after being cancelled. Never resurrect a dead booking. + if (["CANCELLED", "EXPIRED", "REJECTED", "COMPLETED"].includes(booking.status)) + return; if (!booking.trainScheduleId) { // A paid booking with no train is money taken and nothing boarding. The // hold was expired before the payment landed (webhook lag beat the diff --git a/apps/edr-freight-api/src/scripts/import-mor-locations.ts b/apps/edr-freight-api/src/scripts/import-mor-locations.ts index f45c81556..b26305c6a 100644 --- a/apps/edr-freight-api/src/scripts/import-mor-locations.ts +++ b/apps/edr-freight-api/src/scripts/import-mor-locations.ts @@ -64,7 +64,9 @@ async function main(): Promise { const args = process.argv.slice(2); const sheetFlag = args.indexOf("--sheet"); const sheetName = sheetFlag >= 0 ? args[sheetFlag + 1] : DEFAULT_SHEET; - const workbookPath = args.find((arg, i) => !arg.startsWith("--") && i !== sheetFlag + 1); + const workbookPath = args.find( + (arg, i) => !arg.startsWith("--") && (sheetFlag < 0 || i !== sheetFlag + 1), + ); if (!workbookPath) { throw new Error( diff --git a/apps/edr-freight-web/backoffice/src/components/contracts/GlCreateBookingForm.tsx b/apps/edr-freight-web/backoffice/src/components/contracts/GlCreateBookingForm.tsx index dd47ae36e..e208328cc 100644 --- a/apps/edr-freight-web/backoffice/src/components/contracts/GlCreateBookingForm.tsx +++ b/apps/edr-freight-web/backoffice/src/components/contracts/GlCreateBookingForm.tsx @@ -2410,9 +2410,9 @@ export default function GlCreateBookingForm() { {overweightLines.map((line, i) => ( - {line.containerTypeCode}: {line.totalVgmTons}t exceeds - limit {line.maxAllowedTons}t (+{line.excessTons}t - overweight) + {line.containerLabel || line.containerTypeCode}:{" "} + {line.totalVgmTons}t exceeds limit {line.maxAllowedTons}t + (+{line.excessTons}t overweight) ))} diff --git a/apps/edr-freight-web/backoffice/src/pages/contracts/ContractClearanceDetailPage.tsx b/apps/edr-freight-web/backoffice/src/pages/contracts/ContractClearanceDetailPage.tsx index dacae6cea..f91d2525e 100644 --- a/apps/edr-freight-web/backoffice/src/pages/contracts/ContractClearanceDetailPage.tsx +++ b/apps/edr-freight-web/backoffice/src/pages/contracts/ContractClearanceDetailPage.tsx @@ -1,6 +1,6 @@ import { directionLabel } from "@/lib/utils"; -import { useMemo } from "react"; -import { useQuery } from "@tanstack/react-query"; +import { useMemo, useState } from "react"; +import { useMutation, useQuery } from "@tanstack/react-query"; import { useLocation, useParams } from "react-router-dom"; import { Alert, @@ -14,6 +14,7 @@ import { Stack, Text, } from "@mantine/core"; +import { DatePickerInput } from "@mantine/dates"; import { AlertCircle, ArrowRight, @@ -22,9 +23,16 @@ import { PackageCheck, RefreshCw, ShieldCheck, + XCircle, } from "lucide-react"; +import toast from "react-hot-toast"; import { Link } from "react-router-dom"; +import { api } from "@/auth/http"; +import { extractErrorMessage } from "@/utils/errorExtractor"; +import { formatMoney } from "@/lib/format"; +import { toDayString } from "@/hooks/useListControls"; + import { useAuth } from "@/auth/useAuth"; import { FREIGHT_PERMS, @@ -146,6 +154,32 @@ export default function ContractClearanceDetailPage() { !isDjiboutiGl(user); const canResubmitBooking = bookingNeedsChanges && isGlBookingOwner; const canRebook = bookingExpired && isGlBookingOwner; + // The linked booking was CANCELLED with an open wagon-cancellation ledger row + // (consolidation partner lapsed unpaid, staff cut). FEE_PENDING: the customer + // must settle the cancellation-fee invoice first; CREDIT_AVAILABLE: the paid + // freight is credit and GL rebooks it from here (new booking under this + // contract, marked PAID — it re-enters consolidation pairing if odd 20ft). + const cancellation = + clearance?.linkedBookingStatus === "CANCELLED" + ? clearance?.linkedBookingCancellation + : null; + const canRebookCredit = + cancellation?.status === "CREDIT_AVAILABLE" && + hasPermission(user, FREIGHT_PERMS.bookings.wagonCancellationRebook); + const [creditRebookDate, setCreditRebookDate] = useState(null); + const creditRebook = useMutation({ + mutationFn: () => + api.post(`/bookings/wagon-cancellations/${cancellation!.id}/rebook`, { + scheduledDate: toDayString(creditRebookDate!), + }), + onSuccess: () => { + toast.success("Booking recreated from the credit and marked paid."); + void refetch(); + void refetchContract(); + }, + onError: (err) => + toast.error(extractErrorMessage(err, "Rebook failed")), + }); // Rebook completes the SAME expired booking (it already carries the price and // cargo from its first completion) via the /complete endpoint's EXPIRED // branch — routing it through create-booking instead would create a @@ -252,7 +286,18 @@ export default function ContractClearanceDetailPage() { Customs ) : null} - {bookingExpired ? ( + {cancellation ? ( + } + > + {cancellation.status === "FEE_PENDING" + ? "Cancelled — fee pending" + : "Cancelled — rebook credit"} + + ) : bookingExpired ? ( : null} - {bookingExpired ? ( + {cancellation ? ( + } + title={`Booking ${clearance.linkedBookingReference ?? ""} cancelled — consolidation partner not paid`} + > + + {cancellation.status === "FEE_PENDING" ? ( + + The booking shared a wagon with a partner booking that was + never paid, so it could not board and was cancelled. Its paid + freight ({formatMoney(cancellation.creditAmount, cancellation.creditCurrency)}) is held as + rebooking credit. The customer must first pay the cancellation + fee from the portal Payments tab — once it settles, rebook the + shipment here. + + ) : ( + <> + + The cancellation fee is settled. Pick the new shipment day + and rebook — the booking is recreated under this contract + from the {formatMoney(cancellation.creditAmount, cancellation.creditCurrency)} credit and + marked paid (no new freight charge). + + {canRebookCredit ? ( + + setCreditRebookDate(v ? new Date(v) : null)} + minDate={new Date()} + w={220} + /> + + + ) : null} + + )} + + + ) : bookingExpired ? ( #2" when unnumbered. */ + containerLabel: string; + /** This container's VGM — the limit is per container, never pooled. */ totalVgmTons: number; maxAllowedTons: number; excessTons: number; diff --git a/apps/edr-freight-web/portal/src/pages/contracts/NewShipmentPage.tsx b/apps/edr-freight-web/portal/src/pages/contracts/NewShipmentPage.tsx index f27e75d7c..cc92d3ae2 100644 --- a/apps/edr-freight-web/portal/src/pages/contracts/NewShipmentPage.tsx +++ b/apps/edr-freight-web/portal/src/pages/contracts/NewShipmentPage.tsx @@ -1024,8 +1024,9 @@ function PriceConfirmModal({ {overweightLines.map((line, i) => ( - {line.containerTypeCode}: {line.totalVgmTons}t exceeds limit{" "} - {line.maxAllowedTons}t (+{line.excessTons}t overweight) + {line.containerLabel || line.containerTypeCode}:{" "} + {line.totalVgmTons}t exceeds limit {line.maxAllowedTons}t (+ + {line.excessTons}t overweight) ))} diff --git a/apps/edr-freight-web/portal/src/pages/shipping-line/ShippingLineCompletePage.tsx b/apps/edr-freight-web/portal/src/pages/shipping-line/ShippingLineCompletePage.tsx index 809c8e5c1..1a8aecf71 100644 --- a/apps/edr-freight-web/portal/src/pages/shipping-line/ShippingLineCompletePage.tsx +++ b/apps/edr-freight-web/portal/src/pages/shipping-line/ShippingLineCompletePage.tsx @@ -644,8 +644,9 @@ function PriceConfirmModal({ {overweightLines.map((line, i) => ( - {line.containerTypeCode}: {line.totalVgmTons}t exceeds limit{" "} - {line.maxAllowedTons}t (+{line.excessTons}t overweight) + {line.containerLabel || line.containerTypeCode}:{" "} + {line.totalVgmTons}t exceeds limit {line.maxAllowedTons}t (+ + {line.excessTons}t overweight) ))} diff --git a/apps/edr-freight-web/portal/src/services/contracts.service.ts b/apps/edr-freight-web/portal/src/services/contracts.service.ts index 4e9cb79de..2979cf274 100644 --- a/apps/edr-freight-web/portal/src/services/contracts.service.ts +++ b/apps/edr-freight-web/portal/src/services/contracts.service.ts @@ -33,9 +33,12 @@ export interface SubmitContractResponse { message?: string; } -/** A container line whose total VGM exceeds the weight-limit rule. */ +/** One physical container whose VGM exceeds the weight-limit rule. */ export interface OverweightLine { containerTypeCode: string; + /** Container number, or " #2" when unnumbered. */ + containerLabel: string; + /** This container's VGM — the limit is per container, never pooled. */ totalVgmTons: number; maxAllowedTons: number; excessTons: number; diff --git a/apps/edr-freight-web/portal/src/services/shipping-line-bookings.service.ts b/apps/edr-freight-web/portal/src/services/shipping-line-bookings.service.ts index 74797e6dc..c95d5d453 100644 --- a/apps/edr-freight-web/portal/src/services/shipping-line-bookings.service.ts +++ b/apps/edr-freight-web/portal/src/services/shipping-line-bookings.service.ts @@ -70,6 +70,9 @@ export interface ShippingLinePriceQuote { /** Containers over their type's weight limit — a surcharge, not a block. */ overweightLines: { containerTypeCode: string; + /** Container number, or " #2" when unnumbered. */ + containerLabel: string; + /** This container's VGM — the limit is per container, never pooled. */ totalVgmTons: number; maxAllowedTons: number; excessTons: number; diff --git a/e2e-ui/4_5767239985799371288.xlsx b/e2e-ui/4_5767239985799371288.xlsx new file mode 100644 index 000000000..35cb5744e Binary files /dev/null and b/e2e-ui/4_5767239985799371288.xlsx differ diff --git a/packages/types/src/freight/contracts.ts b/packages/types/src/freight/contracts.ts index 98ec76a0c..867787efa 100644 --- a/packages/types/src/freight/contracts.ts +++ b/packages/types/src/freight/contracts.ts @@ -511,6 +511,18 @@ export interface ContractClearanceView { linkedBookingReviewNote?: string | null; /** Shipment day the booking holds; the default when GL resubmits it. */ linkedBookingScheduledDate?: string | null; + /** + * Open wagon-cancellation on a CANCELLED linked booking (consolidation + * partner lapsed, staff cut): FEE_PENDING = customer must pay the + * cancellation fee; CREDIT_AVAILABLE = fee settled, GL rebooks the credit. + */ + linkedBookingCancellation?: { + id: string; + status: string; + wagonsCancelled: number; + creditAmount: number; + creditCurrency: string; + } | null; /** * Pre-declaration handshake with GL Djibouti: who handles the shipment in * transit. `name` stays null until Djibouti answers, and GL Ethiopia cannot