# Spec Delta ## Purpose Enable a contract product line to carry multiple package specifications that share one quantity pool, while transport-plan arrange checks and contract detail arranged-qty displays consume and present that pool correctly (with per-package consumption breakdown). ## ADDED Requirements ### Requirement: Contract product line supports multiple package specs with one quantity The system SHALL allow each contract product line to store one or more package specifications and exactly one line quantity. The line quantity SHALL be the shared quota for all package specifications on that line. The system SHALL still allow the same product to appear on multiple lines. Within one contract, for the same `productId`, each distinct package specification MUST appear on at most one line (no duplicate package specs across lines for that product). Each line MUST have at least one package specification. #### Scenario: Multi-package shared pool on one line - **WHEN** a user saves a contract product line with package specs `25kg/桶` and `槽罐车` and quantity `715` - **THEN** the system persists both package specs on that single line with quantity `715` as the shared pool #### Scenario: Reject duplicate package spec for same product across lines - **WHEN** a user attempts to save two lines for the same product where both include package spec `槽罐车` - **THEN** the system rejects the save with a clear validation error and does not persist the change #### Scenario: Same product separate pools via separate lines - **WHEN** a user saves line A with only `25kg/桶` quantity `15` and line B with only `槽罐车` quantity `700` for the same product - **THEN** the system persists two lines with independent quantities (legacy split-quota behavior remains valid) ### Requirement: Transport plan consumes shared package pool by line When a transport plan is bound to a contract, arranging a stop product with a given package specification SHALL locate the unique contract product line whose package-spec set contains that specification (for the same product). Available quantity and arrange hard-checks SHALL use that line's quantity minus the sum of arranged quantities for **all** package specifications belonging to that line (across counted plans), not a per-package independent quota. Plan stop products SHALL continue to carry exactly one package specification per plan line. #### Scenario: Shared remaining after mixed package arrange - **WHEN** a contract line has packages `[25kg/桶, 槽罐车]` and quantity `715`, and counted plans have arranged `10` for `25kg/桶` and `10` for `槽罐车` - **THEN** querying arrange-qty for either package returns remaining `695` (same pool), and arranging additional quantity that would exceed `695` is rejected at arrange time #### Scenario: Split-quota lines remain independent - **WHEN** the same product has two lines with single packages `25kg/桶`/`15` and `槽罐车`/`700` - **THEN** arranging against `槽罐车` does not reduce the available quantity of the `25kg/桶` line #### Scenario: Package must belong to contract line set - **WHEN** a plan stop product uses a package specification not present on any contract line for that product - **THEN** the system rejects save/arrange package validation with an explicit error ### Requirement: Contract detail shows per-package arranged breakdown and line-level remaining Contract detail (and equivalent product tables that show plan qty columns) SHALL display arranged / archived quantities **broken down by package specification** under each multi-package line, and SHALL show contract quantity and remaining only at the **line aggregate** level. Remaining MUST equal line quantity minus the sum of arranged totals across that line's packages. The system MUST NOT present an independent "remaining" per package that implies a separate quota. #### Scenario: Detail breakdown for shared pool line - **WHEN** a user opens contract detail for a line with packages `[25kg/桶, 槽罐车]`, quantity `715`, arranged `10` + `10` - **THEN** the UI shows per-package arranged (and archived / unarchived-arranged as applicable) for each package, and a line total arranged `20` with remaining `695` (or equivalent line-level remaining presentation) ### Requirement: Contract print and PDF include multi-package lines Contract print / PDF generation SHALL render each product line's package specifications (all values on the line) and SHALL aggregate contract-level `{{packageSpecs}}` from the union of all line package specs (deduplicated), without treating a multi-package line as a single opaque string that breaks dedupe. #### Scenario: Print table cell lists multiple packages - **WHEN** a user prints a contract containing a line with packages `25kg/桶` and `槽罐车` - **THEN** the product table package column (or equivalent) shows both package specs for that line ### Requirement: API exposes packageSpecs list with backward-compatible read Contract product create/update/detail APIs SHALL accept and return `packageSpecs` as a non-empty string array. For backward compatibility, responses MAY also include scalar `packageSpec` equal to the first package in the list (or the sole value). Legacy stored single scalar values MUST be readable as a one-element `packageSpecs` list. #### Scenario: Legacy single value round-trip - **WHEN** the system reads an existing contract product row that stores a single legacy package_spec string (not a multi-value encoding) - **THEN** API `packageSpecs` is a one-element array containing that value and clients can edit/save without data loss