Skip to content

Gift Card Management (Admin)

Flow ID: AD-23 Module(s): gift_cards, coupons, eshop (gifts) Complexity: Medium-High Last Updated: 2026-05-21

Business Context

Gift cards are monetary vouchers purchased by customers through a dedicated checkout flow (separate from the shopping cart). On successful payment, the system generates a single-use coupon code and delivers it to the recipient via email and/or SMS. Admins manage two distinct subsystems under "gift cards": (1) gift card orders -- purchasable monetary vouchers that convert to coupon codes, and (2) promotional gifts -- free products added to orders based on configurable rules. This document covers both admin surfaces.


1. Gift Card Order Management

1.1 Admin Listing

Controller: ecommercen/gift_cards/controllers/AdvGiftCardAdminListing.php (241 lines) Auth: ADVISABLE, ADMIN, ORDERS Route: admin/giftCards (mapped via application/config/routes.php) Admin Menu: ORDERS group, icon admin.menu.gift_cards.listing.icon

The listing page is a Vue-powered SPA that fetches data via JSON endpoints on the same controller.

Endpoints (internal JSON API via ApiEndpointTrait):

MethodActionDescription
list()GET with query paramsPaginated, filtered list (50 per page)
get($orderId)GETSingle gift card order detail
cancelGiftCard($orderId)POSTCancel a gift card order
acceptGiftCard($orderId)POSTAccept/complete a gift card order
scheduleEmailJob($orderId)POSTQueue email resend job
scheduleSMSJob($orderId)POSTQueue SMS resend job
getUsedPayways()GETDistinct payment methods used in orders

Available Filters:

FilterTypeDescription
searchLIKE (OR)Searches customer name/surname, send_to_email, send_to_phone, coupon code
dateFrom / dateToRangeCreated date range
paywayExactPayment method used
emailSentBooleanEmail delivery status
smsSentBooleanSMS delivery status
statusEnumGift card status (Pending/Completed/Canceled)

1.2 Status Lifecycle

Defined in ecommercen/gift_cards/libraries/GiftCardStatus.php (Spatie Enum):

StatusValueDescription
Pending1Payment initiated but not confirmed
Completed10Payment confirmed, coupon generated
Canceled11Order canceled (manual or auto-timeout)

Status filtering uses composite logic in AdvGiftCardOrdersModel::applyStatusFilter():

  • Pending: canceled_at IS NULL AND completed_at IS NULL
  • Completed: completed_at IS NOT NULL AND canceled_at IS NULL
  • Canceled: canceled_at IS NOT NULL

1.3 Accept Flow (Admin Action)

When an admin accepts a pending gift card order (acceptGiftCard()):

  1. Loads the gift card order record
  2. Creates a coupon via coupons_model->insertCoupon():
    • Name: GIFTCARD_{orderId}
    • discount_price = gift card amount
    • max_count_usage = 1 (single use)
    • coupon_type = CouponType::GiftCard() (value: 1)
    • Minimum cart rule: total_cart_from = gift card amount
    • Validity: 5 years from acceptance
  3. Generates a unique coupon code via coupons_model->generateCoupons()
  4. Updates gift card order: status=Completed, sets completed_at, links coupon_id, resets email_sent/sms_sent to false
  5. All within a DB transaction
  6. Calls acceptPostActions($orderId) hook (empty by default, overrideable in client repos)

1.4 Cancel Flow (Admin Action)

When an admin cancels a gift card order (cancelGiftCard()):

  • If Pending: Simple status update to Canceled with canceled_at timestamp
  • If Completed: Transaction that deletes the linked coupon, nullifies coupon_id, sets status to Canceled

Calls cancelPostActions($orderId) hook after cancellation.

1.5 Notification Resend

Admins can manually trigger email or SMS resend for completed gift card orders:

  • Email resend: Schedules ResendGiftCardEmail job on QUEUE_GIFT_CARDS queue
  • SMS resend: Schedules ResendGiftCardSMS job on QUEUE_GIFT_CARDS queue

Both jobs validate that gift cards are enabled before executing. SMS additionally checks enabledSms setting.


2. Gift Card Settings

