diff --git a/apps/api/src/app/orders/orders.service.ts b/apps/api/src/app/orders/orders.service.ts index d54025f..a64fd22 100644 --- a/apps/api/src/app/orders/orders.service.ts +++ b/apps/api/src/app/orders/orders.service.ts @@ -1022,14 +1022,31 @@ export class OrdersService { const grupoRows = prisma && prodIds.length > 0 ? await prisma.$queryRawUnsafe< - { id_erp: number; cod_grupo: number | null; cod_subgrupo: number | null }[] + { + id_erp: number; + cod_grupo: number | null; + cod_subgrupo: number | null; + peso_liquido: string | null; + vol_m3: string | null; + }[] >( - `SELECT id_erp, cod_grupo, cod_subgrupo FROM vw_produtos + `SELECT id_erp, cod_grupo, cod_subgrupo, peso_liquido::text, vol_m3::text + FROM vw_produtos WHERE id_empresa = ${idMatriz} AND id_erp IN (${prodIds.join(',')})`, ) : []; const grupoMap = new Map(grupoRows.map((g) => [Number(g.id_erp), g])); + // Peso total (kg) e cubagem (m3) do pedido: soma de qtd x peso/vol do produto + let pesoTotal = 0; + let m3Total = 0; + for (const it of o.itens) { + const prod = grupoMap.get(it.idProduto); + const qtd = Number(it.qtd); + pesoTotal += qtd * Number(prod?.peso_liquido ?? 0); + m3Total += qtd * Number(prod?.vol_m3 ?? 0); + } + return { id: o.id, numPedSar: o.numPedSar, @@ -1042,6 +1059,8 @@ export class OrdersService { dtPedido: o.dtPedido.toISOString(), idPauta: o.idPauta, codFormapag: o.codFormapag, + pesoTotal: pesoTotal.toFixed(3), + m3Total: m3Total.toFixed(4), total: decimalToString(o.total), descontoPerc: decimalToString(o.descontoPerc), obs: o.obs, @@ -1132,6 +1151,8 @@ export class OrdersService { preco_unitario: string; desconto_perc: string; total: string; + peso_liquido: string | null; + vol_m3: string | null; } const vendedorFilter = @@ -1164,7 +1185,8 @@ export class OrdersService { SELECT ei.ordem, ei.id_produto, TRIM(p.codigo) AS codigo, TRIM(p.descricao) AS descricao, ei.qtd::text, ei.preco_unitario::text, - ei.desconto_perc::text, ei.total::text + ei.desconto_perc::text, ei.total::text, + p.peso_liquido::text AS peso_liquido, p.vol_m3::text AS vol_m3 FROM vw_peditens_erp ei LEFT JOIN vw_produtos p ON p.id_erp = ei.id_produto @@ -1177,6 +1199,15 @@ export class OrdersService { if (!headerRows[0]) throw new NotFoundException(`Pedido ERP ${idPedido} não encontrado`); const h = headerRows[0]; + const pesoTotalErp = itemRows.reduce( + (acc, it) => acc + Number(it.qtd) * Number(it.peso_liquido ?? 0), + 0, + ); + const m3TotalErp = itemRows.reduce( + (acc, it) => acc + Number(it.qtd) * Number(it.vol_m3 ?? 0), + 0, + ); + return { id: `erp-${h.id_pedido}`, numPedSar: (h.num_ped_sar ?? '').trim(), @@ -1207,6 +1238,8 @@ export class OrdersService { aprovadoEm: null, motivoRecusa: null, idempotencyKey: null, + pesoTotal: pesoTotalErp.toFixed(3), + m3Total: m3TotalErp.toFixed(4), itens: itemRows.map((it) => ({ id: `${idPedido}-${it.ordem}`, idProduto: Number(it.id_produto), diff --git a/apps/web/src/cockpits/rep/OrderPrintPage.tsx b/apps/web/src/cockpits/rep/OrderPrintPage.tsx index 0f5de7c..074863b 100644 --- a/apps/web/src/cockpits/rep/OrderPrintPage.tsx +++ b/apps/web/src/cockpits/rep/OrderPrintPage.tsx @@ -381,7 +381,30 @@ export function OrderPrintPage() { {/* ── Totais ──────────────────────────────────────────────────────── */} -
+
+ {/* Peso e cubagem do pedido (logística/frete) */} +
+ {Number(order.pesoTotal ?? 0) > 0 && ( +
+ Peso total:{' '} + {Number(order.pesoTotal).toLocaleString('pt-BR', { maximumFractionDigits: 2 })} kg +
+ )} + {Number(order.m3Total ?? 0) > 0 && ( +
+ Volume:{' '} + {Number(order.m3Total).toLocaleString('pt-BR', { maximumFractionDigits: 3 })} m³ +
+ )} +
{Number(order.totalIpi) > 0 && } diff --git a/libs/shared/api-interface/src/lib/order.contract.ts b/libs/shared/api-interface/src/lib/order.contract.ts index 789caa8..2f1e63d 100644 --- a/libs/shared/api-interface/src/lib/order.contract.ts +++ b/libs/shared/api-interface/src/lib/order.contract.ts @@ -96,6 +96,9 @@ export const PedidoDetailSchema = PedidoSummarySchema.extend({ // Pauta/forma de pagamento do pedido SAR — edição do orçamento pré-carrega idPauta: z.number().int().nullable().optional(), codFormapag: z.number().int().nullable().optional(), + // Peso total (kg) e cubagem (m3) — qtd x peso_liquido/vol_m3 de vw_produtos + pesoTotal: z.string().optional(), + m3Total: z.string().optional(), aprovadoPor: z.number().int().nullable(), aprovadoEm: z.iso.datetime().nullable(), motivoRecusa: z.string().nullable(), diff --git a/scripts/sar-erp-schema.sql b/scripts/sar-erp-schema.sql index 8c2854f..1795d85 100644 --- a/scripts/sar-erp-schema.sql +++ b/scripts/sar-erp-schema.sql @@ -289,7 +289,9 @@ SELECT COALESCE(p.preco_promocional, 0) AS preco_promocional, COALESCE(p.tx_desc_lote, 0) AS tx_desc_lote, p.lista_pauta, - CASE WHEN p.dt_atual > sub.da THEN p.dt_atual ELSE sub.da END AS dt_atual + CASE WHEN p.dt_atual > sub.da THEN p.dt_atual ELSE sub.da END AS dt_atual, + -- vol_m3 no FIM: CREATE OR REPLACE VIEW so aceita coluna nova apos as existentes + COALESCE(p.vol_m3, 0) AS vol_m3 FROM gestao.produto p LEFT JOIN gestao.grupo grp ON grp.codigo = p.cod_grupo AND grp.id_empresa = p.id_empresa LEFT JOIN gestao.grupo sub ON sub.codigo = p.cod_subgrupo AND sub.id_empresa = p.id_empresa