Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

B-21583 - update code to calculate gbloc for AK #14388

Draft
wants to merge 32 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
0126a2c
save gbloc on create for AK
pambecker Dec 12, 2024
ecab38d
Merge branch 'main' into B-21583-gbloc-AK-moves
pambecker Dec 12, 2024
a58f510
update data
pambecker Dec 13, 2024
6aefaf9
more updates per Beth G
pambecker Dec 13, 2024
3e9a48d
Merge branch 'main' into B-21583-gbloc-AK-moves
pambecker Dec 13, 2024
2b476fc
Merge branch 'main' into B-21583-gbloc-AK-moves
pambecker Dec 16, 2024
6dfa28a
tests
pambecker Dec 17, 2024
a42308d
SC update orders fix
pambecker Dec 18, 2024
9aa6b88
sql update
pambecker Dec 18, 2024
5ff57a8
Merge branch 'main' into B-21583-gbloc-AK-moves
pambecker Dec 19, 2024
b96a3c0
test
pambecker Dec 20, 2024
c9df020
tests updates
pambecker Dec 20, 2024
5d2989f
fix tests
pambecker Dec 20, 2024
b619d68
adding alias
pambecker Dec 23, 2024
350876c
cleanup
pambecker Dec 23, 2024
780d6b1
test
pambecker Dec 24, 2024
062c39b
adding tests
pambecker Dec 24, 2024
74604f5
Merge branch 'main' into B-21583-gbloc-AK-moves
pambecker Dec 24, 2024
bc51368
Merge branch 'main' into B-21583-gbloc-AK-moves
pambecker Dec 24, 2024
a73907b
test cleanup
pambecker Dec 27, 2024
4d92ece
Merge branch 'main' into B-21583-gbloc-AK-moves
pambecker Dec 27, 2024
1dad5bd
Merge branch 'main' into B-21583-gbloc-AK-moves
pambecker Dec 30, 2024
462e528
sc create AK, tests
pambecker Dec 30, 2024
afcd82d
Merge branch 'main' into B-21583-gbloc-AK-moves
pambecker Dec 31, 2024
5a87dcc
Merge branch 'main' into B-21583-gbloc-AK-moves
pambecker Jan 3, 2025
91b4d51
Merge branch 'main' into B-21583-gbloc-AK-moves
pambecker Jan 3, 2025
e98e269
dest gbloc changes
pambecker Jan 3, 2025
9308bd1
reorganize oconus gbloc lookup to be more universal for all addr, not…
pambecker Jan 6, 2025
a46ab3c
Merge branch 'main' into B-21583-gbloc-AK-moves
pambecker Jan 6, 2025
ff072ec
Merge branch 'main' into B-21583-gbloc-AK-moves
pambecker Jan 8, 2025
856b8ca
Merge branch 'main' into B-21583-gbloc-AK-moves
pambecker Jan 8, 2025
a15c927
Merge branch 'main' into B-21583-gbloc-AK-moves
pambecker Jan 9, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions migrations/app/migrations_manifest.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1056,6 +1056,7 @@
20241216190428_update_get_zip_code_function_and_update_pricing_proc.up.sql
20241217163231_update_duty_locations_bad_zips.up.sql
20241217180136_add_AK_zips_to_zip3_distances.up.sql
20241217191012_update_move_to_gbloc_for_ak.up.sql
20241218201833_add_PPPO_BASE_ELIZABETH.up.sql
20241220171035_add_additional_AK_zips_to_zip3_distances.up.sql
20241220213134_add_destination_gbloc_db_function.up.sql
Expand All @@ -1065,4 +1066,6 @@
20241227202424_insert_transportation_offices_camp_pendelton.up.sql
20241230190638_remove_AK_zips_from_zip3.up.sql
20241230190647_add_missing_AK_zips_to_zip3_distances.up.sql
20250103130619_revert_data_change_for_gbloc_for_ak.up.sql
20250103142533_update_postal_codes_and_gblocs_for_ak.up.sql
20250103180420_update_pricing_proc_to_use_local_price_variable.up.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
delete from postal_code_to_gblocs where postal_code in (
select uspr_zip_id from v_locations where state = 'AK');

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'
when s.affiliation = 'NAVY' THEN 'NAVY_AND_MARINES'
when s.affiliation = 'MARINES' THEN 'NAVY_AND_MARINES'
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;

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
delete from postal_code_to_gblocs where postal_code in (
select uspr_zip_id from v_locations where state = 'AK');

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'
when s.affiliation = 'NAVY' THEN 'NAVY_AND_MARINES'
when s.affiliation = 'MARINES' THEN 'NAVY_AND_MARINES'
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;
48 changes: 34 additions & 14 deletions pkg/handlers/ghcapi/orders.go
Original file line number Diff line number Diff line change
Expand Up @@ -218,21 +218,41 @@ func (h CreateOrderHandler) Handle(params orderop.CreateOrderParams) middleware.
return orderop.NewCreateOrderUnprocessableEntity(), err
}

