const db = require('../config/dbproc.js'); const Adapter = require('./dbadapter.js'); class CurrencyAdapter extends Adapter { constructor() { super(); } async queryCurrencyList(req, callback) { var apires = this.getApiResultDefined(); try { let limit = req.query.limit; let offset = req.query.offset; let keyword = req.query.keyword ?? ''; let qryBase = "select _idx, name, currency, symbol, rate from tbl_currency "; qryBase += "where isdeleted=0 and (name like '%" + keyword + "%' or currency like '%" + keyword + "%') "; // If no pagination params, return all records directly if (!limit || !offset) { db.query(qryBase + "order by currency asc", [], function (err, result, fields) { if (err) { apires.meta['message'] = err.toString(); apires.meta['code'] = 500; callback('err', apires); } else { apires.success = true; apires.data = JSON.parse(JSON.stringify(result)); callback(null, apires); } }); return; } db.query(qryBase + "order by currency asc", [], function (err, result, fields) { if (err) { apires.meta['message'] = err.toString(); apires.meta['code'] = 500; callback('err', apires); } else { if (result.length > 0) { let pagination = result.length / limit; if (!Number.isInteger(pagination)) { pagination = (Math.floor(result.length / limit)) + 1; } apires.success = true; apires.data.push({ "totalpage": pagination, "totalrows": result.length }); let qryPage = qryBase + "order by currency asc limit " + offset + ", " + limit; db.query(qryPage, [], function (err2, result2, fields2) { if (err2) { apires.meta['message'] = err2.toString(); apires.meta['code'] = 500; callback('err', apires); } else { apires.data.push({ "results": JSON.parse(JSON.stringify(result2)) }); callback(null, apires); } }); } else { apires.meta.code = 200; apires.meta.message = "Record Not Found"; callback(null, apires); } } }); } catch (err) { apires.meta.code = 500; apires.meta.message = err.toString(); callback('error', apires); } } async queryCurrencyDetail(req, callback) { var apires = this.getApiResultDefined(); try { let id = req.params.id; let qry = "select _idx, name, currency, symbol, rate, isdeleted, iby, idt, uby, udt from tbl_currency where _idx='" + id + "' and isdeleted=0"; db.query(qry, [], function (err, result, fields) { if (err) { apires.meta['message'] = err.toString(); apires.meta['code'] = 500; callback('err', apires); } else { if (result.length > 0) { apires.success = true; apires.data.push({ "results": JSON.parse(JSON.stringify(result)) }); callback(null, apires); } else { apires.meta.code = 200; apires.meta.message = "Record Not Found"; callback(null, apires); } } }); } catch (err) { apires.meta.code = 500; apires.meta.message = err.toString(); callback('error', apires); } } async queryCurrencyHistory(req, callback) { var apires = this.getApiResultDefined(); try { let id = req.params.id; // get currency_code first, then fetch log let qryCode = "select currency from tbl_currency where _idx='" + id + "'"; db.query(qryCode, [], function (err, result, fields) { if (err) { apires.meta['message'] = err.toString(); apires.meta['code'] = 500; callback('err', apires); } else { if (result.length === 0) { apires.meta.code = 200; apires.meta.message = "Record Not Found"; callback(null, apires); return; } let currencyCode = result[0].currency; let qryLog = "select _idx, currency_code, old_rate, new_rate, source, remark, iby, idt from tbl_currency_log where currency_code='" + currencyCode + "' order by idt desc"; db.query(qryLog, [], function (err2, result2, fields2) { if (err2) { apires.meta['message'] = err2.toString(); apires.meta['code'] = 500; callback('err', apires); } else { apires.success = true; apires.data.push({ "results": JSON.parse(JSON.stringify(result2)) }); callback(null, apires); } }); } }); } catch (err) { apires.meta.code = 500; apires.meta.message = err.toString(); callback('error', apires); } } async queryCreateCurrency(req, callback) { var apires = this.getApiResultDefined(); try { let name = req.body.name; let currency = req.body.currency; let symbol = req.body.symbol; let rate = req.body.rate; let nik = req.nik; let qry = "insert into tbl_currency set "; qry += "name='" + name + "',"; qry += "currency='" + currency + "',"; qry += "symbol='" + symbol + "',"; qry += "rate='" + rate + "',"; qry += "isdeleted=0,"; qry += "iby='" + nik + "',idt=now()"; db.query(qry, [], function (err, result, fields) { if (err) { apires.meta['message'] = err.toString(); apires.meta['code'] = 500; callback('err', apires); } else { apires.success = true; apires.meta.message = "Saved Success"; apires.data = JSON.parse(JSON.stringify(result)); callback(null, apires); } }); } catch (err) { apires.meta.code = 500; apires.meta.message = err.toString(); callback('error', apires); } } async queryUpdateCurrency(req, callback) { var apires = this.getApiResultDefined(); try { let id = req.params.id; let name = req.body.name; let currency = req.body.currency; let symbol = req.body.symbol; let newRate = req.body.rate; let nik = req.nik; // fetch current rate to detect change let qryOld = "select rate, currency from tbl_currency where _idx='" + id + "' and isdeleted=0"; db.query(qryOld, [], function (err, oldResult, fields) { if (err) { apires.meta['message'] = err.toString(); apires.meta['code'] = 500; callback('err', apires); return; } if (oldResult.length === 0) { apires.meta.code = 200; apires.meta.message = "Record Not Found"; callback(null, apires); return; } let oldRate = oldResult[0].rate; let currencyCode = oldResult[0].currency; let rateChanged = parseFloat(oldRate) !== parseFloat(newRate); let qryUpdate = "update tbl_currency set "; qryUpdate += "name='" + name + "',"; qryUpdate += "currency='" + currency + "',"; qryUpdate += "symbol='" + symbol + "',"; qryUpdate += "rate='" + newRate + "',"; qryUpdate += "uby='" + nik + "',udt=now() "; qryUpdate += "where _idx='" + id + "'"; db.query(qryUpdate, [], function (err2, result2, fields2) { if (err2) { apires.meta['message'] = err2.toString(); apires.meta['code'] = 500; callback('err', apires); return; } if (!rateChanged) { apires.success = true; apires.meta.message = "Updated Success"; apires.data = JSON.parse(JSON.stringify(result2)); callback(null, apires); return; } // log the rate change let qryLog = "insert into tbl_currency_log set "; qryLog += "currency_code='" + currencyCode + "',"; qryLog += "old_rate='" + oldRate + "',"; qryLog += "new_rate='" + newRate + "',"; qryLog += "source='manual',"; qryLog += "iby='" + nik + "',idt=now()"; db.query(qryLog, [], function (err3, result3, fields3) { if (err3) { apires.meta['message'] = err3.toString(); apires.meta['code'] = 500; callback('err', apires); } else { apires.success = true; apires.meta.message = "Updated Success"; apires.data = JSON.parse(JSON.stringify(result2)); callback(null, apires); } }); }); }); } catch (err) { apires.meta.code = 500; apires.meta.message = err.toString(); callback('error', apires); } } async queryDeleteCurrency(req, callback) { var apires = this.getApiResultDefined(); try { let id = req.params.id; let nik = req.nik; let qry = "update tbl_currency set isdeleted=1,dby='" + nik + "',ddt=now() where _idx='" + id + "'"; db.query(qry, [], function (err, result, fields) { if (err) { apires.meta['message'] = err.toString(); apires.meta['code'] = 500; callback('err', apires); } else { apires.success = true; apires.meta.message = "Deleted Success"; apires.data = JSON.parse(JSON.stringify(result)); callback(null, apires); } }); } catch (err) { apires.meta.code = 500; apires.meta.message = err.toString(); callback('error', apires); } } // fetch rates for two currency IDs — used for cross-currency conversion queryCurrencyRates(fromId, toId, callback) { var apires = this.getApiResultDefined(); let qry = "select _idx, rate from tbl_currency where _idx in ('" + fromId + "','" + toId + "') and isdeleted=0"; db.query(qry, [], function (err, result, fields) { if (err) { callback(err, null); return; } var rates = {}; result.forEach(function (row) { rates[row._idx] = parseFloat(row.rate); }); if (rates[fromId] === undefined || rates[toId] === undefined) { callback(new Error('Currency not found'), null); return; } callback(null, { from: rates[fromId], to: rates[toId] }); }); } // convert amount from one currency to another using USD as pivot convertAmount(amount, rateFrom, rateTo, callback) { if (!rateTo || rateTo === 0) { callback(new Error('Invalid target rate: rate cannot be zero'), null); return; } callback(null, parseFloat(amount) * (rateFrom / rateTo)); } } module.exports = CurrencyAdapter;