Commit Graph

27 Commits

Author SHA1 Message Date
Fabian @ Blax Software 2c31a23255 feat(pricing): percentage conditional prices + cheapest-effective resolver + authoring helper
ProductPrice gains meta.percent_off support: percentOff()/isPercentage() and
effectiveAmount($base) — a percentage price resolves against a base (the
product's cheapest standalone price), so it can express e.g. '90% off with
Full Seat' rather than a fixed amount. Product::resolvePriceFor now ranks the
eligible prices by EFFECTIVE amount (percentage-aware) and returns the cheapest,
so a product linked to multiple prerequisites with different fixed/percentage
discounts always resolves to the cheapest the buyer qualifies for. Adds
ProductPrice::setConditionalPricing($requires, $percentOff, $label) — a
merge-safe authoring seam host admin UIs can call instead of hand-poking meta.
2026-08-26 15:52:24 +02:00
Fabian @ Blax Software 07a794c028 feat(pricing): conditional prices via meta.requires + entitlement-checker resolver
Add a generic conditional-pricing mechanic: a ProductPrice may carry
meta.requires (e.g. {"role":"seat"}) so it only applies to buyers who
already hold a prerequisite (loyalty / bundle pricing). Product::resolvePriceFor
returns the cheapest price the buyer is eligible for, delegating the
'does the buyer satisfy this requirement' test to a host-bound
EntitlementChecker contract. Defaults to DenyAllEntitlementChecker so an
unconfigured host never leaks a discount. Adds requires()/isConditional()/
requiresLabel()/requiresSatisfiedBy() and conditional()/standalone() scopes.
2026-08-26 12:35:14 +02:00
Fabian @ Blax Software f10d5c2f04 feat(tax): configurable TaxService applied across every checkout path
Blax\Shop\Services\TaxService::rates($exempt, $rates=null) is one source of
truth that turns "which rate(s)" (config shop.tax.rates or an explicit list)
and "is this customer exempt" into the array Stripe expects. It fails loud
(TaxRateNotConfiguredException) when shop.tax.require is set and no rate is
configured for a non-exempt charge, instead of silently billing 0% VAT.

New config('shop.tax') block (SHOP_TAX_RATES / SHOP_TAX_REQUIRE). Unit tested.

Consumers (learn-atc #1509) delegate getApplicableTaxRates() here so no path
can apply the rate twice (Stripe rejects duplicate tax rates) or drop VAT to 0%.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-21 08:23:56 +02:00
Fabian @ Blax Software 30dc3755d2 test: pin clock in loan-vocabulary test; docs: bump suite counts to 1400/3755
PurchaseResourceTest::it_translates_e_commerce_columns_into_loan_vocabulary
relied on the real wall clock falling inside the fixture's loan window
(2026-05-14..2026-05-28); once that window passed, the loan resolved to
`overdue` and the test failed. Freeze the clock inside the window like its
sibling tests already do.

Update the README test/assertion badges and the Testing section to the current
suite size (1400 tests, 3755 assertions) after the subscription-checkout tests.
2026-06-02 09:48:26 +02:00
Fabian @ Blax Software 0cfbdf221d BF edgecases, R structure, A tests 2026-05-18 13:05:38 +02:00
Fabian @ Blax Software afdcd8bc75 feat: Enhance traits with strict types and improve method signatures
- Added strict types declaration to multiple traits for better type safety.
- Updated method signatures in traits to use nullable types where applicable.
- Improved documentation for traits, including host-model contracts and method descriptions.
- Added new tests to ensure correct behavior of loan checkout and stock management.
- Fixed regression in order number generation to ensure proper string formatting.
- Ensured that currency codes sent to Stripe are consistently lowercased.
2026-05-15 20:26:24 +02:00
Fabian @ Blax Software fe41475c84 I loanable product type, tiered pricing, lifecycle events, host helpers 2026-05-15 10:27:59 +02:00
Fabian @ Blax Software 440be3a36f I order notes, BF checkout currency 2026-01-25 10:40:17 +01:00
Fabian @ Blax Software 1a8f111110 I order 2026-01-05 12:29:55 +01:00
Fabian @ Blax Software a66fd7ccb8 BFI cart / orders 2026-01-05 10:30:21 +01:00
Fabian @ Blax Software 136b7ade63 A prompts, I docs/readme, BF orders, R tests locations 2025-12-30 09:29:43 +01:00
Fabian @ Blax Software 6e9c9043ae I order, A handy methods 2025-12-29 10:26:51 +01:00
Fabian @ Blax Software 9c1fcd6cfd AM orders 2025-12-29 09:59:02 +01:00
a6a2f5842 9e7812c70e BFI cart single item 2025-12-24 19:40:10 +01:00
Fabian @ Blax Software 0e6b420297 BFI pool cart 2025-12-20 12:19:34 +01:00
Fabian @ Blax Software f6c60f3d79 BFI cart conversion product purchase, R cart dates 2025-12-19 09:53:44 +01:00
Fabian @ Blax Software 7a26c9a965 I cart methods 2025-12-18 15:33:47 +01:00
Fabian @ Blax Software d13945a731 IMU cart + test 2025-12-18 12:21:29 +01:00
Fabian @ Blax Software 7360391581 BF pool priority claiming, IA date cast 2025-12-17 12:47:18 +01:00
Fabian @ Blax Software d2cf70ce44 ABFI cart, cartitems, pool/bookings, tests 2025-12-15 12:28:15 +01:00
Fabian @ Blax Software 4a303c0f3f I category methods, IRA product relations & tests 2025-12-05 09:21:07 +01:00
a6a2f5842 c5004158eb A types, enums & statuses, U product models, I shopping trait, A booking support, R tests 2025-12-03 13:59:01 +01:00
a6a2f5842 bc8158ba7b BF test 2025-11-29 08:32:58 +01:00
a6a2f5842 3593a462a1 I basic tests 2025-11-25 17:14:00 +01:00
a6a2f5842 5fb31d0c4f D basic tests 2025-11-25 17:02:39 +01:00
a6a2f5842 7c6b61da45 BFI tests 2025-11-24 14:32:11 +01:00
a6a2f5842 d610cc5717 init 2025-11-21 11:49:41 +01:00