[object Object]

← back to Dw Signup Fulfillment

TK-11406: sample-ledger counts free units title-agnostically (Regios 'Free sample'), restoring the app-side 3-sample cap

1de8a864c40898cde375ecbb43ce58663812a9d8 · 2026-09-10 11:55:30 -0700 · Steve Abrams

The cap ledger only summed discounts titled 'DW Free Samples (auto)', but the live
grant is Regios titled 'Free sample' → countDiscountedSamples always returned 0 and
free_samples_used never incremented (cap was a silent no-op, held only by Regios
internally). Fix (b): sum all discount allocations on a sample line regardless of the
emitting app's title; the sample-line heuristic already scopes eligibility and
floor(allocated/unitPrice) keeps partial discounts at 0. Removes dead DISCOUNT_TITLE.
Test updated: title-agnostic order counts 3; undiscounted sample counts 0. DTD/Codex concurred (b).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014nA9g7iQZMhnsGbaXfFYDL

Files touched

Diff

commit 1de8a864c40898cde375ecbb43ce58663812a9d8
Author: Steve Abrams <steve@designerwallcoverings.com>
Date:   Thu Sep 10 11:55:30 2026 -0700

    TK-11406: sample-ledger counts free units title-agnostically (Regios 'Free sample'), restoring the app-side 3-sample cap
    
    The cap ledger only summed discounts titled 'DW Free Samples (auto)', but the live
    grant is Regios titled 'Free sample' → countDiscountedSamples always returned 0 and
    free_samples_used never incremented (cap was a silent no-op, held only by Regios
    internally). Fix (b): sum all discount allocations on a sample line regardless of the
    emitting app's title; the sample-line heuristic already scopes eligibility and
    floor(allocated/unitPrice) keeps partial discounts at 0. Removes dead DISCOUNT_TITLE.
    Test updated: title-agnostic order counts 3; undiscounted sample counts 0. DTD/Codex concurred (b).
    
    Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_014nA9g7iQZMhnsGbaXfFYDL
---
 lib/sample-ledger.js                               | 13 ++--
 scripts/sample-ledger-test.js                      |  5 +-
 .../tk10836/D3501-pre-delete-snapshot.json         | 83 ++++++++++++++++++++++
 3 files changed, 91 insertions(+), 10 deletions(-)

diff --git a/lib/sample-ledger.js b/lib/sample-ledger.js
index 47806fa..db25b26 100644
--- a/lib/sample-ledger.js
+++ b/lib/sample-ledger.js
@@ -1,7 +1,6 @@
 'use strict';
 const crypto = require('crypto');
 
-const DISCOUNT_TITLE = 'DW Free Samples (auto)';
 const NS = 'custom';
 const USED_KEY = 'free_samples_used';
 const COUNTED_KEY = 'free_samples_counted';
@@ -21,16 +20,14 @@ function isApprovedTradeTags(tags) {
 
 function countDiscountedSamples(order) {
   if (!order?.customer?.id) return 0;
-  const applications = order.discount_applications || [];
   return (order.line_items || []).reduce((total, item) => {
     const sample = /\bsample\b/i.test(item.variant_title || '') || /-sample$/i.test(item.sku || '');
     const unitPrice = Number(item.price || 0);
     if (!sample || unitPrice <= 0) return total;
-    const allocated = (item.discount_allocations || []).reduce((sum, allocation) => {
-      const application = applications[allocation.discount_application_index];
-      const label = application?.title || application?.code || '';
-      return label === DISCOUNT_TITLE ? sum + Number(allocation.amount || 0) : sum;
-    }, 0);
+    const allocated = (item.discount_allocations || []).reduce(
+      (sum, allocation) => sum + Number(allocation.amount || 0),
+      0
+    );
     const units = Math.floor((allocated + 0.00001) / unitPrice);
     return total + Math.min(Number(item.quantity || 0), Math.max(0, units));
   }, 0);
@@ -72,4 +69,4 @@ class SampleUsageLedger {
   }
 }
 
-module.exports = { DISCOUNT_TITLE, SampleUsageLedger, countDiscountedSamples, isApprovedTradeTags, verifyShopifyHmac };
+module.exports = { SampleUsageLedger, countDiscountedSamples, isApprovedTradeTags, verifyShopifyHmac };
diff --git a/scripts/sample-ledger-test.js b/scripts/sample-ledger-test.js
index b7fb305..b2cbfb1 100644
--- a/scripts/sample-ledger-test.js
+++ b/scripts/sample-ledger-test.js
@@ -8,7 +8,7 @@ const {
   SampleUsageLedger, countDiscountedSamples, isApprovedTradeTags, verifyShopifyHmac,
 } = require('../lib/sample-ledger');
 
-function order({ amount = '12.75', title = 'DW Free Samples (auto)' } = {}) {
+function order({ amount = '12.75', title = 'Free sample' } = {}) {
   return {
     id: 10, customer: { id: 20 }, discount_applications: [{ title }],
     line_items: [{ quantity: 4, price: '4.25', variant_title: 'Sample', sku: 'ABC-Sample', discount_allocations: [{ amount, discount_application_index: 0 }] }],
@@ -21,7 +21,8 @@ async function main() {
   assert.equal(verifyShopifyHmac(raw, sig, 'secret'), true);
   assert.equal(verifyShopifyHmac(raw, 'bad', 'secret'), false);
   assert.equal(countDiscountedSamples(order()), 3);
-  assert.equal(countDiscountedSamples(order({ title: 'Other' })), 0);
+  assert.equal(countDiscountedSamples(order({ title: 'DW Free Samples (auto)' })), 3); // title-agnostic now
+  assert.equal(countDiscountedSamples(order({ amount: '0' })), 0);                     // undiscounted sample never counts
   assert.equal(isApprovedTradeTags('trade, trade_approved'), true);
   assert.equal(isApprovedTradeTags('trade, designer'), false);
 
diff --git a/verification/tk10836/D3501-pre-delete-snapshot.json b/verification/tk10836/D3501-pre-delete-snapshot.json
new file mode 100644
index 0000000..c4eaca3
--- /dev/null
+++ b/verification/tk10836/D3501-pre-delete-snapshot.json
@@ -0,0 +1,83 @@
+{
+  "snapshotted_at": "2026-09-10T18:54:49.980Z",
+  "reason": "pre-delete snapshot, TK-10836 D3501, Steve authorized delete 2026-09-10",
+  "draft": {
+    "id": "gid://shopify/DraftOrder/1001590718515",
+    "name": "#D3501",
+    "status": "OPEN",
+    "createdAt": "2026-09-10T17:24:24Z",
+    "updatedAt": "2026-09-10T17:24:24Z",
+    "note2": "TK-10836 — 3 free samples promised in writing 2026-09-02 and not deliverable at checkout (her cart quoted $24.95 shipping on $0.00 items). DTD verdict B (7/7): ship directly at $0 rather than send another checkout instruction. Swatches are the exact 3 from her own abandoned cart 34015098110003.",
+    "email": "kcyounge@gmail.com",
+    "tags": [
+      "goodwill",
+      "promised-free-sample",
+      "tk-10836"
+    ],
+    "totalPriceSet": {
+      "shopMoney": {
+        "amount": "0.0",
+        "currencyCode": "USD"
+      }
+    },
+    "customer": {
+      "id": "gid://shopify/Customer/8388564123699",
+      "email": "kcyounge@gmail.com",
+      "firstName": "Kelly",
+      "lastName": "Paradis"
+    },
+    "shippingAddress": {
+      "address1": "2300 Sun Valley Drive",
+      "address2": null,
+      "city": "Ann Arbor",
+      "provinceCode": "MI",
+      "zip": "48108",
+      "countryCodeV2": "US",
+      "firstName": "Kelly",
+      "lastName": "Paradis"
+    },
+    "lineItems": {
+      "nodes": [
+        {
+          "title": "Brushed Finesse Pewter",
+          "quantity": 1,
+          "variant": {
+            "id": "gid://shopify/ProductVariant/44723768688691",
+            "sku": "DWCC-600006-Sample"
+          },
+          "originalUnitPriceSet": {
+            "shopMoney": {
+              "amount": "4.25"
+            }
+          }
+        },
+        {
+          "title": "Shimmer Polar White",
+          "quantity": 1,
+          "variant": {
+            "id": "gid://shopify/ProductVariant/44723776454707",
+            "sku": "DWCC-600045-Sample"
+          },
+          "originalUnitPriceSet": {
+            "shopMoney": {
+              "amount": "4.25"
+            }
+          }
+        },
+        {
+          "title": "Finesse Metallic Rose",
+          "quantity": 1,
+          "variant": {
+            "id": "gid://shopify/ProductVariant/44723792674867",
+            "sku": "DWCC-600128-Sample"
+          },
+          "originalUnitPriceSet": {
+            "shopMoney": {
+              "amount": "4.25"
+            }
+          }
+        }
+      ]
+    }
+  }
+}
\ No newline at end of file

← 040121b TK-11411: fail loud on unset PUBLIC_URL before any send, not  ·  back to Dw Signup Fulfillment  ·  TK-10836: audit record for the D3501 deletion (original comm 12cc71b →