Files
sap-erp/services/autoclaveRejectionStore.js
T
John 69b4e68baf
SAP-ERP Portal CI/CD / build (push) Failing after 5m20s
first commit
2026-09-23 17:31:02 +05:30

91 lines
3.4 KiB
JavaScript

// services/autoclaveRejectionStore.js
// Stores the "Autoclave Rejection" counts captured on a Receipt from
// Production for FG items (see routes/sap.js POST /receipt-production and
// public/receipt-production.html). This data is PURELY informational — it is
// NOT posted to SAP and has no effect on any inventory/production quantity.
// It lives in the app's own database (APP_SQL_*), keyed by the SAP receipt
// document, and is only ever written AFTER the SAP receipt posts successfully.
'use strict';
const sql = require('mssql');
const TABLE = `[dbo].[ZFG_AUTOCLAVE_REJECTIONS]`;
let _conn = null;
async function getConn() {
if (_conn) return _conn;
_conn = await sql.connect({
server: process.env.APP_SQL_HOST,
port: parseInt(process.env.APP_SQL_PORT),
user: process.env.APP_SQL_USER,
password: process.env.APP_SQL_PASSWORD,
database: process.env.APP_SQL_DATABASE,
options: { encrypt: true, trustServerCertificate: true },
});
return _conn;
}
async function exec(sqlQuery, params = []) {
const conn = await getConn();
const request = conn.request();
params.forEach((param, index) => { request.input(`param${index}`, param); });
const replacedSql = sqlQuery.replace(/\?/g, (m, offset, string) => {
const i = (string.slice(0, offset).match(/\?/g) || []).length;
return `@param${i}`;
});
const result = await request.query(replacedSql);
return result.recordset || [];
}
function isAlreadyExists(e) {
const m = (e.message || '').toLowerCase();
return m.includes('already exists') || m.includes('duplicate') || m.includes('existing object') || m.includes('there is already an object');
}
async function bootstrap() {
console.log('[AUTOCLAVE-STORE] Checking table', TABLE, '...');
await exec(`
CREATE TABLE ${TABLE} (
ID INT IDENTITY(1,1) PRIMARY KEY,
ABS_ENTRY INT,
DOC_ENTRY INT,
DOC_NUM NVARCHAR(30),
ITEM_CODE NVARCHAR(60),
BATCH_NUMBER NVARCHAR(60),
ROWS_JSON NVARCHAR(MAX),
TOTAL_REJECTION NVARCHAR(60),
CREATED_BY NVARCHAR(50),
CREATED_NAME NVARCHAR(100),
CREATED_AT DATETIME2,
COMPANY NVARCHAR(60)
)
`).catch(e => {
if (isAlreadyExists(e)) { console.log('[AUTOCLAVE-STORE] Table exists — OK'); }
else throw e;
});
console.log('[AUTOCLAVE-STORE] ✅ Ready');
}
function toTs(iso) { return iso ? iso.replace('T', ' ').replace('Z', '').substring(0, 23) : null; }
// rows: array of numbers (rejection qty per manually-added row).
async function saveRejection({ absEntry, docEntry, docNum, itemCode, batchNumber, rows, company, createdBy, createdByName }) {
const clean = (Array.isArray(rows) ? rows : [])
.map(r => Number(r))
.filter(n => !isNaN(n) && n > 0);
const total = clean.reduce((s, n) => s + n, 0);
await exec(`
INSERT INTO ${TABLE} (
ABS_ENTRY, DOC_ENTRY, DOC_NUM, ITEM_CODE, BATCH_NUMBER, ROWS_JSON,
TOTAL_REJECTION, CREATED_BY, CREATED_NAME, CREATED_AT, COMPANY
) VALUES (?,?,?,?,?,?,?,?,?,?,?)
`, [
absEntry != null ? parseInt(absEntry) : null,
docEntry != null ? parseInt(docEntry) : null,
docNum != null ? String(docNum) : null,
itemCode || '', batchNumber || '', JSON.stringify(clean),
String(total), createdBy || '', createdByName || createdBy || '',
toTs(new Date().toISOString()), company || '',
]);
return { total, count: clean.length };
}
module.exports = { bootstrap, saveRejection };