Controller: ecommercen/gift_cards/controllers/AdvGiftCardSettings.php (81 lines) Auth: ADVISABLE, ADMIN, ORDERS Route: admin/giftCardsSettingsAdmin Menu: SETTINGS group

Vue-powered settings page. Reads/writes via AdvGiftCardSettingsReader and Registry.

Registry Keys (GIFT_CARDS group)

KeyTypeDescriptionRole Restriction
ENABLEDboolMaster toggle for gift card featureADVISABLE only
GIFT_CARDSarrayPredefined denomination amounts (sorted)--
FREE_AMOUNTboolAllow custom (free-form) amounts--
MIN_AMOUNTnumericMinimum gift card valueRequired
MAX_AMOUNTnumericMaximum gift card value (default 500)Required
SMSboolEnable SMS delivery--
ORDER_PREFIXstringPrefix for order serial numbers--

Payment Method Configuration

Gift card payment methods are configured separately from regular checkout in Adv_settings.php (payment settings):

  • Stored in Registry: METHODS.PAYWAY_GIFT_CARDS
  • Only shown when GIFT_CARDS.ENABLED is true
  • Supported payment gateways (from getGiftCardPayWays() in ecommercen/helpers/eshop_helper.php:286-299):
    • PayPal, PayPal Advanced, Eurobank, Alpha Bank, Ethniki, Viva Wallet, Ethniki EE, XPay (Nexi XPay Greece)
    • Iris is defined but commented out
  • XPay is configured via the XPAY registry group (API_KEY, IS_PRODUCTION); see the Registry Configuration Summary table below.
  • Viva Wallet has a dedicated GIFT_CARD_SOURCE_CODE registry key for gift card transactions

3. Promotional Gift Management

Controller: ecommercen/eshop/controllers/Adv_gifts_admin.php (442 lines) Auth: ADVISABLE, ADMIN, MARKETING Route: gifts_admin

This is a separate subsystem from gift card orders. Promotional gifts are free products automatically added to customer orders based on configurable rules.

CRUD Operations

ActionMethodDescription
Listindex($offset)Paginated list (50/page) with session-persisted search
Addadd()Create new gift rule with products, MUI, images
Editedit($id)Update existing gift rule
Deletedelete($id)Remove gift rule
TogglesetGiftActivity($id, $active)Enable/disable a gift
Searchsearch_append_item($mode)AJAX product search for gift/requirement assignment

Gift Data Fields

FieldTypeDescription
rule_idintGift rule type (from gift_rules_model)
amount_from / amount_todecimalCart value range trigger
internal_namestringAdmin-only label
date_start / date_enddateActive date range (required)
activeboolEnabled/disabled
gift_per_countintNumber of gifts per qualifying order (1-10)
gift_user_choice_countintHow many gifts the user can choose
is_promoboolPromotional flag
priorityintEvaluation priority
remainingint/nullStock limit (null = unlimited)

Requirements System

Gifts can have two types of requirements:

  1. Product requirements (dom_req_ID[]): Specific products that must be in cart
  2. Vendor requirements (req_vendor_ids[]): Products from specific vendors must be in cart

MUI Fields (per language)

FieldTypeDescription
descriptiontextCustomer-facing description
urlstringLink URL
imagefilePrimary image
promo_imagefilePromotional image
extra_vendor_imagefileAdditional vendor-context image
extra_product_imagefileAdditional product-context image

Images uploaded to files/gifts/ via advuploader.

Search Filters (Session-persisted)

FilterDescription
activeActive/inactive status
textFree text search
giftRulesFilter by rule type
maxStockMaximum remaining stock

Extension Hooks

The controller provides three empty protected methods for client repo overrides:

  • afterAdd($giftId) -- post-creation logic
  • afterEdit($giftId) -- post-update logic
  • afterDelete($giftId) -- post-deletion logic

4. Background Jobs

All gift card jobs are in the giftCards queue (QUEUE_GIFT_CARDS constant).

Scheduled Jobs (from application/config/jobs.php)

