This feature is the implementation of discount coupons that can be applied to a cart generating a global discount over the whole cart.
Besides the standard entity properties (id, createdAt, updatedAt, companyId), the Coupon entity properties are:
code): [string, required] The code to be entered to apply the coupon. It is a secret value that only the owner should have.expiresAt): [datetime, required] The expiration date and time that gives the window of time where the coupon is valid.title): [string] The text to show in UIs that represents the coupon.appliedAt): [datetime] Date and time when the code was applied. If not present or empty, it means the coupon has not been used.appliedBy): [object]: Object containing the user type and id of the user that applied the coupon to the cart (she/he could be an operator adding a coupon for a customer, a customer or a guest).cartId): [string]: Identifier of the cart where the coupon was applied. If not present or empty, it means that the coupon has not been applied.amount): [number, required]: The amount of the maximum discount applied when using the coupon.currencyCode): [string, required]: The currency that corresponds to the amount of the coupon. It restricts the coupon to be applied only to carts with that currency.The Cartentity is updated adding the property:
coupons): [object[]] An array of basic coupons information of the coupons applied to the cart. If not present of empty it means that the cart has no applied coupons.Services to manage and use coupons.
POST /coupons (availability: operator)PATCH /coupons/{id} (availability: operator)DELETE /coupons/{id} (availability: operator)GET /coupons (availability: operator)GET /coupons/count (availability: operator)GET /coupons/{id} (availability: operator)POST /carts/{id}/apply-coupon/{couponCode} (availability: guest, customer, operator)DELETE /carts/{id}/coupons/{couponId} (availability: guest, customer, operator)A new menú "Coupons" in the Admin would be available under "Pricing".
The Coupons section would show a grid with the columns:
code): Sortable, searchable.title): Sortable, searchable.currencyCode and amount): Sortable, searchable.createdAt): Sortable, searchable.appliedAt): Sortable, searchable. If the field is not present or empty, show: "Not used yet" if not expired, otherwise show "Expired".appliedBy.id + " (" + appliedBy.type + ")"): Sortable, searchable. If the field is not present or empty, show the empty string "".expiresAt): Sortable, searchable.The grid is by default sorted by createdAt DESC (newer first).
The Store checkout would have an input to enter coupon codes.

And show the already applied ones.

Each coupon UI includes an "X" button to remove the coupon from the cart.
In the cases where the total discount of the applied coupons is not fully used (when the cart total is less than the coupons discount), a warning must be shown in the order summary section of the checkout.
If one or more coupons are removed from the cart and the discount becomes less than the cart total, the warning is automatically removed.

After each application or removal of coupons, the cart subtotals must be refreshed in the UI.