Link receipts to pending purchase approval
All checks were successful
Build and Deploy / build-and-deploy (push) Successful in 2m44s
All checks were successful
Build and Deploy / build-and-deploy (push) Successful in 2m44s
This commit is contained in:
@@ -46,6 +46,9 @@ const mapReceipt = (row) => ({
|
||||
invoice: row.invoice || '',
|
||||
notes: row.notes || '',
|
||||
status: row.status,
|
||||
purchaseOrderId: row.purchase_order_id === null || row.purchase_order_id === undefined ? null : Number(row.purchase_order_id),
|
||||
purchaseOrderNumber: row.purchase_order_number || '',
|
||||
purchaseOrderStatus: row.purchase_order_status || '',
|
||||
createdAt: row.created_at,
|
||||
updatedAt: row.updated_at,
|
||||
approvedAt: row.approved_at
|
||||
@@ -119,7 +122,7 @@ const mapMaterialDetails = (row) => ({
|
||||
updatedAt: row.updated_at
|
||||
});
|
||||
|
||||
const PURCHASE_ORDER_STATUSES = new Set(['draft', 'sent', 'approved', 'received', 'canceled']);
|
||||
const PURCHASE_ORDER_STATUSES = new Set(['draft', 'pending_financial', 'sent', 'approved', 'received', 'canceled']);
|
||||
|
||||
const mapPurchaseOrder = (row) => ({
|
||||
id: row.id,
|
||||
@@ -148,9 +151,12 @@ const createValidationError = (message) => {
|
||||
|
||||
const listReceipts = async () => {
|
||||
const result = await pool.query(`
|
||||
SELECT id, category, product, quantity, unit, supplier, invoice, notes, status, created_at, updated_at, approved_at
|
||||
FROM supply_receipts
|
||||
ORDER BY created_at DESC, id DESC
|
||||
SELECT receipt.id, receipt.category, receipt.product, receipt.quantity, receipt.unit, receipt.supplier, receipt.invoice,
|
||||
receipt.notes, receipt.status, receipt.purchase_order_id, receipt.created_at, receipt.updated_at, receipt.approved_at,
|
||||
purchase_order.number AS purchase_order_number, purchase_order.status AS purchase_order_status
|
||||
FROM supply_receipts receipt
|
||||
LEFT JOIN supply_purchase_orders purchase_order ON purchase_order.id = receipt.purchase_order_id
|
||||
ORDER BY receipt.created_at DESC, receipt.id DESC
|
||||
`);
|
||||
return result.rows.map(mapReceipt);
|
||||
};
|
||||
@@ -930,13 +936,16 @@ const createReceipt = async (payload) => {
|
||||
if (!product) throw createValidationError('Produto ou material é obrigatório.');
|
||||
if (!quantity) throw createValidationError('Quantidade deve ser maior que zero.');
|
||||
|
||||
const result = await pool.query(`
|
||||
const client = await pool.connect();
|
||||
try {
|
||||
await client.query('BEGIN');
|
||||
const result = await client.query(`
|
||||
INSERT INTO supply_receipts (
|
||||
category, product, quantity, unit, supplier, invoice, notes, status, updated_at
|
||||
)
|
||||
VALUES ($1, $2, $3, $4, $5, $6, $7, 'pending', CURRENT_TIMESTAMP)
|
||||
RETURNING id, category, product, quantity, unit, supplier, invoice, notes, status, created_at, updated_at, approved_at
|
||||
`, [
|
||||
`, [
|
||||
category,
|
||||
product,
|
||||
quantity,
|
||||
@@ -944,9 +953,31 @@ const createReceipt = async (payload) => {
|
||||
normalizeText(payload.supplier) || null,
|
||||
normalizeText(payload.invoice) || null,
|
||||
normalizeText(payload.notes) || null
|
||||
]);
|
||||
|
||||
return mapReceipt(result.rows[0]);
|
||||
]);
|
||||
const receipt = result.rows[0];
|
||||
const orderResult = await client.query(`
|
||||
INSERT INTO supply_purchase_orders (supplier, status, notes, updated_at)
|
||||
VALUES ($1, 'pending_financial', $2, CURRENT_TIMESTAMP)
|
||||
RETURNING id;
|
||||
`, [
|
||||
normalizeText(payload.supplier) || 'Sem fornecedor',
|
||||
`Gerada automaticamente pelo recebimento #${receipt.id}${receipt.invoice ? ` · NF ${receipt.invoice}` : ''}`
|
||||
]);
|
||||
const purchaseOrderId = orderResult.rows[0].id;
|
||||
await client.query(`UPDATE supply_purchase_orders SET number = $1 WHERE id = $2;`, [`OC-${String(purchaseOrderId).padStart(5, '0')}`, purchaseOrderId]);
|
||||
await client.query(`INSERT INTO supply_purchase_order_items (purchase_order_id, material, quantity, unit) VALUES ($1, $2, $3, $4);`, [purchaseOrderId, receipt.product, receipt.quantity, receipt.unit]);
|
||||
const linkedReceipt = await client.query(`
|
||||
UPDATE supply_receipts SET purchase_order_id = $2, updated_at = CURRENT_TIMESTAMP WHERE id = $1
|
||||
RETURNING id, category, product, quantity, unit, supplier, invoice, notes, status, purchase_order_id, created_at, updated_at, approved_at;
|
||||
`, [receipt.id, purchaseOrderId]);
|
||||
await client.query('COMMIT');
|
||||
return mapReceipt({ ...linkedReceipt.rows[0], purchase_order_number: `OC-${String(purchaseOrderId).padStart(5, '0')}`, purchase_order_status: 'pending_financial' });
|
||||
} catch (error) {
|
||||
await client.query('ROLLBACK');
|
||||
throw error;
|
||||
} finally {
|
||||
client.release();
|
||||
}
|
||||
};
|
||||
|
||||
const approveReceipt = async (id) => {
|
||||
@@ -956,10 +987,13 @@ const approveReceipt = async (id) => {
|
||||
await client.query('BEGIN');
|
||||
|
||||
const receiptResult = await client.query(`
|
||||
SELECT id, category, product, quantity, unit, supplier, invoice, notes, status, created_at, updated_at, approved_at
|
||||
FROM supply_receipts
|
||||
WHERE id = $1
|
||||
FOR UPDATE
|
||||
SELECT receipt.id, receipt.category, receipt.product, receipt.quantity, receipt.unit, receipt.supplier, receipt.invoice,
|
||||
receipt.notes, receipt.status, receipt.purchase_order_id, receipt.created_at, receipt.updated_at, receipt.approved_at,
|
||||
purchase_order.number AS purchase_order_number, purchase_order.status AS purchase_order_status
|
||||
FROM supply_receipts receipt
|
||||
LEFT JOIN supply_purchase_orders purchase_order ON purchase_order.id = receipt.purchase_order_id
|
||||
WHERE receipt.id = $1
|
||||
FOR UPDATE OF receipt
|
||||
`, [id]);
|
||||
|
||||
if (!receiptResult.rowCount) {
|
||||
@@ -972,13 +1006,17 @@ const approveReceipt = async (id) => {
|
||||
return mapReceipt(receipt);
|
||||
}
|
||||
|
||||
if (receipt.purchase_order_id && !['approved', 'received'].includes(receipt.purchase_order_status)) {
|
||||
throw createValidationError(`A ${receipt.purchase_order_number || 'OC vinculada'} ainda aguarda aprovação financeira.`);
|
||||
}
|
||||
|
||||
const updatedReceiptResult = await client.query(`
|
||||
UPDATE supply_receipts
|
||||
SET status = 'approved',
|
||||
approved_at = CURRENT_TIMESTAMP,
|
||||
updated_at = CURRENT_TIMESTAMP
|
||||
WHERE id = $1
|
||||
RETURNING id, category, product, quantity, unit, supplier, invoice, notes, status, created_at, updated_at, approved_at
|
||||
RETURNING id, category, product, quantity, unit, supplier, invoice, notes, status, purchase_order_id, created_at, updated_at, approved_at
|
||||
`, [id]);
|
||||
|
||||
const lotResult = await client.query(`
|
||||
@@ -1012,8 +1050,12 @@ const approveReceipt = async (id) => {
|
||||
`Recebimento aprovado${receipt.invoice ? ` · NF ${receipt.invoice}` : ''}`
|
||||
]);
|
||||
|
||||
if (receipt.purchase_order_id) {
|
||||
await client.query(`UPDATE supply_purchase_orders SET status = 'received', updated_at = CURRENT_TIMESTAMP WHERE id = $1 AND status = 'approved';`, [receipt.purchase_order_id]);
|
||||
}
|
||||
|
||||
await client.query('COMMIT');
|
||||
return mapReceipt(updatedReceiptResult.rows[0]);
|
||||
return mapReceipt({ ...updatedReceiptResult.rows[0], purchase_order_number: receipt.purchase_order_number, purchase_order_status: receipt.purchase_order_id ? 'received' : '' });
|
||||
} catch (error) {
|
||||
await client.query('ROLLBACK');
|
||||
throw error;
|
||||
|
||||
Reference in New Issue
Block a user