cart.lines.discounts.generate.run · TypeScript · cultiva-cafe-app
// extensions/cultiva-vip-discount/src/run.ts // Shopify Function: VIP Collection Discount — Cultiva Café import type { RunInput, FunctionRunResult } from "../generated/api"; const NO_CHANGES: FunctionRunResult = { discounts: [], discountApplicationStrategy: "FIRST" }; interface Configuration { minimumAmount: number; discountPercentage: number; } export function run(input: RunInput): FunctionRunResult { // 1. Leer configuración del metafield ($app:config) const config = JSON.parse( input.discount?.metafield?.jsonValue ?? '{}' ) as Partial<Configuration>; const minAmount = config.minimumAmount ?? 50.0; const discountPercent = config.discountPercentage ?? 15.0; // 2. Filtrar líneas de la colección VIP const vipLines = input.cart.lines.filter((line) => { if (line.merchandise.__typename !== "ProductVariant") return false; return line.merchandise.product.inVipCollection; }); if (vipLines.length === 0) return NO_CHANGES; // 3. Calcular subtotal VIP const vipSubtotal = vipLines.reduce((acc, line) => { const price = parseFloat(line.cost.amountPerQuantity.amount); return acc + price * line.quantity; }, 0); // 4. Verificar umbral mínimo if (vipSubtotal < minAmount) return NO_CHANGES; // 5. Construir operaciones de descuento por línea const targets = vipLines.map((line) => ({ cartLine: { id: line.id }, })); return { discounts: [ { targets, value: { percentage: { value: String(discountPercent) }, }, message: `☕ Descuento VIP ${discountPercent}% — Cultiva Café`, }, ], discountApplicationStrategy: "FIRST", }; }
# extensions/cultiva-vip-discount/src/run.graphql query RunInput($vipCollectionId: [ID!]) { discount { metafield( namespace: "$app" key: "config" ) { jsonValue } } cart { lines { id quantity cost { amountPerQuantity { amount currencyCode } } merchandise { __typename ... on ProductVariant { id title product { inVipCollection: inAnyCollection( ids: $vipCollectionId ) } } } } } }
{
"discount": {
"metafield": {
"jsonValue": "{\"minimumAmount\":50,\"discountPercentage\":15}"
}
},
"cart": {
"lines": [
{
"id": "gid://shopify/CartLine/1",
"quantity": 2,
"cost": {
"amountPerQuantity": {
"amount": "18.00",
"currencyCode": "EUR"
}
},
"merchandise": {
"__typename": "ProductVariant",
"id": "gid://shopify/ProductVariant/101",
"title": "Ethiopia Yirgacheffe 250g",
"product": {
"inVipCollection": true
}
}
},
{
"id": "gid://shopify/CartLine/2",
"quantity": 1,
"cost": {
"amountPerQuantity": {
"amount": "24.00",
"currencyCode": "EUR"
}
},
"merchandise": {
"__typename": "ProductVariant",
"id": "gid://shopify/ProductVariant/205",
"title": "Kit Barista Pro V60
"product": {
"inVipCollection": true
}
}
}
]
}
}
{
"discounts": [
{
"targets": [
{ "cartLine": { "id": "gid://shopify/CartLine/1" } },
{ "cartLine": { "id": "gid://shopify/CartLine/2" } }
],
"value": {
"percentage": { "value": "15" }
},
"message": "☕ Descuento VIP 15% — Cultiva Café"
}
],
"discountApplicationStrategy": "FIRST"
}
// Ahorro aplicado:
// CartLine/1: 2 × 18,00€ = 36,00€ → -5,40€ → 30,60€
// CartLine/2: 1 × 24,00€ = 24,00€ → -3,60€ → 20,40€
// ─────────────────────────────────────────────────
// Total ahorro: -9,00€
// Total final: 51,00€ (antes 60,00€)
mutation { discountAutomaticAppCreate(automaticAppDiscount: { title: "VIP Collection 15%" functionId: "01J8XKZP7..." metafields: [{ namespace: "$app" key: "config" type: "json" value: "{\"minimumAmount\":50,\"discountPercentage\":15}" }] }) { automaticAppDiscount { id title } userErrors { field message } } }