Skip to content

Commit

Permalink
Merge branch 'main' into B-22227
Browse files Browse the repository at this point in the history
  • Loading branch information
r-mettler authored Feb 25, 2025
2 parents 41bea85 + 810fb35 commit 3d4bbce
Show file tree
Hide file tree
Showing 13 changed files with 629 additions and 14 deletions.
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -280,4 +280,4 @@ require (
pault.ag/go/piv v0.0.0-20190320181422-d9d61c70919c // indirect
)

replace github.com/pdfcpu/pdfcpu => github.com/transcom/pdfcpu v0.0.0-20250131173611-4b416bd62126
replace github.com/pdfcpu/pdfcpu => github.com/transcom/pdfcpu v0.0.0-20250225161110-ce2f81788248
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -633,8 +633,8 @@ github.com/tiaguinho/gosoap v1.4.4 h1:4XZlaqf/y2UAbCPFGcZS4uLKrEvnMr+5pccIyQAUVg
github.com/tiaguinho/gosoap v1.4.4/go.mod h1:4vv86Jl19UkOeoJW/aawihXYNJ/Iy2NHkhgmBUJ2Ibk=
github.com/toqueteos/webbrowser v1.2.0 h1:tVP/gpK69Fx+qMJKsLE7TD8LuGWPnEV71wBN9rrstGQ=
github.com/toqueteos/webbrowser v1.2.0/go.mod h1:XWoZq4cyp9WeUeak7w7LXRUQf1F1ATJMir8RTqb4ayM=
github.com/transcom/pdfcpu v0.0.0-20250131173611-4b416bd62126 h1:XbLtbZvPTc5bY6DuXF2ZHPLPmE3GVe3T/o8PzfmITCA=
github.com/transcom/pdfcpu v0.0.0-20250131173611-4b416bd62126/go.mod h1:8EAma3IBIS7ssMiPlcNIPWwISTuP31WToXfGvc327vI=
github.com/transcom/pdfcpu v0.0.0-20250225161110-ce2f81788248 h1:G1EenmQJPQ5EO1U2iOi3olQxpM0bW+AsPWFpJhnfL1w=
github.com/transcom/pdfcpu v0.0.0-20250225161110-ce2f81788248/go.mod h1:8EAma3IBIS7ssMiPlcNIPWwISTuP31WToXfGvc327vI=
github.com/urfave/cli v1.22.10 h1:p8Fspmz3iTctJstry1PYS3HVdllxnEzTEsgIgtxTrCk=
github.com/urfave/cli v1.22.10/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
github.com/vektra/mockery/v2 v2.45.1 h1:6HpdnKiLCjVtzlRLQPUNIM0u7yrvAoZ7VWF1TltJvTM=
Expand Down
4 changes: 2 additions & 2 deletions pkg/handlers/primeapi/mto_service_item_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1040,8 +1040,8 @@ func (suite *HandlerSuite) TestCreateMTOServiceItemOriginSITHandlerWithDOFSITWit
},
}, nil)
factory.FetchReServiceByCode(suite.DB(), models.ReServiceCodeDOFSIT)
sitEntryDate := time.Date(2024, time.February, 28, 0, 0, 0, 0, time.UTC)
sitDepartureDate := time.Date(2024, time.February, 27, 0, 0, 0, 0, time.UTC)
sitEntryDate := time.Date(2024, time.February, 27, 0, 0, 0, 0, time.UTC)
sitDepartureDate := time.Date(2024, time.February, 28, 0, 0, 0, 0, time.UTC)
sitPostalCode := "00000"

// Original customer pickup address
Expand Down
6 changes: 6 additions & 0 deletions pkg/services/mto_service_item/mto_service_item_creator.go
Original file line number Diff line number Diff line change
Expand Up @@ -910,6 +910,12 @@ func (o *mtoServiceItemCreator) validateFirstDaySITServiceItem(appCtx appcontext
return nil, err
}

//SIT Entry Date must be before SIT Departure Date
err = o.checkSITEntryDateBeforeDepartureDate(serviceItem)
if err != nil {
return nil, err
}

verrs := validate.NewErrors()

// check if the address IDs are nil
Expand Down
150 changes: 148 additions & 2 deletions pkg/services/mto_service_item/mto_service_item_creator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1261,6 +1261,97 @@ func (suite *MTOServiceItemServiceSuite) TestCreateOriginSITServiceItem() {
suite.IsType(apperror.ConflictError{}, err)
})

suite.Run("Do not create DOFSIT if departure date is after entry date", func() {
shipment := setupTestData()
originAddress := factory.BuildAddress(suite.DB(), nil, nil)
reServiceDOFSIT := factory.FetchReServiceByCode(suite.DB(), models.ReServiceCodeDOFSIT)
serviceItemDOFSIT := factory.BuildMTOServiceItem(nil, []factory.Customization{
{
Model: models.MTOServiceItem{
SITEntryDate: models.TimePointer(time.Now().AddDate(0, 0, 1)),
SITDepartureDate: models.TimePointer(time.Now()),
},
},
{
Model: reServiceDOFSIT,
LinkOnly: true,
},
{
Model: shipment,
LinkOnly: true,
},
{
Model: originAddress,
LinkOnly: true,
Type: &factory.Addresses.SITOriginHHGOriginalAddress,
},
}, nil)
builder := query.NewQueryBuilder()
moveRouter := moverouter.NewMoveRouter()
planner := &mocks.Planner{}
planner.On("ZipTransitDistance",
mock.AnythingOfType("*appcontext.appContext"),
mock.Anything,
mock.Anything,
false,
).Return(400, nil)
creator := NewMTOServiceItemCreator(planner, builder, moveRouter, ghcrateengine.NewDomesticUnpackPricer(), ghcrateengine.NewDomesticPackPricer(), ghcrateengine.NewDomesticLinehaulPricer(), ghcrateengine.NewDomesticShorthaulPricer(), ghcrateengine.NewDomesticOriginPricer(), ghcrateengine.NewDomesticDestinationPricer(), ghcrateengine.NewFuelSurchargePricer())
_, _, err := creator.CreateMTOServiceItem(suite.AppContextForTest(), &serviceItemDOFSIT)
suite.Error(err)
expectedError := fmt.Sprintf(
"the SIT Departure Date (%s) must be after the SIT Entry Date (%s)",
serviceItemDOFSIT.SITDepartureDate.Format("2006-01-02"),
serviceItemDOFSIT.SITEntryDate.Format("2006-01-02"),
)
suite.Contains(err.Error(), expectedError)
})

suite.Run("Do not create DOFSIT if departure date is the same as entry date", func() {
today := models.TimePointer(time.Now())
shipment := setupTestData()
originAddress := factory.BuildAddress(suite.DB(), nil, nil)
reServiceDOFSIT := factory.FetchReServiceByCode(suite.DB(), models.ReServiceCodeDOFSIT)
serviceItemDOFSIT := factory.BuildMTOServiceItem(nil, []factory.Customization{
{
Model: models.MTOServiceItem{
SITEntryDate: today,
SITDepartureDate: today,
},
},
{
Model: reServiceDOFSIT,
LinkOnly: true,
},
{
Model: shipment,
LinkOnly: true,
},
{
Model: originAddress,
LinkOnly: true,
Type: &factory.Addresses.SITOriginHHGOriginalAddress,
},
}, nil)
builder := query.NewQueryBuilder()
moveRouter := moverouter.NewMoveRouter()
planner := &mocks.Planner{}
planner.On("ZipTransitDistance",
mock.AnythingOfType("*appcontext.appContext"),
mock.Anything,
mock.Anything,
false,
).Return(400, nil)
creator := NewMTOServiceItemCreator(planner, builder, moveRouter, ghcrateengine.NewDomesticUnpackPricer(), ghcrateengine.NewDomesticPackPricer(), ghcrateengine.NewDomesticLinehaulPricer(), ghcrateengine.NewDomesticShorthaulPricer(), ghcrateengine.NewDomesticOriginPricer(), ghcrateengine.NewDomesticDestinationPricer(), ghcrateengine.NewFuelSurchargePricer())
_, _, err := creator.CreateMTOServiceItem(suite.AppContextForTest(), &serviceItemDOFSIT)
suite.Error(err)
expectedError := fmt.Sprintf(
"the SIT Departure Date (%s) must be after the SIT Entry Date (%s)",
serviceItemDOFSIT.SITDepartureDate.Format("2006-01-02"),
serviceItemDOFSIT.SITEntryDate.Format("2006-01-02"),
)
suite.Contains(err.Error(), expectedError)
})

suite.Run("Do not create standalone DOPSIT service item", func() {
// TESTCASE SCENARIO
// Under test: CreateMTOServiceItem function
Expand Down Expand Up @@ -1686,6 +1777,63 @@ func (suite *MTOServiceItemServiceSuite) TestCreateDestSITServiceItem() {
suite.Contains(err.Error(), expectedError)
})

suite.Run("Do not create DDFSIT if departure date is after entry date", func() {
shipment, creator, reServiceDDFSIT := setupTestData()
serviceItemDDFSIT := factory.BuildMTOServiceItem(nil, []factory.Customization{
{
Model: models.MTOServiceItem{
SITEntryDate: models.TimePointer(time.Now().AddDate(0, 0, 1)),
SITDepartureDate: models.TimePointer(time.Now()),
},
},
{
Model: reServiceDDFSIT,
LinkOnly: true,
},
{
Model: shipment,
LinkOnly: true,
},
}, nil)
_, _, err := creator.CreateMTOServiceItem(suite.AppContextForTest(), &serviceItemDDFSIT)
suite.Error(err)
expectedError := fmt.Sprintf(
"the SIT Departure Date (%s) must be after the SIT Entry Date (%s)",
serviceItemDDFSIT.SITDepartureDate.Format("2006-01-02"),
serviceItemDDFSIT.SITEntryDate.Format("2006-01-02"),
)
suite.Contains(err.Error(), expectedError)
})

suite.Run("Do not create DDFSIT if departure date is the same as entry date", func() {
today := models.TimePointer(time.Now())
shipment, creator, reServiceDDFSIT := setupTestData()
serviceItemDDFSIT := factory.BuildMTOServiceItem(nil, []factory.Customization{
{
Model: models.MTOServiceItem{
SITEntryDate: today,
SITDepartureDate: today,
},
},
{
Model: reServiceDDFSIT,
LinkOnly: true,
},
{
Model: shipment,
LinkOnly: true,
},
}, nil)
_, _, err := creator.CreateMTOServiceItem(suite.AppContextForTest(), &serviceItemDDFSIT)
suite.Error(err)
expectedError := fmt.Sprintf(
"the SIT Departure Date (%s) must be after the SIT Entry Date (%s)",
serviceItemDDFSIT.SITDepartureDate.Format("2006-01-02"),
serviceItemDDFSIT.SITEntryDate.Format("2006-01-02"),
)
suite.Contains(err.Error(), expectedError)
})

// Successful creation of DDASIT service item
suite.Run("Success - DDASIT creation approved", func() {
shipment, creator, reServiceDDFSIT := setupTestData()
Expand Down Expand Up @@ -2103,7 +2251,6 @@ func (suite *MTOServiceItemServiceSuite) TestPriceEstimator() {
mock.Anything,
mock.Anything,
false,
false,
).Return(400, nil)
creator := NewMTOServiceItemCreator(planner, builder, moveRouter, ghcrateengine.NewDomesticUnpackPricer(), ghcrateengine.NewDomesticPackPricer(), ghcrateengine.NewDomesticLinehaulPricer(), ghcrateengine.NewDomesticShorthaulPricer(), ghcrateengine.NewDomesticOriginPricer(), ghcrateengine.NewDomesticDestinationPricer(), ghcrateengine.NewFuelSurchargePricer())

Expand Down Expand Up @@ -2403,7 +2550,6 @@ func (suite *MTOServiceItemServiceSuite) TestPriceEstimator() {
mock.Anything,
mock.Anything,
false,
false,
).Return(800, nil)
creator := NewMTOServiceItemCreator(planner, builder, moveRouter, ghcrateengine.NewDomesticUnpackPricer(), ghcrateengine.NewDomesticPackPricer(), ghcrateengine.NewDomesticLinehaulPricer(), ghcrateengine.NewDomesticShorthaulPricer(), ghcrateengine.NewDomesticOriginPricer(), ghcrateengine.NewDomesticDestinationPricer(), ghcrateengine.NewFuelSurchargePricer())

Expand Down
13 changes: 13 additions & 0 deletions pkg/services/mto_service_item/mto_service_item_validators.go
Original file line number Diff line number Diff line change
Expand Up @@ -830,3 +830,16 @@ func (o *mtoServiceItemCreator) checkSITEntryDateAndFADD(serviceItem *models.MTO

return nil
}

func (o *mtoServiceItemCreator) checkSITEntryDateBeforeDepartureDate(serviceItem *models.MTOServiceItem) error {
if serviceItem.SITEntryDate == nil || serviceItem.SITDepartureDate == nil {
return nil
}

//Departure Date has to be after the Entry Date
if !serviceItem.SITDepartureDate.After(*serviceItem.SITEntryDate) {
return apperror.NewUnprocessableEntityError(fmt.Sprintf("the SIT Departure Date (%s) must be after the SIT Entry Date (%s)",
serviceItem.SITDepartureDate.Format("2006-01-02"), serviceItem.SITEntryDate.Format("2006-01-02")))
}
return nil
}
Original file line number Diff line number Diff line change
Expand Up @@ -833,7 +833,8 @@ func (suite *MTOServiceItemServiceSuite) TestUpdateMTOServiceItemData() {
},
}, nil)
newSITServiceItem := oldSITServiceItem
newSITServiceItem.SITDepartureDate = &later
newSITDepartureDate := later.AddDate(0, 0, 1)
newSITServiceItem.SITDepartureDate = &newSITDepartureDate
serviceItemData := updateMTOServiceItemData{
updatedServiceItem: newSITServiceItem,
oldServiceItem: oldSITServiceItem,
Expand Down Expand Up @@ -1444,4 +1445,49 @@ func (suite *MTOServiceItemServiceSuite) TestCreateMTOServiceItemValidators() {
)
suite.Contains(err.Error(), expectedError)
})

suite.Run("checkSITEntryDateBeforeDepartureDate - success when the SIT entry date is before the SIT departure date", func() {
s := mtoServiceItemCreator{}
serviceItem := setupTestData()
//Set SIT entry date = today, SIT departure date = tomorrow
serviceItem.SITEntryDate = models.TimePointer(time.Now())
serviceItem.SITDepartureDate = models.TimePointer(time.Now().AddDate(0, 0, 1))
err := s.checkSITEntryDateBeforeDepartureDate(&serviceItem)
suite.NoError(err)
})

suite.Run("checkSITEntryDateBeforeDepartureDate - error when the SIT entry date is after the SIT departure date", func() {
s := mtoServiceItemCreator{}
serviceItem := setupTestData()
//Set SIT entry date = tomorrow, SIT departure date = today
serviceItem.SITEntryDate = models.TimePointer(time.Now().AddDate(0, 0, 1))
serviceItem.SITDepartureDate = models.TimePointer(time.Now())
err := s.checkSITEntryDateBeforeDepartureDate(&serviceItem)
suite.Error(err)
suite.IsType(apperror.UnprocessableEntityError{}, err)
expectedError := fmt.Sprintf(
"the SIT Departure Date (%s) must be after the SIT Entry Date (%s)",
serviceItem.SITDepartureDate.Format("2006-01-02"),
serviceItem.SITEntryDate.Format("2006-01-02"),
)
suite.Contains(err.Error(), expectedError)
})

suite.Run("checkSITEntryDateBeforeDepartureDate - error when the SIT entry date is the same as the SIT departure date", func() {
s := mtoServiceItemCreator{}
serviceItem := setupTestData()
//Set SIT entry date = today, SIT departure date = today
today := models.TimePointer(time.Now())
serviceItem.SITEntryDate = today
serviceItem.SITDepartureDate = today
err := s.checkSITEntryDateBeforeDepartureDate(&serviceItem)
suite.Error(err)
suite.IsType(apperror.UnprocessableEntityError{}, err)
expectedError := fmt.Sprintf(
"the SIT Departure Date (%s) must be after the SIT Entry Date (%s)",
serviceItem.SITDepartureDate.Format("2006-01-02"),
serviceItem.SITEntryDate.Format("2006-01-02"),
)
suite.Contains(err.Error(), expectedError)
})
}
15 changes: 11 additions & 4 deletions pkg/services/sit_entry_date_update/sit_entry_date_updater.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package sitentrydateupdate

import (
"database/sql"
"fmt"
"time"

"github.com/transcom/mymove/pkg/appcontext"
Expand Down Expand Up @@ -85,12 +86,18 @@ func (p sitEntryDateUpdater) UpdateSitEntryDate(appCtx appcontext.AppContext, s
// updating sister service item to have the next day for SIT entry date
if s.SITEntryDate == nil {
return nil, apperror.NewUnprocessableEntityError("You must provide the SIT entry date in the request")
} else if s.SITEntryDate != nil {
serviceItem.SITEntryDate = s.SITEntryDate
dayAfter := s.SITEntryDate.Add(24 * time.Hour)
serviceItemAdditionalDays.SITEntryDate = &dayAfter
}

// The new SIT entry date must be before SIT departure date
if serviceItem.SITDepartureDate != nil && !s.SITEntryDate.Before(*serviceItem.SITDepartureDate) {
return nil, apperror.NewUnprocessableEntityError(fmt.Sprintf("the SIT Entry Date (%s) must be before the SIT Departure Date (%s)",
s.SITEntryDate.Format("2006-01-02"), serviceItem.SITDepartureDate.Format("2006-01-02")))
}

serviceItem.SITEntryDate = s.SITEntryDate
dayAfter := s.SITEntryDate.Add(24 * time.Hour)
serviceItemAdditionalDays.SITEntryDate = &dayAfter

// Make the update to both service items and create a InvalidInputError if there were validation issues
transactionError := appCtx.NewTransaction(func(txnCtx appcontext.AppContext) error {

Expand Down
Loading

0 comments on commit 3d4bbce

Please sign in to comment.