Added Wizard for Month/Year End Close
This commit is contained in:
90
server/db.js
90
server/db.js
@@ -460,9 +460,38 @@ function initialize() {
|
||||
expense_account TEXT,
|
||||
pm_expense_account TEXT,
|
||||
pm_clearing_account TEXT,
|
||||
cwip_account TEXT,
|
||||
gain_account TEXT,
|
||||
loss_account TEXT,
|
||||
proceeds_account TEXT,
|
||||
retained_earnings_account TEXT,
|
||||
updated_at TEXT NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS close_periods (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
entity_id INTEGER REFERENCES entities(id),
|
||||
book_code TEXT NOT NULL,
|
||||
period_type TEXT NOT NULL DEFAULT 'month',
|
||||
fiscal_year INTEGER NOT NULL,
|
||||
period_month INTEGER,
|
||||
status TEXT NOT NULL DEFAULT 'open',
|
||||
steps_json TEXT,
|
||||
reconciliation_json TEXT,
|
||||
totals_json TEXT,
|
||||
notes TEXT,
|
||||
started_by INTEGER REFERENCES users(id),
|
||||
started_at TEXT,
|
||||
closed_by INTEGER REFERENCES users(id),
|
||||
closed_at TEXT,
|
||||
reopened_by INTEGER REFERENCES users(id),
|
||||
reopened_at TEXT,
|
||||
created_at TEXT NOT NULL,
|
||||
updated_at TEXT NOT NULL,
|
||||
UNIQUE(entity_id, book_code, period_type, fiscal_year, period_month)
|
||||
);
|
||||
CREATE INDEX IF NOT EXISTS idx_close_periods_scope ON close_periods (entity_id, book_code, status);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS alerts (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
type TEXT NOT NULL,
|
||||
@@ -847,6 +876,13 @@ function migrate() {
|
||||
rebuildReferenceValuesPerCompany();
|
||||
rebuildAssetTemplatesPerCompany();
|
||||
rebuildPartsPerCompany();
|
||||
// Period close: extra GL posting accounts + per-company capitalization threshold.
|
||||
ensureColumn('gl_account_defaults', 'cwip_account', 'TEXT');
|
||||
ensureColumn('gl_account_defaults', 'gain_account', 'TEXT');
|
||||
ensureColumn('gl_account_defaults', 'loss_account', 'TEXT');
|
||||
ensureColumn('gl_account_defaults', 'proceeds_account', 'TEXT');
|
||||
ensureColumn('gl_account_defaults', 'retained_earnings_account', 'TEXT');
|
||||
ensureColumn('entities', 'capitalization_threshold', 'REAL NOT NULL DEFAULT 0');
|
||||
backfillCompanyScope();
|
||||
}
|
||||
|
||||
@@ -1072,27 +1108,49 @@ function seedReferenceValuesForCompany(entityId) {
|
||||
// The defaults are the fallback accounts the depreciation/PM ledgers post to when an asset doesn't
|
||||
// carry its own. Called during initial seed and when a new company is created.
|
||||
function seedGlAccountsForCompany(entityId) {
|
||||
if (!entityId || one('SELECT id FROM gl_accounts WHERE entity_id = ? LIMIT 1', [entityId])) return;
|
||||
if (!entityId) return;
|
||||
const ts = now();
|
||||
const accounts = [
|
||||
['1500', 'Fixed Assets', 'asset', 'debit', 'Asset cost / basis'],
|
||||
['1590', 'Accumulated Depreciation', 'contra_asset', 'credit', 'Accumulated depreciation (contra-asset)'],
|
||||
['2000', 'Maintenance Clearing', 'liability', 'credit', 'PM/maintenance clearing'],
|
||||
['6400', 'Depreciation Expense', 'expense', 'debit', 'Periodic depreciation expense'],
|
||||
['6450', 'Maintenance Expense', 'expense', 'debit', 'Preventative-maintenance spend']
|
||||
];
|
||||
for (const [code, name, type, normal, description] of accounts) {
|
||||
run(
|
||||
`INSERT OR IGNORE INTO gl_accounts (entity_id, code, name, type, normal_balance, description, active, created_at, updated_at)
|
||||
VALUES (?, ?, ?, ?, ?, ?, 1, ?, ?)`,
|
||||
[entityId, code, name, type, normal, description, ts, ts]
|
||||
);
|
||||
// Seed the starter chart only for a brand-new company, so deliberate later deletions aren't undone.
|
||||
if (!one('SELECT id FROM gl_accounts WHERE entity_id = ? LIMIT 1', [entityId])) {
|
||||
const accounts = [
|
||||
['1010', 'Cash / Proceeds Clearing', 'asset', 'debit', 'Disposal proceeds clearing'],
|
||||
['1500', 'Fixed Assets', 'asset', 'debit', 'Asset cost / basis'],
|
||||
['1590', 'Accumulated Depreciation', 'contra_asset', 'credit', 'Accumulated depreciation (contra-asset)'],
|
||||
['1800', 'Construction in Progress', 'asset', 'debit', 'Capital work-in-progress (CWIP)'],
|
||||
['2000', 'Maintenance Clearing', 'liability', 'credit', 'PM/maintenance clearing'],
|
||||
['3900', 'Retained Earnings', 'equity', 'credit', 'Year-end depreciation roll-forward'],
|
||||
['6400', 'Depreciation Expense', 'expense', 'debit', 'Periodic depreciation expense'],
|
||||
['6450', 'Maintenance Expense', 'expense', 'debit', 'Preventative-maintenance spend'],
|
||||
['7200', 'Gain on Disposal', 'revenue', 'credit', 'Gain on asset disposal'],
|
||||
['7300', 'Loss on Disposal', 'expense', 'debit', 'Loss on asset disposal']
|
||||
];
|
||||
for (const [code, name, type, normal, description] of accounts) {
|
||||
run(
|
||||
`INSERT OR IGNORE INTO gl_accounts (entity_id, code, name, type, normal_balance, description, active, created_at, updated_at)
|
||||
VALUES (?, ?, ?, ?, ?, ?, 1, ?, ?)`,
|
||||
[entityId, code, name, type, normal, description, ts, ts]
|
||||
);
|
||||
}
|
||||
}
|
||||
// Ensure the per-company posting defaults exist; backfill the close-account columns for companies
|
||||
// seeded before the close feature (the ledgers post to these account codes regardless of chart rows).
|
||||
run(
|
||||
`INSERT OR IGNORE INTO gl_account_defaults (entity_id, asset_account, accumulated_account, expense_account, pm_expense_account, pm_clearing_account, updated_at)
|
||||
VALUES (?, '1500', '1590', '6400', '6450', '2000', ?)`,
|
||||
`INSERT OR IGNORE INTO gl_account_defaults
|
||||
(entity_id, asset_account, accumulated_account, expense_account, pm_expense_account, pm_clearing_account,
|
||||
cwip_account, gain_account, loss_account, proceeds_account, retained_earnings_account, updated_at)
|
||||
VALUES (?, '1500', '1590', '6400', '6450', '2000', '1800', '7200', '7300', '1010', '3900', ?)`,
|
||||
[entityId, ts]
|
||||
);
|
||||
run(
|
||||
`UPDATE gl_account_defaults SET
|
||||
cwip_account = COALESCE(cwip_account, '1800'),
|
||||
gain_account = COALESCE(gain_account, '7200'),
|
||||
loss_account = COALESCE(loss_account, '7300'),
|
||||
proceeds_account = COALESCE(proceeds_account, '1010'),
|
||||
retained_earnings_account = COALESCE(retained_earnings_account, '3900')
|
||||
WHERE entity_id = ?`,
|
||||
[entityId]
|
||||
);
|
||||
}
|
||||
|
||||
function seed() {
|
||||
|
||||
Reference in New Issue
Block a user