JobScheduleDescription
CancelPendingGiftCardsEvery 15 minAuto-cancel stale pending orders
SendGiftCardsToEmailsEvery 5 minSend emails for unsent completed orders
SendGiftCardsToPhonesEvery 5 minSend SMS for unsent completed orders

On-Demand Jobs (Admin-Triggered)

JobTriggerDescription
ResendGiftCardEmailAdmin buttonResend gift card email for specific order
ResendGiftCardSMSAdmin buttonResend gift card SMS for specific order

CancelPendingGiftCards Logic

Configured timeout: giftCardDateTimeIntervalToDrop (default: PT180M = 3 hours, in application/config/app.php).

  1. Fetches pending orders older than the timeout (excluding Iris and PayPal Advanced)
  2. Bulk cancels standard gateway orders
  3. Iris orders: Queries Iris API for actual payment status; cancels only if Iris reports CANCELED, accepts if paid
  4. PayPal Advanced orders: Queries PayPal REST API for capture status; cancels if not COMPLETED, accepts if COMPLETED

Email Delivery

Two email templates:

  • Recipient email (application/views/main/mail/gift_card.php): Sent to send_to_email with coupon code, amount, sender name, expiration date
  • Customer confirmation (application/views/main/mail/gift_card_inform_customer.php): Sent to purchasing customer confirming the gift card purchase was completed

Email subjects configured in db_default_values.php:

  • GIFT_CARD: "You have received a gift card!" (multi-language)
  • GIFT_CARD_INFORM_CUSTOMER: "Gift Card Purchase" (multi-language)

SMS Delivery

Handled by GiftCardSendSms library (ecommercen/gift_cards/jobs/GiftCardSendSms.php). Uses the customer's language preference for message localization. SMS provider configured via giftCardSMSProvider (default: yuboto).


5. Database Schema

gift_card_orders Table

sql
CREATE TABLE gift_card_orders (
    id               int(11)        NOT NULL AUTO_INCREMENT,
    customer_id      int(11)        NOT NULL,
    amount           decimal(11,2)  NOT NULL,
    currency_id      int(11)        NOT NULL,
    currency_rate    decimal(11,4)  NOT NULL,
    payway           varchar(255)   NOT NULL,
    gift_card_status tinyint(1)     NOT NULL,
    coupon_id        int(11)        DEFAULT NULL,
    send_to_email    varchar(255)   DEFAULT NULL,
    send_to_phone    varchar(255)   DEFAULT NULL,
    send_to_name     varchar(255)   DEFAULT NULL,
    send_to_surname  varchar(255)   DEFAULT NULL,
    message          text           DEFAULT NULL,
    email_sent       tinyint(1)     NOT NULL DEFAULT 0,
    sms_sent         tinyint(1)     NOT NULL DEFAULT 0,
    created_at       datetime       NOT NULL,
    completed_at     datetime       DEFAULT NULL,
    canceled_at      datetime       DEFAULT NULL,
    order_serial     varchar(255)   DEFAULT NULL,
    tran_ticket      varchar(32)    DEFAULT NULL,
    PRIMARY KEY (id)
);

Indexes: customer_id, coupon_id, gift_card_status, currency_id, created_at, payway, composite (gift_card_status, email_sent), composite (gift_card_status, sms_sent).

Foreign key relationships (logical, not enforced):

  • customer_id -> shop_customer.id
  • coupon_id -> coupons.coupon_id
  • currency_id -> currencies.id

6. Modern Domain Layer (REST API)

The gift card order entity has a full modern domain layer under the Order context.

Domain Components

ComponentPath
Entitysrc/Domains/Order/GiftCardOrder/Repository/Entity.php
Repositorysrc/Domains/Order/GiftCardOrder/Repository/Repository.php
RepositoryConfiguratorsrc/Domains/Order/GiftCardOrder/Repository/RepositoryConfigurator.php
WriteRepositorysrc/Domains/Order/GiftCardOrder/Repository/WriteRepository.php
Servicesrc/Domains/Order/GiftCardOrder/Service.php
WriteServicesrc/Domains/Order/GiftCardOrder/WriteService.php
WriteDatasrc/Domains/Order/GiftCardOrder/WriteData.php
Validatorsrc/Domains/Order/GiftCardOrder/Validator.php
ListRequestsrc/Domains/Order/GiftCardOrder/ListRequest.php

