mirror of
https://github.com/christianvidalwolf-prog/Craze-Data-check.git
synced 2026-08-03 14:05:25 +02:00
feat(bc): sync 40hc pricing
This commit is contained in:
@@ -170,37 +170,30 @@ export function MatrixView({ data, headers, rowStatuses }: MatrixViewProps) {
|
||||
setBcValidationError(null);
|
||||
setBcValidationWarning(null);
|
||||
try {
|
||||
const hasWritableItems = bcValidationResult.items.changes.some((change: any) => change.changed);
|
||||
const hasOnlyUomChanges = !hasWritableItems && bcValidationResult.itemUnitsOfMeasure.changes.some((change: any) => change.changed);
|
||||
if (hasOnlyUomChanges) {
|
||||
setBcValidationWarning(bcValidationResult.itemUnitsOfMeasure.supportReason || 'itemUnitsOfMeasure sync is preview only');
|
||||
return;
|
||||
}
|
||||
|
||||
const result = await applyBusinessCentralSync(headers, bcPreviewRow, bcValidationResult.previewToken);
|
||||
if (!result.success) {
|
||||
if (isPreviewTokenMismatchError(result.error)) {
|
||||
const refreshedPreview = await previewBusinessCentralSync(headers, bcPreviewRow);
|
||||
if (refreshedPreview.success) {
|
||||
setBcValidationResult(refreshedPreview);
|
||||
const retry = await applyBusinessCentralSync(headers, bcPreviewRow, refreshedPreview.previewToken);
|
||||
if (retry.success) {
|
||||
setBcValidationResult(prev => retry.preview ? { ...retry.preview, hasChanges: false } : prev);
|
||||
if (retry.warning) {
|
||||
setBcValidationWarning(retry.warning);
|
||||
}
|
||||
return;
|
||||
if (refreshedPreview.success) {
|
||||
setBcValidationResult(refreshedPreview);
|
||||
const retry = await applyBusinessCentralSync(headers, bcPreviewRow, refreshedPreview.previewToken);
|
||||
if (retry.success) {
|
||||
setBcValidationResult(prev => retry.preview ? { ...retry.preview, hasChanges: false } : prev);
|
||||
if (retry.warning) {
|
||||
setBcValidationWarning(retry.warning);
|
||||
}
|
||||
setBcValidationError(retry.error || 'Apply failed');
|
||||
return;
|
||||
}
|
||||
setBcValidationError(retry.error || 'Apply failed');
|
||||
return;
|
||||
}
|
||||
setBcValidationError(result.error || 'Apply failed');
|
||||
if (result.warning) {
|
||||
setBcValidationWarning(result.warning);
|
||||
}
|
||||
return;
|
||||
}
|
||||
setBcValidationError(result.error || 'Apply failed');
|
||||
if (result.warning) {
|
||||
setBcValidationWarning(result.warning);
|
||||
}
|
||||
return;
|
||||
}
|
||||
setBcValidationResult(prev => result.preview ? { ...result.preview, hasChanges: false } : prev);
|
||||
if (result.warning) {
|
||||
setBcValidationWarning(result.warning);
|
||||
@@ -417,8 +410,8 @@ export function MatrixView({ data, headers, rowStatuses }: MatrixViewProps) {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-1 xl:grid-cols-2 gap-4">
|
||||
{(['items', 'itemUnitsOfMeasure'] as const).map(sectionKey => {
|
||||
<div className="grid grid-cols-1 xl:grid-cols-3 gap-4">
|
||||
{(['items', 'itemUnitsOfMeasure', 'itemUnits40HC'] as const).map(sectionKey => {
|
||||
const section = bcValidationResult[sectionKey];
|
||||
const changed = section.changes.filter((change: any) => change.changed);
|
||||
|
||||
@@ -472,7 +465,7 @@ export function MatrixView({ data, headers, rowStatuses }: MatrixViewProps) {
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className="grid grid-cols-1 xl:grid-cols-2 gap-4">
|
||||
<div className="grid grid-cols-1 xl:grid-cols-3 gap-4">
|
||||
<div className="rounded-lg border border-slate-700 bg-slate-950/60 p-4">
|
||||
<div className="flex items-center justify-between mb-3">
|
||||
<div>
|
||||
@@ -514,6 +507,27 @@ export function MatrixView({ data, headers, rowStatuses }: MatrixViewProps) {
|
||||
{JSON.stringify(bcMappingPreview.itemUnitsOfMeasurePayload, null, 2)}
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<div className="rounded-lg border border-slate-700 bg-slate-950/60 p-4">
|
||||
<div className="flex items-center justify-between mb-3">
|
||||
<div>
|
||||
<h3 className="text-sm font-semibold text-white">API `itemUnitsOfMeasure2` 40HC preview</h3>
|
||||
<p className="text-xs text-slate-400">SKU {bcMappingPreview.articleNo}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="space-y-2">
|
||||
{bcMappingPreview.itemUnits40HCFields.map(field => (
|
||||
<div key={field.targetField} className="grid grid-cols-3 gap-3 text-xs">
|
||||
<div className="text-slate-400">{field.sourceLabel}</div>
|
||||
<div className="text-slate-500 truncate">{field.targetField}</div>
|
||||
<div className="text-white truncate">{String(field.value ?? '—')}</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
<pre className="mt-4 text-[11px] leading-relaxed bg-slate-950 border border-slate-800 rounded p-3 overflow-auto text-slate-200">
|
||||
{JSON.stringify(bcMappingPreview.itemUnits40HCPayload, null, 2)}
|
||||
</pre>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -27,7 +27,7 @@ export interface BCFieldChange {
|
||||
}
|
||||
|
||||
export interface BCSyncPreviewSection {
|
||||
type: 'items' | 'itemUnitsOfMeasure';
|
||||
type: 'items' | 'itemUnitsOfMeasure' | 'itemUnits40HC';
|
||||
desired: Record<string, any>;
|
||||
current: Record<string, any> | null;
|
||||
changes: BCFieldChange[];
|
||||
@@ -46,6 +46,7 @@ export interface BCSyncPreviewResult {
|
||||
articleNo: string;
|
||||
items: BCSyncPreviewSection;
|
||||
itemUnitsOfMeasure: BCSyncPreviewSection;
|
||||
itemUnits40HC: BCSyncPreviewSection;
|
||||
hasChanges: boolean;
|
||||
previewToken: string;
|
||||
error?: string;
|
||||
@@ -59,6 +60,7 @@ export interface BCSyncApplyResult {
|
||||
results?: {
|
||||
items: { applied: boolean; reason?: string; url?: string };
|
||||
itemUnitsOfMeasure: { applied: boolean; reason?: string; url?: string };
|
||||
itemUnits40HC: { applied: boolean; reason?: string; url?: string };
|
||||
};
|
||||
error?: string;
|
||||
warning?: string;
|
||||
|
||||
@@ -11,8 +11,10 @@ export interface BusinessCentralMappingPreview {
|
||||
articleNo: string;
|
||||
itemsPayload: Record<string, any>;
|
||||
itemUnitsOfMeasurePayload: Record<string, any>;
|
||||
itemUnits40HCPayload: Record<string, any>;
|
||||
itemsFields: MappingFieldPreview[];
|
||||
itemUnitsFields: MappingFieldPreview[];
|
||||
itemUnits40HCFields: MappingFieldPreview[];
|
||||
}
|
||||
|
||||
function findHeaderIndex(headers: string[], patterns: string[]): number {
|
||||
@@ -81,6 +83,11 @@ export function buildBusinessCentralMappingPreview(headers: string[], row: Excel
|
||||
const cpnpIdx = findHeaderIndex(headers, ['cpnp']);
|
||||
|
||||
const unitsOuterIdx = findHeaderIndex(headers, ['units', 'outer']);
|
||||
const units40HqIdx = (() => {
|
||||
const hqIdx = findHeaderIndex(headers, ['40', 'hq']);
|
||||
if (hqIdx >= 0) return hqIdx;
|
||||
return findHeaderIndex(headers, ['40', 'hc']);
|
||||
})();
|
||||
const outerWIdx = findHeaderIndex(headers, ['outer', 'w']);
|
||||
const outerLIdx = findHeaderIndex(headers, ['outer', 'l']);
|
||||
const outerHIdx = findHeaderIndex(headers, ['outer', 'h']);
|
||||
@@ -108,10 +115,17 @@ export function buildBusinessCentralMappingPreview(headers: string[], row: Excel
|
||||
height: toBcDecimal(getValue(row, outerHIdx)),
|
||||
};
|
||||
|
||||
const itemUnits40HCPayload = {
|
||||
itemNo: getValue(row, articleNoIdx),
|
||||
code: '40HC',
|
||||
qtyPerUnitOfMeasure: toBcDecimal(getValue(row, units40HqIdx)),
|
||||
};
|
||||
|
||||
return {
|
||||
articleNo,
|
||||
itemsPayload,
|
||||
itemUnitsOfMeasurePayload,
|
||||
itemUnits40HCPayload,
|
||||
itemsFields: [
|
||||
makeFieldPreview('Article No.', articleNoIdx, 'no', itemsPayload.no),
|
||||
makeFieldPreview('Article Details - English', articleDetailsEnIdx, 'articleDetailsEnglish', itemsPayload.articleDetailsEnglish),
|
||||
@@ -130,5 +144,9 @@ export function buildBusinessCentralMappingPreview(headers: string[], row: Excel
|
||||
makeFieldPreview('Outer L (cm)', outerLIdx, 'length', itemUnitsOfMeasurePayload.length),
|
||||
makeFieldPreview('Outer H (cm)', outerHIdx, 'height', itemUnitsOfMeasurePayload.height),
|
||||
],
|
||||
itemUnits40HCFields: [
|
||||
makeFieldPreview('Article No.', articleNoIdx, 'itemNo', itemUnits40HCPayload.itemNo),
|
||||
makeFieldPreview('Units 40FT HQ', units40HqIdx, 'qtyPerUnitOfMeasure', itemUnits40HCPayload.qtyPerUnitOfMeasure),
|
||||
],
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user