← back to Dw Signup Fulfillment
verification/tk10836/verify-delivery-profiles.js
86 lines
#!/usr/bin/env node
// TK-10836 Option D: READ-ONLY delivery-profile diagnosis.
// Why was the $0.00 "Free Shipping (No Tracking)" method not offered on Kelly's cart?
// Hypothesis: the free rate is PRICE-CONDITIONED with a minimum > $0, so when the
// "DW Free Samples" automatic discount zeroes the item subtotal to $0.00 the cart
// falls BELOW the minimum and the free rate disappears.
// minimal .env loader (no dotenv dep)
const fs=require('fs'),os=require('os');
for (const line of fs.readFileSync(os.homedir()+'/Projects/secrets-manager/.env','utf8').split('\n')) {
const m=line.match(/^\s*([A-Z0-9_]+)\s*=\s*(.*)$/); if(!m) continue;
let v=m[2].trim().replace(/^['"]|['"]$/g,''); if(!process.env[m[1]]) process.env[m[1]]=v;
}
const STORE = process.env.SHOPIFY_STORE_DOMAIN || 'designer-laboratory-sandbox.myshopify.com';
const TOKEN = process.env.SHOPIFY_FULL_ACCESS_TOKEN; // has read_shipping
const API = '2024-10';
async function gql(query, variables = {}) {
const r = await fetch(`https://${STORE}/admin/api/${API}/graphql.json`, {
method: 'POST',
headers: { 'X-Shopify-Access-Token': TOKEN, 'Content-Type': 'application/json' },
body: JSON.stringify({ query, variables })
});
const j = await r.json();
if (j.errors) console.error('GQL ERRORS:', JSON.stringify(j.errors, null, 2));
return j.data;
}
const Q = `
query {
deliveryProfiles(first: 10) {
nodes {
id name default
productVariantsCount { count }
profileLocationGroups {
locationGroupZones(first: 10) {
nodes {
zone { id name }
methodDefinitions(first: 15) {
nodes {
id name active description
rateProvider {
__typename
... on DeliveryRateDefinition { id price { amount currencyCode } }
... on DeliveryParticipant { id carrierService { formattedName } }
}
methodConditions {
id operator field
conditionCriteria {
__typename
... on MoneyV2 { amount currencyCode }
... on Weight { unit value }
}
}
}
}
}
}
}
}
}
}`;
(async () => {
const d = await gql(Q);
if (!d) return;
const out = [];
for (const p of d.deliveryProfiles.nodes) {
out.push(`\n=== PROFILE: ${p.name} (default=${p.default}, variants=${p.productVariantsCount?.count}) ===`);
for (const lg of p.profileLocationGroups) {
for (const z of lg.locationGroupZones.nodes) {
const zc = '';
out.push(` ZONE: ${z.zone.name} [${zc.slice(0, 120)}]`);
for (const m of z.methodDefinitions.nodes) {
let rate = m.rateProvider.__typename;
if (m.rateProvider.price) rate = `FLAT ${m.rateProvider.price.amount} ${m.rateProvider.price.currencyCode}`;
else if (m.rateProvider.carrierService) rate = `CARRIER ${m.rateProvider.carrierService.formattedName}`;
const conds = (m.methodConditions || []).map(c => {
const cc = c.conditionCriteria || {};
const val = cc.amount !== undefined ? `$${cc.amount}` : (cc.value !== undefined ? `${cc.value}${cc.unit}` : '?');
return `${c.field} ${c.operator} ${val}`;
});
out.push(` - "${m.name}" active=${m.active} | ${rate}` + (conds.length ? `\n CONDITIONS: ${conds.join(' AND ')}` : `\n CONDITIONS: (none — always offered)`));
}
}
}
}
console.log(out.join('\n'));
})();