REST Controller

src/Rest/Order/Controllers/GiftCardOrder.php -- full CRUD with OpenAPI annotations.

MethodPathDescription
GET/rest/order/gift-card-orderCollection with filters/sorts
GET/rest/order/gift-card-order/itemSingle item by filter
GET/rest/order/gift-card-order/{id}Show by ID
POST/rest/order/gift-card-orderCreate
POST/rest/order/gift-card-order/{id}Update
DELETE/rest/order/gift-card-order/{id}Delete

Auth policy (rest_policies.php): Backend auth, roles ADMIN + ORDERS.

Available filters: id, customerId, currencyId, giftCardStatus, couponId, payway, emailSent, smsSent, sendToEmail (partial), sendToName (partial), orderSerial (partial).

Available sorts: id, customerId, amount, giftCardStatus, createdAt, completedAt.

DI Registration

  • Domain: src/Domains/Order/container.php -- registers Repository, RepositoryConfigurator, Service, WriteRepository, Validator, WriteService
  • REST: src/Rest/Order/container.php -- registers GiftCardOrder controller with service bindings

7. Payment Gateway Integration

Gift card orders integrate with payment gateways through the AdvGiftCardPage front controller (ecommercen/gift_cards/controllers/AdvGiftCardPage.php). Each gateway returns form data with a type (redirect, iframe, form) and URL.

Webhook Handling

Viva Wallet (ecommercen/webhooks/AdvViva.php): The webhook handler checks both shop_orders and gift_card_orders tables for the transaction ticket. If the order is a gift card:

  • transactionPaymentCreated -> records installments, calls acceptGiftCard()
  • transactionFailed -> calls cancelGiftCard()

Customer Order History Integration

Gift card orders appear alongside regular orders in the customer admin view (Adv_customers_admin.php::order_history()). The order model uses a UNION query (compileGiftOrdersSelect()) to merge gift card orders into the unified order timeline, with an is_gift_card flag to differentiate display.


8. Client Extension Points

Hook / OverrideLocationPurpose
acceptPostActions($orderId)AdvGiftCardAdminListingCustom logic after accepting a gift card
cancelPostActions($orderId)AdvGiftCardAdminListingCustom logic after canceling a gift card
indexExtras()AdvGiftCardAdminListingAdd extra data to listing page render
afterAdd($giftId)Adv_gifts_adminPost-creation hook for promotional gifts
afterEdit($giftId)Adv_gifts_adminPost-update hook for promotional gifts
afterDelete($giftId)Adv_gifts_adminPost-deletion hook for promotional gifts
AdvGiftCardSettingsReaderCan be overridden in client custom/Custom settings logic
GiftCardSendSmsCan be overriddenCustom SMS delivery

Registry Configuration Summary

GroupKeyDefaultDescription
GIFT_CARDSENABLEDfalseMaster toggle
GIFT_CARDSGIFT_CARDS[]Preset denomination amounts
GIFT_CARDSFREE_AMOUNTfalseAllow custom amounts
GIFT_CARDSMIN_AMOUNT0Minimum value
GIFT_CARDSMAX_AMOUNT500Maximum value
GIFT_CARDSSMSfalseSMS delivery toggle
GIFT_CARDSORDER_PREFIX''Order serial prefix
METHODSPAYWAY_GIFT_CARDS[]Enabled payment methods
VIVAWALLETGIFT_CARD_SOURCE_CODE''Viva source code for gift cards
XPAYAPI_KEY''Nexi XPay API key (required); loaded via getXPaySettings() in ecommercen/helpers/registry_helper.php:346-356
XPAYIS_PRODUCTIONfalseToggle XPay between sandbox (xpaysandbox.nexigroup.com) and production (xpay.nexigroup.com) endpoints

Known Issues & Security Gaps

No known issues for the XPay integration at the admin layer at this time.

For XPay webhook and securityToken verification gaps, see CF-09 Payment Webhooks and IN-23 Nexi XPay Greece.