feat(mall): claim and redeem shop coupons from the storefront

The product page loads a shop's claimable coupons through the shared client and
claims them in place; the buyer coupon list reads owned snapshots with their
claimed/redeemed/expired state. Checkout offers each shop order at most one
owned coupon and submits only the choice; the pay page and order detail render
the server-persisted discount and reduced total, never a client figure.

Coupon fixtures leave the pages; the fixed-data adapter still serves the coupon
domain as the rollback path. The demo seed creates two deterministic templates
and claims them for the demo customer.
This commit is contained in:
2026-09-18 12:12:51 +00:00
parent 23955434c6
commit 0eb94f2ba1
9 changed files with 249 additions and 16 deletions
+10
View File
@@ -118,6 +118,10 @@ onMounted(() => {
</tr>
</tbody>
</table>
<p v-if="order.discount_minor > 0" class="order-discount">
{{ t("checkout.couponDiscount") }}:
<PriceText :amount-minor="order.discount_minor" :currency="order.currency" />
</p>
<p class="order-total">{{ t("user.total") }}: <PriceText :amount-minor="order.total_minor" :currency="order.currency" /></p>
</article>
@@ -218,6 +222,12 @@ onMounted(() => {
border: 1px solid var(--mall-line);
object-fit: contain;
}
.order-discount {
margin: 16px 0 0;
text-align: right;
font-size: 13px;
color: var(--mall-red);
}
.order-total {
margin: 16px 0 0;
text-align: right;