diff --git a/migrations/app/migrations_manifest.txt b/migrations/app/migrations_manifest.txt index 75df2f48cab..c3e1e2d1e86 100644 --- a/migrations/app/migrations_manifest.txt +++ b/migrations/app/migrations_manifest.txt @@ -1090,5 +1090,6 @@ 20250120214107_add_international_ntsr_service_items.up.sql 20250121153007_update_pricing_proc_to_handle_international_shuttle.up.sql 20250121184450_upd_duty_loc_B-22242.up.sql +20250123173216_add_destination_queue_db_func_and_gbloc_view.up.sql 20250204162411_updating_create_accessorial_service_item_proc_for_crating.up.sql 20250206173204_add_hawaii_data.up.sql diff --git a/migrations/app/schema/20250123173216_add_destination_queue_db_func_and_gbloc_view.up.sql b/migrations/app/schema/20250123173216_add_destination_queue_db_func_and_gbloc_view.up.sql new file mode 100644 index 00000000000..5148f0f57d7 --- /dev/null +++ b/migrations/app/schema/20250123173216_add_destination_queue_db_func_and_gbloc_view.up.sql @@ -0,0 +1,502 @@ +--insert USMC gbloc +insert into jppso_regions values ('85b324ae-1a0d-4f7d-971f-ea509dcc73d7', 'USMC','USMC',now(),now()); + +--insert USMC AORs +INSERT INTO gbloc_aors (id,jppso_regions_id,oconus_rate_area_id,department_indicator,shipment_type,is_active,created_at,updated_at) VALUES + ('a8eb35e2-275e-490b-9945-1971b954b958'::uuid,'85b324ae-1a0d-4f7d-971f-ea509dcc73d7'::uuid,'e418be11-2b6f-4714-b026-e293528c50bd'::uuid,'MARINES',NULL,true,now(),now()), + ('ada1b48d-d2e0-481a-8a2e-a265a824647d'::uuid,'85b324ae-1a0d-4f7d-971f-ea509dcc73d7'::uuid,'b41c5636-96dd-4f0d-a18e-eebb17f97ea5'::uuid,'MARINES',NULL,true,now(),now()), + ('588af482-7cd7-42ea-8e05-49dce645ecbe'::uuid,'85b324ae-1a0d-4f7d-971f-ea509dcc73d7'::uuid,'02f32a6a-0338-4545-8437-059862892d2c'::uuid,'MARINES',NULL,true,now(),now()), + ('1ff3bed7-bbf3-432d-9da3-d76264d72913'::uuid,'85b324ae-1a0d-4f7d-971f-ea509dcc73d7'::uuid,'0f128476-d52a-418c-8ba0-c8bfd1c32629'::uuid,'MARINES',NULL,true,now(),now()), + ('0853a854-98b2-4363-a2b1-db14c44dde2f'::uuid,'85b324ae-1a0d-4f7d-971f-ea509dcc73d7'::uuid,'081f84c3-17ec-4ff6-97ce-d5c44a8e4a28'::uuid,'MARINES',NULL,true,now(),now()), + ('21c1ba40-2533-4196-9eb5-6ffddff3a794'::uuid,'85b324ae-1a0d-4f7d-971f-ea509dcc73d7'::uuid,'ce7cdd91-e323-43a6-a604-daaa6bf8be06'::uuid,'MARINES',NULL,true,now(),now()), + ('19ca4073-8736-453e-bb0d-9b13e3b557b0'::uuid,'85b324ae-1a0d-4f7d-971f-ea509dcc73d7'::uuid,'655050d4-711a-43b7-b06d-828ec990c35e'::uuid,'MARINES',NULL,true,now(),now()), + ('a9c2131e-09c3-480d-ba3e-0c144de18aa5'::uuid,'85b324ae-1a0d-4f7d-971f-ea509dcc73d7'::uuid,'455a34af-30a8-4a98-a62b-6f40fd7f047b'::uuid,'MARINES',NULL,true,now(),now()), + ('649e72f8-cac8-483f-a9ed-c9659e37545b'::uuid,'85b324ae-1a0d-4f7d-971f-ea509dcc73d7'::uuid,'1bf1daee-51bb-4c28-aac8-a126ef596486'::uuid,'MARINES',NULL,true,now(),now()), + ('7173f871-f948-4eed-86ae-5e977b16c426'::uuid,'85b324ae-1a0d-4f7d-971f-ea509dcc73d7'::uuid,'15b1d852-0dde-4e1b-b3c6-e08bbc714db3'::uuid,'MARINES',NULL,true,now(),now()); +INSERT INTO gbloc_aors (id,jppso_regions_id,oconus_rate_area_id,department_indicator,shipment_type,is_active,created_at,updated_at) VALUES + ('4f626e2a-cad0-4b4d-baa8-3101275bac23'::uuid,'85b324ae-1a0d-4f7d-971f-ea509dcc73d7'::uuid,'d63de5bb-379b-4f3b-b4c1-554b9746d311'::uuid,'MARINES',NULL,true,now(),now()), + ('de59c604-9119-48fc-bf3f-883de17b7ee6'::uuid,'85b324ae-1a0d-4f7d-971f-ea509dcc73d7'::uuid,'95d142f8-b50a-4108-b5e2-fbd3b7022d3b'::uuid,'MARINES',NULL,true,now(),now()), + ('1cec884c-9e34-42fe-8887-1e8b8fa1cd2e'::uuid,'85b324ae-1a0d-4f7d-971f-ea509dcc73d7'::uuid,'922bb7da-d0e9-431c-a493-95a861dca929'::uuid,'MARINES',NULL,true,now(),now()), + ('0f24b453-e3bc-47ec-86b5-8d8937f65504'::uuid,'85b324ae-1a0d-4f7d-971f-ea509dcc73d7'::uuid,'79aef0ca-9065-4c0e-a134-2889b250cc38'::uuid,'MARINES',NULL,true,now(),now()), + ('2d55560a-7d0a-474f-a0f9-b31c5be8d80e'::uuid,'85b324ae-1a0d-4f7d-971f-ea509dcc73d7'::uuid,'1f181025-e410-41ac-935b-4b5147353f84'::uuid,'MARINES',NULL,true,now(),now()), + ('abcc37f6-9209-4639-8fa1-c8d5f6e4e77d'::uuid,'85b324ae-1a0d-4f7d-971f-ea509dcc73d7'::uuid,'d9ede620-c3f1-4f8d-b60b-eb93664382f7'::uuid,'MARINES',NULL,true,now(),now()), + ('3ac990d2-5df4-4889-a943-2710f818e75a'::uuid,'85b324ae-1a0d-4f7d-971f-ea509dcc73d7'::uuid,'bd27700b-3094-46cc-807b-f18472cbfaf0'::uuid,'MARINES',NULL,true,now(),now()), + ('f3084090-680f-4656-947a-eb2e773e4076'::uuid,'85b324ae-1a0d-4f7d-971f-ea509dcc73d7'::uuid,'2f4a1689-ee65-45fa-9d0c-debd9344f8b9'::uuid,'MARINES',NULL,true,now(),now()), + ('a35ac50b-09a1-46ef-969e-17569717ee10'::uuid,'85b324ae-1a0d-4f7d-971f-ea509dcc73d7'::uuid,'20c52934-2588-4d8f-b3ed-c046d771f4e9'::uuid,'MARINES',NULL,true,now(),now()), + ('107c1479-e6d9-44cb-8342-ac934055074d'::uuid,'85b324ae-1a0d-4f7d-971f-ea509dcc73d7'::uuid,'15fe364b-add5-4ade-bdd9-38fe442616fb'::uuid,'MARINES',NULL,true,now(),now()); +INSERT INTO gbloc_aors (id,jppso_regions_id,oconus_rate_area_id,department_indicator,shipment_type,is_active,created_at,updated_at) VALUES + ('843db089-67cb-463d-a255-1d198f4f7aaa'::uuid,'85b324ae-1a0d-4f7d-971f-ea509dcc73d7'::uuid,'e5a1248e-3870-4a4c-9c9d-2056234eb64a'::uuid,'MARINES',NULL,true,now(),now()), + ('ac820ac9-d380-4c11-9103-172795658e1f'::uuid,'85b324ae-1a0d-4f7d-971f-ea509dcc73d7'::uuid,'efc92db1-4b06-49ab-a295-a98f3f6c9c04'::uuid,'MARINES',NULL,true,now(),now()), + ('dca7ccd2-e438-4f82-8b76-9b61fbf2a593'::uuid,'85b324ae-1a0d-4f7d-971f-ea509dcc73d7'::uuid,'13474ce5-8839-4af7-b975-c3f70ccdab7b'::uuid,'MARINES',NULL,true,now(),now()), + ('def1095b-2a5c-4f7c-8889-9fde15a7ec06'::uuid,'85b324ae-1a0d-4f7d-971f-ea509dcc73d7'::uuid,'d3b05c5e-6faa-4fa9-b725-0904f8a4f3d7'::uuid,'MARINES',NULL,true,now(),now()), + ('d5fbc738-ee31-4c51-8fd4-bbb8db941dc1'::uuid,'85b324ae-1a0d-4f7d-971f-ea509dcc73d7'::uuid,'e5f849fe-5672-4d0d-881c-078e56eea33d'::uuid,'MARINES',NULL,true,now(),now()), + ('ac8c75fe-f637-429d-80fa-913321a65372'::uuid,'85b324ae-1a0d-4f7d-971f-ea509dcc73d7'::uuid,'fca7c60e-fbd9-4885-afdb-ae41c521b560'::uuid,'MARINES',NULL,true,now(),now()), + ('c33eb1f8-b0fc-4670-af5e-5bd423eca6e7'::uuid,'85b324ae-1a0d-4f7d-971f-ea509dcc73d7'::uuid,'0d52a0f0-f39c-4d34-9387-2df45a5810d4'::uuid,'MARINES',NULL,true,now(),now()), + ('188ea995-b8b7-4ce0-97a9-f553f3b72c2f'::uuid,'85b324ae-1a0d-4f7d-971f-ea509dcc73d7'::uuid,'af008e75-81d5-4211-8204-4964c78e70d9'::uuid,'MARINES',NULL,true,now(),now()), + ('4f13c1a6-059b-4aa2-9250-4316e60da2a7'::uuid,'85b324ae-1a0d-4f7d-971f-ea509dcc73d7'::uuid,'dd689e55-af29-4c76-b7e0-c2429ea4833c'::uuid,'MARINES',NULL,true,now(),now()), + ('67e1ff6f-b79b-45cf-b250-3d4ec89bebae'::uuid,'85b324ae-1a0d-4f7d-971f-ea509dcc73d7'::uuid,'60e08330-6869-4586-8198-35f7a4ae9ea7'::uuid,'MARINES',NULL,true,now(),now()); +INSERT INTO gbloc_aors (id,jppso_regions_id,oconus_rate_area_id,department_indicator,shipment_type,is_active,created_at,updated_at) VALUES + ('3a7c679c-0439-4030-8f7e-f6d8e92720d7'::uuid,'85b324ae-1a0d-4f7d-971f-ea509dcc73d7'::uuid,'f7478e79-dbfe-46c8-b337-1e7c46df79dc'::uuid,'MARINES',NULL,true,now(),now()), + ('db91f133-a301-4c87-af9f-6c10584063e6'::uuid,'85b324ae-1a0d-4f7d-971f-ea509dcc73d7'::uuid,'486d7dd4-f51f-4b13-88fc-830b5b15f0a8'::uuid,'MARINES',NULL,true,now(),now()), + ('6b83cc22-36a9-470e-9f43-e65ade5e8a66'::uuid,'85b324ae-1a0d-4f7d-971f-ea509dcc73d7'::uuid,'f66edf62-ba5e-47f8-8264-b6dc9e7dd9ba'::uuid,'MARINES',NULL,true,now(),now()), + ('3df30221-acd3-4428-890c-3a5ef5296cb1'::uuid,'85b324ae-1a0d-4f7d-971f-ea509dcc73d7'::uuid,'0052c55a-d9d7-46b0-9328-58d3911f61b4'::uuid,'MARINES',NULL,true,now(),now()), + ('bae4c9c6-94d8-4ad0-bfc0-7642f5353199'::uuid,'85b324ae-1a0d-4f7d-971f-ea509dcc73d7'::uuid,'16a51fd1-04ed-432a-a8d7-9f17c1de095d'::uuid,'MARINES',NULL,true,now(),now()), + ('1cd873ff-d170-4f48-8f5b-5c5146052d68'::uuid,'85b324ae-1a0d-4f7d-971f-ea509dcc73d7'::uuid,'64b4756f-437d-4aa5-a95e-c396f0cafcbb'::uuid,'MARINES',NULL,true,now(),now()), + ('eb4d870b-8d66-4135-b294-8992e56ad76f'::uuid,'85b324ae-1a0d-4f7d-971f-ea509dcc73d7'::uuid,'f2de1da5-a737-4493-b3f7-7700944a5b62'::uuid,'MARINES',NULL,true,now(),now()), + ('e8c0709c-1f08-4d3e-b848-72ab5b524677'::uuid,'85b324ae-1a0d-4f7d-971f-ea509dcc73d7'::uuid,'7a9c2adb-0562-42c1-a5f1-81710dd19590'::uuid,'MARINES',NULL,true,now(),now()), + ('3c53df36-ee6b-4bc0-a5ca-cedc1dc3c32e'::uuid,'85b324ae-1a0d-4f7d-971f-ea509dcc73d7'::uuid,'e713eed6-35a6-456d-bfb2-0e0646078ab8'::uuid,'MARINES',NULL,true,now(),now()), + ('7cbc7e6c-4da7-47a1-ac93-171b89dba1e0'::uuid,'85b324ae-1a0d-4f7d-971f-ea509dcc73d7'::uuid,'a4594957-0ec6-4edc-85c2-68871f4f6359'::uuid,'MARINES',NULL,true,now(),now()); +INSERT INTO gbloc_aors (id,jppso_regions_id,oconus_rate_area_id,department_indicator,shipment_type,is_active,created_at,updated_at) VALUES + ('d22cb1d2-79b4-45c9-bb6f-8acef54a67b0'::uuid,'85b324ae-1a0d-4f7d-971f-ea509dcc73d7'::uuid,'acd4d2f9-9a49-4a73-be14-3515f19ba0d1'::uuid,'MARINES',NULL,true,now(),now()), + ('5b5e7a5a-d027-44f2-9b4f-f25c1a91bc00'::uuid,'85b324ae-1a0d-4f7d-971f-ea509dcc73d7'::uuid,'c8300ab6-519c-4bef-9b81-25e7334773ca'::uuid,'MARINES',NULL,true,now(),now()), + ('21307477-912d-40ca-a399-6dfebcc322ea'::uuid,'85b324ae-1a0d-4f7d-971f-ea509dcc73d7'::uuid,'67eca2ce-9d88-44ca-bb17-615f3199415c'::uuid,'MARINES',NULL,true,now(),now()), + ('82282efb-7fef-4a6d-a260-a18d2f21fa8d'::uuid,'85b324ae-1a0d-4f7d-971f-ea509dcc73d7'::uuid,'149c3a94-abb1-4af0-aabf-3af019d5e243'::uuid,'MARINES',NULL,true,now(),now()), + ('3bdad313-d414-4842-8e6e-3675e20d78eb'::uuid,'85b324ae-1a0d-4f7d-971f-ea509dcc73d7'::uuid,'87c09b47-058e-47ea-9684-37a8ac1f7120'::uuid,'MARINES',NULL,true,now(),now()), + ('db80b591-045d-4907-9b77-6694fe34e3ed'::uuid,'85b324ae-1a0d-4f7d-971f-ea509dcc73d7'::uuid,'0ba81e85-f175-435a-a7c2-a22d0c44cc7b'::uuid,'MARINES',NULL,true,now(),now()), + ('05970a8a-28aa-454f-a28e-31327a2415dd'::uuid,'85b324ae-1a0d-4f7d-971f-ea509dcc73d7'::uuid,'946256dc-1572-4201-b5ff-464da876f5ff'::uuid,'MARINES',NULL,true,now(),now()), + ('c1b3e0be-0463-4dfc-ab22-016037b41a05'::uuid,'85b324ae-1a0d-4f7d-971f-ea509dcc73d7'::uuid,'5d381518-6beb-422e-8c57-4682b87ff1fe'::uuid,'MARINES',NULL,true,now(),now()), + ('1a92f4b0-4060-4f1b-9b45-b3fc47c5f08d'::uuid,'85b324ae-1a0d-4f7d-971f-ea509dcc73d7'::uuid,'b07fb701-2c9b-4847-a459-76b1f47aa872'::uuid,'MARINES',NULL,true,now(),now()), + ('73794c53-a915-41af-b93d-5ada2e174409'::uuid,'85b324ae-1a0d-4f7d-971f-ea509dcc73d7'::uuid,'b6c51584-f3e8-4c9e-9bdf-f7cac0433319'::uuid,'MARINES',NULL,true,now(),now()); +INSERT INTO gbloc_aors (id,jppso_regions_id,oconus_rate_area_id,department_indicator,shipment_type,is_active,created_at,updated_at) VALUES + ('c03994c2-9e2a-4888-a5c2-c81ee05eba31'::uuid,'85b324ae-1a0d-4f7d-971f-ea509dcc73d7'::uuid,'6097d01d-78ef-40d5-8699-7f8a8e48f4e7'::uuid,'MARINES',NULL,true,now(),now()), + ('ae6a55fd-2171-425a-9716-56d3fb9452e3'::uuid,'85b324ae-1a0d-4f7d-971f-ea509dcc73d7'::uuid,'e48a3602-7fdd-4527-a8a7-f244fb331228'::uuid,'MARINES',NULL,true,now(),now()), + ('f052acf4-7d4a-4061-a2f4-ba19ff17ec4d'::uuid,'85b324ae-1a0d-4f7d-971f-ea509dcc73d7'::uuid,'df47ef29-e902-4bd3-a32d-88d6187399b3'::uuid,'MARINES',NULL,true,now(),now()), + ('10b47428-bef7-4cfe-8564-2ccb654d514a'::uuid,'85b324ae-1a0d-4f7d-971f-ea509dcc73d7'::uuid,'0f4eddf9-b727-4725-848e-3d9329553823'::uuid,'MARINES',NULL,true,now(),now()), + ('4a547501-6aae-4886-be5c-e5a0fad05441'::uuid,'85b324ae-1a0d-4f7d-971f-ea509dcc73d7'::uuid,'d16ebe80-2195-48cf-ba61-b5efb8212754'::uuid,'MARINES',NULL,true,now(),now()), + ('d99cbe3a-84a0-4a2c-8e05-41ce066570ea'::uuid,'85b324ae-1a0d-4f7d-971f-ea509dcc73d7'::uuid,'093268d0-597b-40bd-882a-8f385480bc68'::uuid,'MARINES',NULL,true,now(),now()), + ('ad09f13c-9dd9-468b-ab92-ad3e2d77c905'::uuid,'85b324ae-1a0d-4f7d-971f-ea509dcc73d7'::uuid,'edb8b022-9534-44e7-87ea-e93f5451f057'::uuid,'MARINES',NULL,true,now(),now()), + ('362482c6-7770-49f4-86c9-89e2990e5345'::uuid,'85b324ae-1a0d-4f7d-971f-ea509dcc73d7'::uuid,'4c62bb35-4d2a-4995-9c4f-8c665f2f6d3e'::uuid,'MARINES',NULL,true,now(),now()), + ('45994e2f-1aa4-4aa1-8631-a347a4463bc2'::uuid,'85b324ae-1a0d-4f7d-971f-ea509dcc73d7'::uuid,'58ccfcc5-ded6-4f91-8cb7-8687bc56c4c6'::uuid,'MARINES',NULL,true,now(),now()), + ('b4fd2bf2-05b2-4429-afcb-ebbae512fd2b'::uuid,'85b324ae-1a0d-4f7d-971f-ea509dcc73d7'::uuid,'dbc839c6-7b56-45b0-ab36-a0e77b0d538c'::uuid,'MARINES',NULL,true,now(),now()); +INSERT INTO gbloc_aors (id,jppso_regions_id,oconus_rate_area_id,department_indicator,shipment_type,is_active,created_at,updated_at) VALUES + ('5aa5f596-a9bb-4f37-af0b-6e0cfbfbc711'::uuid,'85b324ae-1a0d-4f7d-971f-ea509dcc73d7'::uuid,'c77e434a-1bf9-44c6-92aa-d377d72d1d44'::uuid,'MARINES',NULL,true,now(),now()), + ('c7bc79d4-525e-496d-93bd-2ea76b32baf4'::uuid,'85b324ae-1a0d-4f7d-971f-ea509dcc73d7'::uuid,'89533190-e613-4c36-99df-7ee3871bb071'::uuid,'MARINES',NULL,true,now(),now()), + ('5bc99ccb-7010-4d2f-99a0-9277eda982ba'::uuid,'85b324ae-1a0d-4f7d-971f-ea509dcc73d7'::uuid,'c86cb50a-99f6-41ed-8e9d-f096bd5cadca'::uuid,'MARINES',NULL,true,now(),now()), + ('dc97dd55-213b-4212-8c1a-aaee7b92fc55'::uuid,'85b324ae-1a0d-4f7d-971f-ea509dcc73d7'::uuid,'b65bd7c4-6251-4682-aa07-77f761c363af'::uuid,'MARINES',NULL,true,now(),now()), + ('3a4daddc-a377-440f-bb5f-d33024374e3e'::uuid,'85b324ae-1a0d-4f7d-971f-ea509dcc73d7'::uuid,'88df8618-798a-4a12-9b14-a7267a6cfd7f'::uuid,'MARINES',NULL,true,now(),now()), + ('e729c30a-0bec-424a-919a-45cbe31998e9'::uuid,'85b324ae-1a0d-4f7d-971f-ea509dcc73d7'::uuid,'15894c4f-eb1a-4b6b-8b3f-e3abc4eeee8d'::uuid,'MARINES',NULL,true,now(),now()), + ('74b6df4f-08ea-48fb-9628-15c3f47f3a27'::uuid,'85b324ae-1a0d-4f7d-971f-ea509dcc73d7'::uuid,'83fd3eb7-6269-46e2-84e1-f6180f40b9e8'::uuid,'MARINES',NULL,true,now(),now()), + ('643112a7-71a9-41d1-97f6-92aee969478a'::uuid,'85b324ae-1a0d-4f7d-971f-ea509dcc73d7'::uuid,'b0f95e07-e3d1-4403-a402-50be9a542cf9'::uuid,'MARINES',NULL,true,now(),now()), + ('73b35029-077b-4d30-8f5a-34c3785f6e96'::uuid,'85b324ae-1a0d-4f7d-971f-ea509dcc73d7'::uuid,'cef18ff2-8f48-47c0-8062-a40f9dec641c'::uuid,'MARINES',NULL,true,now(),now()), + ('9d8862ec-4358-497a-8154-65a83c676261'::uuid,'85b324ae-1a0d-4f7d-971f-ea509dcc73d7'::uuid,'15eefe71-55ae-40b0-8bb5-f1952fcf45c8'::uuid,'MARINES',NULL,true,now(),now()); +INSERT INTO gbloc_aors (id,jppso_regions_id,oconus_rate_area_id,department_indicator,shipment_type,is_active,created_at,updated_at) VALUES + ('8d5591d4-fcc4-44a9-babd-b575672ad6a9'::uuid,'85b324ae-1a0d-4f7d-971f-ea509dcc73d7'::uuid,'d3c5d0a7-0477-44f6-8279-f6b9fa7b3436'::uuid,'MARINES',NULL,true,now(),now()), + ('c1057fc7-1c8b-44e2-a175-131ff0d7429f'::uuid,'85b324ae-1a0d-4f7d-971f-ea509dcc73d7'::uuid,'8b89e7d7-cb36-40bd-ba14-699f1e4b1806'::uuid,'MARINES',NULL,true,now(),now()), + ('ae7949e2-9504-4874-92be-98460e8126da'::uuid,'85b324ae-1a0d-4f7d-971f-ea509dcc73d7'::uuid,'5b833661-8fda-4f2a-9f2b-e1f4c21749a4'::uuid,'MARINES',NULL,true,now(),now()), + ('acf2cacd-0d4f-4de1-afdc-2eb1e72eeb80'::uuid,'85b324ae-1a0d-4f7d-971f-ea509dcc73d7'::uuid,'38bed277-7990-460d-ad27-a69559638f42'::uuid,'MARINES',NULL,true,now(),now()), + ('c66c3d59-def9-4e08-8bee-5b2bacfc5cfd'::uuid,'85b324ae-1a0d-4f7d-971f-ea509dcc73d7'::uuid,'67081e66-7e84-4bac-9c31-aa3e45bbba23'::uuid,'MARINES',NULL,true,now(),now()), + ('1f8cd63a-8dfe-4357-9ac5-2bef71f9d564'::uuid,'85b324ae-1a0d-4f7d-971f-ea509dcc73d7'::uuid,'99e3f894-595f-403a-83f5-f7e035dd1f20'::uuid,'MARINES',NULL,true,now(),now()), + ('3e8030da-8316-4330-abea-35452e39fa61'::uuid,'85b324ae-1a0d-4f7d-971f-ea509dcc73d7'::uuid,'1c0a5988-492f-4bc2-8409-9a143a494248'::uuid,'MARINES',NULL,true,now(),now()), + ('ce3c740a-b0a2-4a55-9abe-c2426fb8d821'::uuid,'85b324ae-1a0d-4f7d-971f-ea509dcc73d7'::uuid,'63e10b54-5348-4362-932e-6613a8db4d42'::uuid,'MARINES',NULL,true,now(),now()), + ('9e913f22-287f-4e42-9544-46d9c6741db7'::uuid,'85b324ae-1a0d-4f7d-971f-ea509dcc73d7'::uuid,'437e9930-0625-4448-938d-ba93a0a98ab5'::uuid,'MARINES',NULL,true,now(),now()), + ('d0ae21fe-07c0-40ee-9aa3-877d6d6a6bb9'::uuid,'85b324ae-1a0d-4f7d-971f-ea509dcc73d7'::uuid,'87d3cb47-1026-4f42-bff6-899ff0fa7660'::uuid,'MARINES',NULL,true,now(),now()); +INSERT INTO gbloc_aors (id,jppso_regions_id,oconus_rate_area_id,department_indicator,shipment_type,is_active,created_at,updated_at) VALUES + ('6f8d7c90-7682-41b7-b5cc-9d4aeb2e22ef'::uuid,'85b324ae-1a0d-4f7d-971f-ea509dcc73d7'::uuid,'0115586e-be8c-4808-b65a-d417fad19238'::uuid,'MARINES',NULL,true,now(),now()), + ('cf7f39c0-8f6b-4598-85db-f465241e66f4'::uuid,'85b324ae-1a0d-4f7d-971f-ea509dcc73d7'::uuid,'6638a77d-4b91-48f6-8241-c87fbdddacd1'::uuid,'MARINES',NULL,true,now(),now()), + ('296a8951-19b1-4868-9937-aef61bb73106'::uuid,'85b324ae-1a0d-4f7d-971f-ea509dcc73d7'::uuid,'97c16bc3-e174-410b-9a09-a0db31420dbc'::uuid,'MARINES',NULL,true,now(),now()), + ('cdcec10e-5300-443f-9aae-7d8ce07142b0'::uuid,'85b324ae-1a0d-4f7d-971f-ea509dcc73d7'::uuid,'3c6c5e35-1281-45fc-83ee-e6d656e155b6'::uuid,'MARINES',NULL,true,now(),now()), + ('e638701f-f8fc-48c0-b2e0-db134b9ece1f'::uuid,'85b324ae-1a0d-4f7d-971f-ea509dcc73d7'::uuid,'6af248be-e5a8-49e9-a9e2-516748279ab5'::uuid,'MARINES',NULL,true,now(),now()), + ('ed4f4905-b1cf-4e57-beac-bc0a2d167c71'::uuid,'85b324ae-1a0d-4f7d-971f-ea509dcc73d7'::uuid,'3580abe3-84da-4b46-af7b-d4379e6cff46'::uuid,'MARINES',NULL,true,now(),now()), + ('2a8b16c9-99f8-43ca-a759-c4884f8f7b24'::uuid,'85b324ae-1a0d-4f7d-971f-ea509dcc73d7'::uuid,'f3bb397e-04e6-4b37-9bf3-b3ebab79a9b6'::uuid,'MARINES',NULL,true,now(),now()), + ('70530105-a4ab-4af3-ba02-9e4cf81237fa'::uuid,'85b324ae-1a0d-4f7d-971f-ea509dcc73d7'::uuid,'f9bfe297-4ee0-4f76-a4bd-64b3a514af5d'::uuid,'MARINES',NULL,true,now(),now()), + ('61e17c04-ed7b-4da9-816a-1b6343086d94'::uuid,'85b324ae-1a0d-4f7d-971f-ea509dcc73d7'::uuid,'70f11a71-667b-422d-ae37-8f25539f7782'::uuid,'MARINES',NULL,true,now(),now()), + ('19d5158f-96a6-48ef-8dd9-b831c582c9c4'::uuid,'85b324ae-1a0d-4f7d-971f-ea509dcc73d7'::uuid,'baf66a9a-3c8a-49e7-83ea-841b9960e184'::uuid,'MARINES',NULL,true,now(),now()); +INSERT INTO gbloc_aors (id,jppso_regions_id,oconus_rate_area_id,department_indicator,shipment_type,is_active,created_at,updated_at) VALUES + ('91043072-657f-4b2a-b5d1-42d8f6a7ba38'::uuid,'85b324ae-1a0d-4f7d-971f-ea509dcc73d7'::uuid,'e96d46b1-3ab7-4b29-b798-ec3b728dd6a1'::uuid,'MARINES',NULL,true,now(),now()), + ('a3dc835e-3989-4476-b560-006745a884bc'::uuid,'85b324ae-1a0d-4f7d-971f-ea509dcc73d7'::uuid,'e4171b5b-d26c-43b3-b41c-68b43bcbb079'::uuid,'MARINES',NULL,true,now(),now()), + ('0cf1dc14-0c9a-4262-9cab-db73c64f6e36'::uuid,'85b324ae-1a0d-4f7d-971f-ea509dcc73d7'::uuid,'a0651bec-1258-4e36-9c76-155247e42c0a'::uuid,'MARINES',NULL,true,now(),now()), + ('e03b53cb-386f-4e1e-ac93-cd1a9260c6b4'::uuid,'85b324ae-1a0d-4f7d-971f-ea509dcc73d7'::uuid,'737a8e63-af19-4902-a4b5-8f80e2268e4b'::uuid,'MARINES',NULL,true,now(),now()), + ('8b3f1142-f6d4-4c2d-9e75-9ab3568742f7'::uuid,'85b324ae-1a0d-4f7d-971f-ea509dcc73d7'::uuid,'870df26e-2c50-4512-aa2e-61094cfbc3e1'::uuid,'MARINES',NULL,true,now(),now()), + ('5f5383b8-f29e-4b9f-8798-99575440c888'::uuid,'85b324ae-1a0d-4f7d-971f-ea509dcc73d7'::uuid,'09dc6547-d346-40c3-93fb-fb7be1fa1b3e'::uuid,'MARINES',NULL,true,now(),now()), + ('1f7a198c-5f62-4f8c-bf91-19d7cdef9bae'::uuid,'85b324ae-1a0d-4f7d-971f-ea509dcc73d7'::uuid,'43d7d081-bb32-4544-84f1-419fe0cb76e1'::uuid,'MARINES',NULL,true,now(),now()), + ('56c17bab-a124-4710-a047-0d67d30a9610'::uuid,'85b324ae-1a0d-4f7d-971f-ea509dcc73d7'::uuid,'d7e57942-9c83-4138-baa0-70e8b5f08598'::uuid,'MARINES',NULL,true,now(),now()), + ('aad1440d-acaf-4ba8-9564-da97ab9ba651'::uuid,'85b324ae-1a0d-4f7d-971f-ea509dcc73d7'::uuid,'c2f06691-5989-41a3-a848-19c9f0fec5df'::uuid,'MARINES',NULL,true,now(),now()), + ('6cc24224-2298-4023-888f-5e624e585171'::uuid,'85b324ae-1a0d-4f7d-971f-ea509dcc73d7'::uuid,'5263a9ed-ff4d-42cc-91d5-dbdefeef54d1'::uuid,'MARINES',NULL,true,now(),now()); +INSERT INTO gbloc_aors (id,jppso_regions_id,oconus_rate_area_id,department_indicator,shipment_type,is_active,created_at,updated_at) VALUES + ('88cd8184-7e3a-48cf-bb72-a9e1c3666cc4'::uuid,'85b324ae-1a0d-4f7d-971f-ea509dcc73d7'::uuid,'54ab3a49-6d78-4922-bac1-94a722b9859a'::uuid,'MARINES',NULL,true,now(),now()), + ('11fdac1c-7ae9-49ea-bee4-90d4582f7c6d'::uuid,'85b324ae-1a0d-4f7d-971f-ea509dcc73d7'::uuid,'3b6fe2e9-9116-4a70-8eef-96205205b0e3'::uuid,'MARINES',NULL,true,now(),now()), + ('83c88ffb-5182-42b3-93f4-635556d8caaf'::uuid,'85b324ae-1a0d-4f7d-971f-ea509dcc73d7'::uuid,'ba0017c8-5d48-4efe-8802-361d2f2bc16d'::uuid,'MARINES',NULL,true,now(),now()), + ('802f7a5f-8ce3-4c40-975a-83cf0ec502fc'::uuid,'85b324ae-1a0d-4f7d-971f-ea509dcc73d7'::uuid,'af65234a-8577-4f6d-a346-7d486e963287'::uuid,'MARINES',NULL,true,now(),now()), + ('5197eed4-f6ae-4f70-b640-b67714b73f87'::uuid,'85b324ae-1a0d-4f7d-971f-ea509dcc73d7'::uuid,'25f62695-ba9b-40c3-a7e4-0c078731123d'::uuid,'MARINES',NULL,true,now(),now()), + ('50d675ab-4064-4edb-8f1d-5739b0318ed9'::uuid,'85b324ae-1a0d-4f7d-971f-ea509dcc73d7'::uuid,'b0422b13-4afe-443e-901f-fe652cde23a4'::uuid,'MARINES',NULL,true,now(),now()), + ('a3733567-2b57-4f12-9390-967e04bc1453'::uuid,'85b324ae-1a0d-4f7d-971f-ea509dcc73d7'::uuid,'ecbc1d89-9cf6-4f52-b453-3ba473a0ff4e'::uuid,'MARINES',NULL,true,now(),now()), + ('6a321494-cdd8-4372-90a1-6a6c67f4e220'::uuid,'85b324ae-1a0d-4f7d-971f-ea509dcc73d7'::uuid,'4e85cb86-e9dd-4c7c-9677-e0a327ac895c'::uuid,'MARINES',NULL,true,now(),now()), + ('99d37d3c-be31-4d3e-9c5e-c9d816a46014'::uuid,'85b324ae-1a0d-4f7d-971f-ea509dcc73d7'::uuid,'7f9dd10d-100e-4252-9786-706349f456ca'::uuid,'MARINES',NULL,true,now(),now()), + ('e9b4c884-ad7f-4c1a-8815-05353834f5c3'::uuid,'85b324ae-1a0d-4f7d-971f-ea509dcc73d7'::uuid,'5451f8d7-60c5-4e22-bbf6-d9af8e6ace54'::uuid,'MARINES',NULL,true,now(),now()); +INSERT INTO gbloc_aors (id,jppso_regions_id,oconus_rate_area_id,department_indicator,shipment_type,is_active,created_at,updated_at) VALUES + ('cfaa046e-6be5-4178-a451-d368317ecb86'::uuid,'85b324ae-1a0d-4f7d-971f-ea509dcc73d7'::uuid,'9e9cba85-7c39-4836-809d-70b54baf392e'::uuid,'MARINES',NULL,true,now(),now()), + ('9b509efb-12d9-42aa-a85a-ffb026866b56'::uuid,'85b324ae-1a0d-4f7d-971f-ea509dcc73d7'::uuid,'f7470914-cf48-43be-b431-a3ca2fe5b290'::uuid,'MARINES',NULL,true,now(),now()), + ('7e54d995-b7bd-457c-bd97-0fd76891402e'::uuid,'85b324ae-1a0d-4f7d-971f-ea509dcc73d7'::uuid,'5a0d3cc1-b866-4bde-b67f-78d565facf3e'::uuid,'MARINES',NULL,true,now(),now()), + ('1357aadd-b420-42c4-8a39-bab8027fa910'::uuid,'85b324ae-1a0d-4f7d-971f-ea509dcc73d7'::uuid,'e629b95a-ec5b-4fc4-897f-e0d1050e1ec6'::uuid,'MARINES',NULL,true,now(),now()), + ('56fbbf0f-e819-41dd-802d-4e677aecd1c9'::uuid,'85b324ae-1a0d-4f7d-971f-ea509dcc73d7'::uuid,'d68a626f-935a-4eb1-ba9b-6829feeff91c'::uuid,'MARINES',NULL,true,now(),now()), + ('bfc2dc53-896f-4f29-92c7-9a7a392b22f2'::uuid,'85b324ae-1a0d-4f7d-971f-ea509dcc73d7'::uuid,'ed496f6e-fd34-48d1-8586-63a1d305c49c'::uuid,'MARINES',NULL,true,now(),now()), + ('d015e8b1-86ea-489f-979d-458ae35ae8d6'::uuid,'85b324ae-1a0d-4f7d-971f-ea509dcc73d7'::uuid,'153b62b2-b1b8-4b9d-afa5-53df4150aba4'::uuid,'MARINES',NULL,true,now(),now()), + ('1f32e712-8b5e-4ae4-b409-c5c92337aed8'::uuid,'85b324ae-1a0d-4f7d-971f-ea509dcc73d7'::uuid,'0020441b-bc0c-436e-be05-b997ca6a853c'::uuid,'MARINES',NULL,true,now(),now()), + ('a8a85e00-e657-41a2-8f32-84bdd9c92ec8'::uuid,'85b324ae-1a0d-4f7d-971f-ea509dcc73d7'::uuid,'a8ae9bb9-e9ac-49b4-81dc-336b8a0dcb54'::uuid,'MARINES',NULL,true,now(),now()), + ('4ad1a57f-0e9e-4405-9a08-0ffa211fc8ce'::uuid,'85b324ae-1a0d-4f7d-971f-ea509dcc73d7'::uuid,'1aa43046-8d6b-4249-88dc-b259d86c0cb8'::uuid,'MARINES',NULL,true,now(),now()); +INSERT INTO gbloc_aors (id,jppso_regions_id,oconus_rate_area_id,department_indicator,shipment_type,is_active,created_at,updated_at) VALUES + ('dd765820-ffa5-4673-a347-fbe3464cd2d8'::uuid,'85b324ae-1a0d-4f7d-971f-ea509dcc73d7'::uuid,'84b50723-95fc-41d1-8115-a734c7e53f66'::uuid,'MARINES',NULL,true,now(),now()), + ('6eff7586-59bd-4638-809b-5cc346646dc9'::uuid,'85b324ae-1a0d-4f7d-971f-ea509dcc73d7'::uuid,'63dc3f78-235e-4b1c-b1db-459d7f5ae25f'::uuid,'MARINES',NULL,true,now(),now()), + ('428b0d7a-3848-4882-a5cc-80d5ae3500d6'::uuid,'85b324ae-1a0d-4f7d-971f-ea509dcc73d7'::uuid,'4bd4c579-c163-4b1b-925a-d852d5a12642'::uuid,'MARINES',NULL,true,now(),now()), + ('9f8311f3-e191-4383-8fb8-2b58cd545dd4'::uuid,'85b324ae-1a0d-4f7d-971f-ea509dcc73d7'::uuid,'ce7f1fc9-5b94-43cb-b398-b31cb6350d6a'::uuid,'MARINES',NULL,true,now(),now()), + ('81e3e6fe-7db3-49ff-b18c-8b078e3d129e'::uuid,'85b324ae-1a0d-4f7d-971f-ea509dcc73d7'::uuid,'4a6a3260-e1ec-4d78-8c07-d89f1405ca16'::uuid,'MARINES',NULL,true,now(),now()), + ('4cf1c40f-60f0-4a47-a351-471720ba0fd3'::uuid,'85b324ae-1a0d-4f7d-971f-ea509dcc73d7'::uuid,'658274b5-720c-4a70-ba9d-249614d85ebc'::uuid,'MARINES',NULL,true,now(),now()), + ('0754978b-d11e-4f2c-b59c-3252d2735b26'::uuid,'85b324ae-1a0d-4f7d-971f-ea509dcc73d7'::uuid,'41f0736c-6d26-4e93-9668-860e9f0e222a'::uuid,'MARINES',NULL,true,now(),now()), + ('c9b8305d-2e16-46a7-9b7c-b3edeb6f8e93'::uuid,'85b324ae-1a0d-4f7d-971f-ea509dcc73d7'::uuid,'c2a8e8c3-dddc-4c0f-a23a-0b4e2c20af0d'::uuid,'MARINES',NULL,true,now(),now()), + ('a8768e6d-1a6d-449a-9f2e-2e198dcd6e00'::uuid,'85b324ae-1a0d-4f7d-971f-ea509dcc73d7'::uuid,'0f1e1c87-0497-4ee2-970d-21ac2d2155db'::uuid,'MARINES',NULL,true,now(),now()), + ('cf292129-d543-4632-9cb3-b074279e42be'::uuid,'85b324ae-1a0d-4f7d-971f-ea509dcc73d7'::uuid,'e40b411d-55f0-4470-83d0-0bbe11fa77dd'::uuid,'MARINES',NULL,true,now(),now()); +INSERT INTO gbloc_aors (id,jppso_regions_id,oconus_rate_area_id,department_indicator,shipment_type,is_active,created_at,updated_at) VALUES + ('3f07cedf-ad90-465e-95a5-ce44a2f088b8'::uuid,'85b324ae-1a0d-4f7d-971f-ea509dcc73d7'::uuid,'2632b4e5-c6cb-4e64-8924-0b7e4b1115ec'::uuid,'MARINES',NULL,true,now(),now()), + ('42a2d93b-9dea-4c63-b0a7-c39364aacf75'::uuid,'85b324ae-1a0d-4f7d-971f-ea509dcc73d7'::uuid,'1336deb9-5c87-409d-8051-4ab9f211eb29'::uuid,'MARINES',NULL,true,now(),now()), + ('64fe0d14-98f7-4f73-9aa3-a19617b2d8c3'::uuid,'85b324ae-1a0d-4f7d-971f-ea509dcc73d7'::uuid,'7a6d3b5b-81a6-4db5-b2ab-ecbfd6bd7941'::uuid,'MARINES',NULL,true,now(),now()), + ('3ab04740-9f13-47f8-a80e-b63ab5b67590'::uuid,'85b324ae-1a0d-4f7d-971f-ea509dcc73d7'::uuid,'91b69254-5976-4839-a31d-972e9958d9cf'::uuid,'MARINES',NULL,true,now(),now()), + ('3be8e483-6bce-4a7d-a3bd-fc1485e79818'::uuid,'85b324ae-1a0d-4f7d-971f-ea509dcc73d7'::uuid,'166f3629-79b9-451a-90a3-c43680929a2f'::uuid,'MARINES',NULL,true,now(),now()), + ('ddf69dcb-345e-47c1-a585-ce24d0854de5'::uuid,'85b324ae-1a0d-4f7d-971f-ea509dcc73d7'::uuid,'4fe05eb4-1b1c-4d4a-a185-0b039ac64835'::uuid,'MARINES',NULL,true,now(),now()), + ('fe9e365f-98a5-4658-a58d-5f8279ff3e5a'::uuid,'85b324ae-1a0d-4f7d-971f-ea509dcc73d7'::uuid,'ca8aecda-4642-45c7-96ed-309c35c4b78f'::uuid,'MARINES',NULL,true,now(),now()), + ('2051a441-f4d0-4b6e-8614-74761de505e6'::uuid,'85b324ae-1a0d-4f7d-971f-ea509dcc73d7'::uuid,'e4bc9404-5466-4a41-993e-09474266afc3'::uuid,'MARINES',NULL,true,now(),now()), + ('6797daed-f002-431c-829b-dab7c1b16ff2'::uuid,'85b324ae-1a0d-4f7d-971f-ea509dcc73d7'::uuid,'d4a51d90-3945-4ad3-9cba-a18d8d7b34d7'::uuid,'MARINES',NULL,true,now(),now()), + ('2398bf11-1986-4914-8e47-6afac423283a'::uuid,'85b324ae-1a0d-4f7d-971f-ea509dcc73d7'::uuid,'a5a60d63-d9a8-4bde-9081-f011784b2d31'::uuid,'MARINES',NULL,true,now(),now()); +INSERT INTO gbloc_aors (id,jppso_regions_id,oconus_rate_area_id,department_indicator,shipment_type,is_active,created_at,updated_at) VALUES + ('f3a6c247-4c4c-4f45-9162-50307d4711f5'::uuid,'85b324ae-1a0d-4f7d-971f-ea509dcc73d7'::uuid,'93842d74-1f3e-46cd-aca9-9f0dafbd20a1'::uuid,'MARINES',NULL,true,now(),now()), + ('0a82b196-7c24-4214-9155-05f0c5c2d7e9'::uuid,'85b324ae-1a0d-4f7d-971f-ea509dcc73d7'::uuid,'1bc0dbda-f0ce-4b76-a551-78dbaaa9e3ec'::uuid,'MARINES',NULL,true,now(),now()), + ('af0a2db3-2e2e-4a78-804b-9a8b89b96e12'::uuid,'85b324ae-1a0d-4f7d-971f-ea509dcc73d7'::uuid,'f1a7ef90-cfa6-4e0c-92c3-f8d70c07ba4d'::uuid,'MARINES',NULL,true,now(),now()), + ('5205a965-d424-469a-9526-17ef551685e6'::uuid,'85b324ae-1a0d-4f7d-971f-ea509dcc73d7'::uuid,'9c5b4c4d-e05c-42ca-bd77-b61f5d8c7afc'::uuid,'MARINES',NULL,true,now(),now()), + ('f263fdb0-933b-42a7-925e-a9852c5804fa'::uuid,'85b324ae-1a0d-4f7d-971f-ea509dcc73d7'::uuid,'27ec2576-78dd-4605-b1a8-0b9ca207fc26'::uuid,'MARINES',NULL,true,now(),now()), + ('b03c7ae3-4d6d-445c-b94a-73af723e5226'::uuid,'85b324ae-1a0d-4f7d-971f-ea509dcc73d7'::uuid,'12396ebc-59e9-430a-8475-759a38af6b7a'::uuid,'MARINES',NULL,true,now(),now()); + + +drop view move_to_gbloc; +CREATE OR REPLACE VIEW move_to_gbloc AS +SELECT move_id, gbloc FROM ( + SELECT DISTINCT ON (sh.move_id) sh.move_id, s.affiliation, + COALESCE(pctg.gbloc, coalesce(pctg_oconus_bos.gbloc, coalesce(pctg_oconus.gbloc, pctg_ppm.gbloc))) AS gbloc + FROM mto_shipments sh + JOIN moves m ON sh.move_id = m.id + JOIN orders o on m.orders_id = o.id + JOIN service_members s on o.service_member_id = s.id + LEFT JOIN ( SELECT a.id AS address_id, + pctg_1.gbloc, pctg_1.postal_code + FROM addresses a + JOIN postal_code_to_gblocs pctg_1 ON a.postal_code::text = pctg_1.postal_code::text) pctg ON pctg.address_id = sh.pickup_address_id + LEFT JOIN ( SELECT ppm.shipment_id, + pctg_1.gbloc + FROM ppm_shipments ppm + JOIN addresses ppm_address ON ppm.pickup_postal_address_id = ppm_address.id + JOIN postal_code_to_gblocs pctg_1 ON ppm_address.postal_code::text = pctg_1.postal_code::text) pctg_ppm ON pctg_ppm.shipment_id = sh.id + LEFT JOIN ( SELECT a.id AS address_id, + cast(jr.code as varchar) AS gbloc, ga.department_indicator + FROM addresses a + JOIN re_oconus_rate_areas ora ON a.us_post_region_cities_id = ora.us_post_region_cities_id + JOIN gbloc_aors ga ON ora.id = ga.oconus_rate_area_id + JOIN jppso_regions jr ON ga.jppso_regions_id = jr.id + ) pctg_oconus_bos ON pctg_oconus_bos.address_id = sh.pickup_address_id + and case when s.affiliation = 'AIR_FORCE' THEN 'AIR_AND_SPACE_FORCE' + when s.affiliation = 'SPACE_FORCE' THEN 'AIR_AND_SPACE_FORCE' + else s.affiliation + end = pctg_oconus_bos.department_indicator + LEFT JOIN ( SELECT a.id AS address_id, + cast(pctg_1.code as varchar) AS gbloc, ga.department_indicator + FROM addresses a + JOIN re_oconus_rate_areas ora ON a.us_post_region_cities_id = ora.us_post_region_cities_id + JOIN gbloc_aors ga ON ora.id = ga.oconus_rate_area_id + JOIN jppso_regions pctg_1 ON ga.jppso_regions_id = pctg_1.id + ) pctg_oconus ON pctg_oconus.address_id = sh.pickup_address_id and pctg_oconus.department_indicator is null + WHERE sh.deleted_at IS NULL + ORDER BY sh.move_id, sh.created_at) as m; + + +-- used for the destination queue +CREATE OR REPLACE VIEW move_to_dest_gbloc +AS +SELECT distinct move_id, gbloc FROM ( + SELECT sh.move_id, s.affiliation, + COALESCE(case when s.affiliation = 'MARINES' then 'USMC' else pctg.gbloc end, coalesce(pctg_oconus_bos.gbloc, coalesce(pctg_oconus.gbloc, pctg_ppm.gbloc))) AS gbloc + FROM mto_shipments sh + JOIN moves m ON sh.move_id = m.id + JOIN orders o on m.orders_id = o.id + JOIN service_members s on o.service_member_id = s.id + LEFT JOIN ( SELECT a.id AS address_id, + pctg_1.gbloc, pctg_1.postal_code + FROM addresses a + JOIN postal_code_to_gblocs pctg_1 ON a.postal_code::text = pctg_1.postal_code::text) pctg ON pctg.address_id = sh.destination_address_id + LEFT JOIN ( SELECT ppm.shipment_id, + pctg_1.gbloc + FROM ppm_shipments ppm + JOIN addresses ppm_address ON ppm.destination_postal_address_id = ppm_address.id + JOIN postal_code_to_gblocs pctg_1 ON ppm_address.postal_code::text = pctg_1.postal_code::text) pctg_ppm ON pctg_ppm.shipment_id = sh.id + LEFT JOIN ( SELECT a.id AS address_id, + cast(jr.code as varchar) AS gbloc, ga.department_indicator + FROM addresses a + JOIN re_oconus_rate_areas ora ON a.us_post_region_cities_id = ora.us_post_region_cities_id + JOIN gbloc_aors ga ON ora.id = ga.oconus_rate_area_id + JOIN jppso_regions jr ON ga.jppso_regions_id = jr.id + ) pctg_oconus_bos ON pctg_oconus_bos.address_id = sh.destination_address_id + and case when s.affiliation = 'AIR_FORCE' THEN 'AIR_AND_SPACE_FORCE' + when s.affiliation = 'SPACE_FORCE' THEN 'AIR_AND_SPACE_FORCE' + else s.affiliation + end = pctg_oconus_bos.department_indicator + LEFT JOIN ( SELECT a.id AS address_id, + cast(pctg_1.code as varchar) AS gbloc, ga.department_indicator + FROM addresses a + JOIN re_oconus_rate_areas ora ON a.us_post_region_cities_id = ora.us_post_region_cities_id + JOIN gbloc_aors ga ON ora.id = ga.oconus_rate_area_id + JOIN jppso_regions pctg_1 ON ga.jppso_regions_id = pctg_1.id + ) pctg_oconus ON pctg_oconus.address_id = sh.destination_address_id and pctg_oconus.department_indicator is null + WHERE sh.deleted_at IS NULL) as m; + +-- database function that returns a list of moves that have destination requests +-- this includes shipment address update requests, destination SIT, & destination shuttle +CREATE OR REPLACE FUNCTION get_destination_queue( + user_gbloc TEXT DEFAULT NULL, + customer_name TEXT DEFAULT NULL, + edipi TEXT DEFAULT NULL, + emplid TEXT DEFAULT NULL, + m_status TEXT[] DEFAULT NULL, + move_code TEXT DEFAULT NULL, + requested_move_date TIMESTAMP DEFAULT NULL, + date_submitted TIMESTAMP DEFAULT NULL, + branch TEXT DEFAULT NULL, + origin_duty_location TEXT DEFAULT NULL, + counseling_office TEXT DEFAULT NULL, + too_assigned_user TEXT DEFAULT NULL, + page INTEGER DEFAULT 1, + per_page INTEGER DEFAULT 20, + sort TEXT DEFAULT NULL, + sort_direction TEXT DEFAULT NULL +) +RETURNS TABLE ( + id UUID, + show BOOLEAN, + locator TEXT, + submitted_at TIMESTAMP WITH TIME ZONE, + orders_id UUID, + status TEXT, + locked_by UUID, + too_assigned_id UUID, + counseling_transportation_office_id UUID, + orders JSONB, + mto_shipments JSONB, + counseling_transportation_office JSONB, + too_assigned JSONB, + total_count BIGINT +) AS $$ +DECLARE + sql_query TEXT; + offset_value INTEGER; + sort_column TEXT; + sort_order TEXT; +BEGIN + IF page < 1 THEN + page := 1; + END IF; + + IF per_page < 1 THEN + per_page := 20; + END IF; + + -- OFFSET for pagination + offset_value := (page - 1) * per_page; + + sql_query := ' + SELECT + moves.id AS id, + moves.show AS show, + moves.locator::TEXT AS locator, + moves.submitted_at::TIMESTAMP WITH TIME ZONE AS submitted_at, + moves.orders_id AS orders_id, + moves.status::TEXT AS status, + moves.locked_by AS locked_by, + moves.too_assigned_id AS too_assigned_id, + moves.counseling_transportation_office_id AS counseling_transportation_office_id, + json_build_object( + ''id'', orders.id, + ''origin_duty_location_gbloc'', orders.gbloc, + ''service_member'', json_build_object( + ''id'', service_members.id, + ''first_name'', service_members.first_name, + ''last_name'', service_members.last_name, + ''edipi'', service_members.edipi, + ''emplid'', service_members.emplid, + ''affiliation'', service_members.affiliation + ), + ''origin_duty_location'', json_build_object( + ''name'', origin_duty_locations.name + ) + )::JSONB AS orders, + COALESCE( + ( + SELECT json_agg( + json_build_object( + ''id'', ms.id, + ''shipment_type'', ms.shipment_type, + ''status'', ms.status, + ''requested_pickup_date'', TO_CHAR(ms.requested_pickup_date, ''YYYY-MM-DD"T00:00:00Z"''), + ''scheduled_pickup_date'', TO_CHAR(ms.scheduled_pickup_date, ''YYYY-MM-DD"T00:00:00Z"''), + ''approved_date'', TO_CHAR(ms.approved_date, ''YYYY-MM-DD"T00:00:00Z"''), + ''prime_estimated_weight'', ms.prime_estimated_weight + ) + ) + FROM ( + SELECT DISTINCT ON (mto_shipments.id) mto_shipments.* + FROM mto_shipments + WHERE mto_shipments.move_id = moves.id + ) AS ms + ), + ''[]'' + )::JSONB AS mto_shipments, + json_build_object( + ''name'', counseling_offices.name + )::JSONB AS counseling_transportation_office, + json_build_object( + ''first_name'', too_user.first_name, + ''last_name'', too_user.last_name + )::JSONB AS too_assigned, + COUNT(*) OVER() AS total_count + FROM moves + JOIN orders ON moves.orders_id = orders.id + JOIN mto_shipments ON mto_shipments.move_id = moves.id + LEFT JOIN ppm_shipments ON ppm_shipments.shipment_id = mto_shipments.id + JOIN mto_service_items ON mto_shipments.id = mto_service_items.mto_shipment_id + JOIN re_services ON mto_service_items.re_service_id = re_services.id + JOIN service_members ON orders.service_member_id = service_members.id + JOIN duty_locations AS new_duty_locations ON orders.new_duty_location_id = new_duty_locations.id + JOIN duty_locations AS origin_duty_locations ON orders.origin_duty_location_id = origin_duty_locations.id + LEFT JOIN office_users AS too_user ON moves.too_assigned_id = too_user.id + LEFT JOIN office_users AS locked_user ON moves.locked_by = locked_user.id + LEFT JOIN transportation_offices AS counseling_offices + ON moves.counseling_transportation_office_id = counseling_offices.id + LEFT JOIN shipment_address_updates ON shipment_address_updates.shipment_id = mto_shipments.id + JOIN move_to_dest_gbloc ON move_to_dest_gbloc.move_id = moves.id + WHERE moves.show = TRUE + '; + + IF user_gbloc IS NOT NULL THEN + sql_query := sql_query || ' AND move_to_dest_gbloc.gbloc = $1 '; + END IF; + + IF customer_name IS NOT NULL THEN + sql_query := sql_query || ' AND ( + service_members.first_name || '' '' || service_members.last_name ILIKE ''%'' || $2 || ''%'' + OR service_members.last_name || '' '' || service_members.first_name ILIKE ''%'' || $2 || ''%'' + )'; + END IF; + + IF edipi IS NOT NULL THEN + sql_query := sql_query || ' AND service_members.edipi ILIKE ''%'' || $3 || ''%'' '; + END IF; + + IF emplid IS NOT NULL THEN + sql_query := sql_query || ' AND service_members.emplid ILIKE ''%'' || $4 || ''%'' '; + END IF; + + IF m_status IS NOT NULL THEN + sql_query := sql_query || ' AND moves.status = ANY($5) '; + END IF; + + IF move_code IS NOT NULL THEN + sql_query := sql_query || ' AND moves.locator ILIKE ''%'' || $6 || ''%'' '; + END IF; + + IF requested_move_date IS NOT NULL THEN + sql_query := sql_query || ' AND ( + mto_shipments.requested_pickup_date::DATE = $7::DATE + OR ppm_shipments.expected_departure_date::DATE = $7::DATE + OR (mto_shipments.shipment_type = ''HHG_OUTOF_NTS'' AND mto_shipments.requested_delivery_date::DATE = $7::DATE) + )'; + END IF; + + IF date_submitted IS NOT NULL THEN + sql_query := sql_query || ' AND moves.submitted_at::DATE = $8::DATE '; + END IF; + + IF branch IS NOT NULL THEN + sql_query := sql_query || ' AND service_members.affiliation ILIKE ''%'' || $9 || ''%'' '; + END IF; + + IF origin_duty_location IS NOT NULL THEN + sql_query := sql_query || ' AND origin_duty_locations.name ILIKE ''%'' || $10 || ''%'' '; + END IF; + + IF counseling_office IS NOT NULL THEN + sql_query := sql_query || ' AND counseling_offices.name ILIKE ''%'' || $11 || ''%'' '; + END IF; + + IF too_assigned_user IS NOT NULL THEN + sql_query := sql_query || ' AND (too_user.first_name || '' '' || too_user.last_name) ILIKE ''%'' || $12 || ''%'' '; + END IF; + + -- add destination queue-specific filters (pending dest address requests, dest SIT & dest shuttle service items) + sql_query := sql_query || ' + AND ( + shipment_address_updates.status = ''REQUESTED'' + OR ( + mto_service_items.status = ''SUBMITTED'' + AND re_services.code IN (''DDFSIT'', ''DDASIT'', ''DDDSIT'', ''DDSHUT'', ''DDSFSC'', ''IDFSIT'', ''IDASIT'', ''IDDSIT'', ''IDSHUT'') + ) + ) + '; + + -- default sorting values if none are provided (move.id) + sort_column := 'id'; + sort_order := 'ASC'; + + IF sort IS NOT NULL THEN + CASE sort + WHEN 'locator' THEN sort_column := 'moves.locator'; + WHEN 'status' THEN sort_column := 'moves.status'; + WHEN 'customerName' THEN sort_column := 'service_members.last_name'; + WHEN 'edipi' THEN sort_column := 'service_members.edipi'; + WHEN 'emplid' THEN sort_column := 'service_members.emplid'; + WHEN 'requestedMoveDate' THEN sort_column := 'COALESCE(mto_shipments.requested_pickup_date, ppm_shipments.expected_departure_date, mto_shipments.requested_delivery_date)'; + WHEN 'appearedInTooAt' THEN sort_column := 'COALESCE(moves.submitted_at, moves.approvals_requested_at)'; + WHEN 'branch' THEN sort_column := 'service_members.affiliation'; + WHEN 'originDutyLocation' THEN sort_column := 'origin_duty_locations.name'; + WHEN 'counselingOffice' THEN sort_column := 'counseling_offices.name'; + WHEN 'assignedTo' THEN sort_column := 'too_user.last_name'; + ELSE + sort_column := 'moves.id'; + END CASE; + END IF; + + IF sort_direction IS NOT NULL THEN + IF LOWER(sort_direction) = 'desc' THEN + sort_order := 'DESC'; + ELSE + sort_order := 'ASC'; + END IF; + END IF; + + sql_query := sql_query || ' + GROUP BY + moves.id, + moves.show, + moves.locator, + moves.submitted_at, + moves.orders_id, + moves.status, + moves.locked_by, + moves.too_assigned_id, + moves.counseling_transportation_office_id, + mto_shipments.requested_pickup_date, + mto_shipments.requested_delivery_date, + ppm_shipments.expected_departure_date, + orders.id, + service_members.id, + service_members.first_name, + service_members.last_name, + service_members.edipi, + service_members.emplid, + service_members.affiliation, + origin_duty_locations.name, + counseling_offices.name, + too_user.first_name, + too_user.last_name'; + sql_query := sql_query || format(' ORDER BY %s %s ', sort_column, sort_order); + sql_query := sql_query || ' LIMIT $13 OFFSET $14 '; + + RETURN QUERY EXECUTE sql_query + USING user_gbloc, customer_name, edipi, emplid, m_status, move_code, requested_move_date, date_submitted, + branch, origin_duty_location, counseling_office, too_assigned_user, per_page, offset_value; + +END; +$$ LANGUAGE plpgsql; diff --git a/pkg/gen/ghcapi/configure_mymove.go b/pkg/gen/ghcapi/configure_mymove.go index 6000c169aaf..415ee1c890d 100644 --- a/pkg/gen/ghcapi/configure_mymove.go +++ b/pkg/gen/ghcapi/configure_mymove.go @@ -247,6 +247,11 @@ func configureAPI(api *ghcoperations.MymoveAPI) http.Handler { return middleware.NotImplemented("operation customer_support_remarks.GetCustomerSupportRemarksForMove has not yet been implemented") }) } + if api.QueuesGetDestinationRequestsQueueHandler == nil { + api.QueuesGetDestinationRequestsQueueHandler = queues.GetDestinationRequestsQueueHandlerFunc(func(params queues.GetDestinationRequestsQueueParams) middleware.Responder { + return middleware.NotImplemented("operation queues.GetDestinationRequestsQueue has not yet been implemented") + }) + } if api.GhcDocumentsGetDocumentHandler == nil { api.GhcDocumentsGetDocumentHandler = ghc_documents.GetDocumentHandlerFunc(func(params ghc_documents.GetDocumentParams) middleware.Responder { return middleware.NotImplemented("operation ghc_documents.GetDocument has not yet been implemented") diff --git a/pkg/gen/ghcapi/embedded_spec.go b/pkg/gen/ghcapi/embedded_spec.go index b1303da9347..bb69f484f51 100644 --- a/pkg/gen/ghcapi/embedded_spec.go +++ b/pkg/gen/ghcapi/embedded_spec.go @@ -4682,6 +4682,156 @@ func init() { } } }, + "/queues/destination-requests": { + "get": { + "description": "A TOO will view this queue when they have destination requests tied to their GBLOC. This includes unapproved destination SIT service items, destination shuttle service items and destination address requests that are not yet approved by the TOO.\n", + "produces": [ + "application/json" + ], + "tags": [ + "queues" + ], + "summary": "Gets queued list of all customer moves by GBLOC that have both CONUS \u0026 OCONUS destination requests (destination SIT, destination shuttle, address requests)", + "operationId": "getDestinationRequestsQueue", + "parameters": [ + { + "type": "integer", + "description": "requested page of results", + "name": "page", + "in": "query" + }, + { + "type": "integer", + "description": "results per page", + "name": "perPage", + "in": "query" + }, + { + "enum": [ + "customerName", + "edipi", + "emplid", + "branch", + "locator", + "status", + "originDutyLocation", + "destinationDutyLocation", + "requestedMoveDate", + "appearedInTooAt", + "assignedTo", + "counselingOffice" + ], + "type": "string", + "description": "field that results should be sorted by", + "name": "sort", + "in": "query" + }, + { + "enum": [ + "asc", + "desc" + ], + "type": "string", + "description": "direction of sort order if applied", + "name": "order", + "in": "query" + }, + { + "type": "string", + "name": "branch", + "in": "query" + }, + { + "type": "string", + "name": "locator", + "in": "query" + }, + { + "type": "string", + "name": "customerName", + "in": "query" + }, + { + "type": "string", + "name": "edipi", + "in": "query" + }, + { + "type": "string", + "name": "emplid", + "in": "query" + }, + { + "uniqueItems": true, + "type": "array", + "items": { + "type": "string" + }, + "collectionFormat": "multi", + "name": "originDutyLocation", + "in": "query" + }, + { + "type": "string", + "name": "destinationDutyLocation", + "in": "query" + }, + { + "type": "string", + "format": "date-time", + "name": "appearedInTooAt", + "in": "query" + }, + { + "type": "string", + "description": "filters the requested pickup date of a shipment on the move", + "name": "requestedMoveDate", + "in": "query" + }, + { + "uniqueItems": true, + "type": "array", + "items": { + "enum": [ + "SUBMITTED", + "SERVICE COUNSELING COMPLETED", + "APPROVALS REQUESTED" + ], + "type": "string" + }, + "description": "Filtering for the status.", + "name": "status", + "in": "query" + }, + { + "type": "string", + "description": "Used to illustrate which user is assigned to this move.\n", + "name": "assignedTo", + "in": "query" + }, + { + "type": "string", + "description": "filters using a counselingOffice name of the move", + "name": "counselingOffice", + "in": "query" + } + ], + "responses": { + "200": { + "description": "Successfully returned all moves matching the criteria", + "schema": { + "$ref": "#/definitions/QueueMovesResult" + } + }, + "403": { + "$ref": "#/responses/PermissionDenied" + }, + "500": { + "$ref": "#/responses/ServerError" + } + } + } + }, "/queues/moves": { "get": { "description": "An office TOO user will be assigned a transportation office that will determine which moves are displayed in their queue based on the origin duty location. GHC moves will show up here onced they have reached the submitted status sent by the customer and have move task orders, shipments, and service items to approve.\n", @@ -21580,6 +21730,162 @@ func init() { } } }, + "/queues/destination-requests": { + "get": { + "description": "A TOO will view this queue when they have destination requests tied to their GBLOC. This includes unapproved destination SIT service items, destination shuttle service items and destination address requests that are not yet approved by the TOO.\n", + "produces": [ + "application/json" + ], + "tags": [ + "queues" + ], + "summary": "Gets queued list of all customer moves by GBLOC that have both CONUS \u0026 OCONUS destination requests (destination SIT, destination shuttle, address requests)", + "operationId": "getDestinationRequestsQueue", + "parameters": [ + { + "type": "integer", + "description": "requested page of results", + "name": "page", + "in": "query" + }, + { + "type": "integer", + "description": "results per page", + "name": "perPage", + "in": "query" + }, + { + "enum": [ + "customerName", + "edipi", + "emplid", + "branch", + "locator", + "status", + "originDutyLocation", + "destinationDutyLocation", + "requestedMoveDate", + "appearedInTooAt", + "assignedTo", + "counselingOffice" + ], + "type": "string", + "description": "field that results should be sorted by", + "name": "sort", + "in": "query" + }, + { + "enum": [ + "asc", + "desc" + ], + "type": "string", + "description": "direction of sort order if applied", + "name": "order", + "in": "query" + }, + { + "type": "string", + "name": "branch", + "in": "query" + }, + { + "type": "string", + "name": "locator", + "in": "query" + }, + { + "type": "string", + "name": "customerName", + "in": "query" + }, + { + "type": "string", + "name": "edipi", + "in": "query" + }, + { + "type": "string", + "name": "emplid", + "in": "query" + }, + { + "uniqueItems": true, + "type": "array", + "items": { + "type": "string" + }, + "collectionFormat": "multi", + "name": "originDutyLocation", + "in": "query" + }, + { + "type": "string", + "name": "destinationDutyLocation", + "in": "query" + }, + { + "type": "string", + "format": "date-time", + "name": "appearedInTooAt", + "in": "query" + }, + { + "type": "string", + "description": "filters the requested pickup date of a shipment on the move", + "name": "requestedMoveDate", + "in": "query" + }, + { + "uniqueItems": true, + "type": "array", + "items": { + "enum": [ + "SUBMITTED", + "SERVICE COUNSELING COMPLETED", + "APPROVALS REQUESTED" + ], + "type": "string" + }, + "description": "Filtering for the status.", + "name": "status", + "in": "query" + }, + { + "type": "string", + "description": "Used to illustrate which user is assigned to this move.\n", + "name": "assignedTo", + "in": "query" + }, + { + "type": "string", + "description": "filters using a counselingOffice name of the move", + "name": "counselingOffice", + "in": "query" + } + ], + "responses": { + "200": { + "description": "Successfully returned all moves matching the criteria", + "schema": { + "$ref": "#/definitions/QueueMovesResult" + } + }, + "403": { + "description": "The request was denied", + "schema": { + "$ref": "#/definitions/Error" + } + }, + "500": { + "description": "A server error occurred", + "schema": { + "$ref": "#/definitions/Error" + } + } + } + } + }, "/queues/moves": { "get": { "description": "An office TOO user will be assigned a transportation office that will determine which moves are displayed in their queue based on the origin duty location. GHC moves will show up here onced they have reached the submitted status sent by the customer and have move task orders, shipments, and service items to approve.\n", diff --git a/pkg/gen/ghcapi/ghcoperations/mymove_api.go b/pkg/gen/ghcapi/ghcoperations/mymove_api.go index 772eafbd710..c7668464a5d 100644 --- a/pkg/gen/ghcapi/ghcoperations/mymove_api.go +++ b/pkg/gen/ghcapi/ghcoperations/mymove_api.go @@ -176,6 +176,9 @@ func NewMymoveAPI(spec *loads.Document) *MymoveAPI { CustomerSupportRemarksGetCustomerSupportRemarksForMoveHandler: customer_support_remarks.GetCustomerSupportRemarksForMoveHandlerFunc(func(params customer_support_remarks.GetCustomerSupportRemarksForMoveParams) middleware.Responder { return middleware.NotImplemented("operation customer_support_remarks.GetCustomerSupportRemarksForMove has not yet been implemented") }), + QueuesGetDestinationRequestsQueueHandler: queues.GetDestinationRequestsQueueHandlerFunc(func(params queues.GetDestinationRequestsQueueParams) middleware.Responder { + return middleware.NotImplemented("operation queues.GetDestinationRequestsQueue has not yet been implemented") + }), GhcDocumentsGetDocumentHandler: ghc_documents.GetDocumentHandlerFunc(func(params ghc_documents.GetDocumentParams) middleware.Responder { return middleware.NotImplemented("operation ghc_documents.GetDocument has not yet been implemented") }), @@ -517,6 +520,8 @@ type MymoveAPI struct { CustomerGetCustomerHandler customer.GetCustomerHandler // CustomerSupportRemarksGetCustomerSupportRemarksForMoveHandler sets the operation handler for the get customer support remarks for move operation CustomerSupportRemarksGetCustomerSupportRemarksForMoveHandler customer_support_remarks.GetCustomerSupportRemarksForMoveHandler + // QueuesGetDestinationRequestsQueueHandler sets the operation handler for the get destination requests queue operation + QueuesGetDestinationRequestsQueueHandler queues.GetDestinationRequestsQueueHandler // GhcDocumentsGetDocumentHandler sets the operation handler for the get document operation GhcDocumentsGetDocumentHandler ghc_documents.GetDocumentHandler // MoveTaskOrderGetEntitlementsHandler sets the operation handler for the get entitlements operation @@ -855,6 +860,9 @@ func (o *MymoveAPI) Validate() error { if o.CustomerSupportRemarksGetCustomerSupportRemarksForMoveHandler == nil { unregistered = append(unregistered, "customer_support_remarks.GetCustomerSupportRemarksForMoveHandler") } + if o.QueuesGetDestinationRequestsQueueHandler == nil { + unregistered = append(unregistered, "queues.GetDestinationRequestsQueueHandler") + } if o.GhcDocumentsGetDocumentHandler == nil { unregistered = append(unregistered, "ghc_documents.GetDocumentHandler") } @@ -1315,6 +1323,10 @@ func (o *MymoveAPI) initHandlerCache() { if o.handlers["GET"] == nil { o.handlers["GET"] = make(map[string]http.Handler) } + o.handlers["GET"]["/queues/destination-requests"] = queues.NewGetDestinationRequestsQueue(o.context, o.QueuesGetDestinationRequestsQueueHandler) + if o.handlers["GET"] == nil { + o.handlers["GET"] = make(map[string]http.Handler) + } o.handlers["GET"]["/documents/{documentId}"] = ghc_documents.NewGetDocument(o.context, o.GhcDocumentsGetDocumentHandler) if o.handlers["GET"] == nil { o.handlers["GET"] = make(map[string]http.Handler) diff --git a/pkg/gen/ghcapi/ghcoperations/queues/get_destination_requests_queue.go b/pkg/gen/ghcapi/ghcoperations/queues/get_destination_requests_queue.go new file mode 100644 index 00000000000..0bc440cf200 --- /dev/null +++ b/pkg/gen/ghcapi/ghcoperations/queues/get_destination_requests_queue.go @@ -0,0 +1,58 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package queues + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime/middleware" +) + +// GetDestinationRequestsQueueHandlerFunc turns a function with the right signature into a get destination requests queue handler +type GetDestinationRequestsQueueHandlerFunc func(GetDestinationRequestsQueueParams) middleware.Responder + +// Handle executing the request and returning a response +func (fn GetDestinationRequestsQueueHandlerFunc) Handle(params GetDestinationRequestsQueueParams) middleware.Responder { + return fn(params) +} + +// GetDestinationRequestsQueueHandler interface for that can handle valid get destination requests queue params +type GetDestinationRequestsQueueHandler interface { + Handle(GetDestinationRequestsQueueParams) middleware.Responder +} + +// NewGetDestinationRequestsQueue creates a new http.Handler for the get destination requests queue operation +func NewGetDestinationRequestsQueue(ctx *middleware.Context, handler GetDestinationRequestsQueueHandler) *GetDestinationRequestsQueue { + return &GetDestinationRequestsQueue{Context: ctx, Handler: handler} +} + +/* + GetDestinationRequestsQueue swagger:route GET /queues/destination-requests queues getDestinationRequestsQueue + +Gets queued list of all customer moves by GBLOC that have both CONUS & OCONUS destination requests (destination SIT, destination shuttle, address requests) + +A TOO will view this queue when they have destination requests tied to their GBLOC. This includes unapproved destination SIT service items, destination shuttle service items and destination address requests that are not yet approved by the TOO. +*/ +type GetDestinationRequestsQueue struct { + Context *middleware.Context + Handler GetDestinationRequestsQueueHandler +} + +func (o *GetDestinationRequestsQueue) ServeHTTP(rw http.ResponseWriter, r *http.Request) { + route, rCtx, _ := o.Context.RouteInfo(r) + if rCtx != nil { + *r = *rCtx + } + var Params = NewGetDestinationRequestsQueueParams() + if err := o.Context.BindValidRequest(r, route, &Params); err != nil { // bind params + o.Context.Respond(rw, r, route.Produces, route, err) + return + } + + res := o.Handler.Handle(Params) // actually handle the request + o.Context.Respond(rw, r, route.Produces, route, res) + +} diff --git a/pkg/gen/ghcapi/ghcoperations/queues/get_destination_requests_queue_parameters.go b/pkg/gen/ghcapi/ghcoperations/queues/get_destination_requests_queue_parameters.go new file mode 100644 index 00000000000..dac60111a5d --- /dev/null +++ b/pkg/gen/ghcapi/ghcoperations/queues/get_destination_requests_queue_parameters.go @@ -0,0 +1,589 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package queues + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "fmt" + "net/http" + + "github.com/go-openapi/errors" + "github.com/go-openapi/runtime" + "github.com/go-openapi/runtime/middleware" + "github.com/go-openapi/strfmt" + "github.com/go-openapi/swag" + "github.com/go-openapi/validate" +) + +// NewGetDestinationRequestsQueueParams creates a new GetDestinationRequestsQueueParams object +// +// There are no default values defined in the spec. +func NewGetDestinationRequestsQueueParams() GetDestinationRequestsQueueParams { + + return GetDestinationRequestsQueueParams{} +} + +// GetDestinationRequestsQueueParams contains all the bound params for the get destination requests queue operation +// typically these are obtained from a http.Request +// +// swagger:parameters getDestinationRequestsQueue +type GetDestinationRequestsQueueParams struct { + + // HTTP Request Object + HTTPRequest *http.Request `json:"-"` + + /* + In: query + */ + AppearedInTooAt *strfmt.DateTime + /*Used to illustrate which user is assigned to this move. + + In: query + */ + AssignedTo *string + /* + In: query + */ + Branch *string + /*filters using a counselingOffice name of the move + In: query + */ + CounselingOffice *string + /* + In: query + */ + CustomerName *string + /* + In: query + */ + DestinationDutyLocation *string + /* + In: query + */ + Edipi *string + /* + In: query + */ + Emplid *string + /* + In: query + */ + Locator *string + /*direction of sort order if applied + In: query + */ + Order *string + /* + Unique: true + In: query + Collection Format: multi + */ + OriginDutyLocation []string + /*requested page of results + In: query + */ + Page *int64 + /*results per page + In: query + */ + PerPage *int64 + /*filters the requested pickup date of a shipment on the move + In: query + */ + RequestedMoveDate *string + /*field that results should be sorted by + In: query + */ + Sort *string + /*Filtering for the status. + Unique: true + In: query + */ + Status []string +} + +// BindRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface +// for simple values it will use straight method calls. +// +// To ensure default values, the struct must have been initialized with NewGetDestinationRequestsQueueParams() beforehand. +func (o *GetDestinationRequestsQueueParams) BindRequest(r *http.Request, route *middleware.MatchedRoute) error { + var res []error + + o.HTTPRequest = r + + qs := runtime.Values(r.URL.Query()) + + qAppearedInTooAt, qhkAppearedInTooAt, _ := qs.GetOK("appearedInTooAt") + if err := o.bindAppearedInTooAt(qAppearedInTooAt, qhkAppearedInTooAt, route.Formats); err != nil { + res = append(res, err) + } + + qAssignedTo, qhkAssignedTo, _ := qs.GetOK("assignedTo") + if err := o.bindAssignedTo(qAssignedTo, qhkAssignedTo, route.Formats); err != nil { + res = append(res, err) + } + + qBranch, qhkBranch, _ := qs.GetOK("branch") + if err := o.bindBranch(qBranch, qhkBranch, route.Formats); err != nil { + res = append(res, err) + } + + qCounselingOffice, qhkCounselingOffice, _ := qs.GetOK("counselingOffice") + if err := o.bindCounselingOffice(qCounselingOffice, qhkCounselingOffice, route.Formats); err != nil { + res = append(res, err) + } + + qCustomerName, qhkCustomerName, _ := qs.GetOK("customerName") + if err := o.bindCustomerName(qCustomerName, qhkCustomerName, route.Formats); err != nil { + res = append(res, err) + } + + qDestinationDutyLocation, qhkDestinationDutyLocation, _ := qs.GetOK("destinationDutyLocation") + if err := o.bindDestinationDutyLocation(qDestinationDutyLocation, qhkDestinationDutyLocation, route.Formats); err != nil { + res = append(res, err) + } + + qEdipi, qhkEdipi, _ := qs.GetOK("edipi") + if err := o.bindEdipi(qEdipi, qhkEdipi, route.Formats); err != nil { + res = append(res, err) + } + + qEmplid, qhkEmplid, _ := qs.GetOK("emplid") + if err := o.bindEmplid(qEmplid, qhkEmplid, route.Formats); err != nil { + res = append(res, err) + } + + qLocator, qhkLocator, _ := qs.GetOK("locator") + if err := o.bindLocator(qLocator, qhkLocator, route.Formats); err != nil { + res = append(res, err) + } + + qOrder, qhkOrder, _ := qs.GetOK("order") + if err := o.bindOrder(qOrder, qhkOrder, route.Formats); err != nil { + res = append(res, err) + } + + qOriginDutyLocation, qhkOriginDutyLocation, _ := qs.GetOK("originDutyLocation") + if err := o.bindOriginDutyLocation(qOriginDutyLocation, qhkOriginDutyLocation, route.Formats); err != nil { + res = append(res, err) + } + + qPage, qhkPage, _ := qs.GetOK("page") + if err := o.bindPage(qPage, qhkPage, route.Formats); err != nil { + res = append(res, err) + } + + qPerPage, qhkPerPage, _ := qs.GetOK("perPage") + if err := o.bindPerPage(qPerPage, qhkPerPage, route.Formats); err != nil { + res = append(res, err) + } + + qRequestedMoveDate, qhkRequestedMoveDate, _ := qs.GetOK("requestedMoveDate") + if err := o.bindRequestedMoveDate(qRequestedMoveDate, qhkRequestedMoveDate, route.Formats); err != nil { + res = append(res, err) + } + + qSort, qhkSort, _ := qs.GetOK("sort") + if err := o.bindSort(qSort, qhkSort, route.Formats); err != nil { + res = append(res, err) + } + + qStatus, qhkStatus, _ := qs.GetOK("status") + if err := o.bindStatus(qStatus, qhkStatus, route.Formats); err != nil { + res = append(res, err) + } + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +// bindAppearedInTooAt binds and validates parameter AppearedInTooAt from query. +func (o *GetDestinationRequestsQueueParams) bindAppearedInTooAt(rawData []string, hasKey bool, formats strfmt.Registry) error { + var raw string + if len(rawData) > 0 { + raw = rawData[len(rawData)-1] + } + + // Required: false + // AllowEmptyValue: false + + if raw == "" { // empty values pass all other validations + return nil + } + + // Format: date-time + value, err := formats.Parse("date-time", raw) + if err != nil { + return errors.InvalidType("appearedInTooAt", "query", "strfmt.DateTime", raw) + } + o.AppearedInTooAt = (value.(*strfmt.DateTime)) + + if err := o.validateAppearedInTooAt(formats); err != nil { + return err + } + + return nil +} + +// validateAppearedInTooAt carries on validations for parameter AppearedInTooAt +func (o *GetDestinationRequestsQueueParams) validateAppearedInTooAt(formats strfmt.Registry) error { + + if err := validate.FormatOf("appearedInTooAt", "query", "date-time", o.AppearedInTooAt.String(), formats); err != nil { + return err + } + return nil +} + +// bindAssignedTo binds and validates parameter AssignedTo from query. +func (o *GetDestinationRequestsQueueParams) bindAssignedTo(rawData []string, hasKey bool, formats strfmt.Registry) error { + var raw string + if len(rawData) > 0 { + raw = rawData[len(rawData)-1] + } + + // Required: false + // AllowEmptyValue: false + + if raw == "" { // empty values pass all other validations + return nil + } + o.AssignedTo = &raw + + return nil +} + +// bindBranch binds and validates parameter Branch from query. +func (o *GetDestinationRequestsQueueParams) bindBranch(rawData []string, hasKey bool, formats strfmt.Registry) error { + var raw string + if len(rawData) > 0 { + raw = rawData[len(rawData)-1] + } + + // Required: false + // AllowEmptyValue: false + + if raw == "" { // empty values pass all other validations + return nil + } + o.Branch = &raw + + return nil +} + +// bindCounselingOffice binds and validates parameter CounselingOffice from query. +func (o *GetDestinationRequestsQueueParams) bindCounselingOffice(rawData []string, hasKey bool, formats strfmt.Registry) error { + var raw string + if len(rawData) > 0 { + raw = rawData[len(rawData)-1] + } + + // Required: false + // AllowEmptyValue: false + + if raw == "" { // empty values pass all other validations + return nil + } + o.CounselingOffice = &raw + + return nil +} + +// bindCustomerName binds and validates parameter CustomerName from query. +func (o *GetDestinationRequestsQueueParams) bindCustomerName(rawData []string, hasKey bool, formats strfmt.Registry) error { + var raw string + if len(rawData) > 0 { + raw = rawData[len(rawData)-1] + } + + // Required: false + // AllowEmptyValue: false + + if raw == "" { // empty values pass all other validations + return nil + } + o.CustomerName = &raw + + return nil +} + +// bindDestinationDutyLocation binds and validates parameter DestinationDutyLocation from query. +func (o *GetDestinationRequestsQueueParams) bindDestinationDutyLocation(rawData []string, hasKey bool, formats strfmt.Registry) error { + var raw string + if len(rawData) > 0 { + raw = rawData[len(rawData)-1] + } + + // Required: false + // AllowEmptyValue: false + + if raw == "" { // empty values pass all other validations + return nil + } + o.DestinationDutyLocation = &raw + + return nil +} + +// bindEdipi binds and validates parameter Edipi from query. +func (o *GetDestinationRequestsQueueParams) bindEdipi(rawData []string, hasKey bool, formats strfmt.Registry) error { + var raw string + if len(rawData) > 0 { + raw = rawData[len(rawData)-1] + } + + // Required: false + // AllowEmptyValue: false + + if raw == "" { // empty values pass all other validations + return nil + } + o.Edipi = &raw + + return nil +} + +// bindEmplid binds and validates parameter Emplid from query. +func (o *GetDestinationRequestsQueueParams) bindEmplid(rawData []string, hasKey bool, formats strfmt.Registry) error { + var raw string + if len(rawData) > 0 { + raw = rawData[len(rawData)-1] + } + + // Required: false + // AllowEmptyValue: false + + if raw == "" { // empty values pass all other validations + return nil + } + o.Emplid = &raw + + return nil +} + +// bindLocator binds and validates parameter Locator from query. +func (o *GetDestinationRequestsQueueParams) bindLocator(rawData []string, hasKey bool, formats strfmt.Registry) error { + var raw string + if len(rawData) > 0 { + raw = rawData[len(rawData)-1] + } + + // Required: false + // AllowEmptyValue: false + + if raw == "" { // empty values pass all other validations + return nil + } + o.Locator = &raw + + return nil +} + +// bindOrder binds and validates parameter Order from query. +func (o *GetDestinationRequestsQueueParams) bindOrder(rawData []string, hasKey bool, formats strfmt.Registry) error { + var raw string + if len(rawData) > 0 { + raw = rawData[len(rawData)-1] + } + + // Required: false + // AllowEmptyValue: false + + if raw == "" { // empty values pass all other validations + return nil + } + o.Order = &raw + + if err := o.validateOrder(formats); err != nil { + return err + } + + return nil +} + +// validateOrder carries on validations for parameter Order +func (o *GetDestinationRequestsQueueParams) validateOrder(formats strfmt.Registry) error { + + if err := validate.EnumCase("order", "query", *o.Order, []interface{}{"asc", "desc"}, true); err != nil { + return err + } + + return nil +} + +// bindOriginDutyLocation binds and validates array parameter OriginDutyLocation from query. +// +// Arrays are parsed according to CollectionFormat: "multi" (defaults to "csv" when empty). +func (o *GetDestinationRequestsQueueParams) bindOriginDutyLocation(rawData []string, hasKey bool, formats strfmt.Registry) error { + // CollectionFormat: multi + originDutyLocationIC := rawData + if len(originDutyLocationIC) == 0 { + return nil + } + + var originDutyLocationIR []string + for _, originDutyLocationIV := range originDutyLocationIC { + originDutyLocationI := originDutyLocationIV + + originDutyLocationIR = append(originDutyLocationIR, originDutyLocationI) + } + + o.OriginDutyLocation = originDutyLocationIR + if err := o.validateOriginDutyLocation(formats); err != nil { + return err + } + + return nil +} + +// validateOriginDutyLocation carries on validations for parameter OriginDutyLocation +func (o *GetDestinationRequestsQueueParams) validateOriginDutyLocation(formats strfmt.Registry) error { + + // uniqueItems: true + if err := validate.UniqueItems("originDutyLocation", "query", o.OriginDutyLocation); err != nil { + return err + } + return nil +} + +// bindPage binds and validates parameter Page from query. +func (o *GetDestinationRequestsQueueParams) bindPage(rawData []string, hasKey bool, formats strfmt.Registry) error { + var raw string + if len(rawData) > 0 { + raw = rawData[len(rawData)-1] + } + + // Required: false + // AllowEmptyValue: false + + if raw == "" { // empty values pass all other validations + return nil + } + + value, err := swag.ConvertInt64(raw) + if err != nil { + return errors.InvalidType("page", "query", "int64", raw) + } + o.Page = &value + + return nil +} + +// bindPerPage binds and validates parameter PerPage from query. +func (o *GetDestinationRequestsQueueParams) bindPerPage(rawData []string, hasKey bool, formats strfmt.Registry) error { + var raw string + if len(rawData) > 0 { + raw = rawData[len(rawData)-1] + } + + // Required: false + // AllowEmptyValue: false + + if raw == "" { // empty values pass all other validations + return nil + } + + value, err := swag.ConvertInt64(raw) + if err != nil { + return errors.InvalidType("perPage", "query", "int64", raw) + } + o.PerPage = &value + + return nil +} + +// bindRequestedMoveDate binds and validates parameter RequestedMoveDate from query. +func (o *GetDestinationRequestsQueueParams) bindRequestedMoveDate(rawData []string, hasKey bool, formats strfmt.Registry) error { + var raw string + if len(rawData) > 0 { + raw = rawData[len(rawData)-1] + } + + // Required: false + // AllowEmptyValue: false + + if raw == "" { // empty values pass all other validations + return nil + } + o.RequestedMoveDate = &raw + + return nil +} + +// bindSort binds and validates parameter Sort from query. +func (o *GetDestinationRequestsQueueParams) bindSort(rawData []string, hasKey bool, formats strfmt.Registry) error { + var raw string + if len(rawData) > 0 { + raw = rawData[len(rawData)-1] + } + + // Required: false + // AllowEmptyValue: false + + if raw == "" { // empty values pass all other validations + return nil + } + o.Sort = &raw + + if err := o.validateSort(formats); err != nil { + return err + } + + return nil +} + +// validateSort carries on validations for parameter Sort +func (o *GetDestinationRequestsQueueParams) validateSort(formats strfmt.Registry) error { + + if err := validate.EnumCase("sort", "query", *o.Sort, []interface{}{"customerName", "edipi", "emplid", "branch", "locator", "status", "originDutyLocation", "destinationDutyLocation", "requestedMoveDate", "appearedInTooAt", "assignedTo", "counselingOffice"}, true); err != nil { + return err + } + + return nil +} + +// bindStatus binds and validates array parameter Status from query. +// +// Arrays are parsed according to CollectionFormat: "" (defaults to "csv" when empty). +func (o *GetDestinationRequestsQueueParams) bindStatus(rawData []string, hasKey bool, formats strfmt.Registry) error { + var qvStatus string + if len(rawData) > 0 { + qvStatus = rawData[len(rawData)-1] + } + + // CollectionFormat: + statusIC := swag.SplitByFormat(qvStatus, "") + if len(statusIC) == 0 { + return nil + } + + var statusIR []string + for i, statusIV := range statusIC { + statusI := statusIV + + if err := validate.EnumCase(fmt.Sprintf("%s.%v", "status", i), "query", statusI, []interface{}{"SUBMITTED", "SERVICE COUNSELING COMPLETED", "APPROVALS REQUESTED"}, true); err != nil { + return err + } + + statusIR = append(statusIR, statusI) + } + + o.Status = statusIR + if err := o.validateStatus(formats); err != nil { + return err + } + + return nil +} + +// validateStatus carries on validations for parameter Status +func (o *GetDestinationRequestsQueueParams) validateStatus(formats strfmt.Registry) error { + + // uniqueItems: true + if err := validate.UniqueItems("status", "query", o.Status); err != nil { + return err + } + return nil +} diff --git a/pkg/gen/ghcapi/ghcoperations/queues/get_destination_requests_queue_responses.go b/pkg/gen/ghcapi/ghcoperations/queues/get_destination_requests_queue_responses.go new file mode 100644 index 00000000000..ea27ea91263 --- /dev/null +++ b/pkg/gen/ghcapi/ghcoperations/queues/get_destination_requests_queue_responses.go @@ -0,0 +1,149 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package queues + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime" + + "github.com/transcom/mymove/pkg/gen/ghcmessages" +) + +// GetDestinationRequestsQueueOKCode is the HTTP code returned for type GetDestinationRequestsQueueOK +const GetDestinationRequestsQueueOKCode int = 200 + +/* +GetDestinationRequestsQueueOK Successfully returned all moves matching the criteria + +swagger:response getDestinationRequestsQueueOK +*/ +type GetDestinationRequestsQueueOK struct { + + /* + In: Body + */ + Payload *ghcmessages.QueueMovesResult `json:"body,omitempty"` +} + +// NewGetDestinationRequestsQueueOK creates GetDestinationRequestsQueueOK with default headers values +func NewGetDestinationRequestsQueueOK() *GetDestinationRequestsQueueOK { + + return &GetDestinationRequestsQueueOK{} +} + +// WithPayload adds the payload to the get destination requests queue o k response +func (o *GetDestinationRequestsQueueOK) WithPayload(payload *ghcmessages.QueueMovesResult) *GetDestinationRequestsQueueOK { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the get destination requests queue o k response +func (o *GetDestinationRequestsQueueOK) SetPayload(payload *ghcmessages.QueueMovesResult) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *GetDestinationRequestsQueueOK) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(200) + if o.Payload != nil { + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } + } +} + +// GetDestinationRequestsQueueForbiddenCode is the HTTP code returned for type GetDestinationRequestsQueueForbidden +const GetDestinationRequestsQueueForbiddenCode int = 403 + +/* +GetDestinationRequestsQueueForbidden The request was denied + +swagger:response getDestinationRequestsQueueForbidden +*/ +type GetDestinationRequestsQueueForbidden struct { + + /* + In: Body + */ + Payload *ghcmessages.Error `json:"body,omitempty"` +} + +// NewGetDestinationRequestsQueueForbidden creates GetDestinationRequestsQueueForbidden with default headers values +func NewGetDestinationRequestsQueueForbidden() *GetDestinationRequestsQueueForbidden { + + return &GetDestinationRequestsQueueForbidden{} +} + +// WithPayload adds the payload to the get destination requests queue forbidden response +func (o *GetDestinationRequestsQueueForbidden) WithPayload(payload *ghcmessages.Error) *GetDestinationRequestsQueueForbidden { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the get destination requests queue forbidden response +func (o *GetDestinationRequestsQueueForbidden) SetPayload(payload *ghcmessages.Error) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *GetDestinationRequestsQueueForbidden) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(403) + if o.Payload != nil { + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } + } +} + +// GetDestinationRequestsQueueInternalServerErrorCode is the HTTP code returned for type GetDestinationRequestsQueueInternalServerError +const GetDestinationRequestsQueueInternalServerErrorCode int = 500 + +/* +GetDestinationRequestsQueueInternalServerError A server error occurred + +swagger:response getDestinationRequestsQueueInternalServerError +*/ +type GetDestinationRequestsQueueInternalServerError struct { + + /* + In: Body + */ + Payload *ghcmessages.Error `json:"body,omitempty"` +} + +// NewGetDestinationRequestsQueueInternalServerError creates GetDestinationRequestsQueueInternalServerError with default headers values +func NewGetDestinationRequestsQueueInternalServerError() *GetDestinationRequestsQueueInternalServerError { + + return &GetDestinationRequestsQueueInternalServerError{} +} + +// WithPayload adds the payload to the get destination requests queue internal server error response +func (o *GetDestinationRequestsQueueInternalServerError) WithPayload(payload *ghcmessages.Error) *GetDestinationRequestsQueueInternalServerError { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the get destination requests queue internal server error response +func (o *GetDestinationRequestsQueueInternalServerError) SetPayload(payload *ghcmessages.Error) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *GetDestinationRequestsQueueInternalServerError) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(500) + if o.Payload != nil { + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } + } +} diff --git a/pkg/gen/ghcapi/ghcoperations/queues/get_destination_requests_queue_urlbuilder.go b/pkg/gen/ghcapi/ghcoperations/queues/get_destination_requests_queue_urlbuilder.go new file mode 100644 index 00000000000..c8b86e869dc --- /dev/null +++ b/pkg/gen/ghcapi/ghcoperations/queues/get_destination_requests_queue_urlbuilder.go @@ -0,0 +1,256 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package queues + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "errors" + "net/url" + golangswaggerpaths "path" + + "github.com/go-openapi/strfmt" + "github.com/go-openapi/swag" +) + +// GetDestinationRequestsQueueURL generates an URL for the get destination requests queue operation +type GetDestinationRequestsQueueURL struct { + AppearedInTooAt *strfmt.DateTime + AssignedTo *string + Branch *string + CounselingOffice *string + CustomerName *string + DestinationDutyLocation *string + Edipi *string + Emplid *string + Locator *string + Order *string + OriginDutyLocation []string + Page *int64 + PerPage *int64 + RequestedMoveDate *string + Sort *string + Status []string + + _basePath string + // avoid unkeyed usage + _ struct{} +} + +// WithBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *GetDestinationRequestsQueueURL) WithBasePath(bp string) *GetDestinationRequestsQueueURL { + o.SetBasePath(bp) + return o +} + +// SetBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *GetDestinationRequestsQueueURL) SetBasePath(bp string) { + o._basePath = bp +} + +// Build a url path and query string +func (o *GetDestinationRequestsQueueURL) Build() (*url.URL, error) { + var _result url.URL + + var _path = "/queues/destination-requests" + + _basePath := o._basePath + if _basePath == "" { + _basePath = "/ghc/v1" + } + _result.Path = golangswaggerpaths.Join(_basePath, _path) + + qs := make(url.Values) + + var appearedInTooAtQ string + if o.AppearedInTooAt != nil { + appearedInTooAtQ = o.AppearedInTooAt.String() + } + if appearedInTooAtQ != "" { + qs.Set("appearedInTooAt", appearedInTooAtQ) + } + + var assignedToQ string + if o.AssignedTo != nil { + assignedToQ = *o.AssignedTo + } + if assignedToQ != "" { + qs.Set("assignedTo", assignedToQ) + } + + var branchQ string + if o.Branch != nil { + branchQ = *o.Branch + } + if branchQ != "" { + qs.Set("branch", branchQ) + } + + var counselingOfficeQ string + if o.CounselingOffice != nil { + counselingOfficeQ = *o.CounselingOffice + } + if counselingOfficeQ != "" { + qs.Set("counselingOffice", counselingOfficeQ) + } + + var customerNameQ string + if o.CustomerName != nil { + customerNameQ = *o.CustomerName + } + if customerNameQ != "" { + qs.Set("customerName", customerNameQ) + } + + var destinationDutyLocationQ string + if o.DestinationDutyLocation != nil { + destinationDutyLocationQ = *o.DestinationDutyLocation + } + if destinationDutyLocationQ != "" { + qs.Set("destinationDutyLocation", destinationDutyLocationQ) + } + + var edipiQ string + if o.Edipi != nil { + edipiQ = *o.Edipi + } + if edipiQ != "" { + qs.Set("edipi", edipiQ) + } + + var emplidQ string + if o.Emplid != nil { + emplidQ = *o.Emplid + } + if emplidQ != "" { + qs.Set("emplid", emplidQ) + } + + var locatorQ string + if o.Locator != nil { + locatorQ = *o.Locator + } + if locatorQ != "" { + qs.Set("locator", locatorQ) + } + + var orderQ string + if o.Order != nil { + orderQ = *o.Order + } + if orderQ != "" { + qs.Set("order", orderQ) + } + + var originDutyLocationIR []string + for _, originDutyLocationI := range o.OriginDutyLocation { + originDutyLocationIS := originDutyLocationI + if originDutyLocationIS != "" { + originDutyLocationIR = append(originDutyLocationIR, originDutyLocationIS) + } + } + + originDutyLocation := swag.JoinByFormat(originDutyLocationIR, "multi") + + for _, qsv := range originDutyLocation { + qs.Add("originDutyLocation", qsv) + } + + var pageQ string + if o.Page != nil { + pageQ = swag.FormatInt64(*o.Page) + } + if pageQ != "" { + qs.Set("page", pageQ) + } + + var perPageQ string + if o.PerPage != nil { + perPageQ = swag.FormatInt64(*o.PerPage) + } + if perPageQ != "" { + qs.Set("perPage", perPageQ) + } + + var requestedMoveDateQ string + if o.RequestedMoveDate != nil { + requestedMoveDateQ = *o.RequestedMoveDate + } + if requestedMoveDateQ != "" { + qs.Set("requestedMoveDate", requestedMoveDateQ) + } + + var sortQ string + if o.Sort != nil { + sortQ = *o.Sort + } + if sortQ != "" { + qs.Set("sort", sortQ) + } + + var statusIR []string + for _, statusI := range o.Status { + statusIS := statusI + if statusIS != "" { + statusIR = append(statusIR, statusIS) + } + } + + status := swag.JoinByFormat(statusIR, "") + + if len(status) > 0 { + qsv := status[0] + if qsv != "" { + qs.Set("status", qsv) + } + } + + _result.RawQuery = qs.Encode() + + return &_result, nil +} + +// Must is a helper function to panic when the url builder returns an error +func (o *GetDestinationRequestsQueueURL) Must(u *url.URL, err error) *url.URL { + if err != nil { + panic(err) + } + if u == nil { + panic("url can't be nil") + } + return u +} + +// String returns the string representation of the path with query string +func (o *GetDestinationRequestsQueueURL) String() string { + return o.Must(o.Build()).String() +} + +// BuildFull builds a full url with scheme, host, path and query string +func (o *GetDestinationRequestsQueueURL) BuildFull(scheme, host string) (*url.URL, error) { + if scheme == "" { + return nil, errors.New("scheme is required for a full url on GetDestinationRequestsQueueURL") + } + if host == "" { + return nil, errors.New("host is required for a full url on GetDestinationRequestsQueueURL") + } + + base, err := o.Build() + if err != nil { + return nil, err + } + + base.Scheme = scheme + base.Host = host + return base, nil +} + +// StringFull returns the string representation of a complete url +func (o *GetDestinationRequestsQueueURL) StringFull(scheme, host string) string { + return o.Must(o.BuildFull(scheme, host)).String() +} diff --git a/pkg/handlers/ghcapi/api.go b/pkg/handlers/ghcapi/api.go index 696148cba36..e1e9c8a7b75 100644 --- a/pkg/handlers/ghcapi/api.go +++ b/pkg/handlers/ghcapi/api.go @@ -568,6 +568,13 @@ func NewGhcAPIHandler(handlerConfig handlers.HandlerConfig) *ghcops.MymoveAPI { officeusercreator.NewOfficeUserFetcherPop(), } + ghcAPI.QueuesGetDestinationRequestsQueueHandler = GetDestinationRequestsQueueHandler{ + handlerConfig, + order.NewOrderFetcher(waf), + movelocker.NewMoveUnlocker(), + officeusercreator.NewOfficeUserFetcherPop(), + } + ghcAPI.QueuesListPrimeMovesHandler = ListPrimeMovesHandler{ handlerConfig, movetaskorder.NewMoveTaskOrderFetcher(waf), diff --git a/pkg/handlers/ghcapi/internal/payloads/model_to_payload.go b/pkg/handlers/ghcapi/internal/payloads/model_to_payload.go index 845721d0019..7e9e05e90fe 100644 --- a/pkg/handlers/ghcapi/internal/payloads/model_to_payload.go +++ b/pkg/handlers/ghcapi/internal/payloads/model_to_payload.go @@ -54,7 +54,7 @@ func OfficeUser(officeUser *models.OfficeUser) *ghcmessages.LockedOfficeUser { } func AssignedOfficeUser(officeUser *models.OfficeUser) *ghcmessages.AssignedOfficeUser { - if officeUser != nil { + if officeUser != nil && officeUser.FirstName != "" && officeUser.LastName != "" { payload := ghcmessages.AssignedOfficeUser{ OfficeUserID: strfmt.UUID(officeUser.ID.String()), FirstName: officeUser.FirstName, diff --git a/pkg/handlers/ghcapi/queues.go b/pkg/handlers/ghcapi/queues.go index 202e5d3d6a0..4d708d415b4 100644 --- a/pkg/handlers/ghcapi/queues.go +++ b/pkg/handlers/ghcapi/queues.go @@ -183,6 +183,127 @@ func (h GetMovesQueueHandler) Handle(params queues.GetMovesQueueParams) middlewa }) } +// GetDestinationRequestsQueueHandler returns the moves for the TOO queue user via GET /queues/destination-requests +type GetDestinationRequestsQueueHandler struct { + handlers.HandlerConfig + services.OrderFetcher + services.MoveUnlocker + services.OfficeUserFetcherPop +} + +// Handle returns the paginated list of moves with destination requests for a TOO user +func (h GetDestinationRequestsQueueHandler) Handle(params queues.GetDestinationRequestsQueueParams) middleware.Responder { + return h.AuditableAppContextFromRequestWithErrors(params.HTTPRequest, + func(appCtx appcontext.AppContext) (middleware.Responder, error) { + if !appCtx.Session().IsOfficeUser() || + (!appCtx.Session().Roles.HasRole(roles.RoleTypeTOO)) { + forbiddenErr := apperror.NewForbiddenError( + "user is not authenticated with TOO role", + ) + appCtx.Logger().Error(forbiddenErr.Error()) + return queues.NewGetDestinationRequestsQueueForbidden(), forbiddenErr + } + + ListOrderParams := services.ListOrderParams{ + Branch: params.Branch, + Locator: params.Locator, + Edipi: params.Edipi, + Emplid: params.Emplid, + CustomerName: params.CustomerName, + DestinationDutyLocation: params.DestinationDutyLocation, + OriginDutyLocation: params.OriginDutyLocation, + AppearedInTOOAt: handlers.FmtDateTimePtrToPopPtr(params.AppearedInTooAt), + RequestedMoveDate: params.RequestedMoveDate, + Status: params.Status, + Page: params.Page, + PerPage: params.PerPage, + Sort: params.Sort, + Order: params.Order, + TOOAssignedUser: params.AssignedTo, + CounselingOffice: params.CounselingOffice, + } + + // we only care about moves in APPROVALS REQUESTED status + if params.Status == nil { + ListOrderParams.Status = []string{string(models.MoveStatusAPPROVALSREQUESTED)} + } + + // default pagination values + if params.Page == nil { + ListOrderParams.Page = models.Int64Pointer(1) + } + if params.PerPage == nil { + ListOrderParams.PerPage = models.Int64Pointer(20) + } + + moves, count, err := h.OrderFetcher.ListDestinationRequestsOrders( + appCtx, + appCtx.Session().OfficeUserID, + roles.RoleTypeTOO, + &ListOrderParams, + ) + if err != nil { + appCtx.Logger(). + Error("error fetching destinaton queue for office user", zap.Error(err)) + return queues.NewGetDestinationRequestsQueueInternalServerError(), err + } + + var officeUser models.OfficeUser + if appCtx.Session().OfficeUserID != uuid.Nil { + officeUser, err = h.OfficeUserFetcherPop.FetchOfficeUserByID(appCtx, appCtx.Session().OfficeUserID) + if err != nil { + appCtx.Logger().Error("Error retrieving office user", zap.Error(err)) + return queues.NewGetDestinationRequestsQueueInternalServerError(), err + } + } + privileges, err := models.FetchPrivilegesForUser(appCtx.DB(), appCtx.Session().UserID) + if err != nil { + appCtx.Logger().Error("Error retreiving user privileges", zap.Error(err)) + } + officeUser.User.Privileges = privileges + officeUser.User.Roles = appCtx.Session().Roles + + if err != nil { + appCtx.Logger(). + Error("error fetching office users", zap.Error(err)) + return queues.NewGetDestinationRequestsQueueInternalServerError(), err + } + + // if the TOO is accessing the queue, we need to unlock move/moves they have locked + if appCtx.Session().IsOfficeUser() { + officeUserID := appCtx.Session().OfficeUserID + for i, move := range moves { + lockedOfficeUserID := move.LockedByOfficeUserID + if lockedOfficeUserID != nil && *lockedOfficeUserID == officeUserID { + copyOfMove := move + unlockedMove, err := h.UnlockMove(appCtx, ©OfMove, officeUserID) + if err != nil { + return queues.NewGetDestinationRequestsQueueInternalServerError(), err + } + moves[i] = *unlockedMove + } + } + err := h.CheckForLockedMovesAndUnlock(appCtx, officeUserID) + if err != nil { + appCtx.Logger().Error(fmt.Sprintf("failed to unlock moves for office user ID: %s", officeUserID), zap.Error(err)) + } + } + + var activeRole string + officeUsers := models.OfficeUsers{officeUser} + queueMoves := payloads.QueueMoves(moves, officeUsers, nil, officeUser, nil, activeRole) + + result := &ghcmessages.QueueMovesResult{ + Page: *ListOrderParams.Page, + PerPage: *ListOrderParams.PerPage, + TotalCount: int64(count), + QueueMoves: *queueMoves, + } + + return queues.NewGetDestinationRequestsQueueOK().WithPayload(result), nil + }) +} + // ListMovesHandler lists moves with the option to filter since a particular date. Optimized ver. type ListPrimeMovesHandler struct { handlers.HandlerConfig diff --git a/pkg/handlers/ghcapi/queues_test.go b/pkg/handlers/ghcapi/queues_test.go index 6a658d6c2aa..90088cf2ec0 100644 --- a/pkg/handlers/ghcapi/queues_test.go +++ b/pkg/handlers/ghcapi/queues_test.go @@ -2249,3 +2249,144 @@ func (suite *HandlerSuite) TestAvailableOfficeUsers() { }) } + +func (suite *HandlerSuite) TestGetDestinationRequestsQueuesHandler() { + waf := entitlements.NewWeightAllotmentFetcher() + // default GBLOC is KKFA + officeUser := factory.BuildOfficeUserWithRoles(suite.DB(), factory.GetTraitActiveOfficeUser(), []roles.RoleType{roles.RoleTypeTOO}) + officeUser.User.Roles = append(officeUser.User.Roles, roles.Role{ + RoleType: roles.RoleTypeTOO, + }) + + postalCode := "90210" + postalCode2 := "73064" + factory.FetchOrBuildPostalCodeToGBLOC(suite.DB(), "90210", "KKFA") + factory.FetchOrBuildPostalCodeToGBLOC(suite.DB(), "73064", "JEAT") + + // setting up two moves, one we will see and the other we won't + move := factory.BuildAvailableToPrimeMove(suite.DB(), []factory.Customization{ + { + Model: models.Move{ + Status: models.MoveStatusAPPROVALSREQUESTED, + Show: models.BoolPointer(true), + }, + }}, nil) + + destinationAddress := factory.BuildAddress(suite.DB(), []factory.Customization{ + { + Model: models.Address{PostalCode: postalCode}, + }, + }, nil) + shipment := factory.BuildMTOShipment(suite.DB(), []factory.Customization{ + { + Model: models.MTOShipment{ + Status: models.MTOShipmentStatusApproved, + }, + }, + { + Model: move, + LinkOnly: true, + }, + { + Model: destinationAddress, + LinkOnly: true, + }, + }, nil) + + // destination service item in SUBMITTED status + factory.BuildMTOServiceItem(suite.DB(), []factory.Customization{ + { + Model: models.ReService{ + Code: models.ReServiceCodeDDFSIT, + }, + }, + { + Model: move, + LinkOnly: true, + }, + { + Model: shipment, + LinkOnly: true, + }, + { + Model: models.MTOServiceItem{ + Status: models.MTOServiceItemStatusSubmitted, + }, + }, + }, nil) + + move2 := factory.BuildAvailableToPrimeMove(suite.DB(), []factory.Customization{ + { + Model: models.Move{ + Status: models.MoveStatusAPPROVALSREQUESTED, + Show: models.BoolPointer(true), + }, + }}, nil) + + destinationAddress2 := factory.BuildAddress(suite.DB(), []factory.Customization{ + { + Model: models.Address{PostalCode: postalCode2}, + }, + }, nil) + shipment2 := factory.BuildMTOShipment(suite.DB(), []factory.Customization{ + { + Model: models.MTOShipment{ + Status: models.MTOShipmentStatusApproved, + }, + }, + { + Model: move2, + LinkOnly: true, + }, + { + Model: destinationAddress2, + LinkOnly: true, + }, + }, nil) + + // destination shuttle + factory.BuildMTOServiceItem(suite.DB(), []factory.Customization{ + { + Model: models.ReService{ + Code: models.ReServiceCodeDDSHUT, + }, + }, + { + Model: move2, + LinkOnly: true, + }, + { + Model: shipment2, + LinkOnly: true, + }, + { + Model: models.MTOServiceItem{ + Status: models.MTOServiceItemStatusSubmitted, + }, + }, + }, nil) + + request := httptest.NewRequest("GET", "/queues/destination-requests", nil) + request = suite.AuthenticateOfficeRequest(request, officeUser) + params := queues.GetDestinationRequestsQueueParams{ + HTTPRequest: request, + } + handlerConfig := suite.HandlerConfig() + mockUnlocker := movelocker.NewMoveUnlocker() + handler := GetDestinationRequestsQueueHandler{ + handlerConfig, + order.NewOrderFetcher(waf), + mockUnlocker, + officeusercreator.NewOfficeUserFetcherPop(), + } + + response := handler.Handle(params) + suite.IsNotErrResponse(response) + suite.IsType(&queues.GetDestinationRequestsQueueOK{}, response) + payload := response.(*queues.GetDestinationRequestsQueueOK).Payload + + // should only have one move + result := payload.QueueMoves[0] + suite.Len(payload.QueueMoves, 1) + suite.Equal(move.ID.String(), result.ID.String()) +} diff --git a/pkg/models/move.go b/pkg/models/move.go index 236bef5af6b..b740c85c5d0 100644 --- a/pkg/models/move.go +++ b/pkg/models/move.go @@ -71,7 +71,7 @@ type Move struct { PPMType *string `db:"ppm_type"` MTOServiceItems MTOServiceItems `has_many:"mto_service_items" fk_id:"move_id"` PaymentRequests PaymentRequests `has_many:"payment_requests" fk_id:"move_id"` - MTOShipments MTOShipments `has_many:"mto_shipments" fk_id:"move_id"` + MTOShipments MTOShipments `json:"mto_shipments" has_many:"mto_shipments" fk_id:"move_id"` ReferenceID *string `db:"reference_id"` ServiceCounselingCompletedAt *time.Time `db:"service_counseling_completed_at"` PrimeCounselingCompletedAt *time.Time `db:"prime_counseling_completed_at"` @@ -98,11 +98,11 @@ type Move struct { SCAssignedID *uuid.UUID `json:"sc_assigned_id" db:"sc_assigned_id"` SCAssignedUser *OfficeUser `belongs_to:"office_users" fk_id:"sc_assigned_id"` TOOAssignedID *uuid.UUID `json:"too_assigned_id" db:"too_assigned_id"` - TOOAssignedUser *OfficeUser `belongs_to:"office_users" fk_id:"too_assigned_id"` + TOOAssignedUser *OfficeUser `json:"too_assigned" belongs_to:"office_users" fk_id:"too_assigned_id"` TIOAssignedID *uuid.UUID `json:"tio_assigned_id" db:"tio_assigned_id"` TIOAssignedUser *OfficeUser `belongs_to:"office_users" fk_id:"tio_assigned_id"` CounselingOfficeID *uuid.UUID `json:"counseling_transportation_office_id" db:"counseling_transportation_office_id"` - CounselingOffice *TransportationOffice `belongs_to:"transportation_offices" fk_id:"counseling_transportation_office_id"` + CounselingOffice *TransportationOffice `json:"counseling_transportation_office" belongs_to:"transportation_offices" fk_id:"counseling_transportation_office_id"` } type MoveWithEarliestDate struct { diff --git a/pkg/models/mto_shipments.go b/pkg/models/mto_shipments.go index b3c69cb52bb..148f1130e65 100644 --- a/pkg/models/mto_shipments.go +++ b/pkg/models/mto_shipments.go @@ -118,74 +118,74 @@ const ( // MTOShipment is an object representing data for a move task order shipment type MTOShipment struct { - ID uuid.UUID `db:"id"` - MoveTaskOrder Move `belongs_to:"moves" fk_id:"move_id"` - MoveTaskOrderID uuid.UUID `db:"move_id"` - ScheduledPickupDate *time.Time `db:"scheduled_pickup_date"` - RequestedPickupDate *time.Time `db:"requested_pickup_date"` - RequestedDeliveryDate *time.Time `db:"requested_delivery_date"` - ApprovedDate *time.Time `db:"approved_date"` - FirstAvailableDeliveryDate *time.Time `db:"first_available_delivery_date"` - ActualPickupDate *time.Time `db:"actual_pickup_date"` - RequiredDeliveryDate *time.Time `db:"required_delivery_date"` - ScheduledDeliveryDate *time.Time `db:"scheduled_delivery_date"` - ActualDeliveryDate *time.Time `db:"actual_delivery_date"` - CustomerRemarks *string `db:"customer_remarks"` - CounselorRemarks *string `db:"counselor_remarks"` - PickupAddress *Address `belongs_to:"addresses" fk_id:"pickup_address_id"` - PickupAddressID *uuid.UUID `db:"pickup_address_id"` - DestinationAddress *Address `belongs_to:"addresses" fk_id:"destination_address_id"` - DestinationAddressID *uuid.UUID `db:"destination_address_id"` - DestinationType *DestinationType `db:"destination_address_type"` - MTOAgents MTOAgents `has_many:"mto_agents" fk_id:"mto_shipment_id"` - MTOServiceItems MTOServiceItems `has_many:"mto_service_items" fk_id:"mto_shipment_id"` - SecondaryPickupAddress *Address `belongs_to:"addresses" fk_id:"secondary_pickup_address_id"` - SecondaryPickupAddressID *uuid.UUID `db:"secondary_pickup_address_id"` - HasSecondaryPickupAddress *bool `db:"has_secondary_pickup_address"` - SecondaryDeliveryAddress *Address `belongs_to:"addresses" fk_id:"secondary_delivery_address_id"` - SecondaryDeliveryAddressID *uuid.UUID `db:"secondary_delivery_address_id"` - HasSecondaryDeliveryAddress *bool `db:"has_secondary_delivery_address"` - TertiaryPickupAddress *Address `belongs_to:"addresses" fk_id:"tertiary_pickup_address_id"` - TertiaryPickupAddressID *uuid.UUID `db:"tertiary_pickup_address_id"` - HasTertiaryPickupAddress *bool `db:"has_tertiary_pickup_address"` - TertiaryDeliveryAddress *Address `belongs_to:"addresses" fk_id:"tertiary_delivery_address_id"` - TertiaryDeliveryAddressID *uuid.UUID `db:"tertiary_delivery_address_id"` - HasTertiaryDeliveryAddress *bool `db:"has_tertiary_delivery_address"` - SITDaysAllowance *int `db:"sit_days_allowance"` - SITDurationUpdates SITDurationUpdates `has_many:"sit_extensions" fk_id:"mto_shipment_id"` - PrimeEstimatedWeight *unit.Pound `db:"prime_estimated_weight"` - PrimeEstimatedWeightRecordedDate *time.Time `db:"prime_estimated_weight_recorded_date"` - PrimeActualWeight *unit.Pound `db:"prime_actual_weight"` - BillableWeightCap *unit.Pound `db:"billable_weight_cap"` - BillableWeightJustification *string `db:"billable_weight_justification"` - NTSRecordedWeight *unit.Pound `db:"nts_recorded_weight"` - ShipmentType MTOShipmentType `db:"shipment_type"` - Status MTOShipmentStatus `db:"status"` - Diversion bool `db:"diversion"` - DiversionReason *string `db:"diversion_reason"` - DivertedFromShipmentID *uuid.UUID `db:"diverted_from_shipment_id"` - ActualProGearWeight *unit.Pound `db:"actual_pro_gear_weight"` - ActualSpouseProGearWeight *unit.Pound `db:"actual_spouse_pro_gear_weight"` - RejectionReason *string `db:"rejection_reason"` - Distance *unit.Miles `db:"distance"` - Reweigh *Reweigh `has_one:"reweighs" fk_id:"shipment_id"` - UsesExternalVendor bool `db:"uses_external_vendor"` - StorageFacility *StorageFacility `belongs_to:"storage_facilities" fk:"storage_facility_id"` - StorageFacilityID *uuid.UUID `db:"storage_facility_id"` - ServiceOrderNumber *string `db:"service_order_number"` - TACType *LOAType `db:"tac_type"` - SACType *LOAType `db:"sac_type"` - PPMShipment *PPMShipment `has_one:"ppm_shipment" fk_id:"shipment_id"` - BoatShipment *BoatShipment `has_one:"boat_shipment" fk_id:"shipment_id"` - DeliveryAddressUpdate *ShipmentAddressUpdate `has_one:"shipment_address_update" fk_id:"shipment_id"` - CreatedAt time.Time `db:"created_at"` - UpdatedAt time.Time `db:"updated_at"` - DeletedAt *time.Time `db:"deleted_at"` - ShipmentLocator *string `db:"shipment_locator"` - OriginSITAuthEndDate *time.Time `db:"origin_sit_auth_end_date"` - DestinationSITAuthEndDate *time.Time `db:"dest_sit_auth_end_date"` - MobileHome *MobileHome `has_one:"mobile_home" fk_id:"shipment_id"` - MarketCode MarketCode `db:"market_code"` + ID uuid.UUID `json:"id" db:"id"` + MoveTaskOrder Move `json:"move_task_order" belongs_to:"moves" fk_id:"move_id"` + MoveTaskOrderID uuid.UUID `json:"move_task_order_id" db:"move_id"` + ScheduledPickupDate *time.Time `json:"scheduled_pickup_date" db:"scheduled_pickup_date"` + RequestedPickupDate *time.Time `json:"requested_pickup_date" db:"requested_pickup_date"` + RequestedDeliveryDate *time.Time `json:"requested_delivery_date" db:"requested_delivery_date"` + ApprovedDate *time.Time `json:"approved_date" db:"approved_date"` + FirstAvailableDeliveryDate *time.Time `json:"first_available_delivery_date" db:"first_available_delivery_date"` + ActualPickupDate *time.Time `json:"actual_pickup_date" db:"actual_pickup_date"` + RequiredDeliveryDate *time.Time `json:"required_delivery_date" db:"required_delivery_date"` + ScheduledDeliveryDate *time.Time `json:"scheduled_delivery_date" db:"scheduled_delivery_date"` + ActualDeliveryDate *time.Time `json:"actual_delivery_date" db:"actual_delivery_date"` + CustomerRemarks *string `json:"customer_remarks" db:"customer_remarks"` + CounselorRemarks *string `json:"counselor_remarks" db:"counselor_remarks"` + PickupAddress *Address `json:"pickup_address" belongs_to:"addresses" fk_id:"pickup_address_id"` + PickupAddressID *uuid.UUID `json:"pickup_address_id" db:"pickup_address_id"` + DestinationAddress *Address `json:"destination_address" belongs_to:"addresses" fk_id:"destination_address_id"` + DestinationAddressID *uuid.UUID `json:"destination_address_id" db:"destination_address_id"` + DestinationType *DestinationType `json:"destination_type" db:"destination_address_type"` + MTOAgents MTOAgents `json:"mto_agents" has_many:"mto_agents" fk_id:"mto_shipment_id"` + MTOServiceItems MTOServiceItems `json:"mto_service_items" has_many:"mto_service_items" fk_id:"mto_shipment_id"` + SecondaryPickupAddress *Address `json:"secondary_pickup_address" belongs_to:"addresses" fk_id:"secondary_pickup_address_id"` + SecondaryPickupAddressID *uuid.UUID `json:"secondary_pickup_address_id" db:"secondary_pickup_address_id"` + HasSecondaryPickupAddress *bool `json:"has_secondary_pickup_address" db:"has_secondary_pickup_address"` + SecondaryDeliveryAddress *Address `json:"secondary_delivery_address" belongs_to:"addresses" fk_id:"secondary_delivery_address_id"` + SecondaryDeliveryAddressID *uuid.UUID `json:"secondary_delivery_address_id" db:"secondary_delivery_address_id"` + HasSecondaryDeliveryAddress *bool `json:"has_secondary_delivery_address" db:"has_secondary_delivery_address"` + TertiaryPickupAddress *Address `json:"tertiary_pickup_address" belongs_to:"addresses" fk_id:"tertiary_pickup_address_id"` + TertiaryPickupAddressID *uuid.UUID `json:"tertiary_pickup_address_id" db:"tertiary_pickup_address_id"` + HasTertiaryPickupAddress *bool `json:"has_tertiary_pickup_address" db:"has_tertiary_pickup_address"` + TertiaryDeliveryAddress *Address `json:"tertiary_delivery_address" belongs_to:"addresses" fk_id:"tertiary_delivery_address_id"` + TertiaryDeliveryAddressID *uuid.UUID `json:"tertiary_delivery_address_id" db:"tertiary_delivery_address_id"` + HasTertiaryDeliveryAddress *bool `json:"has_tertiary_delivery_address" db:"has_tertiary_delivery_address"` + SITDaysAllowance *int `json:"sit_days_allowance" db:"sit_days_allowance"` + SITDurationUpdates SITDurationUpdates `json:"sit_duration_updates" has_many:"sit_extensions" fk_id:"mto_shipment_id"` + PrimeEstimatedWeight *unit.Pound `json:"prime_estimated_weight" db:"prime_estimated_weight"` + PrimeEstimatedWeightRecordedDate *time.Time `json:"prime_estimated_weight_recorded_date" db:"prime_estimated_weight_recorded_date"` + PrimeActualWeight *unit.Pound `json:"prime_actual_weight" db:"prime_actual_weight"` + BillableWeightCap *unit.Pound `json:"billable_weight_cap" db:"billable_weight_cap"` + BillableWeightJustification *string `json:"billable_weight_justification" db:"billable_weight_justification"` + NTSRecordedWeight *unit.Pound `json:"nts_recorded_weight" db:"nts_recorded_weight"` + ShipmentType MTOShipmentType `json:"shipment_type" db:"shipment_type"` + Status MTOShipmentStatus `json:"status" db:"status"` + Diversion bool `json:"diversion" db:"diversion"` + DiversionReason *string `json:"diversion_reason" db:"diversion_reason"` + DivertedFromShipmentID *uuid.UUID `json:"diverted_from_shipment_id" db:"diverted_from_shipment_id"` + ActualProGearWeight *unit.Pound `json:"actual_pro_gear_weight" db:"actual_pro_gear_weight"` + ActualSpouseProGearWeight *unit.Pound `json:"actual_spouse_pro_gear_weight" db:"actual_spouse_pro_gear_weight"` + RejectionReason *string `json:"rejection_reason" db:"rejection_reason"` + Distance *unit.Miles `json:"distance" db:"distance"` + Reweigh *Reweigh `json:"reweigh" has_one:"reweighs" fk_id:"shipment_id"` + UsesExternalVendor bool `json:"uses_external_vendor" db:"uses_external_vendor"` + StorageFacility *StorageFacility `json:"storage_facility" belongs_to:"storage_facilities" fk:"storage_facility_id"` + StorageFacilityID *uuid.UUID `json:"storage_facility_id" db:"storage_facility_id"` + ServiceOrderNumber *string `json:"service_order_number" db:"service_order_number"` + TACType *LOAType `json:"tac_type" db:"tac_type"` + SACType *LOAType `json:"sac_type" db:"sac_type"` + PPMShipment *PPMShipment `json:"ppm_shipment" has_one:"ppm_shipment" fk_id:"shipment_id"` + BoatShipment *BoatShipment `json:"boat_shipment" has_one:"boat_shipment" fk_id:"shipment_id"` + DeliveryAddressUpdate *ShipmentAddressUpdate `json:"delivery_address_update" has_one:"shipment_address_update" fk_id:"shipment_id"` + CreatedAt time.Time `json:"created_at" db:"created_at"` + UpdatedAt time.Time `json:"updated_at" db:"updated_at"` + DeletedAt *time.Time `json:"deleted_at" db:"deleted_at"` + ShipmentLocator *string `json:"shipment_locator" db:"shipment_locator"` + OriginSITAuthEndDate *time.Time `json:"origin_sit_auth_end_date" db:"origin_sit_auth_end_date"` + DestinationSITAuthEndDate *time.Time `json:"destination_sit_auth_end_date" db:"dest_sit_auth_end_date"` + MobileHome *MobileHome `json:"mobile_home" has_one:"mobile_home" fk_id:"shipment_id"` + MarketCode MarketCode `json:"market_code" db:"market_code"` } // TableName overrides the table name used by Pop. diff --git a/pkg/models/order.go b/pkg/models/order.go index 2b0601f17c7..a9120c9579f 100644 --- a/pkg/models/order.go +++ b/pkg/models/order.go @@ -70,14 +70,14 @@ type Order struct { CreatedAt time.Time `json:"created_at" db:"created_at"` UpdatedAt time.Time `json:"updated_at" db:"updated_at"` ServiceMemberID uuid.UUID `json:"service_member_id" db:"service_member_id"` - ServiceMember ServiceMember `belongs_to:"service_members" fk_id:"service_member_id"` + ServiceMember ServiceMember `json:"service_member" belongs_to:"service_members" fk_id:"service_member_id"` IssueDate time.Time `json:"issue_date" db:"issue_date"` ReportByDate time.Time `json:"report_by_date" db:"report_by_date"` OrdersType internalmessages.OrdersType `json:"orders_type" db:"orders_type"` OrdersTypeDetail *internalmessages.OrdersTypeDetail `json:"orders_type_detail" db:"orders_type_detail"` HasDependents bool `json:"has_dependents" db:"has_dependents"` SpouseHasProGear bool `json:"spouse_has_pro_gear" db:"spouse_has_pro_gear"` - OriginDutyLocation *DutyLocation `belongs_to:"duty_locations" fk_id:"origin_duty_location_id"` + OriginDutyLocation *DutyLocation `json:"origin_duty_location" belongs_to:"duty_locations" fk_id:"origin_duty_location_id"` OriginDutyLocationID *uuid.UUID `json:"origin_duty_location_id" db:"origin_duty_location_id"` NewDutyLocationID uuid.UUID `json:"new_duty_location_id" db:"new_duty_location_id"` NewDutyLocation DutyLocation `belongs_to:"duty_locations" fk_id:"new_duty_location_id"` diff --git a/pkg/services/mocks/OrderFetcher.go b/pkg/services/mocks/OrderFetcher.go index c7eb39d01ce..012df5ccb1b 100644 --- a/pkg/services/mocks/OrderFetcher.go +++ b/pkg/services/mocks/OrderFetcher.go @@ -80,6 +80,43 @@ func (_m *OrderFetcher) ListAllOrderLocations(appCtx appcontext.AppContext, offi return r0, r1 } +// ListDestinationRequestsOrders provides a mock function with given fields: appCtx, officeUserID, role, params +func (_m *OrderFetcher) ListDestinationRequestsOrders(appCtx appcontext.AppContext, officeUserID uuid.UUID, role roles.RoleType, params *services.ListOrderParams) ([]models.Move, int, error) { + ret := _m.Called(appCtx, officeUserID, role, params) + + if len(ret) == 0 { + panic("no return value specified for ListDestinationRequestsOrders") + } + + var r0 []models.Move + var r1 int + var r2 error + if rf, ok := ret.Get(0).(func(appcontext.AppContext, uuid.UUID, roles.RoleType, *services.ListOrderParams) ([]models.Move, int, error)); ok { + return rf(appCtx, officeUserID, role, params) + } + if rf, ok := ret.Get(0).(func(appcontext.AppContext, uuid.UUID, roles.RoleType, *services.ListOrderParams) []models.Move); ok { + r0 = rf(appCtx, officeUserID, role, params) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]models.Move) + } + } + + if rf, ok := ret.Get(1).(func(appcontext.AppContext, uuid.UUID, roles.RoleType, *services.ListOrderParams) int); ok { + r1 = rf(appCtx, officeUserID, role, params) + } else { + r1 = ret.Get(1).(int) + } + + if rf, ok := ret.Get(2).(func(appcontext.AppContext, uuid.UUID, roles.RoleType, *services.ListOrderParams) error); ok { + r2 = rf(appCtx, officeUserID, role, params) + } else { + r2 = ret.Error(2) + } + + return r0, r1, r2 +} + // ListOrders provides a mock function with given fields: appCtx, officeUserID, role, params func (_m *OrderFetcher) ListOrders(appCtx appcontext.AppContext, officeUserID uuid.UUID, role roles.RoleType, params *services.ListOrderParams) ([]models.Move, int, error) { ret := _m.Called(appCtx, officeUserID, role, params) diff --git a/pkg/services/order.go b/pkg/services/order.go index c1bd25d1b84..217f3e069f2 100644 --- a/pkg/services/order.go +++ b/pkg/services/order.go @@ -20,6 +20,7 @@ import ( type OrderFetcher interface { FetchOrder(appCtx appcontext.AppContext, orderID uuid.UUID) (*models.Order, error) ListOrders(appCtx appcontext.AppContext, officeUserID uuid.UUID, role roles.RoleType, params *ListOrderParams) ([]models.Move, int, error) + ListDestinationRequestsOrders(appCtx appcontext.AppContext, officeUserID uuid.UUID, role roles.RoleType, params *ListOrderParams) ([]models.Move, int, error) ListAllOrderLocations(appCtx appcontext.AppContext, officeUserID uuid.UUID, params *ListOrderParams) ([]models.Move, error) } diff --git a/pkg/services/order/order_fetcher.go b/pkg/services/order/order_fetcher.go index 923a4dfe82b..500cdbad41f 100644 --- a/pkg/services/order/order_fetcher.go +++ b/pkg/services/order/order_fetcher.go @@ -2,6 +2,7 @@ package order import ( "database/sql" + "encoding/json" "fmt" "regexp" "strings" @@ -9,6 +10,8 @@ import ( "github.com/gobuffalo/pop/v6" "github.com/gofrs/uuid" + "github.com/jinzhu/copier" + "github.com/lib/pq" "go.uber.org/zap" "github.com/transcom/mymove/pkg/appcontext" @@ -307,7 +310,118 @@ func (f orderFetcher) ListOrders(appCtx appcontext.AppContext, officeUserID uuid return moves, count, nil } -// TODO: Update query to select distinct duty locations +// this is a custom/temporary struct used in the below service object to get destination queue moves +type MoveWithCount struct { + models.Move + OrdersRaw json.RawMessage `json:"orders" db:"orders"` + Orders *models.Order `json:"-"` + MTOShipmentsRaw json.RawMessage `json:"mto_shipments" db:"mto_shipments"` + MTOShipments *models.MTOShipments `json:"-"` + CounselingOfficeRaw json.RawMessage `json:"counseling_transportation_office" db:"counseling_transportation_office"` + CounselingOffice *models.TransportationOffice `json:"-"` + TOOAssignedRaw json.RawMessage `json:"too_assigned" db:"too_assigned"` + TOOAssignedUser *models.OfficeUser `json:"-"` + TotalCount int64 `json:"total_count" db:"total_count"` +} + +type JSONB []byte + +func (j *JSONB) UnmarshalJSON(data []byte) error { + *j = data + return nil +} + +func (f orderFetcher) ListDestinationRequestsOrders(appCtx appcontext.AppContext, officeUserID uuid.UUID, role roles.RoleType, params *services.ListOrderParams) ([]models.Move, int, error) { + var moves []models.Move + var movesWithCount []MoveWithCount + + // getting the office user's GBLOC + gblocFetcher := officeuser.NewOfficeUserGblocFetcher() + officeUserGbloc, gblocErr := gblocFetcher.FetchGblocForOfficeUser(appCtx, officeUserID) + if gblocErr != nil { + return []models.Move{}, 0, gblocErr + } + + // calling the database function with all passed in parameters + err := appCtx.DB().RawQuery("SELECT * FROM get_destination_queue($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16)", + officeUserGbloc, + params.CustomerName, + params.Edipi, + params.Emplid, + pq.Array(params.Status), + params.Locator, + params.RequestedMoveDate, + params.AppearedInTOOAt, + params.Branch, + strings.Join(params.OriginDutyLocation, " "), + params.CounselingOffice, + params.TOOAssignedUser, + params.Page, + params.PerPage, + params.Sort, + params.Order). + All(&movesWithCount) + + if err != nil { + return []models.Move{}, 0, err + } + + // each row is sent back with the total count from the db func, so we will take the value from the first one + var count int64 + if len(movesWithCount) > 0 { + count = movesWithCount[0].TotalCount + } else { + count = 0 + } + + // we have to manually loop through each move and populate the nested objects that the queue uses/needs + for i := range movesWithCount { + // populating Move.Orders struct + var order models.Order + if err := json.Unmarshal(movesWithCount[i].OrdersRaw, &order); err != nil { + return nil, 0, fmt.Errorf("error unmarshaling orders JSON: %w", err) + } + movesWithCount[i].OrdersRaw = nil + movesWithCount[i].Orders = &order + + // populating Move.MTOShipments array + var shipments models.MTOShipments + if err := json.Unmarshal(movesWithCount[i].MTOShipmentsRaw, &shipments); err != nil { + return nil, 0, fmt.Errorf("error unmarshaling shipments JSON: %w", err) + } + movesWithCount[i].MTOShipmentsRaw = nil + movesWithCount[i].MTOShipments = &shipments + + // populating Moves.CounselingOffice struct + var counselingTransportationOffice models.TransportationOffice + if err := json.Unmarshal(movesWithCount[i].CounselingOfficeRaw, &counselingTransportationOffice); err != nil { + return nil, 0, fmt.Errorf("error unmarshaling counseling_transportation_office JSON: %w", err) + } + movesWithCount[i].CounselingOfficeRaw = nil + movesWithCount[i].CounselingOffice = &counselingTransportationOffice + + // populating Moves.TOOAssigned struct + var tooAssigned models.OfficeUser + if err := json.Unmarshal(movesWithCount[i].TOOAssignedRaw, &tooAssigned); err != nil { + return nil, 0, fmt.Errorf("error unmarshaling too_assigned JSON: %w", err) + } + movesWithCount[i].TOOAssignedRaw = nil + movesWithCount[i].TOOAssignedUser = &tooAssigned + } + + // the handler consumes a Move object and NOT the MoveWithCount struct used in this func + // so we have to copy our custom struct into the Move struct + for _, moveWithCount := range movesWithCount { + var move models.Move + if err := copier.Copy(&move, &moveWithCount); err != nil { + return nil, 0, fmt.Errorf("error copying movesWithCount into Moves struct: %w", err) + } + moves = append(moves, move) + } + + return moves, int(count), nil +} + func (f orderFetcher) ListAllOrderLocations(appCtx appcontext.AppContext, officeUserID uuid.UUID, params *services.ListOrderParams) ([]models.Move, error) { var moves []models.Move var err error diff --git a/pkg/services/order/order_fetcher_test.go b/pkg/services/order/order_fetcher_test.go index 57e85401246..f597146e48e 100644 --- a/pkg/services/order/order_fetcher_test.go +++ b/pkg/services/order/order_fetcher_test.go @@ -5,6 +5,7 @@ import ( "time" "github.com/gofrs/uuid" + "github.com/stretchr/testify/mock" "github.com/transcom/mymove/pkg/auth" "github.com/transcom/mymove/pkg/factory" @@ -12,6 +13,7 @@ import ( "github.com/transcom/mymove/pkg/models/roles" "github.com/transcom/mymove/pkg/services" "github.com/transcom/mymove/pkg/services/entitlements" + "github.com/transcom/mymove/pkg/services/mocks" moveservice "github.com/transcom/mymove/pkg/services/move" officeuserservice "github.com/transcom/mymove/pkg/services/office_user" "github.com/transcom/mymove/pkg/testdatagen" @@ -2307,3 +2309,471 @@ func (suite *OrderServiceSuite) TestOriginDutyLocationFilter() { suite.Equal(locationName, string(expectedMoves[0].Orders.OriginDutyLocation.Name)) }) } + +func (suite *OrderServiceSuite) TestListDestinationRequestsOrders() { + army := models.AffiliationARMY + airForce := models.AffiliationAIRFORCE + spaceForce := models.AffiliationSPACEFORCE + usmc := models.AffiliationMARINES + + setupTestData := func(officeUserGBLOC string) (models.OfficeUser, auth.Session) { + + officeUser := factory.BuildOfficeUserWithRoles(suite.DB(), []factory.Customization{ + { + Model: models.TransportationOffice{ + Gbloc: officeUserGBLOC, + }, + }, + }, []roles.RoleType{roles.RoleTypeTOO}) + + factory.FetchOrBuildPostalCodeToGBLOC(suite.DB(), "99501", officeUser.TransportationOffice.Gbloc) + + fetcher := &mocks.OfficeUserGblocFetcher{} + fetcher.On("FetchGblocForOfficeUser", + mock.AnythingOfType("*appcontext.appContext"), + officeUser.ID, + ).Return(officeUserGBLOC, nil) + + session := auth.Session{ + ApplicationName: auth.OfficeApp, + Roles: officeUser.User.Roles, + OfficeUserID: officeUser.ID, + IDToken: "fake_token", + AccessToken: "fakeAccessToken", + } + + return officeUser, session + } + + buildMoveKKFA := func() (models.Move, models.MTOShipment) { + postalCode := "90210" + factory.FetchOrBuildPostalCodeToGBLOC(suite.DB(), "90210", "KKFA") + + // setting up two moves, each with requested destination SIT service items + destinationAddress := factory.BuildAddress(suite.DB(), []factory.Customization{ + { + Model: models.Address{PostalCode: postalCode}, + }, + }, nil) + + move := factory.BuildAvailableToPrimeMove(suite.DB(), []factory.Customization{ + { + Model: models.Move{ + Status: models.MoveStatusAPPROVALSREQUESTED, + Show: models.BoolPointer(true), + }, + }}, nil) + + shipment := factory.BuildMTOShipment(suite.DB(), []factory.Customization{ + { + Model: models.MTOShipment{ + Status: models.MTOShipmentStatusApproved, + }, + }, + { + Model: move, + LinkOnly: true, + }, + { + Model: destinationAddress, + LinkOnly: true, + }, + }, nil) + + return move, shipment + } + + buildMoveZone2AK := func(branch models.ServiceMemberAffiliation) (models.Move, models.MTOShipment) { + // Create a USAF move in Alaska Zone II + // this is a hard coded uuid that is a us_post_region_cities_id within AK Zone II + zone2UUID, err := uuid.FromString("66768964-e0de-41f3-b9be-7ef32e4ae2b4") + suite.FatalNoError(err) + destinationAddress := factory.BuildAddress(suite.DB(), []factory.Customization{ + { + Model: models.Address{ + City: "Anchorage", + State: "AK", + PostalCode: "99501", + UsPostRegionCityID: &zone2UUID, + }, + }, + }, nil) + + // setting up two moves, each with requested destination SIT service items + move := factory.BuildAvailableToPrimeMove(suite.DB(), []factory.Customization{ + { + Model: models.Move{ + Status: models.MoveStatusAPPROVALSREQUESTED, + Show: models.BoolPointer(true), + }, + }, + { + Model: models.ServiceMember{ + Affiliation: &branch, + }, + }, + }, nil) + + shipment := factory.BuildMTOShipment(suite.DB(), []factory.Customization{ + { + Model: models.MTOShipment{ + Status: models.MTOShipmentStatusApproved, + }, + }, + { + Model: move, + LinkOnly: true, + }, + { + Model: destinationAddress, + LinkOnly: true, + }, + }, nil) + + return move, shipment + } + + buildMoveZone4AK := func(branch models.ServiceMemberAffiliation) (models.Move, models.MTOShipment) { + // Create a USAF move in Alaska Zone II + // this is a hard coded uuid that is a us_post_region_cities_id within AK Zone II + zone4UUID, err := uuid.FromString("78a6f230-9a3a-46ed-aa48-2e3decfe70ff") + suite.FatalNoError(err) + destinationAddress := factory.BuildAddress(suite.DB(), []factory.Customization{ + { + Model: models.Address{ + City: "Anchorage", + State: "AK", + PostalCode: "99501", + UsPostRegionCityID: &zone4UUID, + }, + }, + }, nil) + // setting up two moves, each with requested destination SIT service items + move := factory.BuildAvailableToPrimeMove(suite.DB(), []factory.Customization{ + { + Model: models.Move{ + Status: models.MoveStatusAPPROVALSREQUESTED, + Show: models.BoolPointer(true), + }, + }, + { + Model: models.ServiceMember{ + Affiliation: &branch, + }, + }, + }, nil) + + shipment := factory.BuildMTOShipment(suite.DB(), []factory.Customization{ + { + Model: models.MTOShipment{ + Status: models.MTOShipmentStatusApproved, + }, + }, + { + Model: move, + LinkOnly: true, + }, + { + Model: destinationAddress, + LinkOnly: true, + }, + }, nil) + + return move, shipment + } + + waf := entitlements.NewWeightAllotmentFetcher() + orderFetcher := NewOrderFetcher(waf) + + suite.Run("returns moves for KKFA GBLOC when destination address is in KKFA GBLOC", func() { + officeUser, session := setupTestData("KKFA") + // setting up two moves, each with requested destination SIT service items + move, shipment := buildMoveKKFA() + + // destination service item in SUBMITTED status + factory.BuildMTOServiceItem(suite.DB(), []factory.Customization{ + { + Model: models.ReService{ + Code: models.ReServiceCodeDDFSIT, + }, + }, + { + Model: move, + LinkOnly: true, + }, + { + Model: shipment, + LinkOnly: true, + }, + { + Model: models.MTOServiceItem{ + Status: models.MTOServiceItemStatusSubmitted, + }, + }, + }, nil) + + move2, shipment2 := buildMoveKKFA() + + // destination shuttle + factory.BuildMTOServiceItem(suite.DB(), []factory.Customization{ + { + Model: models.ReService{ + Code: models.ReServiceCodeDDSHUT, + }, + }, + { + Model: move2, + LinkOnly: true, + }, + { + Model: shipment2, + LinkOnly: true, + }, + { + Model: models.MTOServiceItem{ + Status: models.MTOServiceItemStatusSubmitted, + }, + }, + }, nil) + + move3, shipment3 := buildMoveKKFA() + factory.BuildMTOServiceItem(suite.DB(), []factory.Customization{ + { + Model: models.ReService{ + Code: models.ReServiceCodeMS, + }, + }, + { + Model: move3, + LinkOnly: true, + }, + { + Model: shipment3, + LinkOnly: true, + }, + { + Model: models.MTOServiceItem{ + Status: models.MTOServiceItemStatusApproved, + }, + }, + }, nil) + factory.BuildShipmentAddressUpdate(suite.DB(), []factory.Customization{ + { + Model: shipment3, + LinkOnly: true, + }, + { + Model: move3, + LinkOnly: true, + }, + }, []factory.Trait{factory.GetTraitShipmentAddressUpdateRequested}) + + moves, moveCount, err := orderFetcher.ListDestinationRequestsOrders( + suite.AppContextWithSessionForTest(&session), officeUser.ID, roles.RoleTypeTOO, &services.ListOrderParams{}, + ) + + suite.FatalNoError(err) + suite.Equal(3, moveCount) + suite.Len(moves, 3) + }) + + suite.Run("returns moves for MBFL GBLOC including USAF/SF in Alaska Zone II", func() { + officeUser, session := setupTestData("MBFL") + + // setting up two moves, each with requested destination SIT service items + // a move associated with an air force customer containing AK Zone II shipment + move, shipment := buildMoveZone2AK(airForce) + + // destination service item in SUBMITTED status + factory.BuildMTOServiceItem(suite.DB(), []factory.Customization{ + { + Model: models.ReService{ + Code: models.ReServiceCodeDDFSIT, + }, + }, + { + Model: move, + LinkOnly: true, + }, + { + Model: shipment, + LinkOnly: true, + }, + { + Model: models.MTOServiceItem{ + Status: models.MTOServiceItemStatusSubmitted, + }, + }, + }, nil) + + // Create a move outside Alaska Zone II (Zone IV in this case) + move2, shipment2 := buildMoveZone4AK(spaceForce) + + // destination service item in SUBMITTED status + factory.BuildMTOServiceItem(suite.DB(), []factory.Customization{ + { + Model: models.ReService{ + Code: models.ReServiceCodeDDFSIT, + }, + }, + { + Model: move2, + LinkOnly: true, + }, + { + Model: shipment2, + LinkOnly: true, + }, + { + Model: models.MTOServiceItem{ + Status: models.MTOServiceItemStatusSubmitted, + }, + }, + }, nil) + + params := services.ListOrderParams{Status: []string{string(models.MoveStatusAPPROVALSREQUESTED)}} + moves, moveCount, err := orderFetcher.ListDestinationRequestsOrders( + suite.AppContextWithSessionForTest(&session), officeUser.ID, roles.RoleTypeTOO, ¶ms, + ) + + // we should get both moves back because one is in Zone II & the other is within the postal code GBLOC + suite.FatalNoError(err) + suite.Equal(2, moveCount) + suite.Len(moves, 2) + }) + + suite.Run("returns moves for JEAT GBLOC excluding USAF/SF in Alaska Zone II", func() { + officeUser, session := setupTestData("JEAT") + + // Create a move in Zone II, but not an air force or space force service member + move, shipment := buildMoveZone4AK(army) + + // destination service item in SUBMITTED status + factory.BuildMTOServiceItem(suite.DB(), []factory.Customization{ + { + Model: models.ReService{ + Code: models.ReServiceCodeDDFSIT, + }, + }, + { + Model: move, + LinkOnly: true, + }, + { + Model: shipment, + LinkOnly: true, + }, + { + Model: models.MTOServiceItem{ + Status: models.MTOServiceItemStatusSubmitted, + }, + }, + }, nil) + + moves, moveCount, err := orderFetcher.ListDestinationRequestsOrders( + suite.AppContextWithSessionForTest(&session), officeUser.ID, roles.RoleTypeTOO, &services.ListOrderParams{}, + ) + + suite.FatalNoError(err) + suite.Equal(1, moveCount) + suite.Len(moves, 1) + }) + + suite.Run("returns moves for USMC GBLOC when moves belong to USMC servicemembers", func() { + officeUser, session := setupTestData("USMC") + + // setting up two moves, each with requested destination SIT service items + // both will be USMC moves, one in Zone II AK and the other not + move, shipment := buildMoveZone2AK(usmc) + + // destination service item in SUBMITTED status + factory.BuildMTOServiceItem(suite.DB(), []factory.Customization{ + { + Model: models.ReService{ + Code: models.ReServiceCodeDDFSIT, + }, + }, + { + Model: move, + LinkOnly: true, + }, + { + Model: shipment, + LinkOnly: true, + }, + { + Model: models.MTOServiceItem{ + Status: models.MTOServiceItemStatusSubmitted, + }, + }, + }, nil) + + // this one won't be in Zone II + move2, shipment2 := buildMoveZone4AK(usmc) + + // destination shuttle + factory.BuildMTOServiceItem(suite.DB(), []factory.Customization{ + { + Model: models.ReService{ + Code: models.ReServiceCodeDDSHUT, + }, + }, + { + Model: move2, + LinkOnly: true, + }, + { + Model: shipment2, + LinkOnly: true, + }, + { + Model: models.MTOServiceItem{ + Status: models.MTOServiceItemStatusSubmitted, + }, + }, + }, nil) + + move3, shipment3 := buildMoveZone4AK(usmc) + // we need to create a service item and attach it to the move/shipment + // else the query will exclude the move since it doesn't use LEFT JOINs + factory.BuildMTOServiceItem(suite.DB(), []factory.Customization{ + { + Model: models.ReService{ + Code: models.ReServiceCodeMS, + }, + }, + { + Model: move3, + LinkOnly: true, + }, + { + Model: shipment3, + LinkOnly: true, + }, + { + Model: models.MTOServiceItem{ + Status: models.MTOServiceItemStatusApproved, + }, + }, + }, nil) + factory.BuildShipmentAddressUpdate(suite.DB(), []factory.Customization{ + { + Model: shipment3, + LinkOnly: true, + }, + { + Model: move3, + LinkOnly: true, + }, + }, []factory.Trait{factory.GetTraitShipmentAddressUpdateRequested}) + + moves, moveCount, err := orderFetcher.ListDestinationRequestsOrders( + suite.AppContextWithSessionForTest(&session), officeUser.ID, roles.RoleTypeTOO, &services.ListOrderParams{}, + ) + + // we should get three moves back since they're USMC moves and zone doesn't matter + suite.FatalNoError(err) + suite.Equal(3, moveCount) + suite.Len(moves, 3) + }) +} diff --git a/src/constants/routes.js b/src/constants/routes.js index 1c4121aef59..a018cef31ea 100644 --- a/src/constants/routes.js +++ b/src/constants/routes.js @@ -4,8 +4,8 @@ export const generalRoutes = { REQUEST_ACCOUNT: '/request-account', PRIVACY_SECURITY_POLICY_PATH: '/privacy-and-security-policy', ACCESSIBILITY_PATH: '/accessibility', - QUEUE_SEARCH_PATH: 'Search', - BASE_QUEUE_SEARCH_PATH: '/Search', + QUEUE_SEARCH_PATH: 'search', + BASE_QUEUE_SEARCH_PATH: '/search', }; export const customerRoutes = { @@ -120,6 +120,8 @@ export const tooRoutes = { BASE_SHIPMENT_EDIT_PATH: `${BASE_MOVES_PATH}/shipments/:shipmentId`, MOVE_QUEUE: `move-queue`, BASE_MOVE_QUEUE: `/move-queue`, + BASE_DESTINATION_REQUESTS_QUEUE: `/destination-requests`, + DESTINATION_REQUESTS_QUEUE: `destination-requests`, SHIPMENT_EDIT_PATH: 'shipments/:shipmentId', BASE_MOVE_VIEW_PATH: `${BASE_MOVES_PATH}/details`, MOVE_VIEW_PATH: 'details', diff --git a/src/hooks/queries.js b/src/hooks/queries.js index 17ccfe30f5a..1129a3e7901 100644 --- a/src/hooks/queries.js +++ b/src/hooks/queries.js @@ -34,6 +34,7 @@ import { getPPMActualWeight, searchCustomers, getGBLOCs, + getDestinationRequestsQueue, getBulkAssignmentData, } from 'services/ghcApi'; import { getLoggedInUserQueries } from 'services/internalApi'; @@ -587,6 +588,28 @@ export const useMovesQueueQueries = ({ }; }; +export const useDestinationRequestsQueueQueries = ({ + sort, + order, + filters = [], + currentPage = PAGINATION_PAGE_DEFAULT, + currentPageSize = PAGINATION_PAGE_SIZE_DEFAULT, + viewAsGBLOC, +}) => { + const { data = {}, ...movesQueueQuery } = useQuery( + [MOVES_QUEUE, { sort, order, filters, currentPage, currentPageSize, viewAsGBLOC }], + ({ queryKey }) => getDestinationRequestsQueue(...queryKey), + ); + const { isLoading, isError, isSuccess } = movesQueueQuery; + const { queueMoves, ...dataProps } = data; + return { + queueResult: { data: queueMoves, ...dataProps }, + isLoading, + isError, + isSuccess, + }; +}; + export const useServicesCounselingQueuePPMQueries = ({ sort, order, diff --git a/src/pages/Office/MoveQueue/MoveQueue.jsx b/src/pages/Office/MoveQueue/MoveQueue.jsx index 8ad9e2a252f..e1cfdff3f35 100644 --- a/src/pages/Office/MoveQueue/MoveQueue.jsx +++ b/src/pages/Office/MoveQueue/MoveQueue.jsx @@ -6,8 +6,13 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import styles from './MoveQueue.module.scss'; import { createHeader } from 'components/Table/utils'; -import { useMovesQueueQueries, useUserQueries, useMoveSearchQueries } from 'hooks/queries'; -import { getMovesQueue } from 'services/ghcApi'; +import { + useMovesQueueQueries, + useUserQueries, + useMoveSearchQueries, + useDestinationRequestsQueueQueries, +} from 'hooks/queries'; +import { getDestinationRequestsQueue, getMovesQueue } from 'services/ghcApi'; import { formatDateFromIso, serviceMemberAgencyLabel } from 'utils/formatters'; import MultiSelectCheckBoxFilter from 'components/Table/Filters/MultiSelectCheckBoxFilter'; import SelectFilter from 'components/Table/Filters/SelectFilter'; @@ -274,6 +279,15 @@ const MoveQueue = ({ isQueueManagementFFEnabled, userPrivileges, isBulkAssignmen Task Order Queue , + (isActive ? 'usa-current' : '')} + to={tooRoutes.BASE_DESTINATION_REQUESTS_QUEUE} + > + + Destination Requests Queue + + , (isActive ? 'usa-current' : '')} @@ -344,6 +358,32 @@ const MoveQueue = ({ isQueueManagementFFEnabled, userPrivileges, isBulkAssignmen ); } + if (queueType === tooRoutes.DESTINATION_REQUESTS_QUEUE) { + return ( +
+ {renderNavBar()} + +
+ ); + } return ; }; diff --git a/src/pages/Office/MoveQueue/MoveQueue.test.jsx b/src/pages/Office/MoveQueue/MoveQueue.test.jsx index 468018c37fc..9779f03f75a 100644 --- a/src/pages/Office/MoveQueue/MoveQueue.test.jsx +++ b/src/pages/Office/MoveQueue/MoveQueue.test.jsx @@ -353,7 +353,7 @@ describe('MoveQueue', () => { wrapper.update(); expect(wrapper.find('[data-testid="multi-value-container"]').text()).toEqual('New move'); }); - it('renders Search and Move Queue tabs', () => { + it('renders Search, Destination Queue and Move Queue tabs', () => { reactRouterDom.useParams.mockReturnValue({ queueType: generalRoutes.QUEUE_SEARCH_PATH }); render( @@ -363,6 +363,7 @@ describe('MoveQueue', () => { expect(screen.getByTestId('closeout-tab-link')).toBeInTheDocument(); expect(screen.getByTestId('search-tab-link')).toBeInTheDocument(); expect(screen.getByText('Task Order Queue', { selector: 'span' })).toBeInTheDocument(); + expect(screen.getByText('Destination Requests Queue', { selector: 'span' })).toBeInTheDocument(); expect(screen.getByText('Search', { selector: 'span' })).toBeInTheDocument(); }); it('renders TableQueue when Search tab is selected', () => { diff --git a/src/pages/Office/ServicesCounselingQueue/ServicesCounselingQueue.jsx b/src/pages/Office/ServicesCounselingQueue/ServicesCounselingQueue.jsx index 3ea15da0f27..be1c4ec9e4c 100644 --- a/src/pages/Office/ServicesCounselingQueue/ServicesCounselingQueue.jsx +++ b/src/pages/Office/ServicesCounselingQueue/ServicesCounselingQueue.jsx @@ -615,7 +615,7 @@ const ServicesCounselingQueue = ({ return ; }; - if (queueType === 'Search') { + if (queueType === generalRoutes.QUEUE_SEARCH_PATH) { return (
{renderNavBar()} diff --git a/src/services/ghcApi.js b/src/services/ghcApi.js index b05441939fc..c600b531a72 100644 --- a/src/services/ghcApi.js +++ b/src/services/ghcApi.js @@ -643,6 +643,22 @@ export async function getMovesQueue( ); } +export async function getDestinationRequestsQueue( + key, + { sort, order, filters = [], currentPage = 1, currentPageSize = 20, viewAsGBLOC }, +) { + const operationPath = 'queues.getDestinationRequestsQueue'; + const paramFilters = {}; + filters.forEach((filter) => { + paramFilters[`${filter.id}`] = filter.value; + }); + return makeGHCRequest( + operationPath, + { sort, order, page: currentPage, perPage: currentPageSize, viewAsGBLOC, ...paramFilters }, + { schemaKey: 'queueMovesResult', normalize: false }, + ); +} + export async function getServicesCounselingQueue( key, { diff --git a/swagger-def/ghc.yaml b/swagger-def/ghc.yaml index abb47f8b06f..faf1e7b44af 100644 --- a/swagger-def/ghc.yaml +++ b/swagger-def/ghc.yaml @@ -3784,11 +3784,116 @@ paths: "200": description: Successfully returned all moves matching the criteria schema: - $ref: "#/definitions/QueueMovesResult" - "403": - $ref: "#/responses/PermissionDenied" - "500": - $ref: "#/responses/ServerError" + $ref: '#/definitions/QueueMovesResult' + '403': + $ref: '#/responses/PermissionDenied' + '500': + $ref: '#/responses/ServerError' + /queues/destination-requests: + get: + produces: + - application/json + summary: Gets queued list of all customer moves by GBLOC that have both CONUS & OCONUS destination requests (destination SIT, destination shuttle, address requests) + description: > + A TOO will view this queue when they have destination requests tied to their GBLOC. This includes unapproved destination SIT service items, destination shuttle service items and destination address requests that are not yet approved by the TOO. + operationId: getDestinationRequestsQueue + tags: + - queues + parameters: + - in: query + name: page + type: integer + description: requested page of results + - in: query + name: perPage + type: integer + description: results per page + - in: query + name: sort + type: string + enum: + [ + customerName, + edipi, + emplid, + branch, + locator, + status, + originDutyLocation, + destinationDutyLocation, + requestedMoveDate, + appearedInTooAt, + assignedTo, + counselingOffice, + ] + description: field that results should be sorted by + - in: query + name: order + type: string + enum: [asc, desc] + description: direction of sort order if applied + - in: query + name: branch + type: string + - in: query + name: locator + type: string + - in: query + name: customerName + type: string + - in: query + name: edipi + type: string + - in: query + name: emplid + type: string + - in: query + name: originDutyLocation + type: array + uniqueItems: true + collectionFormat: multi + items: + type: string + - in: query + name: destinationDutyLocation + type: string + - in: query + name: appearedInTooAt + type: string + format: date-time + - in: query + name: requestedMoveDate + type: string + description: filters the requested pickup date of a shipment on the move + - in: query + name: status + type: array + description: Filtering for the status. + uniqueItems: true + items: + type: string + enum: + - SUBMITTED + - SERVICE COUNSELING COMPLETED + - APPROVALS REQUESTED + - in: query + name: assignedTo + type: string + description: | + Used to illustrate which user is assigned to this move. + - in: query + name: counselingOffice + type: string + description: filters using a counselingOffice name of the move + responses: + '200': + description: Successfully returned all moves matching the criteria + schema: + $ref: '#/definitions/QueueMovesResult' + '403': + $ref: '#/responses/PermissionDenied' + '500': + $ref: '#/responses/ServerError' /queues/payment-requests: get: produces: diff --git a/swagger/ghc.yaml b/swagger/ghc.yaml index 870a8832ffe..e6b1d27b36e 100644 --- a/swagger/ghc.yaml +++ b/swagger/ghc.yaml @@ -3947,6 +3947,117 @@ paths: $ref: '#/responses/PermissionDenied' '500': $ref: '#/responses/ServerError' + /queues/destination-requests: + get: + produces: + - application/json + summary: >- + Gets queued list of all customer moves by GBLOC that have both CONUS & + OCONUS destination requests (destination SIT, destination shuttle, + address requests) + description: > + A TOO will view this queue when they have destination requests tied to + their GBLOC. This includes unapproved destination SIT service items, + destination shuttle service items and destination address requests that + are not yet approved by the TOO. + operationId: getDestinationRequestsQueue + tags: + - queues + parameters: + - in: query + name: page + type: integer + description: requested page of results + - in: query + name: perPage + type: integer + description: results per page + - in: query + name: sort + type: string + enum: + - customerName + - edipi + - emplid + - branch + - locator + - status + - originDutyLocation + - destinationDutyLocation + - requestedMoveDate + - appearedInTooAt + - assignedTo + - counselingOffice + description: field that results should be sorted by + - in: query + name: order + type: string + enum: + - asc + - desc + description: direction of sort order if applied + - in: query + name: branch + type: string + - in: query + name: locator + type: string + - in: query + name: customerName + type: string + - in: query + name: edipi + type: string + - in: query + name: emplid + type: string + - in: query + name: originDutyLocation + type: array + uniqueItems: true + collectionFormat: multi + items: + type: string + - in: query + name: destinationDutyLocation + type: string + - in: query + name: appearedInTooAt + type: string + format: date-time + - in: query + name: requestedMoveDate + type: string + description: filters the requested pickup date of a shipment on the move + - in: query + name: status + type: array + description: Filtering for the status. + uniqueItems: true + items: + type: string + enum: + - SUBMITTED + - SERVICE COUNSELING COMPLETED + - APPROVALS REQUESTED + - in: query + name: assignedTo + type: string + description: | + Used to illustrate which user is assigned to this move. + - in: query + name: counselingOffice + type: string + description: filters using a counselingOffice name of the move + responses: + '200': + description: Successfully returned all moves matching the criteria + schema: + $ref: '#/definitions/QueueMovesResult' + '403': + $ref: '#/responses/PermissionDenied' + '500': + $ref: '#/responses/ServerError' /queues/payment-requests: get: produces: