← back to Dw Signup Fulfillment

lib/retail-code.js

53 lines

'use strict';
// PRIMARY retail free-samples path (Steve's decision, TK-10006 — "shared master code").
//
// Shopify scopes function-backed discounts to the OWNING app, and our automation
// token (SHOPIFY_FULFILLMENT_TOKEN) belongs to a DIFFERENT app than the one that
// owns the "DW Free Samples" function — so this service cannot mint per-customer
// codes via discountCodeAppCreate (Shopify rejects cross-app function references).
//
// Instead: ONE shared code discount is created once in the Shopify admin, pointing
// at the DW Free Samples function and limited to "one use per customer" (see
// DEPLOY.md). This module simply EMAILS that shared code to every new customer on
// customers/create. No Shopify write happens here.
//
// Safety comes from the FUNCTION, not the code: signed-in non-trade -> first 3
// SAMPLE units free; trade -> all samples free; anonymous -> none. It never touches
// the $94.42 "Yard" roll variant. "One use per customer" on the discount bounds reuse.
const config = require('./config');
const email = require('./email');

async function issueRetailCode(customer) {
  const code = config.RETAIL_SHARED_CODE;

  // At go-live RETAIL_SHARED_CODE must equal the admin-created code (e.g. DWSAMPLES3).
  // If unset we still run (so the webhook never 500s) but skip the send + warn loudly.
  let warn = null;
  if (!code) {
    warn = 'WARN(go-live): RETAIL_SHARED_CODE is unset — create the shared "DW Free Samples" code discount in Shopify admin and set RETAIL_SHARED_CODE to its code. Skipping the email until then.';
    console.warn('[retail-code] ' + warn);
  }

  const firstName = customer.first_name || (customer.email ? customer.email.split('@')[0] : '');
  const tpl = email.retailCodeEmail({ firstName, code: code || '(code not configured)', count: config.FREE_SAMPLE_COUNT });
  const mail = code
    ? await email.sendEmail({ to: customer.email, subject: tpl.subject, html: tpl.html, source: 'retail-code' })
    : { dryRun: config.DRY_RUN, ok: false, skipped: true };

  return {
    path: 'shared_code',
    code: code || null,
    count: config.FREE_SAMPLE_COUNT,
    warn,
    email: {
      to: customer.email,
      subject: tpl.subject,
      dryRun: mail.dryRun || false,
      ok: mail.ok !== false,
      skipped: mail.skipped || false,
    },
  };
}

module.exports = { issueRetailCode };