Files
Starseed/frontend/modules/transport/utils/forms/carrierPrice.ts
T
tristan d71153e628
Pull Request — Quality gate / Backend (PHP CS + PHPUnit) (pull_request) Successful in 3m9s
Pull Request — Quality gate / Frontend (lint + Vitest + build) (pull_request) Successful in 1m33s
feat(transport) : onglet prix transporteur (ERP-169)
2026-06-17 10:05:27 +02:00

78 lines
3.2 KiB
TypeScript

/**
* Helpers purs de l'onglet Prix transporteur (M4 Transport, ERP-169 — RG-4.09→4.11).
* Une ligne porte une branche CLIENT ou FOURNISSEUR selon `direction` ; les champs
* de la branche INACTIVE doivent toujours partir à null (CHECK BDD
* chk_carrier_price_client_branch / supplier_branch). Testables sans Vue ni API.
*/
import type { CarrierPriceFormDraft } from '~/modules/transport/types/carrierForm'
/** Vrai si une chaîne porte au moins un caractère non-espace. */
function isFilled(value: string | null | undefined): boolean {
return value !== null && value !== undefined && value.trim() !== ''
}
/**
* Payload de la sous-ressource prix (groupe `carrier:write:prices`). Envoie les
* communs + UNIQUEMENT la branche active (l'autre branche à null, exigée par les
* CHECK BDD). Les relations partent en IRI (string|null). Le back re-valide
* l'obligation conditionnelle + l'appartenance de l'adresse (422 inline).
*/
export function buildCarrierPricePayload(price: CarrierPriceFormDraft): Record<string, unknown> {
const common: Record<string, unknown> = {
direction: price.direction,
containerType: price.containerType || null,
pricingUnit: price.pricingUnit || null,
price: price.price || null,
priceState: price.priceState || null,
}
if (price.direction === 'CLIENT') {
return {
...common,
client: price.clientIri || null,
clientDeliveryAddress: price.clientDeliveryAddressIri || null,
departureSite: price.departureSiteIri || null,
// Branche FOURNISSEUR forcée à null (CHECK chk_carrier_price_client_branch).
supplier: null,
supplierSupplyAddress: null,
deliverySite: null,
}
}
if (price.direction === 'FOURNISSEUR') {
return {
...common,
supplier: price.supplierIri || null,
supplierSupplyAddress: price.supplierSupplyAddressIri || null,
deliverySite: price.deliverySiteIri || null,
// Branche CLIENT forcée à null (CHECK chk_carrier_price_supplier_branch).
client: null,
clientDeliveryAddress: null,
departureSite: null,
}
}
// Direction non choisie : on envoie les communs ; le back 422 sur `direction`.
return common
}
/**
* Pré-check léger du gating « + Nouveau prix » : direction choisie, prix rempli, et
* branche active complète (client/adresse/site OU fournisseur/adresse/site). Le back
* reste la couche autoritaire (RG-4.09→4.11) ; ce pré-check évite d'empiler des
* blocs vides.
*/
export function isCarrierPriceValid(price: CarrierPriceFormDraft): boolean {
if (!isFilled(price.price) || !isFilled(price.containerType) || !isFilled(price.pricingUnit) || !isFilled(price.priceState)) {
return false
}
if (price.direction === 'CLIENT') {
return isFilled(price.clientIri) && isFilled(price.clientDeliveryAddressIri) && isFilled(price.departureSiteIri)
}
if (price.direction === 'FOURNISSEUR') {
return isFilled(price.supplierIri) && isFilled(price.supplierSupplyAddressIri) && isFilled(price.deliverySiteIri)
}
return false
}