diff --git a/pkg/models/document.go b/pkg/models/document.go index 7ca82d9aebc..6392434a6ef 100644 --- a/pkg/models/document.go +++ b/pkg/models/document.go @@ -71,6 +71,12 @@ func fetchDocumentWithAccessibilityCheck(db *pop.Connection, session *auth.Sessi return Document{}, err } + // encountered issues trying to filter userUploads using pop. + // going with the option to filter userUploads after the query. + if !includeDeletedDocs { + document.UserUploads = document.UserUploads.FilterDeleted() + } + if checkUserAccessiability { _, smErr := FetchServiceMemberForUser(db, session, document.ServiceMemberID) if smErr != nil { diff --git a/pkg/models/document_test.go b/pkg/models/document_test.go index 8ef56446f12..19e4e21b8c2 100644 --- a/pkg/models/document_test.go +++ b/pkg/models/document_test.go @@ -42,9 +42,17 @@ func (suite *ModelSuite) TestFetchDocument() { ApplicationName: auth.MilApp, ServiceMemberID: serviceMember.ID, } + userUpload := factory.BuildUserUpload(suite.DB(), nil, nil) + err := models.DeleteUserUpload(suite.DB(), &userUpload) + suite.Nil(err) + userUploads := models.UserUploads{userUpload} + document := models.Document{ + ID: *userUpload.DocumentID, ServiceMemberID: serviceMember.ID, + UserUploads: userUploads, } + userUpload.DocumentID = &document.ID verrs, err := suite.DB().ValidateAndSave(&document) if err != nil { @@ -58,6 +66,7 @@ func (suite *ModelSuite) TestFetchDocument() { doc, _ := models.FetchDocument(suite.DB(), &session, document.ID, false) suite.Equal(doc.ID, document.ID) + suite.Equal(0, len(doc.UserUploads)) } func (suite *ModelSuite) TestFetchDeletedDocument() { @@ -70,11 +79,19 @@ func (suite *ModelSuite) TestFetchDeletedDocument() { ServiceMemberID: serviceMember.ID, } + userUpload := factory.BuildUserUpload(suite.DB(), nil, nil) + err := models.DeleteUserUpload(suite.DB(), &userUpload) + suite.Nil(err) + userUploads := models.UserUploads{userUpload} + deletedAt := time.Date(2019, 8, 7, 0, 0, 0, 0, time.UTC) document := models.Document{ + ID: *userUpload.DocumentID, ServiceMemberID: serviceMember.ID, DeletedAt: &deletedAt, + UserUploads: userUploads, } + userUpload.DocumentID = &document.ID verrs, err := suite.DB().ValidateAndSave(&document) if err != nil { @@ -97,4 +114,5 @@ func (suite *ModelSuite) TestFetchDeletedDocument() { // fetches a nil document suite.Equal(doc2.ID, document.ID) suite.Equal(doc2.ServiceMemberID, serviceMember.ID) + suite.Equal(1, len(doc2.UserUploads)) } diff --git a/pkg/services/mto_shipment/mto_shipment_updater.go b/pkg/services/mto_shipment/mto_shipment_updater.go index 5b3bd8cb659..92ca8ba58c8 100644 --- a/pkg/services/mto_shipment/mto_shipment_updater.go +++ b/pkg/services/mto_shipment/mto_shipment_updater.go @@ -1063,15 +1063,27 @@ func reServiceCodesForShipment(shipment models.MTOShipment) []models.ReServiceCo // default service items that we want created as a side effect. // More info in MB-1140: https://dp3.atlassian.net/browse/MB-1140 + // international shipment service items are created in the shipment_approver switch shipment.ShipmentType { case models.MTOShipmentTypeHHG: + if shipment.MarketCode != models.MarketCodeInternational { + originZIP3 := shipment.PickupAddress.PostalCode[0:3] + destinationZIP3 := shipment.DestinationAddress.PostalCode[0:3] + + if originZIP3 == destinationZIP3 { + return []models.ReServiceCode{ + models.ReServiceCodeDSH, + models.ReServiceCodeFSC, + models.ReServiceCodeDOP, + models.ReServiceCodeDDP, + models.ReServiceCodeDPK, + models.ReServiceCodeDUPK, + } + } - originZIP3 := shipment.PickupAddress.PostalCode[0:3] - destinationZIP3 := shipment.DestinationAddress.PostalCode[0:3] - - if originZIP3 == destinationZIP3 { + // Need to create: Dom Linehaul, Fuel Surcharge, Dom Origin Price, Dom Destination Price, Dom Packing, and Dom Unpacking. return []models.ReServiceCode{ - models.ReServiceCodeDSH, + models.ReServiceCodeDLH, models.ReServiceCodeFSC, models.ReServiceCodeDOP, models.ReServiceCodeDDP, @@ -1079,16 +1091,6 @@ func reServiceCodesForShipment(shipment models.MTOShipment) []models.ReServiceCo models.ReServiceCodeDUPK, } } - - // Need to create: Dom Linehaul, Fuel Surcharge, Dom Origin Price, Dom Destination Price, Dom Packing, and Dom Unpacking. - return []models.ReServiceCode{ - models.ReServiceCodeDLH, - models.ReServiceCodeFSC, - models.ReServiceCodeDOP, - models.ReServiceCodeDDP, - models.ReServiceCodeDPK, - models.ReServiceCodeDUPK, - } case models.MTOShipmentTypeHHGIntoNTSDom: // Need to create: Dom Linehaul, Fuel Surcharge, Dom Origin Price, Dom Destination Price, Dom NTS Packing return []models.ReServiceCode{ diff --git a/pkg/services/mto_shipment/shipment_approver.go b/pkg/services/mto_shipment/shipment_approver.go index 4b8df67134a..52e849e469b 100644 --- a/pkg/services/mto_shipment/shipment_approver.go +++ b/pkg/services/mto_shipment/shipment_approver.go @@ -77,6 +77,13 @@ func (f *shipmentApprover) ApproveShipment(appCtx appcontext.AppContext, shipmen } } + // create international shipment service items + if shipment.ShipmentType == models.MTOShipmentTypeHHG && shipment.MarketCode == models.MarketCodeInternational { + err := models.CreateApprovedServiceItemsForShipment(appCtx.DB(), shipment) + if err != nil { + return shipment, err + } + } transactionError := appCtx.NewTransaction(func(txnAppCtx appcontext.AppContext) error { verrs, err := txnAppCtx.DB().ValidateAndSave(shipment) if verrs != nil && verrs.HasAny() { diff --git a/pkg/services/mto_shipment/shipment_approver_test.go b/pkg/services/mto_shipment/shipment_approver_test.go index a20a440c8f5..943cd4edb72 100644 --- a/pkg/services/mto_shipment/shipment_approver_test.go +++ b/pkg/services/mto_shipment/shipment_approver_test.go @@ -2,6 +2,7 @@ package mtoshipment import ( "math" + "slices" "time" "github.com/gofrs/uuid" @@ -13,6 +14,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/route" "github.com/transcom/mymove/pkg/route/mocks" "github.com/transcom/mymove/pkg/services" "github.com/transcom/mymove/pkg/services/ghcrateengine" @@ -188,6 +190,71 @@ func (suite *MTOShipmentServiceSuite) createApproveShipmentSubtestData() (subtes } func (suite *MTOShipmentServiceSuite) TestApproveShipment() { + suite.Run("If the international mtoShipment is approved successfully it should create pre approved mtoServiceItems", func() { + internationalShipment := factory.BuildMTOShipment(suite.AppContextForTest().DB(), []factory.Customization{ + { + Model: models.Move{ + Status: models.MoveStatusAPPROVED, + }, + }, + { + Model: models.Address{ + StreetAddress1: "Tester Address", + City: "Des Moines", + State: "IA", + PostalCode: "50314", + IsOconus: models.BoolPointer(false), + }, + Type: &factory.Addresses.PickupAddress, + }, + { + Model: models.MTOShipment{ + MarketCode: "i", + Status: models.MTOShipmentStatusSubmitted, + }, + }, + { + Model: models.Address{ + StreetAddress1: "JBER", + City: "Anchorage", + State: "AK", + PostalCode: "99505", + IsOconus: models.BoolPointer(true), + }, + Type: &factory.Addresses.DeliveryAddress, + }, + }, nil) + internationalShipmentEtag := etag.GenerateEtag(internationalShipment.UpdatedAt) + + shipmentRouter := NewShipmentRouter() + var serviceItemCreator services.MTOServiceItemCreator + var planner route.Planner + var moveWeights services.MoveWeights + + // Approve international shipment + shipmentApprover := NewShipmentApprover(shipmentRouter, serviceItemCreator, planner, moveWeights) + _, err := shipmentApprover.ApproveShipment(suite.AppContextForTest(), internationalShipment.ID, internationalShipmentEtag) + suite.NoError(err) + + // Get created pre approved service items + var serviceItems []models.MTOServiceItem + err2 := suite.AppContextForTest().DB().EagerPreload("ReService").Where("mto_shipment_id = ?", internationalShipment.ID).Order("created_at asc").All(&serviceItems) + suite.NoError(err2) + + expectedReserviceCodes := []models.ReServiceCode{ + models.ReServiceCodePOEFSC, + models.ReServiceCodeISLH, + models.ReServiceCodeIHPK, + models.ReServiceCodeIHUPK, + } + + suite.Equal(4, len(serviceItems)) + for i := 0; i < len(serviceItems); i++ { + actualReServiceCode := serviceItems[i].ReService.Code + suite.True(slices.Contains(expectedReserviceCodes, actualReServiceCode)) + } + }) + suite.Run("If the mtoShipment is approved successfully it should create approved mtoServiceItems", func() { subtestData := suite.createApproveShipmentSubtestData() appCtx := subtestData.appCtx