metatroncubeswdev 365e45406a Bundle Offers Shopify app: discount function, admin, storefront, deploy stack
Rust discount function (one automatic discount evaluating all offers in priority
order, parity with the Odoo engine), React Router admin with Polaris, theme app
extension and app proxy pages, webhooks incl. GDPR, managed-pricing limits, and
a Docker Compose stack (Postgres + Caddy HTTPS) for a single VPS.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 21:35:58 -04:00

132 lines
4.7 KiB
Plaintext

{%- comment -%}
F17: up to 3 hints for running offers (Cart hints on) that the cart has started but not completed.
Same rules as the Odoo module: fixed = some lines complete and some missing; mix = 0 < eligible < N;
bxgy = buy quantity reached -> "you qualify, add Y more". Offers already applied are skipped.
bundle-offers.js re-renders this block (Section Rendering) after AJAX cart changes.
{%- endcomment -%}
{%- liquid
assign data = app.metafields.bundle_offers.storefront.value
assign country = localization.country.iso_code
assign locale = request.locale.iso_code
assign applied = ''
for item in cart.items
for allocation in item.line_level_discount_allocations
assign applied = applied | append: '|' | append: allocation.discount_application.title
endfor
endfor
-%}
{%- capture hints -%}
{%- assign n = 0 -%}
{%- for offer in data.offers -%}
{%- if n >= 3 -%}{%- break -%}{%- endif -%}
{%- if offer.f[2] != 1 -%}{%- continue -%}{%- endif -%}
{%- if offer.cc.size > 0 -%}{%- unless offer.cc contains country -%}{%- continue -%}{%- endunless -%}{%- endif -%}
{%- if applied contains offer.n -%}{%- continue -%}{%- endif -%}
{%- liquid
assign name = offer.n
if offer.i[locale].n != blank
assign name = offer.i[locale].n
endif
assign hint = ''
if offer.t == 'fixed'
assign have = 0
assign missing = ''
assign missing_count = 0
for line in offer.l
assign qty = 0
for item in cart.items
if item.product.gift_card? or item.selling_plan_allocation
continue
endif
assign ipid = item.product_id | append: ''
assign ivid = item.variant_id | append: ''
if line.v != ''
if ivid == line.v
assign qty = qty | plus: item.quantity
endif
elsif ipid == line.p
assign qty = qty | plus: item.quantity
endif
endfor
if qty >= line.q
assign have = have | plus: 1
elsif missing_count < 3
assign missing_count = missing_count | plus: 1
if missing != ''
assign missing = missing | append: ', '
endif
assign missing = missing | append: line.tt
endif
endfor
if have > 0 and missing_count > 0
assign hint = 'fixed'
endif
else
if offer.t == 'mix'
assign s = offer.sc
assign need = offer.q
else
assign s = offer.bs
assign need = offer.bq
endif
assign count = 0
for item in cart.items
if item.product.gift_card? or item.selling_plan_allocation
continue
endif
assign ipid = item.product_id | append: ''
assign ivid = item.variant_id | append: ''
assign match = false
if s.p contains ipid or s.v contains ivid
assign match = true
else
for c in item.product.collections
assign cid = c.id | append: ''
if s.c contains cid
assign match = true
endif
endfor
endif
if match
assign count = count | plus: item.quantity
endif
endfor
if offer.t == 'mix' and count > 0 and count < need
assign hint = 'mix'
assign k = need | minus: count
elsif offer.t == 'bxgy' and count >= need
assign hint = 'bxgy'
assign k = offer.gq
endif
endif
-%}
{%- if hint == '' -%}{%- continue -%}{%- endif -%}
{%- assign n = n | plus: 1 -%}
{%- capture summary -%}{% render 'bo-summary', offer: offer %}{%- endcapture -%}
{%- capture strong_name -%}<strong>{{ name | escape }}</strong>{%- endcapture -%}
<li>
<a class="bo-hint" href="/apps/bundles/{{ offer.h }}">
{%- case hint -%}
{%- when 'fixed' -%}
{%- capture strong_items -%}<strong>{{ missing | escape }}</strong>{%- endcapture -%}
{{- 'bundle_offers.hints.fixed_html' | t: items: strong_items, name: strong_name, summary: summary -}}
{%- when 'mix' -%}{{- 'bundle_offers.hints.mix_html' | t: count: k, name: strong_name, summary: summary -}}
{%- else -%}{{- 'bundle_offers.hints.bxgy_html' | t: count: k, name: strong_name, summary: summary -}}
{%- endcase -%}
</a>
</li>
{%- endfor -%}
{%- endcapture -%}
<div class="bo-hints" data-bo-hints="{{ block.id }}" {{ block.shopify_attributes }}>
{%- if hints != blank -%}<ul role="list">{{ hints }}</ul>{%- endif -%}
</div>
{% schema %}
{
"name": "Bundle cart hints",
"target": "section",
"enabled_on": { "templates": ["cart"] },
"settings": []
}
{% endschema %}