Files
dashfront/src/api/retoure.js
2026-10-27 00:28:06 +01:00

188 lines
6.2 KiB
JavaScript

import { http } from './http.js';
/**
* Normalizes a retouresummary record from either snake_case (raw view) or camelCase.
* Fields: manifest_id, retoure_number, retoure_date, entity_id, customer_name,
* positions, gross_total, paid_total, ordered_quantity, shipped_quantity, is_paid, is_shipped, created_at
*/
export function normalizeRetoureSummary(row) {
if (!row) return null;
const id = row.manifest_id ?? row.id;
const num = row.retoure_number ?? row.number ?? (id ? `RET-${id}` : '');
const dt = row.retoure_date ?? row.date ?? row.created_at ?? row.createdAt;
const entityId = row.entity_id ?? row.entityId ?? null;
const customerName = row.customer_name ?? row.customerName ?? '';
const positions = Number(row.positions) || 0;
const grossTotal = row.gross_total != null ? Number(row.gross_total) : (row.grossTotal != null ? Number(row.grossTotal) : 0);
const paidTotal = row.paid_total != null ? Number(row.paid_total) : (row.paidTotal != null ? Number(row.paidTotal) : 0);
const orderedQuantity = row.ordered_quantity != null ? Number(row.ordered_quantity) : (row.orderedQuantity != null ? Number(row.orderedQuantity) : 0);
const shippedQuantity = row.shipped_quantity != null ? Number(row.shipped_quantity) : (row.shippedQuantity != null ? Number(row.shippedQuantity) : 0);
const isPaid = Boolean(row.is_paid ?? row.isPaid);
const isShipped = Boolean(row.is_shipped ?? row.isShipped);
const createdAt = row.created_at ?? row.createdAt ?? null;
return {
id,
manifest_id: id,
number: num,
retoure_number: num,
date: dt,
retoure_date: dt,
entityId,
entity_id: entityId,
customerName,
customer_name: customerName,
positions,
grossTotal,
gross_total: grossTotal,
paidTotal,
paid_total: paidTotal,
orderedQuantity,
ordered_quantity: orderedQuantity,
shippedQuantity,
shipped_quantity: shippedQuantity,
isPaid,
is_paid: isPaid,
isShipped,
is_shipped: isShipped,
createdAt,
created_at: createdAt,
lines: row.lines ?? [],
files: row.files ?? [],
shipments: row.shipments ?? [],
payments: row.payments ?? [],
};
}
/**
* Customer Returns / Retouren (manifest type = retoure).
*/
export const retoure = {
/**
* GET /api/retoure
* Query params: q, from, to, isPaid, isShipped, page, pageSize, offset, limit, entityId
* → { retoures: RetoureSummary[], total: number, unfilteredTotal: number }
*/
// #region GET /api/retoure — list
async list({
q,
search,
from,
to,
isPaid,
isShipped,
onlyUnpaid,
onlyUndelivered,
page,
pageSize,
offset,
limit,
entityId,
seekMonths,
} = {}) {
const params = new URLSearchParams();
const query = q || search;
if (query && String(query).trim()) {
params.set('q', String(query).trim());
params.set('search', String(query).trim());
}
if (from) params.set('from', String(from));
if (to) params.set('to', String(to));
if (isPaid !== undefined && isPaid !== null) {
params.set('isPaid', String(isPaid));
} else if (onlyUnpaid === true || onlyUnpaid === 'true') {
params.set('isPaid', 'false');
}
if (isShipped !== undefined && isShipped !== null) {
params.set('isShipped', String(isShipped));
} else if (onlyUndelivered === true || onlyUndelivered === 'true') {
params.set('isShipped', 'false');
}
if (page != null) params.set('page', String(page));
if (pageSize != null) params.set('pageSize', String(pageSize));
if (offset != null) params.set('offset', String(offset));
if (limit != null) params.set('limit', String(limit));
if (entityId != null) params.set('entityId', String(entityId));
if (seekMonths != null && Number(seekMonths) < 0) {
params.set('seekMonths', String(Math.floor(Number(seekMonths))));
}
const qs = params.toString();
const res = await http(`/api/retoure${qs ? `?${qs}` : ''}`);
const rawList = res?.retoures ?? res?.summaries ?? res?.items ?? (Array.isArray(res) ? res : []);
const items = rawList.map(normalizeRetoureSummary);
const total = Number(res?.total ?? res?.count ?? items.length);
const unfilteredTotal = res?.unfilteredTotal != null ? Number(res.unfilteredTotal) : total;
return {
retoures: items,
summaries: items,
items,
total,
unfilteredTotal,
raw: res,
};
},
// #endregion
/** GET /api/retoure/:id → { retoure: Retoure } */
// #region GET /api/retoure/:id — get
async get(id) {
const res = await http(`/api/retoure/${id}`);
if (res && !res.retoure && (res.id != null || res.manifest_id != null)) {
return { retoure: res };
}
return res;
},
// #endregion
/**
* POST /api/retoure
* Body: { number?, date, entityId?, externalNumber?, lines }
* → 201 { retoure: Retoure }
*/
// #region POST /api/retoure — create
async create(body) {
const res = await http('/api/retoure', { method: 'POST', body });
if (res && !res.retoure && (res.id != null || res.manifest_id != null)) {
return { retoure: res };
}
return res;
},
// #endregion
/**
* PUT /api/retoure/:id
* Body: { number?, date?, entityId?, externalNumber?, lines? }
* → 200 { retoure: Retoure }
*/
// #region PUT /api/retoure/:id — update
async update(id, body) {
const res = await http(`/api/retoure/${id}`, { method: 'PUT', body });
if (res && !res.retoure && (res.id != null || res.manifest_id != null)) {
return { retoure: res };
}
return res;
},
// #endregion
/** DELETE /api/retoure/:id → 204 */
// #region DELETE /api/retoure/:id — delete
delete(id) {
return http(`/api/retoure/${id}`, { method: 'DELETE' });
},
// #endregion
/**
* POST /api/retoure/:id/shipment
* Creates return shipment.
* Body: { date?, externalNumber?, lines?: Array<{ sku?: string, orderLineId?: number, amount?: number }>, shipping?: { carrierId, type, state, warehouseId } }
* → 201 { shipment: Shipment }
*/
// #region POST /api/retoure/:id/shipment — createShipment
createShipment(id, body = {}) {
return http(`/api/retoure/${id}/shipment`, { method: 'POST', body });
},
// #endregion
};