Files
plantillas-proyectos/frontend/src/lib/utils/items-logic.ts
2026-03-11 09:52:15 -06:00

122 lines
4.7 KiB
TypeScript

export interface Item {
id?: number;
[key: string]: any;
}
// Helper function to check if an object has any meaningful values
export function hasValues(obj: any): boolean {
if (!obj || typeof obj !== 'object') return false;
return Object.values(obj).some(
(val) =>
val !== undefined &&
val !== null &&
val !== '' &&
!(typeof val === 'object' && !hasValues(val))
);
}
// Clean nested data before sending to API
export function cleanLineData(line: any) {
const cleaned: any = { ...line };
// Helper function to convert to number or undefined
const toNumberOrUndefined = (value: any): number | undefined => {
if (value === undefined || value === null || value === '') {
return undefined;
}
const numValue = Number(value);
return !isNaN(numValue) && isFinite(numValue) ? numValue : undefined;
};
// Convert integer fields
cleaned.part_number = toNumberOrUndefined(cleaned.part_number);
cleaned.component_part_number = toNumberOrUndefined(cleaned.component_part_number);
cleaned.class_id = toNumberOrUndefined(cleaned.class_id);
cleaned.unit_of_measure = toNumberOrUndefined(cleaned.unit_of_measure);
cleaned.alternate_unit = toNumberOrUndefined(cleaned.alternate_unit);
// Remove display-only fields
delete cleaned.class_code;
delete cleaned.class_unit_of_measure;
delete cleaned.class_description;
// UI specific fields that shouldn't be in the payload
delete cleaned.part_description_es;
delete cleaned.part_description_en;
delete cleaned.unit_code;
delete cleaned.unit_description;
delete cleaned.includes_subitems;
delete cleaned.payment_method_description;
// Only delete part_number if it's the string code from UI, but schema expects int ID.
// In this codebase, if part_number is populated from existing data, it's an ID.
// If it's a new item, it might be cleaned.
// Remove display-only fields from nested objects
if (cleaned.customs) {
delete cleaned.customs.origin_country_name;
delete cleaned.customs.fraction_description;
if (!hasValues(cleaned.customs)) delete cleaned.customs;
}
if (cleaned.fa_data) {
delete cleaned.fa_data.includes_subitems;
if (!hasValues(cleaned.fa_data)) delete cleaned.fa_data;
}
// Remove empty nested objects
if (cleaned.financial && !hasValues(cleaned.financial)) delete cleaned.financial;
if (cleaned.quantity && !hasValues(cleaned.quantity)) delete cleaned.quantity;
if (cleaned.description && !hasValues(cleaned.description)) delete cleaned.description;
if (cleaned.reference && !hasValues(cleaned.reference)) delete cleaned.reference;
if (cleaned.series != null) {
const arr = Array.isArray(cleaned.series) ? cleaned.series : [cleaned.series];
cleaned.series = arr
.map((s: any) => {
if (!s || typeof s !== 'object') return null;
const { id, line_item_id, ...rest } = s;
return hasValues(rest) ? rest : null;
})
.filter((s: any) => s != null);
if (cleaned.series.length === 0) delete cleaned.series;
}
return cleaned;
}
// Normalize numeric values from strings to numbers (for editing)
export function normalizeItemData(item: Partial<Item>): Partial<Item> {
if (item) {
const normalizedItem = { ...item };
// Normalize financials
if (normalizedItem.financial) {
const f = normalizedItem.financial;
normalizedItem.financial = {
...f,
unit_cost_usd: f.unit_cost_usd != null ? Number(f.unit_cost_usd) : undefined,
unit_cost_mxn: f.unit_cost_mxn != null ? Number(f.unit_cost_mxn) : undefined,
value_usd: f.value_usd != null ? Number(f.value_usd) : undefined,
value_mxn: f.value_mxn != null ? Number(f.value_mxn) : undefined
};
}
// Normalize quantities
if (normalizedItem.quantity) {
const q = normalizedItem.quantity;
normalizedItem.quantity = {
...q,
quantity: q.quantity != null ? Number(q.quantity) : undefined,
net_weight: q.net_weight != null ? Number(q.net_weight) : undefined,
gross_weight: q.gross_weight != null ? Number(q.gross_weight) : undefined,
package_quantity: q.package_quantity != null ? Number(q.package_quantity) : undefined
};
}
return normalizedItem;
}
return item;
}