修正
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
# backend/app/modules/trial_balance/service.py
|
||||
# 試算表.pdf フォーマットに完全準拠した試算表サービス
|
||||
from decimal import Decimal
|
||||
from typing import Dict, Any, List
|
||||
from app.core.database import get_connection
|
||||
@@ -6,30 +7,9 @@ from app.core.database import get_connection
|
||||
def D(x) -> Decimal:
|
||||
return Decimal(str(x or 0))
|
||||
|
||||
# 科目グループ定義(表示順序を制御)- PDFフォーマットに準拠
|
||||
ACCOUNT_GROUPS = [
|
||||
# 資産の部
|
||||
("現金・預金合計", ["101", "102", "103", "104", "105"]),
|
||||
("売上債権合計", ["201", "202"]),
|
||||
("有価証券合計", ["301"]),
|
||||
("棚卸資産合計", ["210"]),
|
||||
("他流動資産合計", ["203", "204", "205", "206", "207", "208"]),
|
||||
("流動資産合計", ["101", "102", "103", "104", "105", "201", "202", "203", "204", "205", "206", "207", "208", "210", "301"]),
|
||||
("有形固定資産合計", ["401", "402", "403", "404", "405", "406", "407"]),
|
||||
("無形固定資産合計", ["408"]),
|
||||
("投資その他の資産合計", ["301", "410"]),
|
||||
("固定資産合計", ["301", "401", "402", "403", "404", "405", "406", "407", "408", "410"]),
|
||||
("資産合計", ["101", "102", "103", "104", "105", "201", "202", "203", "204", "205", "206", "207", "208", "210", "301", "401", "402", "403", "404", "405", "406", "407", "408", "410"]),
|
||||
# 負債の部
|
||||
("仕入債務合計", ["501"]),
|
||||
("流動負債合計", ["501", "502", "503", "504", "505", "506", "507", "508"]),
|
||||
("固定負債合計", ["509"]),
|
||||
("負債合計", ["501", "502", "503", "504", "505", "506", "507", "508", "509"]),
|
||||
# 資本の部
|
||||
("資本金合計", ["601"]),
|
||||
# 利益剰余金合計は特別処理(602 + 当期純利益の内訳を表示)
|
||||
("純資産合計", ["601", "602"])
|
||||
]
|
||||
# 除外する科目コード
|
||||
EXCLUDED_CODES = {'512', '513', '516'}
|
||||
|
||||
|
||||
def fetch_trial_balance(date_from: str, date_to: str):
|
||||
|
||||
@@ -44,7 +24,6 @@ def fetch_trial_balance(date_from: str, date_to: str):
|
||||
""")
|
||||
accounts = cur.fetchall()
|
||||
|
||||
|
||||
# 科目データを格納
|
||||
account_data: Dict[str, Dict[str, Any]] = {}
|
||||
|
||||
@@ -52,8 +31,11 @@ def fetch_trial_balance(date_from: str, date_to: str):
|
||||
aid = acc["account_id"]
|
||||
code = acc["account_code"]
|
||||
|
||||
# 除外科目をスキップ
|
||||
if code in EXCLUDED_CODES:
|
||||
continue
|
||||
|
||||
# 期首残高: opening_balances テーブルの残高 + date_from より前の仕訳
|
||||
# まず opening_balances テーブルから取得
|
||||
cur.execute("""
|
||||
SELECT COALESCE(opening_debit, 0) - COALESCE(opening_credit, 0) AS ob
|
||||
FROM opening_balances
|
||||
@@ -64,7 +46,6 @@ def fetch_trial_balance(date_from: str, date_to: str):
|
||||
opening_balance_from_table = D(ob_row["ob"]) if ob_row else D(0)
|
||||
|
||||
# date_from より前の仕訳による増減
|
||||
# 修正された仕訳(is_latest = false)は除外
|
||||
cur.execute("""
|
||||
SELECT COALESCE(SUM(l.debit - l.credit), 0) AS opening
|
||||
FROM journal_lines l
|
||||
@@ -76,12 +57,10 @@ def fetch_trial_balance(date_from: str, date_to: str):
|
||||
AND j.is_latest = true
|
||||
""", (aid, date_from))
|
||||
opening_from_journals = D(cur.fetchone()["opening"])
|
||||
|
||||
# 合計
|
||||
|
||||
opening = opening_balance_from_table + opening_from_journals
|
||||
|
||||
# 当期増減(date_from ~ date_to)
|
||||
# 修正された仕訳(is_latest = false)は除外
|
||||
cur.execute("""
|
||||
SELECT
|
||||
COALESCE(SUM(l.debit), 0) AS debit,
|
||||
@@ -97,10 +76,10 @@ def fetch_trial_balance(date_from: str, date_to: str):
|
||||
row = cur.fetchone()
|
||||
debit = D(row["debit"])
|
||||
credit = D(row["credit"])
|
||||
|
||||
|
||||
closing = opening + debit - credit
|
||||
|
||||
# 負債・資本は絶対値で表示(見やすくするため)
|
||||
|
||||
# 負債・資本は絶対値で表示
|
||||
if acc["account_type"] in ("liability", "equity"):
|
||||
opening = abs(opening)
|
||||
closing = abs(closing)
|
||||
@@ -116,182 +95,441 @@ def fetch_trial_balance(date_from: str, date_to: str):
|
||||
"closing_balance": closing,
|
||||
}
|
||||
|
||||
# 結果リスト(グループ化)
|
||||
result_accounts: List[Dict[str, Any]] = []
|
||||
|
||||
# 既に挿入された合計行を追跡
|
||||
inserted_totals = set()
|
||||
|
||||
# 大区分の合計を保存(資産・負債・純資産の総合計)
|
||||
grand_total_closing = D(0)
|
||||
# =============================================
|
||||
# ヘルパー関数
|
||||
# =============================================
|
||||
def acct_row(code):
|
||||
"""個別科目の行を返す(存在しない場合はNone)"""
|
||||
if code not in account_data:
|
||||
return None
|
||||
d = account_data[code]
|
||||
return {
|
||||
"account_code": d["account_code"],
|
||||
"account_name": d["account_name"],
|
||||
"account_type": d["account_type"],
|
||||
"opening_balance": str(d["opening_balance"]),
|
||||
"debit": str(d["debit"]),
|
||||
"credit": str(d["credit"]),
|
||||
"closing_balance": str(d["closing_balance"]),
|
||||
"ratio": None,
|
||||
"is_total": False,
|
||||
}
|
||||
|
||||
# 個別科目を追加
|
||||
for code in sorted(account_data.keys()):
|
||||
data = account_data[code]
|
||||
result_accounts.append({
|
||||
"account_code": data["account_code"],
|
||||
"account_name": data["account_name"],
|
||||
"account_type": data["account_type"],
|
||||
"opening_balance": str(data["opening_balance"]),
|
||||
"debit": str(data["debit"]),
|
||||
"credit": str(data["credit"]),
|
||||
"closing_balance": str(data["closing_balance"]),
|
||||
"ratio": None, # 後で計算
|
||||
"is_total": False
|
||||
})
|
||||
|
||||
# 大区分合計用に総計を積算
|
||||
grand_total_closing += data["closing_balance"]
|
||||
def total_row(name, codes, is_total=True, indent=False):
|
||||
"""合計行を生成"""
|
||||
existing = [c for c in codes if c in account_data]
|
||||
opening = sum(account_data[c]["opening_balance"] for c in existing) if existing else D(0)
|
||||
debit = sum(account_data[c]["debit"] for c in existing) if existing else D(0)
|
||||
credit = sum(account_data[c]["credit"] for c in existing) if existing else D(0)
|
||||
closing = sum(account_data[c]["closing_balance"] for c in existing) if existing else D(0)
|
||||
return {
|
||||
"account_code": "",
|
||||
"account_name": name,
|
||||
"account_type": "",
|
||||
"opening_balance": str(opening),
|
||||
"debit": str(debit),
|
||||
"credit": str(credit),
|
||||
"closing_balance": str(closing),
|
||||
"ratio": None,
|
||||
"is_total": is_total,
|
||||
"indent": indent,
|
||||
}
|
||||
|
||||
# 利益剰余金(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
|
||||
})
|
||||
def custom_row(name, opening, debit, credit, closing,
|
||||
is_total=False, indent=False, account_type="", is_pl=False):
|
||||
"""カスタム行を生成"""
|
||||
row = {
|
||||
"account_code": "",
|
||||
"account_name": name,
|
||||
"account_type": account_type,
|
||||
"opening_balance": str(opening),
|
||||
"debit": str(debit),
|
||||
"credit": str(credit),
|
||||
"closing_balance": str(closing),
|
||||
"ratio": None,
|
||||
"is_total": is_total,
|
||||
"indent": indent,
|
||||
}
|
||||
if is_pl:
|
||||
row["is_pl"] = True
|
||||
return row
|
||||
|
||||
# 合計行を挿入(グループ定義の順序で)
|
||||
for group_name, group_codes in ACCOUNT_GROUPS:
|
||||
# このグループにまだ合計行を挿入していない
|
||||
if group_name in inserted_totals:
|
||||
continue
|
||||
|
||||
# 現在の科目がこのグループに含まれる
|
||||
if code not in group_codes:
|
||||
continue
|
||||
|
||||
# このグループの全科目を取得
|
||||
group_codes_in_data = [gc for gc in group_codes if gc in account_data]
|
||||
if not group_codes_in_data:
|
||||
continue
|
||||
|
||||
# グループの最後の科目コードを取得
|
||||
last_code_in_group = max(group_codes_in_data)
|
||||
|
||||
# 現在の科目がグループの最後の科目の場合
|
||||
if code == last_code_in_group:
|
||||
# グループ合計を計算
|
||||
group_opening = sum(account_data[gc]["opening_balance"] for gc in group_codes_in_data)
|
||||
group_debit = sum(account_data[gc]["debit"] for gc in group_codes_in_data)
|
||||
group_credit = sum(account_data[gc]["credit"] for gc in group_codes_in_data)
|
||||
group_closing = sum(account_data[gc]["closing_balance"] for gc in group_codes_in_data)
|
||||
|
||||
result_accounts.append({
|
||||
"account_code": "",
|
||||
"account_name": group_name,
|
||||
"account_type": "",
|
||||
"opening_balance": str(group_opening),
|
||||
"debit": str(group_debit),
|
||||
"credit": str(group_credit),
|
||||
"closing_balance": str(group_closing),
|
||||
"ratio": None, # 後で計算
|
||||
"is_total": True
|
||||
})
|
||||
|
||||
inserted_totals.add(group_name)
|
||||
|
||||
# 構成比を計算(総資産に対する割合)
|
||||
for acc in result_accounts:
|
||||
closing = D(acc["closing_balance"])
|
||||
if grand_total_closing != 0:
|
||||
ratio = (closing / grand_total_closing) * 100
|
||||
# =============================================
|
||||
# 結果リスト構築(試算表.pdf の順序に完全準拠)
|
||||
# =============================================
|
||||
result_accounts: List[Dict[str, Any]] = []
|
||||
added_codes = set() # 追加済みの科目コードを追跡
|
||||
|
||||
def add(code):
|
||||
"""個別科目を追加"""
|
||||
r = acct_row(code)
|
||||
if r:
|
||||
result_accounts.append(r)
|
||||
added_codes.add(code)
|
||||
|
||||
def add_total(name, codes, **kwargs):
|
||||
"""合計行を追加"""
|
||||
result_accounts.append(total_row(name, codes, **kwargs))
|
||||
|
||||
# ========== 資産の部 ==========
|
||||
|
||||
# 現金・預金
|
||||
cash_codes = ["101", "102", "103", "104", "105"]
|
||||
for c in cash_codes:
|
||||
add(c)
|
||||
add_total("現金・預金合計", cash_codes)
|
||||
|
||||
# 売上債権
|
||||
receivable_codes = ["201", "202"]
|
||||
for c in receivable_codes:
|
||||
add(c)
|
||||
add_total("売上債権合計", receivable_codes)
|
||||
|
||||
# 他流動資産
|
||||
other_current_codes = ["203", "204", "205", "206", "207", "208"]
|
||||
for c in other_current_codes:
|
||||
add(c)
|
||||
add_total("他流動資産合計", other_current_codes)
|
||||
|
||||
# 有価証券
|
||||
securities_codes = ["301"]
|
||||
for c in securities_codes:
|
||||
add(c)
|
||||
add_total("有価証券合計", securities_codes)
|
||||
|
||||
# 流動資産合計
|
||||
current_asset_codes = cash_codes + receivable_codes + other_current_codes + securities_codes
|
||||
add_total("流動資産合計", current_asset_codes)
|
||||
|
||||
# 有形固定資産
|
||||
tangible_codes = ["401", "402", "403", "404", "405", "406", "407"]
|
||||
for c in tangible_codes:
|
||||
add(c)
|
||||
add_total("有形固定資産合計", tangible_codes)
|
||||
|
||||
# 無形固定資産
|
||||
intangible_codes = ["408"]
|
||||
for c in intangible_codes:
|
||||
add(c)
|
||||
add_total("無形固定資産合計", intangible_codes)
|
||||
|
||||
# 投資その他の資産
|
||||
investment_codes = ["410"]
|
||||
for c in investment_codes:
|
||||
add(c)
|
||||
add_total("投資その他の資産合計", investment_codes)
|
||||
|
||||
# 固定資産合計
|
||||
fixed_asset_codes = tangible_codes + intangible_codes + investment_codes
|
||||
add_total("固定資産合計", fixed_asset_codes)
|
||||
|
||||
# 資産合計
|
||||
all_asset_codes = current_asset_codes + fixed_asset_codes
|
||||
add_total("資産合計", all_asset_codes)
|
||||
|
||||
# ========== 負債の部 ==========
|
||||
|
||||
# 仕入債務
|
||||
trade_payable_codes = ["501"]
|
||||
for c in trade_payable_codes:
|
||||
add(c)
|
||||
add_total("仕入債務合計", trade_payable_codes)
|
||||
|
||||
# 流動負債その他(502-508)
|
||||
current_liability_other = ["502", "503", "504", "505", "506", "507", "508"]
|
||||
for c in current_liability_other:
|
||||
add(c)
|
||||
current_liability_codes = trade_payable_codes + current_liability_other
|
||||
add_total("流動負債合計", current_liability_codes)
|
||||
|
||||
# 固定負債
|
||||
fixed_liability_codes = ["509"]
|
||||
for c in fixed_liability_codes:
|
||||
add(c)
|
||||
add_total("固定負債合計", fixed_liability_codes)
|
||||
|
||||
# 負債合計
|
||||
all_liability_codes = current_liability_codes + fixed_liability_codes
|
||||
add_total("負債合計", all_liability_codes)
|
||||
|
||||
# ========== 510/511: 独立科目(負債と資本の間) ==========
|
||||
add("510")
|
||||
add("511")
|
||||
|
||||
# ========== 資本の部 ==========
|
||||
|
||||
# 資本金
|
||||
capital_codes = ["601"]
|
||||
for c in capital_codes:
|
||||
add(c)
|
||||
add_total("資本金合計", capital_codes)
|
||||
|
||||
# 繰越利益剰余金(602)
|
||||
add("602")
|
||||
|
||||
# --- 当期純損益金額の計算 ---
|
||||
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"]
|
||||
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_opening = account_data.get("602", {}).get("opening_balance", D(0))
|
||||
retained_total = retained_opening + net_income
|
||||
|
||||
# 繰越利益
|
||||
result_accounts.append(
|
||||
custom_row("繰越利益", retained_opening, D(0), D(0), retained_opening,
|
||||
indent=True, account_type="equity")
|
||||
)
|
||||
|
||||
# 繰越利益剰余金合計
|
||||
result_accounts.append(
|
||||
custom_row("繰越利益剰余金合計", retained_opening,
|
||||
abs(net_income) if net_income < 0 else D(0),
|
||||
net_income if net_income > 0 else D(0),
|
||||
retained_total,
|
||||
is_total=True, indent=True, account_type="equity")
|
||||
)
|
||||
|
||||
# その他利益剰余金合計
|
||||
result_accounts.append(
|
||||
custom_row("その他利益剰余金合計", D(0), D(0), D(0), D(0),
|
||||
is_total=True, indent=True, account_type="equity")
|
||||
)
|
||||
|
||||
# 利益剰余金合計
|
||||
result_accounts.append(
|
||||
custom_row("利益剰余金合計", retained_opening,
|
||||
abs(net_income) if net_income < 0 else D(0),
|
||||
net_income if net_income > 0 else D(0),
|
||||
retained_total,
|
||||
is_total=True, account_type="equity")
|
||||
)
|
||||
|
||||
# 純資産合計
|
||||
capital_closing = account_data.get("601", {}).get("closing_balance", D(0))
|
||||
equity_total_closing = capital_closing + retained_total
|
||||
equity_total_opening = sum(
|
||||
account_data[c]["opening_balance"] for c in ["601", "602"] if c in account_data
|
||||
)
|
||||
result_accounts.append(
|
||||
custom_row("純資産合計", equity_total_opening, D(0), D(0), equity_total_closing,
|
||||
is_total=True, account_type="equity")
|
||||
)
|
||||
|
||||
# ========== 損益の部(截図フォーマットに準拠) ==========
|
||||
|
||||
# --- P/L 用ヘルパー ---
|
||||
def pl_row(code, indent=False):
|
||||
"""P/L個別科目行(closing = credit-debit or debit-credit)"""
|
||||
if code not in account_data:
|
||||
return None
|
||||
d = account_data[code]
|
||||
if code.startswith("7"):
|
||||
pl_closing = d["credit"] - d["debit"]
|
||||
else:
|
||||
pl_closing = d["debit"] - d["credit"]
|
||||
return {
|
||||
"account_code": d["account_code"],
|
||||
"account_name": d["account_name"],
|
||||
"account_type": d["account_type"],
|
||||
"opening_balance": "0",
|
||||
"debit": str(d["debit"]),
|
||||
"credit": str(d["credit"]),
|
||||
"closing_balance": str(pl_closing),
|
||||
"ratio": None,
|
||||
"is_total": False,
|
||||
"indent": indent,
|
||||
"is_pl": True,
|
||||
}
|
||||
|
||||
def add_pl(code, indent=False):
|
||||
r = pl_row(code, indent)
|
||||
if r:
|
||||
result_accounts.append(r)
|
||||
added_codes.add(code)
|
||||
|
||||
# === 売上高 ===
|
||||
add_pl("701")
|
||||
|
||||
# 売上高合計
|
||||
rev_d = account_data.get("701", {})
|
||||
revenue_val = rev_d.get("credit", D(0)) - rev_d.get("debit", D(0)) if "701" in account_data else D(0)
|
||||
result_accounts.append(
|
||||
custom_row("売上高合計", D(0), D(0), revenue_val, revenue_val, is_total=True, is_pl=True)
|
||||
)
|
||||
|
||||
# === 売上原価セクション ===
|
||||
# 期首商品棚卸高
|
||||
result_accounts.append(
|
||||
custom_row("期首商品棚卸高", D(0), D(0), D(0), D(0), indent=True, is_pl=True)
|
||||
)
|
||||
# 当期商品仕入高(= 801 仕入高)
|
||||
if "801" in account_data:
|
||||
add_pl("801", indent=True)
|
||||
else:
|
||||
result_accounts.append(
|
||||
custom_row("当期商品仕入高", D(0), D(0), D(0), D(0), indent=True, is_pl=True)
|
||||
)
|
||||
added_codes.add("801")
|
||||
# 合計
|
||||
cogs_d = account_data.get("801", {})
|
||||
cogs_debit = cogs_d.get("debit", D(0)) if "801" in account_data else D(0)
|
||||
cogs_credit = cogs_d.get("credit", D(0)) if "801" in account_data else D(0)
|
||||
cogs_net = cogs_debit - cogs_credit
|
||||
result_accounts.append(
|
||||
custom_row("合計", D(0), cogs_debit, cogs_credit, cogs_net,
|
||||
is_total=True, indent=True, is_pl=True)
|
||||
)
|
||||
# 期末商品棚卸高
|
||||
result_accounts.append(
|
||||
custom_row("期末商品棚卸高", D(0), D(0), D(0), D(0), indent=True, is_pl=True)
|
||||
)
|
||||
# 売上原価
|
||||
result_accounts.append(
|
||||
custom_row("売上原価", D(0), cogs_debit, cogs_credit, cogs_net,
|
||||
is_total=True, indent=True, is_pl=True)
|
||||
)
|
||||
|
||||
# === 売上総損益金額 ===
|
||||
gross_profit = revenue_val - cogs_net
|
||||
result_accounts.append(
|
||||
custom_row("売上総損益金額", D(0), D(0), gross_profit, gross_profit,
|
||||
is_total=True, is_pl=True)
|
||||
)
|
||||
|
||||
# === 販売管理費(截図の順序に準拠) ===
|
||||
sga_order = [
|
||||
"812", "813", "814", "815", # 人件費系
|
||||
"802", # 外注費
|
||||
"816", "817", # 交際費・会議費
|
||||
"803", "804", "805", # 旅費・通信・消耗品
|
||||
"818", # 新聞図書費
|
||||
"808", # 支払手数料
|
||||
"806", # 地代家賃
|
||||
"819", "820", # 保険料・租税公課
|
||||
]
|
||||
# 上記リストにない8xx費用科目を末尾に追加(801除外)
|
||||
remaining_8xx = [c for c in sorted(account_data.keys())
|
||||
if c.startswith("8") and c != "801" and c not in sga_order]
|
||||
sga_all = sga_order + remaining_8xx
|
||||
|
||||
sga_debit_total = D(0)
|
||||
sga_credit_total = D(0)
|
||||
sga_closing_total = D(0)
|
||||
for code in sga_all:
|
||||
add_pl(code, indent=True)
|
||||
if code in account_data:
|
||||
d = account_data[code]
|
||||
sga_debit_total += d["debit"]
|
||||
sga_credit_total += d["credit"]
|
||||
sga_closing_total += d["debit"] - d["credit"]
|
||||
|
||||
# 販売管理費計
|
||||
result_accounts.append(
|
||||
custom_row("販売管理費計", D(0), sga_debit_total, sga_credit_total,
|
||||
sga_closing_total, is_total=True, is_pl=True)
|
||||
)
|
||||
|
||||
# === 営業損益金額 ===
|
||||
operating_profit = gross_profit - sga_closing_total
|
||||
result_accounts.append(
|
||||
custom_row("営業損益金額", D(0), D(0), operating_profit, operating_profit,
|
||||
is_total=True, is_pl=True)
|
||||
)
|
||||
|
||||
# === 営業外収益 ===
|
||||
non_op_rev_codes = ["702", "709"]
|
||||
non_op_rev_debit = D(0)
|
||||
non_op_rev_credit = D(0)
|
||||
for code in non_op_rev_codes:
|
||||
add_pl(code, indent=True)
|
||||
if code in account_data:
|
||||
d = account_data[code]
|
||||
non_op_rev_debit += d["debit"]
|
||||
non_op_rev_credit += d["credit"]
|
||||
non_op_rev_closing = non_op_rev_credit - non_op_rev_debit
|
||||
|
||||
# 営業外収益合計
|
||||
result_accounts.append(
|
||||
custom_row("営業外収益合計", D(0), non_op_rev_debit, non_op_rev_credit,
|
||||
non_op_rev_closing, is_total=True, indent=True, is_pl=True)
|
||||
)
|
||||
|
||||
# 営業外費用合計(現在は該当科目なし)
|
||||
result_accounts.append(
|
||||
custom_row("営業外費用合計", D(0), D(0), D(0), D(0),
|
||||
is_total=True, indent=True, is_pl=True)
|
||||
)
|
||||
|
||||
# === 経常損益金額 ===
|
||||
ordinary_profit = operating_profit + non_op_rev_closing
|
||||
result_accounts.append(
|
||||
custom_row("経常損益金額", D(0), D(0), ordinary_profit, ordinary_profit,
|
||||
is_total=True, is_pl=True)
|
||||
)
|
||||
|
||||
# === 特別利益合計 ===
|
||||
result_accounts.append(
|
||||
custom_row("特別利益合計", D(0), D(0), D(0), D(0),
|
||||
is_total=True, indent=True, is_pl=True)
|
||||
)
|
||||
|
||||
# === 特別損失合計 ===
|
||||
result_accounts.append(
|
||||
custom_row("特別損失合計", D(0), D(0), D(0), D(0),
|
||||
is_total=True, indent=True, is_pl=True)
|
||||
)
|
||||
|
||||
# === 当期純損益金額 ===
|
||||
result_accounts.append(
|
||||
custom_row("当期純損益金額", D(0), D(0), ordinary_profit, ordinary_profit,
|
||||
is_total=True, is_pl=True)
|
||||
)
|
||||
|
||||
# ========== 未分類科目(上記にない科目を末尾に追加) ==========
|
||||
for code in sorted(account_data.keys()):
|
||||
if code not in added_codes:
|
||||
add(code)
|
||||
|
||||
# =============================================
|
||||
# 構成比を計算
|
||||
# B/S: 借方残合計ベース
|
||||
# P/L: 売上高(対売上比)ベース
|
||||
# =============================================
|
||||
debit_balance_total = sum(
|
||||
d["closing_balance"] for d in account_data.values()
|
||||
if d["closing_balance"] > 0
|
||||
)
|
||||
|
||||
for acc in result_accounts:
|
||||
closing = D(acc["closing_balance"])
|
||||
if acc.get("is_pl"):
|
||||
# P/L: 対売上比
|
||||
if revenue_val != 0:
|
||||
ratio = (closing / revenue_val) * 100
|
||||
acc["ratio"] = f"{ratio:.2f}"
|
||||
else:
|
||||
acc["ratio"] = "0.00"
|
||||
else:
|
||||
# B/S: 借方残合計ベース
|
||||
if debit_balance_total != 0:
|
||||
ratio = (closing / debit_balance_total) * 100
|
||||
acc["ratio"] = f"{ratio:.2f}"
|
||||
else:
|
||||
acc["ratio"] = "0.00"
|
||||
|
||||
# 総合計を計算
|
||||
total_opening = sum(data["opening_balance"] for data in account_data.values())
|
||||
total_debit = sum(data["debit"] for data in account_data.values())
|
||||
total_credit = sum(data["credit"] for data in account_data.values())
|
||||
total_closing = sum(data["closing_balance"] for data in account_data.values())
|
||||
# 総合計を計算
|
||||
total_opening = sum(d["opening_balance"] for d in account_data.values())
|
||||
total_debit = sum(d["debit"] for d in account_data.values())
|
||||
total_credit = sum(d["credit"] for d in account_data.values())
|
||||
total_closing = sum(d["closing_balance"] for d in account_data.values())
|
||||
|
||||
result = {
|
||||
"totals": {
|
||||
@@ -302,7 +540,7 @@ def fetch_trial_balance(date_from: str, date_to: str):
|
||||
"ratio": "100.00"
|
||||
},
|
||||
"accounts": result_accounts,
|
||||
"grand_total_closing": str(grand_total_closing)
|
||||
"grand_total_closing": str(debit_balance_total),
|
||||
}
|
||||
|
||||
|
||||
return result
|
||||
|
||||
@@ -40,6 +40,7 @@ def get_trial_balance(
|
||||
JOIN accounts a ON a.account_id = l.account_id
|
||||
WHERE e.is_deleted = false
|
||||
AND e.is_latest = true
|
||||
AND a.account_code NOT IN ('512', '513', '516')
|
||||
"""
|
||||
else:
|
||||
# 旧系统:排除已修正的记录(使用 parent_entry_id)
|
||||
@@ -55,6 +56,7 @@ def get_trial_balance(
|
||||
JOIN journal_entries e ON e.journal_entry_id = l.journal_entry_id
|
||||
JOIN accounts a ON a.account_id = l.account_id
|
||||
WHERE e.is_deleted = false
|
||||
AND a.account_code NOT IN ('512', '513', '516')
|
||||
AND e.journal_entry_id NOT IN (
|
||||
SELECT parent_entry_id
|
||||
FROM journal_entries
|
||||
@@ -83,7 +85,11 @@ def get_trial_balance(
|
||||
a.account_name,
|
||||
a.account_type
|
||||
ORDER BY
|
||||
a.account_code
|
||||
CASE
|
||||
WHEN a.account_code < '509' THEN a.account_code
|
||||
WHEN a.account_code IN ('510', '511') THEN '508.' || a.account_code
|
||||
ELSE a.account_code
|
||||
END
|
||||
"""
|
||||
|
||||
with get_connection() as conn, conn.cursor() as cur:
|
||||
|
||||
Reference in New Issue
Block a user