From f27f3ebe907501aed7806a90f0b4cc1ccc8f64b7 Mon Sep 17 00:00:00 2001 From: Cory Kleinjan Date: Tue, 12 Nov 2024 14:20:55 -0600 Subject: [PATCH 01/32] Approving destination address change will update service item pricing --- pkg/handlers/ghcapi/api.go | 4 +- pkg/handlers/ghcapi/mto_service_items_test.go | 4 +- pkg/handlers/ghcapi/mto_shipment_test.go | 4 +- pkg/handlers/primeapi/api.go | 2 +- .../primeapi/mto_service_item_test.go | 4 +- pkg/handlers/supportapi/api.go | 2 +- .../supportapi/mto_service_item_test.go | 7 +- pkg/services/mocks/MTOServiceItemUpdater.go | 30 ++++ .../move_history/move_history_fetcher_test.go | 2 +- pkg/services/mto_service_item.go | 1 + .../mto_service_item_updater.go | 154 +++++++++++++++++- .../mto_service_item_updater_test.go | 5 +- .../mto_service_item_validators.go | 3 + .../shipment_address_update_requester.go | 36 +++- .../sit_extension/sit_extension_denier.go | 3 +- pkg/testdatagen/scenario/shared.go | 6 +- 16 files changed, 236 insertions(+), 31 deletions(-) diff --git a/pkg/handlers/ghcapi/api.go b/pkg/handlers/ghcapi/api.go index 5d20500500e..47fd3176180 100644 --- a/pkg/handlers/ghcapi/api.go +++ b/pkg/handlers/ghcapi/api.go @@ -231,7 +231,7 @@ func NewGhcAPIHandler(handlerConfig handlers.HandlerConfig) *ghcops.MymoveAPI { ghcAPI.MtoServiceItemUpdateMTOServiceItemStatusHandler = UpdateMTOServiceItemStatusHandler{ HandlerConfig: handlerConfig, - MTOServiceItemUpdater: mtoserviceitem.NewMTOServiceItemUpdater(handlerConfig.HHGPlanner(), queryBuilder, moveRouter, shipmentFetcher, addressCreator), + MTOServiceItemUpdater: mtoserviceitem.NewMTOServiceItemUpdater(handlerConfig.HHGPlanner(), queryBuilder, moveRouter, shipmentFetcher, addressCreator, ghcrateengine.NewDomesticUnpackPricer(), ghcrateengine.NewDomesticLinehaulPricer(), ghcrateengine.NewDomesticDestinationPricer(), ghcrateengine.NewFuelSurchargePricer(), ghcrateengine.NewDomesticDestinationSITDeliveryPricer(), ghcrateengine.NewDomesticOriginSITFuelSurchargePricer()), Fetcher: fetch.NewFetcher(queryBuilder), ShipmentSITStatus: sitstatus.NewShipmentSITStatus(), MTOShipmentFetcher: mtoshipment.NewMTOShipmentFetcher(), @@ -501,7 +501,7 @@ func NewGhcAPIHandler(handlerConfig handlers.HandlerConfig) *ghcops.MymoveAPI { ghcAPI.ShipmentUpdateSITServiceItemCustomerExpenseHandler = UpdateSITServiceItemCustomerExpenseHandler{ handlerConfig, - mtoserviceitem.NewMTOServiceItemUpdater(handlerConfig.HHGPlanner(), queryBuilder, moveRouter, shipmentFetcher, addressCreator), + mtoserviceitem.NewMTOServiceItemUpdater(handlerConfig.HHGPlanner(), queryBuilder, moveRouter, shipmentFetcher, addressCreator, ghcrateengine.NewDomesticUnpackPricer(), ghcrateengine.NewDomesticLinehaulPricer(), ghcrateengine.NewDomesticDestinationPricer(), ghcrateengine.NewFuelSurchargePricer(), ghcrateengine.NewDomesticDestinationSITDeliveryPricer(), ghcrateengine.NewDomesticOriginSITFuelSurchargePricer()), mtoshipment.NewMTOShipmentFetcher(), shipmentSITStatus, } diff --git a/pkg/handlers/ghcapi/mto_service_items_test.go b/pkg/handlers/ghcapi/mto_service_items_test.go index 3b0b3e74d1b..8ba2ab744bd 100644 --- a/pkg/handlers/ghcapi/mto_service_items_test.go +++ b/pkg/handlers/ghcapi/mto_service_items_test.go @@ -563,7 +563,7 @@ func (suite *HandlerSuite) TestUpdateMTOServiceItemStatusHandler() { mock.Anything, mock.Anything, ).Return(400, nil) - mtoServiceItemStatusUpdater := mtoserviceitem.NewMTOServiceItemUpdater(planner, queryBuilder, moveRouter, shipmentFetcher, addressCreator) + mtoServiceItemStatusUpdater := mtoserviceitem.NewMTOServiceItemUpdater(planner, queryBuilder, moveRouter, shipmentFetcher, addressCreator, ghcrateengine.NewDomesticUnpackPricer(), ghcrateengine.NewDomesticLinehaulPricer(), ghcrateengine.NewDomesticDestinationPricer(), ghcrateengine.NewFuelSurchargePricer(), ghcrateengine.NewDomesticDestinationSITDeliveryPricer(), ghcrateengine.NewDomesticOriginSITFuelSurchargePricer()) handler := UpdateMTOServiceItemStatusHandler{ HandlerConfig: suite.HandlerConfig(), @@ -623,7 +623,7 @@ func (suite *HandlerSuite) TestUpdateMTOServiceItemStatusHandler() { mock.Anything, mock.Anything, ).Return(400, nil) - mtoServiceItemStatusUpdater := mtoserviceitem.NewMTOServiceItemUpdater(planner, queryBuilder, moveRouter, shipmentFetcher, addressCreator) + mtoServiceItemStatusUpdater := mtoserviceitem.NewMTOServiceItemUpdater(planner, queryBuilder, moveRouter, shipmentFetcher, addressCreator, ghcrateengine.NewDomesticUnpackPricer(), ghcrateengine.NewDomesticLinehaulPricer(), ghcrateengine.NewDomesticDestinationPricer(), ghcrateengine.NewFuelSurchargePricer(), ghcrateengine.NewDomesticDestinationSITDeliveryPricer(), ghcrateengine.NewDomesticOriginSITFuelSurchargePricer()) handler := UpdateMTOServiceItemStatusHandler{ HandlerConfig: suite.HandlerConfig(), diff --git a/pkg/handlers/ghcapi/mto_shipment_test.go b/pkg/handlers/ghcapi/mto_shipment_test.go index aa96acd49f0..5cc9d43ebe8 100644 --- a/pkg/handlers/ghcapi/mto_shipment_test.go +++ b/pkg/handlers/ghcapi/mto_shipment_test.go @@ -4674,7 +4674,7 @@ func (suite *HandlerSuite) TestUpdateSITServiceItemCustomerExpenseHandler() { mock.Anything, mock.Anything, ).Return(400, nil) - updater := mtoserviceitem.NewMTOServiceItemUpdater(planner, builder, moveRouter, shipmentFetcher, addressCreator) + updater := mtoserviceitem.NewMTOServiceItemUpdater(planner, builder, moveRouter, shipmentFetcher, addressCreator, ghcrateengine.NewDomesticUnpackPricer(), ghcrateengine.NewDomesticLinehaulPricer(), ghcrateengine.NewDomesticDestinationPricer(), ghcrateengine.NewFuelSurchargePricer(), ghcrateengine.NewDomesticDestinationSITDeliveryPricer(), ghcrateengine.NewDomesticOriginSITFuelSurchargePricer()) req := httptest.NewRequest("PATCH", fmt.Sprintf("/shipments/%s/sit-service-item/convert-to-customer-expense", approvedShipment.ID.String()), nil) req = suite.AuthenticateOfficeRequest(req, officeUser) handlerConfig := suite.HandlerConfig() @@ -4750,7 +4750,7 @@ func (suite *HandlerSuite) TestUpdateSITServiceItemCustomerExpenseHandler() { mock.Anything, mock.Anything, ).Return(400, nil) - updater := mtoserviceitem.NewMTOServiceItemUpdater(planner, builder, moveRouter, shipmentFetcher, addressCreator) + updater := mtoserviceitem.NewMTOServiceItemUpdater(planner, builder, moveRouter, shipmentFetcher, addressCreator, ghcrateengine.NewDomesticUnpackPricer(), ghcrateengine.NewDomesticLinehaulPricer(), ghcrateengine.NewDomesticDestinationPricer(), ghcrateengine.NewFuelSurchargePricer(), ghcrateengine.NewDomesticDestinationSITDeliveryPricer(), ghcrateengine.NewDomesticOriginSITFuelSurchargePricer()) req := httptest.NewRequest("PATCH", fmt.Sprintf("/shipments/%s/sit-service-item/convert-to-customer-expense", approvedShipment.ID.String()), nil) req = suite.AuthenticateOfficeRequest(req, officeUser) handlerConfig := suite.HandlerConfig() diff --git a/pkg/handlers/primeapi/api.go b/pkg/handlers/primeapi/api.go index b614fb13d60..25afdb43b77 100644 --- a/pkg/handlers/primeapi/api.go +++ b/pkg/handlers/primeapi/api.go @@ -45,7 +45,7 @@ func NewPrimeAPI(handlerConfig handlers.HandlerConfig) *primeoperations.MymoveAP shipmentFetcher := mtoshipment.NewMTOShipmentFetcher() moveWeights := move.NewMoveWeights(mtoshipment.NewShipmentReweighRequester()) uploadCreator := upload.NewUploadCreator(handlerConfig.FileStorer()) - serviceItemUpdater := mtoserviceitem.NewMTOServiceItemUpdater(handlerConfig.HHGPlanner(), queryBuilder, moveRouter, shipmentFetcher, addressCreator) + serviceItemUpdater := mtoserviceitem.NewMTOServiceItemUpdater(handlerConfig.HHGPlanner(), queryBuilder, moveRouter, shipmentFetcher, addressCreator, ghcrateengine.NewDomesticUnpackPricer(), ghcrateengine.NewDomesticLinehaulPricer(), ghcrateengine.NewDomesticDestinationPricer(), ghcrateengine.NewFuelSurchargePricer(), ghcrateengine.NewDomesticDestinationSITDeliveryPricer(), ghcrateengine.NewDomesticOriginSITFuelSurchargePricer()) userUploader, err := uploader.NewUserUploader(handlerConfig.FileStorer(), uploader.MaxCustomerUserUploadFileSizeLimit) if err != nil { diff --git a/pkg/handlers/primeapi/mto_service_item_test.go b/pkg/handlers/primeapi/mto_service_item_test.go index b635bb4d124..cf2e636495e 100644 --- a/pkg/handlers/primeapi/mto_service_item_test.go +++ b/pkg/handlers/primeapi/mto_service_item_test.go @@ -1543,7 +1543,7 @@ func (suite *HandlerSuite) TestUpdateMTOServiceItemDDDSIT() { ).Return(400, nil) subtestData.handler = UpdateMTOServiceItemHandler{ suite.HandlerConfig(), - mtoserviceitem.NewMTOServiceItemUpdater(planner, queryBuilder, moveRouter, shipmentFetcher, addressCreator), + mtoserviceitem.NewMTOServiceItemUpdater(planner, queryBuilder, moveRouter, shipmentFetcher, addressCreator, ghcrateengine.NewDomesticUnpackPricer(), ghcrateengine.NewDomesticLinehaulPricer(), ghcrateengine.NewDomesticDestinationPricer(), ghcrateengine.NewFuelSurchargePricer(), ghcrateengine.NewDomesticDestinationSITDeliveryPricer(), ghcrateengine.NewDomesticOriginSITFuelSurchargePricer()), } // create the params struct @@ -1825,7 +1825,7 @@ func (suite *HandlerSuite) TestUpdateMTOServiceItemDOPSIT() { ).Return(400, nil) subtestData.handler = UpdateMTOServiceItemHandler{ suite.HandlerConfig(), - mtoserviceitem.NewMTOServiceItemUpdater(planner, queryBuilder, moveRouter, shipmentFetcher, addressCreator), + mtoserviceitem.NewMTOServiceItemUpdater(planner, queryBuilder, moveRouter, shipmentFetcher, addressCreator, ghcrateengine.NewDomesticUnpackPricer(), ghcrateengine.NewDomesticLinehaulPricer(), ghcrateengine.NewDomesticDestinationPricer(), ghcrateengine.NewFuelSurchargePricer(), ghcrateengine.NewDomesticDestinationSITDeliveryPricer(), ghcrateengine.NewDomesticOriginSITFuelSurchargePricer()), } // create the params struct diff --git a/pkg/handlers/supportapi/api.go b/pkg/handlers/supportapi/api.go index dd2a5df8b8f..1aba70b9c72 100644 --- a/pkg/handlers/supportapi/api.go +++ b/pkg/handlers/supportapi/api.go @@ -88,7 +88,7 @@ func NewSupportAPIHandler(handlerConfig handlers.HandlerConfig) http.Handler { mtoserviceitem.NewMTOServiceItemCreator(handlerConfig.HHGPlanner(), queryBuilder, moveRouter, ghcrateengine.NewDomesticUnpackPricer(), ghcrateengine.NewDomesticPackPricer(), ghcrateengine.NewDomesticLinehaulPricer(), ghcrateengine.NewDomesticShorthaulPricer(), ghcrateengine.NewDomesticOriginPricer(), ghcrateengine.NewDomesticDestinationPricer(), ghcrateengine.NewFuelSurchargePricer()), handlerConfig.HHGPlanner()), } - supportAPI.MtoServiceItemUpdateMTOServiceItemStatusHandler = UpdateMTOServiceItemStatusHandler{handlerConfig, mtoserviceitem.NewMTOServiceItemUpdater(handlerConfig.HHGPlanner(), queryBuilder, moveRouter, shipmentFetcher, addressCreator)} + supportAPI.MtoServiceItemUpdateMTOServiceItemStatusHandler = UpdateMTOServiceItemStatusHandler{handlerConfig, mtoserviceitem.NewMTOServiceItemUpdater(handlerConfig.HHGPlanner(), queryBuilder, moveRouter, shipmentFetcher, addressCreator, ghcrateengine.NewDomesticUnpackPricer(), ghcrateengine.NewDomesticLinehaulPricer(), ghcrateengine.NewDomesticDestinationPricer(), ghcrateengine.NewFuelSurchargePricer(), ghcrateengine.NewDomesticDestinationSITDeliveryPricer(), ghcrateengine.NewDomesticOriginSITFuelSurchargePricer())} supportAPI.WebhookReceiveWebhookNotificationHandler = ReceiveWebhookNotificationHandler{handlerConfig} // Create TAC and LOA services diff --git a/pkg/handlers/supportapi/mto_service_item_test.go b/pkg/handlers/supportapi/mto_service_item_test.go index 44a56716688..5db466e8d52 100644 --- a/pkg/handlers/supportapi/mto_service_item_test.go +++ b/pkg/handlers/supportapi/mto_service_item_test.go @@ -22,6 +22,7 @@ import ( "github.com/transcom/mymove/pkg/models" routemocks "github.com/transcom/mymove/pkg/route/mocks" "github.com/transcom/mymove/pkg/services/address" + "github.com/transcom/mymove/pkg/services/ghcrateengine" moverouter "github.com/transcom/mymove/pkg/services/move" mtoserviceitem "github.com/transcom/mymove/pkg/services/mto_service_item" mtoshipment "github.com/transcom/mymove/pkg/services/mto_shipment" @@ -85,7 +86,7 @@ func (suite *HandlerSuite) TestUpdateMTOServiceItemStatusHandlerApproveSuccess() mock.Anything, ).Return(400, nil) handler := UpdateMTOServiceItemStatusHandler{handlerConfig, - mtoserviceitem.NewMTOServiceItemUpdater(planner, queryBuilder, moveRouter, shipmentFetcher, addressCreator), + mtoserviceitem.NewMTOServiceItemUpdater(planner, queryBuilder, moveRouter, shipmentFetcher, addressCreator, ghcrateengine.NewDomesticUnpackPricer(), ghcrateengine.NewDomesticLinehaulPricer(), ghcrateengine.NewDomesticDestinationPricer(), ghcrateengine.NewFuelSurchargePricer(), ghcrateengine.NewDomesticDestinationSITDeliveryPricer(), ghcrateengine.NewDomesticOriginSITFuelSurchargePricer()), } // CALL FUNCTION UNDER TEST @@ -141,7 +142,7 @@ func (suite *HandlerSuite) TestUpdateMTOServiceItemStatusHandlerRejectSuccess() mock.Anything, ).Return(400, nil) handler := UpdateMTOServiceItemStatusHandler{handlerConfig, - mtoserviceitem.NewMTOServiceItemUpdater(planner, queryBuilder, moveRouter, shipmentFetcher, addressCreator), + mtoserviceitem.NewMTOServiceItemUpdater(planner, queryBuilder, moveRouter, shipmentFetcher, addressCreator, ghcrateengine.NewDomesticUnpackPricer(), ghcrateengine.NewDomesticLinehaulPricer(), ghcrateengine.NewDomesticDestinationPricer(), ghcrateengine.NewFuelSurchargePricer(), ghcrateengine.NewDomesticDestinationSITDeliveryPricer(), ghcrateengine.NewDomesticOriginSITFuelSurchargePricer()), } // CALL FUNCTION UNDER TEST @@ -197,7 +198,7 @@ func (suite *HandlerSuite) TestUpdateMTOServiceItemStatusHandlerRejectionFailedN mock.Anything, ).Return(400, nil) handler := UpdateMTOServiceItemStatusHandler{handlerConfig, - mtoserviceitem.NewMTOServiceItemUpdater(planner, queryBuilder, moveRouter, shipmentFetcher, addressCreator), + mtoserviceitem.NewMTOServiceItemUpdater(planner, queryBuilder, moveRouter, shipmentFetcher, addressCreator, ghcrateengine.NewDomesticUnpackPricer(), ghcrateengine.NewDomesticLinehaulPricer(), ghcrateengine.NewDomesticDestinationPricer(), ghcrateengine.NewFuelSurchargePricer(), ghcrateengine.NewDomesticDestinationSITDeliveryPricer(), ghcrateengine.NewDomesticOriginSITFuelSurchargePricer()), } // CALL FUNCTION UNDER TEST diff --git a/pkg/services/mocks/MTOServiceItemUpdater.go b/pkg/services/mocks/MTOServiceItemUpdater.go index ed356fd7699..bbb6bd86828 100644 --- a/pkg/services/mocks/MTOServiceItemUpdater.go +++ b/pkg/services/mocks/MTOServiceItemUpdater.go @@ -138,6 +138,36 @@ func (_m *MTOServiceItemUpdater) UpdateMTOServiceItemBasic(appCtx appcontext.App return r0, r1 } +// UpdateMTOServiceItemPricingEstimate provides a mock function with given fields: appCtx, serviceItem, shipment, eTag +func (_m *MTOServiceItemUpdater) UpdateMTOServiceItemPricingEstimate(appCtx appcontext.AppContext, serviceItem *models.MTOServiceItem, shipment models.MTOShipment, eTag string) (*models.MTOServiceItem, error) { + ret := _m.Called(appCtx, serviceItem, shipment, eTag) + + if len(ret) == 0 { + panic("no return value specified for UpdateMTOServiceItemPricingEstimate") + } + + var r0 *models.MTOServiceItem + var r1 error + if rf, ok := ret.Get(0).(func(appcontext.AppContext, *models.MTOServiceItem, models.MTOShipment, string) (*models.MTOServiceItem, error)); ok { + return rf(appCtx, serviceItem, shipment, eTag) + } + if rf, ok := ret.Get(0).(func(appcontext.AppContext, *models.MTOServiceItem, models.MTOShipment, string) *models.MTOServiceItem); ok { + r0 = rf(appCtx, serviceItem, shipment, eTag) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*models.MTOServiceItem) + } + } + + if rf, ok := ret.Get(1).(func(appcontext.AppContext, *models.MTOServiceItem, models.MTOShipment, string) error); ok { + r1 = rf(appCtx, serviceItem, shipment, eTag) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + // UpdateMTOServiceItemPrime provides a mock function with given fields: appCtx, serviceItem, planner, shipment, eTag func (_m *MTOServiceItemUpdater) UpdateMTOServiceItemPrime(appCtx appcontext.AppContext, serviceItem *models.MTOServiceItem, planner route.Planner, shipment models.MTOShipment, eTag string) (*models.MTOServiceItem, error) { ret := _m.Called(appCtx, serviceItem, planner, shipment, eTag) diff --git a/pkg/services/move_history/move_history_fetcher_test.go b/pkg/services/move_history/move_history_fetcher_test.go index 13b85471c12..fef04459564 100644 --- a/pkg/services/move_history/move_history_fetcher_test.go +++ b/pkg/services/move_history/move_history_fetcher_test.go @@ -374,7 +374,7 @@ func (suite *MoveHistoryServiceSuite) TestMoveHistoryFetcherScenarios() { mock.Anything, mock.Anything, ).Return(400, nil) - updater := mtoserviceitem.NewMTOServiceItemUpdater(planner, builder, moveRouter, shipmentFetcher, addressCreator) + updater := mtoserviceitem.NewMTOServiceItemUpdater(planner, builder, moveRouter, shipmentFetcher, addressCreator, ghcrateengine.NewDomesticUnpackPricer(), ghcrateengine.NewDomesticLinehaulPricer(), ghcrateengine.NewDomesticDestinationPricer(), ghcrateengine.NewFuelSurchargePricer(), ghcrateengine.NewDomesticDestinationSITDeliveryPricer(), ghcrateengine.NewDomesticOriginSITFuelSurchargePricer()) move := factory.BuildApprovalsRequestedMove(suite.DB(), nil, nil) serviceItem := factory.BuildMTOServiceItem(suite.DB(), []factory.Customization{ { diff --git a/pkg/services/mto_service_item.go b/pkg/services/mto_service_item.go index 25926ae3fca..914823809c3 100644 --- a/pkg/services/mto_service_item.go +++ b/pkg/services/mto_service_item.go @@ -32,6 +32,7 @@ type MTOServiceItemUpdater interface { ApproveOrRejectServiceItem(appCtx appcontext.AppContext, mtoServiceItemID uuid.UUID, status models.MTOServiceItemStatus, rejectionReason *string, eTag string) (*models.MTOServiceItem, error) UpdateMTOServiceItem(appCtx appcontext.AppContext, serviceItem *models.MTOServiceItem, eTag string, validator string) (*models.MTOServiceItem, error) UpdateMTOServiceItemBasic(appCtx appcontext.AppContext, serviceItem *models.MTOServiceItem, eTag string) (*models.MTOServiceItem, error) + UpdateMTOServiceItemPricingEstimate(appCtx appcontext.AppContext, serviceItem *models.MTOServiceItem, shipment models.MTOShipment, eTag string) (*models.MTOServiceItem, error) UpdateMTOServiceItemPrime(appCtx appcontext.AppContext, serviceItem *models.MTOServiceItem, planner route.Planner, shipment models.MTOShipment, eTag string) (*models.MTOServiceItem, error) ConvertItemToCustomerExpense(appCtx appcontext.AppContext, shipment *models.MTOShipment, customerExpenseReason *string, convertToCustomerExpense bool) (*models.MTOServiceItem, error) } diff --git a/pkg/services/mto_service_item/mto_service_item_updater.go b/pkg/services/mto_service_item/mto_service_item_updater.go index b2ac848273f..1bbbb60afac 100644 --- a/pkg/services/mto_service_item/mto_service_item_updater.go +++ b/pkg/services/mto_service_item/mto_service_item_updater.go @@ -3,6 +3,7 @@ package mtoserviceitem import ( "database/sql" "fmt" + "strconv" "time" "github.com/gobuffalo/validate/v3" @@ -19,6 +20,7 @@ import ( movetaskorder "github.com/transcom/mymove/pkg/services/move_task_order" "github.com/transcom/mymove/pkg/services/query" sitstatus "github.com/transcom/mymove/pkg/services/sit_status" + "github.com/transcom/mymove/pkg/unit" ) // OriginSITLocation is the constant representing when the shipment in storage occurs at the origin @@ -37,22 +39,28 @@ type mtoServiceItemQueryBuilder interface { } type mtoServiceItemUpdater struct { - planner route.Planner - builder mtoServiceItemQueryBuilder - createNewBuilder func() mtoServiceItemQueryBuilder - moveRouter services.MoveRouter - shipmentFetcher services.MTOShipmentFetcher - addressCreator services.AddressCreator + planner route.Planner + builder mtoServiceItemQueryBuilder + createNewBuilder func() mtoServiceItemQueryBuilder + moveRouter services.MoveRouter + shipmentFetcher services.MTOShipmentFetcher + addressCreator services.AddressCreator + unpackPricer services.DomesticUnpackPricer + linehaulPricer services.DomesticLinehaulPricer + destinationPricer services.DomesticDestinationPricer + fuelSurchargePricer services.FuelSurchargePricer + sitFuelSurchargePricer services.DomesticDestinationSITFuelSurchargePricer + sitDeliverPricer services.DomesticDestinationSITDeliveryPricer } // NewMTOServiceItemUpdater returns a new mto service item updater -func NewMTOServiceItemUpdater(planner route.Planner, builder mtoServiceItemQueryBuilder, moveRouter services.MoveRouter, shipmentFetcher services.MTOShipmentFetcher, addressCreator services.AddressCreator) services.MTOServiceItemUpdater { +func NewMTOServiceItemUpdater(planner route.Planner, builder mtoServiceItemQueryBuilder, moveRouter services.MoveRouter, shipmentFetcher services.MTOShipmentFetcher, addressCreator services.AddressCreator, unpackPricer services.DomesticUnpackPricer, linehaulPricer services.DomesticLinehaulPricer, destinationPricer services.DomesticDestinationPricer, fuelSurchargePricer services.FuelSurchargePricer, domesticDestinationSITDeliveryPricer services.DomesticDestinationSITDeliveryPricer, domesticDestinationSITFuelSurchargePricer services.DomesticDestinationSITFuelSurchargePricer) services.MTOServiceItemUpdater { // used inside a transaction and mocking return &mtoServiceItemUpdater{builder: builder} createNewBuilder := func() mtoServiceItemQueryBuilder { return query.NewQueryBuilder() } - return &mtoServiceItemUpdater{planner, builder, createNewBuilder, moveRouter, shipmentFetcher, addressCreator} + return &mtoServiceItemUpdater{planner, builder, createNewBuilder, moveRouter, shipmentFetcher, addressCreator, unpackPricer, linehaulPricer, destinationPricer, fuelSurchargePricer, domesticDestinationSITFuelSurchargePricer, domesticDestinationSITDeliveryPricer} } func (p *mtoServiceItemUpdater) ApproveOrRejectServiceItem( @@ -118,6 +126,121 @@ func (p *mtoServiceItemUpdater) ConvertItemToCustomerExpense( return p.convertItemToCustomerExpense(appCtx, *mtoServiceItem, customerExpenseReason, convertToCustomerExpense, eTag, checkETag()) } +func (p *mtoServiceItemUpdater) findEstimatedPrice(appCtx appcontext.AppContext, serviceItem *models.MTOServiceItem, mtoShipment models.MTOShipment) (unit.Cents, error) { + if serviceItem.ReService.Code == models.ReServiceCodeDDP || + serviceItem.ReService.Code == models.ReServiceCodeDUPK || + serviceItem.ReService.Code == models.ReServiceCodeDLH || + serviceItem.ReService.Code == models.ReServiceCodeFSC || + serviceItem.ReService.Code == models.ReServiceCodeDDDSIT || + serviceItem.ReService.Code == models.ReServiceCodeDDSFSC { + + isPPM := false + if mtoShipment.ShipmentType == models.MTOShipmentTypePPM { + isPPM = true + } + requestedPickupDate := *mtoShipment.RequestedPickupDate + currTime := time.Now() + var distance int + primeEstimatedWeight := *mtoShipment.PrimeEstimatedWeight + + contractCode, err := FetchContractCode(appCtx, currTime) + if err != nil { + contractCode, err = FetchContractCode(appCtx, requestedPickupDate) + if err != nil { + return 0, err + } + } + + var price unit.Cents + + // destination + if serviceItem.ReService.Code == models.ReServiceCodeDDP { + var domesticServiceArea models.ReDomesticServiceArea + if mtoShipment.DestinationAddress != nil { + domesticServiceArea, err = fetchDomesticServiceArea(appCtx, contractCode, mtoShipment.DestinationAddress.PostalCode) + if err != nil { + return 0, err + } + } + + price, _, err = p.destinationPricer.Price(appCtx, contractCode, requestedPickupDate, *mtoShipment.PrimeEstimatedWeight, domesticServiceArea.ServiceArea, isPPM) + if err != nil { + return 0, err + } + } + if serviceItem.ReService.Code == models.ReServiceCodeDUPK { + domesticServiceArea, err := fetchDomesticServiceArea(appCtx, contractCode, mtoShipment.DestinationAddress.PostalCode) + if err != nil { + return 0, err + } + + serviceScheduleDestination := domesticServiceArea.ServicesSchedule + + price, _, err = p.unpackPricer.Price(appCtx, contractCode, requestedPickupDate, *mtoShipment.PrimeEstimatedWeight, serviceScheduleDestination, isPPM) + if err != nil { + return 0, err + } + } + + // linehaul + if serviceItem.ReService.Code == models.ReServiceCodeDLH { + domesticServiceArea, err := fetchDomesticServiceArea(appCtx, contractCode, mtoShipment.PickupAddress.PostalCode) + if err != nil { + return 0, err + } + if mtoShipment.PickupAddress != nil && mtoShipment.DestinationAddress != nil { + distance, err = p.planner.ZipTransitDistance(appCtx, mtoShipment.PickupAddress.PostalCode, mtoShipment.DestinationAddress.PostalCode) + if err != nil { + return 0, err + } + } + price, _, err = p.linehaulPricer.Price(appCtx, contractCode, requestedPickupDate, unit.Miles(distance), *mtoShipment.PrimeEstimatedWeight, domesticServiceArea.ServiceArea, isPPM) + if err != nil { + return 0, err + } + } + // fuel surcharge + if serviceItem.ReService.Code == models.ReServiceCodeFSC { + var pickupDateForFSC time.Time + + // actual pickup date likely won't exist at the time of service item creation, but it could + // use requested pickup date if no actual date exists + if mtoShipment.ActualPickupDate != nil { + pickupDateForFSC = *mtoShipment.ActualPickupDate + } else { + pickupDateForFSC = requestedPickupDate + } + + if mtoShipment.PickupAddress != nil && mtoShipment.DestinationAddress != nil { + distance, err = p.planner.ZipTransitDistance(appCtx, mtoShipment.PickupAddress.PostalCode, mtoShipment.DestinationAddress.PostalCode) + if err != nil { + return 0, err + } + } + + fscWeightBasedDistanceMultiplier, err := LookupFSCWeightBasedDistanceMultiplier(appCtx, primeEstimatedWeight) + if err != nil { + return 0, err + } + fscWeightBasedDistanceMultiplierFloat, err := strconv.ParseFloat(fscWeightBasedDistanceMultiplier, 64) + if err != nil { + return 0, err + } + eiaFuelPrice, err := LookupEIAFuelPrice(appCtx, pickupDateForFSC) + if err != nil { + return 0, err + } + price, _, err = p.fuelSurchargePricer.Price(appCtx, pickupDateForFSC, unit.Miles(distance), primeEstimatedWeight, fscWeightBasedDistanceMultiplierFloat, eiaFuelPrice, isPPM) + if err != nil { + return 0, err + } + + } + return price, nil + } + return 0, nil +} + func (p *mtoServiceItemUpdater) findServiceItem(appCtx appcontext.AppContext, serviceItemID uuid.UUID) (*models.MTOServiceItem, error) { var serviceItem models.MTOServiceItem err := appCtx.DB().Q().EagerPreload( @@ -299,6 +422,21 @@ func (p *mtoServiceItemUpdater) convertItemToCustomerExpense( return &serviceItem, nil } +// UpdateMTOServiceItemPricingEstimate updates the MTO Service Item pricing estimate +func (p *mtoServiceItemUpdater) UpdateMTOServiceItemPricingEstimate( + appCtx appcontext.AppContext, + mtoServiceItem *models.MTOServiceItem, + shipment models.MTOShipment, + eTag string, +) (*models.MTOServiceItem, error) { + estimatedPrice, err := p.findEstimatedPrice(appCtx, mtoServiceItem, shipment) + if estimatedPrice != 0 && err != nil { + mtoServiceItem.PricingEstimate = &estimatedPrice + return p.UpdateMTOServiceItem(appCtx, mtoServiceItem, eTag, UpdateMTOServiceItemBasicValidator) + } + return mtoServiceItem, err +} + // UpdateMTOServiceItemBasic updates the MTO Service Item using base validators func (p *mtoServiceItemUpdater) UpdateMTOServiceItemBasic( appCtx appcontext.AppContext, diff --git a/pkg/services/mto_service_item/mto_service_item_updater_test.go b/pkg/services/mto_service_item/mto_service_item_updater_test.go index 47c55beda43..22259ed6aad 100644 --- a/pkg/services/mto_service_item/mto_service_item_updater_test.go +++ b/pkg/services/mto_service_item/mto_service_item_updater_test.go @@ -23,6 +23,7 @@ import ( "github.com/transcom/mymove/pkg/models" mocks "github.com/transcom/mymove/pkg/route/mocks" "github.com/transcom/mymove/pkg/services/address" + "github.com/transcom/mymove/pkg/services/ghcrateengine" moverouter "github.com/transcom/mymove/pkg/services/move" movetaskorder "github.com/transcom/mymove/pkg/services/move_task_order" mtoshipment "github.com/transcom/mymove/pkg/services/mto_shipment" @@ -48,7 +49,7 @@ func (suite *MTOServiceItemServiceSuite) TestMTOServiceItemUpdater() { mock.Anything, mock.Anything, ).Return(400, nil) - updater := NewMTOServiceItemUpdater(planner, builder, moveRouter, shipmentFetcher, addressCreator) + updater := NewMTOServiceItemUpdater(planner, builder, moveRouter, shipmentFetcher, addressCreator, ghcrateengine.NewDomesticUnpackPricer(), ghcrateengine.NewDomesticLinehaulPricer(), ghcrateengine.NewDomesticDestinationPricer(), ghcrateengine.NewFuelSurchargePricer(), ghcrateengine.NewDomesticDestinationSITDeliveryPricer(), ghcrateengine.NewDomesticOriginSITFuelSurchargePricer()) setupServiceItem := func() (models.MTOServiceItem, string) { serviceItem := testdatagen.MakeDefaultMTOServiceItem(suite.DB()) @@ -1757,7 +1758,7 @@ func (suite *MTOServiceItemServiceSuite) TestUpdateMTOServiceItemStatus() { mock.Anything, mock.Anything, ).Return(400, nil) - updater := NewMTOServiceItemUpdater(planner, builder, moveRouter, shipmentFetcher, addressCreator) + updater := NewMTOServiceItemUpdater(planner, builder, moveRouter, shipmentFetcher, addressCreator, ghcrateengine.NewDomesticUnpackPricer(), ghcrateengine.NewDomesticLinehaulPricer(), ghcrateengine.NewDomesticDestinationPricer(), ghcrateengine.NewFuelSurchargePricer(), ghcrateengine.NewDomesticDestinationSITDeliveryPricer(), ghcrateengine.NewDomesticOriginSITFuelSurchargePricer()) rejectionReason := models.StringPointer("") diff --git a/pkg/services/mto_service_item/mto_service_item_validators.go b/pkg/services/mto_service_item/mto_service_item_validators.go index 09d9c1b09ee..f3423517301 100644 --- a/pkg/services/mto_service_item/mto_service_item_validators.go +++ b/pkg/services/mto_service_item/mto_service_item_validators.go @@ -616,6 +616,9 @@ func (v *updateMTOServiceItemData) setNewMTOServiceItem() *models.MTOServiceItem newMTOServiceItem.ActualWeight = services.SetOptionalPoundField( v.updatedServiceItem.ActualWeight, newMTOServiceItem.ActualWeight) + newMTOServiceItem.PricingEstimate = services.SetNoNilOptionalCentField( + v.updatedServiceItem.PricingEstimate, newMTOServiceItem.PricingEstimate) + return &newMTOServiceItem } diff --git a/pkg/services/shipment_address_update/shipment_address_update_requester.go b/pkg/services/shipment_address_update/shipment_address_update_requester.go index 1b75b668336..18f0ffda5a4 100644 --- a/pkg/services/shipment_address_update/shipment_address_update_requester.go +++ b/pkg/services/shipment_address_update/shipment_address_update_requester.go @@ -465,7 +465,7 @@ func (f *shipmentAddressUpdateRequester) ReviewShipmentAddressChange(appCtx appc if tooApprovalStatus == models.ShipmentAddressUpdateStatusApproved { queryBuilder := query.NewQueryBuilder() - serviceItemUpdater := mtoserviceitem.NewMTOServiceItemUpdater(f.planner, queryBuilder, f.moveRouter, f.shipmentFetcher, f.addressCreator) + serviceItemUpdater := mtoserviceitem.NewMTOServiceItemUpdater(f.planner, queryBuilder, f.moveRouter, f.shipmentFetcher, f.addressCreator, ghcrateengine.NewDomesticUnpackPricer(), ghcrateengine.NewDomesticLinehaulPricer(), ghcrateengine.NewDomesticDestinationPricer(), ghcrateengine.NewFuelSurchargePricer(), ghcrateengine.NewDomesticDestinationSITDeliveryPricer(), ghcrateengine.NewDomesticOriginSITFuelSurchargePricer()) serviceItemCreator := mtoserviceitem.NewMTOServiceItemCreator(f.planner, queryBuilder, f.moveRouter, ghcrateengine.NewDomesticUnpackPricer(), ghcrateengine.NewDomesticPackPricer(), ghcrateengine.NewDomesticLinehaulPricer(), ghcrateengine.NewDomesticShorthaulPricer(), ghcrateengine.NewDomesticOriginPricer(), ghcrateengine.NewDomesticDestinationPricer(), ghcrateengine.NewFuelSurchargePricer()) addressUpdate.Status = models.ShipmentAddressUpdateStatusApproved @@ -497,6 +497,38 @@ func (f *shipmentAddressUpdateRequester) ReviewShipmentAddressChange(appCtx appc return nil, apperror.NewQueryError("MTOShipment", err, "") } + shipmentHasApprovedDestSIT := f.doesShipmentContainApprovedDestinationSIT(shipmentDetails) + + for i, serviceItem := range shipmentDetails.MTOServiceItems { + var updatedServiceItem *models.MTOServiceItem + if serviceItem.ReService.Code == models.ReServiceCodeDDP || serviceItem.ReService.Code == models.ReServiceCodeDUPK { + updatedServiceItem, err = serviceItemUpdater.UpdateMTOServiceItemPricingEstimate(appCtx, &serviceItem, shipment, etag.GenerateEtag(serviceItem.UpdatedAt)) + if err != nil { + return nil, apperror.NewUpdateError(serviceItem.ReServiceID, err.Error()) + } + } + + if !shipmentHasApprovedDestSIT { + if serviceItem.ReService.Code == models.ReServiceCodeDLH || serviceItem.ReService.Code == models.ReServiceCodeFSC { + updatedServiceItem, err = serviceItemUpdater.UpdateMTOServiceItemPricingEstimate(appCtx, &serviceItem, shipment, etag.GenerateEtag(serviceItem.UpdatedAt)) + if err != nil { + return nil, apperror.NewUpdateError(serviceItem.ReServiceID, err.Error()) + } + } + } else { + if serviceItem.ReService.Code == models.ReServiceCodeDDSFSC || serviceItem.ReService.Code == models.ReServiceCodeDDDSIT { + updatedServiceItem, err = serviceItemUpdater.UpdateMTOServiceItemPricingEstimate(appCtx, &serviceItem, shipment, etag.GenerateEtag(serviceItem.UpdatedAt)) + if err != nil { + return nil, apperror.NewUpdateError(serviceItem.ReServiceID, err.Error()) + } + } + } + + if updatedServiceItem != nil { + shipmentDetails.MTOServiceItems[i] = *updatedServiceItem + } + } + // If the pricing type has changed then we automatically reject the DLH or DSH service item on the shipment since it is now inaccurate var approvedPaymentRequestsExistsForServiceItem bool if haulPricingTypeHasChanged && len(shipment.MTOServiceItems) > 0 { @@ -512,8 +544,6 @@ func (f *shipmentAddressUpdateRequester) ReviewShipmentAddressChange(appCtx appc return nil, apperror.NewQueryError("ServiceItemPaymentRequests", err, "") } - shipmentHasApprovedDestSIT := f.doesShipmentContainApprovedDestinationSIT(shipmentDetails) - // do NOT regenerate any service items if the following conditions exist: // payment has already been approved for DLH or DSH service item // destination SIT is on shipment and any of the service items have an appproved status diff --git a/pkg/services/sit_extension/sit_extension_denier.go b/pkg/services/sit_extension/sit_extension_denier.go index 5d677c353b4..bc0ddf8c100 100644 --- a/pkg/services/sit_extension/sit_extension_denier.go +++ b/pkg/services/sit_extension/sit_extension_denier.go @@ -15,6 +15,7 @@ import ( routemocks "github.com/transcom/mymove/pkg/route/mocks" "github.com/transcom/mymove/pkg/services" "github.com/transcom/mymove/pkg/services/address" + "github.com/transcom/mymove/pkg/services/ghcrateengine" mtoserviceitem "github.com/transcom/mymove/pkg/services/mto_service_item" mtoshipment "github.com/transcom/mymove/pkg/services/mto_shipment" "github.com/transcom/mymove/pkg/services/query" @@ -33,7 +34,7 @@ func NewSITExtensionDenier(moveRouter services.MoveRouter) services.SITExtension mock.Anything, mock.Anything, ).Return(400, nil) - return &sitExtensionDenier{moveRouter, mtoserviceitem.NewMTOServiceItemUpdater(planner, query.NewQueryBuilder(), moveRouter, mtoshipment.NewMTOShipmentFetcher(), address.NewAddressCreator())} + return &sitExtensionDenier{moveRouter, mtoserviceitem.NewMTOServiceItemUpdater(planner, query.NewQueryBuilder(), moveRouter, mtoshipment.NewMTOShipmentFetcher(), address.NewAddressCreator(), ghcrateengine.NewDomesticUnpackPricer(), ghcrateengine.NewDomesticLinehaulPricer(), ghcrateengine.NewDomesticDestinationPricer(), ghcrateengine.NewFuelSurchargePricer(), ghcrateengine.NewDomesticDestinationSITDeliveryPricer(), ghcrateengine.NewDomesticOriginSITFuelSurchargePricer())} } // DenySITExtension denies the SIT Extension diff --git a/pkg/testdatagen/scenario/shared.go b/pkg/testdatagen/scenario/shared.go index 44f2bce1b66..e39b3b3a564 100644 --- a/pkg/testdatagen/scenario/shared.go +++ b/pkg/testdatagen/scenario/shared.go @@ -4274,7 +4274,7 @@ func createHHGWithOriginSITServiceItems( mock.Anything, mock.Anything, ).Return(400, nil) - serviceItemUpdator := mtoserviceitem.NewMTOServiceItemUpdater(planner, queryBuilder, moveRouter, shipmentFetcher, addressCreator) + serviceItemUpdator := mtoserviceitem.NewMTOServiceItemUpdater(planner, queryBuilder, moveRouter, shipmentFetcher, addressCreator, ghcrateengine.NewDomesticUnpackPricer(), ghcrateengine.NewDomesticLinehaulPricer(), ghcrateengine.NewDomesticDestinationPricer(), ghcrateengine.NewFuelSurchargePricer(), ghcrateengine.NewDomesticDestinationSITDeliveryPricer(), ghcrateengine.NewDomesticOriginSITFuelSurchargePricer()) var originFirstDaySIT models.MTOServiceItem var originAdditionalDaySIT models.MTOServiceItem @@ -4535,7 +4535,7 @@ func createHHGWithDestinationSITServiceItems(appCtx appcontext.AppContext, prime mock.Anything, mock.Anything, ).Return(400, nil) - serviceItemUpdator := mtoserviceitem.NewMTOServiceItemUpdater(planner, queryBuilder, moveRouter, shipmentFetcher, addressCreator) + serviceItemUpdator := mtoserviceitem.NewMTOServiceItemUpdater(planner, queryBuilder, moveRouter, shipmentFetcher, addressCreator, ghcrateengine.NewDomesticUnpackPricer(), ghcrateengine.NewDomesticLinehaulPricer(), ghcrateengine.NewDomesticDestinationPricer(), ghcrateengine.NewFuelSurchargePricer(), ghcrateengine.NewDomesticDestinationSITDeliveryPricer(), ghcrateengine.NewDomesticOriginSITFuelSurchargePricer()) var destinationFirstDaySIT models.MTOServiceItem var destinationAdditionalDaySIT models.MTOServiceItem @@ -5014,7 +5014,7 @@ func createHHGWithPaymentServiceItems( mock.Anything, mock.Anything, ).Return(400, nil) - serviceItemUpdater := mtoserviceitem.NewMTOServiceItemUpdater(planner, queryBuilder, moveRouter, shipmentFetcher, addressCreator) + serviceItemUpdater := mtoserviceitem.NewMTOServiceItemUpdater(planner, queryBuilder, moveRouter, shipmentFetcher, addressCreator, ghcrateengine.NewDomesticUnpackPricer(), ghcrateengine.NewDomesticLinehaulPricer(), ghcrateengine.NewDomesticDestinationPricer(), ghcrateengine.NewFuelSurchargePricer(), ghcrateengine.NewDomesticDestinationSITDeliveryPricer(), ghcrateengine.NewDomesticOriginSITFuelSurchargePricer()) var originFirstDaySIT models.MTOServiceItem var originAdditionalDaySIT models.MTOServiceItem From b04c7e8ea8e10474e02bd52f17c50fef6dc5a26f Mon Sep 17 00:00:00 2001 From: Jon Spight Date: Wed, 13 Nov 2024 16:03:22 +0000 Subject: [PATCH 02/32] Partial --- pkg/gen/ghcapi/embedded_spec.go | 24 +++++++++++++-- .../get_payment_requests_queue_parameters.go | 29 ++++++++++++++++++- .../get_payment_requests_queue_urlbuilder.go | 9 ++++++ pkg/gen/ghcmessages/queue_payment_request.go | 3 ++ .../internal/payloads/model_to_payload.go | 21 ++++++++++++++ pkg/handlers/ghcapi/queues.go | 1 + pkg/services/payment_request.go | 1 + .../payment_request_list_fetcher.go | 12 +++++++- .../PaymentRequestQueue.jsx | 4 +++ .../PaymentRequestQueue.test.jsx | 4 +++ swagger-def/ghc.yaml | 8 ++++- swagger/ghc.yaml | 7 +++++ 12 files changed, 118 insertions(+), 5 deletions(-) diff --git a/pkg/gen/ghcapi/embedded_spec.go b/pkg/gen/ghcapi/embedded_spec.go index 70103ff2422..c7da564d8d3 100644 --- a/pkg/gen/ghcapi/embedded_spec.go +++ b/pkg/gen/ghcapi/embedded_spec.go @@ -4540,7 +4540,8 @@ func init() { "emplid", "age", "originDutyLocation", - "assignedTo" + "assignedTo", + "counselingOffice" ], "type": "string", "description": "field that results should be sorted by", @@ -4617,6 +4618,12 @@ func init() { "name": "assignedTo", "in": "query" }, + { + "type": "string", + "description": "filters using a counselingOffice name of the move", + "name": "counselingOffice", + "in": "query" + }, { "uniqueItems": true, "type": "array", @@ -12094,6 +12101,9 @@ func init() { "availableOfficeUsers": { "$ref": "#/definitions/AvailableOfficeUsers" }, + "counselingOffice": { + "type": "string" + }, "customer": { "$ref": "#/definitions/Customer" }, @@ -20097,7 +20107,8 @@ func init() { "emplid", "age", "originDutyLocation", - "assignedTo" + "assignedTo", + "counselingOffice" ], "type": "string", "description": "field that results should be sorted by", @@ -20174,6 +20185,12 @@ func init() { "name": "assignedTo", "in": "query" }, + { + "type": "string", + "description": "filters using a counselingOffice name of the move", + "name": "counselingOffice", + "in": "query" + }, { "uniqueItems": true, "type": "array", @@ -28094,6 +28111,9 @@ func init() { "availableOfficeUsers": { "$ref": "#/definitions/AvailableOfficeUsers" }, + "counselingOffice": { + "type": "string" + }, "customer": { "$ref": "#/definitions/Customer" }, diff --git a/pkg/gen/ghcapi/ghcoperations/queues/get_payment_requests_queue_parameters.go b/pkg/gen/ghcapi/ghcoperations/queues/get_payment_requests_queue_parameters.go index 4016167d41d..809e4d8c520 100644 --- a/pkg/gen/ghcapi/ghcoperations/queues/get_payment_requests_queue_parameters.go +++ b/pkg/gen/ghcapi/ghcoperations/queues/get_payment_requests_queue_parameters.go @@ -43,6 +43,10 @@ type GetPaymentRequestsQueueParams struct { In: query */ Branch *string + /*filters using a counselingOffice name of the move + In: query + */ + CounselingOffice *string /* In: query */ @@ -124,6 +128,11 @@ func (o *GetPaymentRequestsQueueParams) BindRequest(r *http.Request, route *midd 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) @@ -235,6 +244,24 @@ func (o *GetPaymentRequestsQueueParams) bindBranch(rawData []string, hasKey bool return nil } +// bindCounselingOffice binds and validates parameter CounselingOffice from query. +func (o *GetPaymentRequestsQueueParams) 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 *GetPaymentRequestsQueueParams) bindCustomerName(rawData []string, hasKey bool, formats strfmt.Registry) error { var raw string @@ -464,7 +491,7 @@ func (o *GetPaymentRequestsQueueParams) bindSort(rawData []string, hasKey bool, // validateSort carries on validations for parameter Sort func (o *GetPaymentRequestsQueueParams) validateSort(formats strfmt.Registry) error { - if err := validate.EnumCase("sort", "query", *o.Sort, []interface{}{"customerName", "locator", "submittedAt", "branch", "status", "dodID", "emplid", "age", "originDutyLocation", "assignedTo"}, true); err != nil { + if err := validate.EnumCase("sort", "query", *o.Sort, []interface{}{"customerName", "locator", "submittedAt", "branch", "status", "dodID", "emplid", "age", "originDutyLocation", "assignedTo", "counselingOffice"}, true); err != nil { return err } diff --git a/pkg/gen/ghcapi/ghcoperations/queues/get_payment_requests_queue_urlbuilder.go b/pkg/gen/ghcapi/ghcoperations/queues/get_payment_requests_queue_urlbuilder.go index 3d092ff6eb1..6cad079f08c 100644 --- a/pkg/gen/ghcapi/ghcoperations/queues/get_payment_requests_queue_urlbuilder.go +++ b/pkg/gen/ghcapi/ghcoperations/queues/get_payment_requests_queue_urlbuilder.go @@ -18,6 +18,7 @@ import ( type GetPaymentRequestsQueueURL struct { AssignedTo *string Branch *string + CounselingOffice *string CustomerName *string DestinationDutyLocation *string DodID *string @@ -83,6 +84,14 @@ func (o *GetPaymentRequestsQueueURL) Build() (*url.URL, error) { 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 diff --git a/pkg/gen/ghcmessages/queue_payment_request.go b/pkg/gen/ghcmessages/queue_payment_request.go index 6f173d37b76..5b4a387fae1 100644 --- a/pkg/gen/ghcmessages/queue_payment_request.go +++ b/pkg/gen/ghcmessages/queue_payment_request.go @@ -31,6 +31,9 @@ type QueuePaymentRequest struct { // available office users AvailableOfficeUsers AvailableOfficeUsers `json:"availableOfficeUsers,omitempty"` + // counseling office + CounselingOffice string `json:"counselingOffice,omitempty"` + // customer Customer *Customer `json:"customer,omitempty"` diff --git a/pkg/handlers/ghcapi/internal/payloads/model_to_payload.go b/pkg/handlers/ghcapi/internal/payloads/model_to_payload.go index 1d45414fb52..91f95b356e6 100644 --- a/pkg/handlers/ghcapi/internal/payloads/model_to_payload.go +++ b/pkg/handlers/ghcapi/internal/payloads/model_to_payload.go @@ -3,6 +3,7 @@ package payloads import ( "encoding/json" "errors" + "fmt" "math" "strings" "time" @@ -2292,7 +2293,23 @@ func QueuePaymentRequests(paymentRequests *models.PaymentRequests, officeUsers [ queuePaymentRequests := make(ghcmessages.QueuePaymentRequests, len(*paymentRequests)) for i, paymentRequest := range *paymentRequests { + + var transportationOffice string + var transportationOfficeId uuid.UUID + moveTaskOrder := paymentRequest.MoveTaskOrder + + if moveTaskOrder.CounselingOffice != nil { + transportationOffice = moveTaskOrder.CounselingOffice.Name + transportationOfficeId = *moveTaskOrder.CounselingOfficeID + } + fmt.Println("--------------Start----------------------------------------------------------------") + fmt.Println() + fmt.Println("movetaskorder: ", moveTaskOrder.CounselingOfficeID) + fmt.Println("counseling office: ", transportationOffice) + fmt.Println("counseling office ID: ", transportationOfficeId) + fmt.Println() + fmt.Println("--------------end----------------------------------------------------------------") orders := moveTaskOrder.Orders var gbloc ghcmessages.GBLOC if moveTaskOrder.ShipmentGBLOC[0].GBLOC != nil { @@ -2312,7 +2329,11 @@ func QueuePaymentRequests(paymentRequests *models.PaymentRequests, officeUsers [ OrderType: (*string)(orders.OrdersType.Pointer()), LockedByOfficeUserID: handlers.FmtUUIDPtr(moveTaskOrder.LockedByOfficeUserID), LockExpiresAt: handlers.FmtDateTimePtr(moveTaskOrder.LockExpiresAt), + // CounselingOffice: moveTaskOrder.CounselingOfficeID, - convert from uuid to string } + // if paymentRequest.MoveTaskOrder.CounselingOfficeID { + // TransportationOfficesFetcher.GetTransportationOffice + // } if paymentRequest.MoveTaskOrder.TIOAssignedUser != nil { queuePaymentRequests[i].AssignedTo = AssignedOfficeUser(paymentRequest.MoveTaskOrder.TIOAssignedUser) diff --git a/pkg/handlers/ghcapi/queues.go b/pkg/handlers/ghcapi/queues.go index 1f69143ce16..c3ff74eae87 100644 --- a/pkg/handlers/ghcapi/queues.go +++ b/pkg/handlers/ghcapi/queues.go @@ -250,6 +250,7 @@ func (h GetPaymentRequestsQueueHandler) Handle( OriginDutyLocation: params.OriginDutyLocation, OrderType: params.OrderType, TIOAssignedUser: params.AssignedTo, + CounselingOffice: params.CounselingOffice, } listPaymentRequestParams.Status = []string{string(models.QueuePaymentRequestPaymentRequested)} diff --git a/pkg/services/payment_request.go b/pkg/services/payment_request.go index 69a9d67c9e7..de9d7e3db40 100644 --- a/pkg/services/payment_request.go +++ b/pkg/services/payment_request.go @@ -94,6 +94,7 @@ type FetchPaymentRequestListParams struct { OrderType *string ViewAsGBLOC *string TIOAssignedUser *string + CounselingOffice *string } // ShipmentPaymentSITBalance is a public struct that's used to return current SIT balances to the TIO for a payment diff --git a/pkg/services/payment_request/payment_request_list_fetcher.go b/pkg/services/payment_request/payment_request_list_fetcher.go index 6794c9abc9e..bbee5c3923a 100644 --- a/pkg/services/payment_request/payment_request_list_fetcher.go +++ b/pkg/services/payment_request/payment_request_list_fetcher.go @@ -103,8 +103,9 @@ func (f *paymentRequestListFetcher) FetchPaymentRequestList(appCtx appcontext.Ap originDutyLocationQuery := dutyLocationFilter(params.OriginDutyLocation) orderQuery := sortOrder(params.Sort, params.Order) tioAssignedUserQuery := tioAssignedUserFilter(params.TIOAssignedUser) + counselingQuery := counselingOfficeFilter(params.CounselingOffice) - options := [12]QueryOption{branchQuery, locatorQuery, dodIDQuery, customerNameQuery, dutyLocationQuery, statusQuery, originDutyLocationQuery, submittedAtQuery, gblocQuery, orderQuery, emplidQuery, tioAssignedUserQuery} + options := [13]QueryOption{branchQuery, locatorQuery, dodIDQuery, customerNameQuery, dutyLocationQuery, statusQuery, originDutyLocationQuery, submittedAtQuery, gblocQuery, orderQuery, emplidQuery, tioAssignedUserQuery, counselingQuery} for _, option := range options { if option != nil { @@ -161,6 +162,7 @@ func (f *paymentRequestListFetcher) FetchPaymentRequestListByMove(appCtx appcont "PaymentServiceItems.MTOServiceItem.ReService", "PaymentServiceItems.MTOServiceItem.MTOShipment", "ProofOfServiceDocs.PrimeUploads.Upload", + "CounselingOffice", "MoveTaskOrder.Contractor", "MoveTaskOrder.Orders.ServiceMember", "MoveTaskOrder.Orders.NewDutyLocation.Address", @@ -428,3 +430,11 @@ func tioAssignedUserFilter(tioAssigned *string) QueryOption { } } } + +func counselingOfficeFilter(office *string) QueryOption { + return func(query *pop.Query) { + if office != nil { + query.Where("transportation_offices.name ILIKE ?", "%"+*office+"%") + } + } +} diff --git a/src/pages/Office/PaymentRequestQueue/PaymentRequestQueue.jsx b/src/pages/Office/PaymentRequestQueue/PaymentRequestQueue.jsx index 74511206562..e68769114fe 100644 --- a/src/pages/Office/PaymentRequestQueue/PaymentRequestQueue.jsx +++ b/src/pages/Office/PaymentRequestQueue/PaymentRequestQueue.jsx @@ -134,6 +134,10 @@ export const columns = (moveLockFlag, isQueueManagementEnabled, showBranchFilter }, ), createHeader('Origin GBLOC', 'originGBLOC', { disableSortBy: true }), + createHeader('Counseling office', 'counselingOffice', { + id: 'counselingOffice', + isFilterable: true, + }), createHeader('Origin Duty Location', 'originDutyLocation.name', { id: 'originDutyLocation', isFilterable: true, diff --git a/src/pages/Office/PaymentRequestQueue/PaymentRequestQueue.test.jsx b/src/pages/Office/PaymentRequestQueue/PaymentRequestQueue.test.jsx index 41ee979d30a..3fb9d1ff5b2 100644 --- a/src/pages/Office/PaymentRequestQueue/PaymentRequestQueue.test.jsx +++ b/src/pages/Office/PaymentRequestQueue/PaymentRequestQueue.test.jsx @@ -59,6 +59,7 @@ jest.mock('hooks/queries', () => ({ locator: 'R993T7', moveID: '5d4b25bb-eb04-4c03-9a81-ee0398cb779e', originGBLOC: 'LKNQ', + counselingOffice: '67592323-fc7e-4b35-83a7-57faa53b7acf', status: 'PENDING', submittedAt: '2020-10-15T23:48:35.420Z', originDutyLocation: { @@ -98,6 +99,7 @@ jest.mock('hooks/queries', () => ({ locator: '0OOGAB', moveID: '8f29e53d-e816-4476-bfee-f38d07b94f2d', originGBLOC: 'LKNQ', + counselingOffice: '67592323-fc7e-4b35-83a7-57faa53b7acf', status: 'PENDING', submittedAt: '2020-10-17T23:48:35.420Z', originDutyLocation: { @@ -195,6 +197,7 @@ describe('PaymentRequestQueue', () => { expect(firstPaymentRequest.find('td.branch').text()).toBe('Coast Guard'); expect(firstPaymentRequest.find('td.originGBLOC').text()).toBe('LKNQ'); expect(firstPaymentRequest.find('td.originDutyLocation').text()).toBe('Scott AFB'); + expect(firstPaymentRequest.find('td.counselingOffice').text()).toBe('67592323-fc7e-4b35-83a7-57faa53b7acf'); const secondPaymentRequest = paymentRequests.at(1); expect(secondPaymentRequest.find('td.customerName').text()).toBe('Booga, Ooga'); @@ -207,6 +210,7 @@ describe('PaymentRequestQueue', () => { expect(secondPaymentRequest.find('td.branch').text()).toBe('Navy'); expect(secondPaymentRequest.find('td.originGBLOC').text()).toBe('LKNQ'); expect(secondPaymentRequest.find('td.originDutyLocation').text()).toBe('Scott AFB'); + expect(secondPaymentRequest.find('td.counselingOffice').text()).toBe('67592323-fc7e-4b35-83a7-57faa53b7acf'); }); it('renders the table with data and expected values with queue management ff', async () => { diff --git a/swagger-def/ghc.yaml b/swagger-def/ghc.yaml index 188e99953b1..f6d2a424ba7 100644 --- a/swagger-def/ghc.yaml +++ b/swagger-def/ghc.yaml @@ -3583,7 +3583,7 @@ paths: - in: query name: sort type: string - enum: [customerName, locator, submittedAt, branch, status, dodID, emplid, age, originDutyLocation, assignedTo] + enum: [customerName, locator, submittedAt, branch, status, dodID, emplid, age, originDutyLocation, assignedTo, counselingOffice] description: field that results should be sorted by - in: query name: order @@ -3629,6 +3629,10 @@ paths: type: string description: | Used to illustrate which user is assigned to this payment request. + - in: query + name: counselingOffice + type: string + description: filters using a counselingOffice name of the move - in: query name: status type: array @@ -6943,6 +6947,8 @@ definitions: $ref: '#/definitions/AvailableOfficeUsers' assignable: type: boolean + counselingOffice: + type: string QueuePaymentRequests: type: array items: diff --git a/swagger/ghc.yaml b/swagger/ghc.yaml index 01f2702035d..cd5f0ad00ef 100644 --- a/swagger/ghc.yaml +++ b/swagger/ghc.yaml @@ -3749,6 +3749,7 @@ paths: - age - originDutyLocation - assignedTo + - counselingOffice description: field that results should be sorted by - in: query name: order @@ -3798,6 +3799,10 @@ paths: type: string description: | Used to illustrate which user is assigned to this payment request. + - in: query + name: counselingOffice + type: string + description: filters using a counselingOffice name of the move - in: query name: status type: array @@ -7241,6 +7246,8 @@ definitions: $ref: '#/definitions/AvailableOfficeUsers' assignable: type: boolean + counselingOffice: + type: string QueuePaymentRequests: type: array items: From a84a0b16e65f2514f8489b140256528511ebc2f5 Mon Sep 17 00:00:00 2001 From: Cory Kleinjan Date: Wed, 13 Nov 2024 11:16:59 -0600 Subject: [PATCH 03/32] Adding in addtional service items to be repriced --- .../mto_service_item_updater.go | 66 +++++++++++++++++++ 1 file changed, 66 insertions(+) diff --git a/pkg/services/mto_service_item/mto_service_item_updater.go b/pkg/services/mto_service_item/mto_service_item_updater.go index 1bbbb60afac..880c235bddf 100644 --- a/pkg/services/mto_service_item/mto_service_item_updater.go +++ b/pkg/services/mto_service_item/mto_service_item_updater.go @@ -199,6 +199,72 @@ func (p *mtoServiceItemUpdater) findEstimatedPrice(appCtx appcontext.AppContext, return 0, err } } + // unpacking + if serviceItem.ReService.Code == models.ReServiceCodeDUPK { + domesticServiceArea, err := fetchDomesticServiceArea(appCtx, contractCode, mtoShipment.DestinationAddress.PostalCode) + if err != nil { + return 0, err + } + price, _, err = p.unpackPricer.Price(appCtx, contractCode, requestedPickupDate, *mtoShipment.PrimeEstimatedWeight, domesticServiceArea.ServicesSchedule, isPPM) + if err != nil { + return 0, err + } + } + // destination sit delivery + if serviceItem.ReService.Code == models.ReServiceCodeDDDSIT { + var pickupDate time.Time + if mtoShipment.ActualPickupDate != nil { + pickupDate = *mtoShipment.ActualPickupDate + } else { + pickupDate = requestedPickupDate + } + domesticServiceArea, err := fetchDomesticServiceArea(appCtx, contractCode, mtoShipment.DestinationAddress.PostalCode) + if err != nil { + return 0, err + } + if mtoShipment.DestinationAddress != nil { + distance, err = p.planner.ZipTransitDistance(appCtx, serviceItem.SITDestinationFinalAddress.PostalCode, mtoShipment.DestinationAddress.PostalCode) + if err != nil { + return 0, err + } + } + price, _, err = p.sitDeliverPricer.Price(appCtx, contractCode, pickupDate, *mtoShipment.PrimeEstimatedWeight, domesticServiceArea.ServiceArea, domesticServiceArea.SITPDSchedule, mtoShipment.DestinationAddress.PostalCode, serviceItem.SITDestinationFinalAddress.PostalCode, unit.Miles(distance)) + if err != nil { + return 0, err + } + } + // destination sit fuel surcharge + if serviceItem.ReService.Code == models.ReServiceCodeDDSFSC { + var pickupDateForFSC time.Time + if mtoShipment.ActualPickupDate != nil { + pickupDateForFSC = *mtoShipment.ActualPickupDate + } else { + pickupDateForFSC = requestedPickupDate + } + + if mtoShipment.DestinationAddress != nil { + distance, err = p.planner.ZipTransitDistance(appCtx, serviceItem.SITDestinationFinalAddress.PostalCode, mtoShipment.DestinationAddress.PostalCode) + if err != nil { + return 0, err + } + } + fscWeightBasedDistanceMultiplier, err := LookupFSCWeightBasedDistanceMultiplier(appCtx, primeEstimatedWeight) + if err != nil { + return 0, err + } + fscWeightBasedDistanceMultiplierFloat, err := strconv.ParseFloat(fscWeightBasedDistanceMultiplier, 64) + if err != nil { + return 0, err + } + eiaFuelPrice, err := LookupEIAFuelPrice(appCtx, pickupDateForFSC) + if err != nil { + return 0, err + } + price, _, err = p.sitFuelSurchargePricer.Price(appCtx, *mtoShipment.ActualPickupDate, unit.Miles(distance), *mtoShipment.PrimeEstimatedWeight, fscWeightBasedDistanceMultiplierFloat, eiaFuelPrice, isPPM) + if err != nil { + return 0, err + } + } // fuel surcharge if serviceItem.ReService.Code == models.ReServiceCodeFSC { var pickupDateForFSC time.Time From 5afa0f2380abb24d36d8e8acbf6c848e347a4f99 Mon Sep 17 00:00:00 2001 From: Cory Kleinjan Date: Wed, 13 Nov 2024 13:16:33 -0600 Subject: [PATCH 04/32] Handling weight changes --- .../mto_service_item_updater.go | 30 ++++++++++++------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/pkg/services/mto_service_item/mto_service_item_updater.go b/pkg/services/mto_service_item/mto_service_item_updater.go index 880c235bddf..35b549159b2 100644 --- a/pkg/services/mto_service_item/mto_service_item_updater.go +++ b/pkg/services/mto_service_item/mto_service_item_updater.go @@ -141,7 +141,17 @@ func (p *mtoServiceItemUpdater) findEstimatedPrice(appCtx appcontext.AppContext, requestedPickupDate := *mtoShipment.RequestedPickupDate currTime := time.Now() var distance int - primeEstimatedWeight := *mtoShipment.PrimeEstimatedWeight + + var shipmentWeight unit.Pound + if mtoShipment.PrimeActualWeight != nil { + shipmentWeight = *mtoShipment.PrimeActualWeight + } else { + if mtoShipment.PrimeEstimatedWeight != nil { + shipmentWeight = *mtoShipment.PrimeEstimatedWeight + } else { + shipmentWeight = 0 + } + } contractCode, err := FetchContractCode(appCtx, currTime) if err != nil { @@ -163,7 +173,7 @@ func (p *mtoServiceItemUpdater) findEstimatedPrice(appCtx appcontext.AppContext, } } - price, _, err = p.destinationPricer.Price(appCtx, contractCode, requestedPickupDate, *mtoShipment.PrimeEstimatedWeight, domesticServiceArea.ServiceArea, isPPM) + price, _, err = p.destinationPricer.Price(appCtx, contractCode, requestedPickupDate, shipmentWeight, domesticServiceArea.ServiceArea, isPPM) if err != nil { return 0, err } @@ -176,7 +186,7 @@ func (p *mtoServiceItemUpdater) findEstimatedPrice(appCtx appcontext.AppContext, serviceScheduleDestination := domesticServiceArea.ServicesSchedule - price, _, err = p.unpackPricer.Price(appCtx, contractCode, requestedPickupDate, *mtoShipment.PrimeEstimatedWeight, serviceScheduleDestination, isPPM) + price, _, err = p.unpackPricer.Price(appCtx, contractCode, requestedPickupDate, shipmentWeight, serviceScheduleDestination, isPPM) if err != nil { return 0, err } @@ -194,7 +204,7 @@ func (p *mtoServiceItemUpdater) findEstimatedPrice(appCtx appcontext.AppContext, return 0, err } } - price, _, err = p.linehaulPricer.Price(appCtx, contractCode, requestedPickupDate, unit.Miles(distance), *mtoShipment.PrimeEstimatedWeight, domesticServiceArea.ServiceArea, isPPM) + price, _, err = p.linehaulPricer.Price(appCtx, contractCode, requestedPickupDate, unit.Miles(distance), shipmentWeight, domesticServiceArea.ServiceArea, isPPM) if err != nil { return 0, err } @@ -205,7 +215,7 @@ func (p *mtoServiceItemUpdater) findEstimatedPrice(appCtx appcontext.AppContext, if err != nil { return 0, err } - price, _, err = p.unpackPricer.Price(appCtx, contractCode, requestedPickupDate, *mtoShipment.PrimeEstimatedWeight, domesticServiceArea.ServicesSchedule, isPPM) + price, _, err = p.unpackPricer.Price(appCtx, contractCode, requestedPickupDate, shipmentWeight, domesticServiceArea.ServicesSchedule, isPPM) if err != nil { return 0, err } @@ -228,7 +238,7 @@ func (p *mtoServiceItemUpdater) findEstimatedPrice(appCtx appcontext.AppContext, return 0, err } } - price, _, err = p.sitDeliverPricer.Price(appCtx, contractCode, pickupDate, *mtoShipment.PrimeEstimatedWeight, domesticServiceArea.ServiceArea, domesticServiceArea.SITPDSchedule, mtoShipment.DestinationAddress.PostalCode, serviceItem.SITDestinationFinalAddress.PostalCode, unit.Miles(distance)) + price, _, err = p.sitDeliverPricer.Price(appCtx, contractCode, pickupDate, shipmentWeight, domesticServiceArea.ServiceArea, domesticServiceArea.SITPDSchedule, mtoShipment.DestinationAddress.PostalCode, serviceItem.SITDestinationFinalAddress.PostalCode, unit.Miles(distance)) if err != nil { return 0, err } @@ -248,7 +258,7 @@ func (p *mtoServiceItemUpdater) findEstimatedPrice(appCtx appcontext.AppContext, return 0, err } } - fscWeightBasedDistanceMultiplier, err := LookupFSCWeightBasedDistanceMultiplier(appCtx, primeEstimatedWeight) + fscWeightBasedDistanceMultiplier, err := LookupFSCWeightBasedDistanceMultiplier(appCtx, shipmentWeight) if err != nil { return 0, err } @@ -260,7 +270,7 @@ func (p *mtoServiceItemUpdater) findEstimatedPrice(appCtx appcontext.AppContext, if err != nil { return 0, err } - price, _, err = p.sitFuelSurchargePricer.Price(appCtx, *mtoShipment.ActualPickupDate, unit.Miles(distance), *mtoShipment.PrimeEstimatedWeight, fscWeightBasedDistanceMultiplierFloat, eiaFuelPrice, isPPM) + price, _, err = p.sitFuelSurchargePricer.Price(appCtx, *mtoShipment.ActualPickupDate, unit.Miles(distance), shipmentWeight, fscWeightBasedDistanceMultiplierFloat, eiaFuelPrice, isPPM) if err != nil { return 0, err } @@ -284,7 +294,7 @@ func (p *mtoServiceItemUpdater) findEstimatedPrice(appCtx appcontext.AppContext, } } - fscWeightBasedDistanceMultiplier, err := LookupFSCWeightBasedDistanceMultiplier(appCtx, primeEstimatedWeight) + fscWeightBasedDistanceMultiplier, err := LookupFSCWeightBasedDistanceMultiplier(appCtx, shipmentWeight) if err != nil { return 0, err } @@ -296,7 +306,7 @@ func (p *mtoServiceItemUpdater) findEstimatedPrice(appCtx appcontext.AppContext, if err != nil { return 0, err } - price, _, err = p.fuelSurchargePricer.Price(appCtx, pickupDateForFSC, unit.Miles(distance), primeEstimatedWeight, fscWeightBasedDistanceMultiplierFloat, eiaFuelPrice, isPPM) + price, _, err = p.fuelSurchargePricer.Price(appCtx, pickupDateForFSC, unit.Miles(distance), shipmentWeight, fscWeightBasedDistanceMultiplierFloat, eiaFuelPrice, isPPM) if err != nil { return 0, err } From 8cac52414d3a078336e77491c091fe5599c78b92 Mon Sep 17 00:00:00 2001 From: Jon Spight Date: Wed, 13 Nov 2024 20:03:25 +0000 Subject: [PATCH 05/32] missing sort --- .../ghcapi/internal/payloads/model_to_payload.go | 5 +---- .../payment_request/payment_request_list_fetcher.go | 13 +++++++++---- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/pkg/handlers/ghcapi/internal/payloads/model_to_payload.go b/pkg/handlers/ghcapi/internal/payloads/model_to_payload.go index 91f95b356e6..9e3fcbac128 100644 --- a/pkg/handlers/ghcapi/internal/payloads/model_to_payload.go +++ b/pkg/handlers/ghcapi/internal/payloads/model_to_payload.go @@ -2329,11 +2329,8 @@ func QueuePaymentRequests(paymentRequests *models.PaymentRequests, officeUsers [ OrderType: (*string)(orders.OrdersType.Pointer()), LockedByOfficeUserID: handlers.FmtUUIDPtr(moveTaskOrder.LockedByOfficeUserID), LockExpiresAt: handlers.FmtDateTimePtr(moveTaskOrder.LockExpiresAt), - // CounselingOffice: moveTaskOrder.CounselingOfficeID, - convert from uuid to string + CounselingOffice: moveTaskOrder.CounselingOffice.Name, } - // if paymentRequest.MoveTaskOrder.CounselingOfficeID { - // TransportationOfficesFetcher.GetTransportationOffice - // } if paymentRequest.MoveTaskOrder.TIOAssignedUser != nil { queuePaymentRequests[i].AssignedTo = AssignedOfficeUser(paymentRequest.MoveTaskOrder.TIOAssignedUser) diff --git a/pkg/services/payment_request/payment_request_list_fetcher.go b/pkg/services/payment_request/payment_request_list_fetcher.go index bbee5c3923a..cbe5c5d1487 100644 --- a/pkg/services/payment_request/payment_request_list_fetcher.go +++ b/pkg/services/payment_request/payment_request_list_fetcher.go @@ -64,6 +64,7 @@ func (f *paymentRequestListFetcher) FetchPaymentRequestList(appCtx appcontext.Ap "MoveTaskOrder.Orders.OriginDutyLocation.TransportationOffice", "MoveTaskOrder.Orders.OriginDutyLocation.Address", "MoveTaskOrder.TIOAssignedUser", + "MoveTaskOrder.CounselingOffice", // See note further below about having to do this in a separate Load call due to a Pop issue. // "MoveTaskOrder.Orders.ServiceMember", ). @@ -72,11 +73,12 @@ func (f *paymentRequestListFetcher) FetchPaymentRequestList(appCtx appcontext.Ap InnerJoin("service_members", "orders.service_member_id = service_members.id"). InnerJoin("duty_locations", "duty_locations.id = orders.origin_duty_location_id"). // Need to use left join because some duty locations do not have transportation offices - LeftJoin("transportation_offices", "duty_locations.transportation_office_id = transportation_offices.id"). + LeftJoin("transportation_offices as origin_to", "duty_locations.transportation_office_id = origin_to.id"). // If a customer puts in an invalid ZIP for their pickup address, it won't show up in this view, // and we don't want it to get hidden from services counselors. LeftJoin("move_to_gbloc", "move_to_gbloc.move_id = moves.id"). LeftJoin("office_users as assigned_user", "moves.tio_assigned_id = assigned_user.id"). + LeftJoin("transportation_offices", "moves.counseling_transportation_office_id = transportation_offices.id"). Where("moves.show = ?", models.BoolPointer(true)) if !privileges.HasPrivilege(models.PrivilegeTypeSafety) { @@ -120,8 +122,12 @@ func (f *paymentRequestListFetcher) FetchPaymentRequestList(appCtx appcontext.Ap if params.PerPage == nil { params.PerPage = models.Int64Pointer(20) } - - err = query.GroupBy("payment_requests.id, service_members.id, moves.id, duty_locations.id, duty_locations.name, assigned_user.last_name, assigned_user.first_name").Paginate(int(*params.Page), int(*params.PerPage)).All(&paymentRequests) + fmt.Println("--------------------3---------------------------------") + fmt.Println("") + fmt.Println(params.CounselingOffice) + fmt.Println("") + fmt.Println("") + err = query.GroupBy("payment_requests.id, service_members.id, moves.id, duty_locations.id, duty_locations.name, assigned_user.last_name, assigned_user.first_name, transportation_offices.id, transportation_offices.name").Paginate(int(*params.Page), int(*params.PerPage)).All(&paymentRequests) if err != nil { return nil, 0, err } @@ -162,7 +168,6 @@ func (f *paymentRequestListFetcher) FetchPaymentRequestListByMove(appCtx appcont "PaymentServiceItems.MTOServiceItem.ReService", "PaymentServiceItems.MTOServiceItem.MTOShipment", "ProofOfServiceDocs.PrimeUploads.Upload", - "CounselingOffice", "MoveTaskOrder.Contractor", "MoveTaskOrder.Orders.ServiceMember", "MoveTaskOrder.Orders.NewDutyLocation.Address", From 8963c837b0bdd3f86d85a2efe2ffae487693df65 Mon Sep 17 00:00:00 2001 From: Jon Spight Date: Wed, 13 Nov 2024 21:00:20 +0000 Subject: [PATCH 06/32] sortable --- pkg/gen/ghcapi/embedded_spec.go | 6 ++++-- pkg/gen/ghcmessages/queue_payment_request.go | 2 +- .../internal/payloads/model_to_payload.go | 20 ++++--------------- .../payment_request_list_fetcher.go | 1 + swagger-def/ghc.yaml | 1 + swagger/ghc.yaml | 1 + 6 files changed, 12 insertions(+), 19 deletions(-) diff --git a/pkg/gen/ghcapi/embedded_spec.go b/pkg/gen/ghcapi/embedded_spec.go index c7da564d8d3..2d880c0966f 100644 --- a/pkg/gen/ghcapi/embedded_spec.go +++ b/pkg/gen/ghcapi/embedded_spec.go @@ -12102,7 +12102,8 @@ func init() { "$ref": "#/definitions/AvailableOfficeUsers" }, "counselingOffice": { - "type": "string" + "type": "string", + "x-nullable": true }, "customer": { "$ref": "#/definitions/Customer" @@ -28112,7 +28113,8 @@ func init() { "$ref": "#/definitions/AvailableOfficeUsers" }, "counselingOffice": { - "type": "string" + "type": "string", + "x-nullable": true }, "customer": { "$ref": "#/definitions/Customer" diff --git a/pkg/gen/ghcmessages/queue_payment_request.go b/pkg/gen/ghcmessages/queue_payment_request.go index 5b4a387fae1..28a4edbb0f7 100644 --- a/pkg/gen/ghcmessages/queue_payment_request.go +++ b/pkg/gen/ghcmessages/queue_payment_request.go @@ -32,7 +32,7 @@ type QueuePaymentRequest struct { AvailableOfficeUsers AvailableOfficeUsers `json:"availableOfficeUsers,omitempty"` // counseling office - CounselingOffice string `json:"counselingOffice,omitempty"` + CounselingOffice *string `json:"counselingOffice,omitempty"` // customer Customer *Customer `json:"customer,omitempty"` diff --git a/pkg/handlers/ghcapi/internal/payloads/model_to_payload.go b/pkg/handlers/ghcapi/internal/payloads/model_to_payload.go index 9e3fcbac128..4b4b7b693d3 100644 --- a/pkg/handlers/ghcapi/internal/payloads/model_to_payload.go +++ b/pkg/handlers/ghcapi/internal/payloads/model_to_payload.go @@ -3,7 +3,6 @@ package payloads import ( "encoding/json" "errors" - "fmt" "math" "strings" "time" @@ -2294,28 +2293,18 @@ func QueuePaymentRequests(paymentRequests *models.PaymentRequests, officeUsers [ for i, paymentRequest := range *paymentRequests { - var transportationOffice string - var transportationOfficeId uuid.UUID - moveTaskOrder := paymentRequest.MoveTaskOrder - if moveTaskOrder.CounselingOffice != nil { - transportationOffice = moveTaskOrder.CounselingOffice.Name - transportationOfficeId = *moveTaskOrder.CounselingOfficeID - } - fmt.Println("--------------Start----------------------------------------------------------------") - fmt.Println() - fmt.Println("movetaskorder: ", moveTaskOrder.CounselingOfficeID) - fmt.Println("counseling office: ", transportationOffice) - fmt.Println("counseling office ID: ", transportationOfficeId) - fmt.Println() - fmt.Println("--------------end----------------------------------------------------------------") orders := moveTaskOrder.Orders var gbloc ghcmessages.GBLOC if moveTaskOrder.ShipmentGBLOC[0].GBLOC != nil { gbloc = ghcmessages.GBLOC(*moveTaskOrder.ShipmentGBLOC[0].GBLOC) } + if paymentRequest.MoveTaskOrder.CounselingOffice != nil { + queuePaymentRequests[i].CounselingOffice = &paymentRequest.MoveTaskOrder.CounselingOffice.Name + } + queuePaymentRequests[i] = &ghcmessages.QueuePaymentRequest{ ID: *handlers.FmtUUID(paymentRequest.ID), MoveID: *handlers.FmtUUID(moveTaskOrder.ID), @@ -2329,7 +2318,6 @@ func QueuePaymentRequests(paymentRequests *models.PaymentRequests, officeUsers [ OrderType: (*string)(orders.OrdersType.Pointer()), LockedByOfficeUserID: handlers.FmtUUIDPtr(moveTaskOrder.LockedByOfficeUserID), LockExpiresAt: handlers.FmtDateTimePtr(moveTaskOrder.LockExpiresAt), - CounselingOffice: moveTaskOrder.CounselingOffice.Name, } if paymentRequest.MoveTaskOrder.TIOAssignedUser != nil { diff --git a/pkg/services/payment_request/payment_request_list_fetcher.go b/pkg/services/payment_request/payment_request_list_fetcher.go index cbe5c5d1487..155202f30ad 100644 --- a/pkg/services/payment_request/payment_request_list_fetcher.go +++ b/pkg/services/payment_request/payment_request_list_fetcher.go @@ -30,6 +30,7 @@ var parameters = map[string]string{ "age": "payment_requests.created_at", "originDutyLocation": "duty_locations.name", "assignedTo": "assigned_user.last_name,assigned_user.first_name", + "counselingOffice": "transportation_offices.id", } // NewPaymentRequestListFetcher returns a new payment request list fetcher diff --git a/swagger-def/ghc.yaml b/swagger-def/ghc.yaml index f6d2a424ba7..ba4b4181cd9 100644 --- a/swagger-def/ghc.yaml +++ b/swagger-def/ghc.yaml @@ -6949,6 +6949,7 @@ definitions: type: boolean counselingOffice: type: string + x-nullable: true QueuePaymentRequests: type: array items: diff --git a/swagger/ghc.yaml b/swagger/ghc.yaml index cd5f0ad00ef..31afd4ab580 100644 --- a/swagger/ghc.yaml +++ b/swagger/ghc.yaml @@ -7248,6 +7248,7 @@ definitions: type: boolean counselingOffice: type: string + x-nullable: true QueuePaymentRequests: type: array items: From eb65c31685fc15d9124305a42f8a68ef778db04b Mon Sep 17 00:00:00 2001 From: Jon Spight Date: Wed, 13 Nov 2024 22:23:18 +0000 Subject: [PATCH 07/32] fixed spacing --- pkg/handlers/ghcapi/internal/payloads/model_to_payload.go | 2 -- pkg/services/payment_request/payment_request_list_fetcher.go | 5 ----- 2 files changed, 7 deletions(-) diff --git a/pkg/handlers/ghcapi/internal/payloads/model_to_payload.go b/pkg/handlers/ghcapi/internal/payloads/model_to_payload.go index 4b4b7b693d3..61c0f35bf73 100644 --- a/pkg/handlers/ghcapi/internal/payloads/model_to_payload.go +++ b/pkg/handlers/ghcapi/internal/payloads/model_to_payload.go @@ -2292,9 +2292,7 @@ func QueuePaymentRequests(paymentRequests *models.PaymentRequests, officeUsers [ queuePaymentRequests := make(ghcmessages.QueuePaymentRequests, len(*paymentRequests)) for i, paymentRequest := range *paymentRequests { - moveTaskOrder := paymentRequest.MoveTaskOrder - orders := moveTaskOrder.Orders var gbloc ghcmessages.GBLOC if moveTaskOrder.ShipmentGBLOC[0].GBLOC != nil { diff --git a/pkg/services/payment_request/payment_request_list_fetcher.go b/pkg/services/payment_request/payment_request_list_fetcher.go index 155202f30ad..f5f7c96c2f4 100644 --- a/pkg/services/payment_request/payment_request_list_fetcher.go +++ b/pkg/services/payment_request/payment_request_list_fetcher.go @@ -123,11 +123,6 @@ func (f *paymentRequestListFetcher) FetchPaymentRequestList(appCtx appcontext.Ap if params.PerPage == nil { params.PerPage = models.Int64Pointer(20) } - fmt.Println("--------------------3---------------------------------") - fmt.Println("") - fmt.Println(params.CounselingOffice) - fmt.Println("") - fmt.Println("") err = query.GroupBy("payment_requests.id, service_members.id, moves.id, duty_locations.id, duty_locations.name, assigned_user.last_name, assigned_user.first_name, transportation_offices.id, transportation_offices.name").Paginate(int(*params.Page), int(*params.PerPage)).All(&paymentRequests) if err != nil { return nil, 0, err From a606db43f2893fe1cfa7ae59f54019534e3ced34 Mon Sep 17 00:00:00 2001 From: Jon Spight Date: Wed, 13 Nov 2024 22:57:29 +0000 Subject: [PATCH 08/32] fixed files --- pkg/gen/ghcapi/embedded_spec.go | 6 +++--- .../queues/get_payment_requests_queue_parameters.go | 2 +- swagger-def/ghc.yaml | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/pkg/gen/ghcapi/embedded_spec.go b/pkg/gen/ghcapi/embedded_spec.go index 1011cd2815c..5bb2bf16311 100644 --- a/pkg/gen/ghcapi/embedded_spec.go +++ b/pkg/gen/ghcapi/embedded_spec.go @@ -4667,7 +4667,7 @@ func init() { "submittedAt", "branch", "status", - "dodID", + "edipi", "emplid", "age", "originDutyLocation", @@ -4753,7 +4753,7 @@ func init() { "type": "string", "description": "filters using a counselingOffice name of the move", "name": "counselingOffice", - "in": "query + "in": "query" }, { "uniqueItems": true, @@ -20616,7 +20616,7 @@ func init() { "submittedAt", "branch", "status", - "dodID", + "edipi", "emplid", "age", "originDutyLocation", diff --git a/pkg/gen/ghcapi/ghcoperations/queues/get_payment_requests_queue_parameters.go b/pkg/gen/ghcapi/ghcoperations/queues/get_payment_requests_queue_parameters.go index da5e7d59879..be6e0fe5d60 100644 --- a/pkg/gen/ghcapi/ghcoperations/queues/get_payment_requests_queue_parameters.go +++ b/pkg/gen/ghcapi/ghcoperations/queues/get_payment_requests_queue_parameters.go @@ -491,7 +491,7 @@ func (o *GetPaymentRequestsQueueParams) bindSort(rawData []string, hasKey bool, // validateSort carries on validations for parameter Sort func (o *GetPaymentRequestsQueueParams) validateSort(formats strfmt.Registry) error { - if err := validate.EnumCase("sort", "query", *o.Sort, []interface{}{"customerName", "locator", "submittedAt", "branch", "status", "dodID", "emplid", "age", "originDutyLocation", "assignedTo", "counselingOffice"}, true); err != nil { + if err := validate.EnumCase("sort", "query", *o.Sort, []interface{}{"customerName", "locator", "submittedAt", "branch", "status", "edipi", "emplid", "age", "originDutyLocation", "assignedTo", "counselingOffice"}, true); err != nil { return err } diff --git a/swagger-def/ghc.yaml b/swagger-def/ghc.yaml index cb5eb04598c..fdf5939bf78 100644 --- a/swagger-def/ghc.yaml +++ b/swagger-def/ghc.yaml @@ -3670,7 +3670,7 @@ paths: - in: query name: sort type: string - enum: [customerName, locator, submittedAt, branch, status, dodID, emplid, age, originDutyLocation, assignedTo, counselingOffice] + enum: [customerName, locator, submittedAt, branch, status, edipi, emplid, age, originDutyLocation, assignedTo, counselingOffice] description: field that results should be sorted by - in: query name: order From 0439356be42855148c2641fa1fd574dfe2e4d657 Mon Sep 17 00:00:00 2001 From: Cory Kleinjan Date: Thu, 14 Nov 2024 04:37:37 +0000 Subject: [PATCH 09/32] updating shipment address update tests --- .../shipment_address_update_requester_test.go | 43 +++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/pkg/services/shipment_address_update/shipment_address_update_requester_test.go b/pkg/services/shipment_address_update/shipment_address_update_requester_test.go index 863e1851d21..2e67fd6ce34 100644 --- a/pkg/services/shipment_address_update/shipment_address_update_requester_test.go +++ b/pkg/services/shipment_address_update/shipment_address_update_requester_test.go @@ -14,8 +14,34 @@ import ( "github.com/transcom/mymove/pkg/services/address" moveservices "github.com/transcom/mymove/pkg/services/move" "github.com/transcom/mymove/pkg/testdatagen" + "github.com/transcom/mymove/pkg/unit" ) +func (suite *ShipmentAddressUpdateServiceSuite) setupServiceItemData() { + originalDomesticServiceArea := testdatagen.FetchOrMakeReDomesticServiceArea(suite.AppContextForTest().DB(), testdatagen.Assertions{ + ReDomesticServiceArea: models.ReDomesticServiceArea{ + ServiceArea: "004", + ServicesSchedule: 2, + }, + ReContract: testdatagen.FetchOrMakeReContract(suite.AppContextForTest().DB(), testdatagen.Assertions{}), + }) + + testdatagen.FetchOrMakeReDomesticLinehaulPrice(suite.DB(), testdatagen.Assertions{ + ReDomesticLinehaulPrice: models.ReDomesticLinehaulPrice{ + Contract: originalDomesticServiceArea.Contract, + ContractID: originalDomesticServiceArea.ContractID, + DomesticServiceArea: originalDomesticServiceArea, + DomesticServiceAreaID: originalDomesticServiceArea.ID, + WeightLower: unit.Pound(500), + WeightUpper: unit.Pound(9999), + MilesLower: 500, + MilesUpper: 9999, + PriceMillicents: unit.Millicents(606800), + IsPeakPeriod: false, + }, + }) +} + func (suite *ShipmentAddressUpdateServiceSuite) TestCreateApprovedShipmentAddressUpdate() { setupTestData := func() models.Move { testdatagen.FetchOrMakeReContractYear(suite.DB(), testdatagen.Assertions{ @@ -587,6 +613,8 @@ func (suite *ShipmentAddressUpdateServiceSuite) TestTOOApprovedShipmentAddressUp suite.Run("TOO approves address change", func() { + suite.setupServiceItemData() + addressChange := factory.BuildShipmentAddressUpdate(suite.DB(), nil, []factory.Trait{ factory.GetTraitAvailableToPrimeMove, }) @@ -849,6 +877,9 @@ func (suite *ShipmentAddressUpdateServiceSuite) TestTOOApprovedShipmentAddressUp "90210", ).Return(2500, nil).Once() move := setupTestData() + + suite.setupServiceItemData() + shipment := factory.BuildMTOShipmentWithMove(&move, suite.DB(), []factory.Customization{ { Model: models.Address{ @@ -915,6 +946,9 @@ func (suite *ShipmentAddressUpdateServiceSuite) TestTOOApprovedShipmentAddressUp "90210", ).Return(2500, nil).Once() move := setupTestData() + + suite.setupServiceItemData() + shipment := factory.BuildMTOShipmentWithMove(&move, suite.DB(), []factory.Customization{ { Model: models.Address{ @@ -970,6 +1004,9 @@ func (suite *ShipmentAddressUpdateServiceSuite) TestTOOApprovedShipmentAddressUp suite.Run("Service items are not rejected when pricing type does not change post TOO approval", func() { move := setupTestData() + + suite.setupServiceItemData() + shipment := factory.BuildMTOShipmentWithMove(&move, suite.DB(), nil, nil) //Generate service items to test their statuses upon approval @@ -1014,6 +1051,9 @@ func (suite *ShipmentAddressUpdateServiceSuite) TestTOOApprovedShipmentAddressUp "90210", ).Return(2500, nil).Once() move := setupTestData() + + suite.setupServiceItemData() + shipment := factory.BuildMTOShipmentWithMove(&move, suite.DB(), []factory.Customization{ { Model: models.Address{ @@ -1081,6 +1121,9 @@ func (suite *ShipmentAddressUpdateServiceSuite) TestTOOApprovedShipmentAddressUp PostalCode: "90210", } move := setupTestData() + + suite.setupServiceItemData() + shipment := factory.BuildMTOShipmentWithMove(&move, suite.DB(), []factory.Customization{ { Model: models.Address{ From ea1d3a8b7ee00a80cf93d97bd1f40817656c60c9 Mon Sep 17 00:00:00 2001 From: Jon Spight Date: Thu, 14 Nov 2024 14:21:01 +0000 Subject: [PATCH 10/32] fixed counseling column --- pkg/handlers/ghcapi/internal/payloads/model_to_payload.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pkg/handlers/ghcapi/internal/payloads/model_to_payload.go b/pkg/handlers/ghcapi/internal/payloads/model_to_payload.go index 61c0f35bf73..c2927aaeb5a 100644 --- a/pkg/handlers/ghcapi/internal/payloads/model_to_payload.go +++ b/pkg/handlers/ghcapi/internal/payloads/model_to_payload.go @@ -2299,10 +2299,6 @@ func QueuePaymentRequests(paymentRequests *models.PaymentRequests, officeUsers [ gbloc = ghcmessages.GBLOC(*moveTaskOrder.ShipmentGBLOC[0].GBLOC) } - if paymentRequest.MoveTaskOrder.CounselingOffice != nil { - queuePaymentRequests[i].CounselingOffice = &paymentRequest.MoveTaskOrder.CounselingOffice.Name - } - queuePaymentRequests[i] = &ghcmessages.QueuePaymentRequest{ ID: *handlers.FmtUUID(paymentRequest.ID), MoveID: *handlers.FmtUUID(moveTaskOrder.ID), @@ -2322,6 +2318,10 @@ func QueuePaymentRequests(paymentRequests *models.PaymentRequests, officeUsers [ queuePaymentRequests[i].AssignedTo = AssignedOfficeUser(paymentRequest.MoveTaskOrder.TIOAssignedUser) } + if paymentRequest.MoveTaskOrder.CounselingOffice != nil { + queuePaymentRequests[i].CounselingOffice = &paymentRequest.MoveTaskOrder.CounselingOffice.Name + } + isAssignable := false if queuePaymentRequests[i].AssignedTo == nil { isAssignable = true From 12eb8377a54f5b73f4cd2f055c66873dd7886ffd Mon Sep 17 00:00:00 2001 From: Cory Kleinjan Date: Thu, 14 Nov 2024 14:29:22 +0000 Subject: [PATCH 11/32] Adding ReContractYear data generation to shipment address tests --- .../shipment_address_update_requester_test.go | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/pkg/services/shipment_address_update/shipment_address_update_requester_test.go b/pkg/services/shipment_address_update/shipment_address_update_requester_test.go index 2e67fd6ce34..034b1420152 100644 --- a/pkg/services/shipment_address_update/shipment_address_update_requester_test.go +++ b/pkg/services/shipment_address_update/shipment_address_update_requester_test.go @@ -40,6 +40,17 @@ func (suite *ShipmentAddressUpdateServiceSuite) setupServiceItemData() { IsPeakPeriod: false, }, }) + + testdatagen.FetchOrMakeReContractYear(suite.DB(), testdatagen.Assertions{ + ReContractYear: models.ReContractYear{ + Contract: originalDomesticServiceArea.Contract, + ContractID: originalDomesticServiceArea.ContractID, + StartDate: time.Date(2019, time.June, 1, 0, 0, 0, 0, time.UTC), + EndDate: time.Date(2030, time.May, 31, 0, 0, 0, 0, time.UTC), + Escalation: 1.0, + EscalationCompounded: 1.0, + }, + }) } func (suite *ShipmentAddressUpdateServiceSuite) TestCreateApprovedShipmentAddressUpdate() { From 484018aa6af4878ff9a51ce1e7aad0fabb639684 Mon Sep 17 00:00:00 2001 From: Cory Kleinjan Date: Thu, 14 Nov 2024 15:24:31 +0000 Subject: [PATCH 12/32] Updating shipment address request tests --- .../shipment_address_update_requester_test.go | 26 +++++++++++-------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/pkg/services/shipment_address_update/shipment_address_update_requester_test.go b/pkg/services/shipment_address_update/shipment_address_update_requester_test.go index 034b1420152..b2edfc521dd 100644 --- a/pkg/services/shipment_address_update/shipment_address_update_requester_test.go +++ b/pkg/services/shipment_address_update/shipment_address_update_requester_test.go @@ -18,6 +18,16 @@ import ( ) func (suite *ShipmentAddressUpdateServiceSuite) setupServiceItemData() { + startDate := time.Date(2020, time.January, 1, 12, 0, 0, 0, time.UTC) + endDate := time.Date(2020, time.December, 31, 12, 0, 0, 0, time.UTC) + + testdatagen.FetchOrMakeReContractYear(suite.DB(), testdatagen.Assertions{ + ReContractYear: models.ReContractYear{ + StartDate: startDate, + EndDate: endDate, + }, + }) + originalDomesticServiceArea := testdatagen.FetchOrMakeReDomesticServiceArea(suite.AppContextForTest().DB(), testdatagen.Assertions{ ReDomesticServiceArea: models.ReDomesticServiceArea{ ServiceArea: "004", @@ -40,17 +50,6 @@ func (suite *ShipmentAddressUpdateServiceSuite) setupServiceItemData() { IsPeakPeriod: false, }, }) - - testdatagen.FetchOrMakeReContractYear(suite.DB(), testdatagen.Assertions{ - ReContractYear: models.ReContractYear{ - Contract: originalDomesticServiceArea.Contract, - ContractID: originalDomesticServiceArea.ContractID, - StartDate: time.Date(2019, time.June, 1, 0, 0, 0, 0, time.UTC), - EndDate: time.Date(2030, time.May, 31, 0, 0, 0, 0, time.UTC), - Escalation: 1.0, - EscalationCompounded: 1.0, - }, - }) } func (suite *ShipmentAddressUpdateServiceSuite) TestCreateApprovedShipmentAddressUpdate() { @@ -1030,6 +1029,11 @@ func (suite *ShipmentAddressUpdateServiceSuite) TestTOOApprovedShipmentAddressUp State: "CA", PostalCode: shipment.DestinationAddress.PostalCode, } + mockPlanner.On("ZipTransitDistance", + mock.AnythingOfType("*appcontext.appContext"), + "90210", + "94535", + ).Return(2500, nil).Once() mockPlanner.On("ZipTransitDistance", mock.AnythingOfType("*appcontext.appContext"), "94535", From d14adc4c4a5bb84405040e4c968ea5dc9028d953 Mon Sep 17 00:00:00 2001 From: Cory Kleinjan Date: Thu, 14 Nov 2024 18:31:30 +0000 Subject: [PATCH 13/32] Adding tests for UpdateMTOSeriveItemPricingEstimate --- .../mto_service_item_updater_test.go | 104 ++++++++++++++++++ 1 file changed, 104 insertions(+) diff --git a/pkg/services/mto_service_item/mto_service_item_updater_test.go b/pkg/services/mto_service_item/mto_service_item_updater_test.go index 11fdf619b79..39d40caead6 100644 --- a/pkg/services/mto_service_item/mto_service_item_updater_test.go +++ b/pkg/services/mto_service_item/mto_service_item_updater_test.go @@ -2346,6 +2346,110 @@ func (suite *MTOServiceItemServiceSuite) TestUpdateMTOServiceItemStatus() { }) } +func (suite *MTOServiceItemServiceSuite) setupServiceItemData() { + startDate := time.Date(2020, time.January, 1, 12, 0, 0, 0, time.UTC) + endDate := time.Date(2020, time.December, 31, 12, 0, 0, 0, time.UTC) + + testdatagen.FetchOrMakeReContractYear(suite.DB(), testdatagen.Assertions{ + ReContractYear: models.ReContractYear{ + StartDate: startDate, + EndDate: endDate, + }, + }) + + originalDomesticServiceArea := testdatagen.FetchOrMakeReDomesticServiceArea(suite.AppContextForTest().DB(), testdatagen.Assertions{ + ReDomesticServiceArea: models.ReDomesticServiceArea{ + ServiceArea: "004", + ServicesSchedule: 2, + }, + ReContract: testdatagen.FetchOrMakeReContract(suite.AppContextForTest().DB(), testdatagen.Assertions{}), + }) + + testdatagen.FetchOrMakeReDomesticLinehaulPrice(suite.DB(), testdatagen.Assertions{ + ReDomesticLinehaulPrice: models.ReDomesticLinehaulPrice{ + Contract: originalDomesticServiceArea.Contract, + ContractID: originalDomesticServiceArea.ContractID, + DomesticServiceArea: originalDomesticServiceArea, + DomesticServiceAreaID: originalDomesticServiceArea.ID, + WeightLower: unit.Pound(500), + WeightUpper: unit.Pound(9999), + MilesLower: 500, + MilesUpper: 9999, + PriceMillicents: unit.Millicents(606800), + IsPeakPeriod: false, + }, + }) +} + +func (suite *MTOServiceItemServiceSuite) TestUpdateMTOServiceItemPricingEstimate() { + suite.setupServiceItemData() + builder := query.NewQueryBuilder() + moveRouter := moverouter.NewMoveRouter() + shipmentFetcher := mtoshipment.NewMTOShipmentFetcher() + addressCreator := address.NewAddressCreator() + planner := &mocks.Planner{} + planner.On("ZipTransitDistance", + mock.AnythingOfType("*appcontext.appContext"), + mock.Anything, + mock.Anything, + ).Return(400, nil) + updater := NewMTOServiceItemUpdater(planner, builder, moveRouter, shipmentFetcher, addressCreator, ghcrateengine.NewDomesticUnpackPricer(), ghcrateengine.NewDomesticLinehaulPricer(), ghcrateengine.NewDomesticDestinationPricer(), ghcrateengine.NewFuelSurchargePricer(), ghcrateengine.NewDomesticDestinationSITDeliveryPricer(), ghcrateengine.NewDomesticOriginSITFuelSurchargePricer()) + + setupServiceItem := func() (models.MTOServiceItem, string) { + serviceItem := testdatagen.MakeDefaultMTOServiceItem(suite.DB()) + eTag := etag.GenerateEtag(serviceItem.UpdatedAt) + return serviceItem, eTag + } + + now := time.Now() + year, month, day := now.Add(time.Hour * 24 * -30).Date() + aMonthAgo := time.Date(year, month, day, 0, 0, 0, 0, time.UTC) + move := factory.BuildAvailableToPrimeMove(suite.DB(), nil, nil) + shipmentSITAllowance := int(90) + estimatedWeight := unit.Pound(1400) + + shipment := factory.BuildMTOShipment(suite.DB(), []factory.Customization{ + { + Model: models.MTOShipment{ + Status: models.MTOShipmentStatusApproved, + SITDaysAllowance: &shipmentSITAllowance, + PrimeEstimatedWeight: &estimatedWeight, + RequiredDeliveryDate: &aMonthAgo, + UpdatedAt: aMonthAgo, + }, + }, + { + Model: move, + LinkOnly: true, + }, + }, nil) + + suite.Run("Validation Error", func() { + serviceItem, eTag := setupServiceItem() + invalidServiceItem := serviceItem + invalidServiceItem.MoveTaskOrderID = serviceItem.ID // invalid Move ID + + updatedServiceItem, err := updater.UpdateMTOServiceItemPricingEstimate(suite.AppContextForTest(), &invalidServiceItem, shipment, eTag) + + suite.Nil(updatedServiceItem) + suite.Error(err) + suite.IsType(apperror.InvalidInputError{}, err) + + invalidInputError := err.(apperror.InvalidInputError) + suite.True(invalidInputError.ValidationErrors.HasAny()) + suite.Contains(invalidInputError.ValidationErrors.Keys(), "moveTaskOrderID") + }) + + suite.Run("Returns updated service item on success", func() { + serviceItem, eTag := setupServiceItem() + + updatedServiceItem, err := updater.UpdateMTOServiceItemPricingEstimate(suite.AppContextForTest(), &serviceItem, shipment, eTag) + + suite.NotNil(updatedServiceItem) + suite.Nil(err) + }) +} + // Helper function to create a rejected service item func buildRejectedServiceItem(suite *MTOServiceItemServiceSuite, reServiceCode models.ReServiceCode, reason string, contactDatePlusGracePeriod, aMonthAgo, now, sitRequestedDelivery time.Time, requestApprovalsRequestedStatus bool) models.MTOServiceItem { return factory.BuildMTOServiceItem(suite.DB(), []factory.Customization{ From daa6151c9d413129bbdacd8d997a2672e110a58d Mon Sep 17 00:00:00 2001 From: Cory Kleinjan Date: Fri, 15 Nov 2024 12:17:44 +0000 Subject: [PATCH 14/32] Updating service item updater tests --- .../mto_service_item_updater.go | 2 +- .../mto_service_item_updater_test.go | 45 +++++++------------ 2 files changed, 17 insertions(+), 30 deletions(-) diff --git a/pkg/services/mto_service_item/mto_service_item_updater.go b/pkg/services/mto_service_item/mto_service_item_updater.go index 35b549159b2..3d1b16b6ec5 100644 --- a/pkg/services/mto_service_item/mto_service_item_updater.go +++ b/pkg/services/mto_service_item/mto_service_item_updater.go @@ -506,7 +506,7 @@ func (p *mtoServiceItemUpdater) UpdateMTOServiceItemPricingEstimate( eTag string, ) (*models.MTOServiceItem, error) { estimatedPrice, err := p.findEstimatedPrice(appCtx, mtoServiceItem, shipment) - if estimatedPrice != 0 && err != nil { + if estimatedPrice != 0 && err == nil { mtoServiceItem.PricingEstimate = &estimatedPrice return p.UpdateMTOServiceItem(appCtx, mtoServiceItem, eTag, UpdateMTOServiceItemBasicValidator) } diff --git a/pkg/services/mto_service_item/mto_service_item_updater_test.go b/pkg/services/mto_service_item/mto_service_item_updater_test.go index 39d40caead6..aaf18b3beef 100644 --- a/pkg/services/mto_service_item/mto_service_item_updater_test.go +++ b/pkg/services/mto_service_item/mto_service_item_updater_test.go @@ -2357,12 +2357,21 @@ func (suite *MTOServiceItemServiceSuite) setupServiceItemData() { }, }) - originalDomesticServiceArea := testdatagen.FetchOrMakeReDomesticServiceArea(suite.AppContextForTest().DB(), testdatagen.Assertions{ + originalDomesticServiceArea := testdatagen.FetchOrMakeReDomesticServiceArea(suite.DB(), testdatagen.Assertions{ ReDomesticServiceArea: models.ReDomesticServiceArea{ ServiceArea: "004", ServicesSchedule: 2, }, - ReContract: testdatagen.FetchOrMakeReContract(suite.AppContextForTest().DB(), testdatagen.Assertions{}), + ReContract: testdatagen.FetchOrMakeReContract(suite.DB(), testdatagen.Assertions{}), + }) + + testdatagen.FetchOrMakeReZip3(suite.DB(), testdatagen.Assertions{ + ReZip3: models.ReZip3{ + Contract: originalDomesticServiceArea.Contract, + ContractID: originalDomesticServiceArea.ContractID, + DomesticServiceArea: originalDomesticServiceArea, + Zip3: "902", + }, }) testdatagen.FetchOrMakeReDomesticLinehaulPrice(suite.DB(), testdatagen.Assertions{ @@ -2373,7 +2382,7 @@ func (suite *MTOServiceItemServiceSuite) setupServiceItemData() { DomesticServiceAreaID: originalDomesticServiceArea.ID, WeightLower: unit.Pound(500), WeightUpper: unit.Pound(9999), - MilesLower: 500, + MilesLower: 250, MilesUpper: 9999, PriceMillicents: unit.Millicents(606800), IsPeakPeriod: false, @@ -2382,7 +2391,6 @@ func (suite *MTOServiceItemServiceSuite) setupServiceItemData() { } func (suite *MTOServiceItemServiceSuite) TestUpdateMTOServiceItemPricingEstimate() { - suite.setupServiceItemData() builder := query.NewQueryBuilder() moveRouter := moverouter.NewMoveRouter() shipmentFetcher := mtoshipment.NewMTOShipmentFetcher() @@ -2401,35 +2409,13 @@ func (suite *MTOServiceItemServiceSuite) TestUpdateMTOServiceItemPricingEstimate return serviceItem, eTag } - now := time.Now() - year, month, day := now.Add(time.Hour * 24 * -30).Date() - aMonthAgo := time.Date(year, month, day, 0, 0, 0, 0, time.UTC) - move := factory.BuildAvailableToPrimeMove(suite.DB(), nil, nil) - shipmentSITAllowance := int(90) - estimatedWeight := unit.Pound(1400) - - shipment := factory.BuildMTOShipment(suite.DB(), []factory.Customization{ - { - Model: models.MTOShipment{ - Status: models.MTOShipmentStatusApproved, - SITDaysAllowance: &shipmentSITAllowance, - PrimeEstimatedWeight: &estimatedWeight, - RequiredDeliveryDate: &aMonthAgo, - UpdatedAt: aMonthAgo, - }, - }, - { - Model: move, - LinkOnly: true, - }, - }, nil) - suite.Run("Validation Error", func() { + suite.setupServiceItemData() serviceItem, eTag := setupServiceItem() invalidServiceItem := serviceItem invalidServiceItem.MoveTaskOrderID = serviceItem.ID // invalid Move ID - updatedServiceItem, err := updater.UpdateMTOServiceItemPricingEstimate(suite.AppContextForTest(), &invalidServiceItem, shipment, eTag) + updatedServiceItem, err := updater.UpdateMTOServiceItemPricingEstimate(suite.AppContextForTest(), &invalidServiceItem, serviceItem.MTOShipment, eTag) suite.Nil(updatedServiceItem) suite.Error(err) @@ -2441,9 +2427,10 @@ func (suite *MTOServiceItemServiceSuite) TestUpdateMTOServiceItemPricingEstimate }) suite.Run("Returns updated service item on success", func() { + suite.setupServiceItemData() serviceItem, eTag := setupServiceItem() - updatedServiceItem, err := updater.UpdateMTOServiceItemPricingEstimate(suite.AppContextForTest(), &serviceItem, shipment, eTag) + updatedServiceItem, err := updater.UpdateMTOServiceItemPricingEstimate(suite.AppContextForTest(), &serviceItem, serviceItem.MTOShipment, eTag) suite.NotNil(updatedServiceItem) suite.Nil(err) From 5216f158e4243791843cadeefa22ab8ae6ff2f8d Mon Sep 17 00:00:00 2001 From: Cory Kleinjan Date: Fri, 15 Nov 2024 14:23:44 +0000 Subject: [PATCH 15/32] Updating mto_service_item_updater tests --- .../mto_service_item_updater.go | 2 +- .../mto_service_item_updater_test.go | 18 +++++++++++++----- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/pkg/services/mto_service_item/mto_service_item_updater.go b/pkg/services/mto_service_item/mto_service_item_updater.go index 3d1b16b6ec5..13ff315337b 100644 --- a/pkg/services/mto_service_item/mto_service_item_updater.go +++ b/pkg/services/mto_service_item/mto_service_item_updater.go @@ -149,7 +149,7 @@ func (p *mtoServiceItemUpdater) findEstimatedPrice(appCtx appcontext.AppContext, if mtoShipment.PrimeEstimatedWeight != nil { shipmentWeight = *mtoShipment.PrimeEstimatedWeight } else { - shipmentWeight = 0 + return 0, apperror.NewInvalidInputError(serviceItem.ID, nil, nil, "No estimated or actual weight exists for this service item.") } } diff --git a/pkg/services/mto_service_item/mto_service_item_updater_test.go b/pkg/services/mto_service_item/mto_service_item_updater_test.go index aaf18b3beef..1baffb834e4 100644 --- a/pkg/services/mto_service_item/mto_service_item_updater_test.go +++ b/pkg/services/mto_service_item/mto_service_item_updater_test.go @@ -2409,6 +2409,11 @@ func (suite *MTOServiceItemServiceSuite) TestUpdateMTOServiceItemPricingEstimate return serviceItem, eTag } + setupServiceItems := func() models.MTOServiceItems { + serviceItems := testdatagen.MakeMTOServiceItems(suite.DB()) + return serviceItems + } + suite.Run("Validation Error", func() { suite.setupServiceItemData() serviceItem, eTag := setupServiceItem() @@ -2426,14 +2431,17 @@ func (suite *MTOServiceItemServiceSuite) TestUpdateMTOServiceItemPricingEstimate suite.Contains(invalidInputError.ValidationErrors.Keys(), "moveTaskOrderID") }) - suite.Run("Returns updated service item on success", func() { + suite.Run("Returns updated service item on success wihtout error", func() { suite.setupServiceItemData() - serviceItem, eTag := setupServiceItem() + serviceItems := setupServiceItems() - updatedServiceItem, err := updater.UpdateMTOServiceItemPricingEstimate(suite.AppContextForTest(), &serviceItem, serviceItem.MTOShipment, eTag) + for _, serviceItem := range serviceItems { + eTag := etag.GenerateEtag(serviceItem.UpdatedAt) + updatedServiceItem, err := updater.UpdateMTOServiceItemPricingEstimate(suite.AppContextForTest(), &serviceItem, serviceItem.MTOShipment, eTag) - suite.NotNil(updatedServiceItem) - suite.Nil(err) + suite.NotNil(updatedServiceItem) + suite.Nil(err) + } }) } From e64002145fed84b053e009fbbbff275e5b9ee8aa Mon Sep 17 00:00:00 2001 From: Cory Kleinjan Date: Fri, 15 Nov 2024 15:28:44 +0000 Subject: [PATCH 16/32] Updating pickupdate for estimated incentive calculations --- .../mto_service_item_updater.go | 54 +++++++------------ 1 file changed, 20 insertions(+), 34 deletions(-) diff --git a/pkg/services/mto_service_item/mto_service_item_updater.go b/pkg/services/mto_service_item/mto_service_item_updater.go index 13ff315337b..6491b32e757 100644 --- a/pkg/services/mto_service_item/mto_service_item_updater.go +++ b/pkg/services/mto_service_item/mto_service_item_updater.go @@ -138,7 +138,16 @@ func (p *mtoServiceItemUpdater) findEstimatedPrice(appCtx appcontext.AppContext, if mtoShipment.ShipmentType == models.MTOShipmentTypePPM { isPPM = true } - requestedPickupDate := *mtoShipment.RequestedPickupDate + + var pickupDate *time.Time + if mtoShipment.ActualPickupDate != nil { + pickupDate = mtoShipment.ActualPickupDate + } else { + if mtoShipment.RequestedPickupDate != nil { + pickupDate = mtoShipment.RequestedPickupDate + } + } + currTime := time.Now() var distance int @@ -154,8 +163,8 @@ func (p *mtoServiceItemUpdater) findEstimatedPrice(appCtx appcontext.AppContext, } contractCode, err := FetchContractCode(appCtx, currTime) - if err != nil { - contractCode, err = FetchContractCode(appCtx, requestedPickupDate) + if err != nil && pickupDate != nil { + contractCode, err = FetchContractCode(appCtx, *pickupDate) if err != nil { return 0, err } @@ -173,7 +182,7 @@ func (p *mtoServiceItemUpdater) findEstimatedPrice(appCtx appcontext.AppContext, } } - price, _, err = p.destinationPricer.Price(appCtx, contractCode, requestedPickupDate, shipmentWeight, domesticServiceArea.ServiceArea, isPPM) + price, _, err = p.destinationPricer.Price(appCtx, contractCode, *pickupDate, shipmentWeight, domesticServiceArea.ServiceArea, isPPM) if err != nil { return 0, err } @@ -186,7 +195,7 @@ func (p *mtoServiceItemUpdater) findEstimatedPrice(appCtx appcontext.AppContext, serviceScheduleDestination := domesticServiceArea.ServicesSchedule - price, _, err = p.unpackPricer.Price(appCtx, contractCode, requestedPickupDate, shipmentWeight, serviceScheduleDestination, isPPM) + price, _, err = p.unpackPricer.Price(appCtx, contractCode, *pickupDate, shipmentWeight, serviceScheduleDestination, isPPM) if err != nil { return 0, err } @@ -204,7 +213,7 @@ func (p *mtoServiceItemUpdater) findEstimatedPrice(appCtx appcontext.AppContext, return 0, err } } - price, _, err = p.linehaulPricer.Price(appCtx, contractCode, requestedPickupDate, unit.Miles(distance), shipmentWeight, domesticServiceArea.ServiceArea, isPPM) + price, _, err = p.linehaulPricer.Price(appCtx, contractCode, *pickupDate, unit.Miles(distance), shipmentWeight, domesticServiceArea.ServiceArea, isPPM) if err != nil { return 0, err } @@ -215,19 +224,13 @@ func (p *mtoServiceItemUpdater) findEstimatedPrice(appCtx appcontext.AppContext, if err != nil { return 0, err } - price, _, err = p.unpackPricer.Price(appCtx, contractCode, requestedPickupDate, shipmentWeight, domesticServiceArea.ServicesSchedule, isPPM) + price, _, err = p.unpackPricer.Price(appCtx, contractCode, *pickupDate, shipmentWeight, domesticServiceArea.ServicesSchedule, isPPM) if err != nil { return 0, err } } // destination sit delivery if serviceItem.ReService.Code == models.ReServiceCodeDDDSIT { - var pickupDate time.Time - if mtoShipment.ActualPickupDate != nil { - pickupDate = *mtoShipment.ActualPickupDate - } else { - pickupDate = requestedPickupDate - } domesticServiceArea, err := fetchDomesticServiceArea(appCtx, contractCode, mtoShipment.DestinationAddress.PostalCode) if err != nil { return 0, err @@ -238,20 +241,13 @@ func (p *mtoServiceItemUpdater) findEstimatedPrice(appCtx appcontext.AppContext, return 0, err } } - price, _, err = p.sitDeliverPricer.Price(appCtx, contractCode, pickupDate, shipmentWeight, domesticServiceArea.ServiceArea, domesticServiceArea.SITPDSchedule, mtoShipment.DestinationAddress.PostalCode, serviceItem.SITDestinationFinalAddress.PostalCode, unit.Miles(distance)) + price, _, err = p.sitDeliverPricer.Price(appCtx, contractCode, *pickupDate, shipmentWeight, domesticServiceArea.ServiceArea, domesticServiceArea.SITPDSchedule, mtoShipment.DestinationAddress.PostalCode, serviceItem.SITDestinationFinalAddress.PostalCode, unit.Miles(distance)) if err != nil { return 0, err } } // destination sit fuel surcharge if serviceItem.ReService.Code == models.ReServiceCodeDDSFSC { - var pickupDateForFSC time.Time - if mtoShipment.ActualPickupDate != nil { - pickupDateForFSC = *mtoShipment.ActualPickupDate - } else { - pickupDateForFSC = requestedPickupDate - } - if mtoShipment.DestinationAddress != nil { distance, err = p.planner.ZipTransitDistance(appCtx, serviceItem.SITDestinationFinalAddress.PostalCode, mtoShipment.DestinationAddress.PostalCode) if err != nil { @@ -266,7 +262,7 @@ func (p *mtoServiceItemUpdater) findEstimatedPrice(appCtx appcontext.AppContext, if err != nil { return 0, err } - eiaFuelPrice, err := LookupEIAFuelPrice(appCtx, pickupDateForFSC) + eiaFuelPrice, err := LookupEIAFuelPrice(appCtx, *pickupDate) if err != nil { return 0, err } @@ -277,16 +273,6 @@ func (p *mtoServiceItemUpdater) findEstimatedPrice(appCtx appcontext.AppContext, } // fuel surcharge if serviceItem.ReService.Code == models.ReServiceCodeFSC { - var pickupDateForFSC time.Time - - // actual pickup date likely won't exist at the time of service item creation, but it could - // use requested pickup date if no actual date exists - if mtoShipment.ActualPickupDate != nil { - pickupDateForFSC = *mtoShipment.ActualPickupDate - } else { - pickupDateForFSC = requestedPickupDate - } - if mtoShipment.PickupAddress != nil && mtoShipment.DestinationAddress != nil { distance, err = p.planner.ZipTransitDistance(appCtx, mtoShipment.PickupAddress.PostalCode, mtoShipment.DestinationAddress.PostalCode) if err != nil { @@ -302,11 +288,11 @@ func (p *mtoServiceItemUpdater) findEstimatedPrice(appCtx appcontext.AppContext, if err != nil { return 0, err } - eiaFuelPrice, err := LookupEIAFuelPrice(appCtx, pickupDateForFSC) + eiaFuelPrice, err := LookupEIAFuelPrice(appCtx, *pickupDate) if err != nil { return 0, err } - price, _, err = p.fuelSurchargePricer.Price(appCtx, pickupDateForFSC, unit.Miles(distance), shipmentWeight, fscWeightBasedDistanceMultiplierFloat, eiaFuelPrice, isPPM) + price, _, err = p.fuelSurchargePricer.Price(appCtx, *pickupDate, unit.Miles(distance), shipmentWeight, fscWeightBasedDistanceMultiplierFloat, eiaFuelPrice, isPPM) if err != nil { return 0, err } From 00c970d925523458083267f514698d4961010601 Mon Sep 17 00:00:00 2001 From: Jon Spight Date: Fri, 15 Nov 2024 23:19:22 +0000 Subject: [PATCH 17/32] test cases and Customer Name fix --- .../payloads/model_to_payload_test.go | 80 +++++++++++++++++++ .../ServicesCounselingQueue.jsx | 2 +- 2 files changed, 81 insertions(+), 1 deletion(-) diff --git a/pkg/handlers/ghcapi/internal/payloads/model_to_payload_test.go b/pkg/handlers/ghcapi/internal/payloads/model_to_payload_test.go index 410f5f29fa2..b4f4325b325 100644 --- a/pkg/handlers/ghcapi/internal/payloads/model_to_payload_test.go +++ b/pkg/handlers/ghcapi/internal/payloads/model_to_payload_test.go @@ -10,6 +10,7 @@ import ( "github.com/transcom/mymove/pkg/gen/ghcmessages" "github.com/transcom/mymove/pkg/handlers" "github.com/transcom/mymove/pkg/models" + "github.com/transcom/mymove/pkg/models/roles" "github.com/transcom/mymove/pkg/storage/test" ) @@ -26,6 +27,85 @@ func TestMove(t *testing.T) { } } +func (suite *PayloadsSuite) TestPaymentRequestQueue() { + officeUser := factory.BuildOfficeUserWithRoles(suite.DB(), nil, []roles.RoleType{roles.RoleTypeTOO}) + + gbloc := "LKNQ" + + approvedMove := factory.BuildAvailableToPrimeMove(suite.DB(), nil, nil) + approvedMove.ShipmentGBLOC = append(approvedMove.ShipmentGBLOC, models.MoveToGBLOC{GBLOC: &gbloc}) + + pr2 := factory.BuildPaymentRequest(suite.DB(), []factory.Customization{ + { + Model: approvedMove, + LinkOnly: true, + }, + { + Model: models.TransportationOffice{ + Gbloc: "LKNQ", + }, + Type: &factory.TransportationOffices.OriginDutyLocation, + }, + { + Model: models.DutyLocation{ + Name: "KJKJKJKJKJK", + }, + Type: &factory.DutyLocations.OriginDutyLocation, + }, + }, nil) + + paymentRequests := models.PaymentRequests{pr2} + transportationOffice := factory.BuildTransportationOffice(suite.DB(), nil, nil) + paymentRequests[0].MoveTaskOrder.TIOAssignedUser = &officeUser + paymentRequests[0].MoveTaskOrder.CounselingOffice = &transportationOffice + + var officeUsers models.OfficeUsers + officeUsers = append(officeUsers, officeUser) + + suite.Run("Test Counseling Offices and TIO AssignedUser ", func() { + result := QueuePaymentRequests(&paymentRequests, officeUsers, officeUser, true, false) + suite.NotNil(result) + }) +} + +func (suite *PayloadsSuite) TestPaymentRequestQueueAvailableOfficeUsers() { + officeUser := factory.BuildOfficeUserWithRoles(suite.DB(), nil, []roles.RoleType{roles.RoleTypeTOO}) + + gbloc := "LKNQ" + + approvedMove := factory.BuildAvailableToPrimeMove(suite.DB(), nil, nil) + approvedMove.ShipmentGBLOC = append(approvedMove.ShipmentGBLOC, models.MoveToGBLOC{GBLOC: &gbloc}) + + pr2 := factory.BuildPaymentRequest(suite.DB(), []factory.Customization{ + { + Model: approvedMove, + LinkOnly: true, + }, + { + Model: models.TransportationOffice{ + Gbloc: "LKNQ", + }, + Type: &factory.TransportationOffices.OriginDutyLocation, + }, + { + Model: models.DutyLocation{ + Name: "KJKJKJKJKJK", + }, + Type: &factory.DutyLocations.OriginDutyLocation, + }, + }, nil) + + paymentRequests := models.PaymentRequests{pr2} + + var officeUsers models.OfficeUsers + officeUsers = append(officeUsers, officeUser) + + suite.Run("attach available office users if move is assignable", func() { + result := QueuePaymentRequests(&paymentRequests, officeUsers, officeUser, false, false) + suite.NotNil(result) + }) +} + func (suite *PayloadsSuite) TestFetchPPMShipment() { ppmShipmentID, _ := uuid.NewV4() diff --git a/src/pages/Office/ServicesCounselingQueue/ServicesCounselingQueue.jsx b/src/pages/Office/ServicesCounselingQueue/ServicesCounselingQueue.jsx index 0b961e2e3c6..08ed5702669 100644 --- a/src/pages/Office/ServicesCounselingQueue/ServicesCounselingQueue.jsx +++ b/src/pages/Office/ServicesCounselingQueue/ServicesCounselingQueue.jsx @@ -255,7 +255,7 @@ export const closeoutColumns = (moveLockFlag, ppmCloseoutGBLOC, ppmCloseoutOrigi ); }, { - id: 'lastName', + id: 'customerName', isFilterable: true, exportValue: (row) => { return `${row.customer.last_name}, ${row.customer.first_name}`; From b26355c79ae0e5ebe575f8cf09a431c688db5500 Mon Sep 17 00:00:00 2001 From: Jon Spight Date: Mon, 18 Nov 2024 22:06:40 +0000 Subject: [PATCH 18/32] merge conflict resolve --- .../ServicesCounselingQueue.jsx | 29 ++++--------------- 1 file changed, 6 insertions(+), 23 deletions(-) diff --git a/src/pages/Office/ServicesCounselingQueue/ServicesCounselingQueue.jsx b/src/pages/Office/ServicesCounselingQueue/ServicesCounselingQueue.jsx index e85f49109bd..c77ff89ef3c 100644 --- a/src/pages/Office/ServicesCounselingQueue/ServicesCounselingQueue.jsx +++ b/src/pages/Office/ServicesCounselingQueue/ServicesCounselingQueue.jsx @@ -260,29 +260,12 @@ export const closeoutColumns = ( {`${row.customer.last_name}, ${row.customer.first_name}`} ); - } - return null; - }, - { id: 'lock' }, - ), - createHeader('ID', 'id', { id: 'id' }), - createHeader( - 'Customer name', - (row) => { - return ( -
- {CHECK_SPECIAL_ORDERS_TYPES(row.orderType) ? ( - {SPECIAL_ORDERS_TYPES[`${row.orderType}`]} - ) : null} - {`${row.customer.last_name}, ${row.customer.first_name}`} -
- ); - }, - { - id: 'customerName', - isFilterable: true, - exportValue: (row) => { - return `${row.customer.last_name}, ${row.customer.first_name}`; + }, + { + id: 'customerName', + isFilterable: true, + exportValue: (row) => { + return `${row.customer.last_name}, ${row.customer.first_name}`; }, }, ), From b52a8cc60e439799cd946388ffd70a69fc71567c Mon Sep 17 00:00:00 2001 From: KonstanceH Date: Tue, 19 Nov 2024 22:06:30 +0000 Subject: [PATCH 19/32] fixed locking move for office user need tests --- pkg/gen/ghcapi/configure_mymove.go | 5 + pkg/gen/ghcapi/embedded_spec.go | 95 ++++++++++++++++ .../move/check_for_locked_moves_and_unlock.go | 56 ++++++++++ ..._for_locked_moves_and_unlock_parameters.go | 91 +++++++++++++++ ...k_for_locked_moves_and_unlock_responses.go | 104 ++++++++++++++++++ ..._for_locked_moves_and_unlock_urlbuilder.go | 101 +++++++++++++++++ pkg/gen/ghcapi/ghcoperations/mymove_api.go | 12 ++ pkg/gen/ghcmessages/unlocked_moves.go | 50 +++++++++ pkg/handlers/ghcapi/api.go | 5 + pkg/handlers/ghcapi/move.go | 21 ++++ pkg/services/move.go | 4 + .../Headers/OfficeLoggedInHeader.jsx | 6 +- src/sagas/entities.js | 7 ++ src/services/ghcApi.js | 6 + src/shared/Entities/schema.js | 2 + swagger-def/ghc.yaml | 32 ++++++ swagger/ghc.yaml | 31 ++++++ 17 files changed, 627 insertions(+), 1 deletion(-) create mode 100644 pkg/gen/ghcapi/ghcoperations/move/check_for_locked_moves_and_unlock.go create mode 100644 pkg/gen/ghcapi/ghcoperations/move/check_for_locked_moves_and_unlock_parameters.go create mode 100644 pkg/gen/ghcapi/ghcoperations/move/check_for_locked_moves_and_unlock_responses.go create mode 100644 pkg/gen/ghcapi/ghcoperations/move/check_for_locked_moves_and_unlock_urlbuilder.go create mode 100644 pkg/gen/ghcmessages/unlocked_moves.go diff --git a/pkg/gen/ghcapi/configure_mymove.go b/pkg/gen/ghcapi/configure_mymove.go index 6283194db7d..d921b1e606b 100644 --- a/pkg/gen/ghcapi/configure_mymove.go +++ b/pkg/gen/ghcapi/configure_mymove.go @@ -105,6 +105,11 @@ func configureAPI(api *ghcoperations.MymoveAPI) http.Handler { return middleware.NotImplemented("operation payment_requests.BulkDownload has not yet been implemented") }) } + if api.MoveCheckForLockedMovesAndUnlockHandler == nil { + api.MoveCheckForLockedMovesAndUnlockHandler = move.CheckForLockedMovesAndUnlockHandlerFunc(func(params move.CheckForLockedMovesAndUnlockParams) middleware.Responder { + return middleware.NotImplemented("operation move.CheckForLockedMovesAndUnlock has not yet been implemented") + }) + } if api.OrderCounselingUpdateAllowanceHandler == nil { api.OrderCounselingUpdateAllowanceHandler = order.CounselingUpdateAllowanceHandlerFunc(func(params order.CounselingUpdateAllowanceParams) middleware.Responder { return middleware.NotImplemented("operation order.CounselingUpdateAllowance has not yet been implemented") diff --git a/pkg/gen/ghcapi/embedded_spec.go b/pkg/gen/ghcapi/embedded_spec.go index f0c4f252bdd..f5b7ce06a2f 100644 --- a/pkg/gen/ghcapi/embedded_spec.go +++ b/pkg/gen/ghcapi/embedded_spec.go @@ -2739,6 +2739,42 @@ func init() { ] } }, + "/moves/{officeUserID}/CheckForLockedMovesAndUnlock": { + "patch": { + "description": "Finds and unlocks any locked moves by QAE,GSR, and headquarter officers", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "move" + ], + "operationId": "checkForLockedMovesAndUnlock", + "responses": { + "200": { + "description": "Successfully unlocked officer's move(s).", + "schema": { + "$ref": "#/definitions/UnlockedMoves" + } + }, + "500": { + "$ref": "#/responses/ServerError" + } + } + }, + "parameters": [ + { + "type": "string", + "format": "uuid", + "description": "ID of the move", + "name": "officeUserID", + "in": "path", + "required": true + } + ] + }, "/mto-shipments": { "post": { "description": "Creates a MTO shipment for the specified Move Task Order.\nRequired fields include:\n* Shipment Type\n* Customer requested pick-up date\n* Pick-up Address\n* Delivery Address\n* Releasing / Receiving agents\nOptional fields include:\n* Delivery Address Type\n* Customer Remarks\n* Releasing / Receiving agents\n* An array of optional accessorial service item codes\n", @@ -13341,6 +13377,16 @@ func init() { "$ref": "#/definitions/TransportationOffice" } }, + "UnlockedMoves": { + "type": "object", + "properties": { + "successMessage": { + "type": "string", + "format": "string", + "x-nullable": true + } + } + }, "UpdateAllowancePayload": { "type": "object", "properties": { @@ -18016,6 +18062,45 @@ func init() { ] } }, + "/moves/{officeUserID}/CheckForLockedMovesAndUnlock": { + "patch": { + "description": "Finds and unlocks any locked moves by QAE,GSR, and headquarter officers", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "move" + ], + "operationId": "checkForLockedMovesAndUnlock", + "responses": { + "200": { + "description": "Successfully unlocked officer's move(s).", + "schema": { + "$ref": "#/definitions/UnlockedMoves" + } + }, + "500": { + "description": "A server error occurred", + "schema": { + "$ref": "#/definitions/Error" + } + } + } + }, + "parameters": [ + { + "type": "string", + "format": "uuid", + "description": "ID of the move", + "name": "officeUserID", + "in": "path", + "required": true + } + ] + }, "/mto-shipments": { "post": { "description": "Creates a MTO shipment for the specified Move Task Order.\nRequired fields include:\n* Shipment Type\n* Customer requested pick-up date\n* Pick-up Address\n* Delivery Address\n* Releasing / Receiving agents\nOptional fields include:\n* Delivery Address Type\n* Customer Remarks\n* Releasing / Receiving agents\n* An array of optional accessorial service item codes\n", @@ -29560,6 +29645,16 @@ func init() { "$ref": "#/definitions/TransportationOffice" } }, + "UnlockedMoves": { + "type": "object", + "properties": { + "successMessage": { + "type": "string", + "format": "string", + "x-nullable": true + } + } + }, "UpdateAllowancePayload": { "type": "object", "properties": { diff --git a/pkg/gen/ghcapi/ghcoperations/move/check_for_locked_moves_and_unlock.go b/pkg/gen/ghcapi/ghcoperations/move/check_for_locked_moves_and_unlock.go new file mode 100644 index 00000000000..542f4f49f26 --- /dev/null +++ b/pkg/gen/ghcapi/ghcoperations/move/check_for_locked_moves_and_unlock.go @@ -0,0 +1,56 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package move + +// 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" +) + +// CheckForLockedMovesAndUnlockHandlerFunc turns a function with the right signature into a check for locked moves and unlock handler +type CheckForLockedMovesAndUnlockHandlerFunc func(CheckForLockedMovesAndUnlockParams) middleware.Responder + +// Handle executing the request and returning a response +func (fn CheckForLockedMovesAndUnlockHandlerFunc) Handle(params CheckForLockedMovesAndUnlockParams) middleware.Responder { + return fn(params) +} + +// CheckForLockedMovesAndUnlockHandler interface for that can handle valid check for locked moves and unlock params +type CheckForLockedMovesAndUnlockHandler interface { + Handle(CheckForLockedMovesAndUnlockParams) middleware.Responder +} + +// NewCheckForLockedMovesAndUnlock creates a new http.Handler for the check for locked moves and unlock operation +func NewCheckForLockedMovesAndUnlock(ctx *middleware.Context, handler CheckForLockedMovesAndUnlockHandler) *CheckForLockedMovesAndUnlock { + return &CheckForLockedMovesAndUnlock{Context: ctx, Handler: handler} +} + +/* + CheckForLockedMovesAndUnlock swagger:route PATCH /moves/{officeUserID}/CheckForLockedMovesAndUnlock move checkForLockedMovesAndUnlock + +Finds and unlocks any locked moves by QAE,GSR, and headquarter officers +*/ +type CheckForLockedMovesAndUnlock struct { + Context *middleware.Context + Handler CheckForLockedMovesAndUnlockHandler +} + +func (o *CheckForLockedMovesAndUnlock) ServeHTTP(rw http.ResponseWriter, r *http.Request) { + route, rCtx, _ := o.Context.RouteInfo(r) + if rCtx != nil { + *r = *rCtx + } + var Params = NewCheckForLockedMovesAndUnlockParams() + 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/move/check_for_locked_moves_and_unlock_parameters.go b/pkg/gen/ghcapi/ghcoperations/move/check_for_locked_moves_and_unlock_parameters.go new file mode 100644 index 00000000000..064322d3222 --- /dev/null +++ b/pkg/gen/ghcapi/ghcoperations/move/check_for_locked_moves_and_unlock_parameters.go @@ -0,0 +1,91 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package move + +// 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/errors" + "github.com/go-openapi/runtime/middleware" + "github.com/go-openapi/strfmt" + "github.com/go-openapi/validate" +) + +// NewCheckForLockedMovesAndUnlockParams creates a new CheckForLockedMovesAndUnlockParams object +// +// There are no default values defined in the spec. +func NewCheckForLockedMovesAndUnlockParams() CheckForLockedMovesAndUnlockParams { + + return CheckForLockedMovesAndUnlockParams{} +} + +// CheckForLockedMovesAndUnlockParams contains all the bound params for the check for locked moves and unlock operation +// typically these are obtained from a http.Request +// +// swagger:parameters checkForLockedMovesAndUnlock +type CheckForLockedMovesAndUnlockParams struct { + + // HTTP Request Object + HTTPRequest *http.Request `json:"-"` + + /*ID of the move + Required: true + In: path + */ + OfficeUserID strfmt.UUID +} + +// 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 NewCheckForLockedMovesAndUnlockParams() beforehand. +func (o *CheckForLockedMovesAndUnlockParams) BindRequest(r *http.Request, route *middleware.MatchedRoute) error { + var res []error + + o.HTTPRequest = r + + rOfficeUserID, rhkOfficeUserID, _ := route.Params.GetOK("officeUserID") + if err := o.bindOfficeUserID(rOfficeUserID, rhkOfficeUserID, route.Formats); err != nil { + res = append(res, err) + } + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +// bindOfficeUserID binds and validates parameter OfficeUserID from path. +func (o *CheckForLockedMovesAndUnlockParams) bindOfficeUserID(rawData []string, hasKey bool, formats strfmt.Registry) error { + var raw string + if len(rawData) > 0 { + raw = rawData[len(rawData)-1] + } + + // Required: true + // Parameter is provided by construction from the route + + // Format: uuid + value, err := formats.Parse("uuid", raw) + if err != nil { + return errors.InvalidType("officeUserID", "path", "strfmt.UUID", raw) + } + o.OfficeUserID = *(value.(*strfmt.UUID)) + + if err := o.validateOfficeUserID(formats); err != nil { + return err + } + + return nil +} + +// validateOfficeUserID carries on validations for parameter OfficeUserID +func (o *CheckForLockedMovesAndUnlockParams) validateOfficeUserID(formats strfmt.Registry) error { + + if err := validate.FormatOf("officeUserID", "path", "uuid", o.OfficeUserID.String(), formats); err != nil { + return err + } + return nil +} diff --git a/pkg/gen/ghcapi/ghcoperations/move/check_for_locked_moves_and_unlock_responses.go b/pkg/gen/ghcapi/ghcoperations/move/check_for_locked_moves_and_unlock_responses.go new file mode 100644 index 00000000000..3c3b2f97ff3 --- /dev/null +++ b/pkg/gen/ghcapi/ghcoperations/move/check_for_locked_moves_and_unlock_responses.go @@ -0,0 +1,104 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package move + +// 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" +) + +// CheckForLockedMovesAndUnlockOKCode is the HTTP code returned for type CheckForLockedMovesAndUnlockOK +const CheckForLockedMovesAndUnlockOKCode int = 200 + +/* +CheckForLockedMovesAndUnlockOK Successfully unlocked officer's move(s). + +swagger:response checkForLockedMovesAndUnlockOK +*/ +type CheckForLockedMovesAndUnlockOK struct { + + /* + In: Body + */ + Payload *ghcmessages.UnlockedMoves `json:"body,omitempty"` +} + +// NewCheckForLockedMovesAndUnlockOK creates CheckForLockedMovesAndUnlockOK with default headers values +func NewCheckForLockedMovesAndUnlockOK() *CheckForLockedMovesAndUnlockOK { + + return &CheckForLockedMovesAndUnlockOK{} +} + +// WithPayload adds the payload to the check for locked moves and unlock o k response +func (o *CheckForLockedMovesAndUnlockOK) WithPayload(payload *ghcmessages.UnlockedMoves) *CheckForLockedMovesAndUnlockOK { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the check for locked moves and unlock o k response +func (o *CheckForLockedMovesAndUnlockOK) SetPayload(payload *ghcmessages.UnlockedMoves) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *CheckForLockedMovesAndUnlockOK) 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 + } + } +} + +// CheckForLockedMovesAndUnlockInternalServerErrorCode is the HTTP code returned for type CheckForLockedMovesAndUnlockInternalServerError +const CheckForLockedMovesAndUnlockInternalServerErrorCode int = 500 + +/* +CheckForLockedMovesAndUnlockInternalServerError A server error occurred + +swagger:response checkForLockedMovesAndUnlockInternalServerError +*/ +type CheckForLockedMovesAndUnlockInternalServerError struct { + + /* + In: Body + */ + Payload *ghcmessages.Error `json:"body,omitempty"` +} + +// NewCheckForLockedMovesAndUnlockInternalServerError creates CheckForLockedMovesAndUnlockInternalServerError with default headers values +func NewCheckForLockedMovesAndUnlockInternalServerError() *CheckForLockedMovesAndUnlockInternalServerError { + + return &CheckForLockedMovesAndUnlockInternalServerError{} +} + +// WithPayload adds the payload to the check for locked moves and unlock internal server error response +func (o *CheckForLockedMovesAndUnlockInternalServerError) WithPayload(payload *ghcmessages.Error) *CheckForLockedMovesAndUnlockInternalServerError { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the check for locked moves and unlock internal server error response +func (o *CheckForLockedMovesAndUnlockInternalServerError) SetPayload(payload *ghcmessages.Error) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *CheckForLockedMovesAndUnlockInternalServerError) 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/move/check_for_locked_moves_and_unlock_urlbuilder.go b/pkg/gen/ghcapi/ghcoperations/move/check_for_locked_moves_and_unlock_urlbuilder.go new file mode 100644 index 00000000000..e103de7869d --- /dev/null +++ b/pkg/gen/ghcapi/ghcoperations/move/check_for_locked_moves_and_unlock_urlbuilder.go @@ -0,0 +1,101 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package move + +// 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" + "strings" + + "github.com/go-openapi/strfmt" +) + +// CheckForLockedMovesAndUnlockURL generates an URL for the check for locked moves and unlock operation +type CheckForLockedMovesAndUnlockURL struct { + OfficeUserID strfmt.UUID + + _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 *CheckForLockedMovesAndUnlockURL) WithBasePath(bp string) *CheckForLockedMovesAndUnlockURL { + 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 *CheckForLockedMovesAndUnlockURL) SetBasePath(bp string) { + o._basePath = bp +} + +// Build a url path and query string +func (o *CheckForLockedMovesAndUnlockURL) Build() (*url.URL, error) { + var _result url.URL + + var _path = "/moves/{officeUserID}/CheckForLockedMovesAndUnlock" + + officeUserID := o.OfficeUserID.String() + if officeUserID != "" { + _path = strings.Replace(_path, "{officeUserID}", officeUserID, -1) + } else { + return nil, errors.New("officeUserId is required on CheckForLockedMovesAndUnlockURL") + } + + _basePath := o._basePath + if _basePath == "" { + _basePath = "/ghc/v1" + } + _result.Path = golangswaggerpaths.Join(_basePath, _path) + + return &_result, nil +} + +// Must is a helper function to panic when the url builder returns an error +func (o *CheckForLockedMovesAndUnlockURL) 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 *CheckForLockedMovesAndUnlockURL) String() string { + return o.Must(o.Build()).String() +} + +// BuildFull builds a full url with scheme, host, path and query string +func (o *CheckForLockedMovesAndUnlockURL) BuildFull(scheme, host string) (*url.URL, error) { + if scheme == "" { + return nil, errors.New("scheme is required for a full url on CheckForLockedMovesAndUnlockURL") + } + if host == "" { + return nil, errors.New("host is required for a full url on CheckForLockedMovesAndUnlockURL") + } + + 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 *CheckForLockedMovesAndUnlockURL) StringFull(scheme, host string) string { + return o.Must(o.BuildFull(scheme, host)).String() +} diff --git a/pkg/gen/ghcapi/ghcoperations/mymove_api.go b/pkg/gen/ghcapi/ghcoperations/mymove_api.go index 1ca4a2173e0..106a1975b77 100644 --- a/pkg/gen/ghcapi/ghcoperations/mymove_api.go +++ b/pkg/gen/ghcapi/ghcoperations/mymove_api.go @@ -90,6 +90,9 @@ func NewMymoveAPI(spec *loads.Document) *MymoveAPI { PaymentRequestsBulkDownloadHandler: payment_requests.BulkDownloadHandlerFunc(func(params payment_requests.BulkDownloadParams) middleware.Responder { return middleware.NotImplemented("operation payment_requests.BulkDownload has not yet been implemented") }), + MoveCheckForLockedMovesAndUnlockHandler: move.CheckForLockedMovesAndUnlockHandlerFunc(func(params move.CheckForLockedMovesAndUnlockParams) middleware.Responder { + return middleware.NotImplemented("operation move.CheckForLockedMovesAndUnlock has not yet been implemented") + }), OrderCounselingUpdateAllowanceHandler: order.CounselingUpdateAllowanceHandlerFunc(func(params order.CounselingUpdateAllowanceParams) middleware.Responder { return middleware.NotImplemented("operation order.CounselingUpdateAllowance has not yet been implemented") }), @@ -435,6 +438,8 @@ type MymoveAPI struct { ReportViolationsAssociateReportViolationsHandler report_violations.AssociateReportViolationsHandler // PaymentRequestsBulkDownloadHandler sets the operation handler for the bulk download operation PaymentRequestsBulkDownloadHandler payment_requests.BulkDownloadHandler + // MoveCheckForLockedMovesAndUnlockHandler sets the operation handler for the check for locked moves and unlock operation + MoveCheckForLockedMovesAndUnlockHandler move.CheckForLockedMovesAndUnlockHandler // OrderCounselingUpdateAllowanceHandler sets the operation handler for the counseling update allowance operation OrderCounselingUpdateAllowanceHandler order.CounselingUpdateAllowanceHandler // OrderCounselingUpdateOrderHandler sets the operation handler for the counseling update order operation @@ -729,6 +734,9 @@ func (o *MymoveAPI) Validate() error { if o.PaymentRequestsBulkDownloadHandler == nil { unregistered = append(unregistered, "payment_requests.BulkDownloadHandler") } + if o.MoveCheckForLockedMovesAndUnlockHandler == nil { + unregistered = append(unregistered, "move.CheckForLockedMovesAndUnlockHandler") + } if o.OrderCounselingUpdateAllowanceHandler == nil { unregistered = append(unregistered, "order.CounselingUpdateAllowanceHandler") } @@ -1137,6 +1145,10 @@ func (o *MymoveAPI) initHandlerCache() { if o.handlers["PATCH"] == nil { o.handlers["PATCH"] = make(map[string]http.Handler) } + o.handlers["PATCH"]["/moves/{officeUserID}/CheckForLockedMovesAndUnlock"] = move.NewCheckForLockedMovesAndUnlock(o.context, o.MoveCheckForLockedMovesAndUnlockHandler) + if o.handlers["PATCH"] == nil { + o.handlers["PATCH"] = make(map[string]http.Handler) + } o.handlers["PATCH"]["/counseling/orders/{orderID}/allowances"] = order.NewCounselingUpdateAllowance(o.context, o.OrderCounselingUpdateAllowanceHandler) if o.handlers["PATCH"] == nil { o.handlers["PATCH"] = make(map[string]http.Handler) diff --git a/pkg/gen/ghcmessages/unlocked_moves.go b/pkg/gen/ghcmessages/unlocked_moves.go new file mode 100644 index 00000000000..0b3eaf5535a --- /dev/null +++ b/pkg/gen/ghcmessages/unlocked_moves.go @@ -0,0 +1,50 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package ghcmessages + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "context" + + "github.com/go-openapi/strfmt" + "github.com/go-openapi/swag" +) + +// UnlockedMoves unlocked moves +// +// swagger:model UnlockedMoves +type UnlockedMoves struct { + + // success message + SuccessMessage *string `json:"successMessage,omitempty"` +} + +// Validate validates this unlocked moves +func (m *UnlockedMoves) Validate(formats strfmt.Registry) error { + return nil +} + +// ContextValidate validates this unlocked moves based on context it is used +func (m *UnlockedMoves) ContextValidate(ctx context.Context, formats strfmt.Registry) error { + return nil +} + +// MarshalBinary interface implementation +func (m *UnlockedMoves) MarshalBinary() ([]byte, error) { + if m == nil { + return nil, nil + } + return swag.WriteJSON(m) +} + +// UnmarshalBinary interface implementation +func (m *UnlockedMoves) UnmarshalBinary(b []byte) error { + var res UnlockedMoves + if err := swag.ReadJSON(b, &res); err != nil { + return err + } + *m = res + return nil +} diff --git a/pkg/handlers/ghcapi/api.go b/pkg/handlers/ghcapi/api.go index 6e97dfe8e65..96b906358b4 100644 --- a/pkg/handlers/ghcapi/api.go +++ b/pkg/handlers/ghcapi/api.go @@ -697,5 +697,10 @@ func NewGhcAPIHandler(handlerConfig handlers.HandlerConfig) *ghcops.MymoveAPI { assignedOfficeUserUpdater, } + ghcAPI.MoveCheckForLockedMovesAndUnlockHandler = CheckForLockedMovesAndUnlockHandler{ + HandlerConfig: handlerConfig, + MoveUnlocker: movelocker.NewMoveUnlocker(), + } + return ghcAPI } diff --git a/pkg/handlers/ghcapi/move.go b/pkg/handlers/ghcapi/move.go index cf8f457545e..5e95695b038 100644 --- a/pkg/handlers/ghcapi/move.go +++ b/pkg/handlers/ghcapi/move.go @@ -333,6 +333,27 @@ func (h MoveCancelerHandler) Handle(params moveop.MoveCancelerParams) middleware }) } +type CheckForLockedMovesAndUnlockHandler struct { + handlers.HandlerConfig + services.MoveUnlocker +} + +func (h CheckForLockedMovesAndUnlockHandler) Handle(params moveop.CheckForLockedMovesAndUnlockParams) middleware.Responder { + return h.AuditableAppContextFromRequestWithErrors(params.HTTPRequest, + func(appCtx appcontext.AppContext) (middleware.Responder, error) { + // if the search move office user is accessing the queue, we need to unlock move/moves they have locked + err := h.CheckForLockedMovesAndUnlock(appCtx, uuid.FromStringOrNil(params.OfficeUserID.String())) + if err != nil { + return moveop.NewCheckForLockedMovesAndUnlockInternalServerError(), err + } + payload := "Successfully unlocked all move(s) for current office user" + + var test ghcmessages.UnlockedMoves + test.SuccessMessage = &payload + return moveop.NewCheckForLockedMovesAndUnlockOK().WithPayload(&test), nil + }) +} + type DeleteAssignedOfficeUserHandler struct { handlers.HandlerConfig services.MoveAssignedOfficeUserUpdater diff --git a/pkg/services/move.go b/pkg/services/move.go index f48f7f9f26b..8a524accbe2 100644 --- a/pkg/services/move.go +++ b/pkg/services/move.go @@ -125,3 +125,7 @@ type MoveAssignedOfficeUserUpdater interface { UpdateAssignedOfficeUser(appCtx appcontext.AppContext, moveID uuid.UUID, officeUser *models.OfficeUser, role roles.RoleType) (*models.Move, error) DeleteAssignedOfficeUser(appCtx appcontext.AppContext, moveID uuid.UUID, role roles.RoleType) (*models.Move, error) } + +type CheckForLockedMovesAndUnlockHandler interface { + CheckForLockedMovesAndUnlock(appCtx appcontext.AppContext, officeUserID uuid.UUID) error +} diff --git a/src/containers/Headers/OfficeLoggedInHeader.jsx b/src/containers/Headers/OfficeLoggedInHeader.jsx index 09d07002920..bb4b747e555 100644 --- a/src/containers/Headers/OfficeLoggedInHeader.jsx +++ b/src/containers/Headers/OfficeLoggedInHeader.jsx @@ -1,7 +1,7 @@ import React from 'react'; import PropTypes from 'prop-types'; import { connect } from 'react-redux'; -import { Link, useNavigate } from 'react-router-dom'; +import { Link, useNavigate, useLocation } from 'react-router-dom'; import classnames from 'classnames'; import GblocSwitcher from 'components/Office/GblocSwitcher/GblocSwitcher'; @@ -12,6 +12,7 @@ import { logOut as logOutAction } from 'store/auth/actions'; import { OfficeUserInfoShape } from 'types/index'; import { selectLoggedInUser } from 'store/entities/selectors'; import { roleTypes } from 'constants/userRoles'; +import { unlockOfficerUserMoves } from 'services/ghcApi'; const OfficeLoggedInHeader = ({ officeUser, activeRole, logOut }) => { const navigate = useNavigate(); @@ -33,10 +34,13 @@ const OfficeLoggedInHeader = ({ officeUser, activeRole, logOut }) => { }; let queueText = ''; + const location = useLocation(); if (activeRole === roleTypes.TOO) { queueText = 'moves'; } else if (activeRole === roleTypes.TIO) { queueText = 'payment requests'; + } else if (activeRole === roleTypes.QAE && location.pathname === '/') { + unlockOfficerUserMoves('move', officeUser.id); } return ( diff --git a/src/sagas/entities.js b/src/sagas/entities.js index 5d44c894c7b..58dc055ec4d 100644 --- a/src/sagas/entities.js +++ b/src/sagas/entities.js @@ -63,6 +63,13 @@ export function* updateAllMoves(action) { yield put(addEntities({ serviceMemberMoves: payload })); } +export function* unlockedMoves(action) { + const { payload } = action; + + const normalizedData = yield call(normalizeResponse, payload, 'move'); + yield put(addEntities(normalizedData)); +} + export function* watchUpdateEntities() { yield all([ takeLatest(UPDATE_SERVICE_MEMBER, updateServiceMember), diff --git a/src/services/ghcApi.js b/src/services/ghcApi.js index 9e879178014..f89c143c9a2 100644 --- a/src/services/ghcApi.js +++ b/src/services/ghcApi.js @@ -885,6 +885,12 @@ export async function updateAssignedOfficeUserForMove({ moveID, officeUserId, ro }); } +export async function unlockOfficerUserMoves(key, officeUserID) { + return makeGHCRequest('move.checkForLockedMovesAndUnlock', { + officeUserID, + }); +} + export async function deleteAssignedOfficeUserForMove({ moveID, roleType }) { return makeGHCRequest('move.deleteAssignedOfficeUser', { moveID, diff --git a/src/shared/Entities/schema.js b/src/shared/Entities/schema.js index 23379c7843e..86b394422ad 100644 --- a/src/shared/Entities/schema.js +++ b/src/shared/Entities/schema.js @@ -199,3 +199,5 @@ export const searchMoves = new schema.Array(searchMove); export const searchMovesResult = new schema.Entity('searchMovesResult'); export const officeUser = new schema.Entity('officeUser'); + +export const unlockedMoves = new schema.Entity('moves', officeUser.id); diff --git a/swagger-def/ghc.yaml b/swagger-def/ghc.yaml index dd29b7c65c7..f511bdea99f 100644 --- a/swagger-def/ghc.yaml +++ b/swagger-def/ghc.yaml @@ -4237,7 +4237,39 @@ paths: - move description: unassigns either a services counselor, task ordering officer, or task invoicing officer from the move operationId: deleteAssignedOfficeUser + /moves/{officeUserID}/CheckForLockedMovesAndUnlock: + parameters: + - description: ID of the move + in: path + name: officeUserID + required: true + format: uuid + type: string + patch: + consumes: + - application/json + produces: + - application/json + responses: + '200': + description: Successfully unlocked officer's move(s). + schema: + $ref: '#/definitions/UnlockedMoves' + '500': + $ref: '#/responses/ServerError' + tags: + - move + description: >- + Finds and unlocks any locked moves by QAE,GSR, and headquarter officers + operationId: checkForLockedMovesAndUnlock definitions: + UnlockedMoves: + type: object + properties: + successMessage: + type: string + format: string + x-nullable: true ApplicationParameters: type: object properties: diff --git a/swagger/ghc.yaml b/swagger/ghc.yaml index 7281c8c3330..36fb8bdcc95 100644 --- a/swagger/ghc.yaml +++ b/swagger/ghc.yaml @@ -4438,7 +4438,38 @@ paths: unassigns either a services counselor, task ordering officer, or task invoicing officer from the move operationId: deleteAssignedOfficeUser + /moves/{officeUserID}/CheckForLockedMovesAndUnlock: + parameters: + - description: ID of the move + in: path + name: officeUserID + required: true + format: uuid + type: string + patch: + consumes: + - application/json + produces: + - application/json + responses: + '200': + description: Successfully unlocked officer's move(s). + schema: + $ref: '#/definitions/UnlockedMoves' + '500': + $ref: '#/responses/ServerError' + tags: + - move + description: Finds and unlocks any locked moves by QAE,GSR, and headquarter officers + operationId: checkForLockedMovesAndUnlock definitions: + UnlockedMoves: + type: object + properties: + successMessage: + type: string + format: string + x-nullable: true ApplicationParameters: type: object properties: From 2cecd785862c93f785b279406d6480a9e7d3ff75 Mon Sep 17 00:00:00 2001 From: KonstanceH Date: Tue, 19 Nov 2024 23:33:38 +0000 Subject: [PATCH 20/32] added officers and changed vars --- pkg/gen/ghcapi/embedded_spec.go | 8 ++++---- .../move/check_for_locked_moves_and_unlock.go | 2 +- .../check_for_locked_moves_and_unlock_parameters.go | 2 +- pkg/handlers/ghcapi/move.go | 10 ++++++---- src/constants/userRoles.js | 1 + src/containers/Headers/OfficeLoggedInHeader.jsx | 7 ++++--- src/sagas/entities.js | 10 +++++----- src/services/ghcApi.js | 2 +- swagger-def/ghc.yaml | 4 ++-- swagger/ghc.yaml | 6 ++++-- 10 files changed, 29 insertions(+), 23 deletions(-) diff --git a/pkg/gen/ghcapi/embedded_spec.go b/pkg/gen/ghcapi/embedded_spec.go index c622e9ae92d..a0ec5c0c21b 100644 --- a/pkg/gen/ghcapi/embedded_spec.go +++ b/pkg/gen/ghcapi/embedded_spec.go @@ -2799,7 +2799,7 @@ func init() { }, "/moves/{officeUserID}/CheckForLockedMovesAndUnlock": { "patch": { - "description": "Finds and unlocks any locked moves by QAE,GSR, and headquarter officers", + "description": "Finds and unlocks any locked moves by QAE,CSR, GSR, and headquarter officers", "consumes": [ "application/json" ], @@ -2826,7 +2826,7 @@ func init() { { "type": "string", "format": "uuid", - "description": "ID of the move", + "description": "ID of the move's officer", "name": "officeUserID", "in": "path", "required": true @@ -18195,7 +18195,7 @@ func init() { }, "/moves/{officeUserID}/CheckForLockedMovesAndUnlock": { "patch": { - "description": "Finds and unlocks any locked moves by QAE,GSR, and headquarter officers", + "description": "Finds and unlocks any locked moves by QAE,CSR, GSR, and headquarter officers", "consumes": [ "application/json" ], @@ -18225,7 +18225,7 @@ func init() { { "type": "string", "format": "uuid", - "description": "ID of the move", + "description": "ID of the move's officer", "name": "officeUserID", "in": "path", "required": true diff --git a/pkg/gen/ghcapi/ghcoperations/move/check_for_locked_moves_and_unlock.go b/pkg/gen/ghcapi/ghcoperations/move/check_for_locked_moves_and_unlock.go index 542f4f49f26..da71c6ea45a 100644 --- a/pkg/gen/ghcapi/ghcoperations/move/check_for_locked_moves_and_unlock.go +++ b/pkg/gen/ghcapi/ghcoperations/move/check_for_locked_moves_and_unlock.go @@ -32,7 +32,7 @@ func NewCheckForLockedMovesAndUnlock(ctx *middleware.Context, handler CheckForLo /* CheckForLockedMovesAndUnlock swagger:route PATCH /moves/{officeUserID}/CheckForLockedMovesAndUnlock move checkForLockedMovesAndUnlock -Finds and unlocks any locked moves by QAE,GSR, and headquarter officers +Finds and unlocks any locked moves by QAE,CSR, GSR, and headquarter officers */ type CheckForLockedMovesAndUnlock struct { Context *middleware.Context diff --git a/pkg/gen/ghcapi/ghcoperations/move/check_for_locked_moves_and_unlock_parameters.go b/pkg/gen/ghcapi/ghcoperations/move/check_for_locked_moves_and_unlock_parameters.go index 064322d3222..46162a72b81 100644 --- a/pkg/gen/ghcapi/ghcoperations/move/check_for_locked_moves_and_unlock_parameters.go +++ b/pkg/gen/ghcapi/ghcoperations/move/check_for_locked_moves_and_unlock_parameters.go @@ -31,7 +31,7 @@ type CheckForLockedMovesAndUnlockParams struct { // HTTP Request Object HTTPRequest *http.Request `json:"-"` - /*ID of the move + /*ID of the move's officer Required: true In: path */ diff --git a/pkg/handlers/ghcapi/move.go b/pkg/handlers/ghcapi/move.go index 5e95695b038..a1bfb63f511 100644 --- a/pkg/handlers/ghcapi/move.go +++ b/pkg/handlers/ghcapi/move.go @@ -346,11 +346,13 @@ func (h CheckForLockedMovesAndUnlockHandler) Handle(params moveop.CheckForLocked if err != nil { return moveop.NewCheckForLockedMovesAndUnlockInternalServerError(), err } - payload := "Successfully unlocked all move(s) for current office user" + payloadMessage := "Successfully unlocked all move(s) for current office user" - var test ghcmessages.UnlockedMoves - test.SuccessMessage = &payload - return moveop.NewCheckForLockedMovesAndUnlockOK().WithPayload(&test), nil + payload := ghcmessages.UnlockedMoves{ + SuccessMessage: &payloadMessage, + } + + return moveop.NewCheckForLockedMovesAndUnlockOK().WithPayload(&payload), nil }) } diff --git a/src/constants/userRoles.js b/src/constants/userRoles.js index 45739f19da0..959cec470e6 100644 --- a/src/constants/userRoles.js +++ b/src/constants/userRoles.js @@ -10,6 +10,7 @@ export const roleTypes = { CUSTOMER_SERVICE_REPRESENTATIVE: 'customer_service_representative', GSR: 'gsr', HQ: 'headquarters', + CSR: 'csr', }; export const adminOfficeRoles = [ diff --git a/src/containers/Headers/OfficeLoggedInHeader.jsx b/src/containers/Headers/OfficeLoggedInHeader.jsx index bb4b747e555..28d4c34b85e 100644 --- a/src/containers/Headers/OfficeLoggedInHeader.jsx +++ b/src/containers/Headers/OfficeLoggedInHeader.jsx @@ -12,7 +12,7 @@ import { logOut as logOutAction } from 'store/auth/actions'; import { OfficeUserInfoShape } from 'types/index'; import { selectLoggedInUser } from 'store/entities/selectors'; import { roleTypes } from 'constants/userRoles'; -import { unlockOfficerUserMoves } from 'services/ghcApi'; +import { checkForLockedMovesAndUnlock } from 'services/ghcApi'; const OfficeLoggedInHeader = ({ officeUser, activeRole, logOut }) => { const navigate = useNavigate(); @@ -35,12 +35,13 @@ const OfficeLoggedInHeader = ({ officeUser, activeRole, logOut }) => { let queueText = ''; const location = useLocation(); + const validUnlockingOfficers = [roleTypes.QAE, roleTypes.CSR, roleTypes.GSR, roleTypes.HQ]; if (activeRole === roleTypes.TOO) { queueText = 'moves'; } else if (activeRole === roleTypes.TIO) { queueText = 'payment requests'; - } else if (activeRole === roleTypes.QAE && location.pathname === '/') { - unlockOfficerUserMoves('move', officeUser.id); + } else if (validUnlockingOfficers.includes(activeRole) && location.pathname === '/') { + checkForLockedMovesAndUnlock('move', officeUser.id); } return ( diff --git a/src/sagas/entities.js b/src/sagas/entities.js index 58dc055ec4d..9852c9e3430 100644 --- a/src/sagas/entities.js +++ b/src/sagas/entities.js @@ -63,12 +63,12 @@ export function* updateAllMoves(action) { yield put(addEntities({ serviceMemberMoves: payload })); } -export function* unlockedMoves(action) { - const { payload } = action; +// export function* unlockedMoves(action) { +// const { payload } = action; - const normalizedData = yield call(normalizeResponse, payload, 'move'); - yield put(addEntities(normalizedData)); -} +// const normalizedData = yield call(normalizeResponse, payload, 'move'); +// yield put(addEntities(normalizedData)); +// } export function* watchUpdateEntities() { yield all([ diff --git a/src/services/ghcApi.js b/src/services/ghcApi.js index a516b71071c..bc8353ca653 100644 --- a/src/services/ghcApi.js +++ b/src/services/ghcApi.js @@ -889,7 +889,7 @@ export async function updateAssignedOfficeUserForMove({ moveID, officeUserId, ro }); } -export async function unlockOfficerUserMoves(key, officeUserID) { +export async function checkForLockedMovesAndUnlock(key, officeUserID) { return makeGHCRequest('move.checkForLockedMovesAndUnlock', { officeUserID, }); diff --git a/swagger-def/ghc.yaml b/swagger-def/ghc.yaml index c7d507022d5..758102087bf 100644 --- a/swagger-def/ghc.yaml +++ b/swagger-def/ghc.yaml @@ -4277,7 +4277,7 @@ paths: operationId: deleteAssignedOfficeUser /moves/{officeUserID}/CheckForLockedMovesAndUnlock: parameters: - - description: ID of the move + - description: ID of the move's officer in: path name: officeUserID required: true @@ -4298,7 +4298,7 @@ paths: tags: - move description: >- - Finds and unlocks any locked moves by QAE,GSR, and headquarter officers + Finds and unlocks any locked moves by QAE,CSR, GSR, and headquarter officers operationId: checkForLockedMovesAndUnlock definitions: UnlockedMoves: diff --git a/swagger/ghc.yaml b/swagger/ghc.yaml index bb983134c24..fb9056af02a 100644 --- a/swagger/ghc.yaml +++ b/swagger/ghc.yaml @@ -4478,7 +4478,7 @@ paths: operationId: deleteAssignedOfficeUser /moves/{officeUserID}/CheckForLockedMovesAndUnlock: parameters: - - description: ID of the move + - description: ID of the move's officer in: path name: officeUserID required: true @@ -4498,7 +4498,9 @@ paths: $ref: '#/responses/ServerError' tags: - move - description: Finds and unlocks any locked moves by QAE,GSR, and headquarter officers + description: >- + Finds and unlocks any locked moves by QAE,CSR, GSR, and headquarter + officers operationId: checkForLockedMovesAndUnlock definitions: UnlockedMoves: From d7b7ba08fc46c79e55e417b7dcda09f21d60ae97 Mon Sep 17 00:00:00 2001 From: Jon Spight Date: Wed, 20 Nov 2024 00:07:37 +0000 Subject: [PATCH 21/32] add on test cases (unfinished) --- .../payloads/model_to_payload_test.go | 28 ++++++++++++++----- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/pkg/handlers/ghcapi/internal/payloads/model_to_payload_test.go b/pkg/handlers/ghcapi/internal/payloads/model_to_payload_test.go index b4f4325b325..990e09db80f 100644 --- a/pkg/handlers/ghcapi/internal/payloads/model_to_payload_test.go +++ b/pkg/handlers/ghcapi/internal/payloads/model_to_payload_test.go @@ -29,6 +29,7 @@ func TestMove(t *testing.T) { func (suite *PayloadsSuite) TestPaymentRequestQueue() { officeUser := factory.BuildOfficeUserWithRoles(suite.DB(), nil, []roles.RoleType{roles.RoleTypeTOO}) + officeUserTIO := factory.BuildOfficeUserWithRoles(suite.DB(), nil, []roles.RoleType{roles.RoleTypeTIO}) gbloc := "LKNQ" @@ -55,16 +56,27 @@ func (suite *PayloadsSuite) TestPaymentRequestQueue() { }, nil) paymentRequests := models.PaymentRequests{pr2} - transportationOffice := factory.BuildTransportationOffice(suite.DB(), nil, nil) - paymentRequests[0].MoveTaskOrder.TIOAssignedUser = &officeUser + transportationOffice := factory.BuildTransportationOffice(suite.DB(), []factory.Customization{ + { + Model: models.TransportationOffice{ + Name: "PPSO", + ProvidesCloseout: true, + }, + }, + }, nil) + paymentRequests[0].MoveTaskOrder.TIOAssignedUser = &officeUserTIO paymentRequests[0].MoveTaskOrder.CounselingOffice = &transportationOffice var officeUsers models.OfficeUsers officeUsers = append(officeUsers, officeUser) suite.Run("Test Counseling Offices and TIO AssignedUser ", func() { - result := QueuePaymentRequests(&paymentRequests, officeUsers, officeUser, true, false) - suite.NotNil(result) + queuePaymentRequests := QueuePaymentRequests(&paymentRequests, officeUsers, officeUser, false, false) + suite.NotNil(queuePaymentRequests) + suite.IsType(queuePaymentRequests, &ghcmessages.QueuePaymentRequests{}) + //unpack and check values of assigned to + //unpack and check values and of counseling office + }) } @@ -100,9 +112,11 @@ func (suite *PayloadsSuite) TestPaymentRequestQueueAvailableOfficeUsers() { var officeUsers models.OfficeUsers officeUsers = append(officeUsers, officeUser) - suite.Run("attach available office users if move is assignable", func() { - result := QueuePaymentRequests(&paymentRequests, officeUsers, officeUser, false, false) - suite.NotNil(result) + suite.Run("Payment request is assignable due to not assigend", func() { + queuePaymentRequests := QueuePaymentRequests(&paymentRequests, officeUsers, officeUser, false, false) + suite.NotNil(queuePaymentRequests) + suite.IsType(queuePaymentRequests, &ghcmessages.QueuePaymentRequests{}) + //unpack and check values of assigned to }) } From 17debbb0a7a5d5f032064427f378255e0f398e47 Mon Sep 17 00:00:00 2001 From: KonstanceH Date: Wed, 20 Nov 2024 07:57:07 +0000 Subject: [PATCH 22/32] remove commented out code --- src/sagas/entities.js | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/sagas/entities.js b/src/sagas/entities.js index 9852c9e3430..5d44c894c7b 100644 --- a/src/sagas/entities.js +++ b/src/sagas/entities.js @@ -63,13 +63,6 @@ export function* updateAllMoves(action) { yield put(addEntities({ serviceMemberMoves: payload })); } -// export function* unlockedMoves(action) { -// const { payload } = action; - -// const normalizedData = yield call(normalizeResponse, payload, 'move'); -// yield put(addEntities(normalizedData)); -// } - export function* watchUpdateEntities() { yield all([ takeLatest(UPDATE_SERVICE_MEMBER, updateServiceMember), From 5b3cacdaa19bbff1b1ff8ce7f5b0f0c39b9688fd Mon Sep 17 00:00:00 2001 From: KonstanceH Date: Wed, 20 Nov 2024 17:18:06 +0000 Subject: [PATCH 23/32] Added test --- pkg/handlers/ghcapi/move_test.go | 84 ++++++++++++++++++++++++++++++++ 1 file changed, 84 insertions(+) diff --git a/pkg/handlers/ghcapi/move_test.go b/pkg/handlers/ghcapi/move_test.go index f57267b0d13..6b2704bcdce 100644 --- a/pkg/handlers/ghcapi/move_test.go +++ b/pkg/handlers/ghcapi/move_test.go @@ -7,9 +7,11 @@ import ( "time" "github.com/go-openapi/strfmt" + "github.com/gofrs/uuid" "github.com/stretchr/testify/mock" "github.com/transcom/mymove/pkg/apperror" + "github.com/transcom/mymove/pkg/auth" "github.com/transcom/mymove/pkg/etag" "github.com/transcom/mymove/pkg/factory" moveops "github.com/transcom/mymove/pkg/gen/ghcapi/ghcoperations/move" @@ -884,3 +886,85 @@ func (suite *HandlerSuite) TestUpdateAssignedOfficeUserHandler() { suite.Nil(payload.TIOAssignedUser) }) } + +func (suite *HandlerSuite) TestCheckForLockedMovesAndUnlockHandler() { + var validOfficeUser models.OfficeUser + var move models.Move + + appCtx := suite.AppContextWithSessionForTest(&auth.Session{ + ApplicationName: auth.OfficeApp, + Roles: validOfficeUser.User.Roles, + OfficeUserID: validOfficeUser.ID, + IDToken: "fake_token", + AccessToken: "fakeAccessToken", + UserID: validOfficeUser.ID, + }) + + mockLocker := movelocker.NewMoveLocker() + setupLockedMove := func() { + validOfficeUser = factory.BuildOfficeUserWithRoles(suite.DB(), nil, []roles.RoleType{roles.RoleTypeTOO}) + move = factory.BuildMove(suite.DB(), []factory.Customization{ + { + Model: models.OfficeUser{ + ID: validOfficeUser.ID, + }, + }, + }, nil) + + move, err := mockLocker.LockMove(appCtx, &move, validOfficeUser.ID) + + suite.NoError(err) + suite.NotNil(move.LockedByOfficeUserID) + } + + setupTestData := func() (*http.Request, CheckForLockedMovesAndUnlockHandler) { + req := httptest.NewRequest("GET", "/moves/{officeUserID}/CheckForLockedMovesAndUnlock", nil) + + handler := CheckForLockedMovesAndUnlockHandler{ + HandlerConfig: suite.HandlerConfig(), + MoveUnlocker: movelocker.NewMoveUnlocker(), + } + + return req, handler + } + suite.PreloadData(setupLockedMove) + + suite.Run("Successful unlocking of move", func() { + req, handler := setupTestData() + + expectedPayloadMessage := "Successfully unlocked all move(s) for current office user" + + officeUserID := strfmt.UUID(validOfficeUser.ID.String()) + params := moveops.CheckForLockedMovesAndUnlockParams{ + HTTPRequest: req, + OfficeUserID: officeUserID, + } + + handler.Handle(params) + suite.NotNil(move) + + response := handler.Handle(params) + suite.IsType(&moveops.CheckForLockedMovesAndUnlockOK{}, response) + payload := response.(*moveops.CheckForLockedMovesAndUnlockOK).Payload + suite.NoError(payload.Validate(strfmt.Default)) + + actualMessage := payload.SuccessMessage + suite.Equal(expectedPayloadMessage, string(*actualMessage)) + }) + + suite.Run("Unsucceful unlocking of move - nil officerUserId", func() { + req, handler := setupTestData() + + invalidOfficeUserID := strfmt.UUID(uuid.Nil.String()) + params := moveops.CheckForLockedMovesAndUnlockParams{ + HTTPRequest: req, + OfficeUserID: invalidOfficeUserID, + } + + handler.Handle(params) + response := handler.Handle(params) + suite.IsType(&moveops.CheckForLockedMovesAndUnlockInternalServerError{}, response) + payload := response.(*moveops.CheckForLockedMovesAndUnlockInternalServerError).Payload + suite.Nil(payload) + }) +} From f8e1c4fcb0e1b875b991a2824f2cf94da309ae4a Mon Sep 17 00:00:00 2001 From: Jon Spight Date: Wed, 20 Nov 2024 17:28:31 +0000 Subject: [PATCH 24/32] added test cases(counseling office, Assignable,AssignedTO) --- .../payloads/model_to_payload_test.go | 80 +++++++++---------- 1 file changed, 37 insertions(+), 43 deletions(-) diff --git a/pkg/handlers/ghcapi/internal/payloads/model_to_payload_test.go b/pkg/handlers/ghcapi/internal/payloads/model_to_payload_test.go index 990e09db80f..f7568e13fe1 100644 --- a/pkg/handlers/ghcapi/internal/payloads/model_to_payload_test.go +++ b/pkg/handlers/ghcapi/internal/payloads/model_to_payload_test.go @@ -64,59 +64,53 @@ func (suite *PayloadsSuite) TestPaymentRequestQueue() { }, }, }, nil) - paymentRequests[0].MoveTaskOrder.TIOAssignedUser = &officeUserTIO - paymentRequests[0].MoveTaskOrder.CounselingOffice = &transportationOffice - var officeUsers models.OfficeUsers officeUsers = append(officeUsers, officeUser) - - suite.Run("Test Counseling Offices and TIO AssignedUser ", func() { - queuePaymentRequests := QueuePaymentRequests(&paymentRequests, officeUsers, officeUser, false, false) - suite.NotNil(queuePaymentRequests) - suite.IsType(queuePaymentRequests, &ghcmessages.QueuePaymentRequests{}) - //unpack and check values of assigned to - //unpack and check values and of counseling office - + var paymentRequestsQueue = QueuePaymentRequests(&paymentRequests, officeUsers, officeUser, false, false) + + suite.Run("Test Payment request is assignable due to not being assigend", func() { + // paymentRequests := QueuePaymentRequests(&paymentRequests, officeUsers, officeUser, false, false) + paymentRequestCopy := *paymentRequestsQueue + suite.NotNil(paymentRequestsQueue) + suite.IsType(paymentRequestsQueue, &ghcmessages.QueuePaymentRequests{}) + suite.Nil(paymentRequestCopy[0].AssignedTo) }) -} -func (suite *PayloadsSuite) TestPaymentRequestQueueAvailableOfficeUsers() { - officeUser := factory.BuildOfficeUserWithRoles(suite.DB(), nil, []roles.RoleType{roles.RoleTypeTOO}) + suite.Run("Test Payment request has no counseling office", func() { + // paymentRequests := QueuePaymentRequests(&paymentRequests, officeUsers, officeUser, false, false) + paymentRequestCopy := *paymentRequestsQueue + suite.NotNil(paymentRequestsQueue) + suite.IsType(paymentRequestsQueue, &ghcmessages.QueuePaymentRequests{}) + suite.Nil(paymentRequestCopy[0].CounselingOffice) + }) - gbloc := "LKNQ" + paymentRequests[0].MoveTaskOrder.TIOAssignedUser = &officeUserTIO + paymentRequests[0].MoveTaskOrder.CounselingOffice = &transportationOffice - approvedMove := factory.BuildAvailableToPrimeMove(suite.DB(), nil, nil) - approvedMove.ShipmentGBLOC = append(approvedMove.ShipmentGBLOC, models.MoveToGBLOC{GBLOC: &gbloc}) + paymentRequestsQueue = QueuePaymentRequests(&paymentRequests, officeUsers, officeUser, false, false) - pr2 := factory.BuildPaymentRequest(suite.DB(), []factory.Customization{ - { - Model: approvedMove, - LinkOnly: true, - }, - { - Model: models.TransportationOffice{ - Gbloc: "LKNQ", - }, - Type: &factory.TransportationOffices.OriginDutyLocation, - }, - { - Model: models.DutyLocation{ - Name: "KJKJKJKJKJK", - }, - Type: &factory.DutyLocations.OriginDutyLocation, - }, - }, nil) + suite.Run("Test PaymentRequest has both Counseling Office and TIO AssignedUser ", func() { + // PaymentRequests := QueuePaymentRequests(&paymentRequests, officeUsers, officeUser, true, false) + PaymentRequestsCopy := *paymentRequestsQueue - paymentRequests := models.PaymentRequests{pr2} + suite.NotNil(PaymentRequests) + suite.IsType(&ghcmessages.QueuePaymentRequests{}, paymentRequestsQueue) + suite.IsType(&ghcmessages.QueuePaymentRequest{}, PaymentRequestsCopy[0]) + suite.Equal(PaymentRequestsCopy[0].AssignedTo.FirstName, officeUserTIO.FirstName) + suite.Equal(PaymentRequestsCopy[0].AssignedTo.LastName, officeUserTIO.LastName) + suite.Equal(*PaymentRequestsCopy[0].CounselingOffice, transportationOffice.Name) + }) - var officeUsers models.OfficeUsers - officeUsers = append(officeUsers, officeUser) + suite.Run("Test PaymentRequest is assignable due to user Supervisor role", func() { + paymentRequests := QueuePaymentRequests(&paymentRequests, officeUsers, officeUser, true, false) + paymentRequestCopy := *paymentRequests + suite.Equal(paymentRequestCopy[0].Assignable, true) + }) - suite.Run("Payment request is assignable due to not assigend", func() { - queuePaymentRequests := QueuePaymentRequests(&paymentRequests, officeUsers, officeUser, false, false) - suite.NotNil(queuePaymentRequests) - suite.IsType(queuePaymentRequests, &ghcmessages.QueuePaymentRequests{}) - //unpack and check values of assigned to + suite.Run("Test PaymentRequest is not assignable due to user HQ role", func() { + paymentRequests := QueuePaymentRequests(&paymentRequests, officeUsers, officeUser, false, true) + paymentRequestCopy := *paymentRequests + suite.Equal(paymentRequestCopy[0].Assignable, false) }) } From 483b8aa96f8fee7e42b3efe689dccaa0afed5b97 Mon Sep 17 00:00:00 2001 From: Cory Kleinjan Date: Wed, 20 Nov 2024 17:45:44 +0000 Subject: [PATCH 25/32] Turning dtod simulate outage off --- config/env/loadtest.app.env | 1 - 1 file changed, 1 deletion(-) diff --git a/config/env/loadtest.app.env b/config/env/loadtest.app.env index 109a11691b3..521864b95ce 100644 --- a/config/env/loadtest.app.env +++ b/config/env/loadtest.app.env @@ -9,7 +9,6 @@ DEBUG_PPROF=false DEVLOCAL_AUTH=true DOD_CA_PACKAGE=/config/tls/api.loadtest.dp3.us.chain.der.p7b DTOD_USE_MOCK=false -DTOD_SIMULATE_OUTAGE=true EMAIL_BACKEND=ses FEATURE_FLAG_SERVER_URL=http://flipt.svc-loadtest.local:8080 HEALTH_SERVER_ENABLED=true From 93307415bb85d93168ca0f9bbfcedb7290850441 Mon Sep 17 00:00:00 2001 From: KonstanceH Date: Wed, 20 Nov 2024 17:45:02 +0000 Subject: [PATCH 26/32] checking circleci test --- pkg/handlers/ghcapi/move_test.go | 31 +++++++++++++++---------------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/pkg/handlers/ghcapi/move_test.go b/pkg/handlers/ghcapi/move_test.go index 6b2704bcdce..572dcae97b0 100644 --- a/pkg/handlers/ghcapi/move_test.go +++ b/pkg/handlers/ghcapi/move_test.go @@ -7,7 +7,6 @@ import ( "time" "github.com/go-openapi/strfmt" - "github.com/gofrs/uuid" "github.com/stretchr/testify/mock" "github.com/transcom/mymove/pkg/apperror" @@ -952,19 +951,19 @@ func (suite *HandlerSuite) TestCheckForLockedMovesAndUnlockHandler() { suite.Equal(expectedPayloadMessage, string(*actualMessage)) }) - suite.Run("Unsucceful unlocking of move - nil officerUserId", func() { - req, handler := setupTestData() - - invalidOfficeUserID := strfmt.UUID(uuid.Nil.String()) - params := moveops.CheckForLockedMovesAndUnlockParams{ - HTTPRequest: req, - OfficeUserID: invalidOfficeUserID, - } - - handler.Handle(params) - response := handler.Handle(params) - suite.IsType(&moveops.CheckForLockedMovesAndUnlockInternalServerError{}, response) - payload := response.(*moveops.CheckForLockedMovesAndUnlockInternalServerError).Payload - suite.Nil(payload) - }) + // suite.Run("Unsucceful unlocking of move - nil officerUserId", func() { + // req, handler := setupTestData() + + // invalidOfficeUserID := strfmt.UUID(uuid.Nil.String()) + // params := moveops.CheckForLockedMovesAndUnlockParams{ + // HTTPRequest: req, + // OfficeUserID: invalidOfficeUserID, + // } + + // handler.Handle(params) + // response := handler.Handle(params) + // suite.IsType(&moveops.CheckForLockedMovesAndUnlockInternalServerError{}, response) + // payload := response.(*moveops.CheckForLockedMovesAndUnlockInternalServerError).Payload + // suite.Nil(payload) + // }) } From 54d67a69165032efa948ed544f2d6d750802cacd Mon Sep 17 00:00:00 2001 From: Jon Spight Date: Wed, 20 Nov 2024 17:49:12 +0000 Subject: [PATCH 27/32] comment removal --- pkg/handlers/ghcapi/internal/payloads/model_to_payload_test.go | 3 --- 1 file changed, 3 deletions(-) diff --git a/pkg/handlers/ghcapi/internal/payloads/model_to_payload_test.go b/pkg/handlers/ghcapi/internal/payloads/model_to_payload_test.go index f7568e13fe1..4e635169054 100644 --- a/pkg/handlers/ghcapi/internal/payloads/model_to_payload_test.go +++ b/pkg/handlers/ghcapi/internal/payloads/model_to_payload_test.go @@ -69,7 +69,6 @@ func (suite *PayloadsSuite) TestPaymentRequestQueue() { var paymentRequestsQueue = QueuePaymentRequests(&paymentRequests, officeUsers, officeUser, false, false) suite.Run("Test Payment request is assignable due to not being assigend", func() { - // paymentRequests := QueuePaymentRequests(&paymentRequests, officeUsers, officeUser, false, false) paymentRequestCopy := *paymentRequestsQueue suite.NotNil(paymentRequestsQueue) suite.IsType(paymentRequestsQueue, &ghcmessages.QueuePaymentRequests{}) @@ -77,7 +76,6 @@ func (suite *PayloadsSuite) TestPaymentRequestQueue() { }) suite.Run("Test Payment request has no counseling office", func() { - // paymentRequests := QueuePaymentRequests(&paymentRequests, officeUsers, officeUser, false, false) paymentRequestCopy := *paymentRequestsQueue suite.NotNil(paymentRequestsQueue) suite.IsType(paymentRequestsQueue, &ghcmessages.QueuePaymentRequests{}) @@ -90,7 +88,6 @@ func (suite *PayloadsSuite) TestPaymentRequestQueue() { paymentRequestsQueue = QueuePaymentRequests(&paymentRequests, officeUsers, officeUser, false, false) suite.Run("Test PaymentRequest has both Counseling Office and TIO AssignedUser ", func() { - // PaymentRequests := QueuePaymentRequests(&paymentRequests, officeUsers, officeUser, true, false) PaymentRequestsCopy := *paymentRequestsQueue suite.NotNil(PaymentRequests) From b48b21635ae9d2f9da9169f89b7414cea2ddda69 Mon Sep 17 00:00:00 2001 From: Tae Jung Date: Wed, 20 Nov 2024 17:55:09 +0000 Subject: [PATCH 28/32] fixed boolean check --- pkg/handlers/primeapi/payloads/model_to_payload.go | 4 ++-- pkg/handlers/primeapiv2/payloads/model_to_payload.go | 4 ++-- pkg/handlers/primeapiv3/payloads/model_to_payload.go | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/pkg/handlers/primeapi/payloads/model_to_payload.go b/pkg/handlers/primeapi/payloads/model_to_payload.go index 61e9794e8c2..32fbcde6cec 100644 --- a/pkg/handlers/primeapi/payloads/model_to_payload.go +++ b/pkg/handlers/primeapi/payloads/model_to_payload.go @@ -729,7 +729,7 @@ func MTOServiceItem(mtoServiceItem *models.MTOServiceItem) primemessages.MTOServ Width: crate.Width.Int32Ptr(), } if mtoServiceItem.ReService.Code == models.ReServiceCodeICRT && mtoServiceItem.MTOShipment.PickupAddress != nil { - if mtoServiceItem.MTOShipment.PickupAddress.IsOconus == models.BoolPointer(true) { + if *mtoServiceItem.MTOShipment.PickupAddress.IsOconus { cratingSI.Market = models.MarketOconus.FullString() } else { cratingSI.Market = models.MarketConus.FullString() @@ -737,7 +737,7 @@ func MTOServiceItem(mtoServiceItem *models.MTOServiceItem) primemessages.MTOServ } if mtoServiceItem.ReService.Code == models.ReServiceCodeIUCRT && mtoServiceItem.MTOShipment.DestinationAddress != nil { - if mtoServiceItem.MTOShipment.DestinationAddress.IsOconus == models.BoolPointer(true) { + if *mtoServiceItem.MTOShipment.DestinationAddress.IsOconus { cratingSI.Market = models.MarketOconus.FullString() } else { cratingSI.Market = models.MarketConus.FullString() diff --git a/pkg/handlers/primeapiv2/payloads/model_to_payload.go b/pkg/handlers/primeapiv2/payloads/model_to_payload.go index 1605e1feacc..e7350548dd9 100644 --- a/pkg/handlers/primeapiv2/payloads/model_to_payload.go +++ b/pkg/handlers/primeapiv2/payloads/model_to_payload.go @@ -657,7 +657,7 @@ func MTOServiceItem(mtoServiceItem *models.MTOServiceItem) primev2messages.MTOSe Width: crate.Width.Int32Ptr(), } if mtoServiceItem.ReService.Code == models.ReServiceCodeICRT && mtoServiceItem.MTOShipment.PickupAddress != nil { - if mtoServiceItem.MTOShipment.PickupAddress.IsOconus == models.BoolPointer(true) { + if *mtoServiceItem.MTOShipment.PickupAddress.IsOconus { cratingSI.Market = models.MarketOconus.FullString() } else { cratingSI.Market = models.MarketConus.FullString() @@ -665,7 +665,7 @@ func MTOServiceItem(mtoServiceItem *models.MTOServiceItem) primev2messages.MTOSe } if mtoServiceItem.ReService.Code == models.ReServiceCodeIUCRT && mtoServiceItem.MTOShipment.DestinationAddress != nil { - if mtoServiceItem.MTOShipment.DestinationAddress.IsOconus == models.BoolPointer(true) { + if *mtoServiceItem.MTOShipment.DestinationAddress.IsOconus { cratingSI.Market = models.MarketOconus.FullString() } else { cratingSI.Market = models.MarketConus.FullString() diff --git a/pkg/handlers/primeapiv3/payloads/model_to_payload.go b/pkg/handlers/primeapiv3/payloads/model_to_payload.go index f39e08d3e21..ab2655b1bd8 100644 --- a/pkg/handlers/primeapiv3/payloads/model_to_payload.go +++ b/pkg/handlers/primeapiv3/payloads/model_to_payload.go @@ -773,7 +773,7 @@ func MTOServiceItem(mtoServiceItem *models.MTOServiceItem) primev3messages.MTOSe Width: crate.Width.Int32Ptr(), } if mtoServiceItem.ReService.Code == models.ReServiceCodeICRT && mtoServiceItem.MTOShipment.PickupAddress != nil { - if mtoServiceItem.MTOShipment.PickupAddress.IsOconus == models.BoolPointer(true) { + if *mtoServiceItem.MTOShipment.PickupAddress.IsOconus { cratingSI.Market = models.MarketOconus.FullString() } else { cratingSI.Market = models.MarketConus.FullString() @@ -781,7 +781,7 @@ func MTOServiceItem(mtoServiceItem *models.MTOServiceItem) primev3messages.MTOSe } if mtoServiceItem.ReService.Code == models.ReServiceCodeIUCRT && mtoServiceItem.MTOShipment.DestinationAddress != nil { - if mtoServiceItem.MTOShipment.DestinationAddress.IsOconus == models.BoolPointer(true) { + if *mtoServiceItem.MTOShipment.DestinationAddress.IsOconus { cratingSI.Market = models.MarketOconus.FullString() } else { cratingSI.Market = models.MarketConus.FullString() From 373309bd6a1a76b6f0962989e44befbaa3e48ccc Mon Sep 17 00:00:00 2001 From: KonstanceH Date: Wed, 20 Nov 2024 19:42:38 +0000 Subject: [PATCH 29/32] moved context inside setup --- pkg/handlers/ghcapi/move_test.go | 49 ++++++++++++++++---------------- 1 file changed, 25 insertions(+), 24 deletions(-) diff --git a/pkg/handlers/ghcapi/move_test.go b/pkg/handlers/ghcapi/move_test.go index 572dcae97b0..94caddce1f2 100644 --- a/pkg/handlers/ghcapi/move_test.go +++ b/pkg/handlers/ghcapi/move_test.go @@ -7,6 +7,7 @@ import ( "time" "github.com/go-openapi/strfmt" + "github.com/gofrs/uuid" "github.com/stretchr/testify/mock" "github.com/transcom/mymove/pkg/apperror" @@ -890,17 +891,17 @@ func (suite *HandlerSuite) TestCheckForLockedMovesAndUnlockHandler() { var validOfficeUser models.OfficeUser var move models.Move - appCtx := suite.AppContextWithSessionForTest(&auth.Session{ - ApplicationName: auth.OfficeApp, - Roles: validOfficeUser.User.Roles, - OfficeUserID: validOfficeUser.ID, - IDToken: "fake_token", - AccessToken: "fakeAccessToken", - UserID: validOfficeUser.ID, - }) - mockLocker := movelocker.NewMoveLocker() setupLockedMove := func() { + appCtx := suite.AppContextWithSessionForTest(&auth.Session{ + ApplicationName: auth.OfficeApp, + Roles: validOfficeUser.User.Roles, + OfficeUserID: validOfficeUser.ID, + IDToken: "fake_token", + AccessToken: "fakeAccessToken", + UserID: validOfficeUser.ID, + }) + validOfficeUser = factory.BuildOfficeUserWithRoles(suite.DB(), nil, []roles.RoleType{roles.RoleTypeTOO}) move = factory.BuildMove(suite.DB(), []factory.Customization{ { @@ -951,19 +952,19 @@ func (suite *HandlerSuite) TestCheckForLockedMovesAndUnlockHandler() { suite.Equal(expectedPayloadMessage, string(*actualMessage)) }) - // suite.Run("Unsucceful unlocking of move - nil officerUserId", func() { - // req, handler := setupTestData() - - // invalidOfficeUserID := strfmt.UUID(uuid.Nil.String()) - // params := moveops.CheckForLockedMovesAndUnlockParams{ - // HTTPRequest: req, - // OfficeUserID: invalidOfficeUserID, - // } - - // handler.Handle(params) - // response := handler.Handle(params) - // suite.IsType(&moveops.CheckForLockedMovesAndUnlockInternalServerError{}, response) - // payload := response.(*moveops.CheckForLockedMovesAndUnlockInternalServerError).Payload - // suite.Nil(payload) - // }) + suite.Run("Unsucceful unlocking of move - nil officerUserId", func() { + req, handler := setupTestData() + + invalidOfficeUserID := strfmt.UUID(uuid.Nil.String()) + params := moveops.CheckForLockedMovesAndUnlockParams{ + HTTPRequest: req, + OfficeUserID: invalidOfficeUserID, + } + + handler.Handle(params) + response := handler.Handle(params) + suite.IsType(&moveops.CheckForLockedMovesAndUnlockInternalServerError{}, response) + payload := response.(*moveops.CheckForLockedMovesAndUnlockInternalServerError).Payload + suite.Nil(payload) + }) } From 9abcc5f8a2a7cdf3f454157176b5723edeae3865 Mon Sep 17 00:00:00 2001 From: Cory Kleinjan Date: Wed, 20 Nov 2024 19:51:26 +0000 Subject: [PATCH 30/32] Adding in mistakenly removed line --- .../office/servicescounseling/servicesCounselingFlows.spec.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/playwright/tests/office/servicescounseling/servicesCounselingFlows.spec.js b/playwright/tests/office/servicescounseling/servicesCounselingFlows.spec.js index cd049d566c9..a15a6440d9e 100644 --- a/playwright/tests/office/servicescounseling/servicesCounselingFlows.spec.js +++ b/playwright/tests/office/servicescounseling/servicesCounselingFlows.spec.js @@ -428,6 +428,8 @@ test.describe('Services counselor user', () => { await page.getByRole('button', { name: 'Confirm' }).click(); await scPage.waitForPage.moveDetails(); + await expect(page.getByText('PACKET READY FOR DOWNLOAD')).toBeVisible(); + // Navigate to the "View documents" page await expect(page.getByRole('button', { name: /View documents/i })).toBeVisible(); await page.getByRole('button', { name: 'View documents' }).click(); From b6b34432024131944ebfa7250285aaf06cbce272 Mon Sep 17 00:00:00 2001 From: KonstanceH Date: Thu, 21 Nov 2024 00:41:38 +0000 Subject: [PATCH 31/32] stopping point to push working changes --- pkg/gen/ghcapi/embedded_spec.go | 4 ++-- .../move/check_for_locked_moves_and_unlock.go | 2 +- src/constants/userRoles.js | 1 - src/containers/Headers/OfficeLoggedInHeader.jsx | 7 ++++++- swagger-def/ghc.yaml | 2 +- swagger/ghc.yaml | 4 +--- 6 files changed, 11 insertions(+), 9 deletions(-) diff --git a/pkg/gen/ghcapi/embedded_spec.go b/pkg/gen/ghcapi/embedded_spec.go index 02047ce4490..b136faa2a72 100644 --- a/pkg/gen/ghcapi/embedded_spec.go +++ b/pkg/gen/ghcapi/embedded_spec.go @@ -2799,7 +2799,7 @@ func init() { }, "/moves/{officeUserID}/CheckForLockedMovesAndUnlock": { "patch": { - "description": "Finds and unlocks any locked moves by QAE,CSR, GSR, and headquarter officers", + "description": "Finds and unlocks any locked moves by an office user", "consumes": [ "application/json" ], @@ -18474,7 +18474,7 @@ func init() { }, "/moves/{officeUserID}/CheckForLockedMovesAndUnlock": { "patch": { - "description": "Finds and unlocks any locked moves by QAE,CSR, GSR, and headquarter officers", + "description": "Finds and unlocks any locked moves by an office user", "consumes": [ "application/json" ], diff --git a/pkg/gen/ghcapi/ghcoperations/move/check_for_locked_moves_and_unlock.go b/pkg/gen/ghcapi/ghcoperations/move/check_for_locked_moves_and_unlock.go index da71c6ea45a..d6fdd41f190 100644 --- a/pkg/gen/ghcapi/ghcoperations/move/check_for_locked_moves_and_unlock.go +++ b/pkg/gen/ghcapi/ghcoperations/move/check_for_locked_moves_and_unlock.go @@ -32,7 +32,7 @@ func NewCheckForLockedMovesAndUnlock(ctx *middleware.Context, handler CheckForLo /* CheckForLockedMovesAndUnlock swagger:route PATCH /moves/{officeUserID}/CheckForLockedMovesAndUnlock move checkForLockedMovesAndUnlock -Finds and unlocks any locked moves by QAE,CSR, GSR, and headquarter officers +Finds and unlocks any locked moves by an office user */ type CheckForLockedMovesAndUnlock struct { Context *middleware.Context diff --git a/src/constants/userRoles.js b/src/constants/userRoles.js index 959cec470e6..45739f19da0 100644 --- a/src/constants/userRoles.js +++ b/src/constants/userRoles.js @@ -10,7 +10,6 @@ export const roleTypes = { CUSTOMER_SERVICE_REPRESENTATIVE: 'customer_service_representative', GSR: 'gsr', HQ: 'headquarters', - CSR: 'csr', }; export const adminOfficeRoles = [ diff --git a/src/containers/Headers/OfficeLoggedInHeader.jsx b/src/containers/Headers/OfficeLoggedInHeader.jsx index 28d4c34b85e..93965f8ce5f 100644 --- a/src/containers/Headers/OfficeLoggedInHeader.jsx +++ b/src/containers/Headers/OfficeLoggedInHeader.jsx @@ -35,7 +35,12 @@ const OfficeLoggedInHeader = ({ officeUser, activeRole, logOut }) => { let queueText = ''; const location = useLocation(); - const validUnlockingOfficers = [roleTypes.QAE, roleTypes.CSR, roleTypes.GSR, roleTypes.HQ]; + const validUnlockingOfficers = [ + roleTypes.QAE, + roleTypes.CUSTOMER_SERVICE_REPRESENTATIVE, + roleTypes.GSR, + roleTypes.HQ, + ]; if (activeRole === roleTypes.TOO) { queueText = 'moves'; } else if (activeRole === roleTypes.TIO) { diff --git a/swagger-def/ghc.yaml b/swagger-def/ghc.yaml index 8e5d71176dc..3c701cd2bee 100644 --- a/swagger-def/ghc.yaml +++ b/swagger-def/ghc.yaml @@ -4326,7 +4326,7 @@ paths: tags: - move description: >- - Finds and unlocks any locked moves by QAE,CSR, GSR, and headquarter officers + Finds and unlocks any locked moves by an office user operationId: checkForLockedMovesAndUnlock definitions: UnlockedMoves: diff --git a/swagger/ghc.yaml b/swagger/ghc.yaml index ac8256f7eec..b0117bf76e1 100644 --- a/swagger/ghc.yaml +++ b/swagger/ghc.yaml @@ -4528,9 +4528,7 @@ paths: $ref: '#/responses/ServerError' tags: - move - description: >- - Finds and unlocks any locked moves by QAE,CSR, GSR, and headquarter - officers + description: Finds and unlocks any locked moves by an office user operationId: checkForLockedMovesAndUnlock definitions: UnlockedMoves: From 3e04d721256dce95f623debfc3feeddcdeb57ed9 Mon Sep 17 00:00:00 2001 From: KonstanceH Date: Thu, 21 Nov 2024 06:45:51 +0000 Subject: [PATCH 32/32] removed successMessage frun unlockedMoves and definistions. updated test --- pkg/gen/ghcapi/embedded_spec.go | 36 ++++++------- .../move/check_for_locked_moves_and_unlock.go | 41 +++++++++++++++ ...k_for_locked_moves_and_unlock_responses.go | 6 +-- pkg/gen/ghcmessages/unlocked_moves.go | 50 ------------------- pkg/handlers/ghcapi/move.go | 10 ++-- pkg/handlers/ghcapi/move_test.go | 2 +- src/services/ghcApi.js | 2 +- swagger-def/ghc.yaml | 13 ++--- swagger/ghc.yaml | 13 ++--- 9 files changed, 74 insertions(+), 99 deletions(-) delete mode 100644 pkg/gen/ghcmessages/unlocked_moves.go diff --git a/pkg/gen/ghcapi/embedded_spec.go b/pkg/gen/ghcapi/embedded_spec.go index b136faa2a72..35af9c64c8a 100644 --- a/pkg/gen/ghcapi/embedded_spec.go +++ b/pkg/gen/ghcapi/embedded_spec.go @@ -2814,7 +2814,13 @@ func init() { "200": { "description": "Successfully unlocked officer's move(s).", "schema": { - "$ref": "#/definitions/UnlockedMoves" + "type": "object", + "properties": { + "successMessage": { + "type": "string", + "example": "OK" + } + } } }, "500": { @@ -13692,16 +13698,6 @@ func init() { "$ref": "#/definitions/TransportationOffice" } }, - "UnlockedMoves": { - "type": "object", - "properties": { - "successMessage": { - "type": "string", - "format": "string", - "x-nullable": true - } - } - }, "UpdateAllowancePayload": { "type": "object", "properties": { @@ -18489,7 +18485,13 @@ func init() { "200": { "description": "Successfully unlocked officer's move(s).", "schema": { - "$ref": "#/definitions/UnlockedMoves" + "type": "object", + "properties": { + "successMessage": { + "type": "string", + "example": "OK" + } + } } }, "500": { @@ -30325,16 +30327,6 @@ func init() { "$ref": "#/definitions/TransportationOffice" } }, - "UnlockedMoves": { - "type": "object", - "properties": { - "successMessage": { - "type": "string", - "format": "string", - "x-nullable": true - } - } - }, "UpdateAllowancePayload": { "type": "object", "properties": { diff --git a/pkg/gen/ghcapi/ghcoperations/move/check_for_locked_moves_and_unlock.go b/pkg/gen/ghcapi/ghcoperations/move/check_for_locked_moves_and_unlock.go index d6fdd41f190..1d723e61825 100644 --- a/pkg/gen/ghcapi/ghcoperations/move/check_for_locked_moves_and_unlock.go +++ b/pkg/gen/ghcapi/ghcoperations/move/check_for_locked_moves_and_unlock.go @@ -6,9 +6,12 @@ package move // Editing this file might prove futile when you re-run the generate command import ( + "context" "net/http" "github.com/go-openapi/runtime/middleware" + "github.com/go-openapi/strfmt" + "github.com/go-openapi/swag" ) // CheckForLockedMovesAndUnlockHandlerFunc turns a function with the right signature into a check for locked moves and unlock handler @@ -54,3 +57,41 @@ func (o *CheckForLockedMovesAndUnlock) ServeHTTP(rw http.ResponseWriter, r *http o.Context.Respond(rw, r, route.Produces, route, res) } + +// CheckForLockedMovesAndUnlockOKBody check for locked moves and unlock o k body +// +// swagger:model CheckForLockedMovesAndUnlockOKBody +type CheckForLockedMovesAndUnlockOKBody struct { + + // success message + // Example: OK + SuccessMessage string `json:"successMessage,omitempty"` +} + +// Validate validates this check for locked moves and unlock o k body +func (o *CheckForLockedMovesAndUnlockOKBody) Validate(formats strfmt.Registry) error { + return nil +} + +// ContextValidate validates this check for locked moves and unlock o k body based on context it is used +func (o *CheckForLockedMovesAndUnlockOKBody) ContextValidate(ctx context.Context, formats strfmt.Registry) error { + return nil +} + +// MarshalBinary interface implementation +func (o *CheckForLockedMovesAndUnlockOKBody) MarshalBinary() ([]byte, error) { + if o == nil { + return nil, nil + } + return swag.WriteJSON(o) +} + +// UnmarshalBinary interface implementation +func (o *CheckForLockedMovesAndUnlockOKBody) UnmarshalBinary(b []byte) error { + var res CheckForLockedMovesAndUnlockOKBody + if err := swag.ReadJSON(b, &res); err != nil { + return err + } + *o = res + return nil +} diff --git a/pkg/gen/ghcapi/ghcoperations/move/check_for_locked_moves_and_unlock_responses.go b/pkg/gen/ghcapi/ghcoperations/move/check_for_locked_moves_and_unlock_responses.go index 3c3b2f97ff3..8b5abbefb35 100644 --- a/pkg/gen/ghcapi/ghcoperations/move/check_for_locked_moves_and_unlock_responses.go +++ b/pkg/gen/ghcapi/ghcoperations/move/check_for_locked_moves_and_unlock_responses.go @@ -26,7 +26,7 @@ type CheckForLockedMovesAndUnlockOK struct { /* In: Body */ - Payload *ghcmessages.UnlockedMoves `json:"body,omitempty"` + Payload *CheckForLockedMovesAndUnlockOKBody `json:"body,omitempty"` } // NewCheckForLockedMovesAndUnlockOK creates CheckForLockedMovesAndUnlockOK with default headers values @@ -36,13 +36,13 @@ func NewCheckForLockedMovesAndUnlockOK() *CheckForLockedMovesAndUnlockOK { } // WithPayload adds the payload to the check for locked moves and unlock o k response -func (o *CheckForLockedMovesAndUnlockOK) WithPayload(payload *ghcmessages.UnlockedMoves) *CheckForLockedMovesAndUnlockOK { +func (o *CheckForLockedMovesAndUnlockOK) WithPayload(payload *CheckForLockedMovesAndUnlockOKBody) *CheckForLockedMovesAndUnlockOK { o.Payload = payload return o } // SetPayload sets the payload to the check for locked moves and unlock o k response -func (o *CheckForLockedMovesAndUnlockOK) SetPayload(payload *ghcmessages.UnlockedMoves) { +func (o *CheckForLockedMovesAndUnlockOK) SetPayload(payload *CheckForLockedMovesAndUnlockOKBody) { o.Payload = payload } diff --git a/pkg/gen/ghcmessages/unlocked_moves.go b/pkg/gen/ghcmessages/unlocked_moves.go deleted file mode 100644 index 0b3eaf5535a..00000000000 --- a/pkg/gen/ghcmessages/unlocked_moves.go +++ /dev/null @@ -1,50 +0,0 @@ -// Code generated by go-swagger; DO NOT EDIT. - -package ghcmessages - -// This file was generated by the swagger tool. -// Editing this file might prove futile when you re-run the swagger generate command - -import ( - "context" - - "github.com/go-openapi/strfmt" - "github.com/go-openapi/swag" -) - -// UnlockedMoves unlocked moves -// -// swagger:model UnlockedMoves -type UnlockedMoves struct { - - // success message - SuccessMessage *string `json:"successMessage,omitempty"` -} - -// Validate validates this unlocked moves -func (m *UnlockedMoves) Validate(formats strfmt.Registry) error { - return nil -} - -// ContextValidate validates this unlocked moves based on context it is used -func (m *UnlockedMoves) ContextValidate(ctx context.Context, formats strfmt.Registry) error { - return nil -} - -// MarshalBinary interface implementation -func (m *UnlockedMoves) MarshalBinary() ([]byte, error) { - if m == nil { - return nil, nil - } - return swag.WriteJSON(m) -} - -// UnmarshalBinary interface implementation -func (m *UnlockedMoves) UnmarshalBinary(b []byte) error { - var res UnlockedMoves - if err := swag.ReadJSON(b, &res); err != nil { - return err - } - *m = res - return nil -} diff --git a/pkg/handlers/ghcapi/move.go b/pkg/handlers/ghcapi/move.go index e2a692182cd..a0a01e10770 100644 --- a/pkg/handlers/ghcapi/move.go +++ b/pkg/handlers/ghcapi/move.go @@ -346,13 +346,11 @@ func (h CheckForLockedMovesAndUnlockHandler) Handle(params moveop.CheckForLocked if err != nil { return moveop.NewCheckForLockedMovesAndUnlockInternalServerError(), err } - payloadMessage := "Successfully unlocked all move(s) for current office user" + var payload moveop.CheckForLockedMovesAndUnlockOK + payload.SetPayload(&moveop.CheckForLockedMovesAndUnlockOKBody{ + SuccessMessage: "Successfully unlocked all move(s) for current office user"}) - payload := ghcmessages.UnlockedMoves{ - SuccessMessage: &payloadMessage, - } - - return moveop.NewCheckForLockedMovesAndUnlockOK().WithPayload(&payload), nil + return &payload, nil }) } diff --git a/pkg/handlers/ghcapi/move_test.go b/pkg/handlers/ghcapi/move_test.go index 94caddce1f2..f345c7cfb85 100644 --- a/pkg/handlers/ghcapi/move_test.go +++ b/pkg/handlers/ghcapi/move_test.go @@ -949,7 +949,7 @@ func (suite *HandlerSuite) TestCheckForLockedMovesAndUnlockHandler() { suite.NoError(payload.Validate(strfmt.Default)) actualMessage := payload.SuccessMessage - suite.Equal(expectedPayloadMessage, string(*actualMessage)) + suite.Equal(expectedPayloadMessage, actualMessage) }) suite.Run("Unsucceful unlocking of move - nil officerUserId", func() { diff --git a/src/services/ghcApi.js b/src/services/ghcApi.js index 58894e9eabd..2d68eeca783 100644 --- a/src/services/ghcApi.js +++ b/src/services/ghcApi.js @@ -890,7 +890,7 @@ export async function updateAssignedOfficeUserForMove({ moveID, officeUserId, ro } export async function checkForLockedMovesAndUnlock(key, officeUserID) { - return makeGHCRequest('move.checkForLockedMovesAndUnlock', { + return makeGHCRequestRaw('move.checkForLockedMovesAndUnlock', { officeUserID, }); } diff --git a/swagger-def/ghc.yaml b/swagger-def/ghc.yaml index 3c701cd2bee..175170bf015 100644 --- a/swagger-def/ghc.yaml +++ b/swagger-def/ghc.yaml @@ -4320,7 +4320,11 @@ paths: '200': description: Successfully unlocked officer's move(s). schema: - $ref: '#/definitions/UnlockedMoves' + type: object + properties: + successMessage: + type: string + example: OK '500': $ref: '#/responses/ServerError' tags: @@ -4329,13 +4333,6 @@ paths: Finds and unlocks any locked moves by an office user operationId: checkForLockedMovesAndUnlock definitions: - UnlockedMoves: - type: object - properties: - successMessage: - type: string - format: string - x-nullable: true ApplicationParameters: type: object properties: diff --git a/swagger/ghc.yaml b/swagger/ghc.yaml index b0117bf76e1..df15db8b85c 100644 --- a/swagger/ghc.yaml +++ b/swagger/ghc.yaml @@ -4523,7 +4523,11 @@ paths: '200': description: Successfully unlocked officer's move(s). schema: - $ref: '#/definitions/UnlockedMoves' + type: object + properties: + successMessage: + type: string + example: OK '500': $ref: '#/responses/ServerError' tags: @@ -4531,13 +4535,6 @@ paths: description: Finds and unlocks any locked moves by an office user operationId: checkForLockedMovesAndUnlock definitions: - UnlockedMoves: - type: object - properties: - successMessage: - type: string - format: string - x-nullable: true ApplicationParameters: type: object properties: