修正
This commit is contained in:
@@ -8,7 +8,13 @@ SELECT
|
||||
FROM journal_lines l
|
||||
JOIN journal_entries j
|
||||
ON j.journal_id = l.journal_id
|
||||
LEFT JOIN journal_entries child
|
||||
ON child.parent_entry_id = j.journal_id
|
||||
WHERE l.account_id = %(account_id)s
|
||||
AND j.journal_date BETWEEN %(date_from)s AND %(date_to)s
|
||||
-- 逆仕訳を除外
|
||||
AND j.description NOT LIKE '[逆仕訳]%'
|
||||
-- 子仕訳(修正後仕訳)を持つ修正前の仕訳を除外
|
||||
AND child.journal_id IS NULL
|
||||
ORDER BY j.journal_date, l.line_id;
|
||||
"""
|
||||
|
||||
@@ -64,8 +64,14 @@ def get_general_ledger(
|
||||
FROM journal_entries j
|
||||
JOIN journal_lines l
|
||||
ON l.journal_id = j.journal_id
|
||||
LEFT JOIN journal_entries child
|
||||
ON child.parent_entry_id = j.journal_id
|
||||
WHERE l.account_id = %s
|
||||
AND j.journal_date BETWEEN %s AND %s
|
||||
-- 逆仕訳を除外
|
||||
AND j.description NOT LIKE '[逆仕訳]%'
|
||||
-- 子仕訳(修正後仕訳)を持つ修正前の仕訳を除外
|
||||
AND child.journal_id IS NULL
|
||||
ORDER BY j.journal_date, l.line_id
|
||||
""", (account_id, date_from, date_to))
|
||||
|
||||
|
||||
@@ -60,14 +60,19 @@ 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 より前の仕訳による増減
|
||||
# 修正された仕訳(親となった仕訳)は除外
|
||||
cur.execute("""
|
||||
SELECT COALESCE(SUM(l.debit - l.credit), 0) AS opening
|
||||
FROM journal_lines l
|
||||
JOIN journal_entries j
|
||||
ON j.journal_entry_id = l.journal_entry_id
|
||||
LEFT JOIN journal_entries child
|
||||
ON child.parent_entry_id = j.journal_entry_id
|
||||
WHERE l.account_id = %s
|
||||
AND j.entry_date < %s
|
||||
AND j.is_deleted = false
|
||||
AND j.description NOT LIKE '[逆仕訳]%%'
|
||||
AND child.journal_entry_id IS NULL
|
||||
""", (aid, date_from))
|
||||
opening_from_journals = D(cur.fetchone()["opening"])
|
||||
|
||||
@@ -75,6 +80,7 @@ def fetch_trial_balance(date_from: str, date_to: str):
|
||||
opening = opening_balance_from_table + opening_from_journals
|
||||
|
||||
# 当期増減(date_from ~ date_to)
|
||||
# 修正された仕訳(親となった仕訳)は除外
|
||||
cur.execute("""
|
||||
SELECT
|
||||
COALESCE(SUM(l.debit), 0) AS debit,
|
||||
@@ -82,9 +88,13 @@ def fetch_trial_balance(date_from: str, date_to: str):
|
||||
FROM journal_lines l
|
||||
JOIN journal_entries j
|
||||
ON j.journal_entry_id = l.journal_entry_id
|
||||
LEFT JOIN journal_entries child
|
||||
ON child.parent_entry_id = j.journal_entry_id
|
||||
WHERE l.account_id = %s
|
||||
AND j.entry_date BETWEEN %s AND %s
|
||||
AND j.is_deleted = false
|
||||
AND j.description NOT LIKE '[逆仕訳]%%'
|
||||
AND child.journal_entry_id IS NULL
|
||||
""", (aid, date_from, date_to))
|
||||
row = cur.fetchone()
|
||||
debit = D(row["debit"])
|
||||
|
||||
@@ -17,9 +17,10 @@ opening AS (
|
||||
SUM(jl.debit) AS opening_debit,
|
||||
SUM(jl.credit) AS opening_credit
|
||||
FROM journal_entries je
|
||||
JOIN journal_lines jl ON jl.journal_id = je.journal_id
|
||||
JOIN journal_lines jl ON jl.journal_entry_id = je.journal_entry_id
|
||||
WHERE je.description = '前期残高'
|
||||
AND je.journal_date = %(start_date)s
|
||||
AND je.entry_date = %(start_date)s
|
||||
AND je.is_deleted = false
|
||||
GROUP BY jl.account_id
|
||||
),
|
||||
|
||||
@@ -29,9 +30,15 @@ period AS (
|
||||
SUM(jl.debit) AS period_debit,
|
||||
SUM(jl.credit) AS period_credit
|
||||
FROM journal_entries je
|
||||
JOIN journal_lines jl ON jl.journal_id = je.journal_id
|
||||
WHERE je.journal_date BETWEEN %(start_date)s AND %(end_date)s
|
||||
JOIN journal_lines jl ON jl.journal_entry_id = je.journal_entry_id
|
||||
LEFT JOIN journal_entries child ON child.parent_entry_id = je.journal_entry_id
|
||||
WHERE je.entry_date BETWEEN %(start_date)s AND %(end_date)s
|
||||
AND je.description <> '前期残高'
|
||||
AND je.is_deleted = false
|
||||
-- 逆仕訳を除外([逆仕訳]プレフィックスを持つ仕訳)
|
||||
AND je.description NOT LIKE '[逆仕訳]%'
|
||||
-- 子仕訳(修正後仕訳)を持つ修正前の仕訳を除外
|
||||
AND child.journal_entry_id IS NULL
|
||||
GROUP BY jl.account_id
|
||||
)
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@ class JournalEntryRequest(BaseModel):
|
||||
tax_paid_account_id: Optional[int] = None # 仮払消費税等 勘定
|
||||
tax_received_account_id: Optional[int] = None # 仮受消費税等 勘定
|
||||
rounding_mode: str = "round" # "round", "floor", or "ceil"
|
||||
parent_entry_id: Optional[int] = None # 修正元の仕訳ID
|
||||
|
||||
class JournalEntryUpdateRequest(BaseModel):
|
||||
description: str
|
||||
@@ -58,7 +59,8 @@ def get_journal_entries(
|
||||
je.fiscal_year,
|
||||
je.version,
|
||||
COALESCE(SUM(jl.debit), 0) as debit_total,
|
||||
COALESCE(SUM(jl.credit), 0) as credit_total
|
||||
COALESCE(SUM(jl.credit), 0) as credit_total,
|
||||
STRING_AGG(DISTINCT CASE WHEN jl.tax_rate IS NOT NULL THEN jl.tax_rate::text END, ', ' ORDER BY CASE WHEN jl.tax_rate IS NOT NULL THEN jl.tax_rate::text END) as tax_rates
|
||||
FROM journal_entries je
|
||||
LEFT JOIN journal_lines jl ON je.journal_entry_id = jl.journal_entry_id
|
||||
WHERE je.is_deleted = false
|
||||
@@ -74,7 +76,8 @@ def get_journal_entries(
|
||||
je.fiscal_year,
|
||||
je.version,
|
||||
COALESCE(SUM(jl.debit), 0) as debit_total,
|
||||
COALESCE(SUM(jl.credit), 0) as credit_total
|
||||
COALESCE(SUM(jl.credit), 0) as credit_total,
|
||||
STRING_AGG(DISTINCT CASE WHEN jl.tax_rate IS NOT NULL THEN jl.tax_rate::text END, ', ' ORDER BY CASE WHEN jl.tax_rate IS NOT NULL THEN jl.tax_rate::text END) as tax_rates
|
||||
FROM journal_entries je
|
||||
LEFT JOIN journal_lines jl ON je.journal_entry_id = jl.journal_entry_id
|
||||
WHERE je.is_deleted = false
|
||||
@@ -202,15 +205,17 @@ def create_reverse_entry(journal_id: int):
|
||||
fiscal_year,
|
||||
version,
|
||||
is_deleted,
|
||||
created_by
|
||||
created_by,
|
||||
parent_entry_id
|
||||
)
|
||||
VALUES (%s, %s, %s, 1, false, %s)
|
||||
VALUES (%s, %s, %s, 1, false, %s, %s)
|
||||
RETURNING journal_entry_id
|
||||
""", (
|
||||
header["entry_date"],
|
||||
f"[逆仕訳] {header['description']}",
|
||||
header["fiscal_year"],
|
||||
"system"
|
||||
"system",
|
||||
journal_id # 逆仕訳の元となる仕訳ID
|
||||
))
|
||||
|
||||
new_entry_id = cur.fetchone()["journal_entry_id"]
|
||||
@@ -322,15 +327,17 @@ def create_journal_entry(req: JournalEntryRequest):
|
||||
fiscal_year,
|
||||
version,
|
||||
is_deleted,
|
||||
created_by
|
||||
created_by,
|
||||
parent_entry_id
|
||||
)
|
||||
VALUES (%s, %s, %s, 1, false, %s)
|
||||
VALUES (%s, %s, %s, 1, false, %s, %s)
|
||||
RETURNING journal_entry_id
|
||||
""", (
|
||||
req.entry_date,
|
||||
req.description,
|
||||
fiscal_year,
|
||||
"system"
|
||||
"system",
|
||||
req.parent_entry_id
|
||||
))
|
||||
|
||||
entry_id = cur.fetchone()["journal_entry_id"]
|
||||
|
||||
109
backend/check_data.py
Normal file
109
backend/check_data.py
Normal file
@@ -0,0 +1,109 @@
|
||||
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'
|
||||
|
||||
import sys
|
||||
sys.path.insert(0, os.path.dirname(__file__))
|
||||
|
||||
from app.core.database import get_connection
|
||||
|
||||
conn = get_connection()
|
||||
cur = conn.cursor()
|
||||
|
||||
# 逸速ビル関連の仕訳を確認
|
||||
cur.execute("""
|
||||
SELECT journal_entry_id, entry_date, description, parent_entry_id, is_deleted
|
||||
FROM journal_entries
|
||||
WHERE description LIKE '%遠達ビル%'
|
||||
ORDER BY journal_entry_id
|
||||
""")
|
||||
|
||||
rows = cur.fetchall()
|
||||
print("\n遠達ビル関連の仕訳:")
|
||||
for r in rows:
|
||||
print(f"ID: {r['journal_entry_id']}, Date: {r['entry_date']}, Desc: {r['description']}, Parent: {r['parent_entry_id']}, is_deleted: {r['is_deleted']}")
|
||||
|
||||
# parent_entry_idが設定されている仕訳IDの一覧を取得
|
||||
cur.execute("""
|
||||
SELECT DISTINCT parent_entry_id
|
||||
FROM journal_entries
|
||||
WHERE parent_entry_id IS NOT NULL
|
||||
ORDER BY parent_entry_id
|
||||
""")
|
||||
|
||||
parent_ids = [r['parent_entry_id'] for r in cur.fetchall()]
|
||||
print(f"\nparent_entry_idとして参照されているID: {parent_ids}")
|
||||
|
||||
cur.close()
|
||||
conn.close()
|
||||
|
||||
# 実際の検索クエリと同じロジックでテスト
|
||||
print("\n--- 検索クエリのテスト(include_history=False) ---")
|
||||
conn2 = get_connection()
|
||||
cur2 = conn2.cursor()
|
||||
|
||||
# まず、条件なしでID 80が取得できるか確認
|
||||
cur2.execute("""
|
||||
SELECT journal_entry_id, description
|
||||
FROM journal_entries
|
||||
WHERE journal_entry_id = 80
|
||||
""")
|
||||
print(f"ID 80の存在確認: {cur2.fetchall()}")
|
||||
|
||||
# 各条件を個別にチェック
|
||||
cur2.execute("SELECT journal_entry_id FROM journal_entries WHERE journal_entry_id = 80 AND is_deleted = false")
|
||||
print(f"is_deleted=false: {len(cur2.fetchall())}件")
|
||||
|
||||
cur2.execute("SELECT journal_entry_id FROM journal_entries WHERE journal_entry_id = 80 AND description NOT LIKE '%[逆仕訳]%'")
|
||||
print(f"NOT LIKE '%%[逆仕訳]%%': {len(cur2.fetchall())}件")
|
||||
|
||||
cur2.execute("""
|
||||
SELECT journal_entry_id FROM journal_entries
|
||||
WHERE journal_entry_id = 80
|
||||
AND journal_entry_id NOT IN (SELECT parent_entry_id FROM journal_entries WHERE parent_entry_id IS NOT NULL)
|
||||
""")
|
||||
print(f"NOT IN parent_entry_id: {len(cur2.fetchall())}件")
|
||||
|
||||
cur2.execute("SELECT journal_entry_id FROM journal_entries WHERE journal_entry_id = 80 AND description LIKE '%逸速ビル%'")
|
||||
print(f"LIKE '%%逸速ビル%%': {len(cur2.fetchall())}件")
|
||||
|
||||
cur2.execute("SELECT journal_entry_id FROM journal_entries WHERE journal_entry_id = 80 AND description LIKE '%遠達ビル%'")
|
||||
print(f"LIKE '%%遠達ビル%%': {len(cur2.fetchall())}件")
|
||||
|
||||
sql = """
|
||||
SELECT
|
||||
je.journal_entry_id,
|
||||
je.entry_date,
|
||||
je.description,
|
||||
je.fiscal_year,
|
||||
je.version,
|
||||
COALESCE(SUM(jl.debit), 0) as debit_total,
|
||||
COALESCE(SUM(jl.credit), 0) as credit_total,
|
||||
STRING_AGG(DISTINCT CASE WHEN jl.tax_rate IS NOT NULL THEN jl.tax_rate::text END, ', ' ORDER BY CASE WHEN jl.tax_rate IS NOT NULL THEN jl.tax_rate::text END) as tax_rates
|
||||
FROM journal_entries je
|
||||
LEFT JOIN journal_lines jl ON je.journal_entry_id = jl.journal_entry_id
|
||||
WHERE je.is_deleted = false
|
||||
AND je.description NOT LIKE %s
|
||||
AND je.journal_entry_id NOT IN (
|
||||
SELECT parent_entry_id
|
||||
FROM journal_entries
|
||||
WHERE parent_entry_id IS NOT NULL
|
||||
)
|
||||
AND je.entry_date >= %s AND je.entry_date <= %s
|
||||
AND je.description LIKE %s
|
||||
GROUP BY je.journal_entry_id, je.entry_date, je.description, je.fiscal_year, je.version
|
||||
ORDER BY je.entry_date DESC, je.journal_entry_id DESC, je.version DESC
|
||||
"""
|
||||
|
||||
cur2.execute(sql, ['%[逆仕訳]%', '2025-06-01', '2025-06-30', '%逸速ビル%'])
|
||||
results = cur2.fetchall()
|
||||
|
||||
print(f"\n検索結果({len(results)}件):")
|
||||
for r in results:
|
||||
print(f"ID: {r['journal_entry_id']}, Date: {r['entry_date']}, Desc: {r['description']}, Tax: {r['tax_rates']}")
|
||||
|
||||
cur2.close()
|
||||
conn2.close()
|
||||
71
backend/check_data_debug.py
Normal file
71
backend/check_data_debug.py
Normal file
@@ -0,0 +1,71 @@
|
||||
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:
|
||||
print("=== 6月の普通預金(102)仕訳 ===")
|
||||
cur.execute("""
|
||||
SELECT
|
||||
je.journal_entry_id,
|
||||
je.entry_date,
|
||||
je.description,
|
||||
je.parent_entry_id,
|
||||
jl.debit,
|
||||
jl.credit
|
||||
FROM journal_entries je
|
||||
JOIN journal_lines jl ON jl.journal_entry_id = je.journal_entry_id
|
||||
JOIN accounts a ON a.account_id = jl.account_id
|
||||
WHERE je.entry_date BETWEEN '2025-06-01' AND '2025-06-30'
|
||||
AND a.account_code = '102'
|
||||
ORDER BY je.journal_entry_id
|
||||
""")
|
||||
|
||||
rows = cur.fetchall()
|
||||
for row in rows:
|
||||
print(f"ID: {row['journal_entry_id']:4d}, Parent: {str(row['parent_entry_id']):4s}, "
|
||||
f"Debit: {row['debit']:6.0f}, Credit: {row['credit']:6.0f}, "
|
||||
f"Desc: {row['description'][:50]}")
|
||||
|
||||
print("\n=== 試算表クエリでの除外状況 ===")
|
||||
cur.execute("""
|
||||
SELECT
|
||||
je.journal_entry_id,
|
||||
je.description,
|
||||
child.journal_entry_id as has_child,
|
||||
jl.debit,
|
||||
jl.credit,
|
||||
CASE
|
||||
WHEN je.description LIKE '[逆仕訳]%%' THEN '除外:逆仕訳'
|
||||
WHEN child.journal_entry_id IS NOT NULL THEN '除外:親仕訳'
|
||||
ELSE '計上'
|
||||
END as status
|
||||
FROM journal_entries je
|
||||
JOIN journal_lines jl ON jl.journal_entry_id = je.journal_entry_id
|
||||
LEFT JOIN journal_entries child ON child.parent_entry_id = je.journal_entry_id
|
||||
JOIN accounts a ON a.account_id = jl.account_id
|
||||
WHERE je.entry_date BETWEEN '2025-06-01' AND '2025-06-30'
|
||||
AND a.account_code = '102'
|
||||
AND je.is_deleted = false
|
||||
ORDER BY je.journal_entry_id
|
||||
""")
|
||||
|
||||
rows = cur.fetchall()
|
||||
total_debit = 0
|
||||
total_credit = 0
|
||||
for row in rows:
|
||||
status = row['status']
|
||||
if status == '計上':
|
||||
total_debit += float(row['debit'])
|
||||
total_credit += float(row['credit'])
|
||||
print(f"ID: {row['journal_entry_id']:4d}, Status: {status:12s}, "
|
||||
f"Debit: {row['debit']:6.0f}, Credit: {row['credit']:6.0f}, "
|
||||
f"Desc: {row['description'][:40]}")
|
||||
|
||||
print(f"\n計上される借方合計: {total_debit:.0f}")
|
||||
print(f"計上される貸方合計: {total_credit:.0f}")
|
||||
45
backend/check_parent_ids.py
Normal file
45
backend/check_parent_ids.py
Normal file
@@ -0,0 +1,45 @@
|
||||
from app.core.database import get_connection
|
||||
|
||||
with get_connection() as conn, conn.cursor() as cur:
|
||||
# 普通預金(102)の6月の仕訳を確認
|
||||
cur.execute('''
|
||||
SELECT
|
||||
je.journal_entry_id,
|
||||
je.entry_date,
|
||||
je.description,
|
||||
je.parent_entry_id,
|
||||
jl.debit,
|
||||
jl.credit,
|
||||
CASE WHEN child.journal_entry_id IS NOT NULL THEN 'Y' ELSE 'N' END as has_child
|
||||
FROM journal_entries je
|
||||
JOIN journal_lines jl ON jl.journal_entry_id = je.journal_entry_id
|
||||
LEFT JOIN journal_entries child ON child.parent_entry_id = je.journal_entry_id
|
||||
WHERE jl.account_id = (SELECT account_id FROM accounts WHERE account_code = '102')
|
||||
AND je.entry_date BETWEEN '2025-06-01' AND '2025-06-30'
|
||||
AND je.is_deleted = false
|
||||
ORDER BY je.journal_entry_id
|
||||
''')
|
||||
rows = cur.fetchall()
|
||||
|
||||
print('ID\t日付\t\t説明\t\t\t\t\tparent\t借方\t\t貸方\t\tchild?')
|
||||
print('='*120)
|
||||
for r in rows:
|
||||
desc = r['description'][:40].ljust(40)
|
||||
parent = str(r['parent_entry_id']) if r['parent_entry_id'] else '-'
|
||||
print(f"{r['journal_entry_id']}\t{r['entry_date']}\t{desc}\t{parent}\t{r['debit']}\t{r['credit']}\t{r['has_child']}")
|
||||
|
||||
print('\n集計(child=Nのみ):')
|
||||
cur.execute('''
|
||||
SELECT
|
||||
SUM(jl.debit) as total_debit,
|
||||
SUM(jl.credit) as total_credit
|
||||
FROM journal_entries je
|
||||
JOIN journal_lines jl ON jl.journal_entry_id = je.journal_entry_id
|
||||
LEFT JOIN journal_entries child ON child.parent_entry_id = je.journal_entry_id
|
||||
WHERE jl.account_id = (SELECT account_id FROM accounts WHERE account_code = '102')
|
||||
AND je.entry_date BETWEEN '2025-06-01' AND '2025-06-30'
|
||||
AND je.is_deleted = false
|
||||
AND child.journal_entry_id IS NULL
|
||||
''')
|
||||
result = cur.fetchone()
|
||||
print(f"借方: {result['total_debit']}, 貸方: {result['total_credit']}")
|
||||
93
backend/check_trial_balance.py
Normal file
93
backend/check_trial_balance.py
Normal file
@@ -0,0 +1,93 @@
|
||||
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'
|
||||
|
||||
import sys
|
||||
sys.path.insert(0, os.path.dirname(__file__))
|
||||
|
||||
from app.core.database import get_connection
|
||||
|
||||
conn = get_connection()
|
||||
cur = conn.cursor()
|
||||
|
||||
# 社会保険料関連の仕訳を確認
|
||||
print("\n=== 2025年4月 社会保険料の仕訳チェーン ===")
|
||||
cur.execute("""
|
||||
SELECT
|
||||
je.journal_entry_id,
|
||||
je.entry_date,
|
||||
je.description,
|
||||
je.parent_entry_id,
|
||||
je.is_deleted,
|
||||
CASE
|
||||
WHEN EXISTS (SELECT 1 FROM journal_entries child WHERE child.parent_entry_id = je.journal_entry_id)
|
||||
THEN 'Y' ELSE 'N'
|
||||
END as has_child
|
||||
FROM journal_entries je
|
||||
WHERE je.description LIKE '%2025年4月 社会保険料%'
|
||||
ORDER BY je.journal_entry_id
|
||||
""")
|
||||
|
||||
rows = cur.fetchall()
|
||||
for r in rows:
|
||||
print(f"ID:{r['journal_entry_id']:3d} 親:{r['parent_entry_id'] or '-':>3} 子:{r['has_child']} 削除:{r['is_deleted']} {r['description']}")
|
||||
|
||||
# 試算表と同じロジックで集計
|
||||
print("\n=== 試算表と同じロジックでの集計(2025-06-01~2025-06-30) ===")
|
||||
cur.execute("""
|
||||
SELECT
|
||||
je.journal_entry_id,
|
||||
je.entry_date,
|
||||
je.description,
|
||||
jl.debit,
|
||||
jl.credit,
|
||||
je.parent_entry_id,
|
||||
je.is_deleted,
|
||||
CASE
|
||||
WHEN EXISTS (SELECT 1 FROM journal_entries child WHERE child.parent_entry_id = je.journal_entry_id)
|
||||
THEN 'Y' ELSE 'N'
|
||||
END as has_child
|
||||
FROM journal_entries je
|
||||
JOIN journal_lines jl ON je.journal_entry_id = jl.journal_entry_id
|
||||
JOIN accounts a ON jl.account_id = a.account_id
|
||||
WHERE a.account_code = '102'
|
||||
AND je.entry_date BETWEEN '2025-06-01' AND '2025-06-30'
|
||||
AND je.description <> '前期残高'
|
||||
AND je.is_deleted = false
|
||||
ORDER BY je.journal_entry_id
|
||||
""")
|
||||
|
||||
print(f"\n{'ID':>3} {'日付':10} {'借方':>12} {'貸方':>12} {'親':>3} {'子':2} {'集計':4} 摘要")
|
||||
print("-" * 120)
|
||||
|
||||
total_debit_all = 0
|
||||
total_credit_all = 0
|
||||
total_debit_filtered = 0
|
||||
total_credit_filtered = 0
|
||||
|
||||
rows = cur.fetchall()
|
||||
for r in rows:
|
||||
total_debit_all += r['debit']
|
||||
total_credit_all += r['credit']
|
||||
|
||||
# 試算表のロジック: 子を持たない仕訳のみ集計
|
||||
should_include = r['has_child'] == 'N'
|
||||
|
||||
if should_include:
|
||||
total_debit_filtered += r['debit']
|
||||
total_credit_filtered += r['credit']
|
||||
|
||||
status = "集計" if should_include else "除外"
|
||||
parent_str = str(r['parent_entry_id']) if r['parent_entry_id'] else "-"
|
||||
|
||||
print(f"{r['journal_entry_id']:3d} {r['entry_date']} {r['debit']:>12,.0f} {r['credit']:>12,.0f} {parent_str:>3} {r['has_child']:2} {status:4} {r['description'][:60]}")
|
||||
|
||||
print("-" * 120)
|
||||
print(f"全仕訳: 借方={total_debit_all:>12,.0f} 貸方={total_credit_all:>12,.0f}")
|
||||
print(f"試算表集計: 借方={total_debit_filtered:>12,.0f} 貸方={total_credit_filtered:>12,.0f}")
|
||||
|
||||
cur.close()
|
||||
conn.close()
|
||||
25
backend/sql/fix_existing_data.sql
Normal file
25
backend/sql/fix_existing_data.sql
Normal file
@@ -0,0 +1,25 @@
|
||||
-- 既存の修正仕訳データを修正
|
||||
|
||||
-- 1. ID 80のis_deletedをfalseに設定(修正版は削除されていないはず)
|
||||
UPDATE journal_entries
|
||||
SET is_deleted = false
|
||||
WHERE journal_entry_id = 80;
|
||||
|
||||
-- 2. 最新の修正仕訳(【修正後】【修正後】など)のparent_entry_idが正しく設定されているか確認
|
||||
-- まず確認クエリ
|
||||
SELECT journal_entry_id, description, parent_entry_id, is_deleted
|
||||
FROM journal_entries
|
||||
WHERE description LIKE '%遠達ビル%'
|
||||
ORDER BY journal_entry_id;
|
||||
|
||||
-- 3. 修正チェーンを正しく設定
|
||||
-- ID 98: [逆仕訳] 【修正後】·遠達ビル 事務所費用 → parent_entry_idを80に設定
|
||||
UPDATE journal_entries SET parent_entry_id = 80 WHERE journal_entry_id = 98;
|
||||
|
||||
-- ID 99: 【修正後】【修正後】·遠達ビル 事務所費用 → parent_entry_idを98に設定
|
||||
UPDATE journal_entries SET parent_entry_id = 98 WHERE journal_entry_id = 99;
|
||||
|
||||
-- 4. すべての【修正後】仕訳のis_deletedをfalseに設定
|
||||
UPDATE journal_entries
|
||||
SET is_deleted = false
|
||||
WHERE description LIKE '【修正後】%';
|
||||
78
backend/sql/set_all_parent_entry_ids.sql
Normal file
78
backend/sql/set_all_parent_entry_ids.sql
Normal file
@@ -0,0 +1,78 @@
|
||||
-- 既存の全仕訳のparent_entry_idを一括設定
|
||||
|
||||
-- ステップ1: 現在の状況を確認
|
||||
SELECT
|
||||
journal_entry_id,
|
||||
entry_date,
|
||||
description,
|
||||
parent_entry_id,
|
||||
is_deleted
|
||||
FROM journal_entries
|
||||
ORDER BY entry_date, journal_entry_id;
|
||||
|
||||
-- ステップ2: [逆仕訳]のparent_entry_idを設定
|
||||
-- [逆仕訳]の直前の同じ日付・同じベース説明の仕訳を親とする
|
||||
UPDATE journal_entries je_reverse
|
||||
SET parent_entry_id = (
|
||||
SELECT je_original.journal_entry_id
|
||||
FROM journal_entries je_original
|
||||
WHERE je_original.entry_date = je_reverse.entry_date
|
||||
AND je_original.journal_entry_id < je_reverse.journal_entry_id
|
||||
AND REPLACE(je_reverse.description, '[逆仕訳] ', '') = je_original.description
|
||||
AND je_original.description NOT LIKE '[逆仕訳]%'
|
||||
ORDER BY je_original.journal_entry_id DESC
|
||||
LIMIT 1
|
||||
)
|
||||
WHERE je_reverse.description LIKE '[逆仕訳]%'
|
||||
AND je_reverse.parent_entry_id IS NULL;
|
||||
|
||||
-- ステップ3: 【修正後】のparent_entry_idを設定
|
||||
-- 【修正後】の直前の逆仕訳を親とする
|
||||
UPDATE journal_entries je_modified
|
||||
SET parent_entry_id = (
|
||||
SELECT je_reverse.journal_entry_id
|
||||
FROM journal_entries je_reverse
|
||||
WHERE je_reverse.journal_entry_id < je_modified.journal_entry_id
|
||||
AND je_reverse.description = '[逆仕訳] ' || REPLACE(je_modified.description, '【修正後】', '')
|
||||
ORDER BY je_reverse.journal_entry_id DESC
|
||||
LIMIT 1
|
||||
)
|
||||
WHERE je_modified.description LIKE '【修正後】%'
|
||||
AND je_modified.parent_entry_id IS NULL;
|
||||
|
||||
-- ステップ4: 複数の【修正後】プレフィックスがある場合の処理
|
||||
-- 【修正後】【修正後】などのケース
|
||||
UPDATE journal_entries je_modified
|
||||
SET parent_entry_id = (
|
||||
SELECT je_reverse.journal_entry_id
|
||||
FROM journal_entries je_reverse
|
||||
WHERE je_reverse.entry_date = je_modified.entry_date
|
||||
AND je_reverse.journal_entry_id < je_modified.journal_entry_id
|
||||
AND je_reverse.description LIKE '[逆仕訳]%'
|
||||
ORDER BY je_reverse.journal_entry_id DESC
|
||||
LIMIT 1
|
||||
)
|
||||
WHERE je_modified.description LIKE '【修正後】%'
|
||||
AND je_modified.parent_entry_id IS NULL;
|
||||
|
||||
-- ステップ5: 結果確認
|
||||
SELECT
|
||||
journal_entry_id,
|
||||
entry_date,
|
||||
LEFT(description, 50) as description,
|
||||
parent_entry_id,
|
||||
is_deleted
|
||||
FROM journal_entries
|
||||
WHERE parent_entry_id IS NOT NULL
|
||||
ORDER BY entry_date, journal_entry_id;
|
||||
|
||||
-- ステップ6: parent_entry_idが設定されていない逆仕訳・修正後を確認
|
||||
SELECT
|
||||
journal_entry_id,
|
||||
entry_date,
|
||||
LEFT(description, 50) as description,
|
||||
parent_entry_id
|
||||
FROM journal_entries
|
||||
WHERE (description LIKE '[逆仕訳]%' OR description LIKE '【修正後】%')
|
||||
AND parent_entry_id IS NULL
|
||||
ORDER BY journal_entry_id;
|
||||
@@ -1,5 +1,9 @@
|
||||
-- 修正後の仕訳に対して、元の仕訳IDをparent_entry_idに設定
|
||||
|
||||
-- 特定の修正チェーンを手動で設定(72 → 79 → 80)
|
||||
-- UPDATE journal_entries SET parent_entry_id = 72 WHERE journal_entry_id = 79;
|
||||
-- UPDATE journal_entries SET parent_entry_id = 79 WHERE journal_entry_id = 80;
|
||||
|
||||
-- ステップ1: 【修正後】の仕訳を確認
|
||||
SELECT
|
||||
je_modified.journal_entry_id as modified_id,
|
||||
|
||||
150
backend/verify_trial_balance.py
Normal file
150
backend/verify_trial_balance.py
Normal file
@@ -0,0 +1,150 @@
|
||||
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'
|
||||
|
||||
import sys
|
||||
sys.path.insert(0, os.path.dirname(__file__))
|
||||
|
||||
from app.core.database import get_connection
|
||||
|
||||
conn = get_connection()
|
||||
cur = conn.cursor()
|
||||
|
||||
print("\n" + "="*120)
|
||||
print("試算表ロジック検証 - 普通預金(102) 2025年6月")
|
||||
print("="*120)
|
||||
|
||||
# 試算表SQLと同じロジックで集計
|
||||
cur.execute("""
|
||||
SELECT
|
||||
jl.account_id,
|
||||
SUM(jl.debit) as total_debit,
|
||||
SUM(jl.credit) as total_credit
|
||||
FROM journal_entries je
|
||||
JOIN journal_lines jl ON jl.journal_entry_id = je.journal_entry_id
|
||||
LEFT JOIN journal_entries child ON child.parent_entry_id = je.journal_entry_id
|
||||
JOIN accounts a ON jl.account_id = a.account_id
|
||||
WHERE je.entry_date BETWEEN '2025-06-01' AND '2025-06-30'
|
||||
AND je.description <> '前期残高'
|
||||
AND je.is_deleted = false
|
||||
AND child.journal_entry_id IS NULL
|
||||
AND a.account_code = '102'
|
||||
GROUP BY jl.account_id
|
||||
""")
|
||||
|
||||
result = cur.fetchone()
|
||||
print(f"\n【試算表の集計結果】")
|
||||
print(f"借方発生額: {result['total_debit']:>15,.0f} 円")
|
||||
print(f"貸方発生額: {result['total_credit']:>15,.0f} 円")
|
||||
|
||||
# 詳細な内訳を確認
|
||||
print(f"\n{'='*120}")
|
||||
print("【集計対象の仕訳詳細】")
|
||||
print(f"{'='*120}")
|
||||
|
||||
cur.execute("""
|
||||
SELECT
|
||||
je.journal_entry_id,
|
||||
je.entry_date,
|
||||
je.description,
|
||||
jl.debit,
|
||||
jl.credit,
|
||||
je.parent_entry_id,
|
||||
CASE WHEN child.journal_entry_id IS NOT NULL THEN 'Y' ELSE 'N' END as has_child
|
||||
FROM journal_entries je
|
||||
JOIN journal_lines jl ON jl.journal_entry_id = je.journal_entry_id
|
||||
LEFT JOIN journal_entries child ON child.parent_entry_id = je.journal_entry_id
|
||||
JOIN accounts a ON jl.account_id = a.account_id
|
||||
WHERE je.entry_date BETWEEN '2025-06-01' AND '2025-06-30'
|
||||
AND je.description <> '前期残高'
|
||||
AND je.is_deleted = false
|
||||
AND a.account_code = '102'
|
||||
ORDER BY je.journal_entry_id
|
||||
""")
|
||||
|
||||
rows = cur.fetchall()
|
||||
|
||||
debit_sum = 0
|
||||
credit_sum = 0
|
||||
debit_included = 0
|
||||
credit_included = 0
|
||||
|
||||
print(f"\n{'ID':>3} {'日付':10} {'借方':>13} {'貸方':>13} {'親ID':>5} {'子':3} {'集計':4} 摘要")
|
||||
print("-" * 120)
|
||||
|
||||
for r in rows:
|
||||
is_included = r['has_child'] == 'N'
|
||||
status = "○" if is_included else "×"
|
||||
|
||||
debit_sum += r['debit']
|
||||
credit_sum += r['credit']
|
||||
|
||||
if is_included:
|
||||
debit_included += r['debit']
|
||||
credit_included += r['credit']
|
||||
|
||||
parent_str = str(r['parent_entry_id']) if r['parent_entry_id'] else "-"
|
||||
|
||||
# 逆仕訳・修正後をマーク
|
||||
desc = r['description'][:60]
|
||||
if '[逆仕訳]' in desc:
|
||||
desc = f"🔄 {desc}"
|
||||
elif '【修正後】' in desc:
|
||||
desc = f"✏️ {desc}"
|
||||
|
||||
print(f"{r['journal_entry_id']:3d} {r['entry_date']} {r['debit']:>13,.0f} {r['credit']:>13,.0f} {parent_str:>5} {r['has_child']:3} {status:4} {desc}")
|
||||
|
||||
print("-" * 120)
|
||||
print(f"{'全仕訳合計':62} {debit_sum:>13,.0f} {credit_sum:>13,.0f}")
|
||||
print(f"{'集計対象(子なし)':60} {debit_included:>13,.0f} {credit_included:>13,.0f}")
|
||||
|
||||
# parent_entry_idの問題を確認
|
||||
print(f"\n{'='*120}")
|
||||
print("【parent_entry_idチェーン確認】")
|
||||
print(f"{'='*120}")
|
||||
|
||||
cur.execute("""
|
||||
SELECT
|
||||
je.journal_entry_id as id,
|
||||
je.description,
|
||||
je.parent_entry_id as parent,
|
||||
(SELECT description FROM journal_entries WHERE journal_entry_id = je.parent_entry_id) as parent_desc,
|
||||
(SELECT COUNT(*) FROM journal_entries child WHERE child.parent_entry_id = je.journal_entry_id) as child_count
|
||||
FROM journal_entries je
|
||||
WHERE (je.description LIKE '%社会保険%' OR je.description LIKE '%遠達ビル%')
|
||||
AND je.entry_date BETWEEN '2025-06-01' AND '2025-06-30'
|
||||
ORDER BY je.journal_entry_id
|
||||
""")
|
||||
|
||||
print(f"\n{'ID':>3} {'親ID':>5} {'子数':>4} 摘要 → 親の摘要")
|
||||
print("-" * 120)
|
||||
|
||||
rows = cur.fetchall()
|
||||
for r in rows:
|
||||
parent_str = str(r['parent']) if r['parent'] else "-"
|
||||
parent_desc_str = r['parent_desc'][:40] if r['parent_desc'] else "-"
|
||||
print(f"{r['id']:3d} {parent_str:>5} {r['child_count']:>4} {r['description'][:50]}")
|
||||
if r['parent_desc']:
|
||||
print(f" └→ 親: {parent_desc_str}")
|
||||
|
||||
cur.close()
|
||||
conn.close()
|
||||
|
||||
print(f"\n{'='*120}")
|
||||
print("【結論】")
|
||||
print(f"{'='*120}")
|
||||
print("""
|
||||
正しい集計方法:
|
||||
1. parent_entry_idチェーンが正しく設定されている場合
|
||||
→ 最後の修正版のみが「子を持たない」状態になり、それのみが集計される
|
||||
|
||||
2. parent_entry_idの設定ミスがある場合
|
||||
→ 逆仕訳や途中の修正版も「子を持たない」と判定され、重複集計される
|
||||
|
||||
対策:
|
||||
- すべてのparent_entry_idを正しく設定する
|
||||
- チェーン: 元 → 逆仕訳 → 修正後 → 逆仕訳 → 修正後 → ...
|
||||
""")
|
||||
Reference in New Issue
Block a user