From 5278ebbc0e8a1db59fdecf2314b1d4e61b445cd9 Mon Sep 17 00:00:00 2001 From: Jon Spight Date: Wed, 4 Dec 2024 19:47:24 +0000 Subject: [PATCH 01/51] Backend: Assigned User Cleanup --- pkg/handlers/ghcapi/payment_request.go | 13 +++++++++++++ .../move_task_order/move_task_order_updater.go | 3 +++ .../mto_service_item/mto_service_item_updater.go | 7 +++++++ 3 files changed, 23 insertions(+) diff --git a/pkg/handlers/ghcapi/payment_request.go b/pkg/handlers/ghcapi/payment_request.go index 622d38b1abc..58b5252db44 100644 --- a/pkg/handlers/ghcapi/payment_request.go +++ b/pkg/handlers/ghcapi/payment_request.go @@ -186,6 +186,7 @@ func (h UpdatePaymentRequestStatusHandler) Handle( &existingPaymentRequest, params.IfMatch, ) + if err != nil { switch err.(type) { case apperror.NotFoundError: @@ -219,6 +220,18 @@ func (h UpdatePaymentRequestStatusHandler) Handle( return paymentrequestop.NewGetPaymentRequestInternalServerError(), err } + //When approving a Payment request - remove the TIO assigned user + + move, err := models.FetchMove(appCtx.DB(), appCtx.Session(), existingPaymentRequest.MoveTaskOrderID) + if err != nil { + return paymentrequestop.NewUpdatePaymentRequestStatusInternalServerError(), err + } + move.TIOAssignedID = nil + verrs, err := models.SaveMoveDependencies(appCtx.DB(), move) + if err != nil || verrs.HasAny() { + return paymentrequestop.NewUpdatePaymentRequestStatusInternalServerError(), err + } + return paymentrequestop.NewUpdatePaymentRequestStatusOK().WithPayload(returnPayload), nil }) } diff --git a/pkg/services/move_task_order/move_task_order_updater.go b/pkg/services/move_task_order/move_task_order_updater.go index 2193251209f..7634e9135d6 100644 --- a/pkg/services/move_task_order/move_task_order_updater.go +++ b/pkg/services/move_task_order/move_task_order_updater.go @@ -56,6 +56,9 @@ func (o moveTaskOrderUpdater) UpdateStatusServiceCounselingCompleted(appCtx appc return err } + //When submiting a move for approval - remove the SC assigned user + move.SCAssignedID = nil + // Save the move. var verrs *validate.Errors verrs, err = appCtx.DB().ValidateAndSave(move) 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..f6c03985310 100644 --- a/pkg/services/mto_service_item/mto_service_item_updater.go +++ b/pkg/services/mto_service_item/mto_service_item_updater.go @@ -165,6 +165,13 @@ func (p *mtoServiceItemUpdater) approveOrRejectServiceItem( returnedServiceItem = *updatedServiceItem + //When updating a service item - remove the TOO assigned user + move.TOOAssignedID = nil + verrs, err := models.SaveMoveDependencies(appCtx.DB(), &move) + if err != nil || verrs.HasAny() { + return err + } + return nil }) From f0a199f8439ecb661e2e2a33d9e2e80fad4340b1 Mon Sep 17 00:00:00 2001 From: Jon Spight Date: Wed, 4 Dec 2024 19:55:23 +0000 Subject: [PATCH 02/51] Removed white space --- pkg/handlers/ghcapi/payment_request.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/pkg/handlers/ghcapi/payment_request.go b/pkg/handlers/ghcapi/payment_request.go index 58b5252db44..c8cc200062f 100644 --- a/pkg/handlers/ghcapi/payment_request.go +++ b/pkg/handlers/ghcapi/payment_request.go @@ -186,7 +186,6 @@ func (h UpdatePaymentRequestStatusHandler) Handle( &existingPaymentRequest, params.IfMatch, ) - if err != nil { switch err.(type) { case apperror.NotFoundError: @@ -221,7 +220,6 @@ func (h UpdatePaymentRequestStatusHandler) Handle( } //When approving a Payment request - remove the TIO assigned user - move, err := models.FetchMove(appCtx.DB(), appCtx.Session(), existingPaymentRequest.MoveTaskOrderID) if err != nil { return paymentrequestop.NewUpdatePaymentRequestStatusInternalServerError(), err From fd2351d95ddced24365df805e9a1f94ff9e0e185 Mon Sep 17 00:00:00 2001 From: Jon Spight Date: Fri, 6 Dec 2024 17:46:23 +0000 Subject: [PATCH 03/51] fixed placement --- .../mto_service_item/mto_service_item_updater.go | 14 +++++++------- 1 file changed, 7 insertions(+), 7 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 f6c03985310..04b389a5c24 100644 --- a/pkg/services/mto_service_item/mto_service_item_updater.go +++ b/pkg/services/mto_service_item/mto_service_item_updater.go @@ -159,19 +159,19 @@ func (p *mtoServiceItemUpdater) approveOrRejectServiceItem( } move := serviceItem.MoveTaskOrder - if _, err = p.moveRouter.ApproveOrRequestApproval(txnAppCtx, move); err != nil { + //When updating a service item - remove the TOO assigned user + move.TOOAssignedID = nil + _, err = models.SaveMoveDependencies(appCtx.DB(), &move) + if err != nil { return err } - returnedServiceItem = *updatedServiceItem - - //When updating a service item - remove the TOO assigned user - move.TOOAssignedID = nil - verrs, err := models.SaveMoveDependencies(appCtx.DB(), &move) - if err != nil || verrs.HasAny() { + if _, err = p.moveRouter.ApproveOrRequestApproval(txnAppCtx, move); err != nil { return err } + returnedServiceItem = *updatedServiceItem + return nil }) From 35b2cddbe2b5fe97884fcbfdff0e63ee550cd975 Mon Sep 17 00:00:00 2001 From: Jon Spight Date: Tue, 10 Dec 2024 22:30:18 +0000 Subject: [PATCH 04/51] TIO/TOO assigned user removal --- pkg/handlers/ghcapi/api.go | 1 + pkg/handlers/ghcapi/payment_request.go | 21 ++++++++++++++++--- .../move_task_order_updater.go | 3 +++ 3 files changed, 22 insertions(+), 3 deletions(-) diff --git a/pkg/handlers/ghcapi/api.go b/pkg/handlers/ghcapi/api.go index 6c6a50aa10e..44b5211f301 100644 --- a/pkg/handlers/ghcapi/api.go +++ b/pkg/handlers/ghcapi/api.go @@ -265,6 +265,7 @@ func NewGhcAPIHandler(handlerConfig handlers.HandlerConfig) *ghcops.MymoveAPI { HandlerConfig: handlerConfig, PaymentRequestStatusUpdater: paymentrequest.NewPaymentRequestStatusUpdater(queryBuilder), PaymentRequestFetcher: paymentrequest.NewPaymentRequestFetcher(), + PaymentRequestListFetcher: paymentrequest.NewPaymentRequestListFetcher(), } ghcAPI.PaymentServiceItemUpdatePaymentServiceItemStatusHandler = UpdatePaymentServiceItemStatusHandler{ diff --git a/pkg/handlers/ghcapi/payment_request.go b/pkg/handlers/ghcapi/payment_request.go index c8cc200062f..8aab5bcfbfe 100644 --- a/pkg/handlers/ghcapi/payment_request.go +++ b/pkg/handlers/ghcapi/payment_request.go @@ -114,6 +114,7 @@ type UpdatePaymentRequestStatusHandler struct { handlers.HandlerConfig services.PaymentRequestStatusUpdater services.PaymentRequestFetcher + services.PaymentRequestListFetcher } // Handle updates payment requests status @@ -224,12 +225,26 @@ func (h UpdatePaymentRequestStatusHandler) Handle( if err != nil { return paymentrequestop.NewUpdatePaymentRequestStatusInternalServerError(), err } - move.TIOAssignedID = nil - verrs, err := models.SaveMoveDependencies(appCtx.DB(), move) - if err != nil || verrs.HasAny() { + requestList, err := h.FetchPaymentRequestListByMove(appCtx, move.Locator) + if err != nil { return paymentrequestop.NewUpdatePaymentRequestStatusInternalServerError(), err } + openPr := false + for _, request := range *requestList { + if request.Status != "REVIEWED" { + openPr = true + } + } + + if !openPr { + move.TIOAssignedID = nil + verrs, err := models.SaveMoveDependencies(appCtx.DB(), move) + if err != nil || verrs.HasAny() { + return paymentrequestop.NewUpdatePaymentRequestStatusInternalServerError(), err + } + } + return paymentrequestop.NewUpdatePaymentRequestStatusOK().WithPayload(returnPayload), nil }) } diff --git a/pkg/services/move_task_order/move_task_order_updater.go b/pkg/services/move_task_order/move_task_order_updater.go index 7634e9135d6..27da4c3f005 100644 --- a/pkg/services/move_task_order/move_task_order_updater.go +++ b/pkg/services/move_task_order/move_task_order_updater.go @@ -210,6 +210,9 @@ func (o *moveTaskOrderUpdater) MakeAvailableToPrime(appCtx appcontext.AppContext return &models.Move{}, apperror.NewPreconditionFailedError(move.ID, query.StaleIdentifierError{StaleIdentifier: eTag}) } + //When approving a shipment - remove the assigned TOO user + move.TOOAssignedID = nil + // If the move is already been made available to prime, we will not need to approve and update the move, // just the provided service items. updateMove := false From 4acfe7e93ecfe5027b80114421ba71960112b738 Mon Sep 17 00:00:00 2001 From: Jon Spight Date: Wed, 11 Dec 2024 15:51:42 +0000 Subject: [PATCH 05/51] Payment Requset rejection - remove assigend user --- pkg/handlers/ghcapi/payment_request.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/handlers/ghcapi/payment_request.go b/pkg/handlers/ghcapi/payment_request.go index 8aab5bcfbfe..e5c13370636 100644 --- a/pkg/handlers/ghcapi/payment_request.go +++ b/pkg/handlers/ghcapi/payment_request.go @@ -232,7 +232,7 @@ func (h UpdatePaymentRequestStatusHandler) Handle( openPr := false for _, request := range *requestList { - if request.Status != "REVIEWED" { + if request.Status != "REVIEWED" && request.Status != "REVIEWED_AND_ALL_SERVICE_ITEMS_REJECTED" { openPr = true } } From b1b8320c8c733fb1b95c8a56bd04636935ec1290 Mon Sep 17 00:00:00 2001 From: Jon Spight Date: Wed, 11 Dec 2024 17:06:54 +0000 Subject: [PATCH 06/51] removed strings --- pkg/handlers/ghcapi/payment_request.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pkg/handlers/ghcapi/payment_request.go b/pkg/handlers/ghcapi/payment_request.go index e5c13370636..9996edc758c 100644 --- a/pkg/handlers/ghcapi/payment_request.go +++ b/pkg/handlers/ghcapi/payment_request.go @@ -232,7 +232,8 @@ func (h UpdatePaymentRequestStatusHandler) Handle( openPr := false for _, request := range *requestList { - if request.Status != "REVIEWED" && request.Status != "REVIEWED_AND_ALL_SERVICE_ITEMS_REJECTED" { + if request.Status != models.PaymentRequestStatusReviewed && + request.Status != models.PaymentRequestStatusReviewedAllRejected { openPr = true } } From 2af75325c471e75019624fe85844a39cd541d810 Mon Sep 17 00:00:00 2001 From: Jon Spight Date: Wed, 11 Dec 2024 18:44:54 +0000 Subject: [PATCH 07/51] added Test --- pkg/handlers/ghcapi/payment_request_test.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pkg/handlers/ghcapi/payment_request_test.go b/pkg/handlers/ghcapi/payment_request_test.go index 3d2f116accc..c0af9b7aba9 100644 --- a/pkg/handlers/ghcapi/payment_request_test.go +++ b/pkg/handlers/ghcapi/payment_request_test.go @@ -272,6 +272,7 @@ func (suite *HandlerSuite) TestUpdatePaymentRequestStatusHandler() { HandlerConfig: suite.HandlerConfig(), PaymentRequestStatusUpdater: statusUpdater, PaymentRequestFetcher: paymentRequestFetcher, + PaymentRequestListFetcher: paymentrequest.NewPaymentRequestListFetcher(), } // Validate incoming payload @@ -310,6 +311,7 @@ func (suite *HandlerSuite) TestUpdatePaymentRequestStatusHandler() { HandlerConfig: suite.HandlerConfig(), PaymentRequestStatusUpdater: statusUpdater, PaymentRequestFetcher: paymentRequestFetcher, + PaymentRequestListFetcher: paymentrequest.NewPaymentRequestListFetcher(), } // Validate incoming payload @@ -407,6 +409,7 @@ func (suite *HandlerSuite) TestUpdatePaymentRequestStatusHandler() { HandlerConfig: suite.HandlerConfig(), PaymentRequestStatusUpdater: paymentRequestStatusUpdater, PaymentRequestFetcher: paymentRequestFetcher, + PaymentRequestListFetcher: paymentrequest.NewPaymentRequestListFetcher(), } // Validate incoming payload From a30a370f9e21c1b53a896de873a0bd6ed5b07489 Mon Sep 17 00:00:00 2001 From: Jon Spight Date: Thu, 12 Dec 2024 20:09:10 +0000 Subject: [PATCH 08/51] Added test for test coverage --- .../payloads/model_to_payload_test.go | 44 ++++++++++++++++++- 1 file changed, 42 insertions(+), 2 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 c779256f33e..f3b40c459cd 100644 --- a/pkg/handlers/ghcapi/internal/payloads/model_to_payload_test.go +++ b/pkg/handlers/ghcapi/internal/payloads/model_to_payload_test.go @@ -13,6 +13,7 @@ import ( "github.com/transcom/mymove/pkg/models" "github.com/transcom/mymove/pkg/models/roles" "github.com/transcom/mymove/pkg/storage/test" + "github.com/transcom/mymove/pkg/testdatagen" ) func TestOrder(_ *testing.T) { @@ -479,6 +480,7 @@ func (suite *PayloadsSuite) TestSearchMoves() { appCtx := suite.AppContextForTest() marines := models.AffiliationMARINES + spaceForce := models.AffiliationSPACEFORCE moveUSMC := factory.BuildMove(suite.DB(), []factory.Customization{ { Model: models.ServiceMember{ @@ -486,14 +488,52 @@ func (suite *PayloadsSuite) TestSearchMoves() { }, }, }, nil) - + moveSF := factory.BuildMove(suite.DB(), []factory.Customization{ + { + Model: models.ServiceMember{ + Affiliation: &spaceForce, + }, + }, + }, nil) + scheduledPickupDate := time.Date(testdatagen.GHCTestYear, time.September, 20, 0, 0, 0, 0, time.UTC) + scheduledDeliveryDate := time.Date(testdatagen.GHCTestYear, time.September, 20, 0, 0, 0, 0, time.UTC) + sitAllowance := int(90) + storageFacility := factory.BuildStorageFacility(suite.DB(), nil, nil) + mtoShipment := factory.BuildMTOShipment(suite.DB(), []factory.Customization{ + { + Model: moveSF, + LinkOnly: true, + }, + { + Model: models.MTOShipment{ + Status: models.MTOShipmentStatusApproved, + ShipmentType: models.MTOShipmentTypeHHGIntoNTSDom, + CounselorRemarks: handlers.FmtString("counselor remark"), + SITDaysAllowance: &sitAllowance, + ScheduledPickupDate: &scheduledPickupDate, + ScheduledDeliveryDate: &scheduledDeliveryDate, + }, + }, + { + Model: storageFacility, + LinkOnly: true, + }, + }, nil) + moveSF.MTOShipments = append(moveSF.MTOShipments, mtoShipment) moves := models.Moves{moveUSMC} - suite.Run("Success - Returns a ghcmessages Upload payload from Upload Struct", func() { + moveSpaceForce := models.Moves{moveSF} + suite.Run("Success - Returns a ghcmessages Upload payload from Upload Struct Marine move with no shipments", func() { payload := SearchMoves(appCtx, moves) suite.IsType(payload, &ghcmessages.SearchMoves{}) suite.NotNil(payload) }) + suite.Run("Success - Returns a ghcmessages Upload payload from Upload Struct Non-Marine move, a shipment, and delivery/pickup time. ", func() { + payload := SearchMoves(appCtx, moveSpaceForce) + suite.IsType(payload, &ghcmessages.SearchMoves{}) + suite.NotNil(payload) + suite.NotNil(mtoShipment) + }) } func (suite *PayloadsSuite) TestMarketCode() { From 09fa6b3bb7e9ddb47f4aa55b6b50ab46200d83c0 Mon Sep 17 00:00:00 2001 From: Jon Spight Date: Thu, 12 Dec 2024 21:16:31 +0000 Subject: [PATCH 09/51] deeper test --- .../payloads/model_to_payload_test.go | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) 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 f3b40c459cd..eae6176102d 100644 --- a/pkg/handlers/ghcapi/internal/payloads/model_to_payload_test.go +++ b/pkg/handlers/ghcapi/internal/payloads/model_to_payload_test.go @@ -481,6 +481,7 @@ func (suite *PayloadsSuite) TestSearchMoves() { marines := models.AffiliationMARINES spaceForce := models.AffiliationSPACEFORCE + army := models.AffiliationARMY moveUSMC := factory.BuildMove(suite.DB(), []factory.Customization{ { Model: models.ServiceMember{ @@ -495,9 +496,18 @@ func (suite *PayloadsSuite) TestSearchMoves() { }, }, }, nil) + moveA := factory.BuildMove(suite.DB(), []factory.Customization{ + { + Model: models.ServiceMember{ + Affiliation: &army, + }, + }, + }, nil) + moveUSMC.Status = models.MoveStatusNeedsServiceCounseling scheduledPickupDate := time.Date(testdatagen.GHCTestYear, time.September, 20, 0, 0, 0, 0, time.UTC) scheduledDeliveryDate := time.Date(testdatagen.GHCTestYear, time.September, 20, 0, 0, 0, 0, time.UTC) sitAllowance := int(90) + gbloc := "LKNQ" storageFacility := factory.BuildStorageFacility(suite.DB(), nil, nil) mtoShipment := factory.BuildMTOShipment(suite.DB(), []factory.Customization{ { @@ -519,9 +529,13 @@ func (suite *PayloadsSuite) TestSearchMoves() { LinkOnly: true, }, }, nil) + moveSF.MTOShipments = append(moveSF.MTOShipments, mtoShipment) + moveSF.ShipmentGBLOC = append(moveSF.ShipmentGBLOC, models.MoveToGBLOC{GBLOC: &gbloc}) + moves := models.Moves{moveUSMC} moveSpaceForce := models.Moves{moveSF} + moveArmy := models.Moves{moveA} suite.Run("Success - Returns a ghcmessages Upload payload from Upload Struct Marine move with no shipments", func() { payload := SearchMoves(appCtx, moves) @@ -533,6 +547,14 @@ func (suite *PayloadsSuite) TestSearchMoves() { suite.IsType(payload, &ghcmessages.SearchMoves{}) suite.NotNil(payload) suite.NotNil(mtoShipment) + + suite.NotNil(moveA) + }) + suite.Run("Success - Returns a ghcmessages Upload payload from Upload Struct Army move, with no shipments. ", func() { + payload := SearchMoves(appCtx, moveArmy) + suite.IsType(payload, &ghcmessages.SearchMoves{}) + suite.NotNil(payload) + }) } From 4622222d2253fa55b2e17068fbb3e1ddfaf0bf32 Mon Sep 17 00:00:00 2001 From: Jon Spight Date: Thu, 12 Dec 2024 23:42:53 +0000 Subject: [PATCH 10/51] Another backend test case --- .../primeapi/payloads/model_to_payload_test.go | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/pkg/handlers/primeapi/payloads/model_to_payload_test.go b/pkg/handlers/primeapi/payloads/model_to_payload_test.go index 5782c851928..b2f50c9c57b 100644 --- a/pkg/handlers/primeapi/payloads/model_to_payload_test.go +++ b/pkg/handlers/primeapi/payloads/model_to_payload_test.go @@ -446,6 +446,21 @@ func (suite *PayloadsSuite) TestInternalServerError() { suite.Equal(traceID.String(), detailError.Instance.String()) } +func (suite *PayloadsSuite) TestNotImplementedError() { + traceID, _ := uuid.NewV4() + detail := "Err" + + noDetailError := NotImplementedError(nil, traceID) + suite.Equal(handlers.NotImplementedErrMessage, *noDetailError.Title) + // suite.Equal(handlers.NotImplementedErrMessage, *noDetailError.Detail) + suite.Equal(traceID.String(), noDetailError.Instance.String()) + + detailError := NotImplementedError(&detail, traceID) + suite.Equal(handlers.NotImplementedErrMessage, *detailError.Title) + suite.Equal(detail, *detailError.Detail) + suite.Equal(traceID.String(), detailError.Instance.String()) +} + func (suite *PayloadsSuite) TestGetDimension() { dimensionType := models.DimensionTypeItem dimensions := models.MTOServiceItemDimensions{ From def3c3e3eab711b569ab70efd9579d2bb20806f1 Mon Sep 17 00:00:00 2001 From: Jon Spight Date: Fri, 13 Dec 2024 16:03:52 +0000 Subject: [PATCH 11/51] Added Test cases --- .../payloads/model_to_payload_test.go | 79 ++++++++++++++++++- 1 file changed, 77 insertions(+), 2 deletions(-) diff --git a/pkg/handlers/primeapi/payloads/model_to_payload_test.go b/pkg/handlers/primeapi/payloads/model_to_payload_test.go index b2f50c9c57b..563c6a7f72c 100644 --- a/pkg/handlers/primeapi/payloads/model_to_payload_test.go +++ b/pkg/handlers/primeapi/payloads/model_to_payload_test.go @@ -610,8 +610,11 @@ func (suite *PayloadsSuite) TestShipmentAddressUpdate() { suite.Equal(strfmt.UUID(shipmentAddressUpdate.ID.String()), result.ID) } -func (suite *PayloadsSuite) TestMTOServiceItemDCRT() { +func (suite *PayloadsSuite) TestMTOServiceItemDCRTandDOFSITandDDFSIT() { reServiceCode := models.ReServiceCodeDCRT + reServiceCodeSIT := models.ReServiceCodeDOFSIT + reServiceCodeDDFSIT := models.ReServiceCodeDDFSIT + reason := "reason" dateOfContact1 := time.Now() timeMilitary1 := "1500Z" @@ -639,11 +642,83 @@ func (suite *PayloadsSuite) TestMTOServiceItemDCRT() { }, }, } + year, month, day := time.Now().Date() + aWeekAgo := time.Date(year, month, day-7, 0, 0, 0, 0, time.UTC) + departureDate := aWeekAgo.Add(time.Hour * 24 * 30) + actualPickupAddress := factory.BuildAddress(nil, nil, []factory.Trait{factory.GetTraitAddress2}) + requestApprovalRequestedStatus := false + mtoServiceItemDOFSIT := &models.MTOServiceItem{ + ID: uuid.Must(uuid.NewV4()), + ReService: models.ReService{Code: reServiceCodeSIT}, + Reason: &reason, + SITDepartureDate: &departureDate, + SITEntryDate: &aWeekAgo, + SITPostalCode: models.StringPointer("90210"), + SITOriginHHGActualAddress: &actualPickupAddress, + SITCustomerContacted: &aWeekAgo, + SITRequestedDelivery: &aWeekAgo, + SITOriginHHGOriginalAddress: &models.Address{ + StreetAddress1: "dummyStreet2", + City: "dummyCity2", + State: "FL", + PostalCode: "55555", + }, + RequestedApprovalsRequestedStatus: &requestApprovalRequestedStatus, + CustomerContacts: models.MTOServiceItemCustomerContacts{ + models.MTOServiceItemCustomerContact{ + DateOfContact: dateOfContact1, + TimeMilitary: timeMilitary1, + FirstAvailableDeliveryDate: firstAvailableDeliveryDate1, + Type: models.CustomerContactTypeFirst, + }, + models.MTOServiceItemCustomerContact{ + DateOfContact: dateOfContact2, + TimeMilitary: timeMilitary2, + FirstAvailableDeliveryDate: firstAvailableDeliveryDate2, + Type: models.CustomerContactTypeSecond, + }, + }, + } + mtoServiceItemDDFSIT := &models.MTOServiceItem{ + ID: uuid.Must(uuid.NewV4()), + ReService: models.ReService{Code: reServiceCodeDDFSIT}, + Reason: &reason, + SITDepartureDate: &departureDate, + SITEntryDate: &aWeekAgo, + SITPostalCode: models.StringPointer("90210"), + SITOriginHHGActualAddress: &actualPickupAddress, + SITCustomerContacted: &aWeekAgo, + SITRequestedDelivery: &aWeekAgo, + SITOriginHHGOriginalAddress: &models.Address{ + StreetAddress1: "dummyStreet2", + City: "dummyCity2", + State: "FL", + PostalCode: "55555", + }, + RequestedApprovalsRequestedStatus: &requestApprovalRequestedStatus, + CustomerContacts: models.MTOServiceItemCustomerContacts{ + models.MTOServiceItemCustomerContact{ + DateOfContact: dateOfContact1, + TimeMilitary: timeMilitary1, + FirstAvailableDeliveryDate: firstAvailableDeliveryDate1, + Type: models.CustomerContactTypeFirst, + }, + models.MTOServiceItemCustomerContact{ + DateOfContact: dateOfContact2, + TimeMilitary: timeMilitary2, + FirstAvailableDeliveryDate: firstAvailableDeliveryDate2, + Type: models.CustomerContactTypeSecond, + }, + }, + } resultDCRT := MTOServiceItem(mtoServiceItemDCRT) + resultDOFSIT := MTOServiceItem(mtoServiceItemDOFSIT) + resultDDFSIT := MTOServiceItem(mtoServiceItemDDFSIT) suite.NotNil(resultDCRT) - + suite.NotNil(resultDOFSIT) + suite.NotNil(resultDDFSIT) _, ok := resultDCRT.(*primemessages.MTOServiceItemDomesticCrating) suite.True(ok) From 27ed6a4b0467403beb3ecf988367c0db30c5d900 Mon Sep 17 00:00:00 2001 From: Jon Spight Date: Fri, 13 Dec 2024 19:39:32 +0000 Subject: [PATCH 12/51] added test case --- .../payloads/model_to_payload_test.go | 74 +++++++++++++++++++ 1 file changed, 74 insertions(+) diff --git a/pkg/handlers/primeapi/payloads/model_to_payload_test.go b/pkg/handlers/primeapi/payloads/model_to_payload_test.go index 563c6a7f72c..a6bc9ea0945 100644 --- a/pkg/handlers/primeapi/payloads/model_to_payload_test.go +++ b/pkg/handlers/primeapi/payloads/model_to_payload_test.go @@ -517,6 +517,80 @@ func (suite *PayloadsSuite) TestPaymentRequests() { suite.Equal(len(paymentRequests), len(*result)) } +func (suite *PayloadsSuite) TestMTOShipmentWithoutServiceItems() { + // Create the addresses + pickupAddress := factory.BuildAddress(suite.DB(), nil, nil) + destinationAddress := factory.BuildAddress(suite.DB(), nil, nil) + destinationType := models.DestinationTypeHomeOfRecord + secondaryPickupAddress := factory.BuildAddress(suite.DB(), nil, []factory.Trait{factory.GetTraitAddress2}) + secondaryDeliveryAddress := factory.BuildAddress(suite.DB(), nil, []factory.Trait{factory.GetTraitAddress4}) + dlhTestWeight := unit.Pound(4000) + + // Create the MTOShipment with populated PickupAddress and DestinationAddress + mtoShipment := factory.BuildMTOShipment(suite.DB(), []factory.Customization{ + { + Model: models.MTOShipment{ + PickupAddressID: &pickupAddress.ID, + DestinationAddressID: &destinationAddress.ID, + DestinationType: &destinationType, + SecondaryPickupAddressID: &secondaryPickupAddress.ID, + SecondaryDeliveryAddressID: &secondaryDeliveryAddress.ID, + PrimeEstimatedWeight: models.PoundPointer(unit.Pound(980)), + PrimeActualWeight: &dlhTestWeight, + NTSRecordedWeight: models.PoundPointer(unit.Pound(249)), + }, + }, + }, nil) + value := MTOShipmentWithoutServiceItems(&mtoShipment) + suite.NotNil(value) +} + +func (suite *PayloadsSuite) TestMTOShipmentsWithoutServiceItems() { + // Create the addresses + pickupAddress := factory.BuildAddress(suite.DB(), nil, nil) + destinationAddress := factory.BuildAddress(suite.DB(), nil, nil) + destinationType := models.DestinationTypeHomeOfRecord + secondaryPickupAddress := factory.BuildAddress(suite.DB(), nil, []factory.Trait{factory.GetTraitAddress2}) + secondaryDeliveryAddress := factory.BuildAddress(suite.DB(), nil, []factory.Trait{factory.GetTraitAddress4}) + dlhTestWeight := unit.Pound(4000) + + // Create the MTOShipment + mtoShipment := factory.BuildMTOShipment(suite.DB(), []factory.Customization{ + { + Model: models.MTOShipment{ + PickupAddressID: &pickupAddress.ID, + DestinationAddressID: &destinationAddress.ID, + DestinationType: &destinationType, + SecondaryPickupAddressID: &secondaryPickupAddress.ID, + SecondaryDeliveryAddressID: &secondaryDeliveryAddress.ID, + PrimeEstimatedWeight: models.PoundPointer(unit.Pound(980)), + PrimeActualWeight: &dlhTestWeight, + NTSRecordedWeight: models.PoundPointer(unit.Pound(249)), + }, + }, + }, nil) + + // Create the MTOShipment + mtoShipmentTwo := factory.BuildMTOShipment(suite.DB(), []factory.Customization{ + { + Model: models.MTOShipment{ + PickupAddressID: &pickupAddress.ID, + DestinationAddressID: &destinationAddress.ID, + DestinationType: &destinationType, + SecondaryPickupAddressID: &secondaryPickupAddress.ID, + SecondaryDeliveryAddressID: &secondaryDeliveryAddress.ID, + PrimeEstimatedWeight: models.PoundPointer(unit.Pound(980)), + PrimeActualWeight: &dlhTestWeight, + NTSRecordedWeight: models.PoundPointer(unit.Pound(249)), + }, + }, + }, nil) + shipments := models.MTOShipments{} + shipments = append(shipments, mtoShipmentTwo, mtoShipment) + value := MTOShipmentsWithoutServiceItems(&shipments) + suite.NotNil(value) +} + func (suite *PayloadsSuite) TestPaymentServiceItem() { paymentServiceItem := models.PaymentServiceItem{ ID: uuid.Must(uuid.NewV4()), From 0f572e4c6e1a60fb8e0b7e862e50bb838e1301a9 Mon Sep 17 00:00:00 2001 From: Jon Spight Date: Fri, 13 Dec 2024 21:44:29 +0000 Subject: [PATCH 13/51] Added Test coverage --- .../payloads/model_to_payload_test.go | 68 +++++++++++++++++++ 1 file changed, 68 insertions(+) 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 13a3be15bb4..a85c93082e8 100644 --- a/pkg/handlers/ghcapi/internal/payloads/model_to_payload_test.go +++ b/pkg/handlers/ghcapi/internal/payloads/model_to_payload_test.go @@ -552,7 +552,75 @@ func (suite *PayloadsSuite) TestCreateCustomer() { suite.IsType(returnedShipmentAddressUpdate, &ghcmessages.CreatedCustomer{}) }) } +func (suite *PayloadsSuite) TestTransportationOffice() { + transportationOffice := factory.BuildTransportationOffice(suite.DB(), []factory.Customization{ + { + Model: models.TransportationOffice{ + ID: uuid.Must(uuid.NewV4()), + }, + }}, nil) + value := TransportationOffice(&transportationOffice) + suite.NotNil(value) +} +func (suite *PayloadsSuite) TestTransportationOffices() { + transportationOffice := factory.BuildTransportationOffice(suite.DB(), []factory.Customization{ + { + Model: models.TransportationOffice{ + ID: uuid.Must(uuid.NewV4()), + }, + }}, nil) + transportationOfficeTwo := factory.BuildTransportationOffice(suite.DB(), []factory.Customization{ + { + Model: models.TransportationOffice{ + ID: uuid.Must(uuid.NewV4()), + }, + }}, nil) + list := models.TransportationOffices{} + list = append(list, transportationOffice, transportationOfficeTwo) + value := TransportationOffices(list) + suite.NotNil(value) +} +func (suite *PayloadsSuite) TestListMove() { + + marines := models.AffiliationMARINES + value := ListMove(nil) + suite.Nil(value) + moveUSMC := factory.BuildMove(suite.DB(), []factory.Customization{ + { + Model: models.ServiceMember{ + Affiliation: &marines, + }, + }, + }, nil) + + value = ListMove(&moveUSMC) + suite.NotNil(value) +} + +func (suite *PayloadsSuite) TestListMoves() { + list := models.Moves{} + + marines := models.AffiliationMARINES + spaceForce := models.AffiliationSPACEFORCE + moveUSMC := factory.BuildMove(suite.DB(), []factory.Customization{ + { + Model: models.ServiceMember{ + Affiliation: &marines, + }, + }, + }, nil) + moveSF := factory.BuildMove(suite.DB(), []factory.Customization{ + { + Model: models.ServiceMember{ + Affiliation: &spaceForce, + }, + }, + }, nil) + list = append(list, moveUSMC, moveSF) + value := ListMoves(&list) + suite.NotNil(value) +} func (suite *PayloadsSuite) TestSearchMoves() { appCtx := suite.AppContextForTest() From 88a13769158949c3ba68dda85b3ff133ef7e9080 Mon Sep 17 00:00:00 2001 From: Jon Spight Date: Fri, 13 Dec 2024 23:05:59 +0000 Subject: [PATCH 14/51] Added Test Coverage --- .../payloads/model_to_payload_test.go | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) 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 a85c93082e8..33a5b7114a8 100644 --- a/pkg/handlers/ghcapi/internal/payloads/model_to_payload_test.go +++ b/pkg/handlers/ghcapi/internal/payloads/model_to_payload_test.go @@ -21,6 +21,22 @@ func TestOrder(_ *testing.T) { Order(order) } +func (suite *PayloadsSuite) TestOrderWithMove() { + move := factory.BuildMove(suite.DB(), nil, nil) + moves := models.Moves{} + moves = append(moves, move) + order := factory.BuildOrder(nil, []factory.Customization{ + { + Model: models.Order{ + ID: uuid.Must(uuid.NewV4()), + HasDependents: *models.BoolPointer(true), + Moves: moves, + }, + }, + }, nil) + Order(&order) +} + // TestMove makes sure zero values/optional fields are handled func TestMove(t *testing.T) { _, err := Move(&models.Move{}, &test.FakeS3Storage{}) @@ -552,6 +568,13 @@ func (suite *PayloadsSuite) TestCreateCustomer() { suite.IsType(returnedShipmentAddressUpdate, &ghcmessages.CreatedCustomer{}) }) } + +func (suite *PayloadsSuite) TestMoveTaskOrder() { + move := factory.BuildMove(suite.DB(), nil, nil) + value := MoveTaskOrder(&move) + suite.NotNil(value) +} + func (suite *PayloadsSuite) TestTransportationOffice() { transportationOffice := factory.BuildTransportationOffice(suite.DB(), []factory.Customization{ { From 04bf15789c55457213492fdcb7fa271dc06c05db Mon Sep 17 00:00:00 2001 From: Jon Spight Date: Fri, 13 Dec 2024 23:45:15 +0000 Subject: [PATCH 15/51] Added test Coverage --- .../payloads/model_to_payload_test.go | 69 +++++++++++++++++++ 1 file changed, 69 insertions(+) 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 33a5b7114a8..e02267a4760 100644 --- a/pkg/handlers/ghcapi/internal/payloads/model_to_payload_test.go +++ b/pkg/handlers/ghcapi/internal/payloads/model_to_payload_test.go @@ -14,6 +14,7 @@ import ( "github.com/transcom/mymove/pkg/models/roles" "github.com/transcom/mymove/pkg/storage/test" "github.com/transcom/mymove/pkg/testdatagen" + "github.com/transcom/mymove/pkg/unit" ) func TestOrder(_ *testing.T) { @@ -37,6 +38,74 @@ func (suite *PayloadsSuite) TestOrderWithMove() { Order(&order) } +func (suite *PayloadsSuite) TestBoatShipment() { + boat := factory.BuildBoatShipment(suite.DB(), nil, nil) + value := BoatShipment(nil, &boat) + suite.NotNil(value) + +} + +func (suite *PayloadsSuite) TestMobileHomeShipment() { + mobileHome := factory.BuildMobileHomeShipment(suite.DB(), nil, nil) + value := MobileHomeShipment(nil, &mobileHome) + suite.NotNil(value) +} + +func (suite *PayloadsSuite) TestMovingExpense() { + contractExpense := models.MovingExpenseReceiptTypeContractedExpense + weightStored := 2000 + sitLocation := models.SITLocationTypeDestination + sitReimburseableAmount := 500 + + movingExpense := models.MovingExpense{ + PPMShipmentID: uuid.Must(uuid.NewV4()), + DocumentID: uuid.Must(uuid.NewV4()), + MovingExpenseType: &contractExpense, + Reason: models.StringPointer("no good"), + SITStartDate: models.TimePointer(time.Now()), + SITEndDate: models.TimePointer(time.Now()), + WeightStored: (*unit.Pound)(&weightStored), + SITLocation: &sitLocation, + SITReimburseableAmount: (*unit.Cents)(&sitReimburseableAmount), + } + value := MovingExpense(nil, &movingExpense) + suite.NotNil(value) +} + +func (suite *PayloadsSuite) TestMovingExpenses() { + contractExpense := models.MovingExpenseReceiptTypeContractedExpense + weightStored := 2000 + sitLocation := models.SITLocationTypeDestination + sitReimburseableAmount := 500 + movingExpenses := models.MovingExpenses{} + + movingExpense := models.MovingExpense{ + PPMShipmentID: uuid.Must(uuid.NewV4()), + DocumentID: uuid.Must(uuid.NewV4()), + MovingExpenseType: &contractExpense, + Reason: models.StringPointer("no good"), + SITStartDate: models.TimePointer(time.Now()), + SITEndDate: models.TimePointer(time.Now()), + WeightStored: (*unit.Pound)(&weightStored), + SITLocation: &sitLocation, + SITReimburseableAmount: (*unit.Cents)(&sitReimburseableAmount), + } + movingExpenseTwo := models.MovingExpense{ + PPMShipmentID: uuid.Must(uuid.NewV4()), + DocumentID: uuid.Must(uuid.NewV4()), + MovingExpenseType: &contractExpense, + Reason: models.StringPointer("no good"), + SITStartDate: models.TimePointer(time.Now()), + SITEndDate: models.TimePointer(time.Now()), + WeightStored: (*unit.Pound)(&weightStored), + SITLocation: &sitLocation, + SITReimburseableAmount: (*unit.Cents)(&sitReimburseableAmount), + } + movingExpenses = append(movingExpenses, movingExpense, movingExpenseTwo) + value := MovingExpenses(nil, movingExpenses) + suite.NotNil(value) +} + // TestMove makes sure zero values/optional fields are handled func TestMove(t *testing.T) { _, err := Move(&models.Move{}, &test.FakeS3Storage{}) From 0b862c8518c7d51c66530b61baa2bde51ddbeec0 Mon Sep 17 00:00:00 2001 From: loganwc Date: Mon, 16 Dec 2024 17:08:23 +0000 Subject: [PATCH 16/51] mobile home and boat shipments now have 2nd and 3rd address on create for prime sim --- .../Shipment/PrimeUIShipmentCreate.jsx | 70 +++++++++++++++++++ .../Shipment/PrimeUIShipmentCreate.test.jsx | 41 +++++++++++ 2 files changed, 111 insertions(+) diff --git a/src/pages/PrimeUI/Shipment/PrimeUIShipmentCreate.jsx b/src/pages/PrimeUI/Shipment/PrimeUIShipmentCreate.jsx index 36139c32e23..c265b67e98c 100644 --- a/src/pages/PrimeUI/Shipment/PrimeUIShipmentCreate.jsx +++ b/src/pages/PrimeUI/Shipment/PrimeUIShipmentCreate.jsx @@ -177,6 +177,10 @@ const PrimeUIShipmentCreate = ({ setFlashMessage }) => { destinationAddress, diversion, divertedFromShipmentId, + hasSecondaryPickupAddress, + hasSecondaryDestinationAddress, + hasTertiaryPickupAddress, + hasTertiaryDestinationAddress, boatShipment: { year, make, @@ -192,6 +196,23 @@ const PrimeUIShipmentCreate = ({ setFlashMessage }) => { }, } = values; + let { tertiaryPickupAddress, tertiaryDestinationAddress, secondaryPickupAddress, secondaryDestinationAddress } = + values; + if (hasSecondaryPickupAddress !== 'true') { + secondaryPickupAddress = {}; + tertiaryPickupAddress = {}; + } + if (hasTertiaryPickupAddress !== 'true') { + tertiaryPickupAddress = {}; + } + if (hasSecondaryDestinationAddress !== 'true') { + secondaryDestinationAddress = {}; + tertiaryDestinationAddress = {}; + } + if (hasTertiaryDestinationAddress !== 'true') { + tertiaryDestinationAddress = {}; + } + // Sum the feet and inches fields into only inches for backend/db const totalLengthInInches = parseInt(lengthInFeet, 10) * 12 + parseInt(lengthInInches, 10); const totalWidthInInches = parseInt(widthInFeet, 10) * 12 + parseInt(widthInInches, 10); @@ -219,6 +240,20 @@ const PrimeUIShipmentCreate = ({ setFlashMessage }) => { destinationAddress: isEmpty(destinationAddress) ? null : formatAddressForPrimeAPI(destinationAddress), diversion: diversion || null, divertedFromShipmentId: divertedFromShipmentId || null, + hasSecondaryPickupAddress: hasSecondaryPickupAddress === 'true', + hasSecondaryDestinationAddress: hasSecondaryDestinationAddress === 'true', + hasTertiaryPickupAddress: hasTertiaryPickupAddress === 'true', + hasTertiaryDestinationAddress: hasTertiaryDestinationAddress === 'true', + secondaryPickupAddress: isEmpty(secondaryPickupAddress) + ? null + : formatAddressForPrimeAPI(secondaryPickupAddress), + secondaryDestinationAddress: isEmpty(secondaryDestinationAddress) + ? null + : formatAddressForPrimeAPI(secondaryDestinationAddress), + tertiaryPickupAddress: isEmpty(tertiaryPickupAddress) ? null : formatAddressForPrimeAPI(tertiaryPickupAddress), + tertiaryDestinationAddress: isEmpty(tertiaryDestinationAddress) + ? null + : formatAddressForPrimeAPI(tertiaryDestinationAddress), }; } else if (isMobileHome) { const { @@ -229,6 +264,10 @@ const PrimeUIShipmentCreate = ({ setFlashMessage }) => { destinationAddress, diversion, divertedFromShipmentId, + hasSecondaryPickupAddress, + hasSecondaryDestinationAddress, + hasTertiaryPickupAddress, + hasTertiaryDestinationAddress, mobileHomeShipment: { year, make, @@ -242,6 +281,23 @@ const PrimeUIShipmentCreate = ({ setFlashMessage }) => { }, } = values; + let { tertiaryPickupAddress, tertiaryDestinationAddress, secondaryPickupAddress, secondaryDestinationAddress } = + values; + if (hasSecondaryPickupAddress !== 'true') { + secondaryPickupAddress = {}; + tertiaryPickupAddress = {}; + } + if (hasTertiaryPickupAddress !== 'true') { + tertiaryPickupAddress = {}; + } + if (hasSecondaryDestinationAddress !== 'true') { + secondaryDestinationAddress = {}; + tertiaryDestinationAddress = {}; + } + if (hasTertiaryDestinationAddress !== 'true') { + tertiaryDestinationAddress = {}; + } + // Sum the feet and inches fields into only inches for backend/db const totalLengthInInches = parseInt(lengthInFeet, 10) * 12 + parseInt(lengthInInches, 10); const totalWidthInInches = parseInt(widthInFeet, 10) * 12 + parseInt(widthInInches, 10); @@ -265,6 +321,20 @@ const PrimeUIShipmentCreate = ({ setFlashMessage }) => { destinationAddress: isEmpty(destinationAddress) ? null : formatAddressForPrimeAPI(destinationAddress), diversion: diversion || null, divertedFromShipmentId: divertedFromShipmentId || null, + hasSecondaryPickupAddress: hasSecondaryPickupAddress === 'true', + hasSecondaryDestinationAddress: hasSecondaryDestinationAddress === 'true', + hasTertiaryPickupAddress: hasTertiaryPickupAddress === 'true', + hasTertiaryDestinationAddress: hasTertiaryDestinationAddress === 'true', + secondaryPickupAddress: isEmpty(secondaryPickupAddress) + ? null + : formatAddressForPrimeAPI(secondaryPickupAddress), + secondaryDestinationAddress: isEmpty(secondaryDestinationAddress) + ? null + : formatAddressForPrimeAPI(secondaryDestinationAddress), + tertiaryPickupAddress: isEmpty(tertiaryPickupAddress) ? null : formatAddressForPrimeAPI(tertiaryPickupAddress), + tertiaryDestinationAddress: isEmpty(tertiaryDestinationAddress) + ? null + : formatAddressForPrimeAPI(tertiaryDestinationAddress), }; } else { const { diff --git a/src/pages/PrimeUI/Shipment/PrimeUIShipmentCreate.test.jsx b/src/pages/PrimeUI/Shipment/PrimeUIShipmentCreate.test.jsx index eec912b1793..ffa73be8202 100644 --- a/src/pages/PrimeUI/Shipment/PrimeUIShipmentCreate.test.jsx +++ b/src/pages/PrimeUI/Shipment/PrimeUIShipmentCreate.test.jsx @@ -171,3 +171,44 @@ describe('Create PPM', () => { }); }); }); + +describe('Create Mobile Home', () => { + it('test with 2nd addresses', async () => { + createPrimeMTOShipmentV3.mockReturnValue({}); + + render(mockedComponent); + + waitFor(async () => { + await userEvent.selectOptions(screen.getByLabelText('Shipment type'), 'MOBILE_HOME'); + + // Start controlled test case to verify everything is working. + let input = await document.querySelector('input[name="pickupAddress.streetAddress1"]'); + expect(input).toBeInTheDocument(); + // enter required street 1 for pickup + await userEvent.type(input, '123 Street'); + + const secondAddressToggle = document.querySelector('[data-testid="has-secondary-pickup"]'); + expect(secondAddressToggle).toBeInTheDocument(); + await userEvent.click(secondAddressToggle); + + input = await document.querySelector('input[name="pickupAddress.streetAddress2"]'); + expect(input).toBeInTheDocument(); + // enter required street 1 for pickup 2 + await userEvent.type(input, '123 Street'); + + input = await document.querySelector('input[name="destinationAddress.streetAddress1"]'); + expect(input).toBeInTheDocument(); + // enter something + await userEvent.type(input, '123 Street'); + + const saveButton = await screen.getByRole('button', { name: 'Save' }); + + expect(saveButton).not.toBeDisabled(); + await userEvent.click(saveButton); + + await waitFor(() => { + expect(mockNavigate).toHaveBeenCalledWith(moveDetailsURL); + }); + }); + }); +}); From b7896a94b38e41f5c734fd64cb7b9c9afbe77540 Mon Sep 17 00:00:00 2001 From: Jon Spight Date: Tue, 17 Dec 2024 00:36:09 +0000 Subject: [PATCH 17/51] Added TIO removal test case --- pkg/factory/move_factory.go | 13 +++- pkg/factory/shared.go | 8 ++ pkg/handlers/ghcapi/api.go | 9 ++- pkg/handlers/ghcapi/payment_request.go | 9 ++- pkg/handlers/ghcapi/payment_request_test.go | 81 +++++++++++++++++---- 5 files changed, 96 insertions(+), 24 deletions(-) diff --git a/pkg/factory/move_factory.go b/pkg/factory/move_factory.go index e2192ae93f0..a3659d3bae2 100644 --- a/pkg/factory/move_factory.go +++ b/pkg/factory/move_factory.go @@ -35,6 +35,14 @@ func BuildMove(db *pop.Connection, customs []Customization, traits []Trait) mode closeoutOffice = BuildTransportationOffice(db, tempCloseoutOfficeCustoms, nil) } + var tioAssignedUser models.OfficeUser + temptioAssignedUserCustoms := customs + tioAssignedUserResult := findValidCustomization(customs, OfficeUsers.TIOAssignedUser) + if tioAssignedUserResult != nil { + temptioAssignedUserCustoms = convertCustomizationInList(temptioAssignedUserCustoms, OfficeUsers.TIOAssignedUser, OfficeUser) + tioAssignedUser = BuildOfficeUser(db, temptioAssignedUserCustoms, nil) + } + var defaultReferenceID string var err error if db != nil { @@ -72,7 +80,10 @@ func BuildMove(db *pop.Connection, customs []Customization, traits []Trait) mode move.CloseoutOffice = &closeoutOffice move.CloseoutOfficeID = &closeoutOffice.ID } - + if tioAssignedUserResult != nil { + move.TIOAssignedUser = &tioAssignedUser + move.TIOAssignedID = &tioAssignedUser.ID + } // Overwrite values with those from assertions testdatagen.MergeModels(&move, cMove) diff --git a/pkg/factory/shared.go b/pkg/factory/shared.go index 7b76ce0529c..677b7e01a03 100644 --- a/pkg/factory/shared.go +++ b/pkg/factory/shared.go @@ -263,6 +263,14 @@ var TransportationOffices = transportationOfficeGroup{ CloseoutOffice: "CloseoutOffice", } +type officeUserGroup struct { + TIOAssignedUser CustomType +} + +var OfficeUsers = officeUserGroup{ + TIOAssignedUser: "TIOAssignedUser", +} + // uploadGroup is a grouping of all the upload related fields type uploadGroup struct { UploadTypePrime CustomType diff --git a/pkg/handlers/ghcapi/api.go b/pkg/handlers/ghcapi/api.go index 78eedf347e0..2e1ba17a2d0 100644 --- a/pkg/handlers/ghcapi/api.go +++ b/pkg/handlers/ghcapi/api.go @@ -267,10 +267,11 @@ func NewGhcAPIHandler(handlerConfig handlers.HandlerConfig) *ghcops.MymoveAPI { } ghcAPI.PaymentRequestsUpdatePaymentRequestStatusHandler = UpdatePaymentRequestStatusHandler{ - HandlerConfig: handlerConfig, - PaymentRequestStatusUpdater: paymentrequest.NewPaymentRequestStatusUpdater(queryBuilder), - PaymentRequestFetcher: paymentrequest.NewPaymentRequestFetcher(), - PaymentRequestListFetcher: paymentrequest.NewPaymentRequestListFetcher(), + HandlerConfig: handlerConfig, + PaymentRequestStatusUpdater: paymentrequest.NewPaymentRequestStatusUpdater(queryBuilder), + PaymentRequestFetcher: paymentrequest.NewPaymentRequestFetcher(), + PaymentRequestListFetcher: paymentrequest.NewPaymentRequestListFetcher(), + MoveAssignedOfficeUserUpdater: move.AssignedOfficeUserUpdater{}, } ghcAPI.PaymentServiceItemUpdatePaymentServiceItemStatusHandler = UpdatePaymentServiceItemStatusHandler{ diff --git a/pkg/handlers/ghcapi/payment_request.go b/pkg/handlers/ghcapi/payment_request.go index 9996edc758c..ac1b465118a 100644 --- a/pkg/handlers/ghcapi/payment_request.go +++ b/pkg/handlers/ghcapi/payment_request.go @@ -18,6 +18,7 @@ import ( "github.com/transcom/mymove/pkg/handlers" "github.com/transcom/mymove/pkg/handlers/ghcapi/internal/payloads" "github.com/transcom/mymove/pkg/models" + "github.com/transcom/mymove/pkg/models/roles" "github.com/transcom/mymove/pkg/services" "github.com/transcom/mymove/pkg/services/audit" "github.com/transcom/mymove/pkg/services/event" @@ -115,6 +116,7 @@ type UpdatePaymentRequestStatusHandler struct { services.PaymentRequestStatusUpdater services.PaymentRequestFetcher services.PaymentRequestListFetcher + services.MoveAssignedOfficeUserUpdater } // Handle updates payment requests status @@ -239,11 +241,12 @@ func (h UpdatePaymentRequestStatusHandler) Handle( } if !openPr { - move.TIOAssignedID = nil - verrs, err := models.SaveMoveDependencies(appCtx.DB(), move) - if err != nil || verrs.HasAny() { + + _, err := h.MoveAssignedOfficeUserUpdater.DeleteAssignedOfficeUser(appCtx, move.ID, roles.RoleTypeTIO) + if err != nil { return paymentrequestop.NewUpdatePaymentRequestStatusInternalServerError(), err } + returnPayload.MoveTaskOrder.TIOAssignedUser = nil } return paymentrequestop.NewUpdatePaymentRequestStatusOK().WithPayload(returnPayload), nil diff --git a/pkg/handlers/ghcapi/payment_request_test.go b/pkg/handlers/ghcapi/payment_request_test.go index c0af9b7aba9..d0a905ba8de 100644 --- a/pkg/handlers/ghcapi/payment_request_test.go +++ b/pkg/handlers/ghcapi/payment_request_test.go @@ -18,6 +18,7 @@ import ( "github.com/transcom/mymove/pkg/models" "github.com/transcom/mymove/pkg/models/roles" "github.com/transcom/mymove/pkg/services/mocks" + "github.com/transcom/mymove/pkg/services/move" paymentrequest "github.com/transcom/mymove/pkg/services/payment_request" "github.com/transcom/mymove/pkg/services/query" "github.com/transcom/mymove/pkg/trace" @@ -228,17 +229,25 @@ func (suite *HandlerSuite) TestGetPaymentRequestsForMoveHandler() { func (suite *HandlerSuite) TestUpdatePaymentRequestStatusHandler() { paymentRequestID, _ := uuid.FromString("00000000-0000-0000-0000-000000000001") - officeUserUUID, _ := uuid.NewV4() setupTestData := func() models.OfficeUser { - officeUser := factory.BuildOfficeUser(nil, []factory.Customization{ - {Model: models.OfficeUser{ - ID: officeUserUUID, - }}, + + transportationOffice := factory.BuildTransportationOffice(suite.DB(), []factory.Customization{ + { + Model: models.TransportationOffice{ + ProvidesCloseout: true, + }, + }, }, nil) - officeUser.User.Roles = append(officeUser.User.Roles, roles.Role{ - RoleType: roles.RoleTypeTIO, - }) + + officeUser := factory.BuildOfficeUserWithRoles(suite.DB(), []factory.Customization{ + { + Model: transportationOffice, + LinkOnly: true, + Type: &factory.TransportationOffices.CloseoutOffice, + }, + }, []roles.RoleType{roles.RoleTypeTIO}) + return officeUser } paymentRequest := models.PaymentRequest{ @@ -250,7 +259,45 @@ func (suite *HandlerSuite) TestUpdatePaymentRequestStatusHandler() { } statusUpdater := paymentrequest.NewPaymentRequestStatusUpdater(query.NewQueryBuilder()) + suite.Run("successful status update payment request and remove assigned user", func() { + officeUser := setupTestData() + pendingPaymentRequest := factory.BuildPaymentRequest(suite.DB(), []factory.Customization{ + { + Model: officeUser, + LinkOnly: true, + Type: &factory.OfficeUsers.TIOAssignedUser, + }, + }, nil) + + suite.NotNil(pendingPaymentRequest.MoveTaskOrder.TIOAssignedID) + + paymentRequestFetcher := &mocks.PaymentRequestFetcher{} + paymentRequestFetcher.On("FetchPaymentRequest", mock.AnythingOfType("*appcontext.appContext"), + mock.Anything).Return(pendingPaymentRequest, nil).Once() + req := httptest.NewRequest("PATCH", fmt.Sprintf("/payment_request/%s/status", pendingPaymentRequest.ID), nil) + req = suite.AuthenticateOfficeRequest(req, officeUser) + + params := paymentrequestop.UpdatePaymentRequestStatusParams{ + HTTPRequest: req, + Body: &ghcmessages.UpdatePaymentRequestStatusPayload{Status: "REVIEWED", RejectionReason: nil, ETag: etag.GenerateEtag(pendingPaymentRequest.UpdatedAt)}, + PaymentRequestID: strfmt.UUID(pendingPaymentRequest.ID.String()), + } + + handler := UpdatePaymentRequestStatusHandler{ + HandlerConfig: suite.HandlerConfig(), + PaymentRequestStatusUpdater: statusUpdater, + PaymentRequestFetcher: paymentRequestFetcher, + PaymentRequestListFetcher: paymentrequest.NewPaymentRequestListFetcher(), + MoveAssignedOfficeUserUpdater: move.AssignedOfficeUserUpdater{}, + } + + response := handler.Handle(params) + + payload := response.(*paymentrequestop.UpdatePaymentRequestStatusOK).Payload + suite.NotNil(payload.ReviewedAt) + suite.Nil(payload.MoveTaskOrder.TIOAssignedUser) + }) suite.Run("successful status update of payment request", func() { officeUser := setupTestData() pendingPaymentRequest := factory.BuildPaymentRequest(suite.DB(), nil, nil) @@ -269,10 +316,11 @@ func (suite *HandlerSuite) TestUpdatePaymentRequestStatusHandler() { } handler := UpdatePaymentRequestStatusHandler{ - HandlerConfig: suite.HandlerConfig(), - PaymentRequestStatusUpdater: statusUpdater, - PaymentRequestFetcher: paymentRequestFetcher, - PaymentRequestListFetcher: paymentrequest.NewPaymentRequestListFetcher(), + HandlerConfig: suite.HandlerConfig(), + PaymentRequestStatusUpdater: statusUpdater, + PaymentRequestFetcher: paymentRequestFetcher, + PaymentRequestListFetcher: paymentrequest.NewPaymentRequestListFetcher(), + MoveAssignedOfficeUserUpdater: move.AssignedOfficeUserUpdater{}, } // Validate incoming payload @@ -308,10 +356,11 @@ func (suite *HandlerSuite) TestUpdatePaymentRequestStatusHandler() { } handler := UpdatePaymentRequestStatusHandler{ - HandlerConfig: suite.HandlerConfig(), - PaymentRequestStatusUpdater: statusUpdater, - PaymentRequestFetcher: paymentRequestFetcher, - PaymentRequestListFetcher: paymentrequest.NewPaymentRequestListFetcher(), + HandlerConfig: suite.HandlerConfig(), + PaymentRequestStatusUpdater: statusUpdater, + PaymentRequestFetcher: paymentRequestFetcher, + PaymentRequestListFetcher: paymentrequest.NewPaymentRequestListFetcher(), + MoveAssignedOfficeUserUpdater: move.AssignedOfficeUserUpdater{}, } // Validate incoming payload From e1fa85d4e86586b24ddbc914cf2b60f4946c1889 Mon Sep 17 00:00:00 2001 From: Jon Spight Date: Tue, 17 Dec 2024 00:50:07 +0000 Subject: [PATCH 18/51] cleaned up tests --- .../payloads/model_to_payload_test.go | 44 +++++++++---------- .../payloads/model_to_payload_test.go | 10 ++--- 2 files changed, 27 insertions(+), 27 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 e02267a4760..9631694ed5e 100644 --- a/pkg/handlers/ghcapi/internal/payloads/model_to_payload_test.go +++ b/pkg/handlers/ghcapi/internal/payloads/model_to_payload_test.go @@ -40,15 +40,15 @@ func (suite *PayloadsSuite) TestOrderWithMove() { func (suite *PayloadsSuite) TestBoatShipment() { boat := factory.BuildBoatShipment(suite.DB(), nil, nil) - value := BoatShipment(nil, &boat) - suite.NotNil(value) + boatShipment := BoatShipment(nil, &boat) + suite.NotNil(boatShipment) } func (suite *PayloadsSuite) TestMobileHomeShipment() { mobileHome := factory.BuildMobileHomeShipment(suite.DB(), nil, nil) - value := MobileHomeShipment(nil, &mobileHome) - suite.NotNil(value) + mobileHomeShipment := MobileHomeShipment(nil, &mobileHome) + suite.NotNil(mobileHomeShipment) } func (suite *PayloadsSuite) TestMovingExpense() { @@ -68,8 +68,8 @@ func (suite *PayloadsSuite) TestMovingExpense() { SITLocation: &sitLocation, SITReimburseableAmount: (*unit.Cents)(&sitReimburseableAmount), } - value := MovingExpense(nil, &movingExpense) - suite.NotNil(value) + movingExpenseValues := MovingExpense(nil, &movingExpense) + suite.NotNil(movingExpenseValues) } func (suite *PayloadsSuite) TestMovingExpenses() { @@ -102,8 +102,8 @@ func (suite *PayloadsSuite) TestMovingExpenses() { SITReimburseableAmount: (*unit.Cents)(&sitReimburseableAmount), } movingExpenses = append(movingExpenses, movingExpense, movingExpenseTwo) - value := MovingExpenses(nil, movingExpenses) - suite.NotNil(value) + movingExpensesValue := MovingExpenses(nil, movingExpenses) + suite.NotNil(movingExpensesValue) } // TestMove makes sure zero values/optional fields are handled @@ -640,44 +640,44 @@ func (suite *PayloadsSuite) TestCreateCustomer() { func (suite *PayloadsSuite) TestMoveTaskOrder() { move := factory.BuildMove(suite.DB(), nil, nil) - value := MoveTaskOrder(&move) - suite.NotNil(value) + moveTaskOrder := MoveTaskOrder(&move) + suite.NotNil(moveTaskOrder) } func (suite *PayloadsSuite) TestTransportationOffice() { - transportationOffice := factory.BuildTransportationOffice(suite.DB(), []factory.Customization{ + office := factory.BuildTransportationOffice(suite.DB(), []factory.Customization{ { Model: models.TransportationOffice{ ID: uuid.Must(uuid.NewV4()), }, }}, nil) - value := TransportationOffice(&transportationOffice) - suite.NotNil(value) + transportationOffice := TransportationOffice(&office) + suite.NotNil(transportationOffice) } func (suite *PayloadsSuite) TestTransportationOffices() { - transportationOffice := factory.BuildTransportationOffice(suite.DB(), []factory.Customization{ + office := factory.BuildTransportationOffice(suite.DB(), []factory.Customization{ { Model: models.TransportationOffice{ ID: uuid.Must(uuid.NewV4()), }, }}, nil) - transportationOfficeTwo := factory.BuildTransportationOffice(suite.DB(), []factory.Customization{ + officeTwo := factory.BuildTransportationOffice(suite.DB(), []factory.Customization{ { Model: models.TransportationOffice{ ID: uuid.Must(uuid.NewV4()), }, }}, nil) - list := models.TransportationOffices{} - list = append(list, transportationOffice, transportationOfficeTwo) - value := TransportationOffices(list) + transportationOfficeList := models.TransportationOffices{} + transportationOfficeList = append(transportationOfficeList, office, officeTwo) + value := TransportationOffices(transportationOfficeList) suite.NotNil(value) } func (suite *PayloadsSuite) TestListMove() { marines := models.AffiliationMARINES - value := ListMove(nil) + listMove := ListMove(nil) - suite.Nil(value) + suite.Nil(listMove) moveUSMC := factory.BuildMove(suite.DB(), []factory.Customization{ { Model: models.ServiceMember{ @@ -686,8 +686,8 @@ func (suite *PayloadsSuite) TestListMove() { }, }, nil) - value = ListMove(&moveUSMC) - suite.NotNil(value) + listMove = ListMove(&moveUSMC) + suite.NotNil(listMove) } func (suite *PayloadsSuite) TestListMoves() { diff --git a/pkg/handlers/primeapi/payloads/model_to_payload_test.go b/pkg/handlers/primeapi/payloads/model_to_payload_test.go index a6bc9ea0945..8ba0c23b130 100644 --- a/pkg/handlers/primeapi/payloads/model_to_payload_test.go +++ b/pkg/handlers/primeapi/payloads/model_to_payload_test.go @@ -541,8 +541,8 @@ func (suite *PayloadsSuite) TestMTOShipmentWithoutServiceItems() { }, }, }, nil) - value := MTOShipmentWithoutServiceItems(&mtoShipment) - suite.NotNil(value) + shipmentWithoutServiceItem := MTOShipmentWithoutServiceItems(&mtoShipment) + suite.NotNil(shipmentWithoutServiceItem) } func (suite *PayloadsSuite) TestMTOShipmentsWithoutServiceItems() { @@ -585,9 +585,9 @@ func (suite *PayloadsSuite) TestMTOShipmentsWithoutServiceItems() { }, }, }, nil) - shipments := models.MTOShipments{} - shipments = append(shipments, mtoShipmentTwo, mtoShipment) - value := MTOShipmentsWithoutServiceItems(&shipments) + shipmentList := models.MTOShipments{} + shipmentList = append(shipmentList, mtoShipmentTwo, mtoShipment) + value := MTOShipmentsWithoutServiceItems(&shipmentList) suite.NotNil(value) } From a841cbea87e7c16ad30f0fcd9b5be818405df1f0 Mon Sep 17 00:00:00 2001 From: Jon Spight Date: Tue, 17 Dec 2024 15:04:17 +0000 Subject: [PATCH 19/51] PR Fixes --- pkg/factory/move_factory_test.go | 18 ++++++++++++++++++ pkg/handlers/ghcapi/payment_request.go | 8 ++++---- .../primeapi/payloads/model_to_payload_test.go | 1 - 3 files changed, 22 insertions(+), 5 deletions(-) diff --git a/pkg/factory/move_factory_test.go b/pkg/factory/move_factory_test.go index 4b8a86a3df0..7f5f10ec6fe 100644 --- a/pkg/factory/move_factory_test.go +++ b/pkg/factory/move_factory_test.go @@ -4,6 +4,7 @@ import ( "time" "github.com/transcom/mymove/pkg/models" + "github.com/transcom/mymove/pkg/models/roles" ) func (suite *FactorySuite) TestBuildMove() { @@ -267,6 +268,23 @@ func (suite *FactorySuite) TestBuildMove() { suite.NotEmpty(move.MTOShipments) suite.Equal(models.MTOShipmentStatusSubmitted, move.MTOShipments[0].Status) }) + suite.Run("Successful creation of a move with an assigned TIO", func() { + officeUser := BuildOfficeUserWithRoles(suite.DB(), nil, []roles.RoleType{roles.RoleTypeTIO}) + + move := BuildMoveWithShipment(suite.DB(), []Customization{ + { + Model: models.Move{ + Status: models.MoveStatusAPPROVED, + }, + }, + { + Model: officeUser, + LinkOnly: true, + Type: &OfficeUsers.TIOAssignedUser, + }, + }, nil) + suite.Equal(officeUser.ID, *move.TIOAssignedID) + }) suite.Run("Successful creation of customized move with shipment", func() { // Under test: BuildMoveWithShipment diff --git a/pkg/handlers/ghcapi/payment_request.go b/pkg/handlers/ghcapi/payment_request.go index ac1b465118a..35e9a20219f 100644 --- a/pkg/handlers/ghcapi/payment_request.go +++ b/pkg/handlers/ghcapi/payment_request.go @@ -232,15 +232,15 @@ func (h UpdatePaymentRequestStatusHandler) Handle( return paymentrequestop.NewUpdatePaymentRequestStatusInternalServerError(), err } - openPr := false + unreviewedPaymentRequset := false for _, request := range *requestList { if request.Status != models.PaymentRequestStatusReviewed && request.Status != models.PaymentRequestStatusReviewedAllRejected { - openPr = true + unreviewedPaymentRequset = true + break } } - - if !openPr { + if !unreviewedPaymentRequset { _, err := h.MoveAssignedOfficeUserUpdater.DeleteAssignedOfficeUser(appCtx, move.ID, roles.RoleTypeTIO) if err != nil { diff --git a/pkg/handlers/primeapi/payloads/model_to_payload_test.go b/pkg/handlers/primeapi/payloads/model_to_payload_test.go index 8ba0c23b130..8d14f98b949 100644 --- a/pkg/handlers/primeapi/payloads/model_to_payload_test.go +++ b/pkg/handlers/primeapi/payloads/model_to_payload_test.go @@ -452,7 +452,6 @@ func (suite *PayloadsSuite) TestNotImplementedError() { noDetailError := NotImplementedError(nil, traceID) suite.Equal(handlers.NotImplementedErrMessage, *noDetailError.Title) - // suite.Equal(handlers.NotImplementedErrMessage, *noDetailError.Detail) suite.Equal(traceID.String(), noDetailError.Instance.String()) detailError := NotImplementedError(&detail, traceID) From 0bbc3c47db60856a160c2ed90653eb02d55d4aff Mon Sep 17 00:00:00 2001 From: Jon Spight Date: Tue, 17 Dec 2024 16:44:17 +0000 Subject: [PATCH 20/51] PR fix - name change --- pkg/handlers/ghcapi/payment_request.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pkg/handlers/ghcapi/payment_request.go b/pkg/handlers/ghcapi/payment_request.go index 35e9a20219f..0ca94b13582 100644 --- a/pkg/handlers/ghcapi/payment_request.go +++ b/pkg/handlers/ghcapi/payment_request.go @@ -232,15 +232,15 @@ func (h UpdatePaymentRequestStatusHandler) Handle( return paymentrequestop.NewUpdatePaymentRequestStatusInternalServerError(), err } - unreviewedPaymentRequset := false + paymentRequestNeedingReview := false for _, request := range *requestList { if request.Status != models.PaymentRequestStatusReviewed && request.Status != models.PaymentRequestStatusReviewedAllRejected { - unreviewedPaymentRequset = true + paymentRequestNeedingReview = true break } } - if !unreviewedPaymentRequset { + if !paymentRequestNeedingReview { _, err := h.MoveAssignedOfficeUserUpdater.DeleteAssignedOfficeUser(appCtx, move.ID, roles.RoleTypeTIO) if err != nil { From a061005bcc1f9d61bc50b972c28bd83b91d5f5fd Mon Sep 17 00:00:00 2001 From: Jon Spight Date: Tue, 17 Dec 2024 17:31:57 +0000 Subject: [PATCH 21/51] PR fix - line removal --- pkg/handlers/ghcapi/payment_request.go | 1 - 1 file changed, 1 deletion(-) diff --git a/pkg/handlers/ghcapi/payment_request.go b/pkg/handlers/ghcapi/payment_request.go index 0ca94b13582..bb19a7331c8 100644 --- a/pkg/handlers/ghcapi/payment_request.go +++ b/pkg/handlers/ghcapi/payment_request.go @@ -241,7 +241,6 @@ func (h UpdatePaymentRequestStatusHandler) Handle( } } if !paymentRequestNeedingReview { - _, err := h.MoveAssignedOfficeUserUpdater.DeleteAssignedOfficeUser(appCtx, move.ID, roles.RoleTypeTIO) if err != nil { return paymentrequestop.NewUpdatePaymentRequestStatusInternalServerError(), err From 90a455a4ea9e78cd90fd24f95cd6101cb0660665 Mon Sep 17 00:00:00 2001 From: Jon Spight Date: Wed, 18 Dec 2024 16:13:06 +0000 Subject: [PATCH 22/51] Validate&save --- pkg/services/mto_service_item/mto_service_item_updater.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) 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 04b389a5c24..611c433540a 100644 --- a/pkg/services/mto_service_item/mto_service_item_updater.go +++ b/pkg/services/mto_service_item/mto_service_item_updater.go @@ -161,7 +161,10 @@ func (p *mtoServiceItemUpdater) approveOrRejectServiceItem( //When updating a service item - remove the TOO assigned user move.TOOAssignedID = nil - _, err = models.SaveMoveDependencies(appCtx.DB(), &move) + verrs, err := appCtx.DB().ValidateAndSave(&move) + if verrs != nil && verrs.HasAny() { + return apperror.NewInvalidInputError(move.ID, nil, verrs, "") + } if err != nil { return err } From 6fd4cf00ec3760c0699326c369db94106ed774c2 Mon Sep 17 00:00:00 2001 From: loganwc Date: Wed, 18 Dec 2024 16:55:54 +0000 Subject: [PATCH 23/51] added 3rd address and fixed 2nd address test --- .../Shipment/PrimeUIShipmentCreate.test.jsx | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/pages/PrimeUI/Shipment/PrimeUIShipmentCreate.test.jsx b/src/pages/PrimeUI/Shipment/PrimeUIShipmentCreate.test.jsx index ffa73be8202..815c90fc14b 100644 --- a/src/pages/PrimeUI/Shipment/PrimeUIShipmentCreate.test.jsx +++ b/src/pages/PrimeUI/Shipment/PrimeUIShipmentCreate.test.jsx @@ -173,7 +173,7 @@ describe('Create PPM', () => { }); describe('Create Mobile Home', () => { - it('test with 2nd addresses', async () => { + it('test with 2nd and 3rd addresses', async () => { createPrimeMTOShipmentV3.mockReturnValue({}); render(mockedComponent); @@ -191,10 +191,19 @@ describe('Create Mobile Home', () => { expect(secondAddressToggle).toBeInTheDocument(); await userEvent.click(secondAddressToggle); - input = await document.querySelector('input[name="pickupAddress.streetAddress2"]'); + input = await document.querySelector('input[name="secondaryPickupAddress.streetAddress1"]'); expect(input).toBeInTheDocument(); // enter required street 1 for pickup 2 - await userEvent.type(input, '123 Street'); + await userEvent.type(input, '123 Street 2'); + + const thirdAddressToggle = document.querySelector('[data-testid="has-tertiary-pickup"]'); + expect(thirdAddressToggle).toBeInTheDocument(); + await userEvent.click(thirdAddressToggle); + + input = await document.querySelector('input[name="tertiaryPickupAddress.streetAddress1"]'); + expect(input).toBeInTheDocument(); + // enter required street 1 for pickup 2 + await userEvent.type(input, '123 Street 2'); input = await document.querySelector('input[name="destinationAddress.streetAddress1"]'); expect(input).toBeInTheDocument(); From 0c3f4ff41df6322fd73b362893f1a479a095b715 Mon Sep 17 00:00:00 2001 From: loganwc Date: Wed, 18 Dec 2024 16:59:22 +0000 Subject: [PATCH 24/51] change typo --- src/pages/PrimeUI/Shipment/PrimeUIShipmentCreate.test.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/PrimeUI/Shipment/PrimeUIShipmentCreate.test.jsx b/src/pages/PrimeUI/Shipment/PrimeUIShipmentCreate.test.jsx index 815c90fc14b..7d3d732c89c 100644 --- a/src/pages/PrimeUI/Shipment/PrimeUIShipmentCreate.test.jsx +++ b/src/pages/PrimeUI/Shipment/PrimeUIShipmentCreate.test.jsx @@ -203,7 +203,7 @@ describe('Create Mobile Home', () => { input = await document.querySelector('input[name="tertiaryPickupAddress.streetAddress1"]'); expect(input).toBeInTheDocument(); // enter required street 1 for pickup 2 - await userEvent.type(input, '123 Street 2'); + await userEvent.type(input, '123 Street 3'); input = await document.querySelector('input[name="destinationAddress.streetAddress1"]'); expect(input).toBeInTheDocument(); From 9714cdf310d0c842c500a1f1556733d1dba8084c Mon Sep 17 00:00:00 2001 From: Jon Spight Date: Wed, 18 Dec 2024 19:26:48 +0000 Subject: [PATCH 25/51] Proper TOO service item removal --- pkg/models/move.go | 18 +++++++++++++++++ .../mto_service_item_updater.go | 20 ++++++++++++++++++- 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/pkg/models/move.go b/pkg/models/move.go index 23c1dd7c479..f3aefca3e51 100644 --- a/pkg/models/move.go +++ b/pkg/models/move.go @@ -413,6 +413,24 @@ func SaveMoveDependencies(db *pop.Connection, move *Move) (*validate.Errors, err return responseVErrors, responseError } +// FetchMoveByMoveIDWithServiceItems returns a Move along with all the associations needed to determine +// the move service item's status. +func FetchMoveByMoveIDWithServiceItems(db *pop.Connection, moveID uuid.UUID) (Move, error) { + var move Move + err := db.Q().Eager( + "MTOServiceItems", + "MTOServiceItems.Status", + ).Where("show = TRUE").Find(&move, moveID) + + if err != nil { + if errors.Cause(err).Error() == RecordNotFoundErrorString { + return Move{}, ErrFetchNotFound + } + return Move{}, err + } + return move, nil +} + // FetchMoveForMoveDates returns a Move along with all the associations needed to determine // the move dates summary information. func FetchMoveForMoveDates(db *pop.Connection, moveID uuid.UUID) (Move, 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 611c433540a..1eb06ebd6c3 100644 --- a/pkg/services/mto_service_item/mto_service_item_updater.go +++ b/pkg/services/mto_service_item/mto_service_item_updater.go @@ -157,10 +157,28 @@ func (p *mtoServiceItemUpdater) approveOrRejectServiceItem( if err != nil { return err } + move := serviceItem.MoveTaskOrder + moveWithServiceItems, err := models.FetchMoveByMoveIDWithServiceItems(txnAppCtx.DB(), move.ID) + if err != nil { + return err + } + + serviceItemsNeedingReview := false + for _, request := range moveWithServiceItems.MTOServiceItems { + if request.Status != models.MTOServiceItemStatusApproved && + request.Status != models.MTOServiceItemStatusRejected { + serviceItemsNeedingReview = true + break + } + } + + //remove assigned user when all service items have been reviewed + if !serviceItemsNeedingReview { + move.TOOAssignedID = nil + } //When updating a service item - remove the TOO assigned user - move.TOOAssignedID = nil verrs, err := appCtx.DB().ValidateAndSave(&move) if verrs != nil && verrs.HasAny() { return apperror.NewInvalidInputError(move.ID, nil, verrs, "") From ae862c0d915133e9a581508fe4ec94fce0f9c13a Mon Sep 17 00:00:00 2001 From: loganwc Date: Wed, 18 Dec 2024 20:17:14 +0000 Subject: [PATCH 26/51] added more test coverage to prime ui shipment create --- .../Shipment/PrimeUIShipmentCreate.test.jsx | 63 +++++++++++++++++++ 1 file changed, 63 insertions(+) diff --git a/src/pages/PrimeUI/Shipment/PrimeUIShipmentCreate.test.jsx b/src/pages/PrimeUI/Shipment/PrimeUIShipmentCreate.test.jsx index 7d3d732c89c..fd49eff9b16 100644 --- a/src/pages/PrimeUI/Shipment/PrimeUIShipmentCreate.test.jsx +++ b/src/pages/PrimeUI/Shipment/PrimeUIShipmentCreate.test.jsx @@ -221,3 +221,66 @@ describe('Create Mobile Home', () => { }); }); }); + +describe('When creating shipment', () => { + it('disabling 2nd/3rd address clears out the data', async () => { + createPrimeMTOShipmentV3.mockReturnValue({}); + + render(mockedComponent); + + waitFor(async () => { + await userEvent.selectOptions(screen.getByLabelText('Shipment type'), 'HHG'); + + // Start controlled test case to verify everything is working. + let input = await document.querySelector('input[name="pickupAddress.streetAddress1"]'); + expect(input).toBeInTheDocument(); + // enter required street 1 for pickup + await userEvent.type(input, '123 Street'); + + const secondAddressToggle = document.querySelector('[data-testid="has-secondary-pickup"]'); + expect(secondAddressToggle).toBeInTheDocument(); + await userEvent.click(secondAddressToggle); + + input = await document.querySelector('input[name="secondaryPickupAddress.streetAddress1"]'); + expect(input).toBeInTheDocument(); + // enter required street 1 for pickup 2 + await userEvent.type(input, '123 Street 2'); + + const thirdAddressToggle = document.querySelector('[data-testid="has-tertiary-pickup"]'); + expect(thirdAddressToggle).toBeInTheDocument(); + await userEvent.click(thirdAddressToggle); + + input = await document.querySelector('input[name="tertiaryPickupAddress.streetAddress1"]'); + expect(input).toBeInTheDocument(); + // enter required street 1 for pickup 2 + await userEvent.type(input, '123 Street 3'); + + const disable3rdAddressToggle = document.querySelector('[data-testid="no-tertiary-pickup"]'); + expect(disable3rdAddressToggle).toBeInTheDocument(); + await userEvent.click(disable3rdAddressToggle); + + const disable2ndAddressToggle = document.querySelector('[data-testid="no-secondary-pickup"]'); + expect(disable2ndAddressToggle).toBeInTheDocument(); + await userEvent.click(disable2ndAddressToggle); + + input = await document.querySelector('input[name="destinationAddress.streetAddress1"]'); + expect(input).toBeInTheDocument(); + // enter something + await userEvent.type(input, '123 Street'); + + const saveButton = await screen.getByRole('button', { name: 'Save' }); + + expect(saveButton).not.toBeDisabled(); + await userEvent.click(saveButton); + + await waitFor(() => { + expect(createPrimeMTOShipmentV3).toHaveBeenCalledWith( + expect.objectContaining({ + secondaryPickupAddress: {}, + tertiaryPickupAddress: {}, + }), + ); + }); + }); + }); +}); From 06493d5de8003a5ecb9d76ca3062217e4047e62c Mon Sep 17 00:00:00 2001 From: Paul Stonebraker Date: Wed, 18 Dec 2024 20:26:06 +0000 Subject: [PATCH 27/51] add factory stuff for SC and TOO --- pkg/factory/move_factory.go | 33 ++++++++++++++++++++++++++--- pkg/factory/move_factory_test.go | 36 ++++++++++++++++++++++++++++++++ pkg/factory/shared.go | 4 ++++ 3 files changed, 70 insertions(+), 3 deletions(-) diff --git a/pkg/factory/move_factory.go b/pkg/factory/move_factory.go index a3659d3bae2..72ecf8d66b4 100644 --- a/pkg/factory/move_factory.go +++ b/pkg/factory/move_factory.go @@ -35,12 +35,28 @@ func BuildMove(db *pop.Connection, customs []Customization, traits []Trait) mode closeoutOffice = BuildTransportationOffice(db, tempCloseoutOfficeCustoms, nil) } + var scAssignedUser models.OfficeUser + tempSCAssignedUserCustoms := customs + scAssignedUserResult := findValidCustomization(customs, OfficeUsers.SCAssignedUser) + if scAssignedUserResult != nil { + tempSCAssignedUserCustoms = convertCustomizationInList(tempSCAssignedUserCustoms, OfficeUsers.SCAssignedUser, OfficeUser) + scAssignedUser = BuildOfficeUser(db, tempSCAssignedUserCustoms, nil) + } + + var tooAssignedUser models.OfficeUser + tempTOOAssignedUserCustoms := customs + tooAssignedUserResult := findValidCustomization(customs, OfficeUsers.TOOAssignedUser) + if tooAssignedUserResult != nil { + tempTOOAssignedUserCustoms = convertCustomizationInList(tempTOOAssignedUserCustoms, OfficeUsers.TOOAssignedUser, OfficeUser) + tooAssignedUser = BuildOfficeUser(db, tempTOOAssignedUserCustoms, nil) + } + var tioAssignedUser models.OfficeUser - temptioAssignedUserCustoms := customs + tempTIOAssignedUserCustoms := customs tioAssignedUserResult := findValidCustomization(customs, OfficeUsers.TIOAssignedUser) if tioAssignedUserResult != nil { - temptioAssignedUserCustoms = convertCustomizationInList(temptioAssignedUserCustoms, OfficeUsers.TIOAssignedUser, OfficeUser) - tioAssignedUser = BuildOfficeUser(db, temptioAssignedUserCustoms, nil) + tempTIOAssignedUserCustoms = convertCustomizationInList(tempTIOAssignedUserCustoms, OfficeUsers.TIOAssignedUser, OfficeUser) + tioAssignedUser = BuildOfficeUser(db, tempTIOAssignedUserCustoms, nil) } var defaultReferenceID string @@ -80,6 +96,17 @@ func BuildMove(db *pop.Connection, customs []Customization, traits []Trait) mode move.CloseoutOffice = &closeoutOffice move.CloseoutOfficeID = &closeoutOffice.ID } + + if scAssignedUserResult != nil { + move.SCAssignedUser = &scAssignedUser + move.SCAssignedID = &scAssignedUser.ID + } + + if tooAssignedUserResult != nil { + move.TOOAssignedUser = &tooAssignedUser + move.TOOAssignedID = &tooAssignedUser.ID + } + if tioAssignedUserResult != nil { move.TIOAssignedUser = &tioAssignedUser move.TIOAssignedID = &tioAssignedUser.ID diff --git a/pkg/factory/move_factory_test.go b/pkg/factory/move_factory_test.go index 7f5f10ec6fe..0ff821a5dc0 100644 --- a/pkg/factory/move_factory_test.go +++ b/pkg/factory/move_factory_test.go @@ -268,6 +268,42 @@ func (suite *FactorySuite) TestBuildMove() { suite.NotEmpty(move.MTOShipments) suite.Equal(models.MTOShipmentStatusSubmitted, move.MTOShipments[0].Status) }) + suite.Run("Successful creation of a move with an assigned SC", func() { + officeUser := BuildOfficeUserWithRoles(suite.DB(), nil, []roles.RoleType{roles.RoleTypeServicesCounselor}) + + move := BuildMoveWithShipment(suite.DB(), []Customization{ + { + Model: models.Move{ + Status: models.MoveStatusAPPROVED, + }, + }, + { + Model: officeUser, + LinkOnly: true, + Type: &OfficeUsers.SCAssignedUser, + }, + }, nil) + suite.Equal(officeUser.ID, *move.SCAssignedID) + }) + + suite.Run("Successful creation of a move with an assigned TOO", func() { + officeUser := BuildOfficeUserWithRoles(suite.DB(), nil, []roles.RoleType{roles.RoleTypeTOO}) + + move := BuildMoveWithShipment(suite.DB(), []Customization{ + { + Model: models.Move{ + Status: models.MoveStatusAPPROVED, + }, + }, + { + Model: officeUser, + LinkOnly: true, + Type: &OfficeUsers.TOOAssignedUser, + }, + }, nil) + suite.Equal(officeUser.ID, *move.TOOAssignedID) + }) + suite.Run("Successful creation of a move with an assigned TIO", func() { officeUser := BuildOfficeUserWithRoles(suite.DB(), nil, []roles.RoleType{roles.RoleTypeTIO}) diff --git a/pkg/factory/shared.go b/pkg/factory/shared.go index 677b7e01a03..59f52644942 100644 --- a/pkg/factory/shared.go +++ b/pkg/factory/shared.go @@ -264,10 +264,14 @@ var TransportationOffices = transportationOfficeGroup{ } type officeUserGroup struct { + SCAssignedUser CustomType + TOOAssignedUser CustomType TIOAssignedUser CustomType } var OfficeUsers = officeUserGroup{ + SCAssignedUser: "SCAssignedUser", + TOOAssignedUser: "TOOAssignedUser", TIOAssignedUser: "TIOAssignedUser", } From f07c194b861b6b1af890e181ceea179e0c972b41 Mon Sep 17 00:00:00 2001 From: Jon Spight Date: Wed, 18 Dec 2024 21:56:44 +0000 Subject: [PATCH 28/51] TOO assigned user tests --- .../mto_service_item_updater.go | 3 +- .../mto_service_item_updater_test.go | 45 +++++++++++++++++++ 2 files changed, 46 insertions(+), 2 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 1eb06ebd6c3..8d2c5aded1e 100644 --- a/pkg/services/mto_service_item/mto_service_item_updater.go +++ b/pkg/services/mto_service_item/mto_service_item_updater.go @@ -166,8 +166,7 @@ func (p *mtoServiceItemUpdater) approveOrRejectServiceItem( serviceItemsNeedingReview := false for _, request := range moveWithServiceItems.MTOServiceItems { - if request.Status != models.MTOServiceItemStatusApproved && - request.Status != models.MTOServiceItemStatusRejected { + if request.Status == models.MTOServiceItemStatusSubmitted { serviceItemsNeedingReview = true break } 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 f2c6889ca98..1614e5804c8 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 @@ -21,6 +21,7 @@ import ( "github.com/transcom/mymove/pkg/factory" "github.com/transcom/mymove/pkg/handlers" "github.com/transcom/mymove/pkg/models" + "github.com/transcom/mymove/pkg/models/roles" mocks "github.com/transcom/mymove/pkg/route/mocks" "github.com/transcom/mymove/pkg/services/address" moverouter "github.com/transcom/mymove/pkg/services/move" @@ -1783,6 +1784,50 @@ func (suite *MTOServiceItemServiceSuite) TestUpdateMTOServiceItemStatus() { suite.Nil(serviceItem.RejectedAt) suite.NotNil(updatedServiceItem) }) + suite.Run("Handling assigned user When TOO reviews move and approves service item", func() { + transportationOffice := factory.BuildTransportationOffice(suite.DB(), []factory.Customization{ + { + Model: models.TransportationOffice{ + ProvidesCloseout: true, + }, + }, + }, nil) + + officeUser := factory.BuildOfficeUserWithRoles(suite.DB(), []factory.Customization{ + { + Model: transportationOffice, + LinkOnly: true, + Type: &factory.TransportationOffices.CloseoutOffice, + }, + }, []roles.RoleType{roles.RoleTypeTOO}) + + move := factory.BuildApprovalsRequestedMove(suite.DB(), []factory.Customization{ + { + Model: officeUser, + LinkOnly: true, + Type: &factory.OfficeUsers.TOOAssignedUser, + }, + }, nil) + + serviceItem := factory.BuildMTOServiceItem(suite.DB(), []factory.Customization{ + { + Model: move, + LinkOnly: true, + }, + }, nil) + + suite.NotNil(move.TOOAssignedUser) + eTag := etag.GenerateEtag(serviceItem.UpdatedAt) + updatedServiceItem, err := updater.ApproveOrRejectServiceItem( + suite.AppContextForTest(), serviceItem.ID, models.MTOServiceItemStatusApproved, rejectionReason, eTag) + suite.NoError(err) + err = suite.DB().Find(&move, move.ID) + suite.NoError(err) + err = suite.DB().Find(&serviceItem, serviceItem.ID) + suite.NoError(err) + suite.Nil(move.TOOAssignedID) + suite.Equal(models.MTOServiceItemStatusApproved, updatedServiceItem.Status) + }) suite.Run("When TOO approves a DDDSIT service item with an existing SITDestinationFinalAddress", func() { move := factory.BuildApprovalsRequestedMove(suite.DB(), nil, nil) From e5d834d35a95cdac4a38ef5d74b227c18a42a5fd Mon Sep 17 00:00:00 2001 From: Jon Spight Date: Fri, 20 Dec 2024 02:05:31 +0000 Subject: [PATCH 29/51] Unfinished Handler -> service --- pkg/handlers/ghcapi/api.go | 2 +- pkg/handlers/ghcapi/payment_request.go | 22 +++------- .../mocks/PaymentRequestListFetcher.go | 28 ++++++++++++ pkg/services/payment_request.go | 1 + .../payment_request_list_fetcher.go | 43 +++++++++++++++++++ 5 files changed, 78 insertions(+), 18 deletions(-) diff --git a/pkg/handlers/ghcapi/api.go b/pkg/handlers/ghcapi/api.go index 2e1ba17a2d0..ca33cea1dce 100644 --- a/pkg/handlers/ghcapi/api.go +++ b/pkg/handlers/ghcapi/api.go @@ -271,7 +271,7 @@ func NewGhcAPIHandler(handlerConfig handlers.HandlerConfig) *ghcops.MymoveAPI { PaymentRequestStatusUpdater: paymentrequest.NewPaymentRequestStatusUpdater(queryBuilder), PaymentRequestFetcher: paymentrequest.NewPaymentRequestFetcher(), PaymentRequestListFetcher: paymentrequest.NewPaymentRequestListFetcher(), - MoveAssignedOfficeUserUpdater: move.AssignedOfficeUserUpdater{}, + MoveAssignedOfficeUserUpdater: move.NewAssignedOfficeUserUpdater(move.NewMoveFetcher()), } ghcAPI.PaymentServiceItemUpdatePaymentServiceItemStatusHandler = UpdatePaymentServiceItemStatusHandler{ diff --git a/pkg/handlers/ghcapi/payment_request.go b/pkg/handlers/ghcapi/payment_request.go index bb19a7331c8..21c9ae38bc6 100644 --- a/pkg/handlers/ghcapi/payment_request.go +++ b/pkg/handlers/ghcapi/payment_request.go @@ -222,31 +222,19 @@ func (h UpdatePaymentRequestStatusHandler) Handle( return paymentrequestop.NewGetPaymentRequestInternalServerError(), err } - //When approving a Payment request - remove the TIO assigned user - move, err := models.FetchMove(appCtx.DB(), appCtx.Session(), existingPaymentRequest.MoveTaskOrderID) + paymnetRequest, err := h.PaymentRequestListFetcher.CheckAndRemovePaymentRequestAssignedUser(appCtx, existingPaymentRequest.MoveTaskOrderID) if err != nil { return paymentrequestop.NewUpdatePaymentRequestStatusInternalServerError(), err } - requestList, err := h.FetchPaymentRequestListByMove(appCtx, move.Locator) - if err != nil { - return paymentrequestop.NewUpdatePaymentRequestStatusInternalServerError(), err - } - - paymentRequestNeedingReview := false - for _, request := range *requestList { - if request.Status != models.PaymentRequestStatusReviewed && - request.Status != models.PaymentRequestStatusReviewedAllRejected { - paymentRequestNeedingReview = true - break - } - } - if !paymentRequestNeedingReview { - _, err := h.MoveAssignedOfficeUserUpdater.DeleteAssignedOfficeUser(appCtx, move.ID, roles.RoleTypeTIO) + // ---------------------- Move to Service (in progress) ----------------------------- + if !paymnetRequest { + _, err := h.MoveAssignedOfficeUserUpdater.DeleteAssignedOfficeUser(appCtx, existingPaymentRequest.MoveTaskOrderID, roles.RoleTypeTIO) if err != nil { return paymentrequestop.NewUpdatePaymentRequestStatusInternalServerError(), err } returnPayload.MoveTaskOrder.TIOAssignedUser = nil } + // ---------------------- Move to Service (in progress) ----------------------------- return paymentrequestop.NewUpdatePaymentRequestStatusOK().WithPayload(returnPayload), nil }) diff --git a/pkg/services/mocks/PaymentRequestListFetcher.go b/pkg/services/mocks/PaymentRequestListFetcher.go index ebb611a7872..f88b128b1ab 100644 --- a/pkg/services/mocks/PaymentRequestListFetcher.go +++ b/pkg/services/mocks/PaymentRequestListFetcher.go @@ -18,6 +18,34 @@ type PaymentRequestListFetcher struct { mock.Mock } +// CheckAndRemovePaymentRequestAssignedUser provides a mock function with given fields: appCtx, id +func (_m *PaymentRequestListFetcher) CheckAndRemovePaymentRequestAssignedUser(appCtx appcontext.AppContext, id uuid.UUID) (bool, error) { + ret := _m.Called(appCtx, id) + + if len(ret) == 0 { + panic("no return value specified for CheckAndRemovePaymentRequestAssignedUser") + } + + var r0 bool + var r1 error + if rf, ok := ret.Get(0).(func(appcontext.AppContext, uuid.UUID) (bool, error)); ok { + return rf(appCtx, id) + } + if rf, ok := ret.Get(0).(func(appcontext.AppContext, uuid.UUID) bool); ok { + r0 = rf(appCtx, id) + } else { + r0 = ret.Get(0).(bool) + } + + if rf, ok := ret.Get(1).(func(appcontext.AppContext, uuid.UUID) error); ok { + r1 = rf(appCtx, id) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + // FetchPaymentRequestList provides a mock function with given fields: appCtx, officeUserID, params func (_m *PaymentRequestListFetcher) FetchPaymentRequestList(appCtx appcontext.AppContext, officeUserID uuid.UUID, params *services.FetchPaymentRequestListParams) (*models.PaymentRequests, int, error) { ret := _m.Called(appCtx, officeUserID, params) diff --git a/pkg/services/payment_request.go b/pkg/services/payment_request.go index ae7e345dc94..329c3dc29e2 100644 --- a/pkg/services/payment_request.go +++ b/pkg/services/payment_request.go @@ -38,6 +38,7 @@ type PaymentRequestShipmentRecalculator interface { type PaymentRequestListFetcher interface { FetchPaymentRequestList(appCtx appcontext.AppContext, officeUserID uuid.UUID, params *FetchPaymentRequestListParams) (*models.PaymentRequests, int, error) FetchPaymentRequestListByMove(appCtx appcontext.AppContext, locator string) (*models.PaymentRequests, error) + CheckAndRemovePaymentRequestAssignedUser(appCtx appcontext.AppContext, id uuid.UUID) (bool, error) } // PaymentRequestFetcher is the exported interface for fetching a payment request diff --git a/pkg/services/payment_request/payment_request_list_fetcher.go b/pkg/services/payment_request/payment_request_list_fetcher.go index 11f0c52805c..8c3b6841529 100644 --- a/pkg/services/payment_request/payment_request_list_fetcher.go +++ b/pkg/services/payment_request/payment_request_list_fetcher.go @@ -17,6 +17,7 @@ import ( ) type paymentRequestListFetcher struct { + services.MoveAssignedOfficeUserUpdater } var parameters = map[string]string{ @@ -221,6 +222,48 @@ func (f *paymentRequestListFetcher) FetchPaymentRequestListByMove(appCtx appcont return &paymentRequests, nil } +// rename function +func (f *paymentRequestListFetcher) CheckAndRemovePaymentRequestAssignedUser(appCtx appcontext.AppContext, id uuid.UUID) (bool, error) { + // ---------------------- Combine into one query - to only hit DB once ----------------------------- + move := models.Move{} + + err := appCtx.DB().Q().Eager( + "SignedCertifications", + "Orders.ServiceMember", + "Orders.UploadedAmendedOrders", + "CloseoutOffice", + "LockedByOfficeUser", + "AdditionalDocuments", + "AdditionalDocuments.UserUploads", + "CounselingOffice", + ).Where("show = TRUE").Find(&move, id) + if err != nil { + return true, err + } + paymentRequests, err := f.FetchPaymentRequestListByMove(appCtx, move.Locator) + // ---------------------- Combine into one query - to only hit DB once ----------------------------- + + paymentRequestNeedingReview := false + for _, request := range *paymentRequests { + if request.Status != models.PaymentRequestStatusReviewed && + request.Status != models.PaymentRequestStatusReviewedAllRejected { + paymentRequestNeedingReview = true + break + } + } + + // ---------------------- Add to handler struct ----------------------------- + // f.wer.DeleteAssignedOfficeUser(appCtx, id, roles.RoleTypeTIO) + // pr2, err := f.MoveAssignedOfficeUserUpdater.DeleteAssignedOfficeUser(appCtx, id, roles.RoleTypeTIO) + // if err != nil { + // return true, err + // } + // fmt.Println(pr2) + // ---------------------- Add to handler struct ----------------------------- + + return paymentRequestNeedingReview, err //only returning a bool because i cannot get DeleteAssignedOfficeUser to work in here +} + // fetchEDIErrorsForPaymentRequest returns the edi_error with the most recent created_at date for a payment request func fetchEDIErrorsForPaymentRequest(appCtx appcontext.AppContext, pr *models.PaymentRequest) (models.EdiError, error) { From 9b11c9da085c7666bdec1a6bcb5a73cc620e60b1 Mon Sep 17 00:00:00 2001 From: Paul Stonebraker Date: Fri, 20 Dec 2024 16:20:41 +0000 Subject: [PATCH 30/51] trying something new with service --- pkg/handlers/ghcapi/payment_request.go | 17 +------- .../mocks/PaymentRequestStatusUpdater.go | 30 +++++++++++++ pkg/services/payment_request.go | 1 + .../payment_request_status_updater.go | 42 +++++++++++++++++++ 4 files changed, 74 insertions(+), 16 deletions(-) diff --git a/pkg/handlers/ghcapi/payment_request.go b/pkg/handlers/ghcapi/payment_request.go index 21c9ae38bc6..9aa7fb1522c 100644 --- a/pkg/handlers/ghcapi/payment_request.go +++ b/pkg/handlers/ghcapi/payment_request.go @@ -18,7 +18,6 @@ import ( "github.com/transcom/mymove/pkg/handlers" "github.com/transcom/mymove/pkg/handlers/ghcapi/internal/payloads" "github.com/transcom/mymove/pkg/models" - "github.com/transcom/mymove/pkg/models/roles" "github.com/transcom/mymove/pkg/services" "github.com/transcom/mymove/pkg/services/audit" "github.com/transcom/mymove/pkg/services/event" @@ -184,7 +183,7 @@ func (h UpdatePaymentRequestStatusHandler) Handle( } // And now let's save our updated model object using the PaymentRequestUpdater service object. - updatedPaymentRequest, err := h.PaymentRequestStatusUpdater.UpdatePaymentRequestStatus( + updatedPaymentRequest, err := h.PaymentRequestStatusUpdater.UpdatePaymentRequestStatusAndCheckAssignment( appCtx, &existingPaymentRequest, params.IfMatch, @@ -222,20 +221,6 @@ func (h UpdatePaymentRequestStatusHandler) Handle( return paymentrequestop.NewGetPaymentRequestInternalServerError(), err } - paymnetRequest, err := h.PaymentRequestListFetcher.CheckAndRemovePaymentRequestAssignedUser(appCtx, existingPaymentRequest.MoveTaskOrderID) - if err != nil { - return paymentrequestop.NewUpdatePaymentRequestStatusInternalServerError(), err - } - // ---------------------- Move to Service (in progress) ----------------------------- - if !paymnetRequest { - _, err := h.MoveAssignedOfficeUserUpdater.DeleteAssignedOfficeUser(appCtx, existingPaymentRequest.MoveTaskOrderID, roles.RoleTypeTIO) - if err != nil { - return paymentrequestop.NewUpdatePaymentRequestStatusInternalServerError(), err - } - returnPayload.MoveTaskOrder.TIOAssignedUser = nil - } - // ---------------------- Move to Service (in progress) ----------------------------- - return paymentrequestop.NewUpdatePaymentRequestStatusOK().WithPayload(returnPayload), nil }) } diff --git a/pkg/services/mocks/PaymentRequestStatusUpdater.go b/pkg/services/mocks/PaymentRequestStatusUpdater.go index bd6542d2199..1e5ec4f94c2 100644 --- a/pkg/services/mocks/PaymentRequestStatusUpdater.go +++ b/pkg/services/mocks/PaymentRequestStatusUpdater.go @@ -44,6 +44,36 @@ func (_m *PaymentRequestStatusUpdater) UpdatePaymentRequestStatus(appCtx appcont return r0, r1 } +// UpdatePaymentRequestStatusAndCheckAssignment provides a mock function with given fields: appCtx, paymentRequest, eTag +func (_m *PaymentRequestStatusUpdater) UpdatePaymentRequestStatusAndCheckAssignment(appCtx appcontext.AppContext, paymentRequest *models.PaymentRequest, eTag string) (*models.PaymentRequest, error) { + ret := _m.Called(appCtx, paymentRequest, eTag) + + if len(ret) == 0 { + panic("no return value specified for UpdatePaymentRequestStatusAndCheckAssignment") + } + + var r0 *models.PaymentRequest + var r1 error + if rf, ok := ret.Get(0).(func(appcontext.AppContext, *models.PaymentRequest, string) (*models.PaymentRequest, error)); ok { + return rf(appCtx, paymentRequest, eTag) + } + if rf, ok := ret.Get(0).(func(appcontext.AppContext, *models.PaymentRequest, string) *models.PaymentRequest); ok { + r0 = rf(appCtx, paymentRequest, eTag) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*models.PaymentRequest) + } + } + + if rf, ok := ret.Get(1).(func(appcontext.AppContext, *models.PaymentRequest, string) error); ok { + r1 = rf(appCtx, paymentRequest, eTag) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + // NewPaymentRequestStatusUpdater creates a new instance of PaymentRequestStatusUpdater. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. // The first argument is typically a *testing.T value. func NewPaymentRequestStatusUpdater(t interface { diff --git a/pkg/services/payment_request.go b/pkg/services/payment_request.go index 329c3dc29e2..7c676dd4d2f 100644 --- a/pkg/services/payment_request.go +++ b/pkg/services/payment_request.go @@ -60,6 +60,7 @@ type PaymentRequestReviewedFetcher interface { //go:generate mockery --name PaymentRequestStatusUpdater type PaymentRequestStatusUpdater interface { UpdatePaymentRequestStatus(appCtx appcontext.AppContext, paymentRequest *models.PaymentRequest, eTag string) (*models.PaymentRequest, error) + UpdatePaymentRequestStatusAndCheckAssignment(appCtx appcontext.AppContext, paymentRequest *models.PaymentRequest, eTag string) (*models.PaymentRequest, error) } // PaymentRequestUploadCreator is the exported interface for creating a payment request upload diff --git a/pkg/services/payment_request/payment_request_status_updater.go b/pkg/services/payment_request/payment_request_status_updater.go index 5bc9f04c030..0f8a38c9e82 100644 --- a/pkg/services/payment_request/payment_request_status_updater.go +++ b/pkg/services/payment_request/payment_request_status_updater.go @@ -8,7 +8,9 @@ import ( "github.com/transcom/mymove/pkg/appcontext" "github.com/transcom/mymove/pkg/apperror" "github.com/transcom/mymove/pkg/models" + "github.com/transcom/mymove/pkg/models/roles" "github.com/transcom/mymove/pkg/services" + moveservice "github.com/transcom/mymove/pkg/services/move" "github.com/transcom/mymove/pkg/services/query" ) @@ -76,3 +78,43 @@ func (p *paymentRequestStatusUpdater) UpdatePaymentRequestStatus(appCtx appconte return paymentRequest, err } + +func (p *paymentRequestStatusUpdater) UpdatePaymentRequestStatusAndCheckAssignment(appCtx appcontext.AppContext, paymentRequest *models.PaymentRequest, eTag string) (*models.PaymentRequest, error) { + paymentRequests := models.PaymentRequests{} + updatedPaymentRequest, err := p.UpdatePaymentRequestStatus(appCtx, paymentRequest, eTag) + if err != nil { + return nil, err + } + // check error + moveID := updatedPaymentRequest.MoveTaskOrderID + + err = appCtx.DB().Q().InnerJoin("moves", "payment_requests.move_id = moves.id").Where("moves.id = ?", moveID).All(&paymentRequests) + // check error + paymentRequestNeedingReview := false + for _, request := range paymentRequests { + if request.Status != models.PaymentRequestStatusReviewed && + request.Status != models.PaymentRequestStatusReviewedAllRejected { + paymentRequestNeedingReview = true + break + } + } + // move := updatedPaymentRequest.MoveTaskOrder + if !paymentRequestNeedingReview { + _, err := moveservice.AssignedOfficeUserUpdater.DeleteAssignedOfficeUser(moveservice.AssignedOfficeUserUpdater{}, appCtx, moveID, roles.RoleTypeTIO) + if err != nil { + return nil, err + } + // move.TIOAssignedID = nil + // move.TIOAssignedUser = nil + + // verrs, err := appCtx.DB().ValidateAndUpdate(&move) + // if err != nil || verrs.HasAny() { + // return nil, apperror.NewInvalidInputError(move.ID, err, verrs, "") + // } + + updatedPaymentRequest.MoveTaskOrder.TIOAssignedID = nil + updatedPaymentRequest.MoveTaskOrder.TIOAssignedUser = nil + } + + return updatedPaymentRequest, err +} From bab025e2c0501c0517f4707b69d06276d1c0666e Mon Sep 17 00:00:00 2001 From: Jon Spight Date: Fri, 20 Dec 2024 20:42:59 +0000 Subject: [PATCH 31/51] Updated Service --- pkg/handlers/ghcapi/payment_request.go | 2 +- pkg/handlers/ghcapi/payment_request_test.go | 39 ------------- pkg/services/payment_request.go | 1 - .../payment_request_status_updater.go | 58 +++++++------------ .../payment_request_status_updater_test.go | 38 ++++++++++++ 5 files changed, 61 insertions(+), 77 deletions(-) diff --git a/pkg/handlers/ghcapi/payment_request.go b/pkg/handlers/ghcapi/payment_request.go index 9aa7fb1522c..31b730e3455 100644 --- a/pkg/handlers/ghcapi/payment_request.go +++ b/pkg/handlers/ghcapi/payment_request.go @@ -183,7 +183,7 @@ func (h UpdatePaymentRequestStatusHandler) Handle( } // And now let's save our updated model object using the PaymentRequestUpdater service object. - updatedPaymentRequest, err := h.PaymentRequestStatusUpdater.UpdatePaymentRequestStatusAndCheckAssignment( + updatedPaymentRequest, err := h.PaymentRequestStatusUpdater.UpdatePaymentRequestStatus( appCtx, &existingPaymentRequest, params.IfMatch, diff --git a/pkg/handlers/ghcapi/payment_request_test.go b/pkg/handlers/ghcapi/payment_request_test.go index d0a905ba8de..a796768e9d1 100644 --- a/pkg/handlers/ghcapi/payment_request_test.go +++ b/pkg/handlers/ghcapi/payment_request_test.go @@ -259,45 +259,6 @@ func (suite *HandlerSuite) TestUpdatePaymentRequestStatusHandler() { } statusUpdater := paymentrequest.NewPaymentRequestStatusUpdater(query.NewQueryBuilder()) - suite.Run("successful status update payment request and remove assigned user", func() { - officeUser := setupTestData() - pendingPaymentRequest := factory.BuildPaymentRequest(suite.DB(), []factory.Customization{ - { - Model: officeUser, - LinkOnly: true, - Type: &factory.OfficeUsers.TIOAssignedUser, - }, - }, nil) - - suite.NotNil(pendingPaymentRequest.MoveTaskOrder.TIOAssignedID) - - paymentRequestFetcher := &mocks.PaymentRequestFetcher{} - paymentRequestFetcher.On("FetchPaymentRequest", mock.AnythingOfType("*appcontext.appContext"), - mock.Anything).Return(pendingPaymentRequest, nil).Once() - - req := httptest.NewRequest("PATCH", fmt.Sprintf("/payment_request/%s/status", pendingPaymentRequest.ID), nil) - req = suite.AuthenticateOfficeRequest(req, officeUser) - - params := paymentrequestop.UpdatePaymentRequestStatusParams{ - HTTPRequest: req, - Body: &ghcmessages.UpdatePaymentRequestStatusPayload{Status: "REVIEWED", RejectionReason: nil, ETag: etag.GenerateEtag(pendingPaymentRequest.UpdatedAt)}, - PaymentRequestID: strfmt.UUID(pendingPaymentRequest.ID.String()), - } - - handler := UpdatePaymentRequestStatusHandler{ - HandlerConfig: suite.HandlerConfig(), - PaymentRequestStatusUpdater: statusUpdater, - PaymentRequestFetcher: paymentRequestFetcher, - PaymentRequestListFetcher: paymentrequest.NewPaymentRequestListFetcher(), - MoveAssignedOfficeUserUpdater: move.AssignedOfficeUserUpdater{}, - } - - response := handler.Handle(params) - - payload := response.(*paymentrequestop.UpdatePaymentRequestStatusOK).Payload - suite.NotNil(payload.ReviewedAt) - suite.Nil(payload.MoveTaskOrder.TIOAssignedUser) - }) suite.Run("successful status update of payment request", func() { officeUser := setupTestData() pendingPaymentRequest := factory.BuildPaymentRequest(suite.DB(), nil, nil) diff --git a/pkg/services/payment_request.go b/pkg/services/payment_request.go index 7c676dd4d2f..329c3dc29e2 100644 --- a/pkg/services/payment_request.go +++ b/pkg/services/payment_request.go @@ -60,7 +60,6 @@ type PaymentRequestReviewedFetcher interface { //go:generate mockery --name PaymentRequestStatusUpdater type PaymentRequestStatusUpdater interface { UpdatePaymentRequestStatus(appCtx appcontext.AppContext, paymentRequest *models.PaymentRequest, eTag string) (*models.PaymentRequest, error) - UpdatePaymentRequestStatusAndCheckAssignment(appCtx appcontext.AppContext, paymentRequest *models.PaymentRequest, eTag string) (*models.PaymentRequest, error) } // PaymentRequestUploadCreator is the exported interface for creating a payment request upload diff --git a/pkg/services/payment_request/payment_request_status_updater.go b/pkg/services/payment_request/payment_request_status_updater.go index 0f8a38c9e82..8ed84b5479c 100644 --- a/pkg/services/payment_request/payment_request_status_updater.go +++ b/pkg/services/payment_request/payment_request_status_updater.go @@ -50,6 +50,9 @@ func (p *paymentRequestStatusUpdater) UpdatePaymentRequestStatus(appCtx appconte } } + paymentRequests := models.PaymentRequests{} + moveID := paymentRequest.MoveTaskOrderID + var verrs *validate.Errors var err error if eTag == "" { @@ -62,34 +65,11 @@ func (p *paymentRequestStatusUpdater) UpdatePaymentRequestStatus(appCtx appconte return nil, apperror.NewInvalidInputError(id, err, verrs, "") } - if err != nil { - switch err.(type) { - case query.StaleIdentifierError: - return &models.PaymentRequest{}, apperror.NewPreconditionFailedError(id, err) - } - - switch err { - case sql.ErrNoRows: - return nil, apperror.NewNotFoundError(id, "") - default: - return nil, apperror.NewQueryError("PaymentRequest", err, "") - } + Qerr := appCtx.DB().Q().InnerJoin("moves", "payment_requests.move_id = moves.id").Where("moves.id = ?", moveID).All(&paymentRequests) + if Qerr != nil { + return nil, Qerr } - return paymentRequest, err -} - -func (p *paymentRequestStatusUpdater) UpdatePaymentRequestStatusAndCheckAssignment(appCtx appcontext.AppContext, paymentRequest *models.PaymentRequest, eTag string) (*models.PaymentRequest, error) { - paymentRequests := models.PaymentRequests{} - updatedPaymentRequest, err := p.UpdatePaymentRequestStatus(appCtx, paymentRequest, eTag) - if err != nil { - return nil, err - } - // check error - moveID := updatedPaymentRequest.MoveTaskOrderID - - err = appCtx.DB().Q().InnerJoin("moves", "payment_requests.move_id = moves.id").Where("moves.id = ?", moveID).All(&paymentRequests) - // check error paymentRequestNeedingReview := false for _, request := range paymentRequests { if request.Status != models.PaymentRequestStatusReviewed && @@ -98,23 +78,29 @@ func (p *paymentRequestStatusUpdater) UpdatePaymentRequestStatusAndCheckAssignme break } } - // move := updatedPaymentRequest.MoveTaskOrder + if !paymentRequestNeedingReview { _, err := moveservice.AssignedOfficeUserUpdater.DeleteAssignedOfficeUser(moveservice.AssignedOfficeUserUpdater{}, appCtx, moveID, roles.RoleTypeTIO) if err != nil { return nil, err } - // move.TIOAssignedID = nil - // move.TIOAssignedUser = nil + paymentRequest.MoveTaskOrder.TIOAssignedID = nil + paymentRequest.MoveTaskOrder.TIOAssignedUser = nil + } - // verrs, err := appCtx.DB().ValidateAndUpdate(&move) - // if err != nil || verrs.HasAny() { - // return nil, apperror.NewInvalidInputError(move.ID, err, verrs, "") - // } + if err != nil { + switch err.(type) { + case query.StaleIdentifierError: + return &models.PaymentRequest{}, apperror.NewPreconditionFailedError(id, err) + } - updatedPaymentRequest.MoveTaskOrder.TIOAssignedID = nil - updatedPaymentRequest.MoveTaskOrder.TIOAssignedUser = nil + switch err { + case sql.ErrNoRows: + return nil, apperror.NewNotFoundError(id, "") + default: + return nil, apperror.NewQueryError("PaymentRequest", err, "") + } } - return updatedPaymentRequest, err + return paymentRequest, err } diff --git a/pkg/services/payment_request/payment_request_status_updater_test.go b/pkg/services/payment_request/payment_request_status_updater_test.go index 178f4437437..9a7aef38fc7 100644 --- a/pkg/services/payment_request/payment_request_status_updater_test.go +++ b/pkg/services/payment_request/payment_request_status_updater_test.go @@ -7,12 +7,50 @@ import ( "github.com/transcom/mymove/pkg/etag" "github.com/transcom/mymove/pkg/factory" "github.com/transcom/mymove/pkg/models" + "github.com/transcom/mymove/pkg/models/roles" "github.com/transcom/mymove/pkg/services/query" "github.com/transcom/mymove/pkg/unit" ) func (suite *PaymentRequestServiceSuite) TestUpdatePaymentRequestStatus() { builder := query.NewQueryBuilder() + suite.Run("If we get a payment request pointer with a status it should update and return no ", func() { + setupTestData := func() models.OfficeUser { + transportationOffice := factory.BuildTransportationOffice(suite.DB(), []factory.Customization{ + { + Model: models.TransportationOffice{ + ProvidesCloseout: true, + }, + }, + }, nil) + + officeUser := factory.BuildOfficeUserWithRoles(suite.DB(), []factory.Customization{ + { + Model: transportationOffice, + LinkOnly: true, + Type: &factory.TransportationOffices.CloseoutOffice, + }, + }, []roles.RoleType{roles.RoleTypeTIO}) + + return officeUser + } + officeUser := setupTestData() + paymentRequest := factory.BuildPaymentRequest(suite.DB(), []factory.Customization{ + { + Model: officeUser, + LinkOnly: true, + Type: &factory.OfficeUsers.TIOAssignedUser, + }, + }, nil) + + paymentRequest.Status = models.PaymentRequestStatusReviewed + updater := NewPaymentRequestStatusUpdater(builder) + updatedPr, err := updater.UpdatePaymentRequestStatus(suite.AppContextForTest(), &paymentRequest, etag.GenerateEtag(paymentRequest.UpdatedAt)) + + suite.NoError(err) + suite.Nil(updatedPr.MoveTaskOrder.TIOAssignedID) + suite.Nil(updatedPr.MoveTaskOrder.TIOAssignedUser) + }) suite.Run("If we get a payment request pointer with a status it should update and return no error", func() { paymentRequest := factory.BuildPaymentRequest(suite.DB(), nil, nil) From 81aa903c4b01daf48ffd694c28c1e6a292c2a591 Mon Sep 17 00:00:00 2001 From: Jon Spight Date: Fri, 20 Dec 2024 21:59:57 +0000 Subject: [PATCH 32/51] updated mocks --- .../mocks/PaymentRequestStatusUpdater.go | 30 ------------------- 1 file changed, 30 deletions(-) diff --git a/pkg/services/mocks/PaymentRequestStatusUpdater.go b/pkg/services/mocks/PaymentRequestStatusUpdater.go index 1e5ec4f94c2..bd6542d2199 100644 --- a/pkg/services/mocks/PaymentRequestStatusUpdater.go +++ b/pkg/services/mocks/PaymentRequestStatusUpdater.go @@ -44,36 +44,6 @@ func (_m *PaymentRequestStatusUpdater) UpdatePaymentRequestStatus(appCtx appcont return r0, r1 } -// UpdatePaymentRequestStatusAndCheckAssignment provides a mock function with given fields: appCtx, paymentRequest, eTag -func (_m *PaymentRequestStatusUpdater) UpdatePaymentRequestStatusAndCheckAssignment(appCtx appcontext.AppContext, paymentRequest *models.PaymentRequest, eTag string) (*models.PaymentRequest, error) { - ret := _m.Called(appCtx, paymentRequest, eTag) - - if len(ret) == 0 { - panic("no return value specified for UpdatePaymentRequestStatusAndCheckAssignment") - } - - var r0 *models.PaymentRequest - var r1 error - if rf, ok := ret.Get(0).(func(appcontext.AppContext, *models.PaymentRequest, string) (*models.PaymentRequest, error)); ok { - return rf(appCtx, paymentRequest, eTag) - } - if rf, ok := ret.Get(0).(func(appcontext.AppContext, *models.PaymentRequest, string) *models.PaymentRequest); ok { - r0 = rf(appCtx, paymentRequest, eTag) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*models.PaymentRequest) - } - } - - if rf, ok := ret.Get(1).(func(appcontext.AppContext, *models.PaymentRequest, string) error); ok { - r1 = rf(appCtx, paymentRequest, eTag) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - // NewPaymentRequestStatusUpdater creates a new instance of PaymentRequestStatusUpdater. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. // The first argument is typically a *testing.T value. func NewPaymentRequestStatusUpdater(t interface { From 26ba792683c0dc9337eed78b1711f58f394f6bfa Mon Sep 17 00:00:00 2001 From: loganwc Date: Mon, 23 Dec 2024 16:15:46 +0000 Subject: [PATCH 33/51] moved test from create to form --- .../Shipment/PrimeUIShipmentCreate.test.jsx | 63 ---------------- .../PrimeUIShipmentCreateForm.test.jsx | 75 ++++++++++++++++++- 2 files changed, 74 insertions(+), 64 deletions(-) diff --git a/src/pages/PrimeUI/Shipment/PrimeUIShipmentCreate.test.jsx b/src/pages/PrimeUI/Shipment/PrimeUIShipmentCreate.test.jsx index fd49eff9b16..7d3d732c89c 100644 --- a/src/pages/PrimeUI/Shipment/PrimeUIShipmentCreate.test.jsx +++ b/src/pages/PrimeUI/Shipment/PrimeUIShipmentCreate.test.jsx @@ -221,66 +221,3 @@ describe('Create Mobile Home', () => { }); }); }); - -describe('When creating shipment', () => { - it('disabling 2nd/3rd address clears out the data', async () => { - createPrimeMTOShipmentV3.mockReturnValue({}); - - render(mockedComponent); - - waitFor(async () => { - await userEvent.selectOptions(screen.getByLabelText('Shipment type'), 'HHG'); - - // Start controlled test case to verify everything is working. - let input = await document.querySelector('input[name="pickupAddress.streetAddress1"]'); - expect(input).toBeInTheDocument(); - // enter required street 1 for pickup - await userEvent.type(input, '123 Street'); - - const secondAddressToggle = document.querySelector('[data-testid="has-secondary-pickup"]'); - expect(secondAddressToggle).toBeInTheDocument(); - await userEvent.click(secondAddressToggle); - - input = await document.querySelector('input[name="secondaryPickupAddress.streetAddress1"]'); - expect(input).toBeInTheDocument(); - // enter required street 1 for pickup 2 - await userEvent.type(input, '123 Street 2'); - - const thirdAddressToggle = document.querySelector('[data-testid="has-tertiary-pickup"]'); - expect(thirdAddressToggle).toBeInTheDocument(); - await userEvent.click(thirdAddressToggle); - - input = await document.querySelector('input[name="tertiaryPickupAddress.streetAddress1"]'); - expect(input).toBeInTheDocument(); - // enter required street 1 for pickup 2 - await userEvent.type(input, '123 Street 3'); - - const disable3rdAddressToggle = document.querySelector('[data-testid="no-tertiary-pickup"]'); - expect(disable3rdAddressToggle).toBeInTheDocument(); - await userEvent.click(disable3rdAddressToggle); - - const disable2ndAddressToggle = document.querySelector('[data-testid="no-secondary-pickup"]'); - expect(disable2ndAddressToggle).toBeInTheDocument(); - await userEvent.click(disable2ndAddressToggle); - - input = await document.querySelector('input[name="destinationAddress.streetAddress1"]'); - expect(input).toBeInTheDocument(); - // enter something - await userEvent.type(input, '123 Street'); - - const saveButton = await screen.getByRole('button', { name: 'Save' }); - - expect(saveButton).not.toBeDisabled(); - await userEvent.click(saveButton); - - await waitFor(() => { - expect(createPrimeMTOShipmentV3).toHaveBeenCalledWith( - expect.objectContaining({ - secondaryPickupAddress: {}, - tertiaryPickupAddress: {}, - }), - ); - }); - }); - }); -}); diff --git a/src/pages/PrimeUI/Shipment/PrimeUIShipmentCreateForm.test.jsx b/src/pages/PrimeUI/Shipment/PrimeUIShipmentCreateForm.test.jsx index 80ea98a6f8a..833caf7e17a 100644 --- a/src/pages/PrimeUI/Shipment/PrimeUIShipmentCreateForm.test.jsx +++ b/src/pages/PrimeUI/Shipment/PrimeUIShipmentCreateForm.test.jsx @@ -181,7 +181,7 @@ function renderShipmentCreateForm(props) { jest.mock('utils/featureFlags', () => ({ ...jest.requireActual('utils/featureFlags'), - isBooleanFlagEnabled: jest.fn().mockImplementation(() => Promise.resolve(false)), + isBooleanFlagEnabled: jest.fn().mockImplementation(() => Promise.resolve()), })); const mockNavigate = jest.fn(); @@ -493,4 +493,77 @@ describe('PrimeUIShipmentCreateForm', () => { // now the text input should be invisible expect(await screen.queryByTestId('divertedFromShipmentIdInput')).toBeNull(); }); + + it.each( + ['BOAT_HAUL_AWAY', 'BOAT_TOW_AWAY', 'MOBILE_HOME'], + 'when creating a %s clears 2nd/3rd address fields when secondary/tertiary checkbox is unchecked', + async (shipmentType) => { + // isBooleanFlagEnabled.mockImplementation(() => Promise.resolve(false)); // Allow for testing of boats and mobile homes + isBooleanFlagEnabled.mockResolvedValue(true); + + const shipmentTypeInput = await screen.findByLabelText('Shipment type'); + expect(shipmentTypeInput).toBeInTheDocument(); + + // Select the boat or mobile home shipment type + await userEvent.selectOptions(shipmentTypeInput, [shipmentType]); + + // Make sure that a PPM-specific field is not visible. + expect(await screen.queryByLabelText('Expected Departure Date')).not.toBeInTheDocument(); + + // Check for usual HHG fields + expect(await screen.findByRole('heading', { name: 'Diversion', level: 2 })).toBeInTheDocument(); + expect(await screen.findByLabelText('Diversion')).not.toBeChecked(); + + // Checking to make sure the text box isn't shown prior to clicking the box + expect(screen.queryByTestId('divertedFromShipmentIdInput')).toBeNull(); + + // Check the diversion box + const diversionCheckbox = await screen.findByLabelText('Diversion'); + await userEvent.click(diversionCheckbox); + + // now the text input should be visible + expect(await screen.findByTestId('divertedFromShipmentIdInput')).toBeInTheDocument(); + + // Now check for a boat and mobile home shipment specific field + expect(await screen.findByLabelText('Length (Feet)')).toBeVisible(); + + let input = await document.querySelector('input[name="pickupAddress.streetAddress1"]'); + expect(input).toBeInTheDocument(); + // enter required street 1 for pickup + await userEvent.type(input, '123 Pickup Street'); + + const secondAddressToggle = document.querySelector('[data-testid="has-secondary-pickup"]'); + expect(secondAddressToggle).toBeInTheDocument(); + await userEvent.click(secondAddressToggle); + + input = await document.querySelector('input[name="secondaryPickupAddress.streetAddress1"]'); + expect(input).toBeInTheDocument(); + // enter required street 1 for pickup 2 + await userEvent.type(input, '123 Pickup Street 2'); + + const thirdAddressToggle = document.querySelector('[data-testid="has-tertiary-pickup"]'); + expect(thirdAddressToggle).toBeInTheDocument(); + await userEvent.click(thirdAddressToggle); + + input = await document.querySelector('input[name="tertiaryPickupAddress.streetAddress1"]'); + expect(input).toBeInTheDocument(); + // enter required street 1 for pickup 2 + await userEvent.type(input, '123 Pickup Street 3'); + + const disable3rdAddressToggle = document.querySelector('[data-testid="no-tertiary-pickup"]'); + expect(disable3rdAddressToggle).toBeInTheDocument(); + await userEvent.click(disable3rdAddressToggle); + + const disable2ndAddressToggle = document.querySelector('[data-testid="no-secondary-pickup"]'); + expect(disable2ndAddressToggle).toBeInTheDocument(); + await userEvent.click(disable2ndAddressToggle); + + expect(input).not.toBeInTheDocument(); + + input = await document.querySelector('input[name="destinationAddress.streetAddress1"]'); + expect(input).toBeInTheDocument(); + // enter something + await userEvent.type(input, '123 destination Street'); + }, + ); }); From 2bd0fd268eaef53939a04f341f41bb59f84b4579 Mon Sep 17 00:00:00 2001 From: loganwc Date: Mon, 23 Dec 2024 16:20:41 +0000 Subject: [PATCH 34/51] removed comment --- src/pages/PrimeUI/Shipment/PrimeUIShipmentCreateForm.test.jsx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/pages/PrimeUI/Shipment/PrimeUIShipmentCreateForm.test.jsx b/src/pages/PrimeUI/Shipment/PrimeUIShipmentCreateForm.test.jsx index 833caf7e17a..8d82913f8c8 100644 --- a/src/pages/PrimeUI/Shipment/PrimeUIShipmentCreateForm.test.jsx +++ b/src/pages/PrimeUI/Shipment/PrimeUIShipmentCreateForm.test.jsx @@ -498,7 +498,6 @@ describe('PrimeUIShipmentCreateForm', () => { ['BOAT_HAUL_AWAY', 'BOAT_TOW_AWAY', 'MOBILE_HOME'], 'when creating a %s clears 2nd/3rd address fields when secondary/tertiary checkbox is unchecked', async (shipmentType) => { - // isBooleanFlagEnabled.mockImplementation(() => Promise.resolve(false)); // Allow for testing of boats and mobile homes isBooleanFlagEnabled.mockResolvedValue(true); const shipmentTypeInput = await screen.findByLabelText('Shipment type'); From 108e8de831863b9e78078ad4455611e2688b4d15 Mon Sep 17 00:00:00 2001 From: Jon Spight Date: Mon, 23 Dec 2024 16:39:09 +0000 Subject: [PATCH 35/51] Removed old code --- .../mocks/PaymentRequestListFetcher.go | 28 ------------- pkg/services/payment_request.go | 1 - .../payment_request_list_fetcher.go | 42 ------------------- 3 files changed, 71 deletions(-) diff --git a/pkg/services/mocks/PaymentRequestListFetcher.go b/pkg/services/mocks/PaymentRequestListFetcher.go index f88b128b1ab..ebb611a7872 100644 --- a/pkg/services/mocks/PaymentRequestListFetcher.go +++ b/pkg/services/mocks/PaymentRequestListFetcher.go @@ -18,34 +18,6 @@ type PaymentRequestListFetcher struct { mock.Mock } -// CheckAndRemovePaymentRequestAssignedUser provides a mock function with given fields: appCtx, id -func (_m *PaymentRequestListFetcher) CheckAndRemovePaymentRequestAssignedUser(appCtx appcontext.AppContext, id uuid.UUID) (bool, error) { - ret := _m.Called(appCtx, id) - - if len(ret) == 0 { - panic("no return value specified for CheckAndRemovePaymentRequestAssignedUser") - } - - var r0 bool - var r1 error - if rf, ok := ret.Get(0).(func(appcontext.AppContext, uuid.UUID) (bool, error)); ok { - return rf(appCtx, id) - } - if rf, ok := ret.Get(0).(func(appcontext.AppContext, uuid.UUID) bool); ok { - r0 = rf(appCtx, id) - } else { - r0 = ret.Get(0).(bool) - } - - if rf, ok := ret.Get(1).(func(appcontext.AppContext, uuid.UUID) error); ok { - r1 = rf(appCtx, id) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - // FetchPaymentRequestList provides a mock function with given fields: appCtx, officeUserID, params func (_m *PaymentRequestListFetcher) FetchPaymentRequestList(appCtx appcontext.AppContext, officeUserID uuid.UUID, params *services.FetchPaymentRequestListParams) (*models.PaymentRequests, int, error) { ret := _m.Called(appCtx, officeUserID, params) diff --git a/pkg/services/payment_request.go b/pkg/services/payment_request.go index 329c3dc29e2..ae7e345dc94 100644 --- a/pkg/services/payment_request.go +++ b/pkg/services/payment_request.go @@ -38,7 +38,6 @@ type PaymentRequestShipmentRecalculator interface { type PaymentRequestListFetcher interface { FetchPaymentRequestList(appCtx appcontext.AppContext, officeUserID uuid.UUID, params *FetchPaymentRequestListParams) (*models.PaymentRequests, int, error) FetchPaymentRequestListByMove(appCtx appcontext.AppContext, locator string) (*models.PaymentRequests, error) - CheckAndRemovePaymentRequestAssignedUser(appCtx appcontext.AppContext, id uuid.UUID) (bool, error) } // PaymentRequestFetcher is the exported interface for fetching a payment request diff --git a/pkg/services/payment_request/payment_request_list_fetcher.go b/pkg/services/payment_request/payment_request_list_fetcher.go index 8c3b6841529..e47e71cd0dd 100644 --- a/pkg/services/payment_request/payment_request_list_fetcher.go +++ b/pkg/services/payment_request/payment_request_list_fetcher.go @@ -222,48 +222,6 @@ func (f *paymentRequestListFetcher) FetchPaymentRequestListByMove(appCtx appcont return &paymentRequests, nil } -// rename function -func (f *paymentRequestListFetcher) CheckAndRemovePaymentRequestAssignedUser(appCtx appcontext.AppContext, id uuid.UUID) (bool, error) { - // ---------------------- Combine into one query - to only hit DB once ----------------------------- - move := models.Move{} - - err := appCtx.DB().Q().Eager( - "SignedCertifications", - "Orders.ServiceMember", - "Orders.UploadedAmendedOrders", - "CloseoutOffice", - "LockedByOfficeUser", - "AdditionalDocuments", - "AdditionalDocuments.UserUploads", - "CounselingOffice", - ).Where("show = TRUE").Find(&move, id) - if err != nil { - return true, err - } - paymentRequests, err := f.FetchPaymentRequestListByMove(appCtx, move.Locator) - // ---------------------- Combine into one query - to only hit DB once ----------------------------- - - paymentRequestNeedingReview := false - for _, request := range *paymentRequests { - if request.Status != models.PaymentRequestStatusReviewed && - request.Status != models.PaymentRequestStatusReviewedAllRejected { - paymentRequestNeedingReview = true - break - } - } - - // ---------------------- Add to handler struct ----------------------------- - // f.wer.DeleteAssignedOfficeUser(appCtx, id, roles.RoleTypeTIO) - // pr2, err := f.MoveAssignedOfficeUserUpdater.DeleteAssignedOfficeUser(appCtx, id, roles.RoleTypeTIO) - // if err != nil { - // return true, err - // } - // fmt.Println(pr2) - // ---------------------- Add to handler struct ----------------------------- - - return paymentRequestNeedingReview, err //only returning a bool because i cannot get DeleteAssignedOfficeUser to work in here -} - // fetchEDIErrorsForPaymentRequest returns the edi_error with the most recent created_at date for a payment request func fetchEDIErrorsForPaymentRequest(appCtx appcontext.AppContext, pr *models.PaymentRequest) (models.EdiError, error) { From d9ca18ce0e4e6288875b0486db8ae6e3033db705 Mon Sep 17 00:00:00 2001 From: Jon Spight Date: Mon, 23 Dec 2024 20:45:30 +0000 Subject: [PATCH 36/51] fixed files --- pkg/handlers/ghcapi/api.go | 1 - pkg/handlers/ghcapi/payment_request.go | 1 - pkg/handlers/ghcapi/payment_request_test.go | 3 --- pkg/services/payment_request/payment_request_list_fetcher.go | 1 - .../payment_request/payment_request_status_updater_test.go | 2 +- 5 files changed, 1 insertion(+), 7 deletions(-) diff --git a/pkg/handlers/ghcapi/api.go b/pkg/handlers/ghcapi/api.go index ca33cea1dce..de147cc5eb8 100644 --- a/pkg/handlers/ghcapi/api.go +++ b/pkg/handlers/ghcapi/api.go @@ -270,7 +270,6 @@ func NewGhcAPIHandler(handlerConfig handlers.HandlerConfig) *ghcops.MymoveAPI { HandlerConfig: handlerConfig, PaymentRequestStatusUpdater: paymentrequest.NewPaymentRequestStatusUpdater(queryBuilder), PaymentRequestFetcher: paymentrequest.NewPaymentRequestFetcher(), - PaymentRequestListFetcher: paymentrequest.NewPaymentRequestListFetcher(), MoveAssignedOfficeUserUpdater: move.NewAssignedOfficeUserUpdater(move.NewMoveFetcher()), } diff --git a/pkg/handlers/ghcapi/payment_request.go b/pkg/handlers/ghcapi/payment_request.go index 31b730e3455..fe30a27a192 100644 --- a/pkg/handlers/ghcapi/payment_request.go +++ b/pkg/handlers/ghcapi/payment_request.go @@ -114,7 +114,6 @@ type UpdatePaymentRequestStatusHandler struct { handlers.HandlerConfig services.PaymentRequestStatusUpdater services.PaymentRequestFetcher - services.PaymentRequestListFetcher services.MoveAssignedOfficeUserUpdater } diff --git a/pkg/handlers/ghcapi/payment_request_test.go b/pkg/handlers/ghcapi/payment_request_test.go index a796768e9d1..6109d90e2a5 100644 --- a/pkg/handlers/ghcapi/payment_request_test.go +++ b/pkg/handlers/ghcapi/payment_request_test.go @@ -280,7 +280,6 @@ func (suite *HandlerSuite) TestUpdatePaymentRequestStatusHandler() { HandlerConfig: suite.HandlerConfig(), PaymentRequestStatusUpdater: statusUpdater, PaymentRequestFetcher: paymentRequestFetcher, - PaymentRequestListFetcher: paymentrequest.NewPaymentRequestListFetcher(), MoveAssignedOfficeUserUpdater: move.AssignedOfficeUserUpdater{}, } @@ -320,7 +319,6 @@ func (suite *HandlerSuite) TestUpdatePaymentRequestStatusHandler() { HandlerConfig: suite.HandlerConfig(), PaymentRequestStatusUpdater: statusUpdater, PaymentRequestFetcher: paymentRequestFetcher, - PaymentRequestListFetcher: paymentrequest.NewPaymentRequestListFetcher(), MoveAssignedOfficeUserUpdater: move.AssignedOfficeUserUpdater{}, } @@ -419,7 +417,6 @@ func (suite *HandlerSuite) TestUpdatePaymentRequestStatusHandler() { HandlerConfig: suite.HandlerConfig(), PaymentRequestStatusUpdater: paymentRequestStatusUpdater, PaymentRequestFetcher: paymentRequestFetcher, - PaymentRequestListFetcher: paymentrequest.NewPaymentRequestListFetcher(), } // Validate incoming payload diff --git a/pkg/services/payment_request/payment_request_list_fetcher.go b/pkg/services/payment_request/payment_request_list_fetcher.go index e47e71cd0dd..11f0c52805c 100644 --- a/pkg/services/payment_request/payment_request_list_fetcher.go +++ b/pkg/services/payment_request/payment_request_list_fetcher.go @@ -17,7 +17,6 @@ import ( ) type paymentRequestListFetcher struct { - services.MoveAssignedOfficeUserUpdater } var parameters = map[string]string{ diff --git a/pkg/services/payment_request/payment_request_status_updater_test.go b/pkg/services/payment_request/payment_request_status_updater_test.go index 9a7aef38fc7..8ca36ccf5d0 100644 --- a/pkg/services/payment_request/payment_request_status_updater_test.go +++ b/pkg/services/payment_request/payment_request_status_updater_test.go @@ -14,7 +14,7 @@ import ( func (suite *PaymentRequestServiceSuite) TestUpdatePaymentRequestStatus() { builder := query.NewQueryBuilder() - suite.Run("If we get a payment request pointer with a status it should update and return no ", func() { + suite.Run("When the last payment request is updated remove the assigend user.", func() { setupTestData := func() models.OfficeUser { transportationOffice := factory.BuildTransportationOffice(suite.DB(), []factory.Customization{ { From 416d9e8eb4e50e38f68a2f32c0ed26c1c94bae86 Mon Sep 17 00:00:00 2001 From: Jon Spight Date: Mon, 23 Dec 2024 22:07:47 +0000 Subject: [PATCH 37/51] Added SC and TOO test cases --- .../move_task_order_updater_test.go | 94 +++++++++++++++++++ 1 file changed, 94 insertions(+) diff --git a/pkg/services/move_task_order/move_task_order_updater_test.go b/pkg/services/move_task_order/move_task_order_updater_test.go index bd1e001e494..70e64840772 100644 --- a/pkg/services/move_task_order/move_task_order_updater_test.go +++ b/pkg/services/move_task_order/move_task_order_updater_test.go @@ -12,6 +12,7 @@ import ( "github.com/transcom/mymove/pkg/etag" "github.com/transcom/mymove/pkg/factory" "github.com/transcom/mymove/pkg/models" + "github.com/transcom/mymove/pkg/models/roles" routemocks "github.com/transcom/mymove/pkg/route/mocks" "github.com/transcom/mymove/pkg/services" "github.com/transcom/mymove/pkg/services/ghcrateengine" @@ -29,6 +30,26 @@ func (suite *MoveTaskOrderServiceSuite) TestMoveTaskOrderUpdater_UpdateStatusSer queryBuilder := query.NewQueryBuilder() planner := &routemocks.Planner{} ppmEstimator := &mocks.PPMEstimator{} + setupTestData := func() models.OfficeUser { + + transportationOffice := factory.BuildTransportationOffice(suite.DB(), []factory.Customization{ + { + Model: models.TransportationOffice{ + ProvidesCloseout: true, + }, + }, + }, nil) + + officeUser := factory.BuildOfficeUserWithRoles(suite.DB(), []factory.Customization{ + { + Model: transportationOffice, + LinkOnly: true, + Type: &factory.TransportationOffices.CloseoutOffice, + }, + }, []roles.RoleType{roles.RoleTypeServicesCounselor}) + + return officeUser + } setUpSignedCertificationCreatorMock := func(returnValue ...interface{}) services.SignedCertificationCreator { mockCreator := &mocks.SignedCertificationCreator{} @@ -66,6 +87,32 @@ func (suite *MoveTaskOrderServiceSuite) TestMoveTaskOrderUpdater_UpdateStatusSer moveRouter, setUpSignedCertificationCreatorMock(nil, nil), setUpSignedCertificationUpdaterMock(nil, nil), ppmEstimator, ) + suite.Run("Makes move available to Prime and Removes assigned TOO office user", func() { + session := suite.AppContextWithSessionForTest(&auth.Session{ + ApplicationName: auth.OfficeApp, + OfficeUserID: uuid.Must(uuid.NewV4()), + }) + + officeUser := setupTestData() + move := factory.BuildMoveWithShipment(suite.DB(), []factory.Customization{ + { + Model: models.Move{ + Status: models.MoveStatusNeedsServiceCounseling, + }, + }, + { + Model: officeUser, + LinkOnly: true, + Type: &factory.OfficeUsers.SCAssignedUser, + }, + }, nil) + + eTag := etag.GenerateEtag(move.UpdatedAt) + + actualMTO, err := mtoUpdater.UpdateStatusServiceCounselingCompleted(session, move.ID, eTag) + suite.NoError(err) + suite.Nil(actualMTO.SCAssignedID) + }) suite.Run("Move status is updated successfully (with HHG shipment)", func() { session := suite.AppContextWithSessionForTest(&auth.Session{ ApplicationName: auth.OfficeApp, @@ -650,6 +697,27 @@ func (suite *MoveTaskOrderServiceSuite) TestMoveTaskOrderUpdater_ShowHide() { func (suite *MoveTaskOrderServiceSuite) TestMoveTaskOrderUpdater_MakeAvailableToPrime() { ppmEstimator := &mocks.PPMEstimator{} + setupTestData := func() models.OfficeUser { + + transportationOffice := factory.BuildTransportationOffice(suite.DB(), []factory.Customization{ + { + Model: models.TransportationOffice{ + ProvidesCloseout: true, + }, + }, + }, nil) + + officeUser := factory.BuildOfficeUserWithRoles(suite.DB(), []factory.Customization{ + { + Model: transportationOffice, + LinkOnly: true, + Type: &factory.TransportationOffices.CloseoutOffice, + }, + }, []roles.RoleType{roles.RoleTypeTIO}) + + return officeUser + } + setUpSignedCertificationCreatorMock := func(returnValue ...interface{}) services.SignedCertificationCreator { mockCreator := &mocks.SignedCertificationCreator{} @@ -783,6 +851,32 @@ func (suite *MoveTaskOrderServiceSuite) TestMoveTaskOrderUpdater_MakeAvailableTo suite.NotNil(fetchedMove.ApprovedAt) suite.Equal(models.MoveStatusAPPROVED, fetchedMove.Status) }) + suite.Run("Makes move available to Prime and Removes assigned TOO office user", func() { + queryBuilder := query.NewQueryBuilder() + moveRouter := moverouter.NewMoveRouter() + planner := &routemocks.Planner{} + planner.On("ZipTransitDistance", + mock.AnythingOfType("*appcontext.appContext"), + mock.Anything, + mock.Anything, + ).Return(400, nil) + officeUser := setupTestData() + move := factory.BuildApprovalsRequestedMove(suite.DB(), []factory.Customization{ + { + Model: officeUser, + LinkOnly: true, + Type: &factory.OfficeUsers.TOOAssignedUser, + }, + }, nil) + + serviceItemCreator := mtoserviceitem.NewMTOServiceItemCreator(planner, queryBuilder, moveRouter, ghcrateengine.NewDomesticUnpackPricer(), ghcrateengine.NewDomesticPackPricer(), ghcrateengine.NewDomesticLinehaulPricer(), ghcrateengine.NewDomesticShorthaulPricer(), ghcrateengine.NewDomesticOriginPricer(), ghcrateengine.NewDomesticDestinationPricer(), ghcrateengine.NewFuelSurchargePricer()) + mtoUpdater := mt.NewMoveTaskOrderUpdater(queryBuilder, serviceItemCreator, moveRouter, setUpSignedCertificationCreatorMock(nil, nil), setUpSignedCertificationUpdaterMock(nil, nil), ppmEstimator) + eTag := etag.GenerateEtag(move.UpdatedAt) + updatedMove, err := mtoUpdater.MakeAvailableToPrime(suite.AppContextForTest(), move.ID, eTag, false, false) + + suite.NoError(err) + suite.Nil(updatedMove.TOOAssignedID) + }) suite.Run("Makes move available to Prime and only creates Move management when it's the only one specified", func() { queryBuilder := query.NewQueryBuilder() From 09ad1ed3b617f644b8f466ca0110d3203b1aca76 Mon Sep 17 00:00:00 2001 From: Jon Spight Date: Tue, 24 Dec 2024 18:00:25 +0000 Subject: [PATCH 38/51] PR changes --- pkg/handlers/ghcapi/api.go | 7 +++---- pkg/handlers/ghcapi/payment_request.go | 1 - pkg/handlers/ghcapi/payment_request_test.go | 15 ++++++--------- pkg/models/move.go | 5 +---- 4 files changed, 10 insertions(+), 18 deletions(-) diff --git a/pkg/handlers/ghcapi/api.go b/pkg/handlers/ghcapi/api.go index de147cc5eb8..5edc3f7e3ee 100644 --- a/pkg/handlers/ghcapi/api.go +++ b/pkg/handlers/ghcapi/api.go @@ -267,10 +267,9 @@ func NewGhcAPIHandler(handlerConfig handlers.HandlerConfig) *ghcops.MymoveAPI { } ghcAPI.PaymentRequestsUpdatePaymentRequestStatusHandler = UpdatePaymentRequestStatusHandler{ - HandlerConfig: handlerConfig, - PaymentRequestStatusUpdater: paymentrequest.NewPaymentRequestStatusUpdater(queryBuilder), - PaymentRequestFetcher: paymentrequest.NewPaymentRequestFetcher(), - MoveAssignedOfficeUserUpdater: move.NewAssignedOfficeUserUpdater(move.NewMoveFetcher()), + HandlerConfig: handlerConfig, + PaymentRequestStatusUpdater: paymentrequest.NewPaymentRequestStatusUpdater(queryBuilder), + PaymentRequestFetcher: paymentrequest.NewPaymentRequestFetcher(), } ghcAPI.PaymentServiceItemUpdatePaymentServiceItemStatusHandler = UpdatePaymentServiceItemStatusHandler{ diff --git a/pkg/handlers/ghcapi/payment_request.go b/pkg/handlers/ghcapi/payment_request.go index fe30a27a192..622d38b1abc 100644 --- a/pkg/handlers/ghcapi/payment_request.go +++ b/pkg/handlers/ghcapi/payment_request.go @@ -114,7 +114,6 @@ type UpdatePaymentRequestStatusHandler struct { handlers.HandlerConfig services.PaymentRequestStatusUpdater services.PaymentRequestFetcher - services.MoveAssignedOfficeUserUpdater } // Handle updates payment requests status diff --git a/pkg/handlers/ghcapi/payment_request_test.go b/pkg/handlers/ghcapi/payment_request_test.go index 6109d90e2a5..17136806724 100644 --- a/pkg/handlers/ghcapi/payment_request_test.go +++ b/pkg/handlers/ghcapi/payment_request_test.go @@ -18,7 +18,6 @@ import ( "github.com/transcom/mymove/pkg/models" "github.com/transcom/mymove/pkg/models/roles" "github.com/transcom/mymove/pkg/services/mocks" - "github.com/transcom/mymove/pkg/services/move" paymentrequest "github.com/transcom/mymove/pkg/services/payment_request" "github.com/transcom/mymove/pkg/services/query" "github.com/transcom/mymove/pkg/trace" @@ -277,10 +276,9 @@ func (suite *HandlerSuite) TestUpdatePaymentRequestStatusHandler() { } handler := UpdatePaymentRequestStatusHandler{ - HandlerConfig: suite.HandlerConfig(), - PaymentRequestStatusUpdater: statusUpdater, - PaymentRequestFetcher: paymentRequestFetcher, - MoveAssignedOfficeUserUpdater: move.AssignedOfficeUserUpdater{}, + HandlerConfig: suite.HandlerConfig(), + PaymentRequestStatusUpdater: statusUpdater, + PaymentRequestFetcher: paymentRequestFetcher, } // Validate incoming payload @@ -316,10 +314,9 @@ func (suite *HandlerSuite) TestUpdatePaymentRequestStatusHandler() { } handler := UpdatePaymentRequestStatusHandler{ - HandlerConfig: suite.HandlerConfig(), - PaymentRequestStatusUpdater: statusUpdater, - PaymentRequestFetcher: paymentRequestFetcher, - MoveAssignedOfficeUserUpdater: move.AssignedOfficeUserUpdater{}, + HandlerConfig: suite.HandlerConfig(), + PaymentRequestStatusUpdater: statusUpdater, + PaymentRequestFetcher: paymentRequestFetcher, } // Validate incoming payload diff --git a/pkg/models/move.go b/pkg/models/move.go index f3aefca3e51..b523638c997 100644 --- a/pkg/models/move.go +++ b/pkg/models/move.go @@ -417,10 +417,7 @@ func SaveMoveDependencies(db *pop.Connection, move *Move) (*validate.Errors, err // the move service item's status. func FetchMoveByMoveIDWithServiceItems(db *pop.Connection, moveID uuid.UUID) (Move, error) { var move Move - err := db.Q().Eager( - "MTOServiceItems", - "MTOServiceItems.Status", - ).Where("show = TRUE").Find(&move, moveID) + err := db.Q().Eager().Where("show = TRUE").Find(&move, moveID) if err != nil { if errors.Cause(err).Error() == RecordNotFoundErrorString { From ad255d99ef504a7db5979c4220f5e0c9d4f28cbe Mon Sep 17 00:00:00 2001 From: loganwc Date: Thu, 26 Dec 2024 16:46:19 +0000 Subject: [PATCH 39/51] do the create tests for mobile home and boats --- .../Shipment/PrimeUIShipmentCreate.test.jsx | 73 ++++++++++--------- 1 file changed, 38 insertions(+), 35 deletions(-) diff --git a/src/pages/PrimeUI/Shipment/PrimeUIShipmentCreate.test.jsx b/src/pages/PrimeUI/Shipment/PrimeUIShipmentCreate.test.jsx index 7d3d732c89c..0198675ae53 100644 --- a/src/pages/PrimeUI/Shipment/PrimeUIShipmentCreate.test.jsx +++ b/src/pages/PrimeUI/Shipment/PrimeUIShipmentCreate.test.jsx @@ -173,51 +173,54 @@ describe('Create PPM', () => { }); describe('Create Mobile Home', () => { - it('test with 2nd and 3rd addresses', async () => { - createPrimeMTOShipmentV3.mockReturnValue({}); + it.each(['MOBILE_HOME', 'BOAT_TOW_AWAY', 'BOAT_HAUL_AWAY'])( + 'test with 2nd and 3rd addresses', + async (shipmentType) => { + createPrimeMTOShipmentV3.mockReturnValue({}); - render(mockedComponent); + render(mockedComponent); - waitFor(async () => { - await userEvent.selectOptions(screen.getByLabelText('Shipment type'), 'MOBILE_HOME'); + waitFor(async () => { + await userEvent.selectOptions(screen.getByLabelText('Shipment type'), shipmentType); - // Start controlled test case to verify everything is working. - let input = await document.querySelector('input[name="pickupAddress.streetAddress1"]'); - expect(input).toBeInTheDocument(); - // enter required street 1 for pickup - await userEvent.type(input, '123 Street'); + // Start controlled test case to verify everything is working. + let input = await document.querySelector('input[name="pickupAddress.streetAddress1"]'); + expect(input).toBeInTheDocument(); + // enter required street 1 for pickup + await userEvent.type(input, '123 Street'); - const secondAddressToggle = document.querySelector('[data-testid="has-secondary-pickup"]'); - expect(secondAddressToggle).toBeInTheDocument(); - await userEvent.click(secondAddressToggle); + const secondAddressToggle = document.querySelector('[data-testid="has-secondary-pickup"]'); + expect(secondAddressToggle).toBeInTheDocument(); + await userEvent.click(secondAddressToggle); - input = await document.querySelector('input[name="secondaryPickupAddress.streetAddress1"]'); - expect(input).toBeInTheDocument(); - // enter required street 1 for pickup 2 - await userEvent.type(input, '123 Street 2'); + input = await document.querySelector('input[name="secondaryPickupAddress.streetAddress1"]'); + expect(input).toBeInTheDocument(); + // enter required street 1 for pickup 2 + await userEvent.type(input, '123 Street 2'); - const thirdAddressToggle = document.querySelector('[data-testid="has-tertiary-pickup"]'); - expect(thirdAddressToggle).toBeInTheDocument(); - await userEvent.click(thirdAddressToggle); + const thirdAddressToggle = document.querySelector('[data-testid="has-tertiary-pickup"]'); + expect(thirdAddressToggle).toBeInTheDocument(); + await userEvent.click(thirdAddressToggle); - input = await document.querySelector('input[name="tertiaryPickupAddress.streetAddress1"]'); - expect(input).toBeInTheDocument(); - // enter required street 1 for pickup 2 - await userEvent.type(input, '123 Street 3'); + input = await document.querySelector('input[name="tertiaryPickupAddress.streetAddress1"]'); + expect(input).toBeInTheDocument(); + // enter required street 1 for pickup 2 + await userEvent.type(input, '123 Street 3'); - input = await document.querySelector('input[name="destinationAddress.streetAddress1"]'); - expect(input).toBeInTheDocument(); - // enter something - await userEvent.type(input, '123 Street'); + input = await document.querySelector('input[name="destinationAddress.streetAddress1"]'); + expect(input).toBeInTheDocument(); + // enter something + await userEvent.type(input, '123 Street'); - const saveButton = await screen.getByRole('button', { name: 'Save' }); + const saveButton = await screen.getByRole('button', { name: 'Save' }); - expect(saveButton).not.toBeDisabled(); - await userEvent.click(saveButton); + expect(saveButton).not.toBeDisabled(); + await userEvent.click(saveButton); - await waitFor(() => { - expect(mockNavigate).toHaveBeenCalledWith(moveDetailsURL); + await waitFor(() => { + expect(mockNavigate).toHaveBeenCalledWith(moveDetailsURL); + }); }); - }); - }); + }, + ); }); From 67500e13417d3e5601159ff12675d6c4dd791e44 Mon Sep 17 00:00:00 2001 From: loganwc Date: Thu, 26 Dec 2024 20:34:07 +0000 Subject: [PATCH 40/51] moved ff check out of form --- .../Shipment/PrimeUIShipmentCreate.jsx | 18 +- .../Shipment/PrimeUIShipmentCreate.test.jsx | 245 ++++++++++++++++-- .../Shipment/PrimeUIShipmentCreateForm.jsx | 18 +- .../PrimeUIShipmentCreateForm.test.jsx | 74 +----- 4 files changed, 247 insertions(+), 108 deletions(-) diff --git a/src/pages/PrimeUI/Shipment/PrimeUIShipmentCreate.jsx b/src/pages/PrimeUI/Shipment/PrimeUIShipmentCreate.jsx index c265b67e98c..9dae219dfbc 100644 --- a/src/pages/PrimeUI/Shipment/PrimeUIShipmentCreate.jsx +++ b/src/pages/PrimeUI/Shipment/PrimeUIShipmentCreate.jsx @@ -1,4 +1,4 @@ -import React, { useState } from 'react'; +import React, { useEffect, useState } from 'react'; import { Formik } from 'formik'; import * as Yup from 'yup'; import { useNavigate, useParams, generatePath } from 'react-router-dom'; @@ -21,13 +21,23 @@ import { setFlashMessage as setFlashMessageAction } from 'store/flash/actions'; import { requiredAddressSchema, partialRequiredAddressSchema } from 'utils/validation'; import PrimeUIShipmentCreateForm from 'pages/PrimeUI/Shipment/PrimeUIShipmentCreateForm'; import { OptionalAddressSchema } from 'components/Customer/MtoShipmentForm/validationSchemas'; -import { SHIPMENT_OPTIONS, SHIPMENT_TYPES } from 'shared/constants'; +import { FEATURE_FLAG_KEYS, SHIPMENT_OPTIONS, SHIPMENT_TYPES } from 'shared/constants'; +import { isBooleanFlagEnabled } from 'utils/featureFlags'; const PrimeUIShipmentCreate = ({ setFlashMessage }) => { const [errorMessage, setErrorMessage] = useState(); const { moveCodeOrID } = useParams(); const navigate = useNavigate(); - + const [enableBoat, setEnableBoat] = useState(false); + const [enableMobileHome, setEnableMobileHome] = useState(false); + + useEffect(() => { + const fetchData = async () => { + setEnableBoat(await isBooleanFlagEnabled(FEATURE_FLAG_KEYS.BOAT)); + setEnableMobileHome(await isBooleanFlagEnabled(FEATURE_FLAG_KEYS.MOBILE_HOME)); + }; + fetchData(); + }, []); const handleClose = () => { navigate(generatePath(primeSimulatorRoutes.VIEW_MOVE_PATH, { moveCodeOrID })); }; @@ -676,7 +686,7 @@ const PrimeUIShipmentCreate = ({ setFlashMessage }) => { {({ isValid, isSubmitting, handleSubmit }) => { return (
- +
({ jest.mock('utils/featureFlags', () => ({ ...jest.requireActual('utils/featureFlags'), - isBooleanFlagEnabled: jest.fn().mockImplementation(() => Promise.resolve(false)), + isBooleanFlagEnabled: jest.fn().mockImplementation(() => Promise.resolve(true)), })); const moveDetailsURL = generatePath(primeSimulatorRoutes.VIEW_MOVE_PATH, { moveCodeOrID: moveId }); +const initialValues = { + shipmentType: '', + + // PPM + counselorRemarks: '', + ppmShipment: { + expectedDepartureDate: '', + sitExpected: false, + sitLocation: '', + sitEstimatedWeight: '', + sitEstimatedEntryDate: '', + sitEstimatedDepartureDate: '', + estimatedWeight: '', + hasProGear: false, + proGearWeight: '', + spouseProGearWeight: '', + pickupAddress: { + city: '', + postalCode: '', + state: '', + streetAddress1: '', + }, + destinationAddress: { + city: '', + postalCode: '', + state: '', + streetAddress1: '', + }, + secondaryDeliveryAddress: { + city: '', + postalCode: '', + state: '', + streetAddress1: '', + }, + secondaryPickupAddress: { + city: '', + postalCode: '', + state: '', + streetAddress1: '', + }, + tertiaryDeliveryAddress: { + city: '', + postalCode: '', + state: '', + streetAddress1: '', + }, + tertiaryPickupAddress: { + city: '', + postalCode: '', + state: '', + streetAddress1: '', + }, + hasSecondaryPickupAddress: 'false', + hasSecondaryDestinationAddress: 'false', + hasTertiaryPickupAddress: 'false', + hasTertiaryDestinationAddress: 'false', + }, + + // Boat Shipment + boatShipment: { + make: 'make', + model: 'model', + year: 1999, + hasTrailer: true, + isRoadworthy: true, + lengthInFeet: 16, + lengthInInches: 0, + widthInFeet: 1, + widthInInches: 1, + heightInFeet: 1, + heightInInches: 1, + }, + + // Mobile Home Shipment + mobileHomeShipment: { + make: 'mobile make', + model: 'mobile model', + year: 1999, + lengthInFeet: 16, + lengthInInches: 0, + widthInFeet: 1, + widthInInches: 1, + heightInFeet: 1, + heightInInches: 1, + }, + + // Other shipment types + requestedPickupDate: '', + estimatedWeight: '', + pickupAddress: {}, + destinationAddress: {}, + secondaryDeliveryAddress: { + city: '', + postalCode: '', + state: '', + streetAddress1: '', + }, + secondaryPickupAddress: { + city: '', + postalCode: '', + state: '', + streetAddress1: '', + }, + tertiaryDeliveryAddress: { + city: '', + postalCode: '', + state: '', + streetAddress1: '', + }, + tertiaryPickupAddress: { + city: '', + postalCode: '', + state: '', + streetAddress1: '', + }, + hasSecondaryPickupAddress: 'false', + hasSecondaryDestinationAddress: 'false', + hasTertiaryPickupAddress: 'false', + hasTertiaryDestinationAddress: 'false', + diversion: '', + divertedFromShipmentId: '', +}; + const mockedComponent = ( - + + + + + ); @@ -145,7 +274,7 @@ describe('Create PPM', () => { await userEvent.selectOptions(screen.getByLabelText('Shipment type'), 'PPM'); // Start controlled test case to verify everything is working. - let input = await document.querySelector('input[name="ppmShipment.pickupAddress.streetAddress1"]'); + let input = await document.querySelector('input[name=ppmShipment.pickupAddress.streetAddress1]'); expect(input).toBeInTheDocument(); // enter required street 1 for pickup await userEvent.type(input, '123 Street'); @@ -159,7 +288,7 @@ describe('Create PPM', () => { await userEvent.type(input, '123 Street'); // Verify destination address street 1 is OPTIONAL. - input = await document.querySelector('input[name="ppmShipment.destinationAddress.streetAddress1"]'); + input = await document.querySelector('input[name=ppmShipment.destinationAddress.streetAddress1]'); expect(input).toBeInTheDocument(); // enter something await userEvent.type(input, '123 Street'); @@ -174,21 +303,51 @@ describe('Create PPM', () => { describe('Create Mobile Home', () => { it.each(['MOBILE_HOME', 'BOAT_TOW_AWAY', 'BOAT_HAUL_AWAY'])( - 'test with 2nd and 3rd addresses', + 'resets secondary and tertiary addresses when flags are not true for shipment type %s', async (shipmentType) => { + isBooleanFlagEnabled.mockImplementation(() => Promise.resolve(true)); createPrimeMTOShipmentV3.mockReturnValue({}); + // Render the component render(mockedComponent); + // Wait for the component to load waitFor(async () => { + expect(screen.getByLabelText('Shipment type')).toBeInTheDocument(); + + // Select shipment type await userEvent.selectOptions(screen.getByLabelText('Shipment type'), shipmentType); - // Start controlled test case to verify everything is working. - let input = await document.querySelector('input[name="pickupAddress.streetAddress1"]'); + await userEvent.type(screen.getByLabelText('Requested pickup'), '01 Nov 2020'); + + // Fill in required pickup and destination addresses + let input = document.querySelector('input[name=pickupAddress.streetAddress1]'); expect(input).toBeInTheDocument(); - // enter required street 1 for pickup await userEvent.type(input, '123 Street'); + input = document.querySelector('input[name=pickupAddress.city]'); + expect(input).toBeInTheDocument(); + await userEvent.type(input, 'Folsom'); + input = document.querySelector('input[name=pickupAddress.state]'); + expect(input).toBeInTheDocument(); + await userEvent.type(input, 'CA'); + input = document.querySelector('input[name=pickupAddress.postalCode]'); + expect(input).toBeInTheDocument(); + await userEvent.type(input, '95630'); + + input = document.querySelector('input[name=destinationAddress.streetAddress1]'); + expect(input).toBeInTheDocument(); + await userEvent.type(input, '456 Destination St'); + input = document.querySelector('input[name=destinationAddress.city]'); + expect(input).toBeInTheDocument(); + await userEvent.type(input, 'Bevy Hills'); + input = document.querySelector('input[name=destinationAddress.state]'); + expect(input).toBeInTheDocument(); + await userEvent.type(input, 'CA'); + input = document.querySelector('input[name=destinationAddress.postalCode]'); + expect(input).toBeInTheDocument(); + await userEvent.type(input, '90210'); + // Enable and disable secondary and tertiary toggles const secondAddressToggle = document.querySelector('[data-testid="has-secondary-pickup"]'); expect(secondAddressToggle).toBeInTheDocument(); await userEvent.click(secondAddressToggle); @@ -196,7 +355,7 @@ describe('Create Mobile Home', () => { input = await document.querySelector('input[name="secondaryPickupAddress.streetAddress1"]'); expect(input).toBeInTheDocument(); // enter required street 1 for pickup 2 - await userEvent.type(input, '123 Street 2'); + await userEvent.type(input, '123 Pickup Street 2'); const thirdAddressToggle = document.querySelector('[data-testid="has-tertiary-pickup"]'); expect(thirdAddressToggle).toBeInTheDocument(); @@ -205,20 +364,74 @@ describe('Create Mobile Home', () => { input = await document.querySelector('input[name="tertiaryPickupAddress.streetAddress1"]'); expect(input).toBeInTheDocument(); // enter required street 1 for pickup 2 - await userEvent.type(input, '123 Street 3'); + await userEvent.type(input, '123 Pickup Street 3'); - input = await document.querySelector('input[name="destinationAddress.streetAddress1"]'); + const disable2ndAddressToggle = document.querySelector('[data-testid="no-secondary-pickup"]'); + expect(disable2ndAddressToggle).toBeInTheDocument(); + await userEvent.click(disable2ndAddressToggle); + + // input boat/mobile home model info + input = document.createElement('input[label="Year"]'); expect(input).toBeInTheDocument(); - // enter something - await userEvent.type(input, '123 Street'); + await userEvent.type(input, '2023'); - const saveButton = await screen.getByRole('button', { name: 'Save' }); + input = document.createElement('input[label="Make"]'); + expect(input).toBeInTheDocument(); + await userEvent.type(input, 'Genesis'); + + input = document.createElement('input[label="Model"]'); + expect(input).toBeInTheDocument(); + await userEvent.type(input, 'G70'); + + // input boat/mobile home dimensions + input = document.createElement('input[label="Length (Feet)"]'); + expect(input).toBeInTheDocument(); + await userEvent.type(input, '10'); + + input = document.createElement('input[label="Length (Inches)"]'); + expect(input).toBeInTheDocument(); + await userEvent.type(input, '10'); + + input = document.createElement('input[label="Width (Feet)"]'); + expect(input).toBeInTheDocument(); + await userEvent.type(input, '10'); + + input = document.createElement('input[label="Width (Inches)"]'); + expect(input).toBeInTheDocument(); + await userEvent.type(input, '10'); + + input = document.createElement('input[label="Height (Feet)"]'); + expect(input).toBeInTheDocument(); + await userEvent.type(input, '10'); + + input = document.createElement('input[label="Height (Inches)"]'); + expect(input).toBeInTheDocument(); + await userEvent.type(input, '10'); + // Submit the form + const saveButton = screen.getByRole('button', { name: 'Save' }); expect(saveButton).not.toBeDisabled(); await userEvent.click(saveButton); - await waitFor(() => { - expect(mockNavigate).toHaveBeenCalledWith(moveDetailsURL); + // Verify that API call resets addresses when flags are not 'true' + expect(createPrimeMTOShipmentV3).toHaveBeenCalledWith({ + body: expect.objectContaining({ + destinationAddress: null, + diversion: null, + divertedFromShipmentId: null, + hasSecondaryDestinationAddress: false, + hasSecondaryPickupAddress: false, + hasTertiaryDestinationAddress: false, + hasTertiaryPickupAddress: false, + secondaryDestinationAddress: {}, + secondaryPickupAddress: {}, + tertiaryDestinationAddress: {}, + tertiaryPickupAddress: {}, + moveTaskOrderID: '9c7b255c-2981-4bf8-839f-61c7458e2b4d', + pickupAddress: null, + primeEstimatedWeight: null, + requestedPickupDate: null, + }), }); }); }, diff --git a/src/pages/PrimeUI/Shipment/PrimeUIShipmentCreateForm.jsx b/src/pages/PrimeUI/Shipment/PrimeUIShipmentCreateForm.jsx index 3f70fb3fb53..22fd5f366df 100644 --- a/src/pages/PrimeUI/Shipment/PrimeUIShipmentCreateForm.jsx +++ b/src/pages/PrimeUI/Shipment/PrimeUIShipmentCreateForm.jsx @@ -1,10 +1,8 @@ -import React, { useState, useEffect } from 'react'; +import React, { useState } from 'react'; import { Radio, FormGroup, Label, Textarea } from '@trussworks/react-uswds'; import { Field, useField, useFormikContext } from 'formik'; -import { isBooleanFlagEnabled } from '../../../utils/featureFlags'; - -import { SHIPMENT_OPTIONS, SHIPMENT_TYPES, FEATURE_FLAG_KEYS } from 'shared/constants'; +import { SHIPMENT_OPTIONS, SHIPMENT_TYPES } from 'shared/constants'; import { CheckboxField, DatePickerInput, DropdownInput } from 'components/form/fields'; import MaskedTextField from 'components/form/fields/MaskedTextField/MaskedTextField'; import styles from 'components/Office/CustomerContactInfoForm/CustomerContactInfoForm.module.scss'; @@ -17,7 +15,7 @@ import { LOCATION_TYPES } from 'types/sitStatusShape'; const sitLocationOptions = dropdownInputOptions(LOCATION_TYPES); -const PrimeUIShipmentCreateForm = () => { +const PrimeUIShipmentCreateForm = ({ enableBoat, enableMobileHome }) => { const { values } = useFormikContext(); const { shipmentType } = values; const { sitExpected, hasProGear } = values.ppmShipment; @@ -25,8 +23,6 @@ const PrimeUIShipmentCreateForm = () => { const [, , checkBoxHelperProps] = useField('diversion'); const [, , divertedFromIdHelperProps] = useField('divertedFromShipmentId'); const [isChecked, setIsChecked] = useState(false); - const [enableBoat, setEnableBoat] = useState(false); - const [enableMobileHome, setEnableMobileHome] = useState(false); const hasShipmentType = !!shipmentType; const isPPM = shipmentType === SHIPMENT_OPTIONS.PPM; @@ -80,14 +76,6 @@ const PrimeUIShipmentCreateForm = () => { return undefined; }; - useEffect(() => { - const fetchData = async () => { - setEnableBoat(await isBooleanFlagEnabled(FEATURE_FLAG_KEYS.BOAT)); - setEnableMobileHome(await isBooleanFlagEnabled(FEATURE_FLAG_KEYS.MOBILE_HOME)); - }; - fetchData(); - }, []); - let shipmentTypeOptions = Object.values(SHIPMENT_TYPES).map((value) => ({ key: value, value })); if (!enableBoat) { // Disallow the Prime from choosing Boat shipments if the feature flag is not enabled diff --git a/src/pages/PrimeUI/Shipment/PrimeUIShipmentCreateForm.test.jsx b/src/pages/PrimeUI/Shipment/PrimeUIShipmentCreateForm.test.jsx index 8d82913f8c8..80ea98a6f8a 100644 --- a/src/pages/PrimeUI/Shipment/PrimeUIShipmentCreateForm.test.jsx +++ b/src/pages/PrimeUI/Shipment/PrimeUIShipmentCreateForm.test.jsx @@ -181,7 +181,7 @@ function renderShipmentCreateForm(props) { jest.mock('utils/featureFlags', () => ({ ...jest.requireActual('utils/featureFlags'), - isBooleanFlagEnabled: jest.fn().mockImplementation(() => Promise.resolve()), + isBooleanFlagEnabled: jest.fn().mockImplementation(() => Promise.resolve(false)), })); const mockNavigate = jest.fn(); @@ -493,76 +493,4 @@ describe('PrimeUIShipmentCreateForm', () => { // now the text input should be invisible expect(await screen.queryByTestId('divertedFromShipmentIdInput')).toBeNull(); }); - - it.each( - ['BOAT_HAUL_AWAY', 'BOAT_TOW_AWAY', 'MOBILE_HOME'], - 'when creating a %s clears 2nd/3rd address fields when secondary/tertiary checkbox is unchecked', - async (shipmentType) => { - isBooleanFlagEnabled.mockResolvedValue(true); - - const shipmentTypeInput = await screen.findByLabelText('Shipment type'); - expect(shipmentTypeInput).toBeInTheDocument(); - - // Select the boat or mobile home shipment type - await userEvent.selectOptions(shipmentTypeInput, [shipmentType]); - - // Make sure that a PPM-specific field is not visible. - expect(await screen.queryByLabelText('Expected Departure Date')).not.toBeInTheDocument(); - - // Check for usual HHG fields - expect(await screen.findByRole('heading', { name: 'Diversion', level: 2 })).toBeInTheDocument(); - expect(await screen.findByLabelText('Diversion')).not.toBeChecked(); - - // Checking to make sure the text box isn't shown prior to clicking the box - expect(screen.queryByTestId('divertedFromShipmentIdInput')).toBeNull(); - - // Check the diversion box - const diversionCheckbox = await screen.findByLabelText('Diversion'); - await userEvent.click(diversionCheckbox); - - // now the text input should be visible - expect(await screen.findByTestId('divertedFromShipmentIdInput')).toBeInTheDocument(); - - // Now check for a boat and mobile home shipment specific field - expect(await screen.findByLabelText('Length (Feet)')).toBeVisible(); - - let input = await document.querySelector('input[name="pickupAddress.streetAddress1"]'); - expect(input).toBeInTheDocument(); - // enter required street 1 for pickup - await userEvent.type(input, '123 Pickup Street'); - - const secondAddressToggle = document.querySelector('[data-testid="has-secondary-pickup"]'); - expect(secondAddressToggle).toBeInTheDocument(); - await userEvent.click(secondAddressToggle); - - input = await document.querySelector('input[name="secondaryPickupAddress.streetAddress1"]'); - expect(input).toBeInTheDocument(); - // enter required street 1 for pickup 2 - await userEvent.type(input, '123 Pickup Street 2'); - - const thirdAddressToggle = document.querySelector('[data-testid="has-tertiary-pickup"]'); - expect(thirdAddressToggle).toBeInTheDocument(); - await userEvent.click(thirdAddressToggle); - - input = await document.querySelector('input[name="tertiaryPickupAddress.streetAddress1"]'); - expect(input).toBeInTheDocument(); - // enter required street 1 for pickup 2 - await userEvent.type(input, '123 Pickup Street 3'); - - const disable3rdAddressToggle = document.querySelector('[data-testid="no-tertiary-pickup"]'); - expect(disable3rdAddressToggle).toBeInTheDocument(); - await userEvent.click(disable3rdAddressToggle); - - const disable2ndAddressToggle = document.querySelector('[data-testid="no-secondary-pickup"]'); - expect(disable2ndAddressToggle).toBeInTheDocument(); - await userEvent.click(disable2ndAddressToggle); - - expect(input).not.toBeInTheDocument(); - - input = await document.querySelector('input[name="destinationAddress.streetAddress1"]'); - expect(input).toBeInTheDocument(); - // enter something - await userEvent.type(input, '123 destination Street'); - }, - ); }); From 27b76a6bfbaead45643409f1b6dd7cf73117211b Mon Sep 17 00:00:00 2001 From: loganwc Date: Fri, 27 Dec 2024 17:04:23 +0000 Subject: [PATCH 41/51] big test --- .../Shipment/PrimeUIShipmentCreate.test.jsx | 91 +++++++++++++++---- 1 file changed, 71 insertions(+), 20 deletions(-) diff --git a/src/pages/PrimeUI/Shipment/PrimeUIShipmentCreate.test.jsx b/src/pages/PrimeUI/Shipment/PrimeUIShipmentCreate.test.jsx index 3af240f1842..0c10c40d7bd 100644 --- a/src/pages/PrimeUI/Shipment/PrimeUIShipmentCreate.test.jsx +++ b/src/pages/PrimeUI/Shipment/PrimeUIShipmentCreate.test.jsx @@ -301,7 +301,57 @@ describe('Create PPM', () => { }); }); -describe('Create Mobile Home', () => { +describe('Create PPM Home', () => { + it('test with 2nd and 3rd addresses', async () => { + createPrimeMTOShipmentV3.mockReturnValue({}); + + render(mockedComponent); + + waitFor(async () => { + await userEvent.selectOptions(screen.getByLabelText('Shipment type'), 'PPM'); + + // Start controlled test case to verify everything is working. + let input = await document.querySelector('input[name="pickupAddress.streetAddress1"]'); + expect(input).toBeInTheDocument(); + // enter required street 1 for pickup + await userEvent.type(input, '123 Street'); + + const secondAddressToggle = document.querySelector('[data-testid="has-secondary-pickup"]'); + expect(secondAddressToggle).toBeInTheDocument(); + await userEvent.click(secondAddressToggle); + + input = await document.querySelector('input[name="secondaryPickupAddress.streetAddress1"]'); + expect(input).toBeInTheDocument(); + // enter required street 1 for pickup 2 + await userEvent.type(input, '123 Street 2'); + + const thirdAddressToggle = document.querySelector('[data-testid="has-tertiary-pickup"]'); + expect(thirdAddressToggle).toBeInTheDocument(); + await userEvent.click(thirdAddressToggle); + + input = await document.querySelector('input[name="tertiaryPickupAddress.streetAddress1"]'); + expect(input).toBeInTheDocument(); + // enter required street 1 for pickup 2 + await userEvent.type(input, '123 Street 3'); + + input = await document.querySelector('input[name="destinationAddress.streetAddress1"]'); + expect(input).toBeInTheDocument(); + // enter something + await userEvent.type(input, '123 Street'); + + const saveButton = await screen.getByRole('button', { name: 'Save' }); + + expect(saveButton).not.toBeDisabled(); + await userEvent.click(saveButton); + + await waitFor(() => { + expect(mockNavigate).toHaveBeenCalledWith(moveDetailsURL); + }); + }); + }); +}); + +describe('Create Mobile Home and Boat', () => { it.each(['MOBILE_HOME', 'BOAT_TOW_AWAY', 'BOAT_HAUL_AWAY'])( 'resets secondary and tertiary addresses when flags are not true for shipment type %s', async (shipmentType) => { @@ -414,25 +464,26 @@ describe('Create Mobile Home', () => { await userEvent.click(saveButton); // Verify that API call resets addresses when flags are not 'true' - expect(createPrimeMTOShipmentV3).toHaveBeenCalledWith({ - body: expect.objectContaining({ - destinationAddress: null, - diversion: null, - divertedFromShipmentId: null, - hasSecondaryDestinationAddress: false, - hasSecondaryPickupAddress: false, - hasTertiaryDestinationAddress: false, - hasTertiaryPickupAddress: false, - secondaryDestinationAddress: {}, - secondaryPickupAddress: {}, - tertiaryDestinationAddress: {}, - tertiaryPickupAddress: {}, - moveTaskOrderID: '9c7b255c-2981-4bf8-839f-61c7458e2b4d', - pickupAddress: null, - primeEstimatedWeight: null, - requestedPickupDate: null, - }), - }); + }); + + expect(createPrimeMTOShipmentV3).toHaveBeenCalledWith({ + body: expect.objectContaining({ + destinationAddress: null, + diversion: null, + divertedFromShipmentId: null, + hasSecondaryDestinationAddress: false, + hasSecondaryPickupAddress: false, + hasTertiaryDestinationAddress: false, + hasTertiaryPickupAddress: false, + secondaryDestinationAddress: null, + secondaryPickupAddress: null, + tertiaryDestinationAddress: null, + tertiaryPickupAddress: null, + moveTaskOrderID: '9c7b255c-2981-4bf8-839f-61c7458e2b4d', + pickupAddress: null, + primeEstimatedWeight: null, + requestedPickupDate: null, + }), }); }, ); From ef7a9135e8153955915334af509c1a793831eb99 Mon Sep 17 00:00:00 2001 From: Jon Spight Date: Tue, 31 Dec 2024 20:01:55 +0000 Subject: [PATCH 42/51] Added PM Closeout Cleanup --- pkg/services/ppmshipment/ppm_shipment_fetcher.go | 1 + .../ppmshipment/ppm_shipment_review_documents.go | 10 +++++++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/pkg/services/ppmshipment/ppm_shipment_fetcher.go b/pkg/services/ppmshipment/ppm_shipment_fetcher.go index 6ac39ad0431..5f005bcdc17 100644 --- a/pkg/services/ppmshipment/ppm_shipment_fetcher.go +++ b/pkg/services/ppmshipment/ppm_shipment_fetcher.go @@ -307,6 +307,7 @@ func FindPPMShipment(appCtx appcontext.AppContext, id uuid.UUID) (*models.PPMShi err := appCtx.DB().Scope(utilities.ExcludeDeletedScope()). EagerPreload( "Shipment", + "Shipment.MoveTaskOrder", "WeightTickets", "MovingExpenses", "ProgearWeightTickets", diff --git a/pkg/services/ppmshipment/ppm_shipment_review_documents.go b/pkg/services/ppmshipment/ppm_shipment_review_documents.go index e6be6e61f0a..10592f40543 100644 --- a/pkg/services/ppmshipment/ppm_shipment_review_documents.go +++ b/pkg/services/ppmshipment/ppm_shipment_review_documents.go @@ -59,7 +59,7 @@ func (p *ppmShipmentReviewDocuments) SubmitReviewedDocuments(appCtx appcontext.A if err != nil { return err } - + updatedPPMShipment.Shipment.MoveTaskOrder.SCAssignedID = nil err = validatePPMShipment(appCtx, updatedPPMShipment, ppmShipment, &ppmShipment.Shipment, PPMShipmentUpdaterChecks...) if err != nil { @@ -74,6 +74,14 @@ func (p *ppmShipmentReviewDocuments) SubmitReviewedDocuments(appCtx appcontext.A return apperror.NewQueryError("PPMShipment", err, "unable to update PPMShipment") } + verrs, err = appCtx.DB().ValidateAndSave(&updatedPPMShipment.Shipment.MoveTaskOrder) + if verrs != nil && verrs.HasAny() { + return apperror.NewInvalidInputError(updatedPPMShipment.ID, nil, verrs, "") + } + if err != nil { + return err + } + err = p.signCertificationPPMCloseout(appCtx, updatedPPMShipment.Shipment.MoveTaskOrderID, updatedPPMShipment.ID) if err != nil { From dc1e4e96099cdb97411fea1765437036613ac76f Mon Sep 17 00:00:00 2001 From: Jon Spight Date: Tue, 31 Dec 2024 20:20:20 +0000 Subject: [PATCH 43/51] PPM Closeout Test case --- .../ppm_shipment_review_documents_test.go | 42 ++++++++++++++++++- 1 file changed, 41 insertions(+), 1 deletion(-) diff --git a/pkg/services/ppmshipment/ppm_shipment_review_documents_test.go b/pkg/services/ppmshipment/ppm_shipment_review_documents_test.go index c374e7d8d4b..3f814f84cbd 100644 --- a/pkg/services/ppmshipment/ppm_shipment_review_documents_test.go +++ b/pkg/services/ppmshipment/ppm_shipment_review_documents_test.go @@ -11,6 +11,7 @@ import ( "github.com/transcom/mymove/pkg/auth" "github.com/transcom/mymove/pkg/factory" "github.com/transcom/mymove/pkg/models" + "github.com/transcom/mymove/pkg/models/roles" "github.com/transcom/mymove/pkg/services" "github.com/transcom/mymove/pkg/services/mocks" signedcertification "github.com/transcom/mymove/pkg/services/signed_certification" @@ -126,7 +127,6 @@ func (suite *PPMShipmentSuite) TestReviewDocuments() { suite.Run("Can route the PPMShipment properly", func() { existingPPMShipment := factory.BuildPPMShipmentThatNeedsCloseout(suite.DB(), nil, nil) - sm := factory.BuildServiceMember(suite.DB(), nil, nil) session := suite.AppContextWithSessionForTest(&auth.Session{ ApplicationName: auth.OfficeApp, @@ -135,6 +135,43 @@ func (suite *PPMShipmentSuite) TestReviewDocuments() { FirstName: "Nelson", LastName: "Muntz", }) + setupTestData := func() models.OfficeUser { + + transportationOffice := factory.BuildTransportationOffice(suite.DB(), []factory.Customization{ + { + Model: models.TransportationOffice{ + ProvidesCloseout: true, + }, + }, + }, nil) + + officeUser := factory.BuildOfficeUserWithRoles(suite.DB(), []factory.Customization{ + { + Model: transportationOffice, + LinkOnly: true, + Type: &factory.TransportationOffices.CloseoutOffice, + }, + }, []roles.RoleType{roles.RoleTypeServicesCounselor}) + + return officeUser + } + + officeUser := setupTestData() + move := factory.BuildMoveWithShipment(suite.DB(), []factory.Customization{ + { + Model: models.Move{ + Status: models.MoveStatusNeedsServiceCounseling, + }, + }, + { + Model: officeUser, + LinkOnly: true, + Type: &factory.OfficeUsers.SCAssignedUser, + }, + }, nil) + + existingPPMShipment.Shipment.MoveTaskOrder = move + suite.NotNil(existingPPMShipment.Shipment.MoveTaskOrder.SCAssignedID) router := setUpPPMShipperRouterMock( func(_ appcontext.AppContext, ppmShipment *models.PPMShipment) error { @@ -154,6 +191,9 @@ func (suite *PPMShipmentSuite) TestReviewDocuments() { existingPPMShipment.ID, ) + //check removal of the SC Assigned User + suite.Nil(updatedPPMShipment.Shipment.MoveTaskOrder.SCAssignedID) + if suite.NoError(err) && suite.NotNil(updatedPPMShipment) { suite.Equal(models.PPMShipmentStatusCloseoutComplete, updatedPPMShipment.Status) From d456a0ade19934b1909a15b1c7a31728c939ec65 Mon Sep 17 00:00:00 2001 From: loganwc Date: Tue, 7 Jan 2025 00:39:54 +0000 Subject: [PATCH 44/51] just redid everything because stupid test coverage --- migrations/app/migrations_manifest.txt | 2 +- .../Shipment/PrimeUIShipmentCreate.jsx | 143 +++++------------- .../Shipment/PrimeUIShipmentCreate.test.jsx | 4 +- .../Shipment/PrimeUIShipmentCreateForm.jsx | 4 +- src/shared/utils.js | 38 +++++ src/shared/utils.test.js | 55 +++++++ 6 files changed, 138 insertions(+), 108 deletions(-) diff --git a/migrations/app/migrations_manifest.txt b/migrations/app/migrations_manifest.txt index 18c13cdaa73..a5330171a14 100644 --- a/migrations/app/migrations_manifest.txt +++ b/migrations/app/migrations_manifest.txt @@ -1052,9 +1052,9 @@ 20241203024453_add_ppm_max_incentive_column.up.sql 20241204155919_update_ordering_proc.up.sql 20241204210208_retroactive_update_of_ppm_max_and_estimated_incentives_prd.up.sql -20241218201833_add_PPPO_BASE_ELIZABETH.up.sql 20241217163231_update_duty_locations_bad_zips.up.sql 20241217180136_add_AK_zips_to_zip3_distances.up.sql +20241218201833_add_PPPO_BASE_ELIZABETH.up.sql 20241220171035_add_additional_AK_zips_to_zip3_distances.up.sql 20241227153723_remove_empty_string_emplid_values.up.sql 20241230190638_remove_AK_zips_from_zip3.up.sql diff --git a/src/pages/PrimeUI/Shipment/PrimeUIShipmentCreate.jsx b/src/pages/PrimeUI/Shipment/PrimeUIShipmentCreate.jsx index 9dae219dfbc..c7117373da0 100644 --- a/src/pages/PrimeUI/Shipment/PrimeUIShipmentCreate.jsx +++ b/src/pages/PrimeUI/Shipment/PrimeUIShipmentCreate.jsx @@ -15,7 +15,7 @@ import styles from 'components/Office/CustomerContactInfoForm/CustomerContactInf import { Form } from 'components/form/Form'; import formStyles from 'styles/form.module.scss'; import WizardNavigation from 'components/Customer/WizardNavigation/WizardNavigation'; -import { isEmpty, isValidWeight } from 'shared/utils'; +import { checkAddressTogglesToClearAddresses, isEmpty, isValidWeight } from 'shared/utils'; import { formatAddressForPrimeAPI, formatSwaggerDate } from 'utils/formatters'; import { setFlashMessage as setFlashMessageAction } from 'store/flash/actions'; import { requiredAddressSchema, partialRequiredAddressSchema } from 'utils/validation'; @@ -115,29 +115,8 @@ const PrimeUIShipmentCreate = ({ setFlashMessage }) => { hasTertiaryDestinationAddress, }, } = values; - let { - ppmShipment: { - tertiaryPickupAddress, - tertiaryDestinationAddress, - secondaryPickupAddress, - secondaryDestinationAddress, - }, - } = values; - if (hasSecondaryPickupAddress !== 'true') { - secondaryPickupAddress = {}; - tertiaryPickupAddress = {}; - } - if (hasTertiaryPickupAddress !== 'true') { - tertiaryPickupAddress = {}; - } - if (hasSecondaryDestinationAddress !== 'true') { - secondaryDestinationAddress = {}; - tertiaryDestinationAddress = {}; - } - if (hasTertiaryDestinationAddress !== 'true') { - tertiaryDestinationAddress = {}; - } + const updatedValues = checkAddressTogglesToClearAddresses(values); body = { moveTaskOrderID: moveCodeOrID, @@ -146,19 +125,19 @@ const PrimeUIShipmentCreate = ({ setFlashMessage }) => { ppmShipment: { expectedDepartureDate: expectedDepartureDate ? formatSwaggerDate(expectedDepartureDate) : null, pickupAddress: isEmpty(pickupAddress) ? null : formatAddressForPrimeAPI(pickupAddress), - secondaryPickupAddress: isEmpty(secondaryPickupAddress) - ? null - : formatAddressForPrimeAPI(secondaryPickupAddress), destinationAddress: isEmpty(destinationAddress) ? null : formatAddressForPrimeAPI(destinationAddress), - secondaryDestinationAddress: isEmpty(secondaryDestinationAddress) + secondaryPickupAddress: isEmpty(updatedValues.secondaryPickupAddress) + ? null + : formatAddressForPrimeAPI(updatedValues.secondaryPickupAddress), + secondaryDestinationAddress: isEmpty(updatedValues.secondaryDestinationAddress) ? null - : formatAddressForPrimeAPI(secondaryDestinationAddress), - tertiaryPickupAddress: isEmpty(tertiaryPickupAddress) + : formatAddressForPrimeAPI(updatedValues.secondaryDestinationAddress), + tertiaryPickupAddress: isEmpty(updatedValues.tertiaryPickupAddress) ? null - : formatAddressForPrimeAPI(tertiaryPickupAddress), - tertiaryDestinationAddress: isEmpty(tertiaryDestinationAddress) + : formatAddressForPrimeAPI(updatedValues.tertiaryPickupAddress), + tertiaryDestinationAddress: isEmpty(updatedValues.tertiaryDestinationAddress) ? null - : formatAddressForPrimeAPI(tertiaryDestinationAddress), + : formatAddressForPrimeAPI(updatedValues.tertiaryDestinationAddress), sitExpected, ...(sitExpected && { sitLocation: sitLocation || null, @@ -206,22 +185,7 @@ const PrimeUIShipmentCreate = ({ setFlashMessage }) => { }, } = values; - let { tertiaryPickupAddress, tertiaryDestinationAddress, secondaryPickupAddress, secondaryDestinationAddress } = - values; - if (hasSecondaryPickupAddress !== 'true') { - secondaryPickupAddress = {}; - tertiaryPickupAddress = {}; - } - if (hasTertiaryPickupAddress !== 'true') { - tertiaryPickupAddress = {}; - } - if (hasSecondaryDestinationAddress !== 'true') { - secondaryDestinationAddress = {}; - tertiaryDestinationAddress = {}; - } - if (hasTertiaryDestinationAddress !== 'true') { - tertiaryDestinationAddress = {}; - } + const updatedValues = checkAddressTogglesToClearAddresses(values); // Sum the feet and inches fields into only inches for backend/db const totalLengthInInches = parseInt(lengthInFeet, 10) * 12 + parseInt(lengthInInches, 10); @@ -254,16 +218,18 @@ const PrimeUIShipmentCreate = ({ setFlashMessage }) => { hasSecondaryDestinationAddress: hasSecondaryDestinationAddress === 'true', hasTertiaryPickupAddress: hasTertiaryPickupAddress === 'true', hasTertiaryDestinationAddress: hasTertiaryDestinationAddress === 'true', - secondaryPickupAddress: isEmpty(secondaryPickupAddress) + secondaryPickupAddress: isEmpty(updatedValues.secondaryPickupAddress) ? null - : formatAddressForPrimeAPI(secondaryPickupAddress), - secondaryDestinationAddress: isEmpty(secondaryDestinationAddress) + : formatAddressForPrimeAPI(updatedValues.secondaryPickupAddress), + secondaryDestinationAddress: isEmpty(updatedValues.secondaryDestinationAddress) ? null - : formatAddressForPrimeAPI(secondaryDestinationAddress), - tertiaryPickupAddress: isEmpty(tertiaryPickupAddress) ? null : formatAddressForPrimeAPI(tertiaryPickupAddress), - tertiaryDestinationAddress: isEmpty(tertiaryDestinationAddress) + : formatAddressForPrimeAPI(updatedValues.secondaryDestinationAddress), + tertiaryPickupAddress: isEmpty(updatedValues.tertiaryPickupAddress) ? null - : formatAddressForPrimeAPI(tertiaryDestinationAddress), + : formatAddressForPrimeAPI(updatedValues.tertiaryPickupAddress), + tertiaryDestinationAddress: isEmpty(updatedValues.tertiaryDestinationAddress) + ? null + : formatAddressForPrimeAPI(updatedValues.tertiaryDestinationAddress), }; } else if (isMobileHome) { const { @@ -291,22 +257,7 @@ const PrimeUIShipmentCreate = ({ setFlashMessage }) => { }, } = values; - let { tertiaryPickupAddress, tertiaryDestinationAddress, secondaryPickupAddress, secondaryDestinationAddress } = - values; - if (hasSecondaryPickupAddress !== 'true') { - secondaryPickupAddress = {}; - tertiaryPickupAddress = {}; - } - if (hasTertiaryPickupAddress !== 'true') { - tertiaryPickupAddress = {}; - } - if (hasSecondaryDestinationAddress !== 'true') { - secondaryDestinationAddress = {}; - tertiaryDestinationAddress = {}; - } - if (hasTertiaryDestinationAddress !== 'true') { - tertiaryDestinationAddress = {}; - } + const updatedValues = checkAddressTogglesToClearAddresses(values); // Sum the feet and inches fields into only inches for backend/db const totalLengthInInches = parseInt(lengthInFeet, 10) * 12 + parseInt(lengthInInches, 10); @@ -335,16 +286,18 @@ const PrimeUIShipmentCreate = ({ setFlashMessage }) => { hasSecondaryDestinationAddress: hasSecondaryDestinationAddress === 'true', hasTertiaryPickupAddress: hasTertiaryPickupAddress === 'true', hasTertiaryDestinationAddress: hasTertiaryDestinationAddress === 'true', - secondaryPickupAddress: isEmpty(secondaryPickupAddress) + secondaryPickupAddress: isEmpty(updatedValues.secondaryPickupAddress) + ? null + : formatAddressForPrimeAPI(updatedValues.secondaryPickupAddress), + secondaryDestinationAddress: isEmpty(updatedValues.secondaryDestinationAddress) ? null - : formatAddressForPrimeAPI(secondaryPickupAddress), - secondaryDestinationAddress: isEmpty(secondaryDestinationAddress) + : formatAddressForPrimeAPI(updatedValues.secondaryDestinationAddress), + tertiaryPickupAddress: isEmpty(updatedValues.tertiaryPickupAddress) ? null - : formatAddressForPrimeAPI(secondaryDestinationAddress), - tertiaryPickupAddress: isEmpty(tertiaryPickupAddress) ? null : formatAddressForPrimeAPI(tertiaryPickupAddress), - tertiaryDestinationAddress: isEmpty(tertiaryDestinationAddress) + : formatAddressForPrimeAPI(updatedValues.tertiaryPickupAddress), + tertiaryDestinationAddress: isEmpty(updatedValues.tertiaryDestinationAddress) ? null - : formatAddressForPrimeAPI(tertiaryDestinationAddress), + : formatAddressForPrimeAPI(updatedValues.tertiaryDestinationAddress), }; } else { const { @@ -360,23 +313,7 @@ const PrimeUIShipmentCreate = ({ setFlashMessage }) => { hasTertiaryDestinationAddress, } = values; - let { tertiaryPickupAddress, tertiaryDestinationAddress, secondaryPickupAddress, secondaryDestinationAddress } = - values; - - if (hasSecondaryPickupAddress !== 'true') { - secondaryPickupAddress = {}; - tertiaryPickupAddress = {}; - } - if (hasTertiaryPickupAddress !== 'true') { - tertiaryPickupAddress = {}; - } - if (hasSecondaryDestinationAddress !== 'true') { - secondaryDestinationAddress = {}; - tertiaryDestinationAddress = {}; - } - if (hasTertiaryDestinationAddress !== 'true') { - tertiaryDestinationAddress = {}; - } + const updatedValues = checkAddressTogglesToClearAddresses(values); body = { moveTaskOrderID: moveCodeOrID, @@ -391,16 +328,18 @@ const PrimeUIShipmentCreate = ({ setFlashMessage }) => { hasSecondaryDestinationAddress: hasSecondaryDestinationAddress === 'true', hasTertiaryPickupAddress: hasTertiaryPickupAddress === 'true', hasTertiaryDestinationAddress: hasTertiaryDestinationAddress === 'true', - secondaryPickupAddress: isEmpty(secondaryPickupAddress) + secondaryPickupAddress: isEmpty(updatedValues.secondaryPickupAddress) + ? null + : formatAddressForPrimeAPI(updatedValues.secondaryPickupAddress), + secondaryDestinationAddress: isEmpty(updatedValues.secondaryDestinationAddress) ? null - : formatAddressForPrimeAPI(secondaryPickupAddress), - secondaryDestinationAddress: isEmpty(secondaryDestinationAddress) + : formatAddressForPrimeAPI(updatedValues.secondaryDestinationAddress), + tertiaryPickupAddress: isEmpty(updatedValues.tertiaryPickupAddress) ? null - : formatAddressForPrimeAPI(secondaryDestinationAddress), - tertiaryPickupAddress: isEmpty(tertiaryPickupAddress) ? null : formatAddressForPrimeAPI(tertiaryPickupAddress), - tertiaryDestinationAddress: isEmpty(tertiaryDestinationAddress) + : formatAddressForPrimeAPI(updatedValues.tertiaryPickupAddress), + tertiaryDestinationAddress: isEmpty(updatedValues.tertiaryDestinationAddress) ? null - : formatAddressForPrimeAPI(tertiaryDestinationAddress), + : formatAddressForPrimeAPI(updatedValues.tertiaryDestinationAddress), }; } diff --git a/src/pages/PrimeUI/Shipment/PrimeUIShipmentCreate.test.jsx b/src/pages/PrimeUI/Shipment/PrimeUIShipmentCreate.test.jsx index 0c10c40d7bd..370372ffe9c 100644 --- a/src/pages/PrimeUI/Shipment/PrimeUIShipmentCreate.test.jsx +++ b/src/pages/PrimeUI/Shipment/PrimeUIShipmentCreate.test.jsx @@ -32,7 +32,7 @@ jest.mock('services/primeApi', () => ({ jest.mock('utils/featureFlags', () => ({ ...jest.requireActual('utils/featureFlags'), - isBooleanFlagEnabled: jest.fn().mockImplementation(() => Promise.resolve(true)), + isBooleanFlagEnabled: jest.fn().mockImplementation(() => Promise.resolve(false)), })); const moveDetailsURL = generatePath(primeSimulatorRoutes.VIEW_MOVE_PATH, { moveCodeOrID: moveId }); @@ -462,8 +462,6 @@ describe('Create Mobile Home and Boat', () => { const saveButton = screen.getByRole('button', { name: 'Save' }); expect(saveButton).not.toBeDisabled(); await userEvent.click(saveButton); - - // Verify that API call resets addresses when flags are not 'true' }); expect(createPrimeMTOShipmentV3).toHaveBeenCalledWith({ diff --git a/src/pages/PrimeUI/Shipment/PrimeUIShipmentCreateForm.jsx b/src/pages/PrimeUI/Shipment/PrimeUIShipmentCreateForm.jsx index 22fd5f366df..ad0215141e2 100644 --- a/src/pages/PrimeUI/Shipment/PrimeUIShipmentCreateForm.jsx +++ b/src/pages/PrimeUI/Shipment/PrimeUIShipmentCreateForm.jsx @@ -408,7 +408,7 @@ const PrimeUIShipmentCreateForm = ({ enableBoat, enableMobileHome }) => { name="hasSecondaryPickupAddress" value="false" title="No, there is not a second pickup address" - checked={hasSecondaryPickupAddress !== 'true'} + checked={hasSecondaryPickupAddress !== 'true' && hasTertiaryPickupAddress !== 'true'} />
@@ -491,7 +491,7 @@ const PrimeUIShipmentCreateForm = ({ enableBoat, enableMobileHome }) => { name="hasSecondaryDestinationAddress" value="false" title="No, there is not a second delivery address" - checked={hasSecondaryDestinationAddress !== 'true'} + checked={hasSecondaryDestinationAddress !== 'true' && hasTertiaryDestinationAddress !== 'true'} /> diff --git a/src/shared/utils.js b/src/shared/utils.js index ac6baa1307b..12ccf91c7a8 100644 --- a/src/shared/utils.js +++ b/src/shared/utils.js @@ -171,3 +171,41 @@ export function isEmpty(obj) { export function isNullUndefinedOrWhitespace(value) { return value == null || value === undefined || value.trim() === ''; } + +export function checkAddressTogglesToClearAddresses(body) { + let values = body; + + if (values.shipmentType === 'PPM') { + if (values.ppmShipment.hasSecondaryPickupAddress !== 'true') { + values.ppmShipment.secondaryPickupAddress = {}; + values.ppmShipment.tertiaryPickupAddress = {}; + } + if (values.ppmShipment.hasTertiaryPickupAddress !== 'true') { + values.ppmShipment.tertiaryPickupAddress = {}; + } + if (values.ppmShipment.hasSecondaryDestinationAddress !== 'true') { + values.ppmShipment.secondaryDestinationAddress = {}; + values.ppmShipment.tertiaryDestinationAddress = {}; + } + if (values.ppmShipment.hasTertiaryDestinationAddress !== 'true') { + values.ppmShipment.tertiaryDestinationAddress = {}; + } + } else { + if (values.hasSecondaryPickupAddress !== 'true') { + values.secondaryPickupAddress = {}; + values.tertiaryPickupAddress = {}; + } + if (values.hasTertiaryPickupAddress !== 'true') { + values.tertiaryPickupAddress = {}; + } + if (values.hasSecondaryDestinationAddress !== 'true') { + values.secondaryDestinationAddress = {}; + values.tertiaryDestinationAddress = {}; + } + if (values.hasTertiaryDestinationAddress !== 'true') { + values.tertiaryDestinationAddress = {}; + } + } + + return values; +} diff --git a/src/shared/utils.test.js b/src/shared/utils.test.js index eb5ea3e0160..dfc7cfcd956 100644 --- a/src/shared/utils.test.js +++ b/src/shared/utils.test.js @@ -86,4 +86,59 @@ describe('utils', () => { }); }); }); + + it('check if 2nd and 3rd addresses should be cleared from prime shipment create payload', () => { + const ppmValues = { + shipmentType: 'PPM', + ppmShipment: { + hasSecondaryPickupAddress: 'false', + hasTertiaryPickupAddress: 'false', + hasSecondaryDestinationAddress: 'false', + hasTertiaryDestinationAddress: 'false', + secondaryPickupAddress: '', + tertiaryPickupAddress: '', + secondaryDestinationAddress: '', + tertiaryDestinationAddress: '', + }, + }; + const hhgValues = { + shipmentType: 'HHG', + hasSecondaryPickupAddress: 'false', + hasTertiaryPickupAddress: 'false', + hasSecondaryDestinationAddress: 'false', + hasTertiaryDestinationAddress: 'false', + secondaryPickupAddress: '', + tertiaryPickupAddress: '', + secondaryDestinationAddress: '', + tertiaryDestinationAddress: '', + }; + + const updatedPPMValues = utils.checkAddressTogglesToClearAddresses(ppmValues); + expect(updatedPPMValues).toEqual({ + shipmentType: 'PPM', + ppmShipment: { + hasSecondaryPickupAddress: 'false', + hasTertiaryPickupAddress: 'false', + hasSecondaryDestinationAddress: 'false', + hasTertiaryDestinationAddress: 'false', + secondaryPickupAddress: {}, + tertiaryPickupAddress: {}, + secondaryDestinationAddress: {}, + tertiaryDestinationAddress: {}, + }, + }); + + const updatedHHGValues = utils.checkAddressTogglesToClearAddresses(hhgValues); + expect(updatedHHGValues).toEqual({ + shipmentType: 'HHG', + hasSecondaryPickupAddress: 'false', + hasTertiaryPickupAddress: 'false', + hasSecondaryDestinationAddress: 'false', + hasTertiaryDestinationAddress: 'false', + secondaryPickupAddress: {}, + tertiaryPickupAddress: {}, + secondaryDestinationAddress: {}, + tertiaryDestinationAddress: {}, + }); + }); }); From 1155ac24343f996a0809ad70c8f6741425cb3925 Mon Sep 17 00:00:00 2001 From: Jon Spight Date: Wed, 8 Jan 2025 21:56:00 +0000 Subject: [PATCH 45/51] removed tests --- .../payloads/model_to_payload_test.go | 62 ------------------- 1 file changed, 62 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 7537a5a01b4..0e6b225889e 100644 --- a/pkg/handlers/ghcapi/internal/payloads/model_to_payload_test.go +++ b/pkg/handlers/ghcapi/internal/payloads/model_to_payload_test.go @@ -13,7 +13,6 @@ import ( "github.com/transcom/mymove/pkg/models" "github.com/transcom/mymove/pkg/models/roles" "github.com/transcom/mymove/pkg/storage/test" - "github.com/transcom/mymove/pkg/testdatagen" "github.com/transcom/mymove/pkg/unit" ) @@ -717,8 +716,6 @@ func (suite *PayloadsSuite) TestSearchMoves() { appCtx := suite.AppContextForTest() marines := models.AffiliationMARINES - spaceForce := models.AffiliationSPACEFORCE - army := models.AffiliationARMY moveUSMC := factory.BuildMove(suite.DB(), []factory.Customization{ { Model: models.ServiceMember{ @@ -726,73 +723,14 @@ func (suite *PayloadsSuite) TestSearchMoves() { }, }, }, nil) - moveSF := factory.BuildMove(suite.DB(), []factory.Customization{ - { - Model: models.ServiceMember{ - Affiliation: &spaceForce, - }, - }, - }, nil) - moveA := factory.BuildMove(suite.DB(), []factory.Customization{ - { - Model: models.ServiceMember{ - Affiliation: &army, - }, - }, - }, nil) - moveUSMC.Status = models.MoveStatusNeedsServiceCounseling - scheduledPickupDate := time.Date(testdatagen.GHCTestYear, time.September, 20, 0, 0, 0, 0, time.UTC) - scheduledDeliveryDate := time.Date(testdatagen.GHCTestYear, time.September, 20, 0, 0, 0, 0, time.UTC) - sitAllowance := int(90) - gbloc := "LKNQ" - storageFacility := factory.BuildStorageFacility(suite.DB(), nil, nil) - mtoShipment := factory.BuildMTOShipment(suite.DB(), []factory.Customization{ - { - Model: moveSF, - LinkOnly: true, - }, - { - Model: models.MTOShipment{ - Status: models.MTOShipmentStatusApproved, - ShipmentType: models.MTOShipmentTypeHHGIntoNTSDom, - CounselorRemarks: handlers.FmtString("counselor remark"), - SITDaysAllowance: &sitAllowance, - ScheduledPickupDate: &scheduledPickupDate, - ScheduledDeliveryDate: &scheduledDeliveryDate, - }, - }, - { - Model: storageFacility, - LinkOnly: true, - }, - }, nil) - - moveSF.MTOShipments = append(moveSF.MTOShipments, mtoShipment) - moveSF.ShipmentGBLOC = append(moveSF.ShipmentGBLOC, models.MoveToGBLOC{GBLOC: &gbloc}) moves := models.Moves{moveUSMC} - moveSpaceForce := models.Moves{moveSF} - moveArmy := models.Moves{moveA} suite.Run("Success - Returns a ghcmessages Upload payload from Upload Struct Marine move with no shipments", func() { payload := SearchMoves(appCtx, moves) suite.IsType(payload, &ghcmessages.SearchMoves{}) suite.NotNil(payload) }) - suite.Run("Success - Returns a ghcmessages Upload payload from Upload Struct Non-Marine move, a shipment, and delivery/pickup time. ", func() { - payload := SearchMoves(appCtx, moveSpaceForce) - suite.IsType(payload, &ghcmessages.SearchMoves{}) - suite.NotNil(payload) - suite.NotNil(mtoShipment) - - suite.NotNil(moveA) - }) - suite.Run("Success - Returns a ghcmessages Upload payload from Upload Struct Army move, with no shipments. ", func() { - payload := SearchMoves(appCtx, moveArmy) - suite.IsType(payload, &ghcmessages.SearchMoves{}) - suite.NotNil(payload) - - }) } func (suite *PayloadsSuite) TestMarketCode() { From 9713b2cc944e11b5832b678603c53a7a6976f328 Mon Sep 17 00:00:00 2001 From: Jon Spight Date: Wed, 8 Jan 2025 21:59:33 +0000 Subject: [PATCH 46/51] PR comments --- pkg/factory/shared.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/factory/shared.go b/pkg/factory/shared.go index 2ff8e0dea9b..d7f5b069776 100644 --- a/pkg/factory/shared.go +++ b/pkg/factory/shared.go @@ -273,14 +273,14 @@ var TransportationOffices = transportationOfficeGroup{ type officeUserGroup struct { SCAssignedUser CustomType - TOOAssignedUser CustomType TIOAssignedUser CustomType + TOOAssignedUser CustomType } var OfficeUsers = officeUserGroup{ SCAssignedUser: "SCAssignedUser", - TOOAssignedUser: "TOOAssignedUser", TIOAssignedUser: "TIOAssignedUser", + TOOAssignedUser: "TOOAssignedUser", } // uploadGroup is a grouping of all the upload related fields From 7dfef82968c70d3fa04585bcc3c760ce599d13d8 Mon Sep 17 00:00:00 2001 From: Jon Spight Date: Mon, 13 Jan 2025 18:59:12 +0000 Subject: [PATCH 47/51] fixced merge conflicts --- pkg/factory/move_factory.go | 4 ---- pkg/factory/shared.go | 8 -------- 2 files changed, 12 deletions(-) diff --git a/pkg/factory/move_factory.go b/pkg/factory/move_factory.go index f496c1dc5f1..4564f893657 100644 --- a/pkg/factory/move_factory.go +++ b/pkg/factory/move_factory.go @@ -35,7 +35,6 @@ func BuildMove(db *pop.Connection, customs []Customization, traits []Trait) mode closeoutOffice = BuildTransportationOffice(db, tempCloseoutOfficeCustoms, nil) } - var counselingOffice models.TransportationOffice tempCounselingOfficeCustoms := customs counselingOfficeResult := findValidCustomization(customs, TransportationOffices.CounselingOffice) @@ -52,7 +51,6 @@ func BuildMove(db *pop.Connection, customs []Customization, traits []Trait) mode scAssignedUser = BuildOfficeUser(db, tempSCAssignedUserCustoms, nil) } - var tooAssignedUser models.OfficeUser tempTOOAssignedUserCustoms := customs tooAssignedUserResult := findValidCustomization(customs, OfficeUsers.TOOAssignedUser) @@ -107,7 +105,6 @@ func BuildMove(db *pop.Connection, customs []Customization, traits []Trait) mode move.CloseoutOfficeID = &closeoutOffice.ID } - if counselingOfficeResult != nil { move.CounselingOffice = &counselingOffice move.CounselingOfficeID = &counselingOffice.ID @@ -118,7 +115,6 @@ func BuildMove(db *pop.Connection, customs []Customization, traits []Trait) mode move.SCAssignedID = &scAssignedUser.ID } - if tooAssignedUserResult != nil { move.TOOAssignedUser = &tooAssignedUser move.TOOAssignedID = &tooAssignedUser.ID diff --git a/pkg/factory/shared.go b/pkg/factory/shared.go index 8d72b513a7d..037f2d352d5 100644 --- a/pkg/factory/shared.go +++ b/pkg/factory/shared.go @@ -273,14 +273,6 @@ var TransportationOffices = transportationOfficeGroup{ CounselingOffice: "CounselingOffice", } -type officeUserGroup struct { - SCAssignedUser CustomType -} - -var OfficeUsers = officeUserGroup{ - SCAssignedUser: "SCAssignedUser", -} - type officeUserGroup struct { SCAssignedUser CustomType TIOAssignedUser CustomType From 28ce85b4a886815bcf8ab04aef1fdf39108d099b Mon Sep 17 00:00:00 2001 From: Jon Spight Date: Mon, 13 Jan 2025 19:49:21 +0000 Subject: [PATCH 48/51] PR Fixes --- pkg/factory/move_factory.go | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/pkg/factory/move_factory.go b/pkg/factory/move_factory.go index 4564f893657..3f923f95204 100644 --- a/pkg/factory/move_factory.go +++ b/pkg/factory/move_factory.go @@ -35,14 +35,6 @@ func BuildMove(db *pop.Connection, customs []Customization, traits []Trait) mode closeoutOffice = BuildTransportationOffice(db, tempCloseoutOfficeCustoms, nil) } - var counselingOffice models.TransportationOffice - tempCounselingOfficeCustoms := customs - counselingOfficeResult := findValidCustomization(customs, TransportationOffices.CounselingOffice) - if counselingOfficeResult != nil { - tempCounselingOfficeCustoms = convertCustomizationInList(tempCounselingOfficeCustoms, TransportationOffices.CounselingOffice, TransportationOffice) - counselingOffice = BuildTransportationOffice(db, tempCounselingOfficeCustoms, nil) - } - var scAssignedUser models.OfficeUser tempSCAssignedUserCustoms := customs scAssignedUserResult := findValidCustomization(customs, OfficeUsers.SCAssignedUser) @@ -67,6 +59,14 @@ func BuildMove(db *pop.Connection, customs []Customization, traits []Trait) mode tioAssignedUser = BuildOfficeUser(db, tempTIOAssignedUserCustoms, nil) } + var counselingOffice models.TransportationOffice + tempCounselingOfficeCustoms := customs + counselingOfficeResult := findValidCustomization(customs, TransportationOffices.CounselingOffice) + if counselingOfficeResult != nil { + tempCounselingOfficeCustoms = convertCustomizationInList(tempCounselingOfficeCustoms, TransportationOffices.CounselingOffice, TransportationOffice) + counselingOffice = BuildTransportationOffice(db, tempCounselingOfficeCustoms, nil) + } + var defaultReferenceID string var err error if db != nil { @@ -105,11 +105,6 @@ func BuildMove(db *pop.Connection, customs []Customization, traits []Trait) mode move.CloseoutOfficeID = &closeoutOffice.ID } - if counselingOfficeResult != nil { - move.CounselingOffice = &counselingOffice - move.CounselingOfficeID = &counselingOffice.ID - } - if scAssignedUserResult != nil { move.SCAssignedUser = &scAssignedUser move.SCAssignedID = &scAssignedUser.ID @@ -125,6 +120,11 @@ func BuildMove(db *pop.Connection, customs []Customization, traits []Trait) mode move.TIOAssignedID = &tioAssignedUser.ID } + if counselingOfficeResult != nil { + move.CounselingOffice = &counselingOffice + move.CounselingOfficeID = &counselingOffice.ID + } + // Overwrite values with those from assertions testdatagen.MergeModels(&move, cMove) From a7757af972ceb12cbc181979606af04e6bd156b4 Mon Sep 17 00:00:00 2001 From: Jon Spight Date: Mon, 13 Jan 2025 21:25:52 +0000 Subject: [PATCH 49/51] Fixed merge conflicts --- pkg/factory/move_factory.go | 28 ++++----- pkg/factory/shared.go | 8 --- .../payloads/model_to_payload_test.go | 63 +------------------ 3 files changed, 14 insertions(+), 85 deletions(-) diff --git a/pkg/factory/move_factory.go b/pkg/factory/move_factory.go index d147fab8d6b..3f923f95204 100644 --- a/pkg/factory/move_factory.go +++ b/pkg/factory/move_factory.go @@ -35,14 +35,6 @@ func BuildMove(db *pop.Connection, customs []Customization, traits []Trait) mode closeoutOffice = BuildTransportationOffice(db, tempCloseoutOfficeCustoms, nil) } - var counselingOffice models.TransportationOffice - tempCounselingOfficeCustoms := customs - counselingOfficeResult := findValidCustomization(customs, TransportationOffices.CounselingOffice) - if counselingOfficeResult != nil { - tempCounselingOfficeCustoms = convertCustomizationInList(tempCounselingOfficeCustoms, TransportationOffices.CounselingOffice, TransportationOffice) - counselingOffice = BuildTransportationOffice(db, tempCounselingOfficeCustoms, nil) - } - var scAssignedUser models.OfficeUser tempSCAssignedUserCustoms := customs scAssignedUserResult := findValidCustomization(customs, OfficeUsers.SCAssignedUser) @@ -67,6 +59,14 @@ func BuildMove(db *pop.Connection, customs []Customization, traits []Trait) mode tioAssignedUser = BuildOfficeUser(db, tempTIOAssignedUserCustoms, nil) } + var counselingOffice models.TransportationOffice + tempCounselingOfficeCustoms := customs + counselingOfficeResult := findValidCustomization(customs, TransportationOffices.CounselingOffice) + if counselingOfficeResult != nil { + tempCounselingOfficeCustoms = convertCustomizationInList(tempCounselingOfficeCustoms, TransportationOffices.CounselingOffice, TransportationOffice) + counselingOffice = BuildTransportationOffice(db, tempCounselingOfficeCustoms, nil) + } + var defaultReferenceID string var err error if db != nil { @@ -105,18 +105,11 @@ func BuildMove(db *pop.Connection, customs []Customization, traits []Trait) mode move.CloseoutOfficeID = &closeoutOffice.ID } - if counselingOfficeResult != nil { - move.CounselingOffice = &counselingOffice - move.CounselingOfficeID = &counselingOffice.ID - } - - if scAssignedUserResult != nil { move.SCAssignedUser = &scAssignedUser move.SCAssignedID = &scAssignedUser.ID } - if tooAssignedUserResult != nil { move.TOOAssignedUser = &tooAssignedUser move.TOOAssignedID = &tooAssignedUser.ID @@ -127,6 +120,11 @@ func BuildMove(db *pop.Connection, customs []Customization, traits []Trait) mode move.TIOAssignedID = &tioAssignedUser.ID } + if counselingOfficeResult != nil { + move.CounselingOffice = &counselingOffice + move.CounselingOfficeID = &counselingOffice.ID + } + // Overwrite values with those from assertions testdatagen.MergeModels(&move, cMove) diff --git a/pkg/factory/shared.go b/pkg/factory/shared.go index 1c0e38146db..207a8cdb86c 100644 --- a/pkg/factory/shared.go +++ b/pkg/factory/shared.go @@ -273,14 +273,6 @@ var TransportationOffices = transportationOfficeGroup{ CounselingOffice: "CounselingOffice", } -type officeUserGroup struct { - SCAssignedUser CustomType -} - -var OfficeUsers = officeUserGroup{ - SCAssignedUser: "SCAssignedUser", -} - type officeUserGroup struct { SCAssignedUser CustomType TOOAssignedUser CustomType 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 7481b293662..d4e330f09b2 100644 --- a/pkg/handlers/ghcapi/internal/payloads/model_to_payload_test.go +++ b/pkg/handlers/ghcapi/internal/payloads/model_to_payload_test.go @@ -14,7 +14,6 @@ import ( "github.com/transcom/mymove/pkg/models" "github.com/transcom/mymove/pkg/models/roles" "github.com/transcom/mymove/pkg/storage/test" - "github.com/transcom/mymove/pkg/testdatagen" "github.com/transcom/mymove/pkg/unit" ) @@ -805,8 +804,6 @@ func (suite *PayloadsSuite) TestSearchMoves() { appCtx := suite.AppContextForTest() marines := models.AffiliationMARINES - spaceForce := models.AffiliationSPACEFORCE - army := models.AffiliationARMY moveUSMC := factory.BuildMove(suite.DB(), []factory.Customization{ { Model: models.ServiceMember{ @@ -814,73 +811,15 @@ func (suite *PayloadsSuite) TestSearchMoves() { }, }, }, nil) - moveSF := factory.BuildMove(suite.DB(), []factory.Customization{ - { - Model: models.ServiceMember{ - Affiliation: &spaceForce, - }, - }, - }, nil) - moveA := factory.BuildMove(suite.DB(), []factory.Customization{ - { - Model: models.ServiceMember{ - Affiliation: &army, - }, - }, - }, nil) - moveUSMC.Status = models.MoveStatusNeedsServiceCounseling - scheduledPickupDate := time.Date(testdatagen.GHCTestYear, time.September, 20, 0, 0, 0, 0, time.UTC) - scheduledDeliveryDate := time.Date(testdatagen.GHCTestYear, time.September, 20, 0, 0, 0, 0, time.UTC) - sitAllowance := int(90) - gbloc := "LKNQ" - storageFacility := factory.BuildStorageFacility(suite.DB(), nil, nil) - mtoShipment := factory.BuildMTOShipment(suite.DB(), []factory.Customization{ - { - Model: moveSF, - LinkOnly: true, - }, - { - Model: models.MTOShipment{ - Status: models.MTOShipmentStatusApproved, - ShipmentType: models.MTOShipmentTypeHHGIntoNTSDom, - CounselorRemarks: handlers.FmtString("counselor remark"), - SITDaysAllowance: &sitAllowance, - ScheduledPickupDate: &scheduledPickupDate, - ScheduledDeliveryDate: &scheduledDeliveryDate, - }, - }, - { - Model: storageFacility, - LinkOnly: true, - }, - }, nil) - - moveSF.MTOShipments = append(moveSF.MTOShipments, mtoShipment) - moveSF.ShipmentGBLOC = append(moveSF.ShipmentGBLOC, models.MoveToGBLOC{GBLOC: &gbloc}) moves := models.Moves{moveUSMC} - moveSpaceForce := models.Moves{moveSF} - moveArmy := models.Moves{moveA} + suite.Run("Success - Returns a ghcmessages Upload payload from Upload Struct Marine move with no shipments", func() { payload := SearchMoves(appCtx, moves) suite.IsType(payload, &ghcmessages.SearchMoves{}) suite.NotNil(payload) }) - suite.Run("Success - Returns a ghcmessages Upload payload from Upload Struct Non-Marine move, a shipment, and delivery/pickup time. ", func() { - payload := SearchMoves(appCtx, moveSpaceForce) - suite.IsType(payload, &ghcmessages.SearchMoves{}) - suite.NotNil(payload) - suite.NotNil(mtoShipment) - - suite.NotNil(moveA) - }) - suite.Run("Success - Returns a ghcmessages Upload payload from Upload Struct Army move, with no shipments. ", func() { - payload := SearchMoves(appCtx, moveArmy) - suite.IsType(payload, &ghcmessages.SearchMoves{}) - suite.NotNil(payload) - - }) } func (suite *PayloadsSuite) TestMarketCode() { From a3eada6c8b3f2886c0a1ade06df1378e2d0f66ff Mon Sep 17 00:00:00 2001 From: Jon Spight Date: Mon, 13 Jan 2025 21:30:20 +0000 Subject: [PATCH 50/51] moved SC to match INT placement --- pkg/factory/move_factory.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/pkg/factory/move_factory.go b/pkg/factory/move_factory.go index 3f923f95204..8561df50127 100644 --- a/pkg/factory/move_factory.go +++ b/pkg/factory/move_factory.go @@ -105,11 +105,6 @@ func BuildMove(db *pop.Connection, customs []Customization, traits []Trait) mode move.CloseoutOfficeID = &closeoutOffice.ID } - if scAssignedUserResult != nil { - move.SCAssignedUser = &scAssignedUser - move.SCAssignedID = &scAssignedUser.ID - } - if tooAssignedUserResult != nil { move.TOOAssignedUser = &tooAssignedUser move.TOOAssignedID = &tooAssignedUser.ID @@ -125,6 +120,11 @@ func BuildMove(db *pop.Connection, customs []Customization, traits []Trait) mode move.CounselingOfficeID = &counselingOffice.ID } + if scAssignedUserResult != nil { + move.SCAssignedUser = &scAssignedUser + move.SCAssignedID = &scAssignedUser.ID + } + // Overwrite values with those from assertions testdatagen.MergeModels(&move, cMove) From 37784db97a8de7658b6ce7860ce86c638338f1b5 Mon Sep 17 00:00:00 2001 From: Jon Spight Date: Mon, 13 Jan 2025 22:26:55 +0000 Subject: [PATCH 51/51] PR Fixes --- pkg/factory/move_factory.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/pkg/factory/move_factory.go b/pkg/factory/move_factory.go index 3f923f95204..8561df50127 100644 --- a/pkg/factory/move_factory.go +++ b/pkg/factory/move_factory.go @@ -105,11 +105,6 @@ func BuildMove(db *pop.Connection, customs []Customization, traits []Trait) mode move.CloseoutOfficeID = &closeoutOffice.ID } - if scAssignedUserResult != nil { - move.SCAssignedUser = &scAssignedUser - move.SCAssignedID = &scAssignedUser.ID - } - if tooAssignedUserResult != nil { move.TOOAssignedUser = &tooAssignedUser move.TOOAssignedID = &tooAssignedUser.ID @@ -125,6 +120,11 @@ func BuildMove(db *pop.Connection, customs []Customization, traits []Trait) mode move.CounselingOfficeID = &counselingOffice.ID } + if scAssignedUserResult != nil { + move.SCAssignedUser = &scAssignedUser + move.SCAssignedID = &scAssignedUser.ID + } + // Overwrite values with those from assertions testdatagen.MergeModels(&move, cMove)