Skip to content

<div style="display: none;" hidden="true" aria-hidden="true">Are you an LLM? You can read better optimized documentation at /guides/GiftsModule.md for this page in Markdown format</div>

Home

Gifts Module

The gifts module (ecommercen/eshop/) allows store administrators to configure promotional gift rules that automatically assign free products to a customer's order when certain conditions are met.

Architecture

The module is composed of four models and supporting controllers:

FilePurpose
ecommercen/eshop/models/Adv_gift_rules_model.phpStatic registry of all available rule types
ecommercen/eshop/models/Adv_gifts_model.phpCore validation engine — evaluates rules against the live cart
ecommercen/eshop/models/Adv_gift_choices_model.phpReads eligible gift products from the gift_choices table
ecommercen/eshop/models/Adv_gift_requirements_model.phpReads requirement products from the gift_requirements table
ecommercen/eshop/controllers/Adv_gifts_admin.phpAdmin CRUD for gift configurations
ecommercen/libraries/AdvCartResource.phpAdjusts cart contents for display (rule 13 deduction)

Gift Rules

Each rule is identified by an integer ID and registered in Adv_gift_rules_model::$data. Every rule entry defines:

  • id — numeric rule identifier
  • name / help — translation keys resolved via t() at runtime
  • validator — method name on Adv_gifts_model called to check cart eligibility
  • removeFields — POST fields to strip when saving a gift of this type (fields not applicable to the rule)
  • setDefaults — field defaults forced on save (e.g., gift_user_choice_count = 0)

Rule Reference

IDNameTriggerNotes
1Products requiredSpecific products in cartUser selects gift
2Vendors requiredProducts from specific vendors in cartUser selects gift
3Cart totalCart total within amount rangeUser selects gift
4Products + cart totalSpecific products AND total thresholdUser selects gift
5Products + min amountSpecific products AND minimum totalOne gift per rule; gift_per_count forced to 1
6Vendors + cart totalVendor products AND total thresholdUser selects gift
7Vendors + min amountVendor products AND minimum totalOne gift per rule; gift_per_count forced to 1
8Vendors + min priceVendor products AND minimum item priceUser selects gift
9Products + min priceSpecific products AND minimum item priceUser selects gift
10Products (combination)All specified products must be in cart simultaneouslyUser selects gift
11Products required (one gift)Specific products in cart; returns at most gift_per_count giftsUser selects gift
12Vendors required (one gift)Vendor products in cart; returns at most gift_per_count giftsUser selects gift
13Products required — get cheapest freeSpecific products in cartAuto-assign — no user choice

Rule 13: Products Required — Get Cheapest Free

Added in v4.98.X. This rule automatically assigns the cheapest qualifying product currently in the customer's cart as a free gift — no manual gift selection is required or presented to the customer.

How it works

  1. The administrator configures a gift with rule 13 and specifies one or more required products.
  2. gift_user_choice_count is forced to 0 on save (setDefaults) — the gift pool is always computed dynamically, not read from the gift_choices table.
  3. When the cart is evaluated, ruleProductsCheapestFreeValidator counts the total quantity of matching required products present in the cart (same logic as rule 1).
  4. If the count is ≥ gift_per_count, the rule qualifies. getCheapestRequirementProductInCart then allocates which products to give for free using a greedy, stock-aware algorithm:
    • Filters the required products to those actually in the cart.
    • Looks up the live price of each via $this->liveData (populated by AdvCartResource).
    • Sorts candidates cheapest-first; ties break by lowest product ID (deterministic).
    • Iterates the sorted list and takes min(remaining_gifts, product_stock) units from each candidate until all owed gifts are assigned.
    • Returns [1 => [pid, pid, ...]] — a flat per-slot list where each entry represents one gift unit (the same pid may appear multiple times if more than one unit of that product is taken).
  5. The free product(s) are added to the cart as gifts. Their quantities are subtracted from the paid cart rows in baseParseCartContents so the customer is not charged for them. Gift slots with duplicate pids are grouped per-pid at display and adjustment time (via array_count_values) so each cart row is deducted by the correct per-product count.
  6. When the order is placed, adjustCartForRule13Gifts removes the free items from the stored basket rows.

Key methods

MethodLocationPurpose
ruleProductsCheapestFreeValidator(int $masterId, array $reqs, array $productsInCart): intAdv_gifts_modelReturns total qty of required products in cart (eligibility check)
getCheapestRequirementProductInCart(int $giftId, array $allRequirements, array $productsInCart, int $giftsToGive): arrayAdv_gifts_modelReturns [1 => [pid, pid, ...]] — flat per-slot list of auto-assigned gift units, allocated greedily cheapest-first with stock awareness
getRule13GiftAdjustments()Adv_order_modelResolves the cheapest free product and deduction count for the current cart
adjustCartForRule13Gifts()Adv_order_modelRemoves the free item from basket rows when the order is placed
adjustCartContentsForRule13()AdvCartResourceSubtracts the free gift qty from the matching cart row before sending cartContents to the frontend

Admin order page behaviour

Rule 13 gifts are handled differently on the admin order add/edit page:

  • The gifts_for_products AJAX endpoint overrides choices[1] with the cheapest product (mirrors AdvCartResource).
  • validateProductGiftSelections skips rule 13 (auto-assigned — no user selection to validate).
  • The Vue Vuex getter forces ruleSatisfiesChoiceSelection = true for rule 13.
  • getRule13GiftAdjustmentsForProducts() is extracted for reuse between the session cart and the admin fake cart so totals are correctly deducted when payment method, transporter, or address changes are made.

Admin UI fields hidden for rule 13

The following fields are not shown when creating or editing a gift with rule 13 (removeFields):

  • amount_from
  • amount_to
  • req_vendor_ids

isLive behaviour

Rule 13 gifts have no rows in the gift_choices table (the pool is computed dynamically). The getActiveGiftRules query was updated to:

  • Select rule_id in the query so it is available in the filter callback.
  • Skip the early-exit on empty choices to prevent rule 13 gifts from being excluded.
  • Bypass the gift_choices existence check in array_filter for rule 13.

Translations

Translation keys eshop.admin.gifts.rule13.name and eshop.admin.gifts.rule13.help are defined in all 8 supported languages:

English:  Products required - get cheapest free
Help:     Required products in cart trigger the rule. The cheapest required
          product currently in cart is automatically assigned as a free gift.
          On a price tie the product with the lowest ID is selected.

Language files updated: english, greek, german, french, spanish, italian, russian, chinese.

Files to Check for Overrides

If you have customized any of the following files in a client repo, review the changes introduced for rule 13:

  • ecommercen/eshop/models/Adv_gifts_model.php
  • ecommercen/eshop/models/Adv_gift_rules_model.php
  • ecommercen/eshop/models/Adv_order_model.php
  • ecommercen/eshop/controllers/Adv_orders_admin.php
  • ecommercen/libraries/AdvCartResource.php
  • assets/admin/js/order-gifts-block.js
  • application/views/admin/footer_js.php