Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

INT B-21707 #14473

Merged
merged 17 commits into from
Jan 6, 2025
Merged
Show file tree
Hide file tree
Changes from 14 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions migrations/app/migrations_manifest.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1062,6 +1062,7 @@
20241220171035_add_additional_AK_zips_to_zip3_distances.up.sql
20241220213134_add_destination_gbloc_db_function.up.sql
20241224172258_add_and_update_po_box_zip.up.sql
20241226173330_add_intl_param_values_to_service_params_table.up.sql
20241227153723_remove_empty_string_emplid_values.up.sql
20241230190638_remove_AK_zips_from_zip3.up.sql
20241230190647_add_missing_AK_zips_to_zip3_distances.up.sql

Large diffs are not rendered by default.

34 changes: 25 additions & 9 deletions pkg/factory/address_factory.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
package factory

import (
"database/sql"

"github.com/gobuffalo/pop/v6"
"github.com/gofrs/uuid"

"github.com/transcom/mymove/pkg/models"
"github.com/transcom/mymove/pkg/testdatagen"
Expand All @@ -24,15 +27,17 @@ func BuildAddress(db *pop.Connection, customs []Customization, traits []Trait) m
}

// Create default Address
beverlyHillsUsprc := uuid.FromStringOrNil("3b9f0ae6-3b2b-44a6-9fcd-8ead346648c4")
address := models.Address{
StreetAddress1: "123 Any Street",
StreetAddress2: models.StringPointer("P.O. Box 12345"),
StreetAddress3: models.StringPointer("c/o Some Person"),
City: "Beverly Hills",
State: "CA",
PostalCode: "90210",
County: models.StringPointer("LOS ANGELES"),
IsOconus: models.BoolPointer(false),
StreetAddress1: "123 Any Street",
StreetAddress2: models.StringPointer("P.O. Box 12345"),
StreetAddress3: models.StringPointer("c/o Some Person"),
City: "Beverly Hills",
State: "CA",
PostalCode: "90210",
County: models.StringPointer("LOS ANGELES"),
IsOconus: models.BoolPointer(false),
UsPostRegionCityID: &beverlyHillsUsprc,
}

// Find/create the Country if customization is provided
Expand All @@ -56,7 +61,7 @@ func BuildAddress(db *pop.Connection, customs []Customization, traits []Trait) m
// Overwrite values with those from customizations
testdatagen.MergeModels(&address, cAddress)

// This helps assign counties when the factory is called for seed data or tests
// This helps assign counties & us_post_region_cities_id values when the factory is called for seed data or tests
// Additionally, also only run if not 90210. 90210's county is by default populated
if db != nil && address.PostalCode != "90210" {
county, err := models.FindCountyByZipCode(db, address.PostalCode)
Expand All @@ -72,6 +77,17 @@ func BuildAddress(db *pop.Connection, customs []Customization, traits []Trait) m
address.County = models.StringPointer("db nil when created")
}

if db != nil && address.PostalCode != "90210" && cAddress.UsPostRegionCityID == nil {
usprc, err := models.FindByZipCode(db, address.PostalCode)
if err != nil && err != sql.ErrNoRows {
address.UsPostRegionCityID = nil
address.UsPostRegionCity = nil
} else if usprc.ID != uuid.Nil {
address.UsPostRegionCityID = &usprc.ID
address.UsPostRegionCity = usprc
}
}

// If db is false, it's a stub. No need to create in database.
if db != nil {
mustCreate(db, &address)
Expand Down
1 change: 1 addition & 0 deletions pkg/factory/address_factory_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ func (suite *FactorySuite) TestBuildAddress() {
suite.Equal(defaultPostalCode, address.PostalCode)
suite.Equal(country.ID, *address.CountryId)
suite.Equal(defaultCounty, *address.County)
suite.NotNil(*address.UsPostRegionCityID)
})

suite.Run("Successful creation of an address with customization", func() {
Expand Down
15 changes: 15 additions & 0 deletions pkg/handlers/primeapi/allowed_payment_service_item_params.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,21 @@ var (
models.ReServiceCodeDOSFSC: {
models.ServiceItemParamNameWeightBilled,
},
models.ReServiceCodeISLH: {
models.ServiceItemParamNameWeightBilled,
},
models.ReServiceCodeIHPK: {
models.ServiceItemParamNameWeightBilled,
},
models.ReServiceCodeIHUPK: {
models.ServiceItemParamNameWeightBilled,
},
models.ReServiceCodePOEFSC: {
models.ServiceItemParamNameWeightBilled,
},
models.ReServiceCodePODFSC: {
models.ServiceItemParamNameWeightBilled,
},
}
)

Expand Down
14 changes: 0 additions & 14 deletions pkg/handlers/primeapi/payment_request_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -947,13 +947,6 @@ func (suite *HandlerSuite) TestCreatePaymentRequestHandlerInvalidMTOReferenceID(
suite.IsType(&paymentrequestop.CreatePaymentRequestUnprocessableEntity{}, response)
typedResponse := response.(*paymentrequestop.CreatePaymentRequestUnprocessableEntity)

// Validate outgoing payload
// TODO: Can't validate the response because of the issue noted below. Figure out a way to
// either alter the service or relax the swagger requirements.
// suite.NoError(typedResponse.Payload.Validate(strfmt.Default))
// CreatePaymentRequestCheck is returning apperror.InvalidCreateInputError without any validation errors
// so InvalidFields won't be added to the payload.

suite.Contains(*typedResponse.Payload.Detail, "has missing ReferenceID")
})

Expand Down Expand Up @@ -1013,13 +1006,6 @@ func (suite *HandlerSuite) TestCreatePaymentRequestHandlerInvalidMTOReferenceID(
suite.IsType(&paymentrequestop.CreatePaymentRequestUnprocessableEntity{}, response)
typedResponse := response.(*paymentrequestop.CreatePaymentRequestUnprocessableEntity)

// Validate outgoing payload
// TODO: Can't validate the response because of the issue noted below. Figure out a way to
// either alter the service or relax the swagger requirements.
// suite.NoError(typedResponse.Payload.Validate(strfmt.Default))
// CreatePaymentRequestCheck is returning apperror.InvalidCreateInputError without any validation errors
// so InvalidFields won't be added to the payload.

suite.Contains(*typedResponse.Payload.Detail, "has missing ReferenceID")
})
}
14 changes: 14 additions & 0 deletions pkg/models/re_rate_area.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package models

import (
"fmt"
"time"

"github.com/gobuffalo/pop/v6"
Expand Down Expand Up @@ -53,3 +54,16 @@ func FetchReRateAreaItem(tx *pop.Connection, contractID uuid.UUID, code string)

return &area, err
}

// 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 {
var rateAreaID uuid.UUID
err := db.RawQuery("SELECT get_rate_area_id($1, $2, $3)", addressID, serviceID, contractID).First(&rateAreaID)
brianmanley-caci marked this conversation as resolved.
Show resolved Hide resolved
if err != nil {
return uuid.Nil, fmt.Errorf("error fetching rate area id for shipment ID: %s, service ID %s, and contract ID: %s: %s", addressID, serviceID, contractID, err)
}
return rateAreaID, nil
}
return uuid.Nil, fmt.Errorf("error fetching rate area ID - required parameters not provided")
}
22 changes: 22 additions & 0 deletions pkg/models/re_rate_area_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@ package models_test
import (
"github.com/gofrs/uuid"

"github.com/transcom/mymove/pkg/factory"
"github.com/transcom/mymove/pkg/models"
"github.com/transcom/mymove/pkg/testdatagen"
)

func (suite *ModelSuite) TestReRateAreaValidation() {
Expand All @@ -28,3 +30,23 @@ func (suite *ModelSuite) TestReRateAreaValidation() {
suite.verifyValidationErrors(&emptyReRateArea, expErrors)
})
}

func (suite *ModelSuite) TestFetchRateAreaID() {
suite.Run("success - fetching a rate area ID", func() {
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)
suite.NotNil(rateAreaId)
suite.NoError(err)
})

