assoconnect/absolute-percent-value-bundle
Represents either an absolute value or a percent, with a type (PERCENT or ABSOLUTE) and a positive numeric string value; percent values must be under 10000.
Locking down the discount/price-modifier data contract. The package's real product value is not math — it is a shape for an ambiguous field. Today most teams model "discount" as two nullable columns (discount_percent, discount_amount) plus a type enum, which lets invalid states exist (both set, neither set, percent = 400%). AbsolutePercentValue collapses that into one non-nullable value with a type discriminator (PERCENT | ABSOLUTE) and a validity rule (percent ≤ 10000, i.e. basis-point-scaled percentages, so 1250 = 12.5%). This is a schema and API-contract decision, and it is the decision this package is actually worth evaluating for.
Promotion / coupon / price-rule roadmap scoping. If the roadmap contains tiered discounts, voucher codes, negotiated contract pricing, or "X% off, capped at $Y," this is the primitive that keeps those features from each inventing their own representation. It supports sizing the work: adopting it is roughly a day; the real effort is migrating existing rows and renegotiating API responses with consumers.
Build vs. buy. Buy is questionable here. The total surface area is one value object plus a normalizer/denormalizer for serialization (the v1.5.1 note "fix denormalize return type" is the whole feature set). A competent PHP dev reproduces this in an afternoon, and the percentage scaling rule (value/100 with a 10000 ceiling) is the only non-obvious logic. Decide this on "do we want a vendor-shaped, Symfony-coupled contract, or do we write 60 lines we fully control?"
Percentage precision / rounding policy. Storing percent as a scaled integer string (10000 = 100%) is a deliberate anti-float-precision choice. This is a product decision about how precise promotions can be (0.01% granularity) and how values are presented in the UI — worth confirming with finance/marketing before it silently becomes the platform standard.
Where monetary calculations live (server vs. client). Adopting a PHP-only value object implies all authoritative discount resolution happens server-side, with the frontend receiving computed amounts. That constrains checkout, cart-preview, and mobile-app design, and should be an explicit architectural decision, not a side effect.
Vendor concentration risk on pricing logic. Pricing is revenue-critical. A package with 1 star, 0 dependents, and releases that only bump Symfony/PHP version constraints concentrates a revenue-path dependency on a single agency's internal utility. The decision this supports is whether to accept that (probably only if you're prepared to fork — MIT permits it) or to vendor the code into your own namespace from day one.
Consider it when:
Look elsewhere when:
moneyphp/money or brick/money — and note they solve a different problem; you may end up needing both.1500 for 15%) and string-typed value are unusual; exposing them means documenting an odd convention to partners forever.Adoption criteria worth writing down before a spike: PHP 8.2+/Symfony version match confirmed; a named internal owner who will fork if upstream stalls; migration plan for existing nullable-column data; and a decision logged on the scaled-percent encoding.
For executives (the honest version): "This is a small, single-purpose library that standardizes how we represent a discount — either a fixed amount or a percentage — so the pricing, promotions, and billing code stop disagreeing about it. The value isn't the code, which is small; it's that pricing bugs caused by ambiguous data become structurally impossible, which is where discount errors actually come from. Risk is contained: MIT-licensed, so we can copy it in-house permanently if the maintainer walks away, and it is ~1 day of integration plus migration work. I'd recommend we treat it as a spec we adopt, not a vendor we depend on — fork it into our namespace, own it, and reassess in two quarters. I would not recommend it as the foundation of a broader pricing engine; it stores values, it doesn't compute them."
For engineering:
"It's an Assoconnect Symfony bundle providing one value object with a type (PERCENT|ABSOLUTE) and a positive numeric string value, plus a serializer normalizer/denormalizer. Percent values are scaled — ceiling 10000 equals 100%, so 1250 is 12.5% — which gives us exact decimal percentages without floats. What it does not give us: any calculation helpers, currency handling, negative values, or composition. Our plan should be to fork it into our own namespace (it's ~1 class + serializer glue), keep the invariant and the scaled encoding, add the calculator we actually need, and own the tests. Two things to verify in the spike: (1) Symfony/Serializer version compatibility with our current app, and (2) how legacy nullable discount_percent / discount_amount rows map into the single value — including what to do with rows where both were populated, since that's a live data-integrity question, not a code question."
How can I help you explore Laravel packages today?