Skip to content

Conversation

@TaprootFreak
Copy link
Collaborator

Summary

  • Add AccountingModule with balance sheet calculation for year-end accounting
  • Add /accounting/balance-sheet/:iban/:year endpoint (Admin/Compliance only)
  • Add yearlyBalances JSON field to Bank entity for opening/closing balances
  • Calculate income (CRDT transactions) and expenses (DBIT transactions) from bank_tx
  • Validate calculated closing balance against defined closing balance
  • Add sync scripts for local development database

Test plan

  • Test balance sheet endpoint with valid IBAN and year
  • Verify income/expenses calculation matches bank_tx data
  • Verify validation message when closing balance matches/mismatches
  • Test with different years (2024, 2025)


if (!Array.isArray(prodData) || prodData.length === 0) {
console.log('No more data to fetch.');
hasMore = false;

function executeSql(sql) {
try {
execSync(`docker exec dfx-mssql /opt/mssql-tools18/bin/sqlcmd -U sa -P 'LocalDev2026@SQL' -d dfx -C -Q "${sql.replace(/"/g, '\\"')}"`, {

Check failure

Code scanning / CodeQL

Uncontrolled command line Critical

This command line depends on a
user-provided value
.

Copilot Autofix

AI 2 days ago

In general, the fix is to avoid passing a single concatenated command string to child_process.execSync, and instead use execFileSync with an explicit executable and an array of arguments. This bypasses the shell, so even if sql contains characters like quotes, semicolons, or backticks, they are treated as data for sqlcmd rather than being interpreted by the shell. We should also avoid manual quote-escaping for shell purposes (sql.replace(/"/g, '\\"')), because shell escaping is no longer needed once we remove the shell.

Concretely, in scripts/sync-bank-tx.js:

  • Add execFileSync to the child_process import.
  • Rewrite executeSql so it calls execFileSync('docker', [...]) instead of execSync with a command string. The arguments array will be:
    • ['exec', 'dfx-mssql', '/opt/mssql-tools18/bin/sqlcmd', '-U', 'sa', '-P', 'LocalDev2026@SQL', '-d', 'dfx', '-C', '-Q', sql]
  • Remove the sql.replace(/"/g, '\\"') since shell quoting is no longer required; the raw sql string can be passed directly as a single argument.
  • Keep the existing options stdio: 'pipe' and maxBuffer to preserve behavior.

No other parts of the file need changing; the rest of the script can continue building SQL as before, but the command execution is now shell-free.

Suggested changeset 1
scripts/sync-bank-tx.js

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/scripts/sync-bank-tx.js b/scripts/sync-bank-tx.js
--- a/scripts/sync-bank-tx.js
+++ b/scripts/sync-bank-tx.js
@@ -6,7 +6,7 @@
  */
 
 const https = require('https');
-const { execSync } = require('child_process');
+const { execSync, execFileSync } = require('child_process');
 const path = require('path');
 require('dotenv').config({ path: path.join(__dirname, '.env.db-debug') });
 
@@ -91,7 +91,16 @@
 
 function executeSql(sql) {
   try {
-    execSync(`docker exec dfx-mssql /opt/mssql-tools18/bin/sqlcmd -U sa -P 'LocalDev2026@SQL' -d dfx -C -Q "${sql.replace(/"/g, '\\"')}"`, {
+    execFileSync('docker', [
+      'exec',
+      'dfx-mssql',
+      '/opt/mssql-tools18/bin/sqlcmd',
+      '-U', 'sa',
+      '-P', 'LocalDev2026@SQL',
+      '-d', 'dfx',
+      '-C',
+      '-Q', sql
+    ], {
       stdio: 'pipe',
       maxBuffer: 50 * 1024 * 1024
     });
EOF
@@ -6,7 +6,7 @@
*/

const https = require('https');
const { execSync } = require('child_process');
const { execSync, execFileSync } = require('child_process');
const path = require('path');
require('dotenv').config({ path: path.join(__dirname, '.env.db-debug') });

@@ -91,7 +91,16 @@

function executeSql(sql) {
try {
execSync(`docker exec dfx-mssql /opt/mssql-tools18/bin/sqlcmd -U sa -P 'LocalDev2026@SQL' -d dfx -C -Q "${sql.replace(/"/g, '\\"')}"`, {
execFileSync('docker', [
'exec',
'dfx-mssql',
'/opt/mssql-tools18/bin/sqlcmd',
'-U', 'sa',
'-P', 'LocalDev2026@SQL',
'-d', 'dfx',
'-C',
'-Q', sql
], {
stdio: 'pipe',
maxBuffer: 50 * 1024 * 1024
});
Copilot is powered by AI and may make mistakes. Always verify output.

function executeSql(sql) {
try {
execSync(`docker exec dfx-mssql /opt/mssql-tools18/bin/sqlcmd -U sa -P 'LocalDev2026@SQL' -d dfx -C -Q "${sql.replace(/"/g, '\\"')}"`, {

Check failure

Code scanning / CodeQL

Incomplete string escaping or encoding High

This does not escape backslash characters in the input.

Copilot Autofix

AI 2 days ago

In general, you should avoid manually escaping characters when building shell commands, and instead either (a) avoid the shell entirely by using execFile/spawn with an argument array, or (b) if you must stay with execSync and a single command string, ensure that all characters that affect the quoting/escaping rules (notably backslash and the quote characters in use) are handled correctly. For our context, using execSync with an argument array is the most reliable fix and preserves existing functionality.

The best fix here is to stop embedding sql into a double‑quoted -Q "..." argument string inside a larger shell‑quoted command. Instead, call docker directly with arguments, and pass the entire sqlcmd invocation (and the sql string) as arguments. Node’s child_process.execSync supports a form where the first argument is the command and the second is an array of arguments; it then handles escaping correctly according to the underlying platform. This means we no longer need sql.replace(...) at all, eliminating the incomplete escaping issue.

Concretely, in scripts/sync-bank-tx.js, update the executeSql function (around line 92–99):

  • Replace the single string command to execSync with a call using the command 'docker' and an array of arguments.
  • Build the argument array equivalent to the original command: ["exec", "dfx-mssql", "/opt/mssql-tools18/bin/sqlcmd", "-U", "sa", "-P", "LocalDev2026@SQL", "-d", "dfx", "-C", "-Q", sql].
  • Remove the sql.replace(/"/g, '\\"') since escaping is now handled by the OS and execSync argument processing.

No new imports are needed; we already import { execSync } from child_process.

Suggested changeset 1
scripts/sync-bank-tx.js

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/scripts/sync-bank-tx.js b/scripts/sync-bank-tx.js
--- a/scripts/sync-bank-tx.js
+++ b/scripts/sync-bank-tx.js
@@ -91,7 +91,16 @@
 
 function executeSql(sql) {
   try {
-    execSync(`docker exec dfx-mssql /opt/mssql-tools18/bin/sqlcmd -U sa -P 'LocalDev2026@SQL' -d dfx -C -Q "${sql.replace(/"/g, '\\"')}"`, {
+    execSync('docker', [
+      'exec',
+      'dfx-mssql',
+      '/opt/mssql-tools18/bin/sqlcmd',
+      '-U', 'sa',
+      '-P', 'LocalDev2026@SQL',
+      '-d', 'dfx',
+      '-C',
+      '-Q', sql
+    ], {
       stdio: 'pipe',
       maxBuffer: 50 * 1024 * 1024
     });
EOF
@@ -91,7 +91,16 @@

function executeSql(sql) {
try {
execSync(`docker exec dfx-mssql /opt/mssql-tools18/bin/sqlcmd -U sa -P 'LocalDev2026@SQL' -d dfx -C -Q "${sql.replace(/"/g, '\\"')}"`, {
execSync('docker', [
'exec',
'dfx-mssql',
'/opt/mssql-tools18/bin/sqlcmd',
'-U', 'sa',
'-P', 'LocalDev2026@SQL',
'-d', 'dfx',
'-C',
'-Q', sql
], {
stdio: 'pipe',
maxBuffer: 50 * 1024 * 1024
});
Copilot is powered by AI and may make mistakes. Always verify output.
@TaprootFreak TaprootFreak force-pushed the feature/accounting-module branch from 3711725 to b4e1987 Compare January 19, 2026 19:08
- Add AccountingModule with balance sheet calculation
- Add /accounting/balance-sheet/:iban/:year endpoint
- Add yearlyBalances field to Bank entity for opening/closing balances
- Calculate income (CRDT) and expenses (DBIT) from bank_tx
- Validate calculated closing against defined closing balance
- Add sync scripts for local development
@TaprootFreak TaprootFreak force-pushed the feature/accounting-module branch from b4e1987 to 3cfeed0 Compare January 19, 2026 19:09
Add historical bank balance data for all banks from 2022-2025:
- Bank Frick EUR/CHF/USD (IDs 1-3)
- Olkypay EUR (ID 4)
- Maerki Baumann EUR/CHF (IDs 5-6)
- Revolut EUR (ID 7)
- Raiffeisen CHF (ID 13)
- Yapeal CHF/EUR (IDs 15-16)

Also includes formatting fixes for accounting controller and service.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants