From 9e80db22af3ef444bf85c7f09aef4979b82a2f8d Mon Sep 17 00:00:00 2001 From: Daniel Jordan Date: Wed, 15 Jan 2025 21:43:45 +0000 Subject: [PATCH] changin proc to return a table, working on closeout --- ...52_add_ppm_estimated_incentive_proc.up.sql | 46 ++++++++----------- .../internal/payloads/model_to_payload.go | 2 +- pkg/models/ppm_shipment.go | 25 +++++++--- pkg/services/ppm_closeout/ppm_closeout.go | 12 ++--- pkg/services/ppmshipment/ppm_estimator.go | 2 +- 5 files changed, 45 insertions(+), 42 deletions(-) diff --git a/migrations/app/schema/20250114164752_add_ppm_estimated_incentive_proc.up.sql b/migrations/app/schema/20250114164752_add_ppm_estimated_incentive_proc.up.sql index ce8be73a674..47436e133a9 100644 --- a/migrations/app/schema/20250114164752_add_ppm_estimated_incentive_proc.up.sql +++ b/migrations/app/schema/20250114164752_add_ppm_estimated_incentive_proc.up.sql @@ -1,5 +1,3 @@ --- function that calculates a ppm incentive given mileage, weight, and dates --- this is used to calculate estimated, max, and actual incentives CREATE OR REPLACE FUNCTION calculate_ppm_incentive( ppm_id UUID, pickup_address_id UUID, @@ -10,16 +8,16 @@ CREATE OR REPLACE FUNCTION calculate_ppm_incentive( is_estimated BOOLEAN, is_actual BOOLEAN, is_max BOOLEAN -) RETURNS NUMERIC AS +) RETURNS TABLE ( + total_incentive NUMERIC, + price_islh NUMERIC, + price_ihpk NUMERIC, + price_ihupk NUMERIC, + price_fsc NUMERIC +) AS $$ DECLARE ppm RECORD; - escalated_price NUMERIC; - estimated_price_islh NUMERIC; - estimated_price_ihpk NUMERIC; - estimated_price_ihupk NUMERIC; - estimated_price_fsc NUMERIC; - total_incentive NUMERIC := 0; contract_id UUID; o_rate_area_id UUID; d_rate_area_id UUID; @@ -34,12 +32,8 @@ BEGIN RAISE EXCEPTION 'is_estimated, is_actual, and is_max cannot all be FALSE. No update will be performed.'; END IF; - -- validating it's a real PPM - SELECT ppms.id - INTO ppm - FROM ppm_shipments ppms - WHERE ppms.id = ppm_id; - + -- Validating it's a real PPM + SELECT ppms.id INTO ppm FROM ppm_shipments ppms WHERE ppms.id = ppm_id; IF ppm IS NULL THEN RAISE EXCEPTION 'PPM with ID % not found', ppm_id; END IF; @@ -61,7 +55,7 @@ BEGIN -- ISLH calculation SELECT rs.id INTO service_id FROM re_services rs WHERE rs.code = 'ISLH'; - estimated_price_islh := ROUND( + price_islh := ROUND( calculate_escalated_price( o_rate_area_id, d_rate_area_id, @@ -71,11 +65,10 @@ BEGIN move_date ) * (weight / 100)::NUMERIC * 100, 0 ); - RAISE NOTICE 'Estimated price for ISLH: % cents', estimated_price_islh; -- IHPK calculation SELECT rs.id INTO service_id FROM re_services rs WHERE rs.code = 'IHPK'; - estimated_price_ihpk := ROUND( + price_ihpk := ROUND( calculate_escalated_price( o_rate_area_id, NULL, @@ -85,11 +78,10 @@ BEGIN move_date ) * (weight / 100)::NUMERIC * 100, 0 ); - RAISE NOTICE 'Estimated price for IHPK: % cents', estimated_price_ihpk; -- IHUPK calculation SELECT rs.id INTO service_id FROM re_services rs WHERE rs.code = 'IHUPK'; - estimated_price_ihupk := ROUND( + price_ihupk := ROUND( calculate_escalated_price( NULL, d_rate_area_id, @@ -99,27 +91,25 @@ BEGIN move_date ) * (weight / 100)::NUMERIC * 100, 0 ); - RAISE NOTICE 'Estimated price for IHUPK: % cents', estimated_price_ihupk; -- FSC calculation estimated_fsc_multiplier := get_fsc_multiplier(weight); fuel_price := get_fuel_price(move_date); price_difference := calculate_price_difference(fuel_price); cents_above_baseline := mileage * estimated_fsc_multiplier; - estimated_price_fsc := ROUND((cents_above_baseline * price_difference) * 100); - RAISE NOTICE 'Estimated price for FSC: % cents', estimated_price_fsc; + price_fsc := ROUND((cents_above_baseline * price_difference) * 100); - -- total - total_incentive := estimated_price_islh + estimated_price_ihpk + estimated_price_ihupk + estimated_price_fsc; - RAISE NOTICE 'Total PPM Incentive: % cents', total_incentive; + -- Total incentive + total_incentive := price_islh + price_ihpk + price_ihupk + price_fsc; - -- now update the incentive value + -- Update the PPM incentive values UPDATE ppm_shipments SET estimated_incentive = CASE WHEN is_estimated THEN total_incentive ELSE estimated_incentive END, final_incentive = CASE WHEN is_actual THEN total_incentive ELSE final_incentive END, max_incentive = CASE WHEN is_max THEN total_incentive ELSE max_incentive END WHERE id = ppm_id; - RETURN total_incentive; + -- Return all values + RETURN QUERY SELECT total_incentive, price_islh, price_ihpk, price_ihupk, price_fsc; END; $$ LANGUAGE plpgsql; diff --git a/pkg/handlers/ghcapi/internal/payloads/model_to_payload.go b/pkg/handlers/ghcapi/internal/payloads/model_to_payload.go index 08879e080a0..89a6290a7ff 100644 --- a/pkg/handlers/ghcapi/internal/payloads/model_to_payload.go +++ b/pkg/handlers/ghcapi/internal/payloads/model_to_payload.go @@ -1306,7 +1306,7 @@ func PPMCloseout(ppmCloseout *models.PPMCloseout) *ghcmessages.PPMCloseout { Gcc: handlers.FmtCost(ppmCloseout.GCC), Aoa: handlers.FmtCost(ppmCloseout.AOA), RemainingIncentive: handlers.FmtCost(ppmCloseout.RemainingIncentive), - HaulType: (*string)(&ppmCloseout.HaulType), + HaulType: (*string)(ppmCloseout.HaulType), HaulPrice: handlers.FmtCost(ppmCloseout.HaulPrice), HaulFSC: handlers.FmtCost(ppmCloseout.HaulFSC), Dop: handlers.FmtCost(ppmCloseout.DOP), diff --git a/pkg/models/ppm_shipment.go b/pkg/models/ppm_shipment.go index fab8720e125..7989b973119 100644 --- a/pkg/models/ppm_shipment.go +++ b/pkg/models/ppm_shipment.go @@ -35,11 +35,15 @@ type PPMCloseout struct { RemainingIncentive *unit.Cents HaulPrice *unit.Cents HaulFSC *unit.Cents - HaulType HaulType + HaulType *HaulType DOP *unit.Cents DDP *unit.Cents PackPrice *unit.Cents UnpackPrice *unit.Cents + IHPKPrice *unit.Cents + IHUPKPrice *unit.Cents + ISLHPrice *unit.Cents + FSCPrice *unit.Cents SITReimbursement *unit.Cents } @@ -321,16 +325,25 @@ func FetchPPMShipmentByPPMShipmentID(db *pop.Connection, ppmShipmentID uuid.UUID return &ppmShipment, nil } +type PPMIncentive struct { + TotalIncentive int `db:"total_incentive"` + PriceISLH int `db:"price_islh"` + PriceIHPK int `db:"price_ihpk"` + PriceIHUPK int `db:"price_ihupk"` + PriceFSC int `db:"price_fsc"` +} + // a db stored proc that will handle updating the estimated_incentive value // this simulates pricing of a basic iHHG shipment with ISLH, IHPK, IHUPK, and the CONUS portion for a FSC -func CalculatePPMIncentive(db *pop.Connection, ppmID uuid.UUID, pickupAddressID uuid.UUID, destAddressID uuid.UUID, moveDate time.Time, mileage int, weight int, isEstimated bool, isActual bool, isMax bool) (int, error) { - var incentive int +func CalculatePPMIncentive(db *pop.Connection, ppmID uuid.UUID, pickupAddressID uuid.UUID, destAddressID uuid.UUID, moveDate time.Time, mileage int, weight int, isEstimated bool, isActual bool, isMax bool) (*PPMIncentive, error) { + var incentive PPMIncentive - err := db.RawQuery("SELECT calculate_ppm_incentive($1, $2, $3, $4, $5, $6, $7, $8, $9)", ppmID, pickupAddressID, destAddressID, moveDate, mileage, weight, isEstimated, isActual, isMax). + // Run the stored procedure and scan the results into the struct + err := db.RawQuery("SELECT * FROM calculate_ppm_incentive($1, $2, $3, $4, $5, $6, $7, $8, $9)", ppmID, pickupAddressID, destAddressID, moveDate, mileage, weight, isEstimated, isActual, isMax). First(&incentive) if err != nil { - return 0, fmt.Errorf("error calculating PPM incentive for PPM ID %s: %w", ppmID, err) + return nil, fmt.Errorf("error calculating PPM incentive for PPM ID %s: %w", ppmID, err) } - return incentive, nil + return &incentive, nil } diff --git a/pkg/services/ppm_closeout/ppm_closeout.go b/pkg/services/ppm_closeout/ppm_closeout.go index 925385d079b..9deab808a96 100644 --- a/pkg/services/ppm_closeout/ppm_closeout.go +++ b/pkg/services/ppm_closeout/ppm_closeout.go @@ -60,11 +60,6 @@ func (p *ppmCloseoutFetcher) GetPPMCloseout(appCtx appcontext.AppContext, ppmShi proGearWeightCustomer, proGearWeightSpouse := p.GetProGearWeights(*ppmShipment) - serviceItems, err := p.getServiceItemPrices(appCtx, *ppmShipment) - if err != nil { - return nil, err - } - var remainingIncentive unit.Cents // Most moves generated by `make db_dev_e2e_populate` skip the part that generates the FinalIncentive for the move, so just return 0. // Moves created through the UI shouldn't be able to skip this part @@ -96,6 +91,11 @@ func (p *ppmCloseoutFetcher) GetPPMCloseout(appCtx appcontext.AppContext, ppmShi fullWeightGCCShipment.ProGearWeight = &proGearCustomerMax fullWeightGCCShipment.SpouseProGearWeight = &proGearSpouseMax gcc, _ := p.calculateGCC(appCtx, *fullWeightGCCShipment, fullAllowableWeight) + + serviceItems, err := p.getServiceItemPrices(appCtx, *ppmShipment) + if err != nil { + return nil, err + } if serviceItems.storageReimbursementCosts != nil { gcc = gcc.AddCents(*serviceItems.storageReimbursementCosts) } @@ -114,7 +114,7 @@ func (p *ppmCloseoutFetcher) GetPPMCloseout(appCtx appcontext.AppContext, ppmShi ppmCloseoutObj.RemainingIncentive = &remainingIncentive ppmCloseoutObj.HaulPrice = serviceItems.haulPrice ppmCloseoutObj.HaulFSC = serviceItems.haulFSC - ppmCloseoutObj.HaulType = serviceItems.haulType + ppmCloseoutObj.HaulType = &serviceItems.haulType ppmCloseoutObj.DOP = serviceItems.dop ppmCloseoutObj.DDP = serviceItems.ddp ppmCloseoutObj.PackPrice = serviceItems.packPrice diff --git a/pkg/services/ppmshipment/ppm_estimator.go b/pkg/services/ppmshipment/ppm_estimator.go index 971527632fc..81c76f99734 100644 --- a/pkg/services/ppmshipment/ppm_estimator.go +++ b/pkg/services/ppmshipment/ppm_estimator.go @@ -780,7 +780,7 @@ func (f *estimatePPM) calculateOCONUSIncentive(appCtx appcontext.AppContext, ppm return nil, fmt.Errorf("failed to calculate PPM incentive: %w", err) } - return (*unit.Cents)(&incentive), nil + return (*unit.Cents)(&incentive.TotalIncentive), nil } func CalculateSITCost(appCtx appcontext.AppContext, ppmShipment *models.PPMShipment, contract models.ReContract) (*unit.Cents, error) {