destinationGBLOC, err := models.FetchGBLOCForPostalCode(appCtx.DB(), newDutyLocation.Address.PostalCode)
if err != nil {
err = apperror.NewBadDataError("New duty location GBLOC cannot be verified")
appCtx.Logger().Error(err.Error())
return orderop.NewCreateOrderUnprocessableEntity(), err
var newDutyLocationGBLOC *string
if *newDutyLocation.Address.IsOconus {
newDutyLocationGBLOCOconus, err := models.FetchOconusAddressGbloc(appCtx.DB(), newDutyLocation.Address, serviceMember)
if err != nil {
return nil, apperror.NewNotFoundError(newDutyLocation.ID, "while looking for Duty Location Oconus GBLOC")
}
newDutyLocationGBLOC = &newDutyLocationGBLOCOconus.Gbloc
} else {
newDutyLocationGBLOCConus, err := models.FetchGBLOCForPostalCode(appCtx.DB(), newDutyLocation.Address.PostalCode)
if err != nil {
err = apperror.NewBadDataError("New duty location GBLOC cannot be verified")
appCtx.Logger().Error(err.Error())
return orderop.NewCreateOrderUnprocessableEntity(), err
}
newDutyLocationGBLOC = &newDutyLocationGBLOCConus.GBLOC
}

originDutyLocationGBLOC, err := models.FetchGBLOCForPostalCode(appCtx.DB(), originDutyLocation.Address.PostalCode)
if err != nil {
switch err {
case sql.ErrNoRows:
return nil, apperror.NewNotFoundError(originDutyLocation.ID, "while looking for Duty Location PostalCodeToGBLOC")
default:
return nil, apperror.NewQueryError("PostalCodeToGBLOC", err, "")
var originDutyLocationGBLOC *string
if *originDutyLocation.Address.IsOconus {
originDutyLocationGBLOCOconus, err := models.FetchOconusAddressGbloc(appCtx.DB(), originDutyLocation.Address, serviceMember)
if err != nil {
return nil, apperror.NewNotFoundError(originDutyLocation.ID, "while looking for Duty Location Oconus GBLOC")
}
originDutyLocationGBLOC = &originDutyLocationGBLOCOconus.Gbloc
} else {
originDutyLocationGBLOCConus, err := models.FetchGBLOCForPostalCode(appCtx.DB(), originDutyLocation.Address.PostalCode)
if err != nil {
switch err {
case sql.ErrNoRows:
return nil, apperror.NewNotFoundError(originDutyLocation.ID, "while looking for Duty Location PostalCodeToGBLOC")
default:
return nil, apperror.NewQueryError("PostalCodeToGBLOC", err, "")
}
}
originDutyLocationGBLOC = &originDutyLocationGBLOCConus.GBLOC
}

grade := (internalmessages.OrderPayGrade)(*payload.Grade)
Expand Down Expand Up @@ -311,9 +331,9 @@ func (h CreateOrderHandler) Handle(params orderop.CreateOrderParams) middleware.
&originDutyLocation,
&grade,
&entitlement,
&originDutyLocationGBLOC.GBLOC,
originDutyLocationGBLOC,
packingAndShippingInstructions,
&destinationGBLOC.GBLOC,
newDutyLocationGBLOC,
)
if err != nil || verrs.HasAny() {
return handlers.ResponseForVErrors(appCtx.Logger(), verrs, err), err
Expand Down
91 changes: 86 additions & 5 deletions pkg/handlers/ghcapi/orders_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,20 +106,100 @@ func (suite *HandlerSuite) TestCreateOrder() {
}

func (suite *HandlerSuite) TestCreateOrderWithOCONUSValues() {
sm := factory.BuildExtendedServiceMember(suite.AppContextForTest().DB(), nil, nil)
customAffiliation := models.AffiliationARMY
sm := factory.BuildExtendedServiceMember(suite.DB(), []factory.Customization{
{
Model: models.ServiceMember{
Affiliation: &customAffiliation,
},
},
}, nil)
officeUser := factory.BuildOfficeUserWithRoles(suite.AppContextForTest().DB(), nil, []roles.RoleType{roles.RoleTypeTOO})

originDutyLocation := factory.BuildDutyLocation(suite.AppContextForTest().DB(), []factory.Customization{
usprc, err := models.FindByZipCode(suite.AppContextForTest().DB(), "99801")
suite.NotNil(usprc)
suite.FatalNoError(err)

address := factory.BuildAddress(suite.DB(), []factory.Customization{
{
Model: models.Address{
IsOconus: models.BoolPointer(true),
UsPostRegionCityID: &usprc.ID,
},
},
}, nil)

originDutyLocation := factory.BuildDutyLocation(suite.DB(), []factory.Customization{
{
Model: models.DutyLocation{
Name: "Not Yuma AFB",
Name: factory.MakeRandomString(8),
AddressID: address.ID,
},
},
}, nil)

dutyLocation := factory.FetchOrBuildCurrentDutyLocation(suite.AppContextForTest().DB())
factory.FetchOrBuildPostalCodeToGBLOC(suite.AppContextForTest().DB(), dutyLocation.Address.PostalCode, "KKFA")
factory.FetchOrBuildDefaultContractor(suite.AppContextForTest().DB(), nil, nil)

contract := models.ReContract{
Code: "Test_create_oconus_order_code",
Name: "Test_create_oconus_order",
}
verrs, err := suite.AppContextForTest().DB().ValidateAndSave(&contract)
if verrs.HasAny() {
suite.Fail(verrs.Error())
}
if err != nil {
suite.Fail(verrs.Error())
}

rateAreaCode := uuid.Must(uuid.NewV4()).String()[0:5]
rateArea := models.ReRateArea{
ID: uuid.Must(uuid.NewV4()),
ContractID: contract.ID,
IsOconus: true,
Code: rateAreaCode,
Name: fmt.Sprintf("Alaska-%s", rateAreaCode),
Contract: contract,
}
verrs, err = suite.DB().ValidateAndCreate(&rateArea)
if verrs.HasAny() {
suite.Fail(verrs.Error())
}
if err != nil {
suite.Fail(err.Error())
}

us_country, err := models.FetchCountryByCode(suite.DB(), "US")
suite.NotNil(us_country)
suite.Nil(err)

oconusRateArea := models.OconusRateArea{
ID: uuid.Must(uuid.NewV4()),
RateAreaId: rateArea.ID,
CountryId: us_country.ID,
UsPostRegionCityId: usprc.ID,
Active: true,
}
verrs, err = suite.DB().ValidateAndCreate(&oconusRateArea)
if verrs.HasAny() {
suite.Fail(verrs.Error())
}
if err != nil {
suite.Fail(err.Error())
}
jppsoRegion := models.JppsoRegions{
Name: "USCG Base Ketchikan",
Code: "MAPK",
}
suite.MustSave(&jppsoRegion)

gblocAors := models.GblocAors{
JppsoRegionID: jppsoRegion.ID,
OconusRateAreaID: oconusRateArea.ID,
}
suite.MustSave(&gblocAors)

factory.FetchOrBuildDefaultContractor(suite.AppContextForTest().DB(), nil, nil)
req := httptest.NewRequest("POST", "/orders", nil)
req = suite.AuthenticateOfficeRequest(req, officeUser)

Expand Down Expand Up @@ -171,6 +251,7 @@ func (suite *HandlerSuite) TestCreateOrderWithOCONUSValues() {
suite.Assertions.Equal(sm.ID.String(), okResponse.Payload.CustomerID.String())
suite.Assertions.Equal(ordersType, okResponse.Payload.OrderType)
suite.Assertions.Equal(handlers.FmtString("123456"), okResponse.Payload.OrderNumber)
suite.Assertions.Equal(ghcmessages.GBLOC("MAPK"), okResponse.Payload.OriginDutyLocationGBLOC)
suite.Assertions.Equal(handlers.FmtString("E19A"), okResponse.Payload.Tac)
suite.Assertions.Equal(handlers.FmtString("SacNumber"), okResponse.Payload.Sac)
suite.Assertions.Equal(&deptIndicator, okResponse.Payload.DepartmentIndicator)
Expand Down
66 changes: 48 additions & 18 deletions pkg/handlers/internalapi/orders.go
Original file line number Diff line number Diff line change
Expand Up @@ -167,9 +167,19 @@ func (h CreateOrdersHandler) Handle(params ordersop.CreateOrdersParams) middlewa
return handlers.ResponseForError(appCtx.Logger(), err), err
}

newDutyLocationGBLOC, err := models.FetchGBLOCForPostalCode(appCtx.DB(), newDutyLocation.Address.PostalCode)
if err != nil {
return handlers.ResponseForError(appCtx.Logger(), err), err
var newDutyLocationGBLOC *string
if *newDutyLocation.Address.IsOconus {
newDutyLocationGBLOCOconus, err := models.FetchOconusAddressGbloc(appCtx.DB(), newDutyLocation.Address, serviceMember)
if err != nil {
return nil, apperror.NewNotFoundError(newDutyLocation.ID, "while looking for Duty Location Oconus GBLOC")
}
newDutyLocationGBLOC = &newDutyLocationGBLOCOconus.Gbloc
} else {
newDutyLocationGBLOCConus, err := models.FetchGBLOCForPostalCode(appCtx.DB(), newDutyLocation.Address.PostalCode)
if err != nil {
return handlers.ResponseForError(appCtx.Logger(), err), err
}
newDutyLocationGBLOC = &newDutyLocationGBLOCConus.GBLOC
}

var dependentsTwelveAndOver *int
Expand All @@ -183,14 +193,24 @@ func (h CreateOrdersHandler) Handle(params ordersop.CreateOrdersParams) middlewa
dependentsUnderTwelve = models.IntPointer(int(*payload.DependentsUnderTwelve))
}

originDutyLocationGBLOC, err := models.FetchGBLOCForPostalCode(appCtx.DB(), originDutyLocation.Address.PostalCode)
if err != nil {
switch err {
case sql.ErrNoRows:
return nil, apperror.NewNotFoundError(originDutyLocation.ID, "while looking for Duty Location PostalCodeToGBLOC")
default:
return nil, apperror.NewQueryError("PostalCodeToGBLOC", err, "")
var originDutyLocationGBLOC *string
if *originDutyLocation.Address.IsOconus {
originDutyLocationGBLOCOconus, err := models.FetchOconusAddressGbloc(appCtx.DB(), originDutyLocation.Address, serviceMember)
if err != nil {
return nil, apperror.NewNotFoundError(originDutyLocation.ID, "while looking for Duty Location Oconus GBLOC")
}
originDutyLocationGBLOC = &originDutyLocationGBLOCOconus.Gbloc
} else {
originDutyLocationGBLOCConus, err := models.FetchGBLOCForPostalCode(appCtx.DB(), originDutyLocation.Address.PostalCode)
if err != nil {
switch err {
case sql.ErrNoRows:
return nil, apperror.NewNotFoundError(originDutyLocation.ID, "while looking for Duty Location PostalCodeToGBLOC")
default:
return nil, apperror.NewQueryError("PostalCodeToGBLOC", err, "")
}
}
originDutyLocationGBLOC = &originDutyLocationGBLOCConus.GBLOC
}

grade := payload.Grade
Expand Down Expand Up @@ -273,9 +293,9 @@ func (h CreateOrdersHandler) Handle(params ordersop.CreateOrdersParams) middlewa
&originDutyLocation,
grade,
&entitlement,
&originDutyLocationGBLOC.GBLOC,
originDutyLocationGBLOC,
packingAndShippingInstructions,
&newDutyLocationGBLOC.GBLOC,
newDutyLocationGBLOC,
)
if err != nil || verrs.HasAny() {
return handlers.ResponseForVErrors(appCtx.Logger(), verrs, err), err
Expand Down Expand Up @@ -363,11 +383,21 @@ func (h UpdateOrdersHandler) Handle(params ordersop.UpdateOrdersParams) middlewa
return handlers.ResponseForError(appCtx.Logger(), err), err
}

newDutyLocationGBLOC, err := models.FetchGBLOCForPostalCode(appCtx.DB(), dutyLocation.Address.PostalCode)
if err != nil {
err = apperror.NewBadDataError("New duty location GBLOC cannot be verified")
appCtx.Logger().Error(err.Error())
return handlers.ResponseForError(appCtx.Logger(), err), err
var newDutyLocationGBLOC *string
if *dutyLocation.Address.IsOconus {
newDutyLocationGBLOCOconus, err := models.FetchOconusAddressGbloc(appCtx.DB(), dutyLocation.Address, order.ServiceMember)
if err != nil {
return nil, apperror.NewNotFoundError(dutyLocation.ID, "while looking for Duty Location Oconus GBLOC")
}
newDutyLocationGBLOC = &newDutyLocationGBLOCOconus.Gbloc
} else {
newDutyLocationGBLOCConus, err := models.FetchGBLOCForPostalCode(appCtx.DB(), dutyLocation.Address.PostalCode)
if err != nil {
err = apperror.NewBadDataError("New duty location GBLOC cannot be verified")
appCtx.Logger().Error(err.Error())
return handlers.ResponseForError(appCtx.Logger(), err), err
}
newDutyLocationGBLOC = &newDutyLocationGBLOCConus.GBLOC
}

if payload.OriginDutyLocationID != "" {
Expand Down Expand Up @@ -428,7 +458,7 @@ func (h UpdateOrdersHandler) Handle(params ordersop.UpdateOrdersParams) middlewa
order.SpouseHasProGear = *payload.SpouseHasProGear
order.NewDutyLocationID = dutyLocation.ID
order.NewDutyLocation = dutyLocation
order.DestinationGBLOC = &newDutyLocationGBLOC.GBLOC
order.DestinationGBLOC = newDutyLocationGBLOC
order.TAC = payload.Tac
order.SAC = payload.Sac

Expand Down
Loading
Loading