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>
132 lines
4.7 KiB
Plaintext
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 %}
|