← back to Dw Signup Fulfillment

lib/giftcard.js

50 lines

'use strict';
// WIRED retail default (Steve's decision, TK-10006). On customers/create the service
// emails the new customer a UNIQUE Shopify gift-card code for their 3 free samples.
// Chosen because the function-backed discount is app-scoped (our token belongs to a
// different app, so it can't mint per-customer function codes), and the admin
// shared-code path wasn't surfacing cleanly. The gift card is fully automated with
// the token we have, unique + single-use per signup, and bounded to $12.75 (so the
// roll-leak exposure is capped at the card balance).
//
// create a Shopify GIFT CARD worth
// FREE_SAMPLE_COUNT × SAMPLE_PRICE (default 3 × $4.25 = $12.75), then email the
// customer the code with a friendly "here are your 3 free samples" template.
//
// Why a gift card (vs a discount code): a gift card is a stored-value balance the
// customer redeems at checkout on ANY line items. The face value ($12.75) is
// sized to exactly cover 3 samples at $4.25. It does NOT hard-limit to 3 samples
// or to the Samples collection — the customer could spend it on anything up to
// the balance. See giftcode-discount.js for the alternative that scopes 100%-off
// to the Samples product set and enforces single-use (Steve chooses at go-live).
//
// DRY_RUN-safe: lib/shopify.js short-circuits the POST and returns a synthetic
// gift_card with a DRYRUN… code so the email template still has something to show.
const config = require('./config');
const shopify = require('./shopify');
const email = require('./email');

async function issueRetailGiftCode(customer) {
  const value = config.SAMPLE_GIFT_VALUE; // 3 × 4.25
  const note = `DW retail free samples (${config.FREE_SAMPLE_COUNT} × $${config.SAMPLE_PRICE}) — customer ${customer.email || customer.id}`;

  const gc = await shopify.createGiftCard({ value, note, currency: config.CURRENCY });
  const card = gc.json && gc.json.gift_card ? gc.json.gift_card : {};
  const code = card.code || '(code returned by Shopify at go-live)';

  const firstName = customer.first_name || (customer.email ? customer.email.split('@')[0] : '');
  const tpl = email.retailGiftEmail({ firstName, code, value, count: config.FREE_SAMPLE_COUNT });
  const mail = await email.sendEmail({ to: customer.email, subject: tpl.subject, html: tpl.html, source: 'retail-gift' });

  return {
    path: 'gift_card',
    value,
    count: config.FREE_SAMPLE_COUNT,
    giftCard: { id: card.id || null, code, dryRun: gc.dryRun || false },
    email: { to: customer.email, subject: tpl.subject, dryRun: mail.dryRun || false, ok: mail.ok !== false },
    shopifyCall: gc.dryRun ? { WOULD: `${gc.method} ${gc.url}`, payload: gc.body } : { status: gc.status },
  };
}

module.exports = { issueRetailGiftCode };