chore: add bulk compare-at-price update script + restore middleware auth
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,76 @@
|
|||||||
|
/**
|
||||||
|
* Met à jour compare_at_price sur tous les produits Shopify existants
|
||||||
|
* en lisant Prix marché / Prix remisé depuis Google Sheets.
|
||||||
|
*
|
||||||
|
* Usage: npx ts-node -r tsconfig-paths/register scripts/update-compare-at-price.ts
|
||||||
|
*/
|
||||||
|
|
||||||
|
import * as dotenv from 'dotenv'
|
||||||
|
dotenv.config({ path: '.env.local' })
|
||||||
|
|
||||||
|
import { readSheetProducts } from '../src/lib/googleSheets'
|
||||||
|
import { fetchAllShopifyProducts, getConfig } from '../src/lib/shopifySync'
|
||||||
|
|
||||||
|
async function main() {
|
||||||
|
console.log('Lecture Google Sheets…')
|
||||||
|
const sheetProducts = await readSheetProducts()
|
||||||
|
console.log(`${sheetProducts.length} produits dans Sheets`)
|
||||||
|
|
||||||
|
console.log('Lecture produits Shopify…')
|
||||||
|
const shopifyProducts = await fetchAllShopifyProducts()
|
||||||
|
console.log(`${shopifyProducts.length} produits dans Shopify`)
|
||||||
|
|
||||||
|
const shopifyByHandle = new Map(shopifyProducts.map(p => [p.handle, p]))
|
||||||
|
|
||||||
|
const { baseUrl, headers } = getConfig()
|
||||||
|
|
||||||
|
let updated = 0
|
||||||
|
let skipped = 0
|
||||||
|
let errors = 0
|
||||||
|
|
||||||
|
for (const sheet of sheetProducts) {
|
||||||
|
const shopify = shopifyByHandle.get(sheet.handle)
|
||||||
|
if (!shopify) { skipped++; continue }
|
||||||
|
|
||||||
|
const newCompareAt = sheet.compareAtPrice ?? null
|
||||||
|
const currentCompareAt = (shopify as { compareAtPrice?: string }).compareAtPrice ?? null
|
||||||
|
|
||||||
|
// Normalise pour comparer (null vs undefined vs "0.00" vs null)
|
||||||
|
const norm = (v: string | null) => (!v || v === '0.00') ? null : v
|
||||||
|
if (norm(newCompareAt) === norm(currentCompareAt)) { skipped++; continue }
|
||||||
|
|
||||||
|
// Récupère le variantId
|
||||||
|
const detailRes = await fetch(`${baseUrl}/products/${shopify.shopifyId}.json?fields=variants`, { headers })
|
||||||
|
if (!detailRes.ok) { console.error(`Erreur lecture variant ${sheet.ref}`); errors++; continue }
|
||||||
|
const detail = await detailRes.json() as { product: { variants: Array<{ id: number }> } }
|
||||||
|
const variantId = detail.product.variants[0]?.id
|
||||||
|
if (!variantId) { errors++; continue }
|
||||||
|
|
||||||
|
const res = await fetch(`${baseUrl}/products/${shopify.shopifyId}.json`, {
|
||||||
|
method: 'PUT',
|
||||||
|
headers,
|
||||||
|
body: JSON.stringify({
|
||||||
|
product: {
|
||||||
|
id: shopify.shopifyId,
|
||||||
|
variants: [{ id: variantId, price: sheet.price, compare_at_price: newCompareAt }],
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
})
|
||||||
|
|
||||||
|
if (res.ok) {
|
||||||
|
console.log(`✓ ${sheet.ref} — price=${sheet.price} compare_at=${newCompareAt ?? 'null'}`)
|
||||||
|
updated++
|
||||||
|
} else {
|
||||||
|
const err = await res.text()
|
||||||
|
console.error(`✗ ${sheet.ref} — ${err}`)
|
||||||
|
errors++
|
||||||
|
}
|
||||||
|
|
||||||
|
// Rate limiting
|
||||||
|
await new Promise(r => setTimeout(r, 300))
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(`\nTerminé : ${updated} mis à jour, ${skipped} inchangés, ${errors} erreurs`)
|
||||||
|
}
|
||||||
|
|
||||||
|
main().catch(err => { console.error(err); process.exit(1) })
|
||||||
@@ -0,0 +1,58 @@
|
|||||||
|
import { NextResponse } from 'next/server'
|
||||||
|
import { readSheetProducts } from '@/lib/googleSheets'
|
||||||
|
import { fetchAllShopifyProducts, getConfig } from '@/lib/shopifySync'
|
||||||
|
|
||||||
|
export const maxDuration = 300
|
||||||
|
|
||||||
|
export async function POST() {
|
||||||
|
const sheetProducts = await readSheetProducts()
|
||||||
|
const shopifyProducts = await fetchAllShopifyProducts()
|
||||||
|
const shopifyByHandle = new Map(shopifyProducts.map(p => [p.handle, p]))
|
||||||
|
const { baseUrl, headers } = getConfig()
|
||||||
|
|
||||||
|
const norm = (v: string | null | undefined) => (!v || v === '0.00') ? null : v
|
||||||
|
|
||||||
|
let updated = 0, skipped = 0, errors = 0
|
||||||
|
const log: string[] = []
|
||||||
|
|
||||||
|
for (const sheet of sheetProducts) {
|
||||||
|
const shopify = shopifyByHandle.get(sheet.handle)
|
||||||
|
if (!shopify) { skipped++; continue }
|
||||||
|
|
||||||
|
const newCompareAt = sheet.compareAtPrice ?? null
|
||||||
|
const currentCompareAt = (shopify as { compareAtPrice?: string }).compareAtPrice ?? null
|
||||||
|
|
||||||
|
if (norm(newCompareAt) === norm(currentCompareAt) && sheet.price === shopify.price) {
|
||||||
|
skipped++; continue
|
||||||
|
}
|
||||||
|
|
||||||
|
const detailRes = await fetch(`${baseUrl}/products/${shopify.shopifyId}.json?fields=variants`, { headers })
|
||||||
|
if (!detailRes.ok) { errors++; log.push(`✗ ${sheet.ref} — lecture variant`); continue }
|
||||||
|
const detail = await detailRes.json() as { product: { variants: Array<{ id: number }> } }
|
||||||
|
const variantId = detail.product.variants[0]?.id
|
||||||
|
if (!variantId) { errors++; continue }
|
||||||
|
|
||||||
|
const res = await fetch(`${baseUrl}/products/${shopify.shopifyId}.json`, {
|
||||||
|
method: 'PUT',
|
||||||
|
headers,
|
||||||
|
body: JSON.stringify({
|
||||||
|
product: {
|
||||||
|
id: shopify.shopifyId,
|
||||||
|
variants: [{ id: variantId, price: sheet.price, compare_at_price: newCompareAt }],
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
})
|
||||||
|
|
||||||
|
if (res.ok) {
|
||||||
|
updated++
|
||||||
|
log.push(`✓ ${sheet.ref} price=${sheet.price} compare_at=${newCompareAt ?? 'null'}`)
|
||||||
|
} else {
|
||||||
|
errors++
|
||||||
|
log.push(`✗ ${sheet.ref} — ${res.status}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
await new Promise(r => setTimeout(r, 300))
|
||||||
|
}
|
||||||
|
|
||||||
|
return NextResponse.json({ updated, skipped, errors, log })
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user