a2c0789625
Quand un onglet est sélectionné, les produits Shopify absents du tab peuvent appartenir à d'autres familles — ne pas les marquer 'deactivate'. Les désactivations ne s'appliquent qu'en mode catalogue complet (sans filtre). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
72 lines
2.3 KiB
TypeScript
72 lines
2.3 KiB
TypeScript
import type { SyncProduct, ShopifyProductFull, SyncChange, DiffResult } from '@/types/sync'
|
|
|
|
const COMPARABLE_FIELDS = ['title', 'description', 'price', 'status'] as const
|
|
|
|
function getChangedFields(
|
|
sheet: SyncProduct,
|
|
shopify: ShopifyProductFull,
|
|
): Array<{ field: string; from: string; to: string }> {
|
|
return COMPARABLE_FIELDS
|
|
.filter((field) => sheet[field] !== shopify[field])
|
|
.map((field) => ({
|
|
field,
|
|
from: String(shopify[field]),
|
|
to: String(sheet[field]),
|
|
}))
|
|
}
|
|
|
|
/**
|
|
* Calcule le diff entre les produits Sheets et Shopify.
|
|
* Matching par handle (ref normalisée).
|
|
* Si tabFilter est fourni, les désactivations sont ignorées : on ne peut pas savoir
|
|
* si un produit Shopify absent du tab appartient à une autre famille ou a été supprimé.
|
|
*/
|
|
export function computeDiff(
|
|
sheetProducts: SyncProduct[],
|
|
shopifyProducts: ShopifyProductFull[],
|
|
tabFilter?: string,
|
|
): DiffResult {
|
|
const shopifyMap = new Map(shopifyProducts.map((p) => [p.handle, p]))
|
|
const sheetHandles = new Set(sheetProducts.map((p) => p.handle))
|
|
|
|
const changes: SyncChange[] = []
|
|
|
|
for (const sheet of sheetProducts) {
|
|
const shopify = shopifyMap.get(sheet.handle)
|
|
if (!shopify) {
|
|
changes.push({ type: 'create', ref: sheet.ref, sheetProduct: sheet })
|
|
} else {
|
|
const changedFields = getChangedFields(sheet, shopify)
|
|
if (changedFields.length > 0) {
|
|
changes.push({
|
|
type: 'update',
|
|
ref: sheet.ref,
|
|
sheetProduct: sheet,
|
|
shopifyProduct: shopify,
|
|
changedFields,
|
|
})
|
|
} else {
|
|
changes.push({ type: 'unchanged', ref: sheet.ref, sheetProduct: sheet, shopifyProduct: shopify })
|
|
}
|
|
}
|
|
}
|
|
|
|
// Désactivations uniquement en mode catalogue complet (sans filtre par famille)
|
|
if (!tabFilter) {
|
|
for (const shopify of shopifyProducts) {
|
|
if (shopify.status === 'active' && !sheetHandles.has(shopify.handle)) {
|
|
changes.push({ type: 'deactivate', ref: shopify.ref, shopifyProduct: shopify })
|
|
}
|
|
}
|
|
}
|
|
|
|
const summary = {
|
|
create: changes.filter((c) => c.type === 'create').length,
|
|
update: changes.filter((c) => c.type === 'update').length,
|
|
deactivate: changes.filter((c) => c.type === 'deactivate').length,
|
|
unchanged: changes.filter((c) => c.type === 'unchanged').length,
|
|
}
|
|
|
|
return { changes, summary }
|
|
}
|