suite.Run("fail - receive error when not all values are provided", func() {
var nilUuid uuid.UUID
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)
suite.Equal(uuid.Nil, rateAreaId)
suite.Error(err)
})
}
8 changes: 8 additions & 0 deletions pkg/models/service_item_param_key.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,10 @@ const (
ServiceItemParamNameNTSPackingFactor ServiceItemParamName = "NTSPackingFactor"
// ServiceItemParamNameNumberDaysSIT is the param key name NumberDaysSIT
ServiceItemParamNameNumberDaysSIT ServiceItemParamName = "NumberDaysSIT"
// ServiceItemParamNamePerUnitCents is the param key name PerUnitCents
ServiceItemParamNamePerUnitCents ServiceItemParamName = "PerUnitCents"
// ServiceItemParamNamePortName is the param key name PortName
ServiceItemParamNamePortName ServiceItemParamName = "PortName"
// ServiceItemParamNamePriceAreaDest is the param key name PriceAreaDest
ServiceItemParamNamePriceAreaDest ServiceItemParamName = "PriceAreaDest"
// ServiceItemParamNamePriceAreaIntlDest is the param key name PriceAreaIntlDest
Expand Down Expand Up @@ -275,6 +279,8 @@ var ValidServiceItemParamNames = []ServiceItemParamName{
ServiceItemParamNameStandaloneCrateCap,
ServiceItemParamNameUncappedRequestTotal,
ServiceItemParamNameLockedPriceCents,
ServiceItemParamNamePerUnitCents,
ServiceItemParamNamePortName,
}

// ValidServiceItemParamNameStrings lists all valid service item param key names
Expand Down Expand Up @@ -349,6 +355,8 @@ var ValidServiceItemParamNameStrings = []string{
string(ServiceItemParamNameStandaloneCrateCap),
string(ServiceItemParamNameUncappedRequestTotal),
string(ServiceItemParamNameLockedPriceCents),
string(ServiceItemParamNamePerUnitCents),
string(ServiceItemParamNamePortName),
}

// ValidServiceItemParamTypes lists all valid service item param types
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
package serviceparamvaluelookups

import (
"fmt"

"github.com/transcom/mymove/pkg/appcontext"
"github.com/transcom/mymove/pkg/models"
"github.com/transcom/mymove/pkg/services/ghcrateengine"
)

// PerUnitCents does lookup on the per unit cents value associated with a service item
type PerUnitCentsLookup struct {
ServiceItem models.MTOServiceItem
MTOShipment models.MTOShipment
}

func (p PerUnitCentsLookup) lookup(appCtx appcontext.AppContext, s *ServiceItemParamKeyData) (string, error) {
serviceID := p.ServiceItem.ReServiceID
contractID := s.ContractID
if p.MTOShipment.RequestedPickupDate == nil {
return "", fmt.Errorf("requested pickup date is required for shipment with id: %s", p.MTOShipment.ID)
}

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)
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)
}
isPeakPeriod := ghcrateengine.IsPeakPeriod(*p.MTOShipment.RequestedPickupDate)
var reIntlOtherPrice models.ReIntlOtherPrice
cameroncaci marked this conversation as resolved.
Show resolved Hide resolved
err = appCtx.DB().Q().
Where("contract_id = ?", contractID).
Where("service_id = ?", serviceID).
Where("is_peak_period = ?", isPeakPeriod).
Where("rate_area_id = ?", rateAreaID).
First(&reIntlOtherPrice)
if err != nil {
return "", fmt.Errorf("error fetching IHPK per unit cents for contractID: %s, serviceID %s, isPeakPeriod: %t, and rateAreaID: %s: %s", contractID, serviceID, isPeakPeriod, rateAreaID, err)
}
return reIntlOtherPrice.PerUnitCents.ToMillicents().ToCents().String(), nil

case models.ReServiceCodeIHUPK:
// IHUPK: Need rate area ID for the destination address
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)
}
isPeakPeriod := ghcrateengine.IsPeakPeriod(*p.MTOShipment.RequestedPickupDate)
var reIntlOtherPrice models.ReIntlOtherPrice
err = appCtx.DB().Q().
Where("contract_id = ?", contractID).
Where("service_id = ?", serviceID).
Where("is_peak_period = ?", isPeakPeriod).
Where("rate_area_id = ?", rateAreaID).
First(&reIntlOtherPrice)
if err != nil {
return "", fmt.Errorf("error fetching IHUPK per unit cents for contractID: %s, serviceID %s, isPeakPeriod: %t, and rateAreaID: %s: %s", contractID, serviceID, isPeakPeriod, rateAreaID, err)
}
return reIntlOtherPrice.PerUnitCents.ToMillicents().ToCents().String(), nil

case models.ReServiceCodeISLH:
// ISLH: Need rate area IDs for origin and destination
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)
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)
}
isPeakPeriod := ghcrateengine.IsPeakPeriod(*p.MTOShipment.RequestedPickupDate)
var reIntlPrice models.ReIntlPrice
err = appCtx.DB().Q().
Where("contract_id = ?", contractID).
Where("service_id = ?", serviceID).
Where("is_peak_period = ?", isPeakPeriod).
Where("origin_rate_area_id = ?", originRateAreaID).
Where("destination_rate_area_id = ?", destRateAreaID).
First(&reIntlPrice)
if err != nil {
return "", fmt.Errorf("error fetching ISLH per unit cents for contractID: %s, serviceID %s, isPeakPeriod: %t, originRateAreaID: %s, and destRateAreaID: %s: %s", contractID, serviceID, isPeakPeriod, originRateAreaID, destRateAreaID, err)
}
return reIntlPrice.PerUnitCents.ToMillicents().ToCents().String(), nil

default:
return "", fmt.Errorf("unsupported service code to retrieve service item param PerUnitCents")
}
}
Loading
Loading