Updated A LOT
This commit is contained in:
114
server/services/zones.js
Normal file
114
server/services/zones.js
Normal file
@@ -0,0 +1,114 @@
|
||||
const { all, audit, now, one, run } = require('../db');
|
||||
|
||||
let cache = null;
|
||||
|
||||
function clearCache() {
|
||||
cache = null;
|
||||
}
|
||||
|
||||
function lookup() {
|
||||
if (!cache) {
|
||||
cache = {};
|
||||
for (const row of all('SELECT * FROM depreciation_zones')) cache[row.code] = row;
|
||||
}
|
||||
return cache;
|
||||
}
|
||||
|
||||
// Raw row (incl. dates) for the engine; null when unknown or disabled.
|
||||
function getZone(code) {
|
||||
if (!code) return null;
|
||||
const zone = lookup()[code];
|
||||
return zone && zone.enabled ? zone : null;
|
||||
}
|
||||
|
||||
function slugify(value) {
|
||||
return String(value || '').trim().toLowerCase().replace(/[^a-z0-9]+/g, '_').replace(/^_+|_+$/g, '').slice(0, 40);
|
||||
}
|
||||
|
||||
function fromRow(row) {
|
||||
if (!row) return null;
|
||||
return {
|
||||
id: row.id,
|
||||
code: row.code,
|
||||
name: row.name,
|
||||
allowance_percent: row.allowance_percent,
|
||||
pis_start: row.pis_start,
|
||||
pis_end: row.pis_end,
|
||||
real_property_end: row.real_property_end,
|
||||
max_recovery_years: row.max_recovery_years,
|
||||
leasehold_life_years: row.leasehold_life_years,
|
||||
notes: row.notes,
|
||||
enabled: Boolean(row.enabled),
|
||||
asset_count: one('SELECT COUNT(*) AS c FROM assets WHERE special_zone = ?', [row.code]).c
|
||||
};
|
||||
}
|
||||
|
||||
function list() {
|
||||
return all('SELECT * FROM depreciation_zones ORDER BY name').map(fromRow);
|
||||
}
|
||||
|
||||
function normalize(body) {
|
||||
const num = (v) => (v === '' || v === null || v === undefined ? null : Number(v));
|
||||
return {
|
||||
name: String(body.name || '').trim(),
|
||||
allowance_percent: Number(body.allowance_percent) || 0,
|
||||
pis_start: body.pis_start || null,
|
||||
pis_end: body.pis_end || null,
|
||||
real_property_end: body.real_property_end || null,
|
||||
max_recovery_years: num(body.max_recovery_years),
|
||||
leasehold_life_years: num(body.leasehold_life_years),
|
||||
notes: body.notes || null,
|
||||
enabled: body.enabled === false ? 0 : 1
|
||||
};
|
||||
}
|
||||
|
||||
function createZone(body, userId) {
|
||||
const input = normalize(body);
|
||||
if (!input.name) throw Object.assign(new Error('A zone name is required'), { status: 400 });
|
||||
const code = slugify(body.code || input.name);
|
||||
if (!code) throw Object.assign(new Error('A valid zone code is required'), { status: 400 });
|
||||
if (one('SELECT id FROM depreciation_zones WHERE code = ?', [code])) {
|
||||
throw Object.assign(new Error('A zone with that code already exists'), { status: 400 });
|
||||
}
|
||||
const ts = now();
|
||||
run(
|
||||
`INSERT INTO depreciation_zones (code, name, allowance_percent, pis_start, pis_end, real_property_end, max_recovery_years, leasehold_life_years, notes, enabled, created_at, updated_at)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
||||
[code, input.name, input.allowance_percent, input.pis_start, input.pis_end, input.real_property_end, input.max_recovery_years, input.leasehold_life_years, input.notes, input.enabled, ts, ts]
|
||||
);
|
||||
clearCache();
|
||||
audit(userId, 'create', 'depreciation_zone', code, null, input);
|
||||
return fromRow(one('SELECT * FROM depreciation_zones WHERE code = ?', [code]));
|
||||
}
|
||||
|
||||
function updateZone(code, body, userId) {
|
||||
const before = one('SELECT * FROM depreciation_zones WHERE code = ?', [code]);
|
||||
if (!before) return null;
|
||||
const input = normalize({ ...before, ...body, enabled: body.enabled === undefined ? Boolean(before.enabled) : body.enabled });
|
||||
run(
|
||||
`UPDATE depreciation_zones SET name = ?, allowance_percent = ?, pis_start = ?, pis_end = ?, real_property_end = ?,
|
||||
max_recovery_years = ?, leasehold_life_years = ?, notes = ?, enabled = ?, updated_at = ? WHERE code = ?`,
|
||||
[input.name, input.allowance_percent, input.pis_start, input.pis_end, input.real_property_end, input.max_recovery_years, input.leasehold_life_years, input.notes, input.enabled, now(), code]
|
||||
);
|
||||
clearCache();
|
||||
audit(userId, 'update', 'depreciation_zone', code, before, input);
|
||||
return fromRow(one('SELECT * FROM depreciation_zones WHERE code = ?', [code]));
|
||||
}
|
||||
|
||||
function deleteZone(code, userId) {
|
||||
const before = one('SELECT * FROM depreciation_zones WHERE code = ?', [code]);
|
||||
if (!before) return false;
|
||||
run('DELETE FROM depreciation_zones WHERE code = ?', [code]);
|
||||
clearCache();
|
||||
audit(userId, 'delete', 'depreciation_zone', code, before, null);
|
||||
return true;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
clearCache,
|
||||
createZone,
|
||||
deleteZone,
|
||||
getZone,
|
||||
list,
|
||||
updateZone
|
||||
};
|
||||
Reference in New Issue
Block a user