Fix monthly actuals: allow negative values and fix save/reconcile error
- Remove min={0} from NumberInput to allow negative actuals (refunds/corrections)
- Fix post() in journal-entries service: use id param directly instead of
RETURNING result which returns [rows, count] in TypeORM QueryRunner
- Handle negative amounts in saveActuals(): negative expense credits the
expense account, negative income debits the income account
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -140,11 +140,11 @@ export class JournalEntriesService {
|
||||
);
|
||||
}
|
||||
|
||||
const result = await this.tenant.query(
|
||||
`UPDATE journal_entries SET is_posted = true, posted_by = $1, posted_at = NOW() WHERE id = $2 RETURNING *`,
|
||||
await this.tenant.query(
|
||||
`UPDATE journal_entries SET is_posted = true, posted_by = $1, posted_at = NOW() WHERE id = $2`,
|
||||
[userId, id],
|
||||
);
|
||||
return this.findOne(result[0].id);
|
||||
return this.findOne(id);
|
||||
}
|
||||
|
||||
async void(id: string, userId: string, reason: string) {
|
||||
|
||||
@@ -127,25 +127,28 @@ export class MonthlyActualsService {
|
||||
for (const line of filteredLines) {
|
||||
const acctType = accountTypeMap.get(line.accountId);
|
||||
if (!acctType) continue;
|
||||
const abs = Math.abs(line.amount);
|
||||
|
||||
if (acctType === 'expense') {
|
||||
// Expense: debit expense account, credit cash
|
||||
jeLines.push({
|
||||
accountId: line.accountId,
|
||||
debit: Math.abs(line.amount),
|
||||
credit: 0,
|
||||
memo: `${monthLabel} actual`,
|
||||
});
|
||||
totalCashCredit += Math.abs(line.amount);
|
||||
if (line.amount > 0) {
|
||||
// Normal expense: debit expense, credit cash
|
||||
jeLines.push({ accountId: line.accountId, debit: abs, credit: 0, memo: `${monthLabel} actual` });
|
||||
totalCashCredit += abs;
|
||||
} else {
|
||||
// Negative expense (refund/correction): credit expense, debit cash
|
||||
jeLines.push({ accountId: line.accountId, debit: 0, credit: abs, memo: `${monthLabel} actual (correction)` });
|
||||
totalCashDebit += abs;
|
||||
}
|
||||
} else if (acctType === 'income') {
|
||||
// Income: credit income account, debit cash
|
||||
jeLines.push({
|
||||
accountId: line.accountId,
|
||||
debit: 0,
|
||||
credit: Math.abs(line.amount),
|
||||
memo: `${monthLabel} actual`,
|
||||
});
|
||||
totalCashDebit += Math.abs(line.amount);
|
||||
if (line.amount > 0) {
|
||||
// Normal income: credit income, debit cash
|
||||
jeLines.push({ accountId: line.accountId, debit: 0, credit: abs, memo: `${monthLabel} actual` });
|
||||
totalCashDebit += abs;
|
||||
} else {
|
||||
// Negative income (correction): debit income, credit cash
|
||||
jeLines.push({ accountId: line.accountId, debit: abs, credit: 0, memo: `${monthLabel} actual (correction)` });
|
||||
totalCashCredit += abs;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -203,7 +203,7 @@ export function MonthlyActualsPage() {
|
||||
size="xs"
|
||||
hideControls
|
||||
decimalScale={2}
|
||||
min={0}
|
||||
allowNegative
|
||||
styles={{ input: { textAlign: 'right', fontFamily: 'monospace' } }}
|
||||
/>
|
||||
</Table.Td>
|
||||
|
||||
Reference in New Issue
Block a user