From 6661c7ac89d88310f6aa2e7cfb7ed49a0a99ae27 Mon Sep 17 00:00:00 2001 From: admin Date: Sat, 17 Jan 2026 11:08:57 +0900 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../modules/opening_balances/lock_router.py | 2 +- backend/app/modules/trial_balance/service.py | 97 +++- backend/app/routers/journal_entries.py | 4 +- backend/app/routers/month_locks.py | 6 +- backend/app/routers/year_locks.py | 8 +- backend/insert_602_opening.py | 32 ++ backend/sql/add_petty_cash.sql | 6 + backend/sql/insert_opening_balances_2025.sql | 5 +- backend/update_opening_balances.py | 45 ++ frontend/journal-entry.html | 452 ++++++++++++++++-- 10 files changed, 610 insertions(+), 47 deletions(-) create mode 100644 backend/insert_602_opening.py create mode 100644 backend/sql/add_petty_cash.sql create mode 100644 backend/update_opening_balances.py diff --git a/backend/app/modules/opening_balances/lock_router.py b/backend/app/modules/opening_balances/lock_router.py index 33e6cf7..61dd245 100644 --- a/backend/app/modules/opening_balances/lock_router.py +++ b/backend/app/modules/opening_balances/lock_router.py @@ -39,7 +39,7 @@ def lock_fiscal_year(req: LockRequest): ON CONFLICT (fiscal_year) DO UPDATE SET is_locked = true, - locked_at = CURRENT_TIMESTAMP + locked_at = CURRENT_TIMESTAMP AT TIME ZONE 'Asia/Tokyo' """, (req.fiscal_year,)) conn.commit() diff --git a/backend/app/modules/trial_balance/service.py b/backend/app/modules/trial_balance/service.py index 99e8174..6562346 100644 --- a/backend/app/modules/trial_balance/service.py +++ b/backend/app/modules/trial_balance/service.py @@ -24,7 +24,7 @@ ACCOUNT_GROUPS = [ ("負債合計", ["501", "502", "503", "504", "505", "506", "507", "508", "509"]), # 資本の部 ("資本金合計", ["601"]), - ("利益剰余金合計", ["602"]), + # 利益剰余金合計は特別処理(602 + 当期純利益の内訳を表示) ("純資産合計", ["601", "602"]) ] @@ -145,6 +145,101 @@ def fetch_trial_balance(date_from: str, date_to: str): # 大区分合計用に総計を積算 grand_total_closing += data["closing_balance"] + # 利益剰余金(602)の後に詳細を挿入 + if code == "602": + # 繰越利益剰余金 = 602の期首残高 + retained_earnings_opening = data["opening_balance"] + + # 当期純損益金額を計算(収益 - 費用) + # 収益(7xx)の合計 + revenue_total = D(0) + for acc_code, acc_data in account_data.items(): + if acc_code.startswith("7"): + # 収益は貸方が増加、借方が減少 + revenue_total += acc_data["credit"] - acc_data["debit"] + + # 費用(8xx)の合計 + expense_total = D(0) + for acc_code, acc_data in account_data.items(): + if acc_code.startswith("8"): + # 費用は借方が増加、貸方が減少 + expense_total += acc_data["debit"] - acc_data["credit"] + + # 当期純損益金額 = 収益 - 費用 + net_income = revenue_total - expense_total + + # 繰越利益剰余金合計 = 期首繰越利益 + 当期純損益 + retained_earnings_total = retained_earnings_opening + net_income + + # 繰越利益の行を追加 + result_accounts.append({ + "account_code": "", + "account_name": " 繰越利益", + "account_type": "equity", + "opening_balance": str(retained_earnings_opening), + "debit": "0", + "credit": "0", + "closing_balance": str(retained_earnings_opening), + "ratio": None, + "is_total": False, + "indent": True + }) + + # 当期純損益金額の行を追加 + result_accounts.append({ + "account_code": "", + "account_name": " 当期純損益金額", + "account_type": "equity", + "opening_balance": "0", + "debit": str(expense_total) if expense_total > 0 else "0", + "credit": str(revenue_total) if revenue_total > 0 else "0", + "closing_balance": str(net_income), + "ratio": None, + "is_total": False, + "indent": True + }) + + # 繰越利益剰余金合計の行を追加 + result_accounts.append({ + "account_code": "", + "account_name": " 繰越利益剰余金合計", + "account_type": "equity", + "opening_balance": str(retained_earnings_opening), + "debit": str(expense_total) if expense_total > 0 else "0", + "credit": str(revenue_total) if revenue_total > 0 else "0", + "closing_balance": str(retained_earnings_total), + "ratio": None, + "is_total": True, + "indent": True + }) + + # その他利益剰余金合計(現在は0) + result_accounts.append({ + "account_code": "", + "account_name": " その他利益剰余金合計", + "account_type": "equity", + "opening_balance": "0", + "debit": "0", + "credit": "0", + "closing_balance": "0", + "ratio": None, + "is_total": True, + "indent": True + }) + + # 利益剰余金合計の行を追加 + result_accounts.append({ + "account_code": "", + "account_name": "利益剰余金合計", + "account_type": "equity", + "opening_balance": str(retained_earnings_opening), + "debit": str(expense_total) if expense_total > 0 else "0", + "credit": str(revenue_total) if revenue_total > 0 else "0", + "closing_balance": str(retained_earnings_total), + "ratio": None, + "is_total": True + }) + # 合計行を挿入(グループ定義の順序で) for group_name, group_codes in ACCOUNT_GROUPS: # このグループにまだ合計行を挿入していない diff --git a/backend/app/routers/journal_entries.py b/backend/app/routers/journal_entries.py index 1c47c0e..3b0d8fb 100644 --- a/backend/app/routers/journal_entries.py +++ b/backend/app/routers/journal_entries.py @@ -423,7 +423,7 @@ def update_journal_entry(journal_id: int, req: JournalEntryUpdateRequest): UPDATE journal_entries SET description = %s, version = version + 1, - updated_at = NOW(), + updated_at = CURRENT_TIMESTAMP AT TIME ZONE 'Asia/Tokyo', updated_reason = %s WHERE journal_id = %s """, ( @@ -472,7 +472,7 @@ def delete_journal_entry(journal_id: int, req: JournalEntryDeleteRequest): cur.execute(""" UPDATE journal_entries SET is_deleted = true, - updated_at = NOW() + updated_at = CURRENT_TIMESTAMP AT TIME ZONE 'Asia/Tokyo' WHERE journal_entry_id = %s AND is_deleted = false RETURNING journal_entry_id diff --git a/backend/app/routers/month_locks.py b/backend/app/routers/month_locks.py index ff16c4f..1742467 100644 --- a/backend/app/routers/month_locks.py +++ b/backend/app/routers/month_locks.py @@ -14,7 +14,7 @@ def get_month_locks(): fiscal_year, month, is_locked, - locked_at, + (locked_at AT TIME ZONE 'UTC') AT TIME ZONE 'Asia/Tokyo' as locked_at, locked_by FROM month_locks ORDER BY fiscal_year, month @@ -39,11 +39,11 @@ def lock_month(fiscal_year: int, month: int): locked_at, locked_by ) - VALUES (%s, %s, true, NOW(), %s) + VALUES (%s, %s, true, CURRENT_TIMESTAMP AT TIME ZONE 'Asia/Tokyo', %s) ON CONFLICT (fiscal_year, month) DO UPDATE SET is_locked = true, - locked_at = NOW(), + locked_at = CURRENT_TIMESTAMP AT TIME ZONE 'Asia/Tokyo', locked_by = EXCLUDED.locked_by """, ( fiscal_year, diff --git a/backend/app/routers/year_locks.py b/backend/app/routers/year_locks.py index 7477682..ce2cf2c 100644 --- a/backend/app/routers/year_locks.py +++ b/backend/app/routers/year_locks.py @@ -8,7 +8,9 @@ router = APIRouter(prefix="/year-locks", tags=["年度锁定"]) def get_year_locks(): with get_connection() as conn, conn.cursor() as cur: cur.execute(""" - SELECT fiscal_year, is_locked, locked_at, locked_by + SELECT fiscal_year, is_locked, + (locked_at AT TIME ZONE 'UTC') AT TIME ZONE 'Asia/Tokyo' as locked_at, + locked_by FROM year_locks ORDER BY fiscal_year """) @@ -20,11 +22,11 @@ def lock_year(fiscal_year: int): with get_connection() as conn, conn.cursor() as cur: cur.execute(""" INSERT INTO year_locks (fiscal_year, is_locked, locked_at, locked_by) - VALUES (%s, true, NOW(), %s) + VALUES (%s, true, CURRENT_TIMESTAMP AT TIME ZONE 'Asia/Tokyo', %s) ON CONFLICT (fiscal_year) DO UPDATE SET is_locked = true, - locked_at = NOW(), + locked_at = CURRENT_TIMESTAMP AT TIME ZONE 'Asia/Tokyo', locked_by = EXCLUDED.locked_by """, (fiscal_year, "system")) conn.commit() diff --git a/backend/insert_602_opening.py b/backend/insert_602_opening.py new file mode 100644 index 0000000..587456c --- /dev/null +++ b/backend/insert_602_opening.py @@ -0,0 +1,32 @@ +import os +os.environ['DB_HOST'] = '192.168.0.61' +os.environ['DB_PORT'] = '55432' +os.environ['DB_NAME'] = 'njts_acct' +os.environ['DB_USER'] = 'njts_app' +os.environ['DB_PASSWORD'] = 'njts_app2025' + +from app.core.database import get_connection + +with get_connection() as conn: + with conn.cursor() as cur: + # 602科目の前期残高を登録 + cur.execute(""" + INSERT INTO opening_balances (fiscal_year, account_id, opening_debit, opening_credit) + VALUES (2025, (SELECT account_id FROM accounts WHERE account_code = '602'), 0, 5206146) + ON CONFLICT (fiscal_year, account_id) + DO UPDATE SET opening_credit = 5206146 + """) + conn.commit() + print('✓ 602科目(繰越利益剰余金)の前期残高 5,206,146円 を登録しました') + + # 確認 + cur.execute(""" + SELECT a.account_code, a.account_name, ob.opening_debit, ob.opening_credit + FROM opening_balances ob + JOIN accounts a ON ob.account_id = a.account_id + WHERE ob.fiscal_year = 2025 AND a.account_code = '602' + """) + row = cur.fetchone() + if row: + print(f"\n【確認】") + print(f"{row['account_code']} {row['account_name']}: 貸方 {row['opening_credit']:,}円") diff --git a/backend/sql/add_petty_cash.sql b/backend/sql/add_petty_cash.sql new file mode 100644 index 0000000..902a9f6 --- /dev/null +++ b/backend/sql/add_petty_cash.sql @@ -0,0 +1,6 @@ +-- ========================= +-- 小口現金科目の追加 +-- ========================= + +INSERT INTO accounts (account_code, account_name, account_type) +VALUES ('105', '小口現金', 'asset'); diff --git a/backend/sql/insert_opening_balances_2025.sql b/backend/sql/insert_opening_balances_2025.sql index fdc31f4..9854ecd 100644 --- a/backend/sql/insert_opening_balances_2025.sql +++ b/backend/sql/insert_opening_balances_2025.sql @@ -43,9 +43,10 @@ INSERT INTO opening_balances (fiscal_year, account_id, opening_debit, opening_cr (2025, (SELECT account_id FROM accounts WHERE account_code = '506'), 0, 669316), -- 資本金(601): 6,000,000(貸方) -(2025, (SELECT account_id FROM accounts WHERE account_code = '601'), 0, 6000000); +(2025, (SELECT account_id FROM accounts WHERE account_code = '601'), 0, 6000000), --- 繰越利益剰余金(602): 5,206,146 は自動計算されるため入力不要 +-- 繰越利益剰余金(602): 5,206,146(貸方) +(2025, (SELECT account_id FROM accounts WHERE account_code = '602'), 0, 5206146); -- 確認用クエリ SELECT diff --git a/backend/update_opening_balances.py b/backend/update_opening_balances.py new file mode 100644 index 0000000..90c3d92 --- /dev/null +++ b/backend/update_opening_balances.py @@ -0,0 +1,45 @@ +import os +os.environ['DB_HOST'] = '192.168.0.61' +os.environ['DB_PORT'] = '55432' +os.environ['DB_NAME'] = 'njts_acct' +os.environ['DB_USER'] = 'njts_app' +os.environ['DB_PASSWORD'] = 'njts_app2025' + +from app.core.database import get_connection + +# SQLファイルを読み込んで実行 +with open('sql/insert_opening_balances_2025.sql', 'r', encoding='utf-8') as f: + sql_content = f.read() + +# セミコロンで分割して実行 +statements = [s.strip() for s in sql_content.split(';') if s.strip() and not s.strip().startswith('--')] + +with get_connection() as conn: + with conn.cursor() as cur: + for statement in statements: + if statement.strip(): + try: + cur.execute(statement) + print(f"✓ 実行成功") + except Exception as e: + print(f"✗ エラー: {e}") + + conn.commit() + print("\n前期残高データを更新しました。") + + # 確認 + cur.execute(""" + SELECT + a.account_code, + a.account_name, + ob.opening_debit, + ob.opening_credit + FROM opening_balances ob + JOIN accounts a ON ob.account_id = a.account_id + WHERE ob.fiscal_year = 2025 + ORDER BY a.account_code + """) + + print("\n【2025年度 前期残高一覧】") + for row in cur.fetchall(): + print(f"{row['account_code']} {row['account_name']:20s} 借方:{row['opening_debit']:>12,} 貸方:{row['opening_credit']:>12,}") diff --git a/frontend/journal-entry.html b/frontend/journal-entry.html index 268f4ee..77302d8 100644 --- a/frontend/journal-entry.html +++ b/frontend/journal-entry.html @@ -45,6 +45,72 @@ .tax-row { background: #f0f8ff; } + .print-header { + display: none; + } + .page-break { + page-break-before: always; + } + .page-number { + display: none; + } + @media print { + @page { + margin: 20mm; + } + body * { + visibility: hidden; + } + #printArea, + #printArea * { + visibility: visible; + } + #printArea { + position: absolute; + left: 0; + top: 0; + width: 100%; + } + button, + .no-print { + display: none !important; + } + .print-header { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 8px; + font-size: 0.9em; + padding-bottom: 4px; + } + .print-header-left { + text-align: left; + } + .print-header-right { + text-align: right; + } + .page-number { + display: block; + text-align: center; + margin-top: 10px; + font-size: 0.9em; + color: #666; + } + #printArea table { + font-size: 0.85em; + } + #printArea th, + #printArea td { + padding: 3px 4px; + } + #printArea h3 { + font-size: 1.1em; + margin-bottom: 6px; + } + thead { + display: table-header-group; + } + } @@ -217,21 +283,15 @@ + - - - - - - - - - - - - -
日付摘要借方合計貸方合計税率操作
+