From 086bc54087fe06c5ec24ebb17df96a5ba021daeb Mon Sep 17 00:00:00 2001 From: Tevin Adams Date: Fri, 10 Jan 2025 15:24:14 +0000 Subject: [PATCH 01/17] required delivery date is populated on ub shipments --- pkg/models/re_contract_year.go | 14 +++ pkg/models/re_contract_year_test.go | 61 +++++++++- pkg/models/re_intl_transit_times.go | 15 +++ pkg/models/re_intl_transit_times_test.go | 20 ++++ pkg/models/re_rate_area.go | 4 +- pkg/models/re_rate_area_test.go | 6 +- .../per_unit_cents_lookup.go | 8 +- .../mto_shipment/mto_shipment_updater.go | 43 ++++++++ .../mto_shipment/mto_shipment_updater_test.go | 104 ++++++++++++++++++ pkg/services/mto_shipment/rules.go | 12 +- .../mto_shipment/shipment_approver.go | 8 ++ 11 files changed, 284 insertions(+), 11 deletions(-) create mode 100644 pkg/models/re_intl_transit_times_test.go diff --git a/pkg/models/re_contract_year.go b/pkg/models/re_contract_year.go index e24801e44a3..2425cfb3f69 100644 --- a/pkg/models/re_contract_year.go +++ b/pkg/models/re_contract_year.go @@ -71,6 +71,20 @@ func (r *ReContractYear) Validate(_ *pop.Connection) (*validate.Errors, error) { ), nil } +// a db stored proc that takes requested pickup date to get the contract +func FetchContractId(db *pop.Connection, requestedPickupDate time.Time) (uuid.UUID, error) { + if !requestedPickupDate.IsZero() { + var reContractYearId uuid.UUID + err := db.RawQuery("SELECT get_contract_id($1)", requestedPickupDate).First(&reContractYearId) + if err != nil { + return uuid.Nil, fmt.Errorf("error fetching contract year id for requested pickup date %s", requestedPickupDate) + } + + return reContractYearId, nil + } + return uuid.Nil, fmt.Errorf("error fetching contract ID - required parameters not provided") +} + func GetExpectedEscalationPriceContractsCount(contractYearName string) (ExpectedEscalationPriceContractsCount, error) { switch contractYearName { case BasePeriodYear1: diff --git a/pkg/models/re_contract_year_test.go b/pkg/models/re_contract_year_test.go index ad7b61403cc..64eee520ebb 100644 --- a/pkg/models/re_contract_year_test.go +++ b/pkg/models/re_contract_year_test.go @@ -4,8 +4,8 @@ import ( "time" "github.com/gofrs/uuid" - "github.com/transcom/mymove/pkg/models" + "github.com/transcom/mymove/pkg/testdatagen" ) func (suite *ModelSuite) TestReContractYearValidations() { @@ -52,3 +52,62 @@ func (suite *ModelSuite) TestReContractYearValidations() { suite.verifyValidationErrors(&badDatesReContractYear, expErrors) }) } + +func (suite *ModelSuite) TestReContractYearModel() { + suite.Run("test that FetchContractId returns the contractId given a requestedPickupDate", func() { + validReContractYear := testdatagen.MakeReContractYear(suite.DB(), testdatagen.Assertions{ + ReContractYear: models.ReContractYear{ + Name: "Base Period Year 1", + StartDate: time.Date(2019, time.October, 1, 0, 0, 0, 0, time.UTC), + EndDate: time.Date(2020, time.September, 30, 0, 0, 0, 0, time.UTC), + Escalation: 1.03, + EscalationCompounded: 1.74, + }, + }) + + requestedPickupDate := time.Date(2019, time.October, 25, 0, 0, 0, 0, time.UTC) + contractYearId, err := models.FetchContractId(suite.DB(), requestedPickupDate) + + suite.Nil(err) + suite.NotNil(contractYearId) + suite.Equal(contractYearId, validReContractYear.ContractID) + }) + + suite.Run("test that FetchContractId returns error when no requestedPickupDate is given", func() { + testdatagen.MakeReContractYear(suite.DB(), testdatagen.Assertions{ + ReContractYear: models.ReContractYear{ + Name: "Base Period Year 1", + StartDate: time.Date(2019, time.October, 1, 0, 0, 0, 0, time.UTC), + EndDate: time.Date(2020, time.September, 30, 0, 0, 0, 0, time.UTC), + Escalation: 1.03, + EscalationCompounded: 1.74, + }, + }) + + var time time.Time + contractYearId, err := models.FetchContractId(suite.DB(), time) + + suite.NotNil(err) + suite.Contains(err.Error(), "error fetching contract ID - required parameters not provided") + suite.Equal(contractYearId, uuid.Nil) + }) + + suite.Run("test that FetchContractId returns error when no contract is found for given requestedPickupDate", func() { + testdatagen.MakeReContractYear(suite.DB(), testdatagen.Assertions{ + ReContractYear: models.ReContractYear{ + Name: "Base Period Year 1", + StartDate: time.Date(2019, time.October, 1, 0, 0, 0, 0, time.UTC), + EndDate: time.Date(2020, time.September, 30, 0, 0, 0, 0, time.UTC), + Escalation: 1.03, + EscalationCompounded: 1.74, + }, + }) + requestedPickupDate := time.Date(2019, time.September, 1, 0, 0, 0, 0, time.UTC) + + contractYearId, err := models.FetchContractId(suite.DB(), requestedPickupDate) + + suite.NotNil(err) + suite.Contains(err.Error(), "error fetching contract year id") + suite.Equal(contractYearId, uuid.Nil) + }) +} diff --git a/pkg/models/re_intl_transit_times.go b/pkg/models/re_intl_transit_times.go index b5652894efa..6b8ba8fb192 100644 --- a/pkg/models/re_intl_transit_times.go +++ b/pkg/models/re_intl_transit_times.go @@ -3,6 +3,7 @@ package models import ( "time" + "github.com/gobuffalo/pop/v6" "github.com/gofrs/uuid" ) @@ -20,3 +21,17 @@ type InternationalTransitTime struct { func (InternationalTransitTime) TableName() string { return "re_intl_transit_times" } + +// fetch the re_intl_transit_time record from the db +func FetchInternationalTransitTime(db *pop.Connection, originRateAreaId uuid.UUID, destinationRateAreaId uuid.UUID) (InternationalTransitTime, error) { + var internationalTransitTime InternationalTransitTime + err := db. + Where("origin_rate_area_id = $1 and destination_rate_area_id = $2", originRateAreaId, destinationRateAreaId). + First(&internationalTransitTime) + + if err != nil { + return internationalTransitTime, err + } + + return internationalTransitTime, nil +} diff --git a/pkg/models/re_intl_transit_times_test.go b/pkg/models/re_intl_transit_times_test.go new file mode 100644 index 00000000000..81077af5b49 --- /dev/null +++ b/pkg/models/re_intl_transit_times_test.go @@ -0,0 +1,20 @@ +package models_test + +import ( + "github.com/gofrs/uuid" + "github.com/transcom/mymove/pkg/models" +) + +func (suite *ModelSuite) TestIntlTransitTimesModel() { + suite.Run("test that FetchInternationalTransitTime returns the re_intl_transit_times given an originRateAreaId and a destinationRateAreaId", func() { + originRateAreaId := uuid.FromStringOrNil("6e802149-7e46-4d7a-ab57-6c4df832085d") + destinationRateAreaId := uuid.FromStringOrNil("c18e25f9-ec34-41ca-8c1b-05558c8d6364") + + fetchedIntlTransitTime, err := models.FetchInternationalTransitTime(suite.DB(), originRateAreaId, destinationRateAreaId) + + suite.Nil(err) + suite.NotNil(fetchedIntlTransitTime) + suite.Equal(originRateAreaId, fetchedIntlTransitTime.OriginRateAreaId) + suite.Equal(destinationRateAreaId, fetchedIntlTransitTime.DestinationRateAreaId) + }) +} diff --git a/pkg/models/re_rate_area.go b/pkg/models/re_rate_area.go index 7b613b42a28..3558f7219dd 100644 --- a/pkg/models/re_rate_area.go +++ b/pkg/models/re_rate_area.go @@ -56,8 +56,8 @@ func FetchReRateAreaItem(tx *pop.Connection, contractID uuid.UUID, code string) } // a db stored proc that takes in an address id & a service code to get the rate area id for an address -func FetchRateAreaID(db *pop.Connection, addressID uuid.UUID, serviceID uuid.UUID, contractID uuid.UUID) (uuid.UUID, error) { - if addressID != uuid.Nil && serviceID != uuid.Nil && contractID != uuid.Nil { +func FetchRateAreaID(db *pop.Connection, addressID uuid.UUID, serviceID *uuid.UUID, contractID uuid.UUID) (uuid.UUID, error) { + if addressID != uuid.Nil && contractID != uuid.Nil { var rateAreaID uuid.UUID err := db.RawQuery("SELECT get_rate_area_id($1, $2, $3)", addressID, serviceID, contractID).First(&rateAreaID) if err != nil { diff --git a/pkg/models/re_rate_area_test.go b/pkg/models/re_rate_area_test.go index 87f310c2088..060c900c353 100644 --- a/pkg/models/re_rate_area_test.go +++ b/pkg/models/re_rate_area_test.go @@ -36,16 +36,16 @@ func (suite *ModelSuite) TestFetchRateAreaID() { service := factory.FetchReServiceByCode(suite.DB(), models.ReServiceCodeIHPK) contract := testdatagen.FetchOrMakeReContract(suite.DB(), testdatagen.Assertions{}) address := factory.BuildAddress(suite.DB(), nil, nil) - rateAreaId, err := models.FetchRateAreaID(suite.DB(), address.ID, service.ID, contract.ID) + rateAreaId, err := models.FetchRateAreaID(suite.DB(), address.ID, &service.ID, contract.ID) suite.NotNil(rateAreaId) suite.NoError(err) }) suite.Run("fail - receive error when not all values are provided", func() { var nilUuid uuid.UUID + nonNilUuid := uuid.Must(uuid.NewV4()) contract := testdatagen.FetchOrMakeReContract(suite.DB(), testdatagen.Assertions{}) - address := factory.BuildAddress(suite.DB(), nil, nil) - rateAreaId, err := models.FetchRateAreaID(suite.DB(), address.ID, nilUuid, contract.ID) + rateAreaId, err := models.FetchRateAreaID(suite.DB(), nilUuid, &nonNilUuid, contract.ID) suite.Equal(uuid.Nil, rateAreaId) suite.Error(err) }) diff --git a/pkg/payment_request/service_param_value_lookups/per_unit_cents_lookup.go b/pkg/payment_request/service_param_value_lookups/per_unit_cents_lookup.go index b339fbf43dd..68d59f13d27 100644 --- a/pkg/payment_request/service_param_value_lookups/per_unit_cents_lookup.go +++ b/pkg/payment_request/service_param_value_lookups/per_unit_cents_lookup.go @@ -24,7 +24,7 @@ func (p PerUnitCentsLookup) lookup(appCtx appcontext.AppContext, s *ServiceItemP switch p.ServiceItem.ReService.Code { case models.ReServiceCodeIHPK: // IHPK: Need rate area ID for the pickup address - rateAreaID, err := models.FetchRateAreaID(appCtx.DB(), *p.MTOShipment.PickupAddressID, serviceID, contractID) + rateAreaID, err := models.FetchRateAreaID(appCtx.DB(), *p.MTOShipment.PickupAddressID, &serviceID, contractID) if err != nil { return "", fmt.Errorf("error fetching rate area id for shipment ID: %s and service ID %s: %s", p.MTOShipment.ID, serviceID, err) } @@ -43,7 +43,7 @@ func (p PerUnitCentsLookup) lookup(appCtx appcontext.AppContext, s *ServiceItemP case models.ReServiceCodeIHUPK: // IHUPK: Need rate area ID for the destination address - rateAreaID, err := models.FetchRateAreaID(appCtx.DB(), *p.MTOShipment.PickupAddressID, serviceID, contractID) + rateAreaID, err := models.FetchRateAreaID(appCtx.DB(), *p.MTOShipment.PickupAddressID, &serviceID, contractID) if err != nil { return "", fmt.Errorf("error fetching rate area id for shipment ID: %s and service ID %s: %s", p.MTOShipment.ID, serviceID, err) } @@ -62,11 +62,11 @@ func (p PerUnitCentsLookup) lookup(appCtx appcontext.AppContext, s *ServiceItemP case models.ReServiceCodeISLH: // ISLH: Need rate area IDs for origin and destination - originRateAreaID, err := models.FetchRateAreaID(appCtx.DB(), *p.MTOShipment.PickupAddressID, serviceID, contractID) + originRateAreaID, err := models.FetchRateAreaID(appCtx.DB(), *p.MTOShipment.PickupAddressID, &serviceID, contractID) if err != nil { return "", fmt.Errorf("error fetching rate area id for origin address for shipment ID: %s and service ID %s: %s", p.MTOShipment.ID, serviceID, err) } - destRateAreaID, err := models.FetchRateAreaID(appCtx.DB(), *p.MTOShipment.DestinationAddressID, serviceID, contractID) + destRateAreaID, err := models.FetchRateAreaID(appCtx.DB(), *p.MTOShipment.DestinationAddressID, &serviceID, contractID) if err != nil { return "", fmt.Errorf("error fetching rate area id for destination address for shipment ID: %s and service ID %s: %s", p.MTOShipment.ID, serviceID, err) } diff --git a/pkg/services/mto_shipment/mto_shipment_updater.go b/pkg/services/mto_shipment/mto_shipment_updater.go index d30e6842292..2588dea8f23 100644 --- a/pkg/services/mto_shipment/mto_shipment_updater.go +++ b/pkg/services/mto_shipment/mto_shipment_updater.go @@ -1040,6 +1040,7 @@ func (o *mtoShipmentStatusUpdater) createShipmentServiceItems(appCtx appcontext. func (o *mtoShipmentStatusUpdater) setRequiredDeliveryDate(appCtx appcontext.AppContext, shipment *models.MTOShipment) error { if shipment.ScheduledPickupDate != nil && shipment.RequiredDeliveryDate == nil && + shipment.ShipmentType != models.MTOShipmentTypeUnaccompaniedBaggage && (shipment.PrimeEstimatedWeight != nil || shipment.NTSRecordedWeight != nil) { var pickupLocation *models.Address @@ -1079,6 +1080,13 @@ func (o *mtoShipmentStatusUpdater) setRequiredDeliveryDate(appCtx appcontext.App } shipment.RequiredDeliveryDate = requiredDeliveryDate + } else if shipment.ShipmentType == models.MTOShipmentTypeUnaccompaniedBaggage { + requiredDeliveryDate, calcErr := CalculateRequiredDeliveryDateUBShipment(appCtx, *shipment.PickupAddress, *shipment.DestinationAddress, *shipment.ScheduledPickupDate) + if calcErr != nil { + return calcErr + } + + shipment.RequiredDeliveryDate = &requiredDeliveryDate } return nil @@ -1240,6 +1248,41 @@ func CalculateRequiredDeliveryDate(appCtx appcontext.AppContext, planner route.P return &requiredDeliveryDate, nil } +// CalculateRequiredDeliveryDateUBShipment function is used to get the Required delivery Date of a UB shipment by finding the re_intl_transit_time using the origin and destination address rate areas. +// The transit time is then added to the day after the pickup date then that date is used as the required delivery date for the UB shipment. +func CalculateRequiredDeliveryDateUBShipment(appCtx appcontext.AppContext, pickupAddress models.Address, destinationAddress models.Address, pickupDate time.Time) (time.Time, error) { + + // Transit times does not include the pickup date. Setting the required delivery date to the day after pickup date + rdd := pickupDate.AddDate(0, 0, 1) + + // get the contract id + contractID, err := models.FetchContractId(appCtx.DB(), pickupDate) + if err != nil { + return rdd, err + } + + // get the rate area id for the origin address + originRateAreaID, err := models.FetchRateAreaID(appCtx.DB(), pickupAddress.ID, nil, contractID) + if err != nil { + return rdd, err + } + + // get the rate area id for the destination address + destRateAreaID, err := models.FetchRateAreaID(appCtx.DB(), destinationAddress.ID, nil, contractID) + if err != nil { + return rdd, err + } + + // lookup the intl transit time + internationalTransitTime, err := models.FetchInternationalTransitTime(appCtx.DB(), originRateAreaID, destRateAreaID) + if err != nil { + return rdd, err + } + + // rdd plus the intl ub transit time + return rdd.AddDate(0, 0, *internationalTransitTime.UbTransitTime), nil +} + // This private function is used to generically construct service items when shipments are approved. func constructMTOServiceItemModels(shipmentID uuid.UUID, mtoID uuid.UUID, reServiceCodes []models.ReServiceCode) models.MTOServiceItems { serviceItems := make(models.MTOServiceItems, len(reServiceCodes)) diff --git a/pkg/services/mto_shipment/mto_shipment_updater_test.go b/pkg/services/mto_shipment/mto_shipment_updater_test.go index ee3fde58147..23830acb59c 100644 --- a/pkg/services/mto_shipment/mto_shipment_updater_test.go +++ b/pkg/services/mto_shipment/mto_shipment_updater_test.go @@ -3445,3 +3445,107 @@ func (suite *MTOShipmentServiceSuite) TestUpdateStatusServiceItems() { suite.Equal(models.ReServiceCodeDSH, serviceItems[0].ReService.Code) }) } + +func (suite *MTOShipmentServiceSuite) TestUpdatingUBShipment() { + suite.Run("Successfully update Required Delivery Date when a UB shipment is updated", func() { + builder := query.NewQueryBuilder() + fetcher := fetch.NewFetcher(builder) + planner := &mocks.Planner{} + planner.On("ZipTransitDistance", + mock.AnythingOfType("*appcontext.appContext"), + mock.Anything, + mock.Anything, + false, + false, + ).Return(1000, nil) + moveRouter := moveservices.NewMoveRouter() + moveWeights := moveservices.NewMoveWeights(NewShipmentReweighRequester()) + mockShipmentRecalculator := mockservices.PaymentRequestShipmentRecalculator{} + mockShipmentRecalculator.On("ShipmentRecalculatePaymentRequest", + mock.AnythingOfType("*appcontext.appContext"), + mock.AnythingOfType("uuid.UUID"), + ).Return(&models.PaymentRequests{}, nil) + mockSender := setUpMockNotificationSender() + addressCreator := address.NewAddressCreator() + addressUpdater := address.NewAddressUpdater() + session := auth.Session{} + mockedUpdater := NewPrimeMTOShipmentUpdater(builder, fetcher, planner, moveRouter, moveWeights, mockSender, &mockShipmentRecalculator, addressUpdater, addressCreator) + + destinationAddress := factory.BuildAddress(suite.DB(), []factory.Customization{ + { + Model: models.Address{ + StreetAddress1: "JBER", + City: "Anchorage", + State: "AK", + PostalCode: "99505", + IsOconus: models.BoolPointer(true), + }, + }, + }, nil) + + pickupAddress := factory.BuildAddress(suite.DB(), []factory.Customization{ + { + Model: models.Address{ + StreetAddress1: "Tester Address", + City: "Des Moines", + State: "IA", + PostalCode: "50314", + IsOconus: models.BoolPointer(false), + }, + }, + }, nil) + + validReContractYear := testdatagen.MakeReContractYear(suite.DB(), testdatagen.Assertions{ + ReContractYear: models.ReContractYear{ + Name: "Base Period Year 1", + StartDate: time.Date(2019, time.October, 1, 0, 0, 0, 0, time.UTC), + EndDate: time.Date(2020, time.September, 30, 0, 0, 0, 0, time.UTC), + Escalation: 1.03, + EscalationCompounded: 1.74, + }, + }) + + pickupDate := validReContractYear.StartDate.AddDate(0, 0, 10) + now := time.Now() + firstAvailableDeliveryDate := now.Add(time.Hour * 24 * 4) + scheduledDeliveryDate := now.Add(time.Hour * 24 * 4) + primeEstimatedWeight := unit.Pound(1234) + + dbUBShipment := factory.BuildMTOShipmentMinimal(suite.DB(), []factory.Customization{ + { + Model: models.MTOShipment{ + ShipmentType: models.MTOShipmentTypeUnaccompaniedBaggage, + FirstAvailableDeliveryDate: &firstAvailableDeliveryDate, + ScheduledPickupDate: &pickupDate, + ApprovedDate: &firstAvailableDeliveryDate, + PrimeEstimatedWeight: &primeEstimatedWeight, + ScheduledDeliveryDate: &scheduledDeliveryDate, + Status: models.MTOShipmentStatusApproved, + PickupAddressID: &pickupAddress.ID, + DestinationAddressID: &destinationAddress.ID, + RequestedPickupDate: &pickupDate, + }, + }, + { + Model: models.Move{ + AvailableToPrimeAt: &now, + ApprovedAt: &now, + }, + }, + }, nil) + + eTag := etag.GenerateEtag(dbUBShipment.UpdatedAt) + primeActualWeight := unit.Pound(1234) + + updatedShipment := &models.MTOShipment{ + ID: dbUBShipment.ID, + PrimeActualWeight: &primeActualWeight, + RequestedPickupDate: dbUBShipment.RequestedPickupDate, + } + + updatedShipment, err := mockedUpdater.UpdateMTOShipment(suite.AppContextWithSessionForTest(&session), updatedShipment, eTag, "test") + + suite.Require().NoError(err) + suite.NotNil(updatedShipment.RequiredDeliveryDate) + }) +} diff --git a/pkg/services/mto_shipment/rules.go b/pkg/services/mto_shipment/rules.go index e9579b24aae..621583f428d 100644 --- a/pkg/services/mto_shipment/rules.go +++ b/pkg/services/mto_shipment/rules.go @@ -337,7 +337,7 @@ func checkPrimeValidationsOnModel(planner route.Planner) validator { // If we have all the data, calculate RDD if latestSchedPickupDate != nil && (latestEstimatedWeight != nil || (older.ShipmentType == models.MTOShipmentTypeHHGOutOfNTSDom && - older.NTSRecordedWeight != nil)) && latestPickupAddress != nil && latestDestinationAddress != nil { + older.NTSRecordedWeight != nil)) && latestPickupAddress != nil && latestDestinationAddress != nil && older.ShipmentType != models.MTOShipmentTypeUnaccompaniedBaggage { weight := latestEstimatedWeight if older.ShipmentType == models.MTOShipmentTypeHHGOutOfNTSDom && older.NTSRecordedWeight != nil { weight = older.NTSRecordedWeight @@ -349,6 +349,16 @@ func checkPrimeValidationsOnModel(planner route.Planner) validator { } newer.RequiredDeliveryDate = requiredDeliveryDate } + + // RDD for UB shipments only need the pick up date, shipment origin address and destination address + if older.ShipmentType == models.MTOShipmentTypeUnaccompaniedBaggage && older.ScheduledPickupDate != nil { + requiredDeliveryDate, calcErr := CalculateRequiredDeliveryDateUBShipment(appCtx, *older.PickupAddress, *older.DestinationAddress, *older.ScheduledPickupDate) + if calcErr != nil { + return calcErr + } + + newer.RequiredDeliveryDate = &requiredDeliveryDate + } return verrs }) } diff --git a/pkg/services/mto_shipment/shipment_approver.go b/pkg/services/mto_shipment/shipment_approver.go index bb7c5245617..c5ace2e2e67 100644 --- a/pkg/services/mto_shipment/shipment_approver.go +++ b/pkg/services/mto_shipment/shipment_approver.go @@ -184,6 +184,7 @@ func (f *shipmentApprover) findShipment(appCtx appcontext.AppContext, shipmentID func (f *shipmentApprover) setRequiredDeliveryDate(appCtx appcontext.AppContext, shipment *models.MTOShipment) error { if shipment.ScheduledPickupDate != nil && shipment.RequiredDeliveryDate == nil && + shipment.ShipmentType != models.MTOShipmentTypeUnaccompaniedBaggage && (shipment.PrimeEstimatedWeight != nil || (shipment.ShipmentType == models.MTOShipmentTypeHHGOutOfNTSDom && shipment.NTSRecordedWeight != nil)) { @@ -217,6 +218,13 @@ func (f *shipmentApprover) setRequiredDeliveryDate(appCtx appcontext.AppContext, } shipment.RequiredDeliveryDate = requiredDeliveryDate + } else if shipment.ScheduledPickupDate != nil && shipment.ShipmentType == models.MTOShipmentTypeUnaccompaniedBaggage { + requiredDeliveryDate, calcErr := CalculateRequiredDeliveryDateUBShipment(appCtx, *shipment.PickupAddress, *shipment.DestinationAddress, *shipment.ScheduledPickupDate) + if calcErr != nil { + return calcErr + } + + shipment.RequiredDeliveryDate = &requiredDeliveryDate } return nil From a691148d4e7701d1c67958f05253cfb635fb299b Mon Sep 17 00:00:00 2001 From: Tevin Adams Date: Fri, 10 Jan 2025 15:52:27 +0000 Subject: [PATCH 02/17] comment adjustment --- pkg/services/mto_shipment/rules.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/services/mto_shipment/rules.go b/pkg/services/mto_shipment/rules.go index 621583f428d..2d28203bb0d 100644 --- a/pkg/services/mto_shipment/rules.go +++ b/pkg/services/mto_shipment/rules.go @@ -350,7 +350,7 @@ func checkPrimeValidationsOnModel(planner route.Planner) validator { newer.RequiredDeliveryDate = requiredDeliveryDate } - // RDD for UB shipments only need the pick up date, shipment origin address and destination address + // RDD for UB shipments only need the pick up date, shipment origin address and destination address to determine required delivery date if older.ShipmentType == models.MTOShipmentTypeUnaccompaniedBaggage && older.ScheduledPickupDate != nil { requiredDeliveryDate, calcErr := CalculateRequiredDeliveryDateUBShipment(appCtx, *older.PickupAddress, *older.DestinationAddress, *older.ScheduledPickupDate) if calcErr != nil { From 92108daabb458adce25b1656dcb2cb7d4f8b2d72 Mon Sep 17 00:00:00 2001 From: Tevin Adams Date: Fri, 10 Jan 2025 16:13:05 +0000 Subject: [PATCH 03/17] Fixing spaces --- pkg/models/re_contract_year_test.go | 1 + pkg/models/re_intl_transit_times_test.go | 1 + 2 files changed, 2 insertions(+) diff --git a/pkg/models/re_contract_year_test.go b/pkg/models/re_contract_year_test.go index 64eee520ebb..5a29320d76f 100644 --- a/pkg/models/re_contract_year_test.go +++ b/pkg/models/re_contract_year_test.go @@ -4,6 +4,7 @@ import ( "time" "github.com/gofrs/uuid" + "github.com/transcom/mymove/pkg/models" "github.com/transcom/mymove/pkg/testdatagen" ) diff --git a/pkg/models/re_intl_transit_times_test.go b/pkg/models/re_intl_transit_times_test.go index 81077af5b49..13e0ec45019 100644 --- a/pkg/models/re_intl_transit_times_test.go +++ b/pkg/models/re_intl_transit_times_test.go @@ -2,6 +2,7 @@ package models_test import ( "github.com/gofrs/uuid" + "github.com/transcom/mymove/pkg/models" ) From 35e109c0cb00937426adaa8f2e81961e8a90a3ae Mon Sep 17 00:00:00 2001 From: Tevin Adams Date: Fri, 10 Jan 2025 20:25:47 +0000 Subject: [PATCH 04/17] Test adjustments --- pkg/factory/mto_shipment_factory.go | 6 +++++- pkg/services/mto_shipment/shipment_approver.go | 2 +- .../mto_shipment/shipment_approver_test.go | 16 ++++++++++------ 3 files changed, 16 insertions(+), 8 deletions(-) diff --git a/pkg/factory/mto_shipment_factory.go b/pkg/factory/mto_shipment_factory.go index 1c7858d572f..a8b2d365d40 100644 --- a/pkg/factory/mto_shipment_factory.go +++ b/pkg/factory/mto_shipment_factory.go @@ -107,7 +107,11 @@ func buildMTOShipmentWithBuildType(db *pop.Connection, customs []Customization, if shipmentHasPickupDetails { newMTOShipment.RequestedPickupDate = models.TimePointer(time.Date(GHCTestYear, time.March, 15, 0, 0, 0, 0, time.UTC)) - newMTOShipment.ScheduledPickupDate = models.TimePointer(time.Date(GHCTestYear, time.March, 16, 0, 0, 0, 0, time.UTC)) + if cMtoShipment.ScheduledPickupDate == nil { + newMTOShipment.ScheduledPickupDate = models.TimePointer(time.Date(GHCTestYear, time.March, 16, 0, 0, 0, 0, time.UTC)) + } else { + newMTOShipment.ScheduledPickupDate = cMtoShipment.ScheduledPickupDate + } newMTOShipment.ActualPickupDate = models.TimePointer(time.Date(GHCTestYear, time.March, 16, 0, 0, 0, 0, time.UTC)) } diff --git a/pkg/services/mto_shipment/shipment_approver.go b/pkg/services/mto_shipment/shipment_approver.go index c5ace2e2e67..b12131e6556 100644 --- a/pkg/services/mto_shipment/shipment_approver.go +++ b/pkg/services/mto_shipment/shipment_approver.go @@ -218,7 +218,7 @@ func (f *shipmentApprover) setRequiredDeliveryDate(appCtx appcontext.AppContext, } shipment.RequiredDeliveryDate = requiredDeliveryDate - } else if shipment.ScheduledPickupDate != nil && shipment.ShipmentType == models.MTOShipmentTypeUnaccompaniedBaggage { + } else if shipment.ScheduledPickupDate != nil && !shipment.ScheduledPickupDate.IsZero() && shipment.ShipmentType == models.MTOShipmentTypeUnaccompaniedBaggage { requiredDeliveryDate, calcErr := CalculateRequiredDeliveryDateUBShipment(appCtx, *shipment.PickupAddress, *shipment.DestinationAddress, *shipment.ScheduledPickupDate) if calcErr != nil { return calcErr diff --git a/pkg/services/mto_shipment/shipment_approver_test.go b/pkg/services/mto_shipment/shipment_approver_test.go index 67dd08fec47..9d1d1cf9f8a 100644 --- a/pkg/services/mto_shipment/shipment_approver_test.go +++ b/pkg/services/mto_shipment/shipment_approver_test.go @@ -916,6 +916,7 @@ func (suite *MTOShipmentServiceSuite) TestApproveShipment() { }) suite.Run("If the OCONUS to CONUS UB mtoShipment is approved successfully it should create pre approved mtoServiceItems", func() { + var scheduledPickupDate time.Time internationalShipment := factory.BuildMTOShipment(suite.AppContextForTest().DB(), []factory.Customization{ { Model: models.Move{ @@ -934,9 +935,10 @@ func (suite *MTOShipmentServiceSuite) TestApproveShipment() { }, { Model: models.MTOShipment{ - MarketCode: models.MarketCodeInternational, - Status: models.MTOShipmentStatusSubmitted, - ShipmentType: models.MTOShipmentTypeUnaccompaniedBaggage, + MarketCode: models.MarketCodeInternational, + Status: models.MTOShipmentStatusSubmitted, + ShipmentType: models.MTOShipmentTypeUnaccompaniedBaggage, + ScheduledPickupDate: &scheduledPickupDate, }, }, { @@ -976,6 +978,7 @@ func (suite *MTOShipmentServiceSuite) TestApproveShipment() { }) suite.Run("If the OCONUS to OCONUS UB mtoShipment is approved successfully it should create pre approved mtoServiceItems", func() { + var scheduledPickupDate time.Time internationalShipment := factory.BuildMTOShipment(suite.AppContextForTest().DB(), []factory.Customization{ { Model: models.Move{ @@ -994,9 +997,10 @@ func (suite *MTOShipmentServiceSuite) TestApproveShipment() { }, { Model: models.MTOShipment{ - MarketCode: models.MarketCodeInternational, - Status: models.MTOShipmentStatusSubmitted, - ShipmentType: models.MTOShipmentTypeUnaccompaniedBaggage, + MarketCode: models.MarketCodeInternational, + Status: models.MTOShipmentStatusSubmitted, + ShipmentType: models.MTOShipmentTypeUnaccompaniedBaggage, + ScheduledPickupDate: &scheduledPickupDate, }, }, { From aa2876030b747fde41e8b6ae6924feeb3a713cac Mon Sep 17 00:00:00 2001 From: Tevin Adams Date: Mon, 13 Jan 2025 18:01:15 +0000 Subject: [PATCH 05/17] Condition adjustment --- pkg/services/mto_shipment/mto_shipment_updater.go | 2 +- pkg/services/mto_shipment/rules.go | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pkg/services/mto_shipment/mto_shipment_updater.go b/pkg/services/mto_shipment/mto_shipment_updater.go index 2588dea8f23..56e6f6c3e36 100644 --- a/pkg/services/mto_shipment/mto_shipment_updater.go +++ b/pkg/services/mto_shipment/mto_shipment_updater.go @@ -1080,7 +1080,7 @@ func (o *mtoShipmentStatusUpdater) setRequiredDeliveryDate(appCtx appcontext.App } shipment.RequiredDeliveryDate = requiredDeliveryDate - } else if shipment.ShipmentType == models.MTOShipmentTypeUnaccompaniedBaggage { + } else if shipment.ShipmentType == models.MTOShipmentTypeUnaccompaniedBaggage && shipment.ScheduledPickupDate != nil && !shipment.ScheduledDeliveryDate.IsZero() { requiredDeliveryDate, calcErr := CalculateRequiredDeliveryDateUBShipment(appCtx, *shipment.PickupAddress, *shipment.DestinationAddress, *shipment.ScheduledPickupDate) if calcErr != nil { return calcErr diff --git a/pkg/services/mto_shipment/rules.go b/pkg/services/mto_shipment/rules.go index 2d28203bb0d..00d4bd7d2a4 100644 --- a/pkg/services/mto_shipment/rules.go +++ b/pkg/services/mto_shipment/rules.go @@ -351,8 +351,8 @@ func checkPrimeValidationsOnModel(planner route.Planner) validator { } // RDD for UB shipments only need the pick up date, shipment origin address and destination address to determine required delivery date - if older.ShipmentType == models.MTOShipmentTypeUnaccompaniedBaggage && older.ScheduledPickupDate != nil { - requiredDeliveryDate, calcErr := CalculateRequiredDeliveryDateUBShipment(appCtx, *older.PickupAddress, *older.DestinationAddress, *older.ScheduledPickupDate) + if older.ShipmentType == models.MTOShipmentTypeUnaccompaniedBaggage && latestSchedPickupDate != nil && !latestSchedPickupDate.IsZero() { + requiredDeliveryDate, calcErr := CalculateRequiredDeliveryDateUBShipment(appCtx, *older.PickupAddress, *older.DestinationAddress, *latestSchedPickupDate) if calcErr != nil { return calcErr } From 2d24eef205cb39ee6cbbea2ca4b0353631b66729 Mon Sep 17 00:00:00 2001 From: Tevin Adams Date: Tue, 14 Jan 2025 18:58:58 +0000 Subject: [PATCH 06/17] Adding hhgTransit logic --- .../mto_shipment/mto_shipment_updater.go | 19 ++++++++++++++----- pkg/services/mto_shipment/rules.go | 2 +- .../mto_shipment/shipment_approver.go | 2 +- 3 files changed, 16 insertions(+), 7 deletions(-) diff --git a/pkg/services/mto_shipment/mto_shipment_updater.go b/pkg/services/mto_shipment/mto_shipment_updater.go index 2fa92e622cc..e82899ce46e 100644 --- a/pkg/services/mto_shipment/mto_shipment_updater.go +++ b/pkg/services/mto_shipment/mto_shipment_updater.go @@ -1081,7 +1081,7 @@ func (o *mtoShipmentStatusUpdater) setRequiredDeliveryDate(appCtx appcontext.App shipment.RequiredDeliveryDate = requiredDeliveryDate } else if shipment.ShipmentType == models.MTOShipmentTypeUnaccompaniedBaggage && shipment.ScheduledPickupDate != nil && !shipment.ScheduledDeliveryDate.IsZero() { - requiredDeliveryDate, calcErr := CalculateRequiredDeliveryDateUBShipment(appCtx, *shipment.PickupAddress, *shipment.DestinationAddress, *shipment.ScheduledPickupDate) + requiredDeliveryDate, calcErr := CalculateRequiredDeliveryDateForInternationalShipment(appCtx, *shipment.PickupAddress, *shipment.DestinationAddress, *shipment.ScheduledPickupDate, shipment.ShipmentType) if calcErr != nil { return calcErr } @@ -1248,9 +1248,9 @@ func CalculateRequiredDeliveryDate(appCtx appcontext.AppContext, planner route.P return &requiredDeliveryDate, nil } -// CalculateRequiredDeliveryDateUBShipment function is used to get the Required delivery Date of a UB shipment by finding the re_intl_transit_time using the origin and destination address rate areas. +// CalculateRequiredDeliveryDateForInternationalShipment function is used to get the Required delivery Date of a UB shipment by finding the re_intl_transit_time using the origin and destination address rate areas. // The transit time is then added to the day after the pickup date then that date is used as the required delivery date for the UB shipment. -func CalculateRequiredDeliveryDateUBShipment(appCtx appcontext.AppContext, pickupAddress models.Address, destinationAddress models.Address, pickupDate time.Time) (time.Time, error) { +func CalculateRequiredDeliveryDateForInternationalShipment(appCtx appcontext.AppContext, pickupAddress models.Address, destinationAddress models.Address, pickupDate time.Time, shipmentType models.MTOShipmentType) (time.Time, error) { // Transit times does not include the pickup date. Setting the required delivery date to the day after pickup date rdd := pickupDate.AddDate(0, 0, 1) @@ -1279,8 +1279,17 @@ func CalculateRequiredDeliveryDateUBShipment(appCtx appcontext.AppContext, picku return rdd, err } - // rdd plus the intl ub transit time - return rdd.AddDate(0, 0, *internationalTransitTime.UbTransitTime), nil + if shipmentType == models.MTOShipmentTypeHHG { + // rdd plus the intl hhg transit time + return rdd.AddDate(0, 0, *internationalTransitTime.HhgTransitTime), nil + } + + if shipmentType == models.MTOShipmentTypeUnaccompaniedBaggage { + // rdd plus the intl ub transit time + return rdd.AddDate(0, 0, *internationalTransitTime.UbTransitTime), nil + } + + return rdd, nil } // This private function is used to generically construct service items when shipments are approved. diff --git a/pkg/services/mto_shipment/rules.go b/pkg/services/mto_shipment/rules.go index 00d4bd7d2a4..282c52d97f0 100644 --- a/pkg/services/mto_shipment/rules.go +++ b/pkg/services/mto_shipment/rules.go @@ -352,7 +352,7 @@ func checkPrimeValidationsOnModel(planner route.Planner) validator { // RDD for UB shipments only need the pick up date, shipment origin address and destination address to determine required delivery date if older.ShipmentType == models.MTOShipmentTypeUnaccompaniedBaggage && latestSchedPickupDate != nil && !latestSchedPickupDate.IsZero() { - requiredDeliveryDate, calcErr := CalculateRequiredDeliveryDateUBShipment(appCtx, *older.PickupAddress, *older.DestinationAddress, *latestSchedPickupDate) + requiredDeliveryDate, calcErr := CalculateRequiredDeliveryDateForInternationalShipment(appCtx, *older.PickupAddress, *older.DestinationAddress, *latestSchedPickupDate, older.ShipmentType) if calcErr != nil { return calcErr } diff --git a/pkg/services/mto_shipment/shipment_approver.go b/pkg/services/mto_shipment/shipment_approver.go index b331dfb1a96..89fd2137d2f 100644 --- a/pkg/services/mto_shipment/shipment_approver.go +++ b/pkg/services/mto_shipment/shipment_approver.go @@ -221,7 +221,7 @@ func (f *shipmentApprover) setRequiredDeliveryDate(appCtx appcontext.AppContext, shipment.RequiredDeliveryDate = requiredDeliveryDate } else if shipment.ScheduledPickupDate != nil && !shipment.ScheduledPickupDate.IsZero() && shipment.ShipmentType == models.MTOShipmentTypeUnaccompaniedBaggage { - requiredDeliveryDate, calcErr := CalculateRequiredDeliveryDateUBShipment(appCtx, *shipment.PickupAddress, *shipment.DestinationAddress, *shipment.ScheduledPickupDate) + requiredDeliveryDate, calcErr := CalculateRequiredDeliveryDateForInternationalShipment(appCtx, *shipment.PickupAddress, *shipment.DestinationAddress, *shipment.ScheduledPickupDate, shipment.ShipmentType) if calcErr != nil { return calcErr } From b8c7d88fbe402b72fcc4c9af11a3bcaa11a5f8d8 Mon Sep 17 00:00:00 2001 From: Tevin Adams Date: Tue, 21 Jan 2025 20:06:57 +0000 Subject: [PATCH 07/17] Refactor --- pkg/handlers/primeapiv3/mto_shipment.go | 2 +- pkg/models/re_contract_year.go | 2 +- pkg/models/re_intl_transit_times.go | 5 +++-- pkg/services/mto_shipment/mto_shipment_updater.go | 11 ++++++++++- pkg/services/mto_shipment/rules.go | 9 --------- 5 files changed, 15 insertions(+), 14 deletions(-) diff --git a/pkg/handlers/primeapiv3/mto_shipment.go b/pkg/handlers/primeapiv3/mto_shipment.go index aa8476f6267..4befec26bfc 100644 --- a/pkg/handlers/primeapiv3/mto_shipment.go +++ b/pkg/handlers/primeapiv3/mto_shipment.go @@ -225,7 +225,7 @@ func (h UpdateMTOShipmentHandler) Handle(params mtoshipmentops.UpdateMTOShipment payloads.ClientError(handlers.PreconditionErrMessage, err.Error(), h.GetTraceIDFromRequest(params.HTTPRequest))), err default: return mtoshipmentops.NewUpdateMTOShipmentInternalServerError().WithPayload( - payloads.InternalServerError(nil, h.GetTraceIDFromRequest(params.HTTPRequest))), err + payloads.InternalServerError(handlers.FmtString(err.Error()), h.GetTraceIDFromRequest(params.HTTPRequest))), err } } mtoShipmentPayload := payloads.MTOShipment(mtoShipment) diff --git a/pkg/models/re_contract_year.go b/pkg/models/re_contract_year.go index 2425cfb3f69..211f8012532 100644 --- a/pkg/models/re_contract_year.go +++ b/pkg/models/re_contract_year.go @@ -71,7 +71,7 @@ func (r *ReContractYear) Validate(_ *pop.Connection) (*validate.Errors, error) { ), nil } -// a db stored proc that takes requested pickup date to get the contract +// This function uses a raw query that calls db function get_contract to get the reContractYearId in respects to the requestedPickupDate func FetchContractId(db *pop.Connection, requestedPickupDate time.Time) (uuid.UUID, error) { if !requestedPickupDate.IsZero() { var reContractYearId uuid.UUID diff --git a/pkg/models/re_intl_transit_times.go b/pkg/models/re_intl_transit_times.go index 6b8ba8fb192..b2f1f83e7e3 100644 --- a/pkg/models/re_intl_transit_times.go +++ b/pkg/models/re_intl_transit_times.go @@ -5,6 +5,7 @@ import ( "github.com/gobuffalo/pop/v6" "github.com/gofrs/uuid" + "github.com/pkg/errors" ) type InternationalTransitTime struct { @@ -26,11 +27,11 @@ func (InternationalTransitTime) TableName() string { func FetchInternationalTransitTime(db *pop.Connection, originRateAreaId uuid.UUID, destinationRateAreaId uuid.UUID) (InternationalTransitTime, error) { var internationalTransitTime InternationalTransitTime err := db. - Where("origin_rate_area_id = $1 and destination_rate_area_id = $2", originRateAreaId, destinationRateAreaId). + Where("origin_rate_area_id = $1 and destination_rate_area_id = 3", originRateAreaId). First(&internationalTransitTime) if err != nil { - return internationalTransitTime, err + return internationalTransitTime, errors.Errorf("could not look up intl transit time") } return internationalTransitTime, nil diff --git a/pkg/services/mto_shipment/mto_shipment_updater.go b/pkg/services/mto_shipment/mto_shipment_updater.go index ff3583747cc..3862eb99238 100644 --- a/pkg/services/mto_shipment/mto_shipment_updater.go +++ b/pkg/services/mto_shipment/mto_shipment_updater.go @@ -846,6 +846,15 @@ func (f *mtoShipmentUpdater) updateShipmentRecord(appCtx appcontext.AppContext, // when populating the market_code column, it is considered domestic if both pickup & dest are CONUS addresses newShipment = models.DetermineShipmentMarketCode(newShipment) + // RDD for UB shipments only need the pick up date, shipment origin address and destination address to determine required delivery date + if newShipment.ScheduledPickupDate != nil && !newShipment.ScheduledPickupDate.IsZero() && newShipment.ShipmentType == models.MTOShipmentTypeUnaccompaniedBaggage { + calculatedRDD, err := CalculateRequiredDeliveryDateForInternationalShipment(appCtx, *newShipment.PickupAddress, *newShipment.DestinationAddress, *newShipment.ScheduledPickupDate, newShipment.ShipmentType) + if err != nil { + return err + } + newShipment.RequestedDeliveryDate = &calculatedRDD + } + if err := txnAppCtx.DB().Update(newShipment); err != nil { return err } @@ -917,7 +926,7 @@ func (f *mtoShipmentUpdater) updateShipmentRecord(appCtx appcontext.AppContext, if t, ok := transactionError.(StaleIdentifierError); ok { return apperror.NewPreconditionFailedError(dbShipment.ID, t) } - return apperror.NewQueryError("mtoShipment", transactionError, "") + return apperror.NewQueryError("mtoShipment", transactionError, transactionError.Error()) } if len(autoReweighShipments) > 0 { diff --git a/pkg/services/mto_shipment/rules.go b/pkg/services/mto_shipment/rules.go index 20934bae56a..77bf72a55b8 100644 --- a/pkg/services/mto_shipment/rules.go +++ b/pkg/services/mto_shipment/rules.go @@ -350,15 +350,6 @@ func checkPrimeValidationsOnModel(planner route.Planner) validator { newer.RequiredDeliveryDate = requiredDeliveryDate } - // RDD for UB shipments only need the pick up date, shipment origin address and destination address to determine required delivery date - if older.ShipmentType == models.MTOShipmentTypeUnaccompaniedBaggage && latestSchedPickupDate != nil && !latestSchedPickupDate.IsZero() { - requiredDeliveryDate, calcErr := CalculateRequiredDeliveryDateForInternationalShipment(appCtx, *older.PickupAddress, *older.DestinationAddress, *latestSchedPickupDate, older.ShipmentType) - if calcErr != nil { - return calcErr - } - - newer.RequiredDeliveryDate = &requiredDeliveryDate - } return verrs }) } From a8a122b9580559e1872e860cb3d06a6c4e99ab68 Mon Sep 17 00:00:00 2001 From: Tevin Adams Date: Wed, 22 Jan 2025 15:08:34 +0000 Subject: [PATCH 08/17] Typo in sql query --- pkg/models/re_intl_transit_times.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/models/re_intl_transit_times.go b/pkg/models/re_intl_transit_times.go index b2f1f83e7e3..f1bc08747f1 100644 --- a/pkg/models/re_intl_transit_times.go +++ b/pkg/models/re_intl_transit_times.go @@ -27,7 +27,7 @@ func (InternationalTransitTime) TableName() string { func FetchInternationalTransitTime(db *pop.Connection, originRateAreaId uuid.UUID, destinationRateAreaId uuid.UUID) (InternationalTransitTime, error) { var internationalTransitTime InternationalTransitTime err := db. - Where("origin_rate_area_id = $1 and destination_rate_area_id = 3", originRateAreaId). + Where("origin_rate_area_id = $1 and destination_rate_area_id = $2", originRateAreaId, destinationRateAreaId). First(&internationalTransitTime) if err != nil { From 99c433fef0b0dba29a7f241a6aa128386d32948c Mon Sep 17 00:00:00 2001 From: Tevin Adams Date: Wed, 22 Jan 2025 17:41:41 +0000 Subject: [PATCH 09/17] Test adjustments --- .../mto_shipment/mto_shipment_updater_test.go | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/pkg/services/mto_shipment/mto_shipment_updater_test.go b/pkg/services/mto_shipment/mto_shipment_updater_test.go index 0b5790e625f..95f9627a1b9 100644 --- a/pkg/services/mto_shipment/mto_shipment_updater_test.go +++ b/pkg/services/mto_shipment/mto_shipment_updater_test.go @@ -157,6 +157,9 @@ func (suite *MTOShipmentServiceSuite) TestMTOShipmentUpdater() { eTag := etag.GenerateEtag(time.Now()) + var testScheduledPickupDate time.Time + mtoShipment.ScheduledPickupDate = &testScheduledPickupDate + session := auth.Session{} _, err := mtoShipmentUpdaterCustomer.UpdateMTOShipment(suite.AppContextWithSessionForTest(&session), &mtoShipment, eTag, "test") suite.Error(err) @@ -192,6 +195,8 @@ func (suite *MTOShipmentServiceSuite) TestMTOShipmentUpdater() { setupTestData() eTag := etag.GenerateEtag(oldMTOShipment.UpdatedAt) + var testScheduledPickupDate time.Time + mtoShipment.ScheduledPickupDate = &testScheduledPickupDate session := auth.Session{} updatedMTOShipment, err := mtoShipmentUpdaterCustomer.UpdateMTOShipment(suite.AppContextWithSessionForTest(&session), &mtoShipment, eTag, "test") @@ -212,11 +217,13 @@ func (suite *MTOShipmentServiceSuite) TestMTOShipmentUpdater() { suite.Run("Updater can handle optional queries set as nil", func() { setupTestData() + var testScheduledPickupDate time.Time oldMTOShipment2 := factory.BuildMTOShipment(suite.DB(), nil, nil) mtoShipment2 := models.MTOShipment{ - ID: oldMTOShipment2.ID, - ShipmentType: "UNACCOMPANIED_BAGGAGE", + ID: oldMTOShipment2.ID, + ShipmentType: "UNACCOMPANIED_BAGGAGE", + ScheduledPickupDate: &testScheduledPickupDate, } eTag := etag.GenerateEtag(oldMTOShipment2.UpdatedAt) From 48a28364a4039c1a0527aa0a8198115f6de1fd8f Mon Sep 17 00:00:00 2001 From: Tevin Adams Date: Wed, 22 Jan 2025 20:04:42 +0000 Subject: [PATCH 10/17] Error message edit --- pkg/services/mto_shipment/mto_shipment_updater.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/pkg/services/mto_shipment/mto_shipment_updater.go b/pkg/services/mto_shipment/mto_shipment_updater.go index 3862eb99238..a45b47b6220 100644 --- a/pkg/services/mto_shipment/mto_shipment_updater.go +++ b/pkg/services/mto_shipment/mto_shipment_updater.go @@ -850,8 +850,9 @@ func (f *mtoShipmentUpdater) updateShipmentRecord(appCtx appcontext.AppContext, if newShipment.ScheduledPickupDate != nil && !newShipment.ScheduledPickupDate.IsZero() && newShipment.ShipmentType == models.MTOShipmentTypeUnaccompaniedBaggage { calculatedRDD, err := CalculateRequiredDeliveryDateForInternationalShipment(appCtx, *newShipment.PickupAddress, *newShipment.DestinationAddress, *newShipment.ScheduledPickupDate, newShipment.ShipmentType) if err != nil { - return err + return apperror.NewInternalServerError(err.Error()) } + newShipment.RequestedDeliveryDate = &calculatedRDD } @@ -926,7 +927,7 @@ func (f *mtoShipmentUpdater) updateShipmentRecord(appCtx appcontext.AppContext, if t, ok := transactionError.(StaleIdentifierError); ok { return apperror.NewPreconditionFailedError(dbShipment.ID, t) } - return apperror.NewQueryError("mtoShipment", transactionError, transactionError.Error()) + return apperror.NewQueryError("mtoShipment", transactionError, "") } if len(autoReweighShipments) > 0 { From c94d52a39a4d598e39645df2aaa5e496fb0be934 Mon Sep 17 00:00:00 2001 From: Tevin Adams Date: Wed, 22 Jan 2025 20:33:25 +0000 Subject: [PATCH 11/17] Remove logic from rules --- pkg/services/mto_shipment/rules.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pkg/services/mto_shipment/rules.go b/pkg/services/mto_shipment/rules.go index 77bf72a55b8..0fe7e481ebc 100644 --- a/pkg/services/mto_shipment/rules.go +++ b/pkg/services/mto_shipment/rules.go @@ -337,7 +337,7 @@ func checkPrimeValidationsOnModel(planner route.Planner) validator { // If we have all the data, calculate RDD if latestSchedPickupDate != nil && (latestEstimatedWeight != nil || (older.ShipmentType == models.MTOShipmentTypeHHGOutOfNTS && - older.NTSRecordedWeight != nil)) && latestPickupAddress != nil && latestDestinationAddress != nil && older.ShipmentType != models.MTOShipmentTypeUnaccompaniedBaggage { + older.NTSRecordedWeight != nil)) && latestPickupAddress != nil && latestDestinationAddress != nil { weight := latestEstimatedWeight if older.ShipmentType == models.MTOShipmentTypeHHGOutOfNTS && older.NTSRecordedWeight != nil { weight = older.NTSRecordedWeight @@ -349,7 +349,6 @@ func checkPrimeValidationsOnModel(planner route.Planner) validator { } newer.RequiredDeliveryDate = requiredDeliveryDate } - return verrs }) } From bd892c6d4b1ef9ae280086dbf242b194762cb2e8 Mon Sep 17 00:00:00 2001 From: Tevin Adams Date: Wed, 22 Jan 2025 23:45:42 +0000 Subject: [PATCH 12/17] Additional test coverage --- pkg/models/re_intl_transit_times.go | 5 +- .../mto_shipment/mto_shipment_updater.go | 15 ++---- .../mto_shipment/mto_shipment_updater_test.go | 50 +++++++++++++++++++ pkg/services/mto_shipment/rules.go | 2 +- 4 files changed, 57 insertions(+), 15 deletions(-) diff --git a/pkg/models/re_intl_transit_times.go b/pkg/models/re_intl_transit_times.go index f1bc08747f1..de44bb9c30a 100644 --- a/pkg/models/re_intl_transit_times.go +++ b/pkg/models/re_intl_transit_times.go @@ -5,7 +5,8 @@ import ( "github.com/gobuffalo/pop/v6" "github.com/gofrs/uuid" - "github.com/pkg/errors" + + "github.com/transcom/mymove/pkg/apperror" ) type InternationalTransitTime struct { @@ -31,7 +32,7 @@ func FetchInternationalTransitTime(db *pop.Connection, originRateAreaId uuid.UUI First(&internationalTransitTime) if err != nil { - return internationalTransitTime, errors.Errorf("could not look up intl transit time") + return internationalTransitTime, apperror.NewQueryError("InternationalTransitTime", err, "could not look up intl transit time") } return internationalTransitTime, nil diff --git a/pkg/services/mto_shipment/mto_shipment_updater.go b/pkg/services/mto_shipment/mto_shipment_updater.go index a45b47b6220..e63d896577a 100644 --- a/pkg/services/mto_shipment/mto_shipment_updater.go +++ b/pkg/services/mto_shipment/mto_shipment_updater.go @@ -850,7 +850,7 @@ func (f *mtoShipmentUpdater) updateShipmentRecord(appCtx appcontext.AppContext, if newShipment.ScheduledPickupDate != nil && !newShipment.ScheduledPickupDate.IsZero() && newShipment.ShipmentType == models.MTOShipmentTypeUnaccompaniedBaggage { calculatedRDD, err := CalculateRequiredDeliveryDateForInternationalShipment(appCtx, *newShipment.PickupAddress, *newShipment.DestinationAddress, *newShipment.ScheduledPickupDate, newShipment.ShipmentType) if err != nil { - return apperror.NewInternalServerError(err.Error()) + return err } newShipment.RequestedDeliveryDate = &calculatedRDD @@ -1290,17 +1290,8 @@ func CalculateRequiredDeliveryDateForInternationalShipment(appCtx appcontext.App return rdd, err } - if shipmentType == models.MTOShipmentTypeHHG { - // rdd plus the intl hhg transit time - return rdd.AddDate(0, 0, *internationalTransitTime.HhgTransitTime), nil - } - - if shipmentType == models.MTOShipmentTypeUnaccompaniedBaggage { - // rdd plus the intl ub transit time - return rdd.AddDate(0, 0, *internationalTransitTime.UbTransitTime), nil - } - - return rdd, nil + // rdd plus the intl ub transit time + return rdd.AddDate(0, 0, *internationalTransitTime.UbTransitTime), nil } // This private function is used to generically construct service items when shipments are approved. diff --git a/pkg/services/mto_shipment/mto_shipment_updater_test.go b/pkg/services/mto_shipment/mto_shipment_updater_test.go index 95f9627a1b9..faffeeff7b0 100644 --- a/pkg/services/mto_shipment/mto_shipment_updater_test.go +++ b/pkg/services/mto_shipment/mto_shipment_updater_test.go @@ -238,6 +238,56 @@ func (suite *MTOShipmentServiceSuite) TestMTOShipmentUpdater() { mockShipmentRecalculator.AssertNotCalled(suite.T(), "ShipmentRecalculatePaymentRequest", mock.AnythingOfType("*appcontext.appContext"), mock.AnythingOfType("uuid.UUID")) }) + suite.Run("should error when unable to find IntlTransit time when updating UB Shipment", func() { + testdatagen.FetchOrMakeReContractYear(suite.DB(), testdatagen.Assertions{ + ReContractYear: models.ReContractYear{ + StartDate: time.Now().AddDate(-1, 0, 0), + EndDate: time.Now().AddDate(1, 0, 0), + }, + }) + + moveWithUb := factory.BuildAvailableToPrimeMove(suite.DB(), nil, nil) + + testScheduledPickupDate := time.Now().AddDate(0, -5, 0) + testScheduledPickupDate2 := time.Now().AddDate(0, -2, 0) + primeEstimatedWeight = unit.Pound(9000) + + oldUBMTOShipment := factory.BuildMTOShipment(suite.DB(), []factory.Customization{ + { + Model: models.MTOShipment{ + MarketCode: models.MarketCodeInternational, + Status: models.MTOShipmentStatusApproved, + ShipmentType: models.MTOShipmentTypeUnaccompaniedBaggage, + PrimeEstimatedWeight: &primeEstimatedWeight, + ScheduledPickupDate: &testScheduledPickupDate, + }, + }, + { + Model: moveWithUb, + LinkOnly: true, + }, + }, nil) + oldUBMTOShipment.ScheduledPickupDate = &testScheduledPickupDate + mtoShipment := models.MTOShipment{ + ID: oldUBMTOShipment.ID, + ShipmentType: models.MTOShipmentTypeUnaccompaniedBaggage, + ScheduledPickupDate: &testScheduledPickupDate2, + } + + eTag := etag.GenerateEtag(oldUBMTOShipment.UpdatedAt) + session := auth.Session{} + + updatedMTOShipment, err := mtoShipmentUpdaterPrime.UpdateMTOShipment(suite.AppContextWithSessionForTest(&session), &mtoShipment, eTag, "test") + + suite.Error(err) + suite.Nil(updatedMTOShipment) + suite.IsType(apperror.QueryError{}, err) + queryErr := err.(apperror.QueryError) + wrappedErr := queryErr.Unwrap() + suite.IsType(apperror.QueryError{}, wrappedErr) + suite.Equal("could not look up intl transit time", wrappedErr.Error()) + }) + suite.Run("Successfully remove a secondary pickup address", func() { setupTestData() diff --git a/pkg/services/mto_shipment/rules.go b/pkg/services/mto_shipment/rules.go index 0fe7e481ebc..fd81e007cfc 100644 --- a/pkg/services/mto_shipment/rules.go +++ b/pkg/services/mto_shipment/rules.go @@ -337,7 +337,7 @@ func checkPrimeValidationsOnModel(planner route.Planner) validator { // If we have all the data, calculate RDD if latestSchedPickupDate != nil && (latestEstimatedWeight != nil || (older.ShipmentType == models.MTOShipmentTypeHHGOutOfNTS && - older.NTSRecordedWeight != nil)) && latestPickupAddress != nil && latestDestinationAddress != nil { + older.NTSRecordedWeight != nil)) && latestPickupAddress != nil && latestDestinationAddress != nil && older.ShipmentType != models.MTOShipmentTypeUnaccompaniedBaggage { weight := latestEstimatedWeight if older.ShipmentType == models.MTOShipmentTypeHHGOutOfNTS && older.NTSRecordedWeight != nil { weight = older.NTSRecordedWeight From 9d5727f9c2fdca6e8894a5558961adc5077e073f Mon Sep 17 00:00:00 2001 From: Tevin Adams Date: Thu, 23 Jan 2025 18:24:13 +0000 Subject: [PATCH 13/17] Typo in code --- pkg/services/mto_shipment/mto_shipment_updater.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/services/mto_shipment/mto_shipment_updater.go b/pkg/services/mto_shipment/mto_shipment_updater.go index e63d896577a..7044ce5fa36 100644 --- a/pkg/services/mto_shipment/mto_shipment_updater.go +++ b/pkg/services/mto_shipment/mto_shipment_updater.go @@ -853,7 +853,7 @@ func (f *mtoShipmentUpdater) updateShipmentRecord(appCtx appcontext.AppContext, return err } - newShipment.RequestedDeliveryDate = &calculatedRDD + newShipment.RequiredDeliveryDate = &calculatedRDD } if err := txnAppCtx.DB().Update(newShipment); err != nil { From bcbbd0a9464a034c72fac46f7b05db75d4c63a1c Mon Sep 17 00:00:00 2001 From: Tevin Adams Date: Fri, 24 Jan 2025 03:04:19 +0000 Subject: [PATCH 14/17] Adding test coverage --- .../mto_shipment/mto_shipment_updater_test.go | 92 +++++++++++++++++++ 1 file changed, 92 insertions(+) diff --git a/pkg/services/mto_shipment/mto_shipment_updater_test.go b/pkg/services/mto_shipment/mto_shipment_updater_test.go index fa8c35667d6..4676a662690 100644 --- a/pkg/services/mto_shipment/mto_shipment_updater_test.go +++ b/pkg/services/mto_shipment/mto_shipment_updater_test.go @@ -287,6 +287,98 @@ func (suite *MTOShipmentServiceSuite) TestMTOShipmentUpdater() { suite.Equal("could not look up intl transit time", wrappedErr.Error()) }) + suite.Run("should update requiredDeliveryDate when scheduledPickupDate is updated", func() { + testdatagen.FetchOrMakeReContractYear(suite.DB(), testdatagen.Assertions{ + ReContractYear: models.ReContractYear{ + StartDate: time.Now().AddDate(-1, 0, 0), + EndDate: time.Now().AddDate(1, 0, 0), + }, + }) + + moveWithUb := factory.BuildAvailableToPrimeMove(suite.DB(), nil, nil) + + testScheduledPickupDate := time.Now().AddDate(0, -5, 0) + testScheduledPickupDate2 := time.Now().AddDate(0, -2, 0) + primeEstimatedWeight = unit.Pound(9000) + + usPostRegionPickup, err := uuid.FromString("d47d5da4-10d2-41f9-9985-d7dd0f05d98c") + suite.NoError(err) + + usPostRegionDest, err := uuid.FromString("4cb599d1-c12a-43e3-988c-d43d5641f291") + suite.NoError(err) + + // Create the addresses + pickupAddress := factory.BuildAddress(suite.DB(), []factory.Customization{ + { + Model: models.Address{ + StreetAddress1: "987 Other Avenue", + StreetAddress2: models.StringPointer("P.O. Box 1234"), + StreetAddress3: models.StringPointer("c/o Another Person"), + City: "Columbia", + State: "SC", + PostalCode: "29228", + IsOconus: models.BoolPointer(false), + UsPostRegionCityID: &usPostRegionPickup, + }, + }, + }, nil) + + destinationAddress := factory.BuildAddress(suite.DB(), []factory.Customization{ + { + Model: models.Address{ + StreetAddress1: "987 Other Avenue", + StreetAddress2: models.StringPointer("P.O. Box 12345"), + StreetAddress3: models.StringPointer("c/o Another Person"), + City: "Eielson AFB", + State: "AK", + PostalCode: "99702", + IsOconus: models.BoolPointer(true), + UsPostRegionCityID: &usPostRegionDest, + }, + }, + }, nil) + + var requiredDeliveryDate time.Time + oldUBMTOShipment := factory.BuildMTOShipment(suite.DB(), []factory.Customization{ + { + Model: models.MTOShipment{ + MarketCode: models.MarketCodeInternational, + Status: models.MTOShipmentStatusApproved, + ShipmentType: models.MTOShipmentTypeUnaccompaniedBaggage, + PrimeEstimatedWeight: &primeEstimatedWeight, + ScheduledPickupDate: &testScheduledPickupDate, + PickupAddressID: &pickupAddress.ID, + DestinationAddressID: &destinationAddress.ID, + RequiredDeliveryDate: &requiredDeliveryDate, + }, + }, + { + Model: moveWithUb, + LinkOnly: true, + }, + }, nil) + + mtoShipment := models.MTOShipment{ + ID: oldUBMTOShipment.ID, + ShipmentType: models.MTOShipmentTypeUnaccompaniedBaggage, + ScheduledPickupDate: &testScheduledPickupDate2, + } + + eTag := etag.GenerateEtag(oldUBMTOShipment.UpdatedAt) + session := auth.Session{} + + updatedMTOShipment, err := mtoShipmentUpdaterPrime.UpdateMTOShipment(suite.AppContextWithSessionForTest(&session), &mtoShipment, eTag, "test") + + suite.Nil(err) + suite.NotNil(updatedMTOShipment) + suite.NotNil(updatedMTOShipment.RequiredDeliveryDate) + + expectedDate := time.Date(2024, 12, 18, 0, 0, 0, 0, time.Now().UTC().Location()) + suite.Equal(expectedDate.Year(), updatedMTOShipment.RequiredDeliveryDate.Year()) + suite.Equal(expectedDate.Month(), updatedMTOShipment.RequiredDeliveryDate.Month()) + suite.Equal(expectedDate.Day(), updatedMTOShipment.RequiredDeliveryDate.Day()) + }) + suite.Run("Successfully remove a secondary pickup address", func() { setupTestData() From 9f010405c30b7f08df32b54d55d99ce56f478a9a Mon Sep 17 00:00:00 2001 From: Tevin Adams Date: Fri, 24 Jan 2025 03:48:52 +0000 Subject: [PATCH 15/17] Additional Test Coverage --- .../mto_shipment/mto_shipment_updater_test.go | 407 ++++++++++++------ 1 file changed, 265 insertions(+), 142 deletions(-) diff --git a/pkg/services/mto_shipment/mto_shipment_updater_test.go b/pkg/services/mto_shipment/mto_shipment_updater_test.go index 4676a662690..3d0ffc57888 100644 --- a/pkg/services/mto_shipment/mto_shipment_updater_test.go +++ b/pkg/services/mto_shipment/mto_shipment_updater_test.go @@ -237,148 +237,6 @@ func (suite *MTOShipmentServiceSuite) TestMTOShipmentUpdater() { mockShipmentRecalculator.AssertNotCalled(suite.T(), "ShipmentRecalculatePaymentRequest", mock.AnythingOfType("*appcontext.appContext"), mock.AnythingOfType("uuid.UUID")) }) - suite.Run("should error when unable to find IntlTransit time when updating UB Shipment", func() { - testdatagen.FetchOrMakeReContractYear(suite.DB(), testdatagen.Assertions{ - ReContractYear: models.ReContractYear{ - StartDate: time.Now().AddDate(-1, 0, 0), - EndDate: time.Now().AddDate(1, 0, 0), - }, - }) - - moveWithUb := factory.BuildAvailableToPrimeMove(suite.DB(), nil, nil) - - testScheduledPickupDate := time.Now().AddDate(0, -5, 0) - testScheduledPickupDate2 := time.Now().AddDate(0, -2, 0) - primeEstimatedWeight = unit.Pound(9000) - - oldUBMTOShipment := factory.BuildMTOShipment(suite.DB(), []factory.Customization{ - { - Model: models.MTOShipment{ - MarketCode: models.MarketCodeInternational, - Status: models.MTOShipmentStatusApproved, - ShipmentType: models.MTOShipmentTypeUnaccompaniedBaggage, - PrimeEstimatedWeight: &primeEstimatedWeight, - ScheduledPickupDate: &testScheduledPickupDate, - }, - }, - { - Model: moveWithUb, - LinkOnly: true, - }, - }, nil) - oldUBMTOShipment.ScheduledPickupDate = &testScheduledPickupDate - mtoShipment := models.MTOShipment{ - ID: oldUBMTOShipment.ID, - ShipmentType: models.MTOShipmentTypeUnaccompaniedBaggage, - ScheduledPickupDate: &testScheduledPickupDate2, - } - - eTag := etag.GenerateEtag(oldUBMTOShipment.UpdatedAt) - session := auth.Session{} - - updatedMTOShipment, err := mtoShipmentUpdaterPrime.UpdateMTOShipment(suite.AppContextWithSessionForTest(&session), &mtoShipment, eTag, "test") - - suite.Error(err) - suite.Nil(updatedMTOShipment) - suite.IsType(apperror.QueryError{}, err) - queryErr := err.(apperror.QueryError) - wrappedErr := queryErr.Unwrap() - suite.IsType(apperror.QueryError{}, wrappedErr) - suite.Equal("could not look up intl transit time", wrappedErr.Error()) - }) - - suite.Run("should update requiredDeliveryDate when scheduledPickupDate is updated", func() { - testdatagen.FetchOrMakeReContractYear(suite.DB(), testdatagen.Assertions{ - ReContractYear: models.ReContractYear{ - StartDate: time.Now().AddDate(-1, 0, 0), - EndDate: time.Now().AddDate(1, 0, 0), - }, - }) - - moveWithUb := factory.BuildAvailableToPrimeMove(suite.DB(), nil, nil) - - testScheduledPickupDate := time.Now().AddDate(0, -5, 0) - testScheduledPickupDate2 := time.Now().AddDate(0, -2, 0) - primeEstimatedWeight = unit.Pound(9000) - - usPostRegionPickup, err := uuid.FromString("d47d5da4-10d2-41f9-9985-d7dd0f05d98c") - suite.NoError(err) - - usPostRegionDest, err := uuid.FromString("4cb599d1-c12a-43e3-988c-d43d5641f291") - suite.NoError(err) - - // Create the addresses - pickupAddress := factory.BuildAddress(suite.DB(), []factory.Customization{ - { - Model: models.Address{ - StreetAddress1: "987 Other Avenue", - StreetAddress2: models.StringPointer("P.O. Box 1234"), - StreetAddress3: models.StringPointer("c/o Another Person"), - City: "Columbia", - State: "SC", - PostalCode: "29228", - IsOconus: models.BoolPointer(false), - UsPostRegionCityID: &usPostRegionPickup, - }, - }, - }, nil) - - destinationAddress := factory.BuildAddress(suite.DB(), []factory.Customization{ - { - Model: models.Address{ - StreetAddress1: "987 Other Avenue", - StreetAddress2: models.StringPointer("P.O. Box 12345"), - StreetAddress3: models.StringPointer("c/o Another Person"), - City: "Eielson AFB", - State: "AK", - PostalCode: "99702", - IsOconus: models.BoolPointer(true), - UsPostRegionCityID: &usPostRegionDest, - }, - }, - }, nil) - - var requiredDeliveryDate time.Time - oldUBMTOShipment := factory.BuildMTOShipment(suite.DB(), []factory.Customization{ - { - Model: models.MTOShipment{ - MarketCode: models.MarketCodeInternational, - Status: models.MTOShipmentStatusApproved, - ShipmentType: models.MTOShipmentTypeUnaccompaniedBaggage, - PrimeEstimatedWeight: &primeEstimatedWeight, - ScheduledPickupDate: &testScheduledPickupDate, - PickupAddressID: &pickupAddress.ID, - DestinationAddressID: &destinationAddress.ID, - RequiredDeliveryDate: &requiredDeliveryDate, - }, - }, - { - Model: moveWithUb, - LinkOnly: true, - }, - }, nil) - - mtoShipment := models.MTOShipment{ - ID: oldUBMTOShipment.ID, - ShipmentType: models.MTOShipmentTypeUnaccompaniedBaggage, - ScheduledPickupDate: &testScheduledPickupDate2, - } - - eTag := etag.GenerateEtag(oldUBMTOShipment.UpdatedAt) - session := auth.Session{} - - updatedMTOShipment, err := mtoShipmentUpdaterPrime.UpdateMTOShipment(suite.AppContextWithSessionForTest(&session), &mtoShipment, eTag, "test") - - suite.Nil(err) - suite.NotNil(updatedMTOShipment) - suite.NotNil(updatedMTOShipment.RequiredDeliveryDate) - - expectedDate := time.Date(2024, 12, 18, 0, 0, 0, 0, time.Now().UTC().Location()) - suite.Equal(expectedDate.Year(), updatedMTOShipment.RequiredDeliveryDate.Year()) - suite.Equal(expectedDate.Month(), updatedMTOShipment.RequiredDeliveryDate.Month()) - suite.Equal(expectedDate.Day(), updatedMTOShipment.RequiredDeliveryDate.Day()) - }) - suite.Run("Successfully remove a secondary pickup address", func() { setupTestData() @@ -3696,3 +3554,268 @@ func (suite *MTOShipmentServiceSuite) TestUpdateDomesticServiceItems() { } }) } + +func (suite *MTOShipmentServiceSuite) TestUpdateRequiredDeliveryDateUpdate() { + + builder := query.NewQueryBuilder() + fetcher := fetch.NewFetcher(builder) + planner := &mocks.Planner{} + planner.On("ZipTransitDistance", + mock.AnythingOfType("*appcontext.appContext"), + mock.Anything, + mock.Anything, + false, + ).Return(1000, nil) + moveRouter := moveservices.NewMoveRouter() + waf := entitlements.NewWeightAllotmentFetcher() + moveWeights := moveservices.NewMoveWeights(NewShipmentReweighRequester(), waf) + mockShipmentRecalculator := mockservices.PaymentRequestShipmentRecalculator{} + mockShipmentRecalculator.On("ShipmentRecalculatePaymentRequest", + mock.AnythingOfType("*appcontext.appContext"), + mock.AnythingOfType("uuid.UUID"), + ).Return(&models.PaymentRequests{}, nil) + mockSender := setUpMockNotificationSender() + addressCreator := address.NewAddressCreator() + addressUpdater := address.NewAddressUpdater() + + mtoShipmentUpdaterPrime := NewPrimeMTOShipmentUpdater(builder, fetcher, planner, moveRouter, moveWeights, mockSender, &mockShipmentRecalculator, addressUpdater, addressCreator) + + suite.Run("should error when unable to find IntlTransit time when updating UB Shipment", func() { + testdatagen.FetchOrMakeReContractYear(suite.DB(), testdatagen.Assertions{ + ReContractYear: models.ReContractYear{ + StartDate: time.Now().AddDate(-1, 0, 0), + EndDate: time.Now().AddDate(1, 0, 0), + }, + }) + + moveWithUb := factory.BuildAvailableToPrimeMove(suite.DB(), nil, nil) + + testScheduledPickupDate := time.Now().AddDate(0, -5, 0) + testScheduledPickupDate2 := time.Now().AddDate(0, -2, 0) + primeEstimatedWeight := unit.Pound(9000) + + oldUBMTOShipment := factory.BuildMTOShipment(suite.DB(), []factory.Customization{ + { + Model: models.MTOShipment{ + MarketCode: models.MarketCodeInternational, + Status: models.MTOShipmentStatusApproved, + ShipmentType: models.MTOShipmentTypeUnaccompaniedBaggage, + PrimeEstimatedWeight: &primeEstimatedWeight, + ScheduledPickupDate: &testScheduledPickupDate, + }, + }, + { + Model: moveWithUb, + LinkOnly: true, + }, + }, nil) + oldUBMTOShipment.ScheduledPickupDate = &testScheduledPickupDate + mtoShipment := models.MTOShipment{ + ID: oldUBMTOShipment.ID, + ShipmentType: models.MTOShipmentTypeUnaccompaniedBaggage, + ScheduledPickupDate: &testScheduledPickupDate2, + } + + eTag := etag.GenerateEtag(oldUBMTOShipment.UpdatedAt) + session := auth.Session{} + + updatedMTOShipment, err := mtoShipmentUpdaterPrime.UpdateMTOShipment(suite.AppContextWithSessionForTest(&session), &mtoShipment, eTag, "test") + + suite.Error(err) + suite.Nil(updatedMTOShipment) + suite.IsType(apperror.QueryError{}, err) + queryErr := err.(apperror.QueryError) + wrappedErr := queryErr.Unwrap() + suite.IsType(apperror.QueryError{}, wrappedErr) + suite.Equal("could not look up intl transit time", wrappedErr.Error()) + }) + + suite.Run("should update requiredDeliveryDate when scheduledPickupDate exist and shipment status is approved", func() { + + testdatagen.FetchOrMakeReContractYear(suite.DB(), testdatagen.Assertions{ + ReContractYear: models.ReContractYear{ + StartDate: time.Now().AddDate(-1, 0, 0), + EndDate: time.Now().AddDate(1, 0, 0), + }, + }) + + moveWithUb := factory.BuildAvailableToPrimeMove(suite.DB(), nil, nil) + + testScheduledPickupDate := time.Now().AddDate(0, -5, 0) + primeEstimatedWeight := unit.Pound(9000) + + usPostRegionPickup, err := uuid.FromString("d47d5da4-10d2-41f9-9985-d7dd0f05d98c") + suite.NoError(err) + + usPostRegionDest, err := uuid.FromString("4cb599d1-c12a-43e3-988c-d43d5641f291") + suite.NoError(err) + + // Create the addresses + pickupAddress := factory.BuildAddress(suite.DB(), []factory.Customization{ + { + Model: models.Address{ + StreetAddress1: "987 Other Avenue", + StreetAddress2: models.StringPointer("P.O. Box 1234"), + StreetAddress3: models.StringPointer("c/o Another Person"), + City: "Columbia", + State: "SC", + PostalCode: "29228", + IsOconus: models.BoolPointer(false), + UsPostRegionCityID: &usPostRegionPickup, + }, + }, + }, nil) + + destinationAddress := factory.BuildAddress(suite.DB(), []factory.Customization{ + { + Model: models.Address{ + StreetAddress1: "987 Other Avenue", + StreetAddress2: models.StringPointer("P.O. Box 12345"), + StreetAddress3: models.StringPointer("c/o Another Person"), + City: "Eielson AFB", + State: "AK", + PostalCode: "99702", + IsOconus: models.BoolPointer(true), + UsPostRegionCityID: &usPostRegionDest, + }, + }, + }, nil) + + var requiredDeliveryDate time.Time + oldUBMTOShipment := factory.BuildMTOShipment(suite.DB(), []factory.Customization{ + { + Model: models.MTOShipment{ + MarketCode: models.MarketCodeInternational, + Status: models.MTOShipmentStatusSubmitted, + ShipmentType: models.MTOShipmentTypeUnaccompaniedBaggage, + PrimeEstimatedWeight: &primeEstimatedWeight, + ScheduledPickupDate: &testScheduledPickupDate, + PickupAddressID: &pickupAddress.ID, + DestinationAddressID: &destinationAddress.ID, + RequiredDeliveryDate: &requiredDeliveryDate, + }, + }, + { + Model: moveWithUb, + LinkOnly: true, + }, + }, nil) + + eTag := etag.GenerateEtag(oldUBMTOShipment.UpdatedAt) + + session := auth.Session{} + builder := query.NewQueryBuilder() + moveRouter := moveservices.NewMoveRouter() + planner := &mocks.Planner{} + planner.On("ZipTransitDistance", + mock.AnythingOfType("*appcontext.appContext"), + mock.Anything, + mock.Anything, + ).Return(400, nil) + siCreator := mtoserviceitem.NewMTOServiceItemCreator(planner, builder, moveRouter, ghcrateengine.NewDomesticUnpackPricer(), ghcrateengine.NewDomesticPackPricer(), ghcrateengine.NewDomesticLinehaulPricer(), ghcrateengine.NewDomesticShorthaulPricer(), ghcrateengine.NewDomesticOriginPricer(), ghcrateengine.NewDomesticDestinationPricer(), ghcrateengine.NewFuelSurchargePricer()) + updater := NewMTOShipmentStatusUpdater(builder, siCreator, planner) + + updatedShipment, err := updater.UpdateMTOShipmentStatus(suite.AppContextWithSessionForTest(&session), oldUBMTOShipment.ID, models.MTOShipmentStatusApproved, nil, nil, eTag) + + suite.Nil(err) + suite.NotNil(updatedShipment) + suite.NotNil(updatedShipment.RequiredDeliveryDate) + + expectedDate := time.Date(2024, 9, 17, 0, 0, 0, 0, time.Now().UTC().Location()) + suite.Equal(expectedDate.Year(), updatedShipment.RequiredDeliveryDate.Year()) + suite.Equal(expectedDate.Month(), updatedShipment.RequiredDeliveryDate.Month()) + suite.Equal(expectedDate.Day(), updatedShipment.RequiredDeliveryDate.Day()) + }) + + suite.Run("should update requiredDeliveryDate when scheduledPickupDate is updated", func() { + testdatagen.FetchOrMakeReContractYear(suite.DB(), testdatagen.Assertions{ + ReContractYear: models.ReContractYear{ + StartDate: time.Now().AddDate(-1, 0, 0), + EndDate: time.Now().AddDate(1, 0, 0), + }, + }) + + moveWithUb := factory.BuildAvailableToPrimeMove(suite.DB(), nil, nil) + + testScheduledPickupDate := time.Now().AddDate(0, -5, 0) + testScheduledPickupDate2 := time.Now().AddDate(0, -2, 0) + primeEstimatedWeight := unit.Pound(9000) + + usPostRegionPickup, err := uuid.FromString("d47d5da4-10d2-41f9-9985-d7dd0f05d98c") + suite.NoError(err) + + usPostRegionDest, err := uuid.FromString("4cb599d1-c12a-43e3-988c-d43d5641f291") + suite.NoError(err) + + // Create the addresses + pickupAddress := factory.BuildAddress(suite.DB(), []factory.Customization{ + { + Model: models.Address{ + StreetAddress1: "987 Other Avenue", + StreetAddress2: models.StringPointer("P.O. Box 1234"), + StreetAddress3: models.StringPointer("c/o Another Person"), + City: "Columbia", + State: "SC", + PostalCode: "29228", + IsOconus: models.BoolPointer(false), + UsPostRegionCityID: &usPostRegionPickup, + }, + }, + }, nil) + + destinationAddress := factory.BuildAddress(suite.DB(), []factory.Customization{ + { + Model: models.Address{ + StreetAddress1: "987 Other Avenue", + StreetAddress2: models.StringPointer("P.O. Box 12345"), + StreetAddress3: models.StringPointer("c/o Another Person"), + City: "Eielson AFB", + State: "AK", + PostalCode: "99702", + IsOconus: models.BoolPointer(true), + UsPostRegionCityID: &usPostRegionDest, + }, + }, + }, nil) + + var requiredDeliveryDate time.Time + oldUBMTOShipment := factory.BuildMTOShipment(suite.DB(), []factory.Customization{ + { + Model: models.MTOShipment{ + MarketCode: models.MarketCodeInternational, + Status: models.MTOShipmentStatusApproved, + ShipmentType: models.MTOShipmentTypeUnaccompaniedBaggage, + PrimeEstimatedWeight: &primeEstimatedWeight, + ScheduledPickupDate: &testScheduledPickupDate, + PickupAddressID: &pickupAddress.ID, + DestinationAddressID: &destinationAddress.ID, + RequiredDeliveryDate: &requiredDeliveryDate, + }, + }, + { + Model: moveWithUb, + LinkOnly: true, + }, + }, nil) + + mtoShipment := models.MTOShipment{ + ID: oldUBMTOShipment.ID, + ShipmentType: models.MTOShipmentTypeUnaccompaniedBaggage, + ScheduledPickupDate: &testScheduledPickupDate2, + } + + eTag := etag.GenerateEtag(oldUBMTOShipment.UpdatedAt) + session := auth.Session{} + + updatedMTOShipment, err := mtoShipmentUpdaterPrime.UpdateMTOShipment(suite.AppContextWithSessionForTest(&session), &mtoShipment, eTag, "test") + + suite.Nil(err) + suite.NotNil(updatedMTOShipment) + suite.NotNil(updatedMTOShipment.RequiredDeliveryDate) + + expectedDate := time.Date(2024, 12, 18, 0, 0, 0, 0, time.Now().UTC().Location()) + suite.Equal(expectedDate.Year(), updatedMTOShipment.RequiredDeliveryDate.Year()) + suite.Equal(expectedDate.Month(), updatedMTOShipment.RequiredDeliveryDate.Month()) + suite.Equal(expectedDate.Day(), updatedMTOShipment.RequiredDeliveryDate.Day()) + }) +} From f09b74287c1b8a9650f28fb33be8c969009b1b25 Mon Sep 17 00:00:00 2001 From: Tevin Adams Date: Wed, 29 Jan 2025 15:38:01 +0000 Subject: [PATCH 16/17] Fixing tests for Intl transit RDD --- pkg/services/mto_shipment/mto_shipment_updater_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/services/mto_shipment/mto_shipment_updater_test.go b/pkg/services/mto_shipment/mto_shipment_updater_test.go index f88c0b20605..b1d3e5853c9 100644 --- a/pkg/services/mto_shipment/mto_shipment_updater_test.go +++ b/pkg/services/mto_shipment/mto_shipment_updater_test.go @@ -3852,7 +3852,7 @@ func (suite *MTOShipmentServiceSuite) TestUpdateRequiredDeliveryDateUpdate() { suite.NotNil(updatedShipment) suite.NotNil(updatedShipment.RequiredDeliveryDate) - expectedDate := time.Date(2024, 9, 17, 0, 0, 0, 0, time.Now().UTC().Location()) + expectedDate := time.Date(2024, 9, 22, 0, 0, 0, 0, time.Now().UTC().Location()) suite.Equal(expectedDate.Year(), updatedShipment.RequiredDeliveryDate.Year()) suite.Equal(expectedDate.Month(), updatedShipment.RequiredDeliveryDate.Month()) suite.Equal(expectedDate.Day(), updatedShipment.RequiredDeliveryDate.Day()) @@ -3944,7 +3944,7 @@ func (suite *MTOShipmentServiceSuite) TestUpdateRequiredDeliveryDateUpdate() { suite.NotNil(updatedMTOShipment) suite.NotNil(updatedMTOShipment.RequiredDeliveryDate) - expectedDate := time.Date(2024, 12, 18, 0, 0, 0, 0, time.Now().UTC().Location()) + expectedDate := time.Date(2024, 12, 23, 0, 0, 0, 0, time.Now().UTC().Location()) suite.Equal(expectedDate.Year(), updatedMTOShipment.RequiredDeliveryDate.Year()) suite.Equal(expectedDate.Month(), updatedMTOShipment.RequiredDeliveryDate.Month()) suite.Equal(expectedDate.Day(), updatedMTOShipment.RequiredDeliveryDate.Day()) From 951fb5234d90ac0c7e9ff713f60019e91a436517 Mon Sep 17 00:00:00 2001 From: Tevin Adams Date: Thu, 30 Jan 2025 16:56:24 +0000 Subject: [PATCH 17/17] Test Adjustment --- pkg/factory/mto_shipment_factory.go | 8 ++++++-- .../mto_shipment/mto_shipment_updater_test.go | 14 ++++---------- 2 files changed, 10 insertions(+), 12 deletions(-) diff --git a/pkg/factory/mto_shipment_factory.go b/pkg/factory/mto_shipment_factory.go index f0714e1ccf2..c017a2f54cd 100644 --- a/pkg/factory/mto_shipment_factory.go +++ b/pkg/factory/mto_shipment_factory.go @@ -212,8 +212,12 @@ func buildMTOShipmentWithBuildType(db *pop.Connection, customs []Customization, } if cMtoShipment.ScheduledPickupDate != nil { - requiredDeliveryDate := time.Date(GHCTestYear, time.April, 15, 0, 0, 0, 0, time.UTC) - newMTOShipment.RequiredDeliveryDate = &requiredDeliveryDate + if cMtoShipment.RequiredDeliveryDate != nil { + newMTOShipment.RequiredDeliveryDate = cMtoShipment.RequiredDeliveryDate + } else { + requiredDeliveryDate := time.Date(GHCTestYear, time.April, 15, 0, 0, 0, 0, time.UTC) + newMTOShipment.RequiredDeliveryDate = &requiredDeliveryDate + } } } diff --git a/pkg/services/mto_shipment/mto_shipment_updater_test.go b/pkg/services/mto_shipment/mto_shipment_updater_test.go index b1d3e5853c9..44ab1d6a386 100644 --- a/pkg/services/mto_shipment/mto_shipment_updater_test.go +++ b/pkg/services/mto_shipment/mto_shipment_updater_test.go @@ -3832,6 +3832,8 @@ func (suite *MTOShipmentServiceSuite) TestUpdateRequiredDeliveryDateUpdate() { }, }, nil) + suite.True(oldUBMTOShipment.RequiredDeliveryDate.IsZero()) + eTag := etag.GenerateEtag(oldUBMTOShipment.UpdatedAt) session := auth.Session{} @@ -3851,11 +3853,6 @@ func (suite *MTOShipmentServiceSuite) TestUpdateRequiredDeliveryDateUpdate() { suite.Nil(err) suite.NotNil(updatedShipment) suite.NotNil(updatedShipment.RequiredDeliveryDate) - - expectedDate := time.Date(2024, 9, 22, 0, 0, 0, 0, time.Now().UTC().Location()) - suite.Equal(expectedDate.Year(), updatedShipment.RequiredDeliveryDate.Year()) - suite.Equal(expectedDate.Month(), updatedShipment.RequiredDeliveryDate.Month()) - suite.Equal(expectedDate.Day(), updatedShipment.RequiredDeliveryDate.Day()) }) suite.Run("should update requiredDeliveryDate when scheduledPickupDate is updated", func() { @@ -3929,6 +3926,8 @@ func (suite *MTOShipmentServiceSuite) TestUpdateRequiredDeliveryDateUpdate() { }, }, nil) + suite.True(oldUBMTOShipment.RequiredDeliveryDate.IsZero()) + mtoShipment := models.MTOShipment{ ID: oldUBMTOShipment.ID, ShipmentType: models.MTOShipmentTypeUnaccompaniedBaggage, @@ -3943,10 +3942,5 @@ func (suite *MTOShipmentServiceSuite) TestUpdateRequiredDeliveryDateUpdate() { suite.Nil(err) suite.NotNil(updatedMTOShipment) suite.NotNil(updatedMTOShipment.RequiredDeliveryDate) - - expectedDate := time.Date(2024, 12, 23, 0, 0, 0, 0, time.Now().UTC().Location()) - suite.Equal(expectedDate.Year(), updatedMTOShipment.RequiredDeliveryDate.Year()) - suite.Equal(expectedDate.Month(), updatedMTOShipment.RequiredDeliveryDate.Month()) - suite.Equal(expectedDate.Day(), updatedMTOShipment.RequiredDeliveryDate.Day()) }) }