diff --git a/pkg/handlers/ghcapi/mto_shipment_test.go b/pkg/handlers/ghcapi/mto_shipment_test.go index e1d57e98e17..9b0f17e3f7e 100644 --- a/pkg/handlers/ghcapi/mto_shipment_test.go +++ b/pkg/handlers/ghcapi/mto_shipment_test.go @@ -244,9 +244,9 @@ func (suite *HandlerSuite) TestListMTOShipmentsHandler() { suite.Equal(int64(190), *payloadShipment.SitDaysAllowance) suite.Equal(sitstatus.OriginSITLocation, payloadShipment.SitStatus.CurrentSIT.Location) suite.Equal(int64(8), *payloadShipment.SitStatus.CurrentSIT.DaysInSIT) - suite.Equal(int64(175), *payloadShipment.SitStatus.TotalDaysRemaining) - suite.Equal(int64(15), *payloadShipment.SitStatus.TotalSITDaysUsed) // 7 from the previous SIT and 7 from the current - suite.Equal(int64(15), *payloadShipment.SitStatus.CalculatedTotalDaysInSIT) + suite.Equal(int64(174), *payloadShipment.SitStatus.TotalDaysRemaining) + suite.Equal(int64(16), *payloadShipment.SitStatus.TotalSITDaysUsed) // 7 from the previous SIT and 7 from the current (+2 for including last days) + suite.Equal(int64(16), *payloadShipment.SitStatus.CalculatedTotalDaysInSIT) suite.Equal(subtestData.sit.SITEntryDate.Format("2006-01-02"), payloadShipment.SitStatus.CurrentSIT.SitEntryDate.String()) suite.Equal(subtestData.sit.SITDepartureDate.Format("2006-01-02"), payloadShipment.SitStatus.CurrentSIT.SitDepartureDate.String()) diff --git a/pkg/handlers/ghcapi/payment_request_test.go b/pkg/handlers/ghcapi/payment_request_test.go index 994b8770708..33eb7ec946a 100644 --- a/pkg/handlers/ghcapi/payment_request_test.go +++ b/pkg/handlers/ghcapi/payment_request_test.go @@ -926,7 +926,7 @@ func (suite *HandlerSuite) TestShipmentsSITBalanceHandler() { suite.Equal(int64(120), shipmentSITBalance.TotalSITDaysAuthorized) suite.Equal(int64(60), shipmentSITBalance.PendingSITDaysInvoiced) // Since there is no departure date on one of the SITs, +1 is added to the count to count the last day - suite.Equal(int64(-61), shipmentSITBalance.TotalSITDaysRemaining) // Well over entitlement + suite.Equal(int64(-62), shipmentSITBalance.TotalSITDaysRemaining) // Well over entitlement suite.Equal(destinationPaymentEndDate.Format("2006-01-02"), shipmentSITBalance.PendingBilledEndDate.String()) suite.Equal(int64(30), *shipmentSITBalance.PreviouslyBilledDays) }) diff --git a/pkg/services/mocks/ShipmentSITStatus.go b/pkg/services/mocks/ShipmentSITStatus.go index 983b69c24ee..86b760f36d9 100644 --- a/pkg/services/mocks/ShipmentSITStatus.go +++ b/pkg/services/mocks/ShipmentSITStatus.go @@ -102,7 +102,7 @@ func (_m *ShipmentSITStatus) CalculateShipmentsSITStatuses(appCtx appcontext.App } // RetrieveShipmentSIT provides a mock function with given fields: appCtx, shipment -func (_m *ShipmentSITStatus) RetrieveShipmentSIT(appCtx appcontext.AppContext, shipment models.MTOShipment) models.SITServiceItemGroupings { +func (_m *ShipmentSITStatus) RetrieveShipmentSIT(appCtx appcontext.AppContext, shipment models.MTOShipment) (models.SITServiceItemGroupings, error) { ret := _m.Called(appCtx, shipment) if len(ret) == 0 { @@ -110,6 +110,10 @@ func (_m *ShipmentSITStatus) RetrieveShipmentSIT(appCtx appcontext.AppContext, s } var r0 models.SITServiceItemGroupings + var r1 error + if rf, ok := ret.Get(0).(func(appcontext.AppContext, models.MTOShipment) (models.SITServiceItemGroupings, error)); ok { + return rf(appCtx, shipment) + } if rf, ok := ret.Get(0).(func(appcontext.AppContext, models.MTOShipment) models.SITServiceItemGroupings); ok { r0 = rf(appCtx, shipment) } else { @@ -118,7 +122,13 @@ func (_m *ShipmentSITStatus) RetrieveShipmentSIT(appCtx appcontext.AppContext, s } } - return r0 + if rf, ok := ret.Get(1).(func(appcontext.AppContext, models.MTOShipment) error); ok { + r1 = rf(appCtx, shipment) + } else { + r1 = ret.Error(1) + } + + return r0, r1 } // NewShipmentSITStatus creates a new instance of ShipmentSITStatus. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. 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 495f9f53493..0068951430e 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 @@ -477,8 +477,8 @@ func (suite *MTOServiceItemServiceSuite) TestMTOServiceItemUpdater() { var postUpdatedServiceItemShipment models.MTOShipment suite.DB().Q().Find(&postUpdatedServiceItemShipment, shipment.ID) suite.NotNil(postUpdatedServiceItemShipment) - // Verify the departure date is before the original shipment authorized end date - suite.True(updatedServiceItem.SITDepartureDate.Before(*shipmentWithCalculatedStatus.DestinationSITAuthEndDate)) + // Verify the departure date is equal to the shipment SIT status departure date (Previously shipment SIT status would have an improper end date due to calc issues. This was fixed in B-20967) + suite.True(updatedServiceItem.SITDepartureDate.Equal(*shipmentWithCalculatedStatus.DestinationSITAuthEndDate)) // Verify the updated shipment authorized end date is equal to the departure date // Truncate to the nearest day. This is because the shipment only inherits the day, month, year from the service item, not the hour, minute, or second suite.True(updatedServiceItem.SITDepartureDate.Truncate(24 * time.Hour).Equal(postUpdatedServiceItemShipment.DestinationSITAuthEndDate.Truncate(24 * time.Hour))) @@ -605,8 +605,8 @@ func (suite *MTOServiceItemServiceSuite) TestMTOServiceItemUpdater() { var postUpdatedServiceItemShipment models.MTOShipment suite.DB().Q().Find(&postUpdatedServiceItemShipment, shipment.ID) suite.NotNil(postUpdatedServiceItemShipment) - // Verify the departure date is before the original shipment authorized end date - suite.True(updatedServiceItem.SITDepartureDate.Before(*shipmentWithCalculatedStatus.OriginSITAuthEndDate)) + // Verify the departure date is equal to the shipment SIT status departure date (Previously shipment SIT status would have an improper end date due to calc issues. This was fixed in B-20967) + suite.True(updatedServiceItem.SITDepartureDate.Equal(*shipmentWithCalculatedStatus.OriginSITAuthEndDate)) // Verify the updated shipment authorized end date is equal to the departure date // Truncate to the nearest day. This is because the shipment only inherits the day, month, year from the service item, not the hour, minute, or second suite.True(updatedServiceItem.SITDepartureDate.Truncate(24 * time.Hour).Equal(postUpdatedServiceItemShipment.OriginSITAuthEndDate.Truncate(24 * time.Hour))) diff --git a/pkg/services/mto_shipment.go b/pkg/services/mto_shipment.go index 5c40aafaa34..a409c6db436 100644 --- a/pkg/services/mto_shipment.go +++ b/pkg/services/mto_shipment.go @@ -151,5 +151,5 @@ type ShipmentSITStatus interface { CalculateShipmentsSITStatuses(appCtx appcontext.AppContext, shipments []models.MTOShipment) map[string]SITStatus CalculateShipmentSITStatus(appCtx appcontext.AppContext, shipment models.MTOShipment) (*SITStatus, models.MTOShipment, error) CalculateShipmentSITAllowance(appCtx appcontext.AppContext, shipment models.MTOShipment) (int, error) - RetrieveShipmentSIT(appCtx appcontext.AppContext, shipment models.MTOShipment) models.SITServiceItemGroupings + RetrieveShipmentSIT(appCtx appcontext.AppContext, shipment models.MTOShipment) (models.SITServiceItemGroupings, error) } diff --git a/pkg/services/payment_request/payment_request_shipments_sit_balance.go b/pkg/services/payment_request/payment_request_shipments_sit_balance.go index 808f30163f8..43f8c9374c4 100644 --- a/pkg/services/payment_request/payment_request_shipments_sit_balance.go +++ b/pkg/services/payment_request/payment_request_shipments_sit_balance.go @@ -114,7 +114,10 @@ func calculateReviewedSITBalance(appCtx appcontext.AppContext, paymentServiceIte } // sort the SIT service items into past, current and future to aid in the upcoming calculations - shipmentSIT := sitstatus.NewShipmentSITStatus().RetrieveShipmentSIT(appCtx, shipment) + shipmentSIT, err := sitstatus.NewShipmentSITStatus().RetrieveShipmentSIT(appCtx, shipment) + if err != nil { + return err + } sortedShipmentSIT := sitstatus.SortShipmentSITs(shipmentSIT, today) totalSITDaysAuthorized, err := sitstatus.NewShipmentSITStatus().CalculateShipmentSITAllowance(appCtx, shipment) @@ -155,7 +158,10 @@ func calculatePendingSITBalance(appCtx appcontext.AppContext, paymentServiceItem return err } // sort the SIT service items into past, current and future to aid in the upcoming calculations - shipmentSIT := sitstatus.NewShipmentSITStatus().RetrieveShipmentSIT(appCtx, shipment) + shipmentSIT, err := sitstatus.NewShipmentSITStatus().RetrieveShipmentSIT(appCtx, shipment) + if err != nil { + return err + } sortedShipmentSIT := sitstatus.SortShipmentSITs(shipmentSIT, today) totalSITAllowance, err := sitstatus.NewShipmentSITStatus().CalculateShipmentSITAllowance(appCtx, shipment) if err != nil { @@ -173,7 +179,9 @@ func calculatePendingSITBalance(appCtx appcontext.AppContext, paymentServiceItem // Even though these have been set before, we should do these calculations again in order to recalculate the // totalSITEndDate using this service item's entry date. - totalSITEndDate := sitstatus.CalculateSITAuthorizedEndDate(totalSITAllowance, daysInSIT, *paymentServiceItem.MTOServiceItem.SITEntryDate, calculateTotalDaysInSIT) + // Additionally retrieve the latest SIT Departure date from the current SIT if it exists. The first current SIT is chosen as there is not currently support for more than one SIT + // Per AC under B-20899 + totalSITEndDate := sitstatus.CalculateSITAuthorizedEndDate(totalSITAllowance, daysInSIT, *paymentServiceItem.MTOServiceItem.SITEntryDate, calculateTotalDaysInSIT, sortedShipmentSIT.CurrentSITs[0].Summary.SITDepartureDate) shipmentSITBalance.TotalSITEndDate = totalSITEndDate shipmentsSITBalances[shipment.ID.String()] = shipmentSITBalance @@ -191,7 +199,9 @@ func calculatePendingSITBalance(appCtx appcontext.AppContext, paymentServiceItem totalSITDaysUsed := sitstatus.CalculateTotalDaysInSIT(sortedShipmentSIT, today) totalSITDaysRemaining := totalSITDaysAuthorized - totalSITDaysUsed - totalSITEndDate := sitstatus.CalculateSITAuthorizedEndDate(totalSITAllowance, daysInSIT, *paymentServiceItem.MTOServiceItem.SITEntryDate, calculateTotalDaysInSIT) + // Retrieve the latest SIT Departure date from the current SIT if it exists. The first current SIT is chosen as there is not currently support for more than one SIT + // Per AC under B-20899 + totalSITEndDate := sitstatus.CalculateSITAuthorizedEndDate(totalSITAllowance, daysInSIT, *paymentServiceItem.MTOServiceItem.SITEntryDate, calculateTotalDaysInSIT, sortedShipmentSIT.CurrentSITs[0].Summary.SITDepartureDate) shipmentSITBalance.TotalSITDaysAuthorized = totalSITDaysAuthorized shipmentSITBalance.TotalSITDaysRemaining = totalSITDaysRemaining diff --git a/pkg/services/payment_request/payment_request_shipments_sit_balance_test.go b/pkg/services/payment_request/payment_request_shipments_sit_balance_test.go index 8d238e7ff26..30b8458ff31 100644 --- a/pkg/services/payment_request/payment_request_shipments_sit_balance_test.go +++ b/pkg/services/payment_request/payment_request_shipments_sit_balance_test.go @@ -203,7 +203,7 @@ func (suite *PaymentRequestServiceSuite) TestListShipmentPaymentSITBalance() { suite.Equal(paymentEndDate.String(), pendingSITBalance.PendingBilledEndDate.String()) suite.Equal(120, pendingSITBalance.TotalSITDaysAuthorized) suite.Equal(89, pendingSITBalance.TotalSITDaysRemaining) - suite.Equal(doasit.SITEntryDate.AddDate(0, 0, 119).String(), pendingSITBalance.TotalSITEndDate.UTC().String()) + suite.Equal(doasit.SITEntryDate.AddDate(0, 0, 118).String(), pendingSITBalance.TotalSITEndDate.UTC().String()) }) suite.Run("calculates pending destination SIT balance when origin was invoiced previously", func() { @@ -528,9 +528,9 @@ func (suite *PaymentRequestServiceSuite) TestListShipmentPaymentSITBalance() { suite.Equal(120, pendingSITBalance.TotalSITDaysAuthorized) // 120 total authorized - 30 from origin SIT - 60 from destination SIT = 30 SIT days remaining - suite.Equal(29, pendingSITBalance.TotalSITDaysRemaining) + suite.Equal(28, pendingSITBalance.TotalSITDaysRemaining) - suite.Equal(ddasit.SITEntryDate.AddDate(0, 0, 89).String(), pendingSITBalance.TotalSITEndDate.UTC().String()) + suite.Equal(ddasit.SITEntryDate.AddDate(0, 0, 87).String(), pendingSITBalance.TotalSITEndDate.UTC().String()) }) suite.Run("ignores including previously denied service items in SIT balance", func() { @@ -842,7 +842,7 @@ func (suite *PaymentRequestServiceSuite) TestListShipmentPaymentSITBalance() { suite.Equal(shipment.ID.String(), pendingSITBalance.ShipmentID.String()) suite.Equal(120, pendingSITBalance.TotalSITDaysAuthorized) suite.Equal(60, pendingSITBalance.PendingSITDaysInvoiced) - suite.Equal(44, pendingSITBalance.TotalSITDaysRemaining) + suite.Equal(43, pendingSITBalance.TotalSITDaysRemaining) suite.Equal(destinationPaymentEndDate.String(), pendingSITBalance.PendingBilledEndDate.String()) suite.Nil(pendingSITBalance.PreviouslyBilledDays) }) diff --git a/pkg/services/sit_status/shipment_sit_status.go b/pkg/services/sit_status/shipment_sit_status.go index da8fd7bd265..79e6cdc624b 100644 --- a/pkg/services/sit_status/shipment_sit_status.go +++ b/pkg/services/sit_status/shipment_sit_status.go @@ -30,16 +30,16 @@ func NewShipmentSITStatus() services.ShipmentSITStatus { } type SortedShipmentSITs struct { - pastSITs models.SITServiceItemGroupings - currentSITs models.SITServiceItemGroupings - futureSITs models.SITServiceItemGroupings + PastSITs models.SITServiceItemGroupings + CurrentSITs models.SITServiceItemGroupings // Takes an array but at this time only a single CurrentSIT is supported. This could potentially be used for partial delivery current SITs + FutureSITs models.SITServiceItemGroupings } func newSortedShipmentSITs() SortedShipmentSITs { return SortedShipmentSITs{ - pastSITs: make([]models.SITServiceItemGrouping, 0), - currentSITs: make([]models.SITServiceItemGrouping, 0), - futureSITs: make([]models.SITServiceItemGrouping, 0), + PastSITs: make([]models.SITServiceItemGrouping, 0), + CurrentSITs: make([]models.SITServiceItemGrouping, 0), + FutureSITs: make([]models.SITServiceItemGrouping, 0), } } @@ -48,11 +48,11 @@ func SortShipmentSITs(sitGroupings models.SITServiceItemGroupings, today time.Ti shipmentSITs := newSortedShipmentSITs() for _, sitGrouping := range sitGroupings { if sitGrouping.Summary.SITEntryDate.After(today) { - shipmentSITs.futureSITs = append(shipmentSITs.futureSITs, sitGrouping) + shipmentSITs.FutureSITs = append(shipmentSITs.FutureSITs, sitGrouping) } else if sitGrouping.Summary.SITDepartureDate != nil && sitGrouping.Summary.SITDepartureDate.Before(today) { - shipmentSITs.pastSITs = append(shipmentSITs.pastSITs, sitGrouping) + shipmentSITs.PastSITs = append(shipmentSITs.PastSITs, sitGrouping) } else { - shipmentSITs.currentSITs = append(shipmentSITs.currentSITs, sitGrouping) + shipmentSITs.CurrentSITs = append(shipmentSITs.CurrentSITs, sitGrouping) } } return shipmentSITs @@ -73,7 +73,7 @@ func Clamp(input, min, max int) (int, error) { // Retrieve the SIT service item groupings for the provided shipment // Each SIT grouping has a top-level summary of the grouped SIT -func (f shipmentSITStatus) RetrieveShipmentSIT(appCtx appcontext.AppContext, shipment models.MTOShipment) models.SITServiceItemGroupings { +func (f shipmentSITStatus) RetrieveShipmentSIT(appCtx appcontext.AppContext, shipment models.MTOShipment) (models.SITServiceItemGroupings, error) { var shipmentSITs models.SITServiceItemGroupings year, month, day := time.Now().Date() @@ -113,16 +113,22 @@ func (f shipmentSITStatus) RetrieveShipmentSIT(appCtx appcontext.AppContext, shi } } + // Get the total SIT allowance for this shipment + totalSITAllowance, err := f.CalculateShipmentSITAllowance(appCtx, shipment) + if err != nil { + return nil, err + } + // Generate summaries for each group and append them to shipmentSITs for _, group := range groupedSITs { - summary := f.generateSITSummary(*group, today) + summary := f.generateSITSummary(*group, today, totalSITAllowance) if summary != nil { group.Summary = *summary shipmentSITs = append(shipmentSITs, *group) } } - return shipmentSITs + return shipmentSITs, nil } // Helper function to take in an MTO service item's ReServiceCode and validate it @@ -138,23 +144,24 @@ func containsReServiceCode(validCodes []models.ReServiceCode, code models.ReServ } // Helper function to generate the SIT Summary for a group of service items -func (f shipmentSITStatus) generateSITSummary(sit models.SITServiceItemGrouping, today time.Time) *models.SITSummary { +// This is where the craziest part of the SIT code should ever be (Besides the grouping section) +// Due to our service item architecture, SIT is split across many service items +// and due to existing handlers and service objects, it's possible these SIT service items +// will have discrepancies and information spread across multiple items. +// This SIT summary is to make it readable down the line, and handle all complex calculations +// in one, central location. +func (f shipmentSITStatus) generateSITSummary(sit models.SITServiceItemGrouping, today time.Time, totalSitAllowance int) *models.SITSummary { if sit.ServiceItems == nil { // Return nil if there are no service items return nil } - // This is where the craziest part of the code should ever be (Besides the grouping section) - // Due to our service item architecture, SIT is split across many service items - // and due to existing handlers and service objects, it's possible these SIT service items - // will have discrepancies and information spread across multiple items. - // This SIT summary is to make it readable down the line, and handle all complex calculations - // in one, central location. + var earliestSITEntryDate *time.Time var earliestSITDepartureDate *time.Time var earliestSITAuthorizedEndDate *time.Time var earliestSITCustomerContacted *time.Time var earliestSITRequestedDelivery *time.Time - var calculatedTotalDaysInSIT *int + var calculatedTotalDaysInSIT int var location string var firstDaySITServiceItemID uuid.UUID @@ -191,18 +198,21 @@ func (f shipmentSITStatus) generateSITSummary(sit models.SITServiceItemGrouping, if earliestSITDepartureDate == nil || (sitServiceItem.SITDepartureDate != nil && sitServiceItem.SITDepartureDate.Before(*earliestSITDepartureDate)) { earliestSITDepartureDate = sitServiceItem.SITDepartureDate } + } - // Grab the earliest SIT Authorized End Date - // based off of the provided earliest SIT entry date - // retrieving the authorized end date requires a SIT entry date - if earliestSITAuthorizedEndDate == nil && earliestSITEntryDate != nil { - daysInSIT := daysInSIT(*earliestSITEntryDate, earliestSITDepartureDate, today) - calculatedTotalDaysInSIT = &daysInSIT - earliestSITAuthorizedEndDateValue := CalculateSITAuthorizedEndDate(len(sit.ServiceItems), daysInSIT, *earliestSITEntryDate, *calculatedTotalDaysInSIT) - earliestSITAuthorizedEndDate = &earliestSITAuthorizedEndDateValue - } + // Calculate the days in SIT based on the earliest SIT entry date and earliest SIT departure date if any were discovered from the SIT group + if earliestSITEntryDate != nil { + calculatedTotalDaysInSIT = daysInSIT(*earliestSITEntryDate, earliestSITDepartureDate, today) + } + + // Calculate the SIT Authorized End Date + if earliestSITEntryDate != nil { + earliestSITAuthorizedEndDateValue := CalculateSITAuthorizedEndDate(totalSitAllowance, calculatedTotalDaysInSIT, *earliestSITEntryDate, calculatedTotalDaysInSIT, earliestSITDepartureDate) + earliestSITAuthorizedEndDate = &earliestSITAuthorizedEndDateValue + } - // Grab the first Customer Contacted + // Grab the first Customer Contacted + for _, sitServiceItem := range sit.ServiceItems { if earliestSITCustomerContacted == nil && sitServiceItem.SITCustomerContacted != nil { earliestSITCustomerContacted = sitServiceItem.SITCustomerContacted } @@ -216,7 +226,7 @@ func (f shipmentSITStatus) generateSITSummary(sit models.SITServiceItemGrouping, return &models.SITSummary{ FirstDaySITServiceItemID: firstDaySITServiceItemID, Location: location, - DaysInSIT: *calculatedTotalDaysInSIT, + DaysInSIT: calculatedTotalDaysInSIT, SITEntryDate: *earliestSITEntryDate, SITDepartureDate: earliestSITDepartureDate, SITAuthorizedEndDate: *earliestSITAuthorizedEndDate, @@ -237,7 +247,10 @@ func (f shipmentSITStatus) CalculateShipmentSITStatus(appCtx appcontext.AppConte year, month, day := time.Now().Date() today := time.Date(year, month, day, 0, 0, 0, 0, time.UTC) - sitGroupings := f.RetrieveShipmentSIT(appCtx, shipment) + sitGroupings, err := f.RetrieveShipmentSIT(appCtx, shipment) + if err != nil { + return nil, shipment, err + } // Sort the SIT groupings into past, current, future shipmentSITGroupings := SortShipmentSITs(sitGroupings, today) @@ -247,7 +260,7 @@ func (f shipmentSITStatus) CalculateShipmentSITStatus(appCtx appcontext.AppConte currentSIT := getCurrentSIT(shipmentSITGroupings) // There were no relevant SIT service items for this shipment - if currentSIT == nil && len(shipmentSITGroupings.pastSITs) == 0 { + if currentSIT == nil && len(shipmentSITGroupings.PastSITs) == 0 { return nil, shipment, nil } @@ -263,7 +276,7 @@ func (f shipmentSITStatus) CalculateShipmentSITStatus(appCtx appcontext.AppConte shipmentSITStatus.TotalSITDaysUsed = totalSITDaysUsedClampedResult shipmentSITStatus.CalculatedTotalDaysInSIT = CalculateTotalDaysInSIT(shipmentSITGroupings, today) shipmentSITStatus.TotalDaysRemaining = totalSITAllowance - shipmentSITStatus.TotalSITDaysUsed - shipmentSITStatus.PastSITs = shipmentSITGroupings.pastSITs + shipmentSITStatus.PastSITs = shipmentSITGroupings.PastSITs if currentSIT != nil { location := currentSIT.Summary.Location @@ -271,7 +284,7 @@ func (f shipmentSITStatus) CalculateShipmentSITStatus(appCtx appcontext.AppConte daysInSIT := daysInSIT(currentSIT.Summary.SITEntryDate, currentSIT.Summary.SITDepartureDate, today) sitEntryDate := currentSIT.Summary.SITEntryDate sitDepartureDate := currentSIT.Summary.SITDepartureDate - sitAuthorizedEndDate := CalculateSITAuthorizedEndDate(totalSITAllowance, daysInSIT, sitEntryDate, shipmentSITStatus.CalculatedTotalDaysInSIT) + sitAuthorizedEndDate := CalculateSITAuthorizedEndDate(totalSITAllowance, daysInSIT, sitEntryDate, shipmentSITStatus.CalculatedTotalDaysInSIT, sitDepartureDate) var sitCustomerContacted, sitRequestedDelivery *time.Time sitCustomerContacted = currentSIT.Summary.SITCustomerContacted sitRequestedDelivery = currentSIT.Summary.SITRequestedDelivery @@ -322,10 +335,10 @@ SIT service items that have already started are prioritized, followed by SIT service items that start in the future. */ func getCurrentSIT(shipmentSITs SortedShipmentSITs) *models.SITServiceItemGrouping { - if len(shipmentSITs.currentSITs) > 0 { - return getEarliestSIT(shipmentSITs.currentSITs) - } else if len(shipmentSITs.futureSITs) > 0 { - return getEarliestSIT(shipmentSITs.futureSITs) + if len(shipmentSITs.CurrentSITs) > 0 { + return getEarliestSIT(shipmentSITs.CurrentSITs) + } else if len(shipmentSITs.FutureSITs) > 0 { + return getEarliestSIT(shipmentSITs.FutureSITs) } return nil } @@ -340,20 +353,21 @@ func getCurrentSIT(shipmentSITs SortedShipmentSITs) *models.SITServiceItemGroupi // return value is Today - SITEntryDate, adding 1 to include today. func daysInSIT(sitEntryDate time.Time, sitDepartureDate *time.Time, today time.Time) int { var days int + // Per B-20967, the last day should now always be inclusive even if there is a SIT departure date if sitDepartureDate != nil && sitDepartureDate.Before(today) { - days = int(sitDepartureDate.Sub(sitEntryDate).Hours()) / 24 + days = int(sitDepartureDate.Sub(sitEntryDate).Hours())/24 + 1 } else if sitEntryDate.Before(today) || sitEntryDate.Equal(today) { - days = int(today.Sub(sitEntryDate).Hours())/24 + 1 // This is to count start and end as full days + days = int(today.Sub(sitEntryDate).Hours())/24 + 1 } return days } func CalculateTotalDaysInSIT(shipmentSITs SortedShipmentSITs, today time.Time) int { totalDays := 0 - for _, pastSIT := range shipmentSITs.pastSITs { + for _, pastSIT := range shipmentSITs.PastSITs { totalDays += daysInSIT(pastSIT.Summary.SITEntryDate, pastSIT.Summary.SITDepartureDate, today) } - for _, currentSIT := range shipmentSITs.currentSITs { + for _, currentSIT := range shipmentSITs.CurrentSITs { totalDays += daysInSIT(currentSIT.Summary.SITEntryDate, currentSIT.Summary.SITDepartureDate, today) } return totalDays @@ -362,14 +376,29 @@ func CalculateTotalDaysInSIT(shipmentSITs SortedShipmentSITs, today time.Time) i // adds up all the days from pastSITs func CalculateTotalPastDaysInSIT(shipmentSITs SortedShipmentSITs, today time.Time) int { totalDays := 0 - for _, pastSIT := range shipmentSITs.pastSITs { + for _, pastSIT := range shipmentSITs.PastSITs { totalDays += daysInSIT(pastSIT.Summary.SITEntryDate, pastSIT.Summary.SITDepartureDate, today) } return totalDays } -func CalculateSITAuthorizedEndDate(totalSITAllowance int, currentDaysInSIT int, sitEntryDate time.Time, calculatedTotalDaysInSIT int) time.Time { - return sitEntryDate.AddDate(0, 0, (totalSITAllowance - (calculatedTotalDaysInSIT - currentDaysInSIT))) +func CalculateSITAuthorizedEndDate(totalSITAllowance int, currentDaysInSIT int, sitEntryDate time.Time, totalDaysInSITSoFar int, sitDepartureDate *time.Time) time.Time { + sitAuthorizedEndDate := sitEntryDate.AddDate(0, 0, (totalSITAllowance - (totalDaysInSITSoFar - currentDaysInSIT))) + // Subtract the last day to be inclusive of counting it + // Eg, this func successfully counts totalSITAllowance days from SITEntryDate, but per customer requirements, they will + // then count that last day too. So if given 90 days of allowance, we'd get Aug 20 2024 thru Nov 18 2024. 90 days as expected + // but then if you count the last day, it gets 91. Thus making the calculation incorrect. This is why we subtract a day, to be inclusive of it + sitAuthorizedEndDate = sitAuthorizedEndDate.AddDate(0, 0, -1) + // Ensure that the authorized end date does not go before the entry date + if sitAuthorizedEndDate.Before(sitEntryDate) { + sitAuthorizedEndDate = sitEntryDate + } + // If the SIT departure date is set and it is before the currently authorized end date + // then the original SIT authorized end date should be updated to the departure date + if sitDepartureDate != nil && (sitDepartureDate.Before(sitAuthorizedEndDate) && sitDepartureDate.After(sitEntryDate)) { + sitAuthorizedEndDate = *sitDepartureDate + } + return sitAuthorizedEndDate } func (f shipmentSITStatus) CalculateShipmentsSITStatuses(appCtx appcontext.AppContext, shipments []models.MTOShipment) map[string]services.SITStatus { diff --git a/pkg/services/sit_status/shipment_sit_status_test.go b/pkg/services/sit_status/shipment_sit_status_test.go index 36980ecb724..8b9da651035 100644 --- a/pkg/services/sit_status/shipment_sit_status_test.go +++ b/pkg/services/sit_status/shipment_sit_status_test.go @@ -116,9 +116,9 @@ func (suite *SITStatusServiceSuite) TestShipmentSITStatus() { suite.NotNil(sitStatus) suite.Len(sitStatus.PastSITs, 1) suite.Equal(dofsit.ID.String(), sitStatus.PastSITs[0].ServiceItems[0].ID.String()) - suite.Equal(15, sitStatus.TotalSITDaysUsed) - suite.Equal(15, sitStatus.CalculatedTotalDaysInSIT) - suite.Equal(75, sitStatus.TotalDaysRemaining) + suite.Equal(16, sitStatus.TotalSITDaysUsed) + suite.Equal(16, sitStatus.CalculatedTotalDaysInSIT) + suite.Equal(74, sitStatus.TotalDaysRemaining) suite.Nil(sitStatus.CurrentSIT) // No current SIT since all SIT items have departed status // check that shipment values impacted by current SIT do not get updated since current SIT is nil suite.Nil(shipment.DestinationSITAuthEndDate) @@ -238,9 +238,9 @@ func (suite *SITStatusServiceSuite) TestShipmentSITStatus() { suite.NotNil(sitStatus) suite.Equal(OriginSITLocation, sitStatus.CurrentSIT.Location) - suite.Equal(23, sitStatus.TotalSITDaysUsed) // 15 days from previous SIT, 7 days from the current - suite.Equal(23, sitStatus.CalculatedTotalDaysInSIT) - suite.Equal(67, sitStatus.TotalDaysRemaining) + suite.Equal(24, sitStatus.TotalSITDaysUsed) // 15 days from previous SIT, 7 days from the current + suite.Equal(24, sitStatus.CalculatedTotalDaysInSIT) + suite.Equal(66, sitStatus.TotalDaysRemaining) suite.Equal(8, sitStatus.CurrentSIT.DaysInSIT) suite.Equal(aWeekAgo.String(), sitStatus.CurrentSIT.SITEntryDate.String()) suite.Nil(sitStatus.CurrentSIT.SITDepartureDate) @@ -315,9 +315,9 @@ func (suite *SITStatusServiceSuite) TestShipmentSITStatus() { suite.NotNil(sitStatus) suite.Equal(DestinationSITLocation, sitStatus.CurrentSIT.Location) - suite.Equal(23, sitStatus.TotalSITDaysUsed) // 15 days from previous SIT, 7 days from the current - suite.Equal(23, sitStatus.CalculatedTotalDaysInSIT) - suite.Equal(67, sitStatus.TotalDaysRemaining) + suite.Equal(24, sitStatus.TotalSITDaysUsed) // 15 days from previous SIT, 7 days from the current + suite.Equal(24, sitStatus.CalculatedTotalDaysInSIT) + suite.Equal(66, sitStatus.TotalDaysRemaining) suite.Equal(8, sitStatus.CurrentSIT.DaysInSIT) suite.Equal(aWeekAgo.String(), sitStatus.CurrentSIT.SITEntryDate.String()) suite.Nil(sitStatus.CurrentSIT.SITDepartureDate) diff --git a/pkg/testdatagen/testharness/dispatch.go b/pkg/testdatagen/testharness/dispatch.go index ff91b5b0890..8033ca02825 100644 --- a/pkg/testdatagen/testharness/dispatch.go +++ b/pkg/testdatagen/testharness/dispatch.go @@ -59,6 +59,9 @@ var actionDispatcher = map[string]actionFunc{ "HHGMoveInSIT": func(appCtx appcontext.AppContext) testHarnessResponse { return MakeHHGMoveInSIT(appCtx) }, + "HHGMoveWithPastSITs": func(appCtx appcontext.AppContext) testHarnessResponse { + return HHGMoveWithPastSITs(appCtx) + }, "HHGMoveInSITNoDestinationSITOutDate": func(appCtx appcontext.AppContext) testHarnessResponse { return MakeHHGMoveInSITNoDestinationSITOutDate(appCtx) }, diff --git a/pkg/testdatagen/testharness/make_move.go b/pkg/testdatagen/testharness/make_move.go index 54fd95f67b4..23e8665a889 100644 --- a/pkg/testdatagen/testharness/make_move.go +++ b/pkg/testdatagen/testharness/make_move.go @@ -5321,6 +5321,123 @@ func MakeHHGMoveInSIT(appCtx appcontext.AppContext) models.Move { return move } +// Creates an HHG move with a past Origin and Destination SIT +func HHGMoveWithPastSITs(appCtx appcontext.AppContext) models.Move { + userUploader := newUserUploader(appCtx) + userInfo := newUserInfo("customer") + + user := factory.BuildUser(appCtx.DB(), []factory.Customization{ + { + Model: models.User{ + OktaEmail: userInfo.email, + Active: true, + }, + }, + }, nil) + customer := factory.BuildExtendedServiceMember(appCtx.DB(), []factory.Customization{ + { + Model: models.ServiceMember{ + PersonalEmail: &userInfo.email, + FirstName: &userInfo.firstName, + LastName: &userInfo.lastName, + CacValidated: true, + }, + }, + { + Model: user, + LinkOnly: true, + }, + }, nil) + dependentsAuthorized := true + sitDaysAllowance := 90 + entitlements := factory.BuildEntitlement(appCtx.DB(), []factory.Customization{ + { + Model: models.Entitlement{ + DependentsAuthorized: &dependentsAuthorized, + StorageInTransit: &sitDaysAllowance, + }, + }, + }, nil) + orders := factory.BuildOrder(appCtx.DB(), []factory.Customization{ + { + Model: customer, + LinkOnly: true, + }, + { + Model: entitlements, + LinkOnly: true, + }, + { + Model: models.UserUpload{}, + ExtendedParams: &factory.UserUploadExtendedParams{ + UserUploader: userUploader, + AppContext: appCtx, + }, + }, + }, nil) + now := time.Now() + move := factory.BuildMove(appCtx.DB(), []factory.Customization{ + { + Model: orders, + LinkOnly: true, + }, + { + Model: models.Move{ + Status: models.MoveStatusAPPROVALSREQUESTED, + AvailableToPrimeAt: &now, + }, + }, + }, nil) + estimatedWeight := unit.Pound(1400) + actualWeight := unit.Pound(2000) + + requestedPickupDate := now.AddDate(0, 3, 0) + requestedDeliveryDate := requestedPickupDate.AddDate(0, 1, 0) + // pickupAddress := factory.BuildAddress(appCtx.DB(), nil, nil) + + shipment := factory.BuildMTOShipment(appCtx.DB(), []factory.Customization{ + { + Model: models.MTOShipment{ + PrimeEstimatedWeight: &estimatedWeight, + PrimeActualWeight: &actualWeight, + ShipmentType: models.MTOShipmentTypeHHG, + Status: models.MTOShipmentStatusApproved, + RequestedPickupDate: &requestedPickupDate, + RequestedDeliveryDate: &requestedDeliveryDate, + SITDaysAllowance: &sitDaysAllowance, + }, + }, + { + Model: move, + LinkOnly: true, + }, + }, nil) + + agentUserInfo := newUserInfo("agent") + factory.BuildMTOAgent(appCtx.DB(), []factory.Customization{ + { + Model: shipment, + LinkOnly: true, + }, + {Model: models.MTOAgent{ + FirstName: &agentUserInfo.firstName, + LastName: &agentUserInfo.lastName, + Email: &agentUserInfo.email, + MTOAgentType: models.MTOAgentReleasing, + }, + }, + }, nil) + + fourMonthsAgo := now.AddDate(0, 0, -120) + threeMonthsAgo := now.AddDate(0, 0, -90) + twoMonthsAgo := now.AddDate(0, 0, -60) + oneMonthAgo := now.AddDate(0, 0, -30) + factory.BuildOriginSITServiceItems(appCtx.DB(), move, shipment, &fourMonthsAgo, &threeMonthsAgo) + factory.BuildDestSITServiceItems(appCtx.DB(), move, shipment, &twoMonthsAgo, &oneMonthAgo) + + return move +} + func MakeHHGMoveInSITNoExcessWeight(appCtx appcontext.AppContext) models.Move { userUploader := newUserUploader(appCtx) userInfo := newUserInfo("customer") diff --git a/playwright/tests/office/txo/sitUpdates.spec.js b/playwright/tests/office/txo/sitUpdates.spec.js index 23f739b0b88..cc7bd670288 100644 --- a/playwright/tests/office/txo/sitUpdates.spec.js +++ b/playwright/tests/office/txo/sitUpdates.spec.js @@ -1,5 +1,4 @@ // @ts-check - import { test, expect } from '../../utils/office/officeTest'; import { TooFlowPage } from './tooTestFixture'; @@ -8,6 +7,147 @@ test.describe('TOO user', () => { /** @type {TooFlowPage} */ let tooFlowPage; + // Helper func to calculate days between 2 given dates + // This is to support months of 30 and 31 dayss + const calculateDaysDiff = (startDate, endDate) => { + let days = 0; + const currentDate = new Date(startDate); + + while (currentDate < endDate) { + days += 1; + currentDate.setDate(currentDate.getDate() + 1); + } + + return days; + }; + + test.describe('previewing shipment with current SIT with past SIT', () => { + test.beforeEach(async ({ officePage }) => { + // build move in SIT with 90 days authorized and without pending extension requests + // SIT entry date of 30 days ago, no departure date so it is current + const move = await officePage.testHarness.buildHHGMoveInSIT(); + await officePage.signInAsNewTOOUser(); + tooFlowPage = new TooFlowPage(officePage, move); + await tooFlowPage.waitForLoading(); + await officePage.tooNavigateToMove(tooFlowPage.moveLocator); + }); + + test('sum of days is correct between past Origin SIT and current Destination SIT', async ({ page }) => { + // navigate to MTO tab + await page.getByTestId('MoveTaskOrder-Tab').click(); + await tooFlowPage.waitForPage.moveTaskOrder(); + // assert that days authorization is 90 + await expect(page.getByTestId('sitStatusTable').getByText('90', { exact: true }).first()).toBeVisible(); + // get today + const today = new Date(); + // get 1 month ago + const oneMonthAgo = new Date(today); + oneMonthAgo.setMonth(today.getMonth() - 1); + // get 2 months ago + const twoMonthsAgo = new Date(today); + twoMonthsAgo.setMonth(today.getMonth() - 2); + // get days between + const daysBetweenTwoMonthsAgoAndOneMonthAgo = calculateDaysDiff(twoMonthsAgo, oneMonthAgo); + const daysBetweenOneMonthAgoAndToday = calculateDaysDiff(oneMonthAgo, today); + // get sums + const totalDaysUsed = daysBetweenTwoMonthsAgoAndOneMonthAgo + daysBetweenOneMonthAgoAndToday; + const remainingDays = 90 - totalDaysUsed; + // assert that days used is the following sum + // - past origin SIT (entry 2 months ago, departure 1 month ago) + // - current destination SIT (entry 1 month ago, departure not given yet) + await expect( + page.getByTestId('sitStatusTable').getByText(`${totalDaysUsed}`, { exact: true }).first(), + ).toBeVisible(); + // assert that days remaining is authorized minus totalDaysUsed + await expect( + page.getByTestId('sitStatusTable').getByText(`${remainingDays}`, { exact: true }).first(), + ).toBeVisible(); + // assert that total days in destination sit is 1 month, inclusive of last day + await expect( + page.getByTestId('sitStartAndEndTable').getByText(`${daysBetweenOneMonthAgoAndToday}`, { exact: true }).first(), + ).toBeVisible(); + + // Get the SIT start date from the UI + const sitStartDateText = await page.getByTestId('sitStartAndEndTable').locator('td').nth(0).innerText(); + const sitStartDate = new Date(sitStartDateText); + + // Calculate the authorized end date by adding 90 days to the start date and then subtracting total days used + const authorizedEndDate = new Date(sitStartDate); + // Use 89 because the last day is counted as a whole day + // Subtract by "daysBetweenTwoMonthsAgoAndOneMonthAgo" (past SIT days) instead of total days used + // This is because the authorized end date is based on the remaining days at the start of the current SIT + authorizedEndDate.setDate(authorizedEndDate.getDate() + 89 - daysBetweenTwoMonthsAgoAndOneMonthAgo); + // format + const day = new Intl.DateTimeFormat('en', { day: '2-digit' }).format(authorizedEndDate); + const month = new Intl.DateTimeFormat('en', { month: 'short' }).format(authorizedEndDate); + const year = new Intl.DateTimeFormat('en', { year: 'numeric' }).format(authorizedEndDate); + const expectedAuthorizedEndDate = `${day} ${month} ${year}`; + // assert + await expect( + page.getByTestId('sitStartAndEndTable').getByText(`${expectedAuthorizedEndDate}`, { exact: true }).first(), + ).toBeVisible(); + }); + }); + + test.describe('previewing shipment with past origin and destination SIT', () => { + test.beforeEach(async ({ officePage }) => { + // build move in SIT with 90 days authorized and without pending extension requests + // Origin sit had an entry date of four months ago, departure date of three months ago + // Destination sit had an entry date of two months ago, departure date of one month ago + const move = await officePage.testHarness.buildHHGMoveWithPastSITs(); + await officePage.signInAsNewTOOUser(); + tooFlowPage = new TooFlowPage(officePage, move); + await tooFlowPage.waitForLoading(); + await officePage.tooNavigateToMove(tooFlowPage.moveLocator); + }); + + test('sum of days is correct between past Origin SIT and past Destination SIT', async ({ page }) => { + // navigate to MTO tab + await page.getByTestId('MoveTaskOrder-Tab').click(); + await tooFlowPage.waitForPage.moveTaskOrder(); + // assert that days authorization is 90 + await expect(page.getByTestId('sitStatusTable').getByText('90', { exact: true }).first()).toBeVisible(); + // get today + const today = new Date(); + // get months + const destinationDepartureDate = new Date(today); + destinationDepartureDate.setMonth(today.getMonth() - 1); + const destinationEntryDate = new Date(today); + destinationEntryDate.setMonth(today.getMonth() - 2); + const originDepartureDate = new Date(today); + originDepartureDate.setMonth(today.getMonth() - 3); + const originEntryDate = new Date(today); + originEntryDate.setMonth(today.getMonth() - 4); + // days between + const totalDaysBetweenDestination = calculateDaysDiff(destinationEntryDate, destinationDepartureDate); + const totalDaysBetweenOrigin = calculateDaysDiff(originEntryDate, originDepartureDate); + // get sums + const totalDaysUsed = totalDaysBetweenDestination + totalDaysBetweenOrigin; + const remainingDays = 90 - totalDaysUsed; + // assert sums + await expect( + page.getByTestId('sitStatusTable').getByText(`${totalDaysUsed}`, { exact: true }).first(), + ).toBeVisible(); + // assert that days remaining is authorized minus totalDaysUsed + await expect( + page.getByTestId('sitStatusTable').getByText(`${remainingDays}`, { exact: true }).first(), + ).toBeVisible(); + // assert previous sit days + await expect( + page + .getByTestId('previouslyUsedSitTable') + .getByText(`${totalDaysBetweenDestination} days at destination`, { exact: false }) + .first(), + ).toBeVisible(); + await expect( + page + .getByTestId('previouslyUsedSitTable') + .getByText(`${totalDaysBetweenOrigin} days at origin`, { exact: false }) + .first(), + ).toBeVisible(); + }); + }); + test.describe('updating a move shipment in SIT', () => { test.beforeEach(async ({ officePage }) => { // build move in SIT with 90 days authorized and without pending extension requests @@ -24,11 +164,11 @@ test.describe('TOO user', () => { await tooFlowPage.waitForPage.moveTaskOrder(); const target = await page - .getByTestId('sitDaysAtCurrentLocation') + .getByTestId('currentSitDepartureDate') .locator('table[class="DataTable_dataTable__TGt9M table--data-point"]') .locator('tbody') .locator('td') - .nth(1) + .nth(0) .locator('div') .locator('span') .textContent(); @@ -103,8 +243,8 @@ test.describe('TOO user', () => { .textContent(); expect(daysApprovedCapture).toEqual('90'); - expect(daysUsedCapture).toEqual('61'); // 30 days in past origin sit, 31 days in destination sit - expect(daysLeftCapture).toEqual('29'); // of the 90 authorized, 61 have been used + expect(daysUsedCapture).toEqual('62'); // 31 days in past origin sit, 31 days in destination sit + expect(daysLeftCapture).toEqual('28'); // of the 90 authorized, 62 have been used }); test('is unable to decrease the SIT authorization below the number of days already used', async ({ page }) => { @@ -248,7 +388,7 @@ test.describe('TOO user', () => { await expect(page.getByText('Total days remaining')).toBeVisible(); await expect(page.getByText('SIT start date').nth(0)).toBeVisible(); await expect(page.getByText('SIT authorized end date')).toBeVisible(); - await expect(page.getByText('Calculated total SIT days')).toBeVisible(); + await expect(page.getByText('Total days in destination SIT')).toBeVisible(); }); test('is showing the SIT Departure Date section', async ({ page }) => { // navigate to MTO tab diff --git a/playwright/tests/utils/testharness.js b/playwright/tests/utils/testharness.js index ff4d7f61dc3..1faf82f5ee5 100644 --- a/playwright/tests/utils/testharness.js +++ b/playwright/tests/utils/testharness.js @@ -177,6 +177,14 @@ export class TestHarness { return this.buildDefault('HHGMoveInSIT'); } + /** + * Use testharness to build a move with an hhg shipment with a past origin and destination SIT + * @returns {Promise} + */ + async buildHHGMoveWithPastSITs() { + return this.buildDefault('HHGMoveWithPastSITs'); + } + /** * * Use testharness to build a move with an hhg shipment in SIT without destination address * @returns {Promise} diff --git a/src/components/Office/ShipmentSITDisplay/ShipmentSITDisplay.jsx b/src/components/Office/ShipmentSITDisplay/ShipmentSITDisplay.jsx index 670eede75e4..3d6712fd034 100644 --- a/src/components/Office/ShipmentSITDisplay/ShipmentSITDisplay.jsx +++ b/src/components/Office/ShipmentSITDisplay/ShipmentSITDisplay.jsx @@ -105,16 +105,16 @@ const SitStatusTables = ({ shipment, sitExtensions, sitStatus, openModalButton, sitEntryDate = moment(sitEntryDate, swaggerDateFormat); const sitStartDateElement =

{formatDate(sitEntryDate, swaggerDateFormat, 'DD MMM YYYY')}

; const sitEndDate = - formatDateForDatePicker( - moment(sitStatus.currentSIT?.sitAuthorizedEndDate, swaggerDateFormat).subtract(1, 'days'), - ) || '\u2014'; + formatDateForDatePicker(moment(sitStatus.currentSIT?.sitAuthorizedEndDate, swaggerDateFormat)) || '\u2014'; // Previous SIT calculations and date ranges const previousDaysUsed = sitStatus.pastSITServiceItemGroupings?.map((sitGroup) => { // Build the past SIT text based off the past sit group summary rather than individual service items - const sitDaysUsed = moment(sitGroup.summary.sitDepartureDate).diff(sitGroup.summary.sitEntryDate, 'days'); + // The server provides sitDaysUsed + const sitDaysUsed = sitGroup.summary.daysInSIT || DEFAULT_EMPTY_VALUE; const location = sitGroup.summary.location === LOCATION_TYPES.ORIGIN ? 'origin' : 'destination'; + // Display the dates the server used to calculate sitDaysUsed const start = formatDate(sitGroup.summary.sitEntryDate, swaggerDateFormat, 'DD MMM YYYY'); const end = formatDate(sitGroup.summary.sitDepartureDate, swaggerDateFormat, 'DD MMM YYYY'); const text = `${sitDaysUsed} days at ${location} (${start} - ${end})`; @@ -179,20 +179,20 @@ const SitStatusTables = ({ shipment, sitExtensions, sitStatus, openModalButton, {sitStatus.currentSIT && ( <>
- {/* Sit Start and End table */} + {/* Sit Start and End table with total days at current location */} {currentDaysInSIT > 0 &&

Current location: {currentLocation}

}
-
- {/* Total days at current location */} +
+ {/* Current SIT departure date */}
@@ -201,7 +201,7 @@ const SitStatusTables = ({ shipment, sitExtensions, sitStatus, openModalButton, {/* Past SIT Service Items Info Section */} {sitStatus.pastSITServiceItemGroupings && ( <> -
+
{!sitStatus.currentSIT && ( diff --git a/src/components/Office/ShipmentSITDisplay/ShipmentSITDisplay.test.jsx b/src/components/Office/ShipmentSITDisplay/ShipmentSITDisplay.test.jsx index 0da70b8a58c..96c6128fed9 100644 --- a/src/components/Office/ShipmentSITDisplay/ShipmentSITDisplay.test.jsx +++ b/src/components/Office/ShipmentSITDisplay/ShipmentSITDisplay.test.jsx @@ -63,10 +63,10 @@ describe('ShipmentSITDisplay', () => { expect(screen.getByText('Current location: destination SIT')).toBeInTheDocument(); expect(screen.getByText('Total days in destination SIT')).toBeInTheDocument(); expect(screen.getByText('15')).toBeInTheDocument(); - const sitStartAndEndTable = await screen.findByTestId('sitStartAndEndTable'); - expect(sitStartAndEndTable).toBeInTheDocument(); - expect(within(sitStartAndEndTable).getByText('Calculated total SIT days')).toBeInTheDocument(); - expect(within(sitStartAndEndTable).getByText('45')).toBeInTheDocument(); + const sitStatusTable = await screen.findByTestId('sitStatusTable'); + expect(sitStatusTable).toBeInTheDocument(); + expect(within(sitStatusTable).getByText('Total days used')).toBeInTheDocument(); + expect(within(sitStatusTable).getByText('45')).toBeInTheDocument(); }); it('renders the Shipment SIT at Origin, with customer delivery info', async () => { @@ -246,12 +246,12 @@ describe('ShipmentSITDisplay', () => { expect(within(sitStartAndEndTable).queryByText('Current location')).not.toBeInTheDocument(); expect(within(sitStartAndEndTable).getByText('SIT start date')).toBeInTheDocument(); expect(within(sitStartAndEndTable).getByText('SIT authorized end date')).toBeInTheDocument(); - expect(within(sitStartAndEndTable).getByText('Calculated total SIT days')).toBeInTheDocument(); + expect(within(sitStartAndEndTable).getByText('Total days in origin SIT')).toBeInTheDocument(); expect(within(sitStartAndEndTable).getByText('0')).toBeInTheDocument(); - const sitDaysAtCurrentLocation = await screen.findByTestId('sitDaysAtCurrentLocation'); - expect(sitDaysAtCurrentLocation).toBeInTheDocument(); - expect(within(sitDaysAtCurrentLocation).getByText('Total days in origin SIT')).toBeInTheDocument(); - expect(within(sitDaysAtCurrentLocation).getByText('0')).toBeInTheDocument(); + const currentSitDepartureDate = await screen.findByTestId('currentSitDepartureDate'); + expect(currentSitDepartureDate).toBeInTheDocument(); + expect(within(currentSitDepartureDate).getByText('SIT departure date')).toBeInTheDocument(); + expect(within(currentSitDepartureDate).getByText('—')).toBeInTheDocument(); }); it('calls SIT extension callback when button clicked', async () => { @@ -419,7 +419,7 @@ describe('ShipmentSITDisplay', () => { const sitStartAndEndTable = await screen.findByTestId('sitStartAndEndTable'); expect(sitStartAndEndTable).toBeInTheDocument(); expect(within(sitStartAndEndTable).getByText('SIT authorized end date')).toBeInTheDocument(); - expect(within(sitStartAndEndTable).getByText('27 Aug 2021')).toBeInTheDocument(); + expect(within(sitStartAndEndTable).getByText('28 Aug 2021')).toBeInTheDocument(); }); it('does not render pastSitDepartureDateTable if current sit', async () => { render(