← back to Dw Daily Catchup 20260909
lib/readiness-repairs.js
52 lines
'use strict';
function repairType(reason) {
if (/missing spec.*width/.test(reason)) return 'restore-width-metafield';
if (/mfr-sku/.test(reason)) return 'verify-manufacturer-code';
if (/description/.test(reason)) return 'repair-description';
if (/sample.variant/.test(reason)) return 'restore-sample-variant';
if (/price|sellable/.test(reason)) return 'verify-sellable-price';
if (/no product image/.test(reason)) return 'restore-product-image';
if (/private-label-leak/.test(reason)) return 'correct-private-label';
if (/banned word/.test(reason)) return 'correct-title';
return 'review-readiness';
}
function buildRepairReport(decisions, { generatedAt = new Date().toISOString(), complete = true } = {}) {
const latest = new Map();
for (const row of decisions) {
if (!row.shopify_id) continue;
const previous = latest.get(row.shopify_id);
if (!previous || String(row.ts) >= String(previous.ts)) latest.set(row.shopify_id, row);
}
const items = [];
const counts = {};
for (const row of latest.values()) {
if (!['skip-gate', 'skip-read-error', 'activate-error', 'settlement-hold', 'settlement-block'].includes(row.action)) continue;
const groups = new Map();
for (const reason of row.reasons || []) {
const type = repairType(reason);
if (!groups.has(type)) groups.set(type, []);
groups.get(type).push(reason);
}
if (row.action === 'settlement-hold') groups.set('retry-image-review', [row.settlement?.reason || 'unknown']);
if (row.action === 'settlement-block') groups.set('settlement-block-review', [row.settlement?.reason || 'unknown']);
if (row.action === 'activate-error') groups.set('verify-activation-result', ['Shopify did not confirm ACTIVE']);
for (const [type, reasons] of groups) {
counts[type] = (counts[type] || 0) + 1;
items.push({ id: `${row.shopify_id}:${type}`, shopify_id: row.shopify_id,
dw_sku: row.dw_sku, vendor: row.vendor, title: row.title,
observed_at: row.ts, created_at: row.ts, type, reasons: [...new Set(reasons)],
source: 'rotation-live-check', width_source: row.width_source || null,
diagnostics: row.settlement?.diagnostics || null,
requires: type === 'retry-image-review' ? 'provider-recovery-and-fresh-review' : 'verified-source-and-live-recheck',
apply_authorized: false,
});
}
}
return { schema_version: 1, generated_at: generatedAt, scan_complete: complete,
scope: 'Products observed in this activation run; not the entire draft catalog',
mode: 'review-only', products_observed: latest.size,
products_needing_attention: new Set(items.map(item => item.shopify_id)).size,
counts, items };
}
module.exports = { buildRepairReport, repairType };