Customer Engagement Commerce Gap Mining
Customer Engagement Commerce Gap Mining
Section titled “Customer Engagement Commerce Gap Mining”Scope: customer-facing commerce and engagement features from the legacy web source. This is not a UI-copy exercise. Source paths are evidence only; modern implementation should use Supabase, Kill Bill, Strapi, Novu, Storage, Cron/Queues, and DDD feature slices.
Ubiquitous Names
Section titled “Ubiquitous Names”PromotionEntitlement: customer-owned coupon, gift coupon, product coupon, or service credit with ownership, expiry, use, cancellation, and restoration state.GiftCouponPurchase: buyer/receiver gift coupon payment intent, payment proof, issued coupon, SMS handoff, resend, and cancellation state.GiftFulfillmentRequest: product gift order using an entitlement, with recipient, address, fulfillment state, and operator repair history.PromotionUseLedger: immutable coupon use/restoration journal for reservation payment, gift fulfillment, cancellation, and expiry.CampaignPublication: event, promotion, alliance, popup, sponsor benefit, result page, and campaign landing content authored through CMS.NotificationInboxItem: customer-visible notification with show window, action target, read state, and delivery audit linkage.PartnerBenefitProgram: configurable external benefit program such as milk, lovebox, or cleaning service.PartnerBenefitLead: customer application, eligibility proof, cancellation, export batch, result attachment, and partner handoff audit.
Component Flow
Section titled “Component Flow”flowchart LR Customer[Customer portal] Kill Bill[Kill Bill] CMS[Strapi CMS] Novu[Novu] Cron[Supabase Cron/Queues] Storage[(Supabase Storage)] Promotion[PromotionEntitlement] GiftPurchase[GiftCouponPurchase] GiftFulfillment[GiftFulfillmentRequest] Campaign[CampaignPublication] Inbox[NotificationInboxItem] PartnerProgram[PartnerBenefitProgram] PartnerLead[PartnerBenefitLead] ExportBatch[PartnerBenefitExportBatch] Customer --> GiftPurchase GiftPurchase --> Kill Bill GiftPurchase --> Promotion Promotion --> GiftFulfillment GiftFulfillment --> Promotion Customer --> Campaign CMS --> Campaign Campaign --> Promotion Customer --> PartnerLead PartnerProgram --> PartnerLead Cron --> ExportBatch PartnerLead --> ExportBatch ExportBatch --> Storage Promotion --> Inbox PartnerLead --> Inbox Inbox --> Novu
Source Evidence And Migration Gaps
Section titled “Source Evidence And Migration Gaps”Coupon Purchase, Registration, Resend, Cancellation
Section titled “Coupon Purchase, Registration, Resend, Cancellation”Source behavior:
- Gift coupon payment prepare accepts buyer/receiver information, price, gift
coupon type, and message, then creates a pending coupon payment row. Evidence:
source-refs/sanmopia_web/application/controllers/api/Shop.php:10-55andsource-refs/sanmopia_web/application/models/Coupon_model.php:280-319. - Source deletes stale unpaid coupon payment rows from previous days before
creating a new pending payment. Evidence:
source-refs/sanmopia_web/application/models/Coupon_model.php:289-294. - Coupon issuance uses generated coupon numbers, buyer/receiver fields, price,
and publish date. Evidence:
source-refs/sanmopia_web/application/models/Coupon_model.php:396-453. - Gift coupon registration can happen by coupon id or by receiver phone after
signup/profile changes. Evidence:
source-refs/sanmopia_web/application/models/Coupon_model.php:328-394. - Gift coupon resend sends SMS to a new receiver phone but source update of
receiver fields is commented out. Evidence:
source-refs/sanmopia_web/application/controllers/api/Shop.php:109-177. - Gift coupon cancellation marks coupon payment refunded and coupon deleted only
after checking whether the gift coupon was used. Evidence:
source-refs/sanmopia_web/application/controllers/api/Shop.php:179-230andsource-refs/sanmopia_web/application/models/Coupon_model.php:561-583.
Modern gap:
GiftCouponPurchaseshould use Kill Bill pre-registration and verification, then issuePromotionEntitlementonly from confirmed payment state.PromotionEntitlementneeds owner/receiver separation. Anonymous buyer and future signup claim should be explicit, not inferred by mutable phone lookup.- Resend must be a
GiftCouponDeliveryAttemptwith recipient snapshot, provider response, idempotency key, and delivery audit. It must not silently change ownership. - Cancellation must distinguish payment refund, entitlement revocation, already-used rejection, and customer-visible refund status.
Product Gift Fulfillment And Coupon Restoration
Section titled “Product Gift Fulfillment And Coupon Restoration”Source behavior:
- Gift product order validates login, coupon ownership, usable coupon state,
product id, recipient, phone, address, and comment, then inserts a product
application. Evidence:
source-refs/sanmopia_web/application/controllers/api/Shop.php:57-107. - Product coupon use checks for existing product apply rows and old product
coupon kinds. Evidence:
source-refs/sanmopia_web/application/models/Coupon_model.php:260-278. - Shopping mall coupons can be created from reservation context and attached to
a user coupon row. Evidence:
source-refs/sanmopia_web/application/models/Coupon_model.php:495-528. - Reservation cancellation restores used coupons and appends a reuse log with
reservation id. Evidence:
source-refs/sanmopia_web/application/models/Coupon_model.php:530-553. - Admin stop/cancel status changes reset product coupons only for
normal-service reservations whose status is
13or9. Source hard-deletes existingCOUPON_TBrows, counts attended days fromMANAGER_ATTENDANCE_TB, republishes no coupon for<=2days, a one-weekPRODUCT120,000 coupon for3-7days, or a two-weekPRODUCT230,000 coupon for>=8days, then immediately inserts aUSER_COUPON_TBrow with+6 monthexpiry. Evidence:source-refs/sanmopia-admin/application/models/Reservation_model.php:1873-1880,source-refs/sanmopia-admin/application/models/Reservation_model.php:1888-1892,source-refs/sanmopia-admin/application/models/Coupon_model.php:63-87,source-refs/sanmopia-admin/application/models/Coupon_model.php:97-142, andsource-refs/sanmopia-admin/application/models/Coupon_model.php:144-157. Backend domain now owns the replacement asProductCouponResetPolicy: it deduplicates stale product entitlement ids into auditable revocations, plans no replacement for<=2actual service days, and uses the versioned promotion catalog for3-7and>=8actual-service-day replacement entitlements instead of sourcePRODUCT1/PRODUCT2literals. Application commandPlanReservationPromotionSideEffectHandlernow composes product reset and cancellation-only reservation coupon restore in one persistable plan, so stop status13cannot accidentally restore used reservation coupons. Remaining migration is outbox command execution, workflow binding, repair commands, and actor-visible ledger/read models. Supabase persistence now storessanmopia_reservation_promotion_side_effect_plansplussanmopia_promotion_entitlement_outbox_entriesso replay can use idempotency-key conflict protection instead of controller deletes or flag flips. - Initial product coupon issue is separate from reset/reissue: normal
reservations can receive one-week or two-week product coupons based on service
term and publish date, voucher-only service details are excluded, and an
existing coupon may have only its publish date updated for compatibility.
Evidence:
source-refs/sanmopia-admin/application/models/Coupon_model.php:210-323. - Used reservation coupons can also be reopened by cancellation logic. Web
cancellation writes mother actor text; admin cancellation writes admin actor
text. Both clear
USE_FLandUSE_DTand appendUSER_COUPON_REUSE_LOG. Backend domain now owns this asReservationCouponRestorePolicy, with actor-aware restore reasons and existingPromotionEntitlement.restoretransitions instead of direct flag updates. The application side-effect command defaults customer, operator, and system restore reasons from actor kind and rejects reservation coupon restore ids on service-stop commands. Evidence:source-refs/sanmopia_web/application/models/Coupon_model.php:530-553, andsource-refs/sanmopia-admin/application/models/Coupon_model.php:935-958. - Coupon expiry processing scans coupons whose expiry is today and writes expiry
history. Evidence:
source-refs/sanmopia_web/application/models/Coupon_model.php:624-640.
Modern gap:
GiftFulfillmentRequestshould consume aPromotionEntitlementthrough a command that creates aPromotionUseLedgerentry. Fulfillment, entitlement use, and address snapshot must commit atomically.- Reservation cancellation should execute
PromotionEntitlementRestoredfacts from the persisted side-effect plan through the payment/reservation workflow instead of directly toggling use flags. - Stop/cancel product-coupon reset now has an application-level
ReservationPromotionSideEffectPlanwith actual-service-day input, original entitlement lineage, idempotency key, cancellation/stop trigger, Supabase plan snapshot, and entitlement outbox rows. Remaining acceptance: execute entitlement cancellation/issue/restore from the outbox, add repair state, and prove stopped or cancelled normal reservations reproduce the source bands (<=2none,3-7one-week 20,000,>=8two-week 30,000) without duplicate grants on command replay or repeated edits while already stopped. - Used-coupon restoration should append ledger facts and customer-visible
history instead of only flipping
USER_COUPON_TBflags. - Expiry should be a scheduled Supabase Cron/Queue job over entitlement policy versions with idempotent ledger entries.
- Product coupon source codes such as product buckets remain adapter mappings, not domain enums.
Campaigns, Events, Alliance Benefits
Section titled “Campaigns, Events, Alliance Benefits”Source behavior:
- Event controller maps many hardcoded slugs to static view templates for
review events, app review events, culture events, sponsor benefits, campaign
results, and one-off partner pages. Evidence:
source-refs/sanmopia_web/application/controllers/Event.php:14-184. - Additional service benefits are another switch over sponsor slugs, with
deleted/deprecated cases left in comments and some image-only pages. Evidence:
source-refs/sanmopia_web/application/controllers/Event.php:186-227. - Alliance page and event result page are separate switch-style routes.
Evidence:
source-refs/sanmopia_web/application/controllers/Event.php:229-264.
Modern gap:
CampaignPublicationshould replace static view switches. Strapi should own campaign page body, media, CTA, active windows, result pages, partner sponsor pages, and deprecated state.CampaignPlacementshould own popup/banner/entry-slot placement rules and dismissal keys.- Review-event application, winner announcement, and reward issuance should be modeled as campaign participation/award facts if any operational workflow is required; static content alone is insufficient.
Customer Notification Inbox
Section titled “Customer Notification Inbox”Source behavior:
- Notification rows store user id, notification type, optional show date, and
optional action data payload. Evidence:
source-refs/sanmopia_web/application/models/Notification_model.php:16-39. - Notifications can be inserted from FCM token lookup, resolving token to user
before inserting an inbox row. Evidence:
source-refs/sanmopia_web/application/models/Notification_model.php:42-53. - Inbox reads notification type template data plus row-specific data where
show date is due, ordered newest first. Evidence:
source-refs/sanmopia_web/application/models/Notification_model.php:56-69.
Modern gap:
NotificationInboxItemshould separate content template, row action payload, show window, read/archive state, and delivery channel audit.- Novu dispatch should write
CommunicationDispatchEvent; inbox item should not be the delivery proof. - Token-based insertion is a legacy adapter concern. Modern commands should target customer profile ids and let communication delivery resolve devices.
Partner Benefit Lead Programs
Section titled “Partner Benefit Lead Programs”Source behavior:
- Momfirst submit validates user login, applicant fields, program types,
eligible reservation, then inserts one or more benefit application rows and
sends customer notifications by program. Evidence:
source-refs/sanmopia_web/application/controllers/api/Momfirst.php:10-95. - Momfirst cancel loops selected product types and deletes application info.
Evidence:
source-refs/sanmopia_web/application/controllers/api/Momfirst.php:97-146. - Momfirst model owns program type validation, eligible reservation lookup,
insert/cancel, export data, export sent flags, SMS reservation, application
status reads, and delete flows. Evidence:
source-refs/sanmopia_web/application/models/Momfirst_model.php:21-859. - Clean service submit validates housing/service fields, eligible reservation,
duplicate application state, and inserts a lead. Evidence:
source-refs/sanmopia_web/application/controllers/api/Clean.php:9-91. - Clean service has export data, export sent flags, cancellation, eligibility,
and application status paths. Evidence:
source-refs/sanmopia_web/application/models/Clean_model.php:50-673. - CLI schedulers build and send CSV exports for Momfirst/Clean programs.
Evidence:
source-refs/sanmopia_web/application/controllers/cli/Momfirst.php:22-174andsource-refs/sanmopia_web/application/controllers/cli/Clean.php:21-142.
Modern gap:
PartnerBenefitProgrammust be configurable by code, eligibility policy, required fields, cancellation window, export cadence, partner destination, notification workflow, and active dates.PartnerBenefitLeadshould keep applicant snapshot, reservation eligibility proof, submitted fields, cancellation state, and customer-visible status.PartnerBenefitExportBatchshould be generated by workflow/Cron, write CSV or partner payload artifacts to private Supabase Storage, and track sent state, retry, missing rows, and partner response.- Lead deletion should become cancellation/anonymization policy. Do not hard delete rows when legal/audit retention or partner export state exists.
Feature-Level Queue
Section titled “Feature-Level Queue”- Backend/contract:
PromotionEntitlementread model with ownership, receiver, expiry, use, restoration, and cancellation state. - Backend/contract:
GiftCouponPurchaseKill Bill workflow with payment verification, entitlement issuance, resend attempt, and refund/revoke state. - Backend/contract:
GiftFulfillmentRequestcommand and operator repair audit. - Backend:
PromotionUseLedgeridempotent restore/expire/use ledger. - Backend/contract/frontend-worker: customer coupon wallet projection and sent coupon projection.
- Backend/docs:
CampaignPublicationandCampaignPlacementthrough Strapi, including campaign result pages and sponsor benefit slots. - Backend/contract:
NotificationInboxItemread model plus Novu dispatch audit linkage. - Backend/contract:
PartnerBenefitProgram,PartnerBenefitLead, andPartnerBenefitExportBatchwith Supabase Storage artifacts. - Docs: map each legacy coupon/product/program source code at adapter boundary only; no legacy product code as domain language.