@kalbi/zeicheck 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -94,8 +94,11 @@ zeicheck explain <rule-id>
94
94
  | 家事按分妥当性 | ✅ | — | — |
95
95
  | 役員報酬妥当性 | — | — | ✅ |
96
96
  | 資本金1000万以下 | — | — | ✅ |
97
-
98
- > **注**: 給与所得者向けルールは今後追加予定です(源泉徴収税額検証、基礎控除確認等)。
97
+ | **給与所得者向け** | | | |
98
+ | 基礎控除額確認 | — | ✅ | — |
99
+ | 所得控除合計チェック | — | ✅ | — |
100
+ | 課税所得計算 | — | ✅ | — |
101
+ | 源泉徴収税額整合性 | — | ✅ | — |
99
102
 
100
103
  ## ルール一覧
101
104
 
@@ -103,19 +106,19 @@ zeicheck explain <rule-id>
103
106
 
104
107
  #### 貸借対照表 (Balance Sheet)
105
108
 
106
- | ルールID | 説明 | 重要度 |
109
+ | ルールID | 説明 | 重要度 | 備考 |
107
110
  | ------------------------------------ | ------------------------------ | ------- | ----- |
108
111
  | `balance-sheet/equation` | 資産合計 = 負債合計 + 資本合計 | error | ※共有 |
109
- | `balance-sheet/opening-owner-equity` | 事業主貸/借の期首残高が0 | error |
110
- | `balance-sheet/motoire-kin-formula` | 元入金繰越計算の検証 | error |
112
+ | `balance-sheet/opening-owner-equity` | 事業主貸/借の期首残高が0 | error | |
113
+ | `balance-sheet/motoire-kin-formula` | 元入金繰越計算の検証 | error | |
111
114
  | `balance-sheet/non-negative-cash` | 現金残高が負でないか | warning | ※共有 |
112
115
 
113
116
  #### 損益計算書 (Income Statement)
114
117
 
115
- | ルールID | 説明 | 重要度 |
118
+ | ルールID | 説明 | 重要度 | 備考 |
116
119
  | -------------------------------- | ------------------- | ------ | ----- |
117
- | `income-statement/pl-chain` | P/L各段階の計算検証 | error |
118
- | `income-statement/expense-total` | 経費合計の一致 | error |
120
+ | `income-statement/pl-chain` | P/L各段階の計算検証 | error | |
121
+ | `income-statement/expense-total` | 経費合計の一致 | error | |
119
122
  | `income-statement/cogs` | 売上原価の計算検証 | error | ※共有 |
120
123
 
121
124
  #### 帳票間整合性 (Cross-Statement)
@@ -153,6 +156,15 @@ zeicheck explain <rule-id>
153
156
  | ------------------------------ | ------------------ | ------- |
154
157
  | `home-office/reasonable-ratio` | 家事按分率の妥当性 | warning |
155
158
 
159
+ ### 給与所得者ルール(`applicableTo: ["individual"]`)
160
+
161
+ | ルールID | 説明 | 重要度 |
162
+ | ------------------------------ | ------------------------------ | ------- |
163
+ | `individual/basic-deduction` | 基礎控除が標準額(48万円)か | info |
164
+ | `individual/deduction-total` | 所得控除合計の一致 | error |
165
+ | `individual/taxable-income` | 課税所得 = 合計所得 − 控除合計 | error |
166
+ | `individual/withholding-total` | 源泉徴収税額の整合性 | warning |
167
+
156
168
  ### 法人ルール(`applicableTo: ["corporate"]`)
157
169
 
158
170
  | ルールID | 説明 | 重要度 |
@@ -1020,6 +1020,125 @@ var reasonableRatioRule = {
1020
1020
  }
1021
1021
  };
1022
1022
 
1023
+ // src/rules/individual/basic-deduction.ts
1024
+ var BASIC_DEDUCTION_STANDARD = yen(48e4);
1025
+ var basicDeductionRule = {
1026
+ meta: {
1027
+ id: "individual/basic-deduction",
1028
+ name: "\u57FA\u790E\u63A7\u9664\u984D\u78BA\u8A8D",
1029
+ description: "\u57FA\u790E\u63A7\u9664\u304C\u6A19\u6E96\u984D\uFF0848\u4E07\u5186\uFF09\u3067\u3042\u308B\u304B\u78BA\u8A8D\u3057\u307E\u3059\u3002\u5408\u8A08\u6240\u5F97\u91D1\u984D\u304C2,400\u4E07\u5186\u4EE5\u4E0B\u306E\u5834\u5408\u306F48\u4E07\u5186\u304C\u9069\u7528\u3055\u308C\u307E\u3059\u3002",
1030
+ severity: "info",
1031
+ applicableTo: ["individual"]
1032
+ },
1033
+ check(ctx) {
1034
+ if (ctx.taxReturn.returnType !== "individual") return [];
1035
+ const basic = ctx.taxReturn.taxFormB.basicDeduction;
1036
+ const diagnostics = [];
1037
+ if (basic !== BASIC_DEDUCTION_STANDARD && basic !== 0) {
1038
+ diagnostics.push({
1039
+ ruleId: this.meta.id,
1040
+ severity: this.meta.severity,
1041
+ message: `\u57FA\u790E\u63A7\u9664\u984D(${formatYen(basic)})\u304C\u6A19\u6E96\u984D(${formatYen(BASIC_DEDUCTION_STANDARD)})\u3068\u7570\u306A\u308A\u307E\u3059\u3002\u5408\u8A08\u6240\u5F97\u91D1\u984D\u304C2,400\u4E07\u5186\u8D85\u306E\u5834\u5408\u306F\u9013\u6E1B\u3055\u308C\u307E\u3059\u3002`,
1042
+ expected: `\u57FA\u790E\u63A7\u9664 = ${formatYen(BASIC_DEDUCTION_STANDARD)}\uFF08\u5408\u8A08\u6240\u5F972,400\u4E07\u5186\u4EE5\u4E0B\u306E\u5834\u5408\uFF09`
1043
+ });
1044
+ }
1045
+ return diagnostics;
1046
+ }
1047
+ };
1048
+
1049
+ // src/rules/individual/deduction-total.ts
1050
+ var deductionTotalRule = {
1051
+ meta: {
1052
+ id: "individual/deduction-total",
1053
+ name: "\u6240\u5F97\u63A7\u9664\u5408\u8A08\u30C1\u30A7\u30C3\u30AF",
1054
+ description: "\u7533\u544A\u66F8\u7B2C\u4E8C\u8868\u306E\u5404\u63A7\u9664\u9805\u76EE\u306E\u5408\u8A08\u304C\u7B2C\u4E00\u8868\u306E\u6240\u5F97\u63A7\u9664\u5408\u8A08\u3068\u4E00\u81F4\u3059\u308B\u304B\u78BA\u8A8D\u3057\u307E\u3059\u3002",
1055
+ severity: "error",
1056
+ applicableTo: ["individual"]
1057
+ },
1058
+ check(ctx) {
1059
+ if (ctx.taxReturn.returnType !== "individual") return [];
1060
+ const formA = ctx.taxReturn.taxFormA;
1061
+ const formB = ctx.taxReturn.taxFormB;
1062
+ const diagnostics = [];
1063
+ const computed = formB.socialInsurance + formB.smallBusinessMutualAid + formB.lifeInsurance + formB.earthquakeInsurance + formB.spouseDeduction + formB.dependentDeduction + formB.basicDeduction;
1064
+ if (computed !== formA.totalDeductions) {
1065
+ diagnostics.push({
1066
+ ruleId: this.meta.id,
1067
+ severity: this.meta.severity,
1068
+ message: `\u6240\u5F97\u63A7\u9664\u5408\u8A08(${formatYen(formA.totalDeductions)}) \u2260 \u5404\u63A7\u9664\u9805\u76EE\u306E\u5408\u7B97(${formatYen(computed)})`,
1069
+ expected: `\u6240\u5F97\u63A7\u9664\u5408\u8A08 = ${formatYen(computed)}`
1070
+ });
1071
+ }
1072
+ return diagnostics;
1073
+ }
1074
+ };
1075
+
1076
+ // src/rules/individual/taxable-income.ts
1077
+ var taxableIncomeRule = {
1078
+ meta: {
1079
+ id: "individual/taxable-income",
1080
+ name: "\u8AB2\u7A0E\u6240\u5F97\u8A08\u7B97\u30C1\u30A7\u30C3\u30AF",
1081
+ description: "\u8AB2\u7A0E\u3055\u308C\u308B\u6240\u5F97\u91D1\u984D\u304C\u5408\u8A08\u6240\u5F97\u91D1\u984D\u304B\u3089\u6240\u5F97\u63A7\u9664\u5408\u8A08\u3092\u5DEE\u3057\u5F15\u3044\u305F\u5024\u3068\u4E00\u81F4\u3059\u308B\u304B\u78BA\u8A8D\u3057\u307E\u3059\u3002",
1082
+ severity: "error",
1083
+ applicableTo: ["individual"]
1084
+ },
1085
+ check(ctx) {
1086
+ if (ctx.taxReturn.returnType !== "individual") return [];
1087
+ const form = ctx.taxReturn.taxFormA;
1088
+ const diagnostics = [];
1089
+ const expected = Math.max(
1090
+ 0,
1091
+ form.totalIncome - form.totalDeductions
1092
+ );
1093
+ if (form.taxableIncome !== expected) {
1094
+ diagnostics.push({
1095
+ ruleId: this.meta.id,
1096
+ severity: this.meta.severity,
1097
+ message: `\u8AB2\u7A0E\u6240\u5F97\u91D1\u984D(${formatYen(form.taxableIncome)}) \u2260 \u5408\u8A08\u6240\u5F97(${formatYen(form.totalIncome)}) \u2212 \u6240\u5F97\u63A7\u9664(${formatYen(form.totalDeductions)})`,
1098
+ expected: `\u8AB2\u7A0E\u6240\u5F97\u91D1\u984D = ${formatYen(expected)}`
1099
+ });
1100
+ }
1101
+ return diagnostics;
1102
+ }
1103
+ };
1104
+
1105
+ // src/rules/individual/withholding-total.ts
1106
+ var withholdingTotalRule = {
1107
+ meta: {
1108
+ id: "individual/withholding-total",
1109
+ name: "\u6E90\u6CC9\u5FB4\u53CE\u7A0E\u984D\u30C1\u30A7\u30C3\u30AF",
1110
+ description: "\u6240\u5F97\u306E\u5185\u8A33\u306B\u8A18\u8F09\u3055\u308C\u305F\u6E90\u6CC9\u5FB4\u53CE\u7A0E\u984D\u306E\u6574\u5408\u6027\u3092\u78BA\u8A8D\u3057\u307E\u3059\u3002\u7D66\u4E0E\u6240\u5F97\u8005\u306F\u901A\u5E38\u3001\u6E90\u6CC9\u5FB4\u53CE\u7A0E\u984D\u304C\u8A18\u8F09\u3055\u308C\u307E\u3059\u3002",
1111
+ severity: "warning",
1112
+ applicableTo: ["individual"]
1113
+ },
1114
+ check(ctx) {
1115
+ if (ctx.taxReturn.returnType !== "individual") return [];
1116
+ const details = ctx.taxReturn.taxFormB.incomeDetails;
1117
+ const diagnostics = [];
1118
+ if (details.length === 0) {
1119
+ diagnostics.push({
1120
+ ruleId: this.meta.id,
1121
+ severity: this.meta.severity,
1122
+ message: "\u6240\u5F97\u306E\u5185\u8A33\u304C\u672A\u8A18\u8F09\u3067\u3059\u3002\u7D66\u4E0E\u6240\u5F97\u8005\u306E\u5834\u5408\u306F\u6E90\u6CC9\u5FB4\u53CE\u7968\u306E\u60C5\u5831\u3092\u8A18\u8F09\u3057\u3066\u304F\u3060\u3055\u3044\u3002"
1123
+ });
1124
+ return diagnostics;
1125
+ }
1126
+ const totalWithheld = details.reduce(
1127
+ (sum, d) => sum + d.withheld,
1128
+ 0
1129
+ );
1130
+ if (totalWithheld === 0) {
1131
+ diagnostics.push({
1132
+ ruleId: this.meta.id,
1133
+ severity: this.meta.severity,
1134
+ message: "\u6E90\u6CC9\u5FB4\u53CE\u7A0E\u984D\u306E\u5408\u8A08\u304C0\u5186\u3067\u3059\u3002\u7D66\u4E0E\u6240\u5F97\u8005\u306E\u5834\u5408\u306F\u6E90\u6CC9\u5FB4\u53CE\u7A0E\u984D\u304C\u901A\u5E38\u5B58\u5728\u3057\u307E\u3059\u3002",
1135
+ expected: `\u6E90\u6CC9\u5FB4\u53CE\u7A0E\u984D\u5408\u8A08 > ${formatYen(0)}`
1136
+ });
1137
+ }
1138
+ return diagnostics;
1139
+ }
1140
+ };
1141
+
1023
1142
  // src/rules/corporate/bs-equation.ts
1024
1143
  var corporateBsEquationRule = {
1025
1144
  meta: {
@@ -1441,6 +1560,10 @@ registerRule(smallAssetThresholdRule);
1441
1560
  registerRule(openingClosingMatchRule);
1442
1561
  registerRule(yearOverYearChangeRule);
1443
1562
  registerRule(reasonableRatioRule);
1563
+ registerRule(basicDeductionRule);
1564
+ registerRule(deductionTotalRule);
1565
+ registerRule(taxableIncomeRule);
1566
+ registerRule(withholdingTotalRule);
1444
1567
  registerRule(corporateBsEquationRule);
1445
1568
  registerRule(corporatePlChainRule);
1446
1569
  registerRule(corporateExpenseTotalRule);
@@ -1479,10 +1602,10 @@ import { z } from "zod";
1479
1602
  var severitySchema = z.enum(["error", "warning", "info", "off"]);
1480
1603
  var ruleValueSchema = z.union([
1481
1604
  severitySchema,
1482
- z.tuple([severitySchema, z.record(z.unknown())])
1605
+ z.tuple([severitySchema, z.record(z.string(), z.unknown())])
1483
1606
  ]);
1484
1607
  var configSchema = z.object({
1485
- rules: z.record(ruleValueSchema).default({}),
1608
+ rules: z.record(z.string(), ruleValueSchema).default({}),
1486
1609
  priorYearFile: z.string().optional(),
1487
1610
  format: z.enum(["stylish", "json"]).default("stylish"),
1488
1611
  warningsAsErrors: z.boolean().default(false)
@@ -1644,4 +1767,4 @@ export {
1644
1767
  loadConfig,
1645
1768
  getFormatter
1646
1769
  };
1647
- //# sourceMappingURL=chunk-5PKY24GY.js.map
1770
+ //# sourceMappingURL=chunk-6ADWLQU7.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/models/types.ts","../src/parser/xtx-reader.ts","../src/parser/form-detector.ts","../src/parser/normalizer.ts","../src/parser/index.ts","../src/rules/rule-runner.ts","../src/utils/monetary.ts","../src/rules/balance-sheet/bs-equation.ts","../src/rules/income-statement/pl-arithmetic-chain.ts","../src/rules/income-statement/cogs-calculation.ts","../src/rules/income-statement/expense-total.ts","../src/rules/cross-statement/bs-pl-bridge.ts","../src/rules/balance-sheet/opening-owner-equity.ts","../src/rules/balance-sheet/motoire-kin-formula.ts","../src/rules/balance-sheet/non-negative-cash.ts","../src/rules/deductions/blue-deduction-cap.ts","../src/rules/deductions/blue-deduction-eligibility.ts","../src/rules/depreciation/useful-life-rates.ts","../src/rules/depreciation/small-asset-threshold.ts","../src/rules/cross-statement/decision-to-return.ts","../src/rules/cross-statement/depreciation-sum.ts","../src/rules/continuity/opening-closing-match.ts","../src/rules/continuity/year-over-year-change.ts","../src/rules/home-office/reasonable-ratio.ts","../src/rules/individual/basic-deduction.ts","../src/rules/individual/deduction-total.ts","../src/rules/individual/taxable-income.ts","../src/rules/individual/withholding-total.ts","../src/rules/corporate/bs-equation.ts","../src/rules/corporate/pl-chain.ts","../src/rules/corporate/expense-total.ts","../src/rules/corporate/bs-pl-bridge.ts","../src/rules/corporate/betsu4-accounting-profit.ts","../src/rules/corporate/betsu4-taxable-income.ts","../src/rules/corporate/betsu1-match.ts","../src/rules/corporate/capital-under-10m.ts","../src/rules/corporate/officer-compensation.ts","../src/rules/corporate/entertainment-limit.ts","../src/rules/corporate/small-corp-tax-rate.ts","../src/rules/corporate/retained-earnings-continuity.ts","../src/rules/index.ts","../src/config/index.ts","../src/utils/errors.ts","../src/config/defaults.ts","../src/config/schema.ts","../src/cli/formatter/stylish.ts","../src/cli/formatter/json.ts","../src/cli/formatter/index.ts"],"sourcesContent":["/**\n * Core types for zeicheck tax return models.\n */\n\n/** Branded type for integer yen amounts. Prevents accidental float usage. */\nexport type Yen = number & { readonly __brand: unique symbol };\n\n/** Create a Yen value from a number. Truncates to integer. */\nexport function yen(n: number): Yen {\n return Math.trunc(n) as Yen;\n}\n\n/** Fiscal year representation */\nexport interface FiscalYear {\n /** 和暦年 (e.g., 5 for 令和5年) */\n readonly nengo: number;\n /** 西暦年 (e.g., 2023) */\n readonly year: number;\n /** 期首日 */\n readonly startDate: string;\n /** 期末日 */\n readonly endDate: string;\n}\n\n/** Account balance with opening and closing amounts */\nexport interface AccountBalance {\n readonly opening: Yen;\n readonly closing: Yen;\n}\n\n/** 申告区分(個人事業主/個人/法人) */\nexport type TaxReturnType = \"sole-proprietor\" | \"individual\" | \"corporate\";\n\n/** Form types in e-Tax xtx files */\nexport enum FormType {\n /** 申告書第一表 */\n ABA = \"ABA\",\n /** 申告書第二表 */\n ABB = \"ABB\",\n /** 青色申告決算書(一般用) */\n VCA = \"VCA\",\n /** 法人税申告書 別表一 */\n HOA = \"HOA\",\n /** 法人税申告書 別表四 */\n HOD = \"HOD\",\n /** 法人決算書 */\n HOK = \"HOK\",\n}\n\n/** Metadata about the tax return */\nexport interface TaxReturnMetadata {\n readonly filePath: string;\n readonly formTypes: FormType[];\n readonly filingMethod?: string;\n}\n","/**\n * Reads and parses .xtx (XML) files into ParsedXtxFile structures.\n */\n\nimport { readFile } from \"node:fs/promises\";\nimport { XMLParser } from \"fast-xml-parser\";\nimport type { ParsedForm, ParsedXtxFile } from \"./types.js\";\n\nconst parser = new XMLParser({\n ignoreAttributes: false,\n attributeNamePrefix: \"@_\",\n isArray: (_name: string, jpath: string) => {\n // Ensure FormData and Field are always arrays\n return jpath === \"DataRoot.FormData\" || /\\.FormData\\.Field$/.test(jpath);\n },\n});\n\ninterface XmlField {\n \"#text\"?: string;\n \"@_id\": string;\n}\n\ninterface XmlFormData {\n \"@_id\": string;\n Field?: XmlField[];\n}\n\ninterface XmlDataRoot {\n DataRoot: {\n FormData?: XmlFormData[];\n };\n}\n\nfunction parseXml(xml: string): ParsedXtxFile {\n const result = parser.parse(xml) as XmlDataRoot;\n\n const root = result.DataRoot;\n if (!root) {\n throw new Error(\"Invalid xtx: missing DataRoot element\");\n }\n\n const formDataArray = root.FormData ?? [];\n const forms: ParsedForm[] = formDataArray.map((fd) => {\n const fields = new Map<string, string>();\n const xmlFields = fd.Field ?? [];\n for (const field of xmlFields) {\n const value = field[\"#text\"] != null ? String(field[\"#text\"]) : \"\";\n fields.set(field[\"@_id\"], value);\n }\n return {\n formType: fd[\"@_id\"],\n fields,\n };\n });\n\n return { forms, rawXml: xml };\n}\n\n/** Parse an xtx XML string into a structured ParsedXtxFile. */\nexport function readXtxString(xml: string): ParsedXtxFile {\n return parseXml(xml);\n}\n\n/** Read and parse an xtx file from the filesystem. */\nexport async function readXtxFile(filePath: string): Promise<ParsedXtxFile> {\n const xml = await readFile(filePath, \"utf-8\");\n return parseXml(xml);\n}\n","/**\n * Detects which form types are present in a parsed xtx file.\n */\n\nimport { FormType } from \"../models/types.js\";\nimport type { ParsedXtxFile } from \"./types.js\";\n\nconst knownForms: ReadonlyMap<string, FormType> = new Map([\n [\"ABA\", FormType.ABA],\n [\"ABB\", FormType.ABB],\n [\"VCA\", FormType.VCA],\n [\"HOA\", FormType.HOA],\n [\"HOD\", FormType.HOD],\n [\"HOK\", FormType.HOK],\n]);\n\n/** Detect FormType enum values from parsed forms. */\nexport function detectForms(parsed: ParsedXtxFile): FormType[] {\n const detected: FormType[] = [];\n for (const form of parsed.forms) {\n const formType = knownForms.get(form.formType);\n if (formType !== undefined) {\n detected.push(formType);\n }\n }\n return detected;\n}\n","/**\n * Normalizes a ParsedXtxFile into a typed TaxReturn model.\n */\n\nimport type { BalanceSheet } from \"../models/balance-sheet.js\";\nimport type { CorporateBalanceSheet } from \"../models/corporate-balance-sheet.js\";\nimport type { CorporateIncomeStatement } from \"../models/corporate-income-statement.js\";\nimport type {\n CorporateInfo,\n CorporateTaxFormMain,\n IncomeAdjustmentSchedule,\n} from \"../models/corporate-tax-form.js\";\nimport type { DepreciationSchedule } from \"../models/depreciation-schedule.js\";\nimport type { IncomeStatement } from \"../models/income-statement.js\";\nimport type { TaxFormA, TaxFormB } from \"../models/tax-form.js\";\nimport {\n FormType,\n yen,\n type AccountBalance,\n type FiscalYear,\n type Yen,\n} from \"../models/types.js\";\nimport type {\n SoleProprietorReturn,\n IndividualReturn,\n CorporateReturn,\n TaxReturn,\n} from \"../models/tax-return.js\";\nimport { detectForms } from \"./form-detector.js\";\nimport type { ParsedXtxFile } from \"./types.js\";\n\n/** Read a yen value from a field map, defaulting to 0. */\nfunction yenField(fields: Map<string, string>, code: string): Yen {\n const raw = fields.get(code);\n return yen(raw ? Number(raw) : 0);\n}\n\n/** Build an AccountBalance from opening/closing field codes. */\nfunction accountBalance(\n fields: Map<string, string>,\n openingCode: string,\n closingCode: string,\n): AccountBalance {\n return {\n opening: yenField(fields, openingCode),\n closing: yenField(fields, closingCode),\n };\n}\n\nfunction getFormFields(\n parsed: ParsedXtxFile,\n formType: string,\n): Map<string, string> {\n const form = parsed.forms.find((f) => f.formType === formType);\n return form?.fields ?? new Map();\n}\n\n// ── Sole Proprietor builders ──\n\nfunction buildIncomeStatement(vca: Map<string, string>): IncomeStatement {\n return {\n revenue: yenField(vca, \"ITA_VCA0010\"),\n cogs: {\n openingInventory: yenField(vca, \"ITA_VCA0020\"),\n purchases: yenField(vca, \"ITA_VCA0030\"),\n closingInventory: yenField(vca, \"ITA_VCA0040\"),\n total: yenField(vca, \"ITA_VCA0050\"),\n },\n grossProfit: yenField(vca, \"ITA_VCA0060\"),\n expenses: {\n taxes: yenField(vca, \"ITA_VCA0100\"),\n insurance: yenField(vca, \"ITA_VCA0110\"),\n repairs: yenField(vca, \"ITA_VCA0120\"),\n depreciation: yenField(vca, \"ITA_VCA0130\"),\n welfare: yenField(vca, \"ITA_VCA0140\"),\n salaries: yenField(vca, \"ITA_VCA0150\"),\n outsourcing: yenField(vca, \"ITA_VCA0160\"),\n interest: yenField(vca, \"ITA_VCA0170\"),\n rent: yenField(vca, \"ITA_VCA0180\"),\n retirement: yenField(vca, \"ITA_VCA0190\"),\n utilities: yenField(vca, \"ITA_VCA0200\"),\n travel: yenField(vca, \"ITA_VCA0210\"),\n communication: yenField(vca, \"ITA_VCA0220\"),\n advertising: yenField(vca, \"ITA_VCA0230\"),\n entertainment: yenField(vca, \"ITA_VCA0240\"),\n consumables: yenField(vca, \"ITA_VCA0250\"),\n miscellaneous: yenField(vca, \"ITA_VCA0260\"),\n otherExpenses: yenField(vca, \"ITA_VCA0270\"),\n },\n totalExpenses: yenField(vca, \"ITA_VCA0280\"),\n operatingIncome: yenField(vca, \"ITA_VCA0290\"),\n };\n}\n\nfunction buildBalanceSheet(vca: Map<string, string>): BalanceSheet {\n return {\n // Assets\n cash: accountBalance(vca, \"ITA_VCA1010\", \"ITA_VCA1210\"),\n deposits: accountBalance(vca, \"ITA_VCA1020\", \"ITA_VCA1220\"),\n accountsReceivable: accountBalance(vca, \"ITA_VCA1030\", \"ITA_VCA1230\"),\n inventory: accountBalance(vca, \"ITA_VCA1040\", \"ITA_VCA1240\"),\n otherCurrentAssets: accountBalance(vca, \"ITA_VCA1050\", \"ITA_VCA1250\"),\n buildings: accountBalance(vca, \"ITA_VCA1060\", \"ITA_VCA1260\"),\n buildingImprovements: accountBalance(vca, \"ITA_VCA1070\", \"ITA_VCA1270\"),\n machinery: accountBalance(vca, \"ITA_VCA1080\", \"ITA_VCA1280\"),\n vehicles: accountBalance(vca, \"ITA_VCA1090\", \"ITA_VCA1290\"),\n tools: accountBalance(vca, \"ITA_VCA1100\", \"ITA_VCA1300\"),\n land: accountBalance(vca, \"ITA_VCA1110\", \"ITA_VCA1310\"),\n otherFixedAssets: accountBalance(vca, \"ITA_VCA1120\", \"ITA_VCA1320\"),\n accumulatedDepreciation: accountBalance(vca, \"ITA_VCA1130\", \"ITA_VCA1330\"),\n assetsTotal: accountBalance(vca, \"ITA_VCA1140\", \"ITA_VCA1340\"),\n\n // Liabilities\n accountsPayable: accountBalance(vca, \"ITA_VCA1410\", \"ITA_VCA1510\"),\n borrowings: accountBalance(vca, \"ITA_VCA1420\", \"ITA_VCA1520\"),\n otherCurrentLiabilities: accountBalance(vca, \"ITA_VCA1430\", \"ITA_VCA1530\"),\n liabilitiesTotal: accountBalance(vca, \"ITA_VCA1440\", \"ITA_VCA1540\"),\n\n // Equity\n ownerEquity: accountBalance(vca, \"ITA_VCA1610\", \"ITA_VCA1710\"),\n ownerDrawings: accountBalance(vca, \"ITA_VCA1620\", \"ITA_VCA1720\"),\n ownerContributions: accountBalance(vca, \"ITA_VCA1630\", \"ITA_VCA1730\"),\n retainedEarnings: yenField(vca, \"ITA_VCA1640\"),\n equityTotal: accountBalance(vca, \"ITA_VCA1650\", \"ITA_VCA1750\"),\n };\n}\n\nfunction buildTaxFormA(aba: Map<string, string>): TaxFormA {\n return {\n businessIncome: yenField(aba, \"ITA_ABA0010\"),\n realEstateIncome: yenField(aba, \"ITA_ABA0020\"),\n otherIncome: yenField(aba, \"ITA_ABA0030\"),\n businessProfit: yenField(aba, \"ITA_ABA0110\"),\n realEstateProfit: yenField(aba, \"ITA_ABA0120\"),\n totalIncome: yenField(aba, \"ITA_ABA0130\"),\n totalDeductions: yenField(aba, \"ITA_ABA0280\"),\n blueReturnDeduction: yenField(aba, \"ITA_ABA0290\"),\n taxableIncome: yenField(aba, \"ITA_ABA0310\"),\n incomeTax: yenField(aba, \"ITA_ABA0320\"),\n taxDue: yenField(aba, \"ITA_ABA0360\"),\n };\n}\n\nfunction buildTaxFormB(abb: Map<string, string>): TaxFormB {\n return {\n incomeDetails: [\n {\n type: abb.get(\"ITA_ABB0010\") ?? \"\",\n payer: abb.get(\"ITA_ABB0020\") ?? \"\",\n amount: yenField(abb, \"ITA_ABB0030\"),\n withheld: yenField(abb, \"ITA_ABB0040\"),\n },\n ],\n socialInsurance: yenField(abb, \"ITA_ABB0110\"),\n smallBusinessMutualAid: yenField(abb, \"ITA_ABB0120\"),\n lifeInsurance: yenField(abb, \"ITA_ABB0130\"),\n earthquakeInsurance: yenField(abb, \"ITA_ABB0140\"),\n spouseDeduction: yenField(abb, \"ITA_ABB0210\"),\n dependentDeduction: yenField(abb, \"ITA_ABB0220\"),\n basicDeduction: yenField(abb, \"ITA_ABB0230\"),\n };\n}\n\n// ── Corporate builders ──\n\nfunction buildCorporateIncomeStatement(\n hok: Map<string, string>,\n): CorporateIncomeStatement {\n return {\n revenue: yenField(hok, \"ITA_HOK0010\"),\n cogs: {\n openingInventory: yenField(hok, \"ITA_HOK0020\"),\n purchases: yenField(hok, \"ITA_HOK0030\"),\n closingInventory: yenField(hok, \"ITA_HOK0040\"),\n total: yenField(hok, \"ITA_HOK0050\"),\n },\n grossProfit: yenField(hok, \"ITA_HOK0060\"),\n expenses: {\n taxes: yenField(hok, \"ITA_HOK0100\"),\n insurance: yenField(hok, \"ITA_HOK0110\"),\n repairs: yenField(hok, \"ITA_HOK0120\"),\n depreciation: yenField(hok, \"ITA_HOK0130\"),\n welfare: yenField(hok, \"ITA_HOK0140\"),\n salaries: yenField(hok, \"ITA_HOK0150\"),\n outsourcing: yenField(hok, \"ITA_HOK0160\"),\n interest: yenField(hok, \"ITA_HOK0170\"),\n rent: yenField(hok, \"ITA_HOK0180\"),\n retirement: yenField(hok, \"ITA_HOK0190\"),\n utilities: yenField(hok, \"ITA_HOK0200\"),\n travel: yenField(hok, \"ITA_HOK0210\"),\n communication: yenField(hok, \"ITA_HOK0220\"),\n advertising: yenField(hok, \"ITA_HOK0230\"),\n entertainment: yenField(hok, \"ITA_HOK0240\"),\n consumables: yenField(hok, \"ITA_HOK0250\"),\n miscellaneous: yenField(hok, \"ITA_HOK0260\"),\n otherExpenses: yenField(hok, \"ITA_HOK0270\"),\n },\n totalExpenses: yenField(hok, \"ITA_HOK0280\"),\n operatingIncome: yenField(hok, \"ITA_HOK0290\"),\n nonOperatingIncome: yenField(hok, \"ITA_HOK0300\"),\n nonOperatingExpenses: yenField(hok, \"ITA_HOK0310\"),\n ordinaryIncome: yenField(hok, \"ITA_HOK0320\"),\n extraordinaryGain: yenField(hok, \"ITA_HOK0330\"),\n extraordinaryLoss: yenField(hok, \"ITA_HOK0340\"),\n preTaxIncome: yenField(hok, \"ITA_HOK0350\"),\n corporateTax: yenField(hok, \"ITA_HOK0360\"),\n netIncome: yenField(hok, \"ITA_HOK0370\"),\n };\n}\n\nfunction buildCorporateBalanceSheet(\n hok: Map<string, string>,\n): CorporateBalanceSheet {\n return {\n // Assets\n cash: accountBalance(hok, \"ITA_HOK1010\", \"ITA_HOK1210\"),\n deposits: accountBalance(hok, \"ITA_HOK1020\", \"ITA_HOK1220\"),\n accountsReceivable: accountBalance(hok, \"ITA_HOK1030\", \"ITA_HOK1230\"),\n inventory: accountBalance(hok, \"ITA_HOK1040\", \"ITA_HOK1240\"),\n otherCurrentAssets: accountBalance(hok, \"ITA_HOK1050\", \"ITA_HOK1250\"),\n buildings: accountBalance(hok, \"ITA_HOK1060\", \"ITA_HOK1260\"),\n buildingImprovements: accountBalance(hok, \"ITA_HOK1070\", \"ITA_HOK1270\"),\n machinery: accountBalance(hok, \"ITA_HOK1080\", \"ITA_HOK1280\"),\n vehicles: accountBalance(hok, \"ITA_HOK1090\", \"ITA_HOK1290\"),\n tools: accountBalance(hok, \"ITA_HOK1100\", \"ITA_HOK1300\"),\n land: accountBalance(hok, \"ITA_HOK1110\", \"ITA_HOK1310\"),\n otherFixedAssets: accountBalance(hok, \"ITA_HOK1120\", \"ITA_HOK1320\"),\n accumulatedDepreciation: accountBalance(hok, \"ITA_HOK1130\", \"ITA_HOK1330\"),\n assetsTotal: accountBalance(hok, \"ITA_HOK1140\", \"ITA_HOK1340\"),\n\n // Liabilities\n accountsPayable: accountBalance(hok, \"ITA_HOK1410\", \"ITA_HOK1510\"),\n borrowings: accountBalance(hok, \"ITA_HOK1420\", \"ITA_HOK1520\"),\n accruedExpenses: accountBalance(hok, \"ITA_HOK1430\", \"ITA_HOK1530\"),\n corporateTaxPayable: accountBalance(hok, \"ITA_HOK1440\", \"ITA_HOK1540\"),\n otherCurrentLiabilities: accountBalance(hok, \"ITA_HOK1450\", \"ITA_HOK1550\"),\n liabilitiesTotal: accountBalance(hok, \"ITA_HOK1460\", \"ITA_HOK1560\"),\n\n // Net Assets\n capitalStock: accountBalance(hok, \"ITA_HOK1610\", \"ITA_HOK1710\"),\n capitalSurplus: accountBalance(hok, \"ITA_HOK1620\", \"ITA_HOK1720\"),\n retainedEarnings: accountBalance(hok, \"ITA_HOK1630\", \"ITA_HOK1730\"),\n netIncome: yenField(hok, \"ITA_HOK0370\"),\n equityTotal: accountBalance(hok, \"ITA_HOK1650\", \"ITA_HOK1750\"),\n };\n}\n\nfunction buildCorporateTaxForm(hoa: Map<string, string>): CorporateTaxFormMain {\n return {\n taxableIncome: yenField(hoa, \"ITA_HOA0010\"),\n corporateTaxAmount: yenField(hoa, \"ITA_HOA0020\"),\n taxCredits: yenField(hoa, \"ITA_HOA0030\"),\n localCorporateTax: yenField(hoa, \"ITA_HOA0040\"),\n taxDue: yenField(hoa, \"ITA_HOA0050\"),\n };\n}\n\nfunction buildIncomeAdjustment(\n hod: Map<string, string>,\n): IncomeAdjustmentSchedule {\n return {\n accountingProfit: yenField(hod, \"ITA_HOD0010\"),\n addBackTotal: yenField(hod, \"ITA_HOD0020\"),\n deductionTotal: yenField(hod, \"ITA_HOD0030\"),\n taxableIncome: yenField(hod, \"ITA_HOD0040\"),\n };\n}\n\nfunction buildCorporateInfo(hok: Map<string, string>): CorporateInfo {\n const capitalRaw = hok.get(\"ITA_HOK1710\");\n const capitalAmount = yen(capitalRaw ? Number(capitalRaw) : 0);\n const monthsRaw = hok.get(\"ITA_HOK9010\");\n const fiscalYearMonths = monthsRaw ? Number(monthsRaw) : 12;\n const officerRaw = hok.get(\"ITA_HOK9020\");\n const officerCount = officerRaw ? Number(officerRaw) : 1;\n\n return {\n capitalAmount,\n fiscalYearMonths,\n isSmallCorp: capitalAmount <= 10_000_000,\n officerCount,\n };\n}\n\n// ── Shared helpers ──\n\nfunction buildDefaultFiscalYear(): FiscalYear {\n return {\n nengo: 5,\n year: 2023,\n startDate: \"2023-01-01\",\n endDate: \"2023-12-31\",\n };\n}\n\nfunction buildEmptyDepreciationSchedule(): DepreciationSchedule {\n return {\n assets: [],\n totalDepreciation: yen(0),\n totalBusinessDepreciation: yen(0),\n };\n}\n\n/** Check if the parsed file contains corporate form types (HOK). */\nfunction isCorporateReturn(parsed: ParsedXtxFile): boolean {\n return parsed.forms.some((f) => f.formType === \"HOK\");\n}\n\n/** Check if the parsed file contains sole-proprietor form types (VCA). */\nfunction isSoleProprietorReturn(parsed: ParsedXtxFile): boolean {\n return parsed.forms.some((f) => f.formType === \"VCA\");\n}\n\n/** Normalize as sole-proprietor return (個人事業主・青色申告). */\nfunction normalizeSoleProprietor(\n parsed: ParsedXtxFile,\n formTypes: FormType[],\n): SoleProprietorReturn {\n const vca = getFormFields(parsed, \"VCA\");\n const aba = getFormFields(parsed, \"ABA\");\n const abb = getFormFields(parsed, \"ABB\");\n\n return {\n returnType: \"sole-proprietor\",\n fiscalYear: buildDefaultFiscalYear(),\n incomeStatement: buildIncomeStatement(vca),\n balanceSheet: buildBalanceSheet(vca),\n taxFormA: buildTaxFormA(aba),\n taxFormB: buildTaxFormB(abb),\n depreciationSchedule: buildEmptyDepreciationSchedule(),\n metadata: {\n filePath: \"\",\n formTypes,\n },\n };\n}\n\n/** Normalize as individual return (給与所得者等の確定申告). */\nfunction normalizeIndividual(\n parsed: ParsedXtxFile,\n formTypes: FormType[],\n): IndividualReturn {\n const aba = getFormFields(parsed, \"ABA\");\n const abb = getFormFields(parsed, \"ABB\");\n\n return {\n returnType: \"individual\",\n fiscalYear: buildDefaultFiscalYear(),\n taxFormA: buildTaxFormA(aba),\n taxFormB: buildTaxFormB(abb),\n metadata: {\n filePath: \"\",\n formTypes,\n },\n };\n}\n\n/** Normalize as corporate return. */\nfunction normalizeCorporate(\n parsed: ParsedXtxFile,\n formTypes: FormType[],\n): CorporateReturn {\n const hok = getFormFields(parsed, \"HOK\");\n const hoa = getFormFields(parsed, \"HOA\");\n const hod = getFormFields(parsed, \"HOD\");\n\n return {\n returnType: \"corporate\",\n fiscalYear: buildDefaultFiscalYear(),\n incomeStatement: buildCorporateIncomeStatement(hok),\n balanceSheet: buildCorporateBalanceSheet(hok),\n corporateTaxForm: buildCorporateTaxForm(hoa),\n incomeAdjustment: buildIncomeAdjustment(hod),\n corporateInfo: buildCorporateInfo(hok),\n depreciationSchedule: buildEmptyDepreciationSchedule(),\n metadata: {\n filePath: \"\",\n formTypes,\n },\n };\n}\n\n/**\n * Convert a ParsedXtxFile into a typed TaxReturn.\n *\n * Detection order:\n * 1. HOK form present → corporate\n * 2. VCA form present → sole-proprietor (個人事業主)\n * 3. Otherwise → individual (給与所得者等)\n */\nexport function normalize(parsed: ParsedXtxFile): TaxReturn {\n const formTypes = detectForms(parsed);\n\n if (isCorporateReturn(parsed)) {\n return normalizeCorporate(parsed, formTypes);\n }\n\n if (isSoleProprietorReturn(parsed)) {\n return normalizeSoleProprietor(parsed, formTypes);\n }\n\n return normalizeIndividual(parsed, formTypes);\n}\n","/**\n * Public API for the parser module.\n */\n\nexport type { ParsedField, ParsedForm, ParsedXtxFile } from \"./types.js\";\nexport { readXtxFile, readXtxString } from \"./xtx-reader.js\";\nexport { detectForms } from \"./form-detector.js\";\nexport { getFieldName } from \"./field-registry.js\";\nexport { normalize } from \"./normalizer.js\";\n\nimport type { TaxReturn } from \"../models/tax-return.js\";\nimport { normalize } from \"./normalizer.js\";\nimport { readXtxFile as readFile, readXtxString as readString } from \"./xtx-reader.js\";\n\n/** Parse an xtx file from disk and return a typed TaxReturn. */\nexport async function parseXtxFile(filePath: string): Promise<TaxReturn> {\n const parsed = await readFile(filePath);\n const taxReturn = normalize(parsed);\n return {\n ...taxReturn,\n metadata: { ...taxReturn.metadata, filePath },\n };\n}\n\n/** Parse an xtx XML string and return a typed TaxReturn. */\nexport function parseXtxString(xml: string): TaxReturn {\n const parsed = readString(xml);\n return normalize(parsed);\n}\n","import type { Rule, RuleContext, RuleDiagnostic, Severity } from \"./types.js\";\n\nconst severityOrder: Record<Severity, number> = {\n error: 0,\n warning: 1,\n info: 2,\n off: 3,\n};\n\nexport function runRules(rules: Rule[], ctx: RuleContext): RuleDiagnostic[] {\n const diagnostics: RuleDiagnostic[] = [];\n\n for (const rule of rules) {\n const configEntry = ctx.config.rules[rule.meta.id];\n const severity: Severity = Array.isArray(configEntry)\n ? configEntry[0]\n : configEntry ?? rule.meta.severity;\n\n if (severity === \"off\") continue;\n\n const { applicableTo } = rule.meta;\n if (applicableTo && !applicableTo.includes(ctx.taxReturn.returnType)) continue;\n\n const results = rule.check(ctx);\n for (const diag of results) {\n diagnostics.push({ ...diag, severity });\n }\n }\n\n diagnostics.sort((a, b) => severityOrder[a.severity] - severityOrder[b.severity]);\n return diagnostics;\n}\n","/**\n * Safe integer-yen arithmetic utilities.\n * Japanese tax returns use only whole yen amounts.\n */\n\nimport { type Yen, yen } from \"../models/types.js\";\n\n/** Add two Yen amounts */\nexport function add(a: Yen, b: Yen): Yen {\n return yen(a + b);\n}\n\n/** Subtract b from a */\nexport function subtract(a: Yen, b: Yen): Yen {\n return yen(a - b);\n}\n\n/** Sum an array of Yen amounts */\nexport function sum(items: readonly Yen[]): Yen {\n return yen(items.reduce((acc, v) => acc + v, 0));\n}\n\n/** Check if a Yen amount is non-negative */\nexport function isNonNegative(a: Yen): boolean {\n return a >= 0;\n}\n\n/** Check if two Yen amounts are equal */\nexport function equals(a: Yen, b: Yen): boolean {\n return a === b;\n}\n\n/** Format a Yen amount with comma separators (e.g., \"1,234,567\") */\nexport function formatYen(a: Yen): string {\n return a.toLocaleString(\"ja-JP\");\n}\n","import { formatYen } from \"../../utils/monetary.js\";\nimport { yen } from \"../../models/types.js\";\nimport type { Rule, RuleContext, RuleDiagnostic } from \"../types.js\";\n\nexport const bsEquationRule: Rule = {\n meta: {\n id: \"balance-sheet/equation\",\n name: \"Balance Sheet Equation\",\n description: \"資産合計 = 負債合計 + 資本合計 を検証する\",\n severity: \"error\",\n applicableTo: [\"sole-proprietor\", \"corporate\"],\n },\n\n check(ctx: RuleContext): RuleDiagnostic[] {\n if (ctx.taxReturn.returnType === \"individual\") return [];\n const bs = ctx.taxReturn.balanceSheet;\n const diagnostics: RuleDiagnostic[] = [];\n\n // Check closing balance equation\n const closingAssets = bs.assetsTotal.closing;\n const closingLiabilities = bs.liabilitiesTotal.closing;\n const closingEquity = bs.equityTotal.closing;\n\n if (closingAssets !== closingLiabilities + closingEquity) {\n diagnostics.push({\n ruleId: \"balance-sheet/equation\",\n severity: \"error\",\n message: `期末残高: 資産合計(${formatYen(closingAssets)}) ≠ 負債合計(${formatYen(closingLiabilities)}) + 資本合計(${formatYen(closingEquity)})`,\n expected: `資産合計 = ${formatYen(yen(closingLiabilities + closingEquity))}`,\n });\n }\n\n // Check opening balance equation\n const openingAssets = bs.assetsTotal.opening;\n const openingLiabilities = bs.liabilitiesTotal.opening;\n const openingEquity = bs.equityTotal.opening;\n\n if (openingAssets !== openingLiabilities + openingEquity) {\n diagnostics.push({\n ruleId: \"balance-sheet/equation\",\n severity: \"error\",\n message: `期首残高: 資産合計(${formatYen(openingAssets)}) ≠ 負債合計(${formatYen(openingLiabilities)}) + 資本合計(${formatYen(openingEquity)})`,\n expected: `資産合計 = ${formatYen(yen(openingLiabilities + openingEquity))}`,\n });\n }\n\n return diagnostics;\n },\n};\n","import { formatYen } from \"../../utils/monetary.js\";\nimport type { Yen } from \"../../models/types.js\";\nimport type { Rule, RuleContext, RuleDiagnostic } from \"../types.js\";\n\nexport const plArithmeticChainRule: Rule = {\n meta: {\n id: \"income-statement/pl-chain\",\n name: \"P/L Arithmetic Chain\",\n description: \"損益計算書の計算連鎖を検証する\",\n severity: \"error\",\n applicableTo: [\"sole-proprietor\"],\n },\n\n check(ctx: RuleContext): RuleDiagnostic[] {\n if (ctx.taxReturn.returnType !== \"sole-proprietor\") return [];\n const pl = ctx.taxReturn.incomeStatement;\n const diagnostics: RuleDiagnostic[] = [];\n\n // Check: grossProfit = revenue - cogs.total\n const expectedGross = (pl.revenue - pl.cogs.total) as Yen;\n if (pl.grossProfit !== expectedGross) {\n diagnostics.push({\n ruleId: \"income-statement/pl-chain\",\n severity: \"error\",\n message: `売上総利益(${formatYen(pl.grossProfit)}) ≠ 売上(${formatYen(pl.revenue)}) - 売上原価(${formatYen(pl.cogs.total)})`,\n expected: `売上総利益 = ${formatYen(expectedGross)}`,\n });\n }\n\n // Check: operatingIncome = grossProfit - totalExpenses\n const expectedOperating = (pl.grossProfit - pl.totalExpenses) as Yen;\n if (pl.operatingIncome !== expectedOperating) {\n diagnostics.push({\n ruleId: \"income-statement/pl-chain\",\n severity: \"error\",\n message: `所得金額(${formatYen(pl.operatingIncome)}) ≠ 売上総利益(${formatYen(pl.grossProfit)}) - 経費合計(${formatYen(pl.totalExpenses)})`,\n expected: `所得金額 = ${formatYen(expectedOperating)}`,\n });\n }\n\n return diagnostics;\n },\n};\n","import { formatYen } from \"../../utils/monetary.js\";\nimport type { Yen } from \"../../models/types.js\";\nimport type { Rule, RuleContext, RuleDiagnostic } from \"../types.js\";\n\nexport const cogsCalculationRule: Rule = {\n meta: {\n id: \"income-statement/cogs\",\n name: \"COGS Calculation\",\n description: \"売上原価の計算を検証する\",\n severity: \"error\",\n applicableTo: [\"sole-proprietor\", \"corporate\"],\n },\n\n check(ctx: RuleContext): RuleDiagnostic[] {\n if (ctx.taxReturn.returnType === \"individual\") return [];\n const cogs = ctx.taxReturn.incomeStatement.cogs;\n\n // Skip if all COGS values are zero\n if (\n cogs.openingInventory === 0 &&\n cogs.purchases === 0 &&\n cogs.closingInventory === 0 &&\n cogs.total === 0\n ) {\n return [];\n }\n\n const expected = (cogs.openingInventory +\n cogs.purchases -\n cogs.closingInventory) as Yen;\n if (cogs.total !== expected) {\n return [\n {\n ruleId: \"income-statement/cogs\",\n severity: \"error\",\n message: `売上原価合計(${formatYen(cogs.total)}) ≠ 期首棚卸高(${formatYen(cogs.openingInventory)}) + 仕入金額(${formatYen(cogs.purchases)}) - 期末棚卸高(${formatYen(cogs.closingInventory)})`,\n expected: `売上原価合計 = ${formatYen(expected)}`,\n },\n ];\n }\n\n return [];\n },\n};\n","import { formatYen } from \"../../utils/monetary.js\";\nimport type { Yen } from \"../../models/types.js\";\nimport type { Rule, RuleContext, RuleDiagnostic } from \"../types.js\";\n\nexport const expenseTotalRule: Rule = {\n meta: {\n id: \"income-statement/expense-total\",\n name: \"Expense Total\",\n description: \"経費合計が各経費項目の合計と一致するか検証する\",\n severity: \"error\",\n applicableTo: [\"sole-proprietor\"],\n },\n\n check(ctx: RuleContext): RuleDiagnostic[] {\n if (ctx.taxReturn.returnType !== \"sole-proprietor\") return [];\n const exp = ctx.taxReturn.incomeStatement.expenses;\n\n const computed = (exp.salaries +\n exp.outsourcing +\n exp.retirement +\n exp.rent +\n exp.interest +\n exp.taxes +\n exp.insurance +\n exp.repairs +\n exp.consumables +\n exp.depreciation +\n exp.welfare +\n exp.utilities +\n exp.travel +\n exp.communication +\n exp.advertising +\n exp.entertainment +\n exp.miscellaneous +\n exp.otherExpenses) as Yen;\n\n const totalExpenses = ctx.taxReturn.incomeStatement.totalExpenses;\n\n if (totalExpenses !== computed) {\n return [\n {\n ruleId: \"income-statement/expense-total\",\n severity: \"error\",\n message: `経費合計(${formatYen(totalExpenses)}) ≠ 各経費項目の合計(${formatYen(computed)})`,\n expected: `経費合計 = ${formatYen(computed)}`,\n },\n ];\n }\n\n return [];\n },\n};\n","import { formatYen } from \"../../utils/monetary.js\";\nimport type { Yen } from \"../../models/types.js\";\nimport type { Rule, RuleContext, RuleDiagnostic } from \"../types.js\";\n\nexport const bsPlBridgeRule: Rule = {\n meta: {\n id: \"cross-statement/bs-pl-bridge\",\n name: \"BS-PL Bridge\",\n description:\n \"貸借対照表の青色申告特別控除前の所得金額と損益計算書の所得金額の一致を検証する\",\n severity: \"error\",\n applicableTo: [\"sole-proprietor\"],\n },\n\n check(ctx: RuleContext): RuleDiagnostic[] {\n if (ctx.taxReturn.returnType !== \"sole-proprietor\") return [];\n const bsRetained = ctx.taxReturn.balanceSheet.retainedEarnings;\n const plOperating = ctx.taxReturn.incomeStatement.operatingIncome;\n\n if (bsRetained !== plOperating) {\n return [\n {\n ruleId: \"cross-statement/bs-pl-bridge\",\n severity: \"error\",\n message: `損益計算書の所得金額(${formatYen(plOperating)}) ≠ 貸借対照表の青色申告特別控除前の所得金額(${formatYen(bsRetained as Yen)})`,\n expected: `両方とも同一の値であるべき: ${formatYen(plOperating)}`,\n },\n ];\n }\n\n return [];\n },\n};\n","import type { Rule, RuleContext, RuleDiagnostic } from \"../types.js\";\nimport { formatYen } from \"../../utils/monetary.js\";\n\n/**\n * balance-sheet/opening-owner-equity\n * 事業主貸・事業主借は期首残高が0であるべき(前期末で精算される)\n */\nexport const openingOwnerEquityRule: Rule = {\n meta: {\n id: \"balance-sheet/opening-owner-equity\",\n name: \"事業主貸借 期首残高ゼロ\",\n description:\n \"事業主貸と事業主借は毎期首に元入金へ振替されるため、期首残高は0円であるべきです。\",\n severity: \"error\",\n applicableTo: [\"sole-proprietor\"],\n },\n\n check(ctx: RuleContext): RuleDiagnostic[] {\n if (ctx.taxReturn.returnType !== \"sole-proprietor\") return [];\n const diagnostics: RuleDiagnostic[] = [];\n const bs = ctx.taxReturn.balanceSheet;\n\n if (bs.ownerDrawings.opening !== 0) {\n diagnostics.push({\n ruleId: this.meta.id,\n severity: this.meta.severity,\n message: `事業主貸の期首残高が0ではありません: ${formatYen(bs.ownerDrawings.opening)}`,\n expected: \"事業主貸の期首残高 = ¥0\",\n });\n }\n\n if (bs.ownerContributions.opening !== 0) {\n diagnostics.push({\n ruleId: this.meta.id,\n severity: this.meta.severity,\n message: `事業主借の期首残高が0ではありません: ${formatYen(bs.ownerContributions.opening)}`,\n expected: \"事業主借の期首残高 = ¥0\",\n });\n }\n\n return diagnostics;\n },\n};\n","import type { Rule, RuleContext, RuleDiagnostic } from \"../types.js\";\nimport { formatYen } from \"../../utils/monetary.js\";\nimport { yen } from \"../../models/types.js\";\n\n/**\n * balance-sheet/motoire-kin-formula\n * 元入金繰越計算: 元入金(当期首) = 元入金(前期首) + 所得(前期) + 事業主借(前期末) - 事業主貸(前期末)\n */\nexport const motoireKinFormulaRule: Rule = {\n meta: {\n id: \"balance-sheet/motoire-kin-formula\",\n name: \"元入金繰越計算\",\n description:\n \"元入金(当期) = 元入金(前期) + 青色申告特別控除前所得(前期) + 事業主借(前期末) - 事業主貸(前期末) であるべきです。前年データが必要です。\",\n severity: \"error\",\n applicableTo: [\"sole-proprietor\"],\n },\n\n check(ctx: RuleContext): RuleDiagnostic[] {\n if (ctx.taxReturn.returnType !== \"sole-proprietor\") return [];\n if (!ctx.priorYear || ctx.priorYear.returnType !== \"sole-proprietor\")\n return [];\n\n const priorBs = ctx.priorYear.balanceSheet;\n const currentBs = ctx.taxReturn.balanceSheet;\n\n const expected = yen(\n priorBs.ownerEquity.opening +\n priorBs.retainedEarnings +\n priorBs.ownerContributions.closing -\n priorBs.ownerDrawings.closing,\n );\n\n const actual = currentBs.ownerEquity.opening;\n\n if (actual !== expected) {\n return [\n {\n ruleId: this.meta.id,\n severity: this.meta.severity,\n message: `元入金の期首残高(${formatYen(actual)}) ≠ 繰越計算額(${formatYen(expected)})`,\n details: `計算式: 元入金(前期首)(${formatYen(priorBs.ownerEquity.opening)}) + 所得(前期)(${formatYen(priorBs.retainedEarnings)}) + 事業主借(前期末)(${formatYen(priorBs.ownerContributions.closing)}) - 事業主貸(前期末)(${formatYen(priorBs.ownerDrawings.closing)})`,\n expected: `元入金の期首残高 = ${formatYen(expected)}`,\n },\n ];\n }\n\n return [];\n },\n};\n","import type { Rule, RuleContext, RuleDiagnostic } from \"../types.js\";\nimport { formatYen } from \"../../utils/monetary.js\";\n\n/**\n * balance-sheet/non-negative-cash\n * 現金残高が負でないかチェック\n */\nexport const nonNegativeCashRule: Rule = {\n meta: {\n id: \"balance-sheet/non-negative-cash\",\n name: \"現金残高の非負チェック\",\n description:\n \"現金残高は0以上であるべきです。マイナス残高は記帳ミスの可能性があります。\",\n severity: \"warning\",\n applicableTo: [\"sole-proprietor\", \"corporate\"],\n },\n\n check(ctx: RuleContext): RuleDiagnostic[] {\n if (ctx.taxReturn.returnType === \"individual\") return [];\n const diagnostics: RuleDiagnostic[] = [];\n const bs = ctx.taxReturn.balanceSheet;\n\n if (bs.cash.opening < 0) {\n diagnostics.push({\n ruleId: this.meta.id,\n severity: this.meta.severity,\n message: `現金の期首残高がマイナスです: ${formatYen(bs.cash.opening)}`,\n });\n }\n\n if (bs.cash.closing < 0) {\n diagnostics.push({\n ruleId: this.meta.id,\n severity: this.meta.severity,\n message: `現金の期末残高がマイナスです: ${formatYen(bs.cash.closing)}`,\n });\n }\n\n return diagnostics;\n },\n};\n","import type { Rule, RuleContext, RuleDiagnostic } from \"../types.js\";\nimport { formatYen } from \"../../utils/monetary.js\";\n\n/**\n * deductions/blue-deduction-cap\n * 青色申告特別控除額が控除前所得を超えていないかチェック\n */\nexport const blueDeductionCapRule: Rule = {\n meta: {\n id: \"deductions/blue-deduction-cap\",\n name: \"青色控除上限チェック\",\n description:\n \"青色申告特別控除額は、控除前の所得金額を超えることはできません。所得を超える場合は所得金額が上限となります。\",\n severity: \"warning\",\n applicableTo: [\"sole-proprietor\"],\n },\n\n check(ctx: RuleContext): RuleDiagnostic[] {\n if (ctx.taxReturn.returnType !== \"sole-proprietor\") return [];\n const deduction = ctx.taxReturn.taxFormA.blueReturnDeduction;\n const income = ctx.taxReturn.incomeStatement.operatingIncome;\n\n if (deduction > income) {\n return [\n {\n ruleId: this.meta.id,\n severity: this.meta.severity,\n message: `青色申告特別控除額(${formatYen(deduction)}) > 控除前所得(${formatYen(income)})`,\n details:\n \"青色申告特別控除額は控除前所得金額が上限です。所得が少ない場合は所得金額までしか控除できません。\",\n expected: `青色申告特別控除額 ≤ ${formatYen(income)}`,\n },\n ];\n }\n\n return [];\n },\n};\n","import type { Rule, RuleContext, RuleDiagnostic } from \"../types.js\";\nimport { yen } from \"../../models/types.js\";\nimport { formatYen } from \"../../utils/monetary.js\";\n\n/**\n * deductions/blue-deduction-eligibility\n * 65万円(55万円)控除の適用要件チェック\n */\nexport const blueDeductionEligibilityRule: Rule = {\n meta: {\n id: \"deductions/blue-deduction-eligibility\",\n name: \"青色控除65万円適用要件\",\n description:\n \"65万円の青色申告特別控除にはe-Taxによる申告または電子帳簿保存が必要です(令和2年分以降)。要件を満たさない場合は55万円が上限です。\",\n severity: \"info\",\n applicableTo: [\"sole-proprietor\"],\n },\n\n check(ctx: RuleContext): RuleDiagnostic[] {\n if (ctx.taxReturn.returnType !== \"sole-proprietor\") return [];\n const deduction = ctx.taxReturn.taxFormA.blueReturnDeduction;\n const limit55 = yen(550000);\n const limit65 = yen(650000);\n\n if (deduction > limit55 && deduction <= limit65) {\n return [\n {\n ruleId: this.meta.id,\n severity: this.meta.severity,\n message: `青色申告特別控除額が${formatYen(limit65)}です。e-Tax申告または電子帳簿保存の要件を確認してください。`,\n details:\n \"令和2年分以降、65万円控除にはe-Taxによる確定申告の送信、または電子帳簿保存法に基づく電子帳簿の備付けおよび保存が必要です。要件を満たさない場合は55万円が上限となります。\",\n },\n ];\n }\n\n return [];\n },\n};\n","import type { Rule, RuleContext, RuleDiagnostic } from \"../types.js\";\n\n/** Common useful life expectations (simplified lookup) */\nconst COMMON_USEFUL_LIVES: Record<string, number[]> = {\n パソコン: [4],\n サーバー: [5],\n 普通自動車: [6],\n 軽自動車: [4],\n 木造建物: [22],\n 鉄筋コンクリート建物: [47],\n 金属製家具: [15],\n};\n\n/**\n * depreciation/useful-life-rates\n * 耐用年数が法定テーブルと一致するかチェック\n */\nexport const usefulLifeRatesRule: Rule = {\n meta: {\n id: \"depreciation/useful-life-rates\",\n name: \"法定耐用年数チェック\",\n description:\n \"減価償却資産の耐用年数が法定耐用年数テーブルと一致するか確認します。\",\n severity: \"warning\",\n applicableTo: [\"sole-proprietor\", \"corporate\"],\n },\n\n check(ctx: RuleContext): RuleDiagnostic[] {\n if (ctx.taxReturn.returnType === \"individual\") return [];\n const diagnostics: RuleDiagnostic[] = [];\n const assets = ctx.taxReturn.depreciationSchedule.assets;\n\n for (const asset of assets) {\n for (const [keyword, validLives] of Object.entries(COMMON_USEFUL_LIVES)) {\n if (\n asset.name.includes(keyword) &&\n !validLives.includes(asset.usefulLife)\n ) {\n diagnostics.push({\n ruleId: this.meta.id,\n severity: this.meta.severity,\n message: `「${asset.name}」の耐用年数(${asset.usefulLife}年)が法定耐用年数(${validLives.join(\"/\")}年)と異なります`,\n });\n }\n }\n }\n\n return diagnostics;\n },\n};\n","import type { Rule, RuleContext, RuleDiagnostic } from \"../types.js\";\nimport { formatYen } from \"../../utils/monetary.js\";\nimport { yen } from \"../../models/types.js\";\n\n/**\n * depreciation/small-asset-threshold\n * 少額減価償却資産の閾値チェック\n */\nexport const smallAssetThresholdRule: Rule = {\n meta: {\n id: \"depreciation/small-asset-threshold\",\n name: \"少額資産の償却方法チェック\",\n description:\n \"取得価額10万円以下は全額経費、10万円超30万円以下は少額減価償却資産の特例(青色申告者)が適用可能です。\",\n severity: \"warning\",\n applicableTo: [\"sole-proprietor\", \"corporate\"],\n },\n\n check(ctx: RuleContext): RuleDiagnostic[] {\n if (ctx.taxReturn.returnType === \"individual\") return [];\n const diagnostics: RuleDiagnostic[] = [];\n const assets = ctx.taxReturn.depreciationSchedule.assets;\n const threshold10 = yen(100000);\n const threshold30 = yen(300000);\n\n for (const asset of assets) {\n if (asset.acquisitionCost <= threshold10 && asset.usefulLife > 1) {\n diagnostics.push({\n ruleId: this.meta.id,\n severity: this.meta.severity,\n message: `「${asset.name}」(取得価額${formatYen(asset.acquisitionCost)})は10万円以下のため、全額経費計上が可能です`,\n });\n }\n\n if (\n asset.acquisitionCost > threshold10 &&\n asset.acquisitionCost <= threshold30 &&\n asset.depreciationMethod !== \"一括償却\"\n ) {\n diagnostics.push({\n ruleId: this.meta.id,\n severity: this.meta.severity,\n message: `「${asset.name}」(取得価額${formatYen(asset.acquisitionCost)})は30万円以下のため、少額減価償却資産の特例(一括経費計上)が適用可能です`,\n details:\n \"青色申告者は取得価額30万円未満の減価償却資産について、年間合計300万円まで全額経費に計上できます。\",\n });\n }\n }\n\n return diagnostics;\n },\n};\n","import type { Rule, RuleContext, RuleDiagnostic } from \"../types.js\";\nimport { formatYen } from \"../../utils/monetary.js\";\nimport { yen } from \"../../models/types.js\";\n\n/**\n * cross-statement/decision-to-return\n * 決算書の所得金額が申告書第一表に正しく転記されているかチェック\n */\nexport const decisionToReturnRule: Rule = {\n meta: {\n id: \"cross-statement/decision-to-return\",\n name: \"決算書→申告書 転記一致\",\n description:\n \"青色申告決算書の売上金額・所得金額が申告書第一表に正しく転記されているか確認します。\",\n severity: \"error\",\n applicableTo: [\"sole-proprietor\"],\n },\n\n check(ctx: RuleContext): RuleDiagnostic[] {\n if (ctx.taxReturn.returnType !== \"sole-proprietor\") return [];\n const diagnostics: RuleDiagnostic[] = [];\n const pl = ctx.taxReturn.incomeStatement;\n const form = ctx.taxReturn.taxFormA;\n\n // 売上(収入)金額の転記チェック\n if (pl.revenue !== form.businessIncome) {\n diagnostics.push({\n ruleId: this.meta.id,\n severity: this.meta.severity,\n message: `決算書の売上金額(${formatYen(pl.revenue)}) ≠ 申告書の営業等収入(${formatYen(form.businessIncome)})`,\n expected: `申告書の営業等収入 = ${formatYen(pl.revenue)}`,\n });\n }\n\n // 所得金額の転記チェック(青色控除前)\n // 申告書の営業等所得 = 決算書の所得 - 青色申告特別控除\n const expectedProfit = yen(pl.operatingIncome - form.blueReturnDeduction);\n if (form.businessProfit !== expectedProfit) {\n diagnostics.push({\n ruleId: this.meta.id,\n severity: this.meta.severity,\n message: `申告書の営業等所得(${formatYen(form.businessProfit)}) ≠ 決算書所得(${formatYen(pl.operatingIncome)}) - 青色控除(${formatYen(form.blueReturnDeduction)})`,\n expected: `申告書の営業等所得 = ${formatYen(expectedProfit)}`,\n });\n }\n\n return diagnostics;\n },\n};\n","import type { Rule, RuleContext, RuleDiagnostic } from \"../types.js\";\nimport { formatYen } from \"../../utils/monetary.js\";\n\n/**\n * cross-statement/depreciation-sum\n * 減価償却費の計上額が損益計算書と一致するかチェック\n */\nexport const depreciationSumRule: Rule = {\n meta: {\n id: \"cross-statement/depreciation-sum\",\n name: \"減価償却費合計の一致\",\n description:\n \"減価償却明細の必要経費算入額合計が損益計算書の減価償却費と一致するか確認します。\",\n severity: \"error\",\n applicableTo: [\"sole-proprietor\"],\n },\n\n check(ctx: RuleContext): RuleDiagnostic[] {\n if (ctx.taxReturn.returnType !== \"sole-proprietor\") return [];\n const scheduleTotal =\n ctx.taxReturn.depreciationSchedule.totalBusinessDepreciation;\n const plDepreciation = ctx.taxReturn.incomeStatement.expenses.depreciation;\n\n // Skip if both are zero (no depreciation)\n if (scheduleTotal === 0 && plDepreciation === 0) return [];\n\n if (scheduleTotal !== plDepreciation) {\n return [\n {\n ruleId: this.meta.id,\n severity: this.meta.severity,\n message: `減価償却明細の合計(${formatYen(scheduleTotal)}) ≠ P/L減価償却費(${formatYen(plDepreciation)})`,\n expected: `両方とも同一の値であるべき: ${formatYen(scheduleTotal)}`,\n },\n ];\n }\n\n return [];\n },\n};\n","import type { Rule, RuleContext, RuleDiagnostic } from \"../types.js\";\nimport type { AccountBalance } from \"../../models/types.js\";\nimport { formatYen } from \"../../utils/monetary.js\";\n\nconst COMMON_ACCOUNT_NAMES: Record<string, string> = {\n cash: \"現金\",\n deposits: \"預金\",\n accountsReceivable: \"売掛金\",\n inventory: \"棚卸資産\",\n buildings: \"建物\",\n vehicles: \"車両運搬具\",\n tools: \"工具器具備品\",\n land: \"土地\",\n accountsPayable: \"買掛金\",\n borrowings: \"借入金\",\n};\n\n/**\n * continuity/opening-closing-match\n * 当期の期首残高が前期の期末残高と一致するかチェック\n */\nexport const openingClosingMatchRule: Rule = {\n meta: {\n id: \"continuity/opening-closing-match\",\n name: \"期首=前期末 一致チェック\",\n description:\n \"当期の期首残高が前期の期末残高と一致するか確認します。前年データが必要です。\",\n severity: \"error\",\n applicableTo: [\"sole-proprietor\", \"corporate\"],\n },\n\n check(ctx: RuleContext): RuleDiagnostic[] {\n if (!ctx.priorYear) return [];\n if (ctx.taxReturn.returnType === \"individual\") return [];\n if (ctx.priorYear.returnType === \"individual\") return [];\n\n const diagnostics: RuleDiagnostic[] = [];\n const currentBs = ctx.taxReturn.balanceSheet;\n const priorBs = ctx.priorYear.balanceSheet;\n\n // Common accounts (both sole-proprietor and corporate)\n for (const [key, label] of Object.entries(COMMON_ACCOUNT_NAMES)) {\n const current = currentBs[key as keyof typeof currentBs] as\n | AccountBalance\n | undefined;\n const prior = priorBs[key as keyof typeof priorBs] as\n | AccountBalance\n | undefined;\n\n if (\n current &&\n prior &&\n typeof current === \"object\" &&\n \"opening\" in current &&\n \"closing\" in prior &&\n current.opening !== prior.closing\n ) {\n diagnostics.push({\n ruleId: this.meta.id,\n severity: this.meta.severity,\n message: `${label}: 当期首(${formatYen(current.opening)}) ≠ 前期末(${formatYen(prior.closing)})`,\n expected: `${label}の期首残高 = ${formatYen(prior.closing)}`,\n });\n }\n }\n\n // Sole-proprietor-specific: 元入金\n if (\n ctx.taxReturn.returnType === \"sole-proprietor\" &&\n ctx.priorYear.returnType === \"sole-proprietor\"\n ) {\n const curBs = ctx.taxReturn.balanceSheet;\n const priBs = ctx.priorYear.balanceSheet;\n if (curBs.ownerEquity.opening !== priBs.ownerEquity.closing) {\n diagnostics.push({\n ruleId: this.meta.id,\n severity: this.meta.severity,\n message: `元入金: 当期首(${formatYen(curBs.ownerEquity.opening)}) ≠ 前期末(${formatYen(priBs.ownerEquity.closing)})`,\n expected: `元入金の期首残高 = ${formatYen(priBs.ownerEquity.closing)}`,\n });\n }\n }\n\n // Corporate-specific: 資本金, 資本剰余金, 利益剰余金\n if (\n ctx.taxReturn.returnType === \"corporate\" &&\n ctx.priorYear.returnType === \"corporate\"\n ) {\n const curBs = ctx.taxReturn.balanceSheet;\n const priBs = ctx.priorYear.balanceSheet;\n const corpAccounts: [AccountBalance, AccountBalance, string][] = [\n [curBs.capitalStock, priBs.capitalStock, \"資本金\"],\n [curBs.capitalSurplus, priBs.capitalSurplus, \"資本剰余金\"],\n [curBs.retainedEarnings, priBs.retainedEarnings, \"利益剰余金\"],\n ];\n for (const [current, prior, label] of corpAccounts) {\n if (current.opening !== prior.closing) {\n diagnostics.push({\n ruleId: this.meta.id,\n severity: this.meta.severity,\n message: `${label}: 当期首(${formatYen(current.opening)}) ≠ 前期末(${formatYen(prior.closing)})`,\n expected: `${label}の期首残高 = ${formatYen(prior.closing)}`,\n });\n }\n }\n }\n\n return diagnostics;\n },\n};\n","import type { Rule, RuleContext, RuleDiagnostic } from \"../types.js\";\nimport type { Yen } from \"../../models/types.js\";\nimport { formatYen } from \"../../utils/monetary.js\";\n\nconst FIELDS_TO_CHECK: { key: string; label: string }[] = [\n { key: \"revenue\", label: \"売上\" },\n { key: \"totalExpenses\", label: \"経費合計\" },\n { key: \"operatingIncome\", label: \"所得金額\" },\n];\n\n/**\n * continuity/year-over-year-change\n * 前年比で大幅な変動がある場合に警告\n */\nexport const yearOverYearChangeRule: Rule = {\n meta: {\n id: \"continuity/year-over-year-change\",\n name: \"前年比変動チェック\",\n description:\n \"売上・経費・所得が前年比で200%超の増加または80%超の減少がある場合に警告します。前年データが必要です。\",\n severity: \"warning\",\n applicableTo: [\"sole-proprietor\", \"corporate\"],\n },\n\n check(ctx: RuleContext): RuleDiagnostic[] {\n if (!ctx.priorYear) return [];\n if (ctx.taxReturn.returnType === \"individual\") return [];\n if (ctx.priorYear.returnType === \"individual\") return [];\n\n const diagnostics: RuleDiagnostic[] = [];\n const currentPl = ctx.taxReturn.incomeStatement;\n const priorPl = ctx.priorYear.incomeStatement;\n\n for (const { key, label } of FIELDS_TO_CHECK) {\n const current = currentPl[key as keyof typeof currentPl] as Yen;\n const prior = priorPl[key as keyof typeof priorPl] as Yen;\n\n if (prior === 0) continue;\n\n const ratio = current / prior;\n\n if (ratio > 3.0) {\n diagnostics.push({\n ruleId: this.meta.id,\n severity: this.meta.severity,\n message: `${label}が前年比${Math.round(ratio * 100)}%です(${formatYen(prior)} → ${formatYen(current)})`,\n details:\n \"200%を超える大幅な増加があります。記帳内容をご確認ください。\",\n });\n } else if (ratio < 0.2) {\n diagnostics.push({\n ruleId: this.meta.id,\n severity: this.meta.severity,\n message: `${label}が前年比${Math.round(ratio * 100)}%です(${formatYen(prior)} → ${formatYen(current)})`,\n details:\n \"80%を超える大幅な減少があります。記帳内容をご確認ください。\",\n });\n }\n }\n\n return diagnostics;\n },\n};\n","import type { Rule, RuleContext, RuleDiagnostic } from \"../types.js\";\n\nconst DEFAULT_MAX_RATIO = 0.9;\n\n/**\n * home-office/reasonable-ratio\n * 家事按分率の妥当性チェック\n */\nexport const reasonableRatioRule: Rule = {\n meta: {\n id: \"home-office/reasonable-ratio\",\n name: \"家事按分率の妥当性\",\n description:\n \"減価償却資産の事業専用割合(家事按分率)が妥当な範囲内かチェックします。デフォルトの上限は90%です。\",\n severity: \"warning\",\n applicableTo: [\"sole-proprietor\"],\n },\n\n check(ctx: RuleContext): RuleDiagnostic[] {\n if (ctx.taxReturn.returnType !== \"sole-proprietor\") return [];\n const diagnostics: RuleDiagnostic[] = [];\n const assets = ctx.taxReturn.depreciationSchedule.assets;\n\n const ruleConfig = ctx.config.rules[this.meta.id];\n let maxRatio = DEFAULT_MAX_RATIO;\n if (\n Array.isArray(ruleConfig) &&\n typeof ruleConfig[1]?.maxRatio === \"number\"\n ) {\n maxRatio = ruleConfig[1].maxRatio;\n }\n\n for (const asset of assets) {\n if (asset.businessUseRatio > maxRatio) {\n diagnostics.push({\n ruleId: this.meta.id,\n severity: this.meta.severity,\n message: `「${asset.name}」の事業専用割合(${Math.round(asset.businessUseRatio * 100)}%)が上限(${Math.round(maxRatio * 100)}%)を超えています`,\n details:\n \"家事按分率が高すぎる場合、税務調査で否認される可能性があります。実態に即した割合を設定してください。\",\n });\n }\n }\n\n return diagnostics;\n },\n};\n","/**\n * 基礎控除確認ルール\n * 基礎控除が標準額(48万円)であるか確認する。\n */\n\nimport type { Rule, RuleContext, RuleDiagnostic } from \"../types.js\";\nimport { formatYen } from \"../../utils/monetary.js\";\nimport { yen } from \"../../models/types.js\";\n\nconst BASIC_DEDUCTION_STANDARD = yen(480000);\n\nexport const basicDeductionRule: Rule = {\n meta: {\n id: \"individual/basic-deduction\",\n name: \"基礎控除額確認\",\n description:\n \"基礎控除が標準額(48万円)であるか確認します。合計所得金額が2,400万円以下の場合は48万円が適用されます。\",\n severity: \"info\",\n applicableTo: [\"individual\"],\n },\n\n check(ctx: RuleContext): RuleDiagnostic[] {\n if (ctx.taxReturn.returnType !== \"individual\") return [];\n\n const basic = ctx.taxReturn.taxFormB.basicDeduction;\n const diagnostics: RuleDiagnostic[] = [];\n\n if (basic !== BASIC_DEDUCTION_STANDARD && basic !== 0) {\n diagnostics.push({\n ruleId: this.meta.id,\n severity: this.meta.severity,\n message: `基礎控除額(${formatYen(basic)})が標準額(${formatYen(BASIC_DEDUCTION_STANDARD)})と異なります。合計所得金額が2,400万円超の場合は逓減されます。`,\n expected: `基礎控除 = ${formatYen(BASIC_DEDUCTION_STANDARD)}(合計所得2,400万円以下の場合)`,\n });\n }\n\n return diagnostics;\n },\n};\n","/**\n * 所得控除合計チェックルール\n * 申告書第二表の各控除項目の合計が第一表の所得控除合計と一致するか確認する。\n */\n\nimport type { Rule, RuleContext, RuleDiagnostic } from \"../types.js\";\nimport { formatYen } from \"../../utils/monetary.js\";\nimport type { Yen } from \"../../models/types.js\";\n\nexport const deductionTotalRule: Rule = {\n meta: {\n id: \"individual/deduction-total\",\n name: \"所得控除合計チェック\",\n description:\n \"申告書第二表の各控除項目の合計が第一表の所得控除合計と一致するか確認します。\",\n severity: \"error\",\n applicableTo: [\"individual\"],\n },\n\n check(ctx: RuleContext): RuleDiagnostic[] {\n if (ctx.taxReturn.returnType !== \"individual\") return [];\n\n const formA = ctx.taxReturn.taxFormA;\n const formB = ctx.taxReturn.taxFormB;\n const diagnostics: RuleDiagnostic[] = [];\n\n // Sum deduction items from 第二表\n const computed = (formB.socialInsurance +\n formB.smallBusinessMutualAid +\n formB.lifeInsurance +\n formB.earthquakeInsurance +\n formB.spouseDeduction +\n formB.dependentDeduction +\n formB.basicDeduction) as Yen;\n\n if (computed !== formA.totalDeductions) {\n diagnostics.push({\n ruleId: this.meta.id,\n severity: this.meta.severity,\n message: `所得控除合計(${formatYen(formA.totalDeductions)}) ≠ 各控除項目の合算(${formatYen(computed)})`,\n expected: `所得控除合計 = ${formatYen(computed)}`,\n });\n }\n\n return diagnostics;\n },\n};\n","/**\n * 課税所得計算チェックルール\n * 課税される所得金額 = 合計所得金額 − 所得控除合計 を検証する。\n */\n\nimport type { Rule, RuleContext, RuleDiagnostic } from \"../types.js\";\nimport { formatYen } from \"../../utils/monetary.js\";\nimport type { Yen } from \"../../models/types.js\";\n\nexport const taxableIncomeRule: Rule = {\n meta: {\n id: \"individual/taxable-income\",\n name: \"課税所得計算チェック\",\n description:\n \"課税される所得金額が合計所得金額から所得控除合計を差し引いた値と一致するか確認します。\",\n severity: \"error\",\n applicableTo: [\"individual\"],\n },\n\n check(ctx: RuleContext): RuleDiagnostic[] {\n if (ctx.taxReturn.returnType !== \"individual\") return [];\n\n const form = ctx.taxReturn.taxFormA;\n const diagnostics: RuleDiagnostic[] = [];\n\n // 課税所得 = 合計所得 - 所得控除合計(負の場合は0)\n const expected = Math.max(\n 0,\n form.totalIncome - form.totalDeductions,\n ) as Yen;\n\n if (form.taxableIncome !== expected) {\n diagnostics.push({\n ruleId: this.meta.id,\n severity: this.meta.severity,\n message: `課税所得金額(${formatYen(form.taxableIncome)}) ≠ 合計所得(${formatYen(form.totalIncome)}) − 所得控除(${formatYen(form.totalDeductions)})`,\n expected: `課税所得金額 = ${formatYen(expected)}`,\n });\n }\n\n return diagnostics;\n },\n};\n","/**\n * 源泉徴収税額整合性チェックルール\n * 所得の内訳(第二表)に記載された源泉徴収税額の合計が0でないことを確認する。\n * 給与所得者は通常、源泉徴収税額が存在するはず。\n */\n\nimport type { Rule, RuleContext, RuleDiagnostic } from \"../types.js\";\nimport { formatYen } from \"../../utils/monetary.js\";\nimport type { Yen } from \"../../models/types.js\";\n\nexport const withholdingTotalRule: Rule = {\n meta: {\n id: \"individual/withholding-total\",\n name: \"源泉徴収税額チェック\",\n description:\n \"所得の内訳に記載された源泉徴収税額の整合性を確認します。給与所得者は通常、源泉徴収税額が記載されます。\",\n severity: \"warning\",\n applicableTo: [\"individual\"],\n },\n\n check(ctx: RuleContext): RuleDiagnostic[] {\n if (ctx.taxReturn.returnType !== \"individual\") return [];\n\n const details = ctx.taxReturn.taxFormB.incomeDetails;\n const diagnostics: RuleDiagnostic[] = [];\n\n if (details.length === 0) {\n diagnostics.push({\n ruleId: this.meta.id,\n severity: this.meta.severity,\n message:\n \"所得の内訳が未記載です。給与所得者の場合は源泉徴収票の情報を記載してください。\",\n });\n return diagnostics;\n }\n\n const totalWithheld = details.reduce(\n (sum, d) => (sum + d.withheld) as Yen,\n 0 as Yen,\n );\n\n if (totalWithheld === 0) {\n diagnostics.push({\n ruleId: this.meta.id,\n severity: this.meta.severity,\n message:\n \"源泉徴収税額の合計が0円です。給与所得者の場合は源泉徴収税額が通常存在します。\",\n expected: `源泉徴収税額合計 > ${formatYen(0 as Yen)}`,\n });\n }\n\n return diagnostics;\n },\n};\n","import { formatYen } from \"../../utils/monetary.js\";\nimport { yen } from \"../../models/types.js\";\nimport type { Rule, RuleContext, RuleDiagnostic } from \"../types.js\";\n\n/**\n * corporate/bs-equation\n * 法人B/S: 資産合計 = 負債合計 + 純資産合計\n */\nexport const corporateBsEquationRule: Rule = {\n meta: {\n id: \"corporate/bs-equation\",\n name: \"法人B/S等式\",\n description: \"資産合計 = 負債合計 + 純資産合計 を検証する\",\n severity: \"error\",\n applicableTo: [\"corporate\"],\n },\n\n check(ctx: RuleContext): RuleDiagnostic[] {\n if (ctx.taxReturn.returnType !== \"corporate\") return [];\n const bs = ctx.taxReturn.balanceSheet;\n const diagnostics: RuleDiagnostic[] = [];\n\n const closingAssets = bs.assetsTotal.closing;\n const closingLiabilities = bs.liabilitiesTotal.closing;\n const closingEquity = bs.equityTotal.closing;\n\n if (closingAssets !== closingLiabilities + closingEquity) {\n diagnostics.push({\n ruleId: this.meta.id,\n severity: this.meta.severity,\n message: `期末残高: 資産合計(${formatYen(closingAssets)}) ≠ 負債合計(${formatYen(closingLiabilities)}) + 純資産合計(${formatYen(closingEquity)})`,\n expected: `資産合計 = ${formatYen(yen(closingLiabilities + closingEquity))}`,\n });\n }\n\n const openingAssets = bs.assetsTotal.opening;\n const openingLiabilities = bs.liabilitiesTotal.opening;\n const openingEquity = bs.equityTotal.opening;\n\n if (openingAssets !== openingLiabilities + openingEquity) {\n diagnostics.push({\n ruleId: this.meta.id,\n severity: this.meta.severity,\n message: `期首残高: 資産合計(${formatYen(openingAssets)}) ≠ 負債合計(${formatYen(openingLiabilities)}) + 純資産合計(${formatYen(openingEquity)})`,\n expected: `資産合計 = ${formatYen(yen(openingLiabilities + openingEquity))}`,\n });\n }\n\n return diagnostics;\n },\n};\n","import { formatYen } from \"../../utils/monetary.js\";\nimport type { Yen } from \"../../models/types.js\";\nimport type { Rule, RuleContext, RuleDiagnostic } from \"../types.js\";\n\n/**\n * corporate/pl-chain\n * 法人P/L: 営業利益→経常利益→税引前当期純利益→当期純利益\n */\nexport const corporatePlChainRule: Rule = {\n meta: {\n id: \"corporate/pl-chain\",\n name: \"法人P/L計算連鎖\",\n description:\n \"営業利益 + 営業外収益 - 営業外費用 = 経常利益、経常利益 + 特別利益 - 特別損失 = 税引前当期純利益、税引前当期純利益 - 法人税等 = 当期純利益 を検証する\",\n severity: \"error\",\n applicableTo: [\"corporate\"],\n },\n\n check(ctx: RuleContext): RuleDiagnostic[] {\n if (ctx.taxReturn.returnType !== \"corporate\") return [];\n const pl = ctx.taxReturn.incomeStatement;\n const diagnostics: RuleDiagnostic[] = [];\n\n // grossProfit = revenue - cogs\n const expectedGross = (pl.revenue - pl.cogs.total) as Yen;\n if (pl.grossProfit !== expectedGross) {\n diagnostics.push({\n ruleId: this.meta.id,\n severity: this.meta.severity,\n message: `売上総利益(${formatYen(pl.grossProfit)}) ≠ 売上高(${formatYen(pl.revenue)}) - 売上原価(${formatYen(pl.cogs.total)})`,\n expected: `売上総利益 = ${formatYen(expectedGross)}`,\n });\n }\n\n // operatingIncome = grossProfit - totalExpenses\n const expectedOperating = (pl.grossProfit - pl.totalExpenses) as Yen;\n if (pl.operatingIncome !== expectedOperating) {\n diagnostics.push({\n ruleId: this.meta.id,\n severity: this.meta.severity,\n message: `営業利益(${formatYen(pl.operatingIncome)}) ≠ 売上総利益(${formatYen(pl.grossProfit)}) - 販管費(${formatYen(pl.totalExpenses)})`,\n expected: `営業利益 = ${formatYen(expectedOperating)}`,\n });\n }\n\n // ordinaryIncome = operatingIncome + nonOperatingIncome - nonOperatingExpenses\n const expectedOrdinary = (pl.operatingIncome + pl.nonOperatingIncome - pl.nonOperatingExpenses) as Yen;\n if (pl.ordinaryIncome !== expectedOrdinary) {\n diagnostics.push({\n ruleId: this.meta.id,\n severity: this.meta.severity,\n message: `経常利益(${formatYen(pl.ordinaryIncome)}) ≠ 営業利益(${formatYen(pl.operatingIncome)}) + 営業外収益(${formatYen(pl.nonOperatingIncome)}) - 営業外費用(${formatYen(pl.nonOperatingExpenses)})`,\n expected: `経常利益 = ${formatYen(expectedOrdinary)}`,\n });\n }\n\n // preTaxIncome = ordinaryIncome + extraordinaryGain - extraordinaryLoss\n const expectedPreTax = (pl.ordinaryIncome + pl.extraordinaryGain - pl.extraordinaryLoss) as Yen;\n if (pl.preTaxIncome !== expectedPreTax) {\n diagnostics.push({\n ruleId: this.meta.id,\n severity: this.meta.severity,\n message: `税引前当期純利益(${formatYen(pl.preTaxIncome)}) ≠ 経常利益(${formatYen(pl.ordinaryIncome)}) + 特別利益(${formatYen(pl.extraordinaryGain)}) - 特別損失(${formatYen(pl.extraordinaryLoss)})`,\n expected: `税引前当期純利益 = ${formatYen(expectedPreTax)}`,\n });\n }\n\n // netIncome = preTaxIncome - corporateTax\n const expectedNet = (pl.preTaxIncome - pl.corporateTax) as Yen;\n if (pl.netIncome !== expectedNet) {\n diagnostics.push({\n ruleId: this.meta.id,\n severity: this.meta.severity,\n message: `当期純利益(${formatYen(pl.netIncome)}) ≠ 税引前当期純利益(${formatYen(pl.preTaxIncome)}) - 法人税等(${formatYen(pl.corporateTax)})`,\n expected: `当期純利益 = ${formatYen(expectedNet)}`,\n });\n }\n\n return diagnostics;\n },\n};\n","import { formatYen } from \"../../utils/monetary.js\";\nimport type { Yen } from \"../../models/types.js\";\nimport type { Rule, RuleContext, RuleDiagnostic } from \"../types.js\";\n\n/**\n * corporate/expense-total\n * 法人販管費の合計検証\n */\nexport const corporateExpenseTotalRule: Rule = {\n meta: {\n id: \"corporate/expense-total\",\n name: \"法人販管費合計チェック\",\n description: \"販売費及び一般管理費の合計が各費目の合計と一致するか検証する\",\n severity: \"error\",\n applicableTo: [\"corporate\"],\n },\n\n check(ctx: RuleContext): RuleDiagnostic[] {\n if (ctx.taxReturn.returnType !== \"corporate\") return [];\n const exp = ctx.taxReturn.incomeStatement.expenses;\n\n const computed = (\n exp.salaries +\n exp.outsourcing +\n exp.retirement +\n exp.rent +\n exp.interest +\n exp.taxes +\n exp.insurance +\n exp.repairs +\n exp.consumables +\n exp.depreciation +\n exp.welfare +\n exp.utilities +\n exp.travel +\n exp.communication +\n exp.advertising +\n exp.entertainment +\n exp.miscellaneous +\n exp.otherExpenses\n ) as Yen;\n\n const totalExpenses = ctx.taxReturn.incomeStatement.totalExpenses;\n\n if (totalExpenses !== computed) {\n return [\n {\n ruleId: this.meta.id,\n severity: this.meta.severity,\n message: `販管費合計(${formatYen(totalExpenses)}) ≠ 各費目の合計(${formatYen(computed)})`,\n expected: `販管費合計 = ${formatYen(computed)}`,\n },\n ];\n }\n\n return [];\n },\n};\n","import { formatYen } from \"../../utils/monetary.js\";\nimport type { Rule, RuleContext, RuleDiagnostic } from \"../types.js\";\n\n/**\n * corporate/bs-pl-bridge\n * B/S当期純利益 = P/L当期純利益\n */\nexport const corporateBsPlBridgeRule: Rule = {\n meta: {\n id: \"corporate/bs-pl-bridge\",\n name: \"法人B/S↔P/L整合性\",\n description:\n \"貸借対照表の当期純利益と損益計算書の当期純利益が一致するか検証する\",\n severity: \"error\",\n applicableTo: [\"corporate\"],\n },\n\n check(ctx: RuleContext): RuleDiagnostic[] {\n if (ctx.taxReturn.returnType !== \"corporate\") return [];\n const bsNetIncome = ctx.taxReturn.balanceSheet.netIncome;\n const plNetIncome = ctx.taxReturn.incomeStatement.netIncome;\n\n if (bsNetIncome !== plNetIncome) {\n return [\n {\n ruleId: this.meta.id,\n severity: this.meta.severity,\n message: `B/S当期純利益(${formatYen(bsNetIncome)}) ≠ P/L当期純利益(${formatYen(plNetIncome)})`,\n expected: `両方とも同一の値であるべき: ${formatYen(plNetIncome)}`,\n },\n ];\n }\n\n return [];\n },\n};\n","import { formatYen } from \"../../utils/monetary.js\";\nimport type { Rule, RuleContext, RuleDiagnostic } from \"../types.js\";\n\n/**\n * corporate/betsu4-accounting-profit\n * 別表四の当期利益 = P/L税引前当期純利益\n */\nexport const betsu4AccountingProfitRule: Rule = {\n meta: {\n id: \"corporate/betsu4-accounting-profit\",\n name: \"別表四↔P/L整合性\",\n description:\n \"別表四の当期利益又は当期欠損の額が損益計算書の税引前当期純利益と一致するか検証する\",\n severity: \"error\",\n applicableTo: [\"corporate\"],\n },\n\n check(ctx: RuleContext): RuleDiagnostic[] {\n if (ctx.taxReturn.returnType !== \"corporate\") return [];\n const scheduleProfit = ctx.taxReturn.incomeAdjustment.accountingProfit;\n const plPreTax = ctx.taxReturn.incomeStatement.preTaxIncome;\n\n if (scheduleProfit !== plPreTax) {\n return [\n {\n ruleId: this.meta.id,\n severity: this.meta.severity,\n message: `別表四の当期利益(${formatYen(scheduleProfit)}) ≠ P/L税引前当期純利益(${formatYen(plPreTax)})`,\n expected: `別表四の当期利益 = ${formatYen(plPreTax)}`,\n },\n ];\n }\n\n return [];\n },\n};\n","import { formatYen } from \"../../utils/monetary.js\";\nimport type { Yen } from \"../../models/types.js\";\nimport type { Rule, RuleContext, RuleDiagnostic } from \"../types.js\";\n\n/**\n * corporate/betsu4-taxable-income\n * 別表四: 当期利益 + 加算 - 減算 = 所得金額\n */\nexport const betsu4TaxableIncomeRule: Rule = {\n meta: {\n id: \"corporate/betsu4-taxable-income\",\n name: \"別表四所得金額計算\",\n description:\n \"別表四の所得金額 = 当期利益 + 加算項目合計 - 減算項目合計 を検証する\",\n severity: \"error\",\n applicableTo: [\"corporate\"],\n },\n\n check(ctx: RuleContext): RuleDiagnostic[] {\n if (ctx.taxReturn.returnType !== \"corporate\") return [];\n const adj = ctx.taxReturn.incomeAdjustment;\n\n const expected = (adj.accountingProfit + adj.addBackTotal - adj.deductionTotal) as Yen;\n\n if (adj.taxableIncome !== expected) {\n return [\n {\n ruleId: this.meta.id,\n severity: this.meta.severity,\n message: `別表四の所得金額(${formatYen(adj.taxableIncome)}) ≠ 当期利益(${formatYen(adj.accountingProfit)}) + 加算(${formatYen(adj.addBackTotal)}) - 減算(${formatYen(adj.deductionTotal)})`,\n expected: `所得金額 = ${formatYen(expected)}`,\n },\n ];\n }\n\n return [];\n },\n};\n","import { formatYen } from \"../../utils/monetary.js\";\nimport type { Rule, RuleContext, RuleDiagnostic } from \"../types.js\";\n\n/**\n * corporate/betsu1-match\n * 別表一の所得金額 = 別表四の所得金額\n */\nexport const betsu1MatchRule: Rule = {\n meta: {\n id: \"corporate/betsu1-match\",\n name: \"別表一↔別表四整合性\",\n description:\n \"別表一(法人税申告書)の所得金額が別表四の所得金額と一致するか検証する\",\n severity: \"error\",\n applicableTo: [\"corporate\"],\n },\n\n check(ctx: RuleContext): RuleDiagnostic[] {\n if (ctx.taxReturn.returnType !== \"corporate\") return [];\n const betsu1Income = ctx.taxReturn.corporateTaxForm.taxableIncome;\n const betsu4Income = ctx.taxReturn.incomeAdjustment.taxableIncome;\n\n if (betsu1Income !== betsu4Income) {\n return [\n {\n ruleId: this.meta.id,\n severity: this.meta.severity,\n message: `別表一の所得金額(${formatYen(betsu1Income)}) ≠ 別表四の所得金額(${formatYen(betsu4Income)})`,\n expected: `別表一の所得金額 = ${formatYen(betsu4Income)}`,\n },\n ];\n }\n\n return [];\n },\n};\n","import { formatYen } from \"../../utils/monetary.js\";\nimport { yen } from \"../../models/types.js\";\nimport type { Rule, RuleContext, RuleDiagnostic } from \"../types.js\";\n\nconst CAPITAL_LIMIT = yen(10_000_000);\n\n/**\n * corporate/capital-under-10m\n * 資本金が1000万円以下であることを確認(マイクロ法人前提)\n */\nexport const capitalUnder10mRule: Rule = {\n meta: {\n id: \"corporate/capital-under-10m\",\n name: \"資本金1000万以下チェック\",\n description:\n \"マイクロ法人として資本金が1,000万円以下であることを確認する。消費税の免税事業者要件にも関連します。\",\n severity: \"warning\",\n applicableTo: [\"corporate\"],\n },\n\n check(ctx: RuleContext): RuleDiagnostic[] {\n if (ctx.taxReturn.returnType !== \"corporate\") return [];\n const capital = ctx.taxReturn.corporateInfo.capitalAmount;\n\n if (capital > CAPITAL_LIMIT) {\n return [\n {\n ruleId: this.meta.id,\n severity: this.meta.severity,\n message: `資本金(${formatYen(capital)})が1,000万円を超えています`,\n details:\n \"資本金1,000万円超の場合、設立初年度から消費税の課税事業者となります。マイクロ法人では通常1,000万円以下に設定します。\",\n expected: `資本金 ≤ ${formatYen(CAPITAL_LIMIT)}`,\n },\n ];\n }\n\n return [];\n },\n};\n","import { formatYen } from \"../../utils/monetary.js\";\nimport { yen } from \"../../models/types.js\";\nimport type { Rule, RuleContext, RuleDiagnostic } from \"../types.js\";\n\n/**\n * corporate/officer-compensation\n * 役員報酬の妥当性チェック\n */\nexport const officerCompensationRule: Rule = {\n meta: {\n id: \"corporate/officer-compensation\",\n name: \"役員報酬妥当性チェック\",\n description:\n \"役員報酬(給料賃金)が売上に対して妥当な範囲内かチェックする。一人法人では給料賃金 = 役員報酬として検証する。\",\n severity: \"warning\",\n applicableTo: [\"corporate\"],\n },\n\n check(ctx: RuleContext): RuleDiagnostic[] {\n if (ctx.taxReturn.returnType !== \"corporate\") return [];\n const diagnostics: RuleDiagnostic[] = [];\n const pl = ctx.taxReturn.incomeStatement;\n const salaries = pl.expenses.salaries;\n\n // 役員報酬が0の場合はスキップ\n if (salaries === 0) return [];\n\n // 役員報酬が売上を超えている場合\n if (salaries > pl.revenue && pl.revenue > 0) {\n diagnostics.push({\n ruleId: this.meta.id,\n severity: this.meta.severity,\n message: `役員報酬(${formatYen(salaries)})が売上高(${formatYen(pl.revenue)})を超えています`,\n details:\n \"役員報酬が売上を超える状態が継続すると債務超過のリスクがあります。\",\n });\n }\n\n // 役員報酬が経常利益を大幅に超えて赤字になっている場合\n if (pl.ordinaryIncome < 0 && salaries > 0) {\n const incomeBeforeSalary = yen(pl.ordinaryIncome + salaries);\n if (incomeBeforeSalary > 0) {\n diagnostics.push({\n ruleId: this.meta.id,\n severity: this.meta.severity,\n message: `役員報酬控除前は黒字(${formatYen(incomeBeforeSalary)})ですが、役員報酬(${formatYen(salaries)})により経常赤字(${formatYen(pl.ordinaryIncome)})となっています`,\n details:\n \"役員報酬の金額が適正か見直しを検討してください。定期同額給与の要件にもご注意ください。\",\n });\n }\n }\n\n return diagnostics;\n },\n};\n","import { formatYen } from \"../../utils/monetary.js\";\nimport { yen } from \"../../models/types.js\";\nimport type { Yen } from \"../../models/types.js\";\nimport type { Rule, RuleContext, RuleDiagnostic } from \"../types.js\";\n\n/**\n * corporate/entertainment-limit\n * 交際費の損金算入限度額チェック(中小法人:年800万円)\n */\nexport const entertainmentLimitRule: Rule = {\n meta: {\n id: \"corporate/entertainment-limit\",\n name: \"交際費損金算入限度\",\n description:\n \"中小法人の交際費の損金算入限度額(年800万円)を超えていないかチェックする。事業年度が12ヶ月未満の場合は月割計算する。\",\n severity: \"warning\",\n applicableTo: [\"corporate\"],\n },\n\n check(ctx: RuleContext): RuleDiagnostic[] {\n if (ctx.taxReturn.returnType !== \"corporate\") return [];\n const entertainment = ctx.taxReturn.incomeStatement.expenses.entertainment;\n\n if (entertainment === 0) return [];\n\n const months = ctx.taxReturn.corporateInfo.fiscalYearMonths;\n const annualLimit = yen(8_000_000);\n const limit = yen(Math.trunc((annualLimit * months) / 12)) as Yen;\n\n if (entertainment > limit) {\n return [\n {\n ruleId: this.meta.id,\n severity: this.meta.severity,\n message: `交際費(${formatYen(entertainment)})が損金算入限度額(${formatYen(limit)})を超えています`,\n details:\n months < 12\n ? `事業年度${months}ヶ月のため、限度額は800万円×${months}/12で計算しています。超過分は損金不算入となります。`\n : \"中小法人の交際費の損金算入限度額は年800万円です。超過分は損金不算入となります。\",\n expected: `交際費 ≤ ${formatYen(limit)}`,\n },\n ];\n }\n\n return [];\n },\n};\n","import { formatYen } from \"../../utils/monetary.js\";\nimport { yen } from \"../../models/types.js\";\nimport type { Rule, RuleContext, RuleDiagnostic } from \"../types.js\";\n\nconst REDUCED_RATE_LIMIT = yen(8_000_000);\n\n/**\n * corporate/small-corp-tax-rate\n * 中小法人の軽減税率適用チェック\n */\nexport const smallCorpTaxRateRule: Rule = {\n meta: {\n id: \"corporate/small-corp-tax-rate\",\n name: \"軽減税率適用チェック\",\n description:\n \"中小法人の所得800万円以下の部分に軽減税率(15%)が適用可能か確認する。資本金1億円以下の法人が対象。\",\n severity: \"info\",\n applicableTo: [\"corporate\"],\n },\n\n check(ctx: RuleContext): RuleDiagnostic[] {\n if (ctx.taxReturn.returnType !== \"corporate\") return [];\n const info = ctx.taxReturn.corporateInfo;\n const taxableIncome = ctx.taxReturn.incomeAdjustment.taxableIncome;\n\n if (!info.isSmallCorp) return [];\n if (taxableIncome <= 0) return [];\n\n if (taxableIncome > REDUCED_RATE_LIMIT) {\n return [\n {\n ruleId: this.meta.id,\n severity: this.meta.severity,\n message: `所得金額(${formatYen(taxableIncome)})が800万円を超えています。800万円以下の部分に軽減税率15%、超過分に23.2%が適用されます。`,\n details: `軽減税率適用分: ${formatYen(REDUCED_RATE_LIMIT)}、通常税率適用分: ${formatYen(yen(taxableIncome - REDUCED_RATE_LIMIT))}`,\n },\n ];\n }\n\n return [];\n },\n};\n","import { formatYen } from \"../../utils/monetary.js\";\nimport { yen } from \"../../models/types.js\";\nimport type { Rule, RuleContext, RuleDiagnostic } from \"../types.js\";\n\n/**\n * corporate/retained-earnings-continuity\n * 利益剰余金の繰越: 期末利益剰余金 = 期首利益剰余金 + 当期純利益\n */\nexport const retainedEarningsContinuityRule: Rule = {\n meta: {\n id: \"corporate/retained-earnings-continuity\",\n name: \"利益剰余金繰越チェック\",\n description:\n \"利益剰余金の期末残高 = 期首残高 + 当期純利益 であることを検証する(配当なしを前提)\",\n severity: \"error\",\n applicableTo: [\"corporate\"],\n },\n\n check(ctx: RuleContext): RuleDiagnostic[] {\n if (ctx.taxReturn.returnType !== \"corporate\") return [];\n const bs = ctx.taxReturn.balanceSheet;\n\n const expected = yen(bs.retainedEarnings.opening + bs.netIncome);\n const actual = bs.retainedEarnings.closing;\n\n if (actual !== expected) {\n return [\n {\n ruleId: this.meta.id,\n severity: this.meta.severity,\n message: `利益剰余金の期末残高(${formatYen(actual)}) ≠ 期首残高(${formatYen(bs.retainedEarnings.opening)}) + 当期純利益(${formatYen(bs.netIncome)})`,\n details:\n \"配当や自己株式取得がある場合はその分を考慮してください。\",\n expected: `利益剰余金の期末残高 = ${formatYen(expected)}`,\n },\n ];\n }\n\n return [];\n },\n};\n","import type { Rule } from \"./types.js\";\n\n// Core rules\nimport { bsEquationRule } from \"./balance-sheet/bs-equation.js\";\nimport { plArithmeticChainRule } from \"./income-statement/pl-arithmetic-chain.js\";\nimport { cogsCalculationRule } from \"./income-statement/cogs-calculation.js\";\nimport { expenseTotalRule } from \"./income-statement/expense-total.js\";\nimport { bsPlBridgeRule } from \"./cross-statement/bs-pl-bridge.js\";\n\n// Balance sheet rules\nimport { openingOwnerEquityRule } from \"./balance-sheet/opening-owner-equity.js\";\nimport { motoireKinFormulaRule } from \"./balance-sheet/motoire-kin-formula.js\";\nimport { nonNegativeCashRule } from \"./balance-sheet/non-negative-cash.js\";\n\n// Deduction rules\nimport { blueDeductionCapRule } from \"./deductions/blue-deduction-cap.js\";\nimport { blueDeductionEligibilityRule } from \"./deductions/blue-deduction-eligibility.js\";\n\n// Depreciation rules\nimport { usefulLifeRatesRule } from \"./depreciation/useful-life-rates.js\";\nimport { smallAssetThresholdRule } from \"./depreciation/small-asset-threshold.js\";\n\n// Cross-statement rules\nimport { decisionToReturnRule } from \"./cross-statement/decision-to-return.js\";\nimport { depreciationSumRule } from \"./cross-statement/depreciation-sum.js\";\n\n// Continuity rules\nimport { openingClosingMatchRule } from \"./continuity/opening-closing-match.js\";\nimport { yearOverYearChangeRule } from \"./continuity/year-over-year-change.js\";\n\n// Home office rules\nimport { reasonableRatioRule } from \"./home-office/reasonable-ratio.js\";\n\n// Individual (wage earner) rules\nimport {\n basicDeductionRule,\n deductionTotalRule,\n taxableIncomeRule,\n withholdingTotalRule,\n} from \"./individual/index.js\";\n\n// Corporate rules\nimport {\n corporateBsEquationRule,\n corporatePlChainRule,\n corporateExpenseTotalRule,\n corporateBsPlBridgeRule,\n betsu4AccountingProfitRule,\n betsu4TaxableIncomeRule,\n betsu1MatchRule,\n capitalUnder10mRule,\n officerCompensationRule,\n entertainmentLimitRule,\n smallCorpTaxRateRule,\n retainedEarningsContinuityRule,\n} from \"./corporate/index.js\";\n\nconst ruleRegistry = new Map<string, Rule>();\n\nexport function registerRule(rule: Rule): void {\n ruleRegistry.set(rule.meta.id, rule);\n}\n\nexport function getAllRules(): Rule[] {\n return [...ruleRegistry.values()];\n}\n\nexport function getRule(id: string): Rule | undefined {\n return ruleRegistry.get(id);\n}\n\n// Register individual rules\nregisterRule(bsEquationRule);\nregisterRule(openingOwnerEquityRule);\nregisterRule(motoireKinFormulaRule);\nregisterRule(nonNegativeCashRule);\nregisterRule(plArithmeticChainRule);\nregisterRule(cogsCalculationRule);\nregisterRule(expenseTotalRule);\nregisterRule(bsPlBridgeRule);\nregisterRule(decisionToReturnRule);\nregisterRule(depreciationSumRule);\nregisterRule(blueDeductionCapRule);\nregisterRule(blueDeductionEligibilityRule);\nregisterRule(usefulLifeRatesRule);\nregisterRule(smallAssetThresholdRule);\nregisterRule(openingClosingMatchRule);\nregisterRule(yearOverYearChangeRule);\nregisterRule(reasonableRatioRule);\n\n// Register individual (wage earner) rules\nregisterRule(basicDeductionRule);\nregisterRule(deductionTotalRule);\nregisterRule(taxableIncomeRule);\nregisterRule(withholdingTotalRule);\n\n// Register corporate rules\nregisterRule(corporateBsEquationRule);\nregisterRule(corporatePlChainRule);\nregisterRule(corporateExpenseTotalRule);\nregisterRule(corporateBsPlBridgeRule);\nregisterRule(betsu4AccountingProfitRule);\nregisterRule(betsu4TaxableIncomeRule);\nregisterRule(betsu1MatchRule);\nregisterRule(capitalUnder10mRule);\nregisterRule(officerCompensationRule);\nregisterRule(entertainmentLimitRule);\nregisterRule(smallCorpTaxRateRule);\nregisterRule(retainedEarningsContinuityRule);\n\nexport type {\n Rule,\n RuleContext,\n RuleConfig,\n ResolvedConfig,\n RuleDiagnostic,\n RuleMeta,\n Severity,\n} from \"./types.js\";\nexport { runRules } from \"./rule-runner.js\";\n","import { readFile } from \"node:fs/promises\";\nimport { resolve } from \"node:path\";\nimport { ConfigError } from \"../utils/errors.js\";\nimport type { ResolvedConfig } from \"../rules/types.js\";\nimport { defaultConfig } from \"./defaults.js\";\nimport { configSchema } from \"./schema.js\";\n\nexport type { ZeicheckConfig } from \"./types.js\";\n\n/**\n * Load configuration from a file path, or use defaults.\n * Merges with defaults so partial configs are fine.\n */\nexport async function loadConfig(configPath?: string): Promise<ResolvedConfig> {\n if (!configPath) {\n // Try to find .zeicheckrc.json in cwd\n const defaultPath = resolve(process.cwd(), \".zeicheckrc.json\");\n try {\n return await readConfigFile(defaultPath);\n } catch {\n return defaultConfig;\n }\n }\n\n return readConfigFile(configPath);\n}\n\nasync function readConfigFile(filePath: string): Promise<ResolvedConfig> {\n let raw: string;\n try {\n raw = await readFile(filePath, \"utf-8\");\n } catch {\n throw new ConfigError(`設定ファイルが見つかりません: ${filePath}`, filePath);\n }\n\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw);\n } catch {\n throw new ConfigError(\n `設定ファイルのJSON解析に失敗しました: ${filePath}`,\n filePath,\n );\n }\n\n const result = configSchema.safeParse(parsed);\n if (!result.success) {\n const issues = result.error.issues\n .map((i) => ` ${i.path.join(\".\")}: ${i.message}`)\n .join(\"\\n\");\n throw new ConfigError(\n `設定ファイルのバリデーションに失敗しました:\\n${issues}`,\n filePath,\n );\n }\n\n return result.data;\n}\n","/**\n * Custom error classes for zeicheck.\n */\n\nexport class ParseError extends Error {\n constructor(message: string, public readonly filePath?: string) {\n super(message);\n this.name = \"ParseError\";\n }\n}\n\nexport class ConfigError extends Error {\n constructor(message: string, public readonly configPath?: string) {\n super(message);\n this.name = \"ConfigError\";\n }\n}\n","import type { ZeicheckConfig } from \"./types.js\";\n\nexport const defaultConfig: ZeicheckConfig = {\n rules: {},\n format: \"stylish\",\n warningsAsErrors: false,\n};\n","import { z } from \"zod\";\n\nconst severitySchema = z.enum([\"error\", \"warning\", \"info\", \"off\"]);\n\nconst ruleValueSchema = z.union([\n severitySchema,\n z.tuple([severitySchema, z.record(z.string(), z.unknown())]),\n]);\n\nexport const configSchema = z.object({\n rules: z.record(z.string(), ruleValueSchema).default({}),\n priorYearFile: z.string().optional(),\n format: z.enum([\"stylish\", \"json\"]).default(\"stylish\"),\n warningsAsErrors: z.boolean().default(false),\n});\n\nexport type ConfigInput = z.input<typeof configSchema>;\n","import pc from \"picocolors\";\nimport type { RuleDiagnostic, Severity } from \"../../rules/types.js\";\nimport type { FormatInput, FormatResult, Formatter } from \"./types.js\";\n\nfunction colorSeverity(severity: Severity): string {\n switch (severity) {\n case \"error\":\n return pc.red(severity);\n case \"warning\":\n return pc.yellow(severity);\n case \"info\":\n return pc.blue(severity);\n default:\n return severity;\n }\n}\n\nfunction padRight(str: string, len: number): string {\n return str + \" \".repeat(Math.max(0, len - str.length));\n}\n\nexport const stylishFormatter: Formatter = {\n format(input: FormatInput): FormatResult {\n const { filePath, diagnostics } = input;\n\n let errorCount = 0;\n let warningCount = 0;\n let infoCount = 0;\n\n for (const d of diagnostics) {\n if (d.severity === \"error\") errorCount++;\n else if (d.severity === \"warning\") warningCount++;\n else if (d.severity === \"info\") infoCount++;\n }\n\n if (diagnostics.length === 0) {\n return { output: \"\", errorCount: 0, warningCount: 0, infoCount: 0 };\n }\n\n const lines: string[] = [];\n lines.push(\"\");\n lines.push(pc.underline(filePath));\n lines.push(\"\");\n\n // Compute column widths\n const maxRuleIdLen = Math.max(\n ...diagnostics.map((d) => d.ruleId.length),\n );\n const maxSeverityLen = 7; // \"warning\" is the longest\n\n for (const diag of diagnostics) {\n const ruleId = padRight(diag.ruleId, maxRuleIdLen);\n const severity = padRight(diag.severity, maxSeverityLen);\n lines.push(\n ` ${ruleId} ${colorSeverity(diag.severity as Severity)}${\" \".repeat(maxSeverityLen - diag.severity.length)} ${diag.message}`,\n );\n if (diag.expected) {\n lines.push(\n ` ${\" \".repeat(maxRuleIdLen)} ${\" \".repeat(maxSeverityLen)} ${pc.green(`→ ${diag.expected}`)}`,\n );\n }\n }\n\n lines.push(\"\");\n\n const total = diagnostics.length;\n const summary = `${pc.bold(errorCount > 0 ? pc.red(`✖ ${total} 件の問題`) : `✖ ${total} 件の問題`)} (${errorCount} errors, ${warningCount} warnings)`;\n lines.push(summary);\n\n return {\n output: lines.join(\"\\n\"),\n errorCount,\n warningCount,\n infoCount,\n };\n },\n};\n","import type { FormatInput, FormatResult, Formatter } from \"./types.js\";\n\nexport const jsonFormatter: Formatter = {\n format(input: FormatInput): FormatResult {\n const { filePath, diagnostics } = input;\n\n let errorCount = 0;\n let warningCount = 0;\n let infoCount = 0;\n\n for (const d of diagnostics) {\n if (d.severity === \"error\") errorCount++;\n else if (d.severity === \"warning\") warningCount++;\n else if (d.severity === \"info\") infoCount++;\n }\n\n const output = JSON.stringify(\n {\n filePath,\n diagnostics,\n summary: {\n total: diagnostics.length,\n errors: errorCount,\n warnings: warningCount,\n info: infoCount,\n },\n },\n null,\n 2,\n );\n\n return { output, errorCount, warningCount, infoCount };\n },\n};\n","import type { Formatter } from \"./types.js\";\nimport { stylishFormatter } from \"./stylish.js\";\nimport { jsonFormatter } from \"./json.js\";\n\nexport type { Formatter, FormatInput, FormatResult } from \"./types.js\";\n\nexport function getFormatter(name: string): Formatter {\n switch (name) {\n case \"json\":\n return jsonFormatter;\n case \"stylish\":\n default:\n return stylishFormatter;\n }\n}\n"],"mappings":"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","names":["FormType","readFile","readFile"]}
package/dist/cli.js CHANGED
@@ -7,7 +7,7 @@ import {
7
7
  loadConfig,
8
8
  parseXtxFile,
9
9
  runRules
10
- } from "./chunk-5PKY24GY.js";
10
+ } from "./chunk-6ADWLQU7.js";
11
11
 
12
12
  // src/cli.ts
13
13
  import { Command } from "commander";
package/dist/index.js CHANGED
@@ -9,7 +9,7 @@ import {
9
9
  parseXtxString,
10
10
  runRules,
11
11
  yen
12
- } from "./chunk-5PKY24GY.js";
12
+ } from "./chunk-6ADWLQU7.js";
13
13
  export {
14
14
  FormType,
15
15
  getAllRules,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kalbi/zeicheck",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "description": "e-Tax (xtx) 確定申告データの整合性チェッカー",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -49,17 +49,17 @@
49
49
  "node": ">=20"
50
50
  },
51
51
  "dependencies": {
52
- "commander": "^13.1.0",
52
+ "commander": "^14.0.3",
53
53
  "fast-xml-parser": "^5.2.0",
54
54
  "picocolors": "^1.1.1",
55
- "zod": "^3.24.2"
55
+ "zod": "^4.3.6"
56
56
  },
57
57
  "devDependencies": {
58
- "@types/node": "^22.13.4",
59
- "eslint": "^9.20.0",
58
+ "@types/node": "^25.2.3",
59
+ "@vitest/coverage-v8": "^4.0.18",
60
+ "eslint": "^10.0.0",
60
61
  "tsup": "^8.4.0",
61
62
  "typescript": "^5.7.3",
62
- "vitest": "^3.0.6",
63
- "@vitest/coverage-v8": "^3.0.6"
63
+ "vitest": "^4.0.18"
64
64
  }
65
65
  }
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/models/types.ts","../src/parser/xtx-reader.ts","../src/parser/form-detector.ts","../src/parser/normalizer.ts","../src/parser/index.ts","../src/rules/rule-runner.ts","../src/utils/monetary.ts","../src/rules/balance-sheet/bs-equation.ts","../src/rules/income-statement/pl-arithmetic-chain.ts","../src/rules/income-statement/cogs-calculation.ts","../src/rules/income-statement/expense-total.ts","../src/rules/cross-statement/bs-pl-bridge.ts","../src/rules/balance-sheet/opening-owner-equity.ts","../src/rules/balance-sheet/motoire-kin-formula.ts","../src/rules/balance-sheet/non-negative-cash.ts","../src/rules/deductions/blue-deduction-cap.ts","../src/rules/deductions/blue-deduction-eligibility.ts","../src/rules/depreciation/useful-life-rates.ts","../src/rules/depreciation/small-asset-threshold.ts","../src/rules/cross-statement/decision-to-return.ts","../src/rules/cross-statement/depreciation-sum.ts","../src/rules/continuity/opening-closing-match.ts","../src/rules/continuity/year-over-year-change.ts","../src/rules/home-office/reasonable-ratio.ts","../src/rules/corporate/bs-equation.ts","../src/rules/corporate/pl-chain.ts","../src/rules/corporate/expense-total.ts","../src/rules/corporate/bs-pl-bridge.ts","../src/rules/corporate/betsu4-accounting-profit.ts","../src/rules/corporate/betsu4-taxable-income.ts","../src/rules/corporate/betsu1-match.ts","../src/rules/corporate/capital-under-10m.ts","../src/rules/corporate/officer-compensation.ts","../src/rules/corporate/entertainment-limit.ts","../src/rules/corporate/small-corp-tax-rate.ts","../src/rules/corporate/retained-earnings-continuity.ts","../src/rules/index.ts","../src/config/index.ts","../src/utils/errors.ts","../src/config/defaults.ts","../src/config/schema.ts","../src/cli/formatter/stylish.ts","../src/cli/formatter/json.ts","../src/cli/formatter/index.ts"],"sourcesContent":["/**\n * Core types for zeicheck tax return models.\n */\n\n/** Branded type for integer yen amounts. Prevents accidental float usage. */\nexport type Yen = number & { readonly __brand: unique symbol };\n\n/** Create a Yen value from a number. Truncates to integer. */\nexport function yen(n: number): Yen {\n return Math.trunc(n) as Yen;\n}\n\n/** Fiscal year representation */\nexport interface FiscalYear {\n /** 和暦年 (e.g., 5 for 令和5年) */\n readonly nengo: number;\n /** 西暦年 (e.g., 2023) */\n readonly year: number;\n /** 期首日 */\n readonly startDate: string;\n /** 期末日 */\n readonly endDate: string;\n}\n\n/** Account balance with opening and closing amounts */\nexport interface AccountBalance {\n readonly opening: Yen;\n readonly closing: Yen;\n}\n\n/** 申告区分(個人事業主/個人/法人) */\nexport type TaxReturnType = \"sole-proprietor\" | \"individual\" | \"corporate\";\n\n/** Form types in e-Tax xtx files */\nexport enum FormType {\n /** 申告書第一表 */\n ABA = \"ABA\",\n /** 申告書第二表 */\n ABB = \"ABB\",\n /** 青色申告決算書(一般用) */\n VCA = \"VCA\",\n /** 法人税申告書 別表一 */\n HOA = \"HOA\",\n /** 法人税申告書 別表四 */\n HOD = \"HOD\",\n /** 法人決算書 */\n HOK = \"HOK\",\n}\n\n/** Metadata about the tax return */\nexport interface TaxReturnMetadata {\n readonly filePath: string;\n readonly formTypes: FormType[];\n readonly filingMethod?: string;\n}\n","/**\n * Reads and parses .xtx (XML) files into ParsedXtxFile structures.\n */\n\nimport { readFile } from \"node:fs/promises\";\nimport { XMLParser } from \"fast-xml-parser\";\nimport type { ParsedForm, ParsedXtxFile } from \"./types.js\";\n\nconst parser = new XMLParser({\n ignoreAttributes: false,\n attributeNamePrefix: \"@_\",\n isArray: (_name: string, jpath: string) => {\n // Ensure FormData and Field are always arrays\n return jpath === \"DataRoot.FormData\" || /\\.FormData\\.Field$/.test(jpath);\n },\n});\n\ninterface XmlField {\n \"#text\"?: string;\n \"@_id\": string;\n}\n\ninterface XmlFormData {\n \"@_id\": string;\n Field?: XmlField[];\n}\n\ninterface XmlDataRoot {\n DataRoot: {\n FormData?: XmlFormData[];\n };\n}\n\nfunction parseXml(xml: string): ParsedXtxFile {\n const result = parser.parse(xml) as XmlDataRoot;\n\n const root = result.DataRoot;\n if (!root) {\n throw new Error(\"Invalid xtx: missing DataRoot element\");\n }\n\n const formDataArray = root.FormData ?? [];\n const forms: ParsedForm[] = formDataArray.map((fd) => {\n const fields = new Map<string, string>();\n const xmlFields = fd.Field ?? [];\n for (const field of xmlFields) {\n const value = field[\"#text\"] != null ? String(field[\"#text\"]) : \"\";\n fields.set(field[\"@_id\"], value);\n }\n return {\n formType: fd[\"@_id\"],\n fields,\n };\n });\n\n return { forms, rawXml: xml };\n}\n\n/** Parse an xtx XML string into a structured ParsedXtxFile. */\nexport function readXtxString(xml: string): ParsedXtxFile {\n return parseXml(xml);\n}\n\n/** Read and parse an xtx file from the filesystem. */\nexport async function readXtxFile(filePath: string): Promise<ParsedXtxFile> {\n const xml = await readFile(filePath, \"utf-8\");\n return parseXml(xml);\n}\n","/**\n * Detects which form types are present in a parsed xtx file.\n */\n\nimport { FormType } from \"../models/types.js\";\nimport type { ParsedXtxFile } from \"./types.js\";\n\nconst knownForms: ReadonlyMap<string, FormType> = new Map([\n [\"ABA\", FormType.ABA],\n [\"ABB\", FormType.ABB],\n [\"VCA\", FormType.VCA],\n [\"HOA\", FormType.HOA],\n [\"HOD\", FormType.HOD],\n [\"HOK\", FormType.HOK],\n]);\n\n/** Detect FormType enum values from parsed forms. */\nexport function detectForms(parsed: ParsedXtxFile): FormType[] {\n const detected: FormType[] = [];\n for (const form of parsed.forms) {\n const formType = knownForms.get(form.formType);\n if (formType !== undefined) {\n detected.push(formType);\n }\n }\n return detected;\n}\n","/**\n * Normalizes a ParsedXtxFile into a typed TaxReturn model.\n */\n\nimport type { BalanceSheet } from \"../models/balance-sheet.js\";\nimport type { CorporateBalanceSheet } from \"../models/corporate-balance-sheet.js\";\nimport type { CorporateIncomeStatement } from \"../models/corporate-income-statement.js\";\nimport type {\n CorporateInfo,\n CorporateTaxFormMain,\n IncomeAdjustmentSchedule,\n} from \"../models/corporate-tax-form.js\";\nimport type { DepreciationSchedule } from \"../models/depreciation-schedule.js\";\nimport type { IncomeStatement } from \"../models/income-statement.js\";\nimport type { TaxFormA, TaxFormB } from \"../models/tax-form.js\";\nimport {\n FormType,\n yen,\n type AccountBalance,\n type FiscalYear,\n type Yen,\n} from \"../models/types.js\";\nimport type {\n SoleProprietorReturn,\n IndividualReturn,\n CorporateReturn,\n TaxReturn,\n} from \"../models/tax-return.js\";\nimport { detectForms } from \"./form-detector.js\";\nimport type { ParsedXtxFile } from \"./types.js\";\n\n/** Read a yen value from a field map, defaulting to 0. */\nfunction yenField(fields: Map<string, string>, code: string): Yen {\n const raw = fields.get(code);\n return yen(raw ? Number(raw) : 0);\n}\n\n/** Build an AccountBalance from opening/closing field codes. */\nfunction accountBalance(\n fields: Map<string, string>,\n openingCode: string,\n closingCode: string,\n): AccountBalance {\n return {\n opening: yenField(fields, openingCode),\n closing: yenField(fields, closingCode),\n };\n}\n\nfunction getFormFields(\n parsed: ParsedXtxFile,\n formType: string,\n): Map<string, string> {\n const form = parsed.forms.find((f) => f.formType === formType);\n return form?.fields ?? new Map();\n}\n\n// ── Sole Proprietor builders ──\n\nfunction buildIncomeStatement(vca: Map<string, string>): IncomeStatement {\n return {\n revenue: yenField(vca, \"ITA_VCA0010\"),\n cogs: {\n openingInventory: yenField(vca, \"ITA_VCA0020\"),\n purchases: yenField(vca, \"ITA_VCA0030\"),\n closingInventory: yenField(vca, \"ITA_VCA0040\"),\n total: yenField(vca, \"ITA_VCA0050\"),\n },\n grossProfit: yenField(vca, \"ITA_VCA0060\"),\n expenses: {\n taxes: yenField(vca, \"ITA_VCA0100\"),\n insurance: yenField(vca, \"ITA_VCA0110\"),\n repairs: yenField(vca, \"ITA_VCA0120\"),\n depreciation: yenField(vca, \"ITA_VCA0130\"),\n welfare: yenField(vca, \"ITA_VCA0140\"),\n salaries: yenField(vca, \"ITA_VCA0150\"),\n outsourcing: yenField(vca, \"ITA_VCA0160\"),\n interest: yenField(vca, \"ITA_VCA0170\"),\n rent: yenField(vca, \"ITA_VCA0180\"),\n retirement: yenField(vca, \"ITA_VCA0190\"),\n utilities: yenField(vca, \"ITA_VCA0200\"),\n travel: yenField(vca, \"ITA_VCA0210\"),\n communication: yenField(vca, \"ITA_VCA0220\"),\n advertising: yenField(vca, \"ITA_VCA0230\"),\n entertainment: yenField(vca, \"ITA_VCA0240\"),\n consumables: yenField(vca, \"ITA_VCA0250\"),\n miscellaneous: yenField(vca, \"ITA_VCA0260\"),\n otherExpenses: yenField(vca, \"ITA_VCA0270\"),\n },\n totalExpenses: yenField(vca, \"ITA_VCA0280\"),\n operatingIncome: yenField(vca, \"ITA_VCA0290\"),\n };\n}\n\nfunction buildBalanceSheet(vca: Map<string, string>): BalanceSheet {\n return {\n // Assets\n cash: accountBalance(vca, \"ITA_VCA1010\", \"ITA_VCA1210\"),\n deposits: accountBalance(vca, \"ITA_VCA1020\", \"ITA_VCA1220\"),\n accountsReceivable: accountBalance(vca, \"ITA_VCA1030\", \"ITA_VCA1230\"),\n inventory: accountBalance(vca, \"ITA_VCA1040\", \"ITA_VCA1240\"),\n otherCurrentAssets: accountBalance(vca, \"ITA_VCA1050\", \"ITA_VCA1250\"),\n buildings: accountBalance(vca, \"ITA_VCA1060\", \"ITA_VCA1260\"),\n buildingImprovements: accountBalance(vca, \"ITA_VCA1070\", \"ITA_VCA1270\"),\n machinery: accountBalance(vca, \"ITA_VCA1080\", \"ITA_VCA1280\"),\n vehicles: accountBalance(vca, \"ITA_VCA1090\", \"ITA_VCA1290\"),\n tools: accountBalance(vca, \"ITA_VCA1100\", \"ITA_VCA1300\"),\n land: accountBalance(vca, \"ITA_VCA1110\", \"ITA_VCA1310\"),\n otherFixedAssets: accountBalance(vca, \"ITA_VCA1120\", \"ITA_VCA1320\"),\n accumulatedDepreciation: accountBalance(vca, \"ITA_VCA1130\", \"ITA_VCA1330\"),\n assetsTotal: accountBalance(vca, \"ITA_VCA1140\", \"ITA_VCA1340\"),\n\n // Liabilities\n accountsPayable: accountBalance(vca, \"ITA_VCA1410\", \"ITA_VCA1510\"),\n borrowings: accountBalance(vca, \"ITA_VCA1420\", \"ITA_VCA1520\"),\n otherCurrentLiabilities: accountBalance(vca, \"ITA_VCA1430\", \"ITA_VCA1530\"),\n liabilitiesTotal: accountBalance(vca, \"ITA_VCA1440\", \"ITA_VCA1540\"),\n\n // Equity\n ownerEquity: accountBalance(vca, \"ITA_VCA1610\", \"ITA_VCA1710\"),\n ownerDrawings: accountBalance(vca, \"ITA_VCA1620\", \"ITA_VCA1720\"),\n ownerContributions: accountBalance(vca, \"ITA_VCA1630\", \"ITA_VCA1730\"),\n retainedEarnings: yenField(vca, \"ITA_VCA1640\"),\n equityTotal: accountBalance(vca, \"ITA_VCA1650\", \"ITA_VCA1750\"),\n };\n}\n\nfunction buildTaxFormA(aba: Map<string, string>): TaxFormA {\n return {\n businessIncome: yenField(aba, \"ITA_ABA0010\"),\n realEstateIncome: yenField(aba, \"ITA_ABA0020\"),\n otherIncome: yenField(aba, \"ITA_ABA0030\"),\n businessProfit: yenField(aba, \"ITA_ABA0110\"),\n realEstateProfit: yenField(aba, \"ITA_ABA0120\"),\n totalIncome: yenField(aba, \"ITA_ABA0130\"),\n totalDeductions: yenField(aba, \"ITA_ABA0280\"),\n blueReturnDeduction: yenField(aba, \"ITA_ABA0290\"),\n taxableIncome: yenField(aba, \"ITA_ABA0310\"),\n incomeTax: yenField(aba, \"ITA_ABA0320\"),\n taxDue: yenField(aba, \"ITA_ABA0360\"),\n };\n}\n\nfunction buildTaxFormB(abb: Map<string, string>): TaxFormB {\n return {\n incomeDetails: [\n {\n type: abb.get(\"ITA_ABB0010\") ?? \"\",\n payer: abb.get(\"ITA_ABB0020\") ?? \"\",\n amount: yenField(abb, \"ITA_ABB0030\"),\n withheld: yenField(abb, \"ITA_ABB0040\"),\n },\n ],\n socialInsurance: yenField(abb, \"ITA_ABB0110\"),\n smallBusinessMutualAid: yenField(abb, \"ITA_ABB0120\"),\n lifeInsurance: yenField(abb, \"ITA_ABB0130\"),\n earthquakeInsurance: yenField(abb, \"ITA_ABB0140\"),\n spouseDeduction: yenField(abb, \"ITA_ABB0210\"),\n dependentDeduction: yenField(abb, \"ITA_ABB0220\"),\n basicDeduction: yenField(abb, \"ITA_ABB0230\"),\n };\n}\n\n// ── Corporate builders ──\n\nfunction buildCorporateIncomeStatement(\n hok: Map<string, string>,\n): CorporateIncomeStatement {\n return {\n revenue: yenField(hok, \"ITA_HOK0010\"),\n cogs: {\n openingInventory: yenField(hok, \"ITA_HOK0020\"),\n purchases: yenField(hok, \"ITA_HOK0030\"),\n closingInventory: yenField(hok, \"ITA_HOK0040\"),\n total: yenField(hok, \"ITA_HOK0050\"),\n },\n grossProfit: yenField(hok, \"ITA_HOK0060\"),\n expenses: {\n taxes: yenField(hok, \"ITA_HOK0100\"),\n insurance: yenField(hok, \"ITA_HOK0110\"),\n repairs: yenField(hok, \"ITA_HOK0120\"),\n depreciation: yenField(hok, \"ITA_HOK0130\"),\n welfare: yenField(hok, \"ITA_HOK0140\"),\n salaries: yenField(hok, \"ITA_HOK0150\"),\n outsourcing: yenField(hok, \"ITA_HOK0160\"),\n interest: yenField(hok, \"ITA_HOK0170\"),\n rent: yenField(hok, \"ITA_HOK0180\"),\n retirement: yenField(hok, \"ITA_HOK0190\"),\n utilities: yenField(hok, \"ITA_HOK0200\"),\n travel: yenField(hok, \"ITA_HOK0210\"),\n communication: yenField(hok, \"ITA_HOK0220\"),\n advertising: yenField(hok, \"ITA_HOK0230\"),\n entertainment: yenField(hok, \"ITA_HOK0240\"),\n consumables: yenField(hok, \"ITA_HOK0250\"),\n miscellaneous: yenField(hok, \"ITA_HOK0260\"),\n otherExpenses: yenField(hok, \"ITA_HOK0270\"),\n },\n totalExpenses: yenField(hok, \"ITA_HOK0280\"),\n operatingIncome: yenField(hok, \"ITA_HOK0290\"),\n nonOperatingIncome: yenField(hok, \"ITA_HOK0300\"),\n nonOperatingExpenses: yenField(hok, \"ITA_HOK0310\"),\n ordinaryIncome: yenField(hok, \"ITA_HOK0320\"),\n extraordinaryGain: yenField(hok, \"ITA_HOK0330\"),\n extraordinaryLoss: yenField(hok, \"ITA_HOK0340\"),\n preTaxIncome: yenField(hok, \"ITA_HOK0350\"),\n corporateTax: yenField(hok, \"ITA_HOK0360\"),\n netIncome: yenField(hok, \"ITA_HOK0370\"),\n };\n}\n\nfunction buildCorporateBalanceSheet(\n hok: Map<string, string>,\n): CorporateBalanceSheet {\n return {\n // Assets\n cash: accountBalance(hok, \"ITA_HOK1010\", \"ITA_HOK1210\"),\n deposits: accountBalance(hok, \"ITA_HOK1020\", \"ITA_HOK1220\"),\n accountsReceivable: accountBalance(hok, \"ITA_HOK1030\", \"ITA_HOK1230\"),\n inventory: accountBalance(hok, \"ITA_HOK1040\", \"ITA_HOK1240\"),\n otherCurrentAssets: accountBalance(hok, \"ITA_HOK1050\", \"ITA_HOK1250\"),\n buildings: accountBalance(hok, \"ITA_HOK1060\", \"ITA_HOK1260\"),\n buildingImprovements: accountBalance(hok, \"ITA_HOK1070\", \"ITA_HOK1270\"),\n machinery: accountBalance(hok, \"ITA_HOK1080\", \"ITA_HOK1280\"),\n vehicles: accountBalance(hok, \"ITA_HOK1090\", \"ITA_HOK1290\"),\n tools: accountBalance(hok, \"ITA_HOK1100\", \"ITA_HOK1300\"),\n land: accountBalance(hok, \"ITA_HOK1110\", \"ITA_HOK1310\"),\n otherFixedAssets: accountBalance(hok, \"ITA_HOK1120\", \"ITA_HOK1320\"),\n accumulatedDepreciation: accountBalance(hok, \"ITA_HOK1130\", \"ITA_HOK1330\"),\n assetsTotal: accountBalance(hok, \"ITA_HOK1140\", \"ITA_HOK1340\"),\n\n // Liabilities\n accountsPayable: accountBalance(hok, \"ITA_HOK1410\", \"ITA_HOK1510\"),\n borrowings: accountBalance(hok, \"ITA_HOK1420\", \"ITA_HOK1520\"),\n accruedExpenses: accountBalance(hok, \"ITA_HOK1430\", \"ITA_HOK1530\"),\n corporateTaxPayable: accountBalance(hok, \"ITA_HOK1440\", \"ITA_HOK1540\"),\n otherCurrentLiabilities: accountBalance(hok, \"ITA_HOK1450\", \"ITA_HOK1550\"),\n liabilitiesTotal: accountBalance(hok, \"ITA_HOK1460\", \"ITA_HOK1560\"),\n\n // Net Assets\n capitalStock: accountBalance(hok, \"ITA_HOK1610\", \"ITA_HOK1710\"),\n capitalSurplus: accountBalance(hok, \"ITA_HOK1620\", \"ITA_HOK1720\"),\n retainedEarnings: accountBalance(hok, \"ITA_HOK1630\", \"ITA_HOK1730\"),\n netIncome: yenField(hok, \"ITA_HOK0370\"),\n equityTotal: accountBalance(hok, \"ITA_HOK1650\", \"ITA_HOK1750\"),\n };\n}\n\nfunction buildCorporateTaxForm(hoa: Map<string, string>): CorporateTaxFormMain {\n return {\n taxableIncome: yenField(hoa, \"ITA_HOA0010\"),\n corporateTaxAmount: yenField(hoa, \"ITA_HOA0020\"),\n taxCredits: yenField(hoa, \"ITA_HOA0030\"),\n localCorporateTax: yenField(hoa, \"ITA_HOA0040\"),\n taxDue: yenField(hoa, \"ITA_HOA0050\"),\n };\n}\n\nfunction buildIncomeAdjustment(\n hod: Map<string, string>,\n): IncomeAdjustmentSchedule {\n return {\n accountingProfit: yenField(hod, \"ITA_HOD0010\"),\n addBackTotal: yenField(hod, \"ITA_HOD0020\"),\n deductionTotal: yenField(hod, \"ITA_HOD0030\"),\n taxableIncome: yenField(hod, \"ITA_HOD0040\"),\n };\n}\n\nfunction buildCorporateInfo(hok: Map<string, string>): CorporateInfo {\n const capitalRaw = hok.get(\"ITA_HOK1710\");\n const capitalAmount = yen(capitalRaw ? Number(capitalRaw) : 0);\n const monthsRaw = hok.get(\"ITA_HOK9010\");\n const fiscalYearMonths = monthsRaw ? Number(monthsRaw) : 12;\n const officerRaw = hok.get(\"ITA_HOK9020\");\n const officerCount = officerRaw ? Number(officerRaw) : 1;\n\n return {\n capitalAmount,\n fiscalYearMonths,\n isSmallCorp: capitalAmount <= 10_000_000,\n officerCount,\n };\n}\n\n// ── Shared helpers ──\n\nfunction buildDefaultFiscalYear(): FiscalYear {\n return {\n nengo: 5,\n year: 2023,\n startDate: \"2023-01-01\",\n endDate: \"2023-12-31\",\n };\n}\n\nfunction buildEmptyDepreciationSchedule(): DepreciationSchedule {\n return {\n assets: [],\n totalDepreciation: yen(0),\n totalBusinessDepreciation: yen(0),\n };\n}\n\n/** Check if the parsed file contains corporate form types (HOK). */\nfunction isCorporateReturn(parsed: ParsedXtxFile): boolean {\n return parsed.forms.some((f) => f.formType === \"HOK\");\n}\n\n/** Check if the parsed file contains sole-proprietor form types (VCA). */\nfunction isSoleProprietorReturn(parsed: ParsedXtxFile): boolean {\n return parsed.forms.some((f) => f.formType === \"VCA\");\n}\n\n/** Normalize as sole-proprietor return (個人事業主・青色申告). */\nfunction normalizeSoleProprietor(\n parsed: ParsedXtxFile,\n formTypes: FormType[],\n): SoleProprietorReturn {\n const vca = getFormFields(parsed, \"VCA\");\n const aba = getFormFields(parsed, \"ABA\");\n const abb = getFormFields(parsed, \"ABB\");\n\n return {\n returnType: \"sole-proprietor\",\n fiscalYear: buildDefaultFiscalYear(),\n incomeStatement: buildIncomeStatement(vca),\n balanceSheet: buildBalanceSheet(vca),\n taxFormA: buildTaxFormA(aba),\n taxFormB: buildTaxFormB(abb),\n depreciationSchedule: buildEmptyDepreciationSchedule(),\n metadata: {\n filePath: \"\",\n formTypes,\n },\n };\n}\n\n/** Normalize as individual return (給与所得者等の確定申告). */\nfunction normalizeIndividual(\n parsed: ParsedXtxFile,\n formTypes: FormType[],\n): IndividualReturn {\n const aba = getFormFields(parsed, \"ABA\");\n const abb = getFormFields(parsed, \"ABB\");\n\n return {\n returnType: \"individual\",\n fiscalYear: buildDefaultFiscalYear(),\n taxFormA: buildTaxFormA(aba),\n taxFormB: buildTaxFormB(abb),\n metadata: {\n filePath: \"\",\n formTypes,\n },\n };\n}\n\n/** Normalize as corporate return. */\nfunction normalizeCorporate(\n parsed: ParsedXtxFile,\n formTypes: FormType[],\n): CorporateReturn {\n const hok = getFormFields(parsed, \"HOK\");\n const hoa = getFormFields(parsed, \"HOA\");\n const hod = getFormFields(parsed, \"HOD\");\n\n return {\n returnType: \"corporate\",\n fiscalYear: buildDefaultFiscalYear(),\n incomeStatement: buildCorporateIncomeStatement(hok),\n balanceSheet: buildCorporateBalanceSheet(hok),\n corporateTaxForm: buildCorporateTaxForm(hoa),\n incomeAdjustment: buildIncomeAdjustment(hod),\n corporateInfo: buildCorporateInfo(hok),\n depreciationSchedule: buildEmptyDepreciationSchedule(),\n metadata: {\n filePath: \"\",\n formTypes,\n },\n };\n}\n\n/**\n * Convert a ParsedXtxFile into a typed TaxReturn.\n *\n * Detection order:\n * 1. HOK form present → corporate\n * 2. VCA form present → sole-proprietor (個人事業主)\n * 3. Otherwise → individual (給与所得者等)\n */\nexport function normalize(parsed: ParsedXtxFile): TaxReturn {\n const formTypes = detectForms(parsed);\n\n if (isCorporateReturn(parsed)) {\n return normalizeCorporate(parsed, formTypes);\n }\n\n if (isSoleProprietorReturn(parsed)) {\n return normalizeSoleProprietor(parsed, formTypes);\n }\n\n return normalizeIndividual(parsed, formTypes);\n}\n","/**\n * Public API for the parser module.\n */\n\nexport type { ParsedField, ParsedForm, ParsedXtxFile } from \"./types.js\";\nexport { readXtxFile, readXtxString } from \"./xtx-reader.js\";\nexport { detectForms } from \"./form-detector.js\";\nexport { getFieldName } from \"./field-registry.js\";\nexport { normalize } from \"./normalizer.js\";\n\nimport type { TaxReturn } from \"../models/tax-return.js\";\nimport { normalize } from \"./normalizer.js\";\nimport { readXtxFile as readFile, readXtxString as readString } from \"./xtx-reader.js\";\n\n/** Parse an xtx file from disk and return a typed TaxReturn. */\nexport async function parseXtxFile(filePath: string): Promise<TaxReturn> {\n const parsed = await readFile(filePath);\n const taxReturn = normalize(parsed);\n return {\n ...taxReturn,\n metadata: { ...taxReturn.metadata, filePath },\n };\n}\n\n/** Parse an xtx XML string and return a typed TaxReturn. */\nexport function parseXtxString(xml: string): TaxReturn {\n const parsed = readString(xml);\n return normalize(parsed);\n}\n","import type { Rule, RuleContext, RuleDiagnostic, Severity } from \"./types.js\";\n\nconst severityOrder: Record<Severity, number> = {\n error: 0,\n warning: 1,\n info: 2,\n off: 3,\n};\n\nexport function runRules(rules: Rule[], ctx: RuleContext): RuleDiagnostic[] {\n const diagnostics: RuleDiagnostic[] = [];\n\n for (const rule of rules) {\n const configEntry = ctx.config.rules[rule.meta.id];\n const severity: Severity = Array.isArray(configEntry)\n ? configEntry[0]\n : configEntry ?? rule.meta.severity;\n\n if (severity === \"off\") continue;\n\n const { applicableTo } = rule.meta;\n if (applicableTo && !applicableTo.includes(ctx.taxReturn.returnType)) continue;\n\n const results = rule.check(ctx);\n for (const diag of results) {\n diagnostics.push({ ...diag, severity });\n }\n }\n\n diagnostics.sort((a, b) => severityOrder[a.severity] - severityOrder[b.severity]);\n return diagnostics;\n}\n","/**\n * Safe integer-yen arithmetic utilities.\n * Japanese tax returns use only whole yen amounts.\n */\n\nimport { type Yen, yen } from \"../models/types.js\";\n\n/** Add two Yen amounts */\nexport function add(a: Yen, b: Yen): Yen {\n return yen(a + b);\n}\n\n/** Subtract b from a */\nexport function subtract(a: Yen, b: Yen): Yen {\n return yen(a - b);\n}\n\n/** Sum an array of Yen amounts */\nexport function sum(items: readonly Yen[]): Yen {\n return yen(items.reduce((acc, v) => acc + v, 0));\n}\n\n/** Check if a Yen amount is non-negative */\nexport function isNonNegative(a: Yen): boolean {\n return a >= 0;\n}\n\n/** Check if two Yen amounts are equal */\nexport function equals(a: Yen, b: Yen): boolean {\n return a === b;\n}\n\n/** Format a Yen amount with comma separators (e.g., \"1,234,567\") */\nexport function formatYen(a: Yen): string {\n return a.toLocaleString(\"ja-JP\");\n}\n","import { formatYen } from \"../../utils/monetary.js\";\nimport { yen } from \"../../models/types.js\";\nimport type { Rule, RuleContext, RuleDiagnostic } from \"../types.js\";\n\nexport const bsEquationRule: Rule = {\n meta: {\n id: \"balance-sheet/equation\",\n name: \"Balance Sheet Equation\",\n description: \"資産合計 = 負債合計 + 資本合計 を検証する\",\n severity: \"error\",\n applicableTo: [\"sole-proprietor\", \"corporate\"],\n },\n\n check(ctx: RuleContext): RuleDiagnostic[] {\n if (ctx.taxReturn.returnType === \"individual\") return [];\n const bs = ctx.taxReturn.balanceSheet;\n const diagnostics: RuleDiagnostic[] = [];\n\n // Check closing balance equation\n const closingAssets = bs.assetsTotal.closing;\n const closingLiabilities = bs.liabilitiesTotal.closing;\n const closingEquity = bs.equityTotal.closing;\n\n if (closingAssets !== closingLiabilities + closingEquity) {\n diagnostics.push({\n ruleId: \"balance-sheet/equation\",\n severity: \"error\",\n message: `期末残高: 資産合計(${formatYen(closingAssets)}) ≠ 負債合計(${formatYen(closingLiabilities)}) + 資本合計(${formatYen(closingEquity)})`,\n expected: `資産合計 = ${formatYen(yen(closingLiabilities + closingEquity))}`,\n });\n }\n\n // Check opening balance equation\n const openingAssets = bs.assetsTotal.opening;\n const openingLiabilities = bs.liabilitiesTotal.opening;\n const openingEquity = bs.equityTotal.opening;\n\n if (openingAssets !== openingLiabilities + openingEquity) {\n diagnostics.push({\n ruleId: \"balance-sheet/equation\",\n severity: \"error\",\n message: `期首残高: 資産合計(${formatYen(openingAssets)}) ≠ 負債合計(${formatYen(openingLiabilities)}) + 資本合計(${formatYen(openingEquity)})`,\n expected: `資産合計 = ${formatYen(yen(openingLiabilities + openingEquity))}`,\n });\n }\n\n return diagnostics;\n },\n};\n","import { formatYen } from \"../../utils/monetary.js\";\nimport type { Yen } from \"../../models/types.js\";\nimport type { Rule, RuleContext, RuleDiagnostic } from \"../types.js\";\n\nexport const plArithmeticChainRule: Rule = {\n meta: {\n id: \"income-statement/pl-chain\",\n name: \"P/L Arithmetic Chain\",\n description: \"損益計算書の計算連鎖を検証する\",\n severity: \"error\",\n applicableTo: [\"sole-proprietor\"],\n },\n\n check(ctx: RuleContext): RuleDiagnostic[] {\n if (ctx.taxReturn.returnType !== \"sole-proprietor\") return [];\n const pl = ctx.taxReturn.incomeStatement;\n const diagnostics: RuleDiagnostic[] = [];\n\n // Check: grossProfit = revenue - cogs.total\n const expectedGross = (pl.revenue - pl.cogs.total) as Yen;\n if (pl.grossProfit !== expectedGross) {\n diagnostics.push({\n ruleId: \"income-statement/pl-chain\",\n severity: \"error\",\n message: `売上総利益(${formatYen(pl.grossProfit)}) ≠ 売上(${formatYen(pl.revenue)}) - 売上原価(${formatYen(pl.cogs.total)})`,\n expected: `売上総利益 = ${formatYen(expectedGross)}`,\n });\n }\n\n // Check: operatingIncome = grossProfit - totalExpenses\n const expectedOperating = (pl.grossProfit - pl.totalExpenses) as Yen;\n if (pl.operatingIncome !== expectedOperating) {\n diagnostics.push({\n ruleId: \"income-statement/pl-chain\",\n severity: \"error\",\n message: `所得金額(${formatYen(pl.operatingIncome)}) ≠ 売上総利益(${formatYen(pl.grossProfit)}) - 経費合計(${formatYen(pl.totalExpenses)})`,\n expected: `所得金額 = ${formatYen(expectedOperating)}`,\n });\n }\n\n return diagnostics;\n },\n};\n","import { formatYen } from \"../../utils/monetary.js\";\nimport type { Yen } from \"../../models/types.js\";\nimport type { Rule, RuleContext, RuleDiagnostic } from \"../types.js\";\n\nexport const cogsCalculationRule: Rule = {\n meta: {\n id: \"income-statement/cogs\",\n name: \"COGS Calculation\",\n description: \"売上原価の計算を検証する\",\n severity: \"error\",\n applicableTo: [\"sole-proprietor\", \"corporate\"],\n },\n\n check(ctx: RuleContext): RuleDiagnostic[] {\n if (ctx.taxReturn.returnType === \"individual\") return [];\n const cogs = ctx.taxReturn.incomeStatement.cogs;\n\n // Skip if all COGS values are zero\n if (\n cogs.openingInventory === 0 &&\n cogs.purchases === 0 &&\n cogs.closingInventory === 0 &&\n cogs.total === 0\n ) {\n return [];\n }\n\n const expected = (cogs.openingInventory +\n cogs.purchases -\n cogs.closingInventory) as Yen;\n if (cogs.total !== expected) {\n return [\n {\n ruleId: \"income-statement/cogs\",\n severity: \"error\",\n message: `売上原価合計(${formatYen(cogs.total)}) ≠ 期首棚卸高(${formatYen(cogs.openingInventory)}) + 仕入金額(${formatYen(cogs.purchases)}) - 期末棚卸高(${formatYen(cogs.closingInventory)})`,\n expected: `売上原価合計 = ${formatYen(expected)}`,\n },\n ];\n }\n\n return [];\n },\n};\n","import { formatYen } from \"../../utils/monetary.js\";\nimport type { Yen } from \"../../models/types.js\";\nimport type { Rule, RuleContext, RuleDiagnostic } from \"../types.js\";\n\nexport const expenseTotalRule: Rule = {\n meta: {\n id: \"income-statement/expense-total\",\n name: \"Expense Total\",\n description: \"経費合計が各経費項目の合計と一致するか検証する\",\n severity: \"error\",\n applicableTo: [\"sole-proprietor\"],\n },\n\n check(ctx: RuleContext): RuleDiagnostic[] {\n if (ctx.taxReturn.returnType !== \"sole-proprietor\") return [];\n const exp = ctx.taxReturn.incomeStatement.expenses;\n\n const computed = (exp.salaries +\n exp.outsourcing +\n exp.retirement +\n exp.rent +\n exp.interest +\n exp.taxes +\n exp.insurance +\n exp.repairs +\n exp.consumables +\n exp.depreciation +\n exp.welfare +\n exp.utilities +\n exp.travel +\n exp.communication +\n exp.advertising +\n exp.entertainment +\n exp.miscellaneous +\n exp.otherExpenses) as Yen;\n\n const totalExpenses = ctx.taxReturn.incomeStatement.totalExpenses;\n\n if (totalExpenses !== computed) {\n return [\n {\n ruleId: \"income-statement/expense-total\",\n severity: \"error\",\n message: `経費合計(${formatYen(totalExpenses)}) ≠ 各経費項目の合計(${formatYen(computed)})`,\n expected: `経費合計 = ${formatYen(computed)}`,\n },\n ];\n }\n\n return [];\n },\n};\n","import { formatYen } from \"../../utils/monetary.js\";\nimport type { Yen } from \"../../models/types.js\";\nimport type { Rule, RuleContext, RuleDiagnostic } from \"../types.js\";\n\nexport const bsPlBridgeRule: Rule = {\n meta: {\n id: \"cross-statement/bs-pl-bridge\",\n name: \"BS-PL Bridge\",\n description:\n \"貸借対照表の青色申告特別控除前の所得金額と損益計算書の所得金額の一致を検証する\",\n severity: \"error\",\n applicableTo: [\"sole-proprietor\"],\n },\n\n check(ctx: RuleContext): RuleDiagnostic[] {\n if (ctx.taxReturn.returnType !== \"sole-proprietor\") return [];\n const bsRetained = ctx.taxReturn.balanceSheet.retainedEarnings;\n const plOperating = ctx.taxReturn.incomeStatement.operatingIncome;\n\n if (bsRetained !== plOperating) {\n return [\n {\n ruleId: \"cross-statement/bs-pl-bridge\",\n severity: \"error\",\n message: `損益計算書の所得金額(${formatYen(plOperating)}) ≠ 貸借対照表の青色申告特別控除前の所得金額(${formatYen(bsRetained as Yen)})`,\n expected: `両方とも同一の値であるべき: ${formatYen(plOperating)}`,\n },\n ];\n }\n\n return [];\n },\n};\n","import type { Rule, RuleContext, RuleDiagnostic } from \"../types.js\";\nimport { formatYen } from \"../../utils/monetary.js\";\n\n/**\n * balance-sheet/opening-owner-equity\n * 事業主貸・事業主借は期首残高が0であるべき(前期末で精算される)\n */\nexport const openingOwnerEquityRule: Rule = {\n meta: {\n id: \"balance-sheet/opening-owner-equity\",\n name: \"事業主貸借 期首残高ゼロ\",\n description:\n \"事業主貸と事業主借は毎期首に元入金へ振替されるため、期首残高は0円であるべきです。\",\n severity: \"error\",\n applicableTo: [\"sole-proprietor\"],\n },\n\n check(ctx: RuleContext): RuleDiagnostic[] {\n if (ctx.taxReturn.returnType !== \"sole-proprietor\") return [];\n const diagnostics: RuleDiagnostic[] = [];\n const bs = ctx.taxReturn.balanceSheet;\n\n if (bs.ownerDrawings.opening !== 0) {\n diagnostics.push({\n ruleId: this.meta.id,\n severity: this.meta.severity,\n message: `事業主貸の期首残高が0ではありません: ${formatYen(bs.ownerDrawings.opening)}`,\n expected: \"事業主貸の期首残高 = ¥0\",\n });\n }\n\n if (bs.ownerContributions.opening !== 0) {\n diagnostics.push({\n ruleId: this.meta.id,\n severity: this.meta.severity,\n message: `事業主借の期首残高が0ではありません: ${formatYen(bs.ownerContributions.opening)}`,\n expected: \"事業主借の期首残高 = ¥0\",\n });\n }\n\n return diagnostics;\n },\n};\n","import type { Rule, RuleContext, RuleDiagnostic } from \"../types.js\";\nimport { formatYen } from \"../../utils/monetary.js\";\nimport { yen } from \"../../models/types.js\";\n\n/**\n * balance-sheet/motoire-kin-formula\n * 元入金繰越計算: 元入金(当期首) = 元入金(前期首) + 所得(前期) + 事業主借(前期末) - 事業主貸(前期末)\n */\nexport const motoireKinFormulaRule: Rule = {\n meta: {\n id: \"balance-sheet/motoire-kin-formula\",\n name: \"元入金繰越計算\",\n description:\n \"元入金(当期) = 元入金(前期) + 青色申告特別控除前所得(前期) + 事業主借(前期末) - 事業主貸(前期末) であるべきです。前年データが必要です。\",\n severity: \"error\",\n applicableTo: [\"sole-proprietor\"],\n },\n\n check(ctx: RuleContext): RuleDiagnostic[] {\n if (ctx.taxReturn.returnType !== \"sole-proprietor\") return [];\n if (!ctx.priorYear || ctx.priorYear.returnType !== \"sole-proprietor\")\n return [];\n\n const priorBs = ctx.priorYear.balanceSheet;\n const currentBs = ctx.taxReturn.balanceSheet;\n\n const expected = yen(\n priorBs.ownerEquity.opening +\n priorBs.retainedEarnings +\n priorBs.ownerContributions.closing -\n priorBs.ownerDrawings.closing,\n );\n\n const actual = currentBs.ownerEquity.opening;\n\n if (actual !== expected) {\n return [\n {\n ruleId: this.meta.id,\n severity: this.meta.severity,\n message: `元入金の期首残高(${formatYen(actual)}) ≠ 繰越計算額(${formatYen(expected)})`,\n details: `計算式: 元入金(前期首)(${formatYen(priorBs.ownerEquity.opening)}) + 所得(前期)(${formatYen(priorBs.retainedEarnings)}) + 事業主借(前期末)(${formatYen(priorBs.ownerContributions.closing)}) - 事業主貸(前期末)(${formatYen(priorBs.ownerDrawings.closing)})`,\n expected: `元入金の期首残高 = ${formatYen(expected)}`,\n },\n ];\n }\n\n return [];\n },\n};\n","import type { Rule, RuleContext, RuleDiagnostic } from \"../types.js\";\nimport { formatYen } from \"../../utils/monetary.js\";\n\n/**\n * balance-sheet/non-negative-cash\n * 現金残高が負でないかチェック\n */\nexport const nonNegativeCashRule: Rule = {\n meta: {\n id: \"balance-sheet/non-negative-cash\",\n name: \"現金残高の非負チェック\",\n description:\n \"現金残高は0以上であるべきです。マイナス残高は記帳ミスの可能性があります。\",\n severity: \"warning\",\n applicableTo: [\"sole-proprietor\", \"corporate\"],\n },\n\n check(ctx: RuleContext): RuleDiagnostic[] {\n if (ctx.taxReturn.returnType === \"individual\") return [];\n const diagnostics: RuleDiagnostic[] = [];\n const bs = ctx.taxReturn.balanceSheet;\n\n if (bs.cash.opening < 0) {\n diagnostics.push({\n ruleId: this.meta.id,\n severity: this.meta.severity,\n message: `現金の期首残高がマイナスです: ${formatYen(bs.cash.opening)}`,\n });\n }\n\n if (bs.cash.closing < 0) {\n diagnostics.push({\n ruleId: this.meta.id,\n severity: this.meta.severity,\n message: `現金の期末残高がマイナスです: ${formatYen(bs.cash.closing)}`,\n });\n }\n\n return diagnostics;\n },\n};\n","import type { Rule, RuleContext, RuleDiagnostic } from \"../types.js\";\nimport { formatYen } from \"../../utils/monetary.js\";\n\n/**\n * deductions/blue-deduction-cap\n * 青色申告特別控除額が控除前所得を超えていないかチェック\n */\nexport const blueDeductionCapRule: Rule = {\n meta: {\n id: \"deductions/blue-deduction-cap\",\n name: \"青色控除上限チェック\",\n description:\n \"青色申告特別控除額は、控除前の所得金額を超えることはできません。所得を超える場合は所得金額が上限となります。\",\n severity: \"warning\",\n applicableTo: [\"sole-proprietor\"],\n },\n\n check(ctx: RuleContext): RuleDiagnostic[] {\n if (ctx.taxReturn.returnType !== \"sole-proprietor\") return [];\n const deduction = ctx.taxReturn.taxFormA.blueReturnDeduction;\n const income = ctx.taxReturn.incomeStatement.operatingIncome;\n\n if (deduction > income) {\n return [\n {\n ruleId: this.meta.id,\n severity: this.meta.severity,\n message: `青色申告特別控除額(${formatYen(deduction)}) > 控除前所得(${formatYen(income)})`,\n details:\n \"青色申告特別控除額は控除前所得金額が上限です。所得が少ない場合は所得金額までしか控除できません。\",\n expected: `青色申告特別控除額 ≤ ${formatYen(income)}`,\n },\n ];\n }\n\n return [];\n },\n};\n","import type { Rule, RuleContext, RuleDiagnostic } from \"../types.js\";\nimport { yen } from \"../../models/types.js\";\nimport { formatYen } from \"../../utils/monetary.js\";\n\n/**\n * deductions/blue-deduction-eligibility\n * 65万円(55万円)控除の適用要件チェック\n */\nexport const blueDeductionEligibilityRule: Rule = {\n meta: {\n id: \"deductions/blue-deduction-eligibility\",\n name: \"青色控除65万円適用要件\",\n description:\n \"65万円の青色申告特別控除にはe-Taxによる申告または電子帳簿保存が必要です(令和2年分以降)。要件を満たさない場合は55万円が上限です。\",\n severity: \"info\",\n applicableTo: [\"sole-proprietor\"],\n },\n\n check(ctx: RuleContext): RuleDiagnostic[] {\n if (ctx.taxReturn.returnType !== \"sole-proprietor\") return [];\n const deduction = ctx.taxReturn.taxFormA.blueReturnDeduction;\n const limit55 = yen(550000);\n const limit65 = yen(650000);\n\n if (deduction > limit55 && deduction <= limit65) {\n return [\n {\n ruleId: this.meta.id,\n severity: this.meta.severity,\n message: `青色申告特別控除額が${formatYen(limit65)}です。e-Tax申告または電子帳簿保存の要件を確認してください。`,\n details:\n \"令和2年分以降、65万円控除にはe-Taxによる確定申告の送信、または電子帳簿保存法に基づく電子帳簿の備付けおよび保存が必要です。要件を満たさない場合は55万円が上限となります。\",\n },\n ];\n }\n\n return [];\n },\n};\n","import type { Rule, RuleContext, RuleDiagnostic } from \"../types.js\";\n\n/** Common useful life expectations (simplified lookup) */\nconst COMMON_USEFUL_LIVES: Record<string, number[]> = {\n パソコン: [4],\n サーバー: [5],\n 普通自動車: [6],\n 軽自動車: [4],\n 木造建物: [22],\n 鉄筋コンクリート建物: [47],\n 金属製家具: [15],\n};\n\n/**\n * depreciation/useful-life-rates\n * 耐用年数が法定テーブルと一致するかチェック\n */\nexport const usefulLifeRatesRule: Rule = {\n meta: {\n id: \"depreciation/useful-life-rates\",\n name: \"法定耐用年数チェック\",\n description:\n \"減価償却資産の耐用年数が法定耐用年数テーブルと一致するか確認します。\",\n severity: \"warning\",\n applicableTo: [\"sole-proprietor\", \"corporate\"],\n },\n\n check(ctx: RuleContext): RuleDiagnostic[] {\n if (ctx.taxReturn.returnType === \"individual\") return [];\n const diagnostics: RuleDiagnostic[] = [];\n const assets = ctx.taxReturn.depreciationSchedule.assets;\n\n for (const asset of assets) {\n for (const [keyword, validLives] of Object.entries(COMMON_USEFUL_LIVES)) {\n if (\n asset.name.includes(keyword) &&\n !validLives.includes(asset.usefulLife)\n ) {\n diagnostics.push({\n ruleId: this.meta.id,\n severity: this.meta.severity,\n message: `「${asset.name}」の耐用年数(${asset.usefulLife}年)が法定耐用年数(${validLives.join(\"/\")}年)と異なります`,\n });\n }\n }\n }\n\n return diagnostics;\n },\n};\n","import type { Rule, RuleContext, RuleDiagnostic } from \"../types.js\";\nimport { formatYen } from \"../../utils/monetary.js\";\nimport { yen } from \"../../models/types.js\";\n\n/**\n * depreciation/small-asset-threshold\n * 少額減価償却資産の閾値チェック\n */\nexport const smallAssetThresholdRule: Rule = {\n meta: {\n id: \"depreciation/small-asset-threshold\",\n name: \"少額資産の償却方法チェック\",\n description:\n \"取得価額10万円以下は全額経費、10万円超30万円以下は少額減価償却資産の特例(青色申告者)が適用可能です。\",\n severity: \"warning\",\n applicableTo: [\"sole-proprietor\", \"corporate\"],\n },\n\n check(ctx: RuleContext): RuleDiagnostic[] {\n if (ctx.taxReturn.returnType === \"individual\") return [];\n const diagnostics: RuleDiagnostic[] = [];\n const assets = ctx.taxReturn.depreciationSchedule.assets;\n const threshold10 = yen(100000);\n const threshold30 = yen(300000);\n\n for (const asset of assets) {\n if (asset.acquisitionCost <= threshold10 && asset.usefulLife > 1) {\n diagnostics.push({\n ruleId: this.meta.id,\n severity: this.meta.severity,\n message: `「${asset.name}」(取得価額${formatYen(asset.acquisitionCost)})は10万円以下のため、全額経費計上が可能です`,\n });\n }\n\n if (\n asset.acquisitionCost > threshold10 &&\n asset.acquisitionCost <= threshold30 &&\n asset.depreciationMethod !== \"一括償却\"\n ) {\n diagnostics.push({\n ruleId: this.meta.id,\n severity: this.meta.severity,\n message: `「${asset.name}」(取得価額${formatYen(asset.acquisitionCost)})は30万円以下のため、少額減価償却資産の特例(一括経費計上)が適用可能です`,\n details:\n \"青色申告者は取得価額30万円未満の減価償却資産について、年間合計300万円まで全額経費に計上できます。\",\n });\n }\n }\n\n return diagnostics;\n },\n};\n","import type { Rule, RuleContext, RuleDiagnostic } from \"../types.js\";\nimport { formatYen } from \"../../utils/monetary.js\";\nimport { yen } from \"../../models/types.js\";\n\n/**\n * cross-statement/decision-to-return\n * 決算書の所得金額が申告書第一表に正しく転記されているかチェック\n */\nexport const decisionToReturnRule: Rule = {\n meta: {\n id: \"cross-statement/decision-to-return\",\n name: \"決算書→申告書 転記一致\",\n description:\n \"青色申告決算書の売上金額・所得金額が申告書第一表に正しく転記されているか確認します。\",\n severity: \"error\",\n applicableTo: [\"sole-proprietor\"],\n },\n\n check(ctx: RuleContext): RuleDiagnostic[] {\n if (ctx.taxReturn.returnType !== \"sole-proprietor\") return [];\n const diagnostics: RuleDiagnostic[] = [];\n const pl = ctx.taxReturn.incomeStatement;\n const form = ctx.taxReturn.taxFormA;\n\n // 売上(収入)金額の転記チェック\n if (pl.revenue !== form.businessIncome) {\n diagnostics.push({\n ruleId: this.meta.id,\n severity: this.meta.severity,\n message: `決算書の売上金額(${formatYen(pl.revenue)}) ≠ 申告書の営業等収入(${formatYen(form.businessIncome)})`,\n expected: `申告書の営業等収入 = ${formatYen(pl.revenue)}`,\n });\n }\n\n // 所得金額の転記チェック(青色控除前)\n // 申告書の営業等所得 = 決算書の所得 - 青色申告特別控除\n const expectedProfit = yen(pl.operatingIncome - form.blueReturnDeduction);\n if (form.businessProfit !== expectedProfit) {\n diagnostics.push({\n ruleId: this.meta.id,\n severity: this.meta.severity,\n message: `申告書の営業等所得(${formatYen(form.businessProfit)}) ≠ 決算書所得(${formatYen(pl.operatingIncome)}) - 青色控除(${formatYen(form.blueReturnDeduction)})`,\n expected: `申告書の営業等所得 = ${formatYen(expectedProfit)}`,\n });\n }\n\n return diagnostics;\n },\n};\n","import type { Rule, RuleContext, RuleDiagnostic } from \"../types.js\";\nimport { formatYen } from \"../../utils/monetary.js\";\n\n/**\n * cross-statement/depreciation-sum\n * 減価償却費の計上額が損益計算書と一致するかチェック\n */\nexport const depreciationSumRule: Rule = {\n meta: {\n id: \"cross-statement/depreciation-sum\",\n name: \"減価償却費合計の一致\",\n description:\n \"減価償却明細の必要経費算入額合計が損益計算書の減価償却費と一致するか確認します。\",\n severity: \"error\",\n applicableTo: [\"sole-proprietor\"],\n },\n\n check(ctx: RuleContext): RuleDiagnostic[] {\n if (ctx.taxReturn.returnType !== \"sole-proprietor\") return [];\n const scheduleTotal =\n ctx.taxReturn.depreciationSchedule.totalBusinessDepreciation;\n const plDepreciation = ctx.taxReturn.incomeStatement.expenses.depreciation;\n\n // Skip if both are zero (no depreciation)\n if (scheduleTotal === 0 && plDepreciation === 0) return [];\n\n if (scheduleTotal !== plDepreciation) {\n return [\n {\n ruleId: this.meta.id,\n severity: this.meta.severity,\n message: `減価償却明細の合計(${formatYen(scheduleTotal)}) ≠ P/L減価償却費(${formatYen(plDepreciation)})`,\n expected: `両方とも同一の値であるべき: ${formatYen(scheduleTotal)}`,\n },\n ];\n }\n\n return [];\n },\n};\n","import type { Rule, RuleContext, RuleDiagnostic } from \"../types.js\";\nimport type { AccountBalance } from \"../../models/types.js\";\nimport { formatYen } from \"../../utils/monetary.js\";\n\nconst COMMON_ACCOUNT_NAMES: Record<string, string> = {\n cash: \"現金\",\n deposits: \"預金\",\n accountsReceivable: \"売掛金\",\n inventory: \"棚卸資産\",\n buildings: \"建物\",\n vehicles: \"車両運搬具\",\n tools: \"工具器具備品\",\n land: \"土地\",\n accountsPayable: \"買掛金\",\n borrowings: \"借入金\",\n};\n\n/**\n * continuity/opening-closing-match\n * 当期の期首残高が前期の期末残高と一致するかチェック\n */\nexport const openingClosingMatchRule: Rule = {\n meta: {\n id: \"continuity/opening-closing-match\",\n name: \"期首=前期末 一致チェック\",\n description:\n \"当期の期首残高が前期の期末残高と一致するか確認します。前年データが必要です。\",\n severity: \"error\",\n applicableTo: [\"sole-proprietor\", \"corporate\"],\n },\n\n check(ctx: RuleContext): RuleDiagnostic[] {\n if (!ctx.priorYear) return [];\n if (ctx.taxReturn.returnType === \"individual\") return [];\n if (ctx.priorYear.returnType === \"individual\") return [];\n\n const diagnostics: RuleDiagnostic[] = [];\n const currentBs = ctx.taxReturn.balanceSheet;\n const priorBs = ctx.priorYear.balanceSheet;\n\n // Common accounts (both sole-proprietor and corporate)\n for (const [key, label] of Object.entries(COMMON_ACCOUNT_NAMES)) {\n const current = currentBs[key as keyof typeof currentBs] as\n | AccountBalance\n | undefined;\n const prior = priorBs[key as keyof typeof priorBs] as\n | AccountBalance\n | undefined;\n\n if (\n current &&\n prior &&\n typeof current === \"object\" &&\n \"opening\" in current &&\n \"closing\" in prior &&\n current.opening !== prior.closing\n ) {\n diagnostics.push({\n ruleId: this.meta.id,\n severity: this.meta.severity,\n message: `${label}: 当期首(${formatYen(current.opening)}) ≠ 前期末(${formatYen(prior.closing)})`,\n expected: `${label}の期首残高 = ${formatYen(prior.closing)}`,\n });\n }\n }\n\n // Sole-proprietor-specific: 元入金\n if (\n ctx.taxReturn.returnType === \"sole-proprietor\" &&\n ctx.priorYear.returnType === \"sole-proprietor\"\n ) {\n const curBs = ctx.taxReturn.balanceSheet;\n const priBs = ctx.priorYear.balanceSheet;\n if (curBs.ownerEquity.opening !== priBs.ownerEquity.closing) {\n diagnostics.push({\n ruleId: this.meta.id,\n severity: this.meta.severity,\n message: `元入金: 当期首(${formatYen(curBs.ownerEquity.opening)}) ≠ 前期末(${formatYen(priBs.ownerEquity.closing)})`,\n expected: `元入金の期首残高 = ${formatYen(priBs.ownerEquity.closing)}`,\n });\n }\n }\n\n // Corporate-specific: 資本金, 資本剰余金, 利益剰余金\n if (\n ctx.taxReturn.returnType === \"corporate\" &&\n ctx.priorYear.returnType === \"corporate\"\n ) {\n const curBs = ctx.taxReturn.balanceSheet;\n const priBs = ctx.priorYear.balanceSheet;\n const corpAccounts: [AccountBalance, AccountBalance, string][] = [\n [curBs.capitalStock, priBs.capitalStock, \"資本金\"],\n [curBs.capitalSurplus, priBs.capitalSurplus, \"資本剰余金\"],\n [curBs.retainedEarnings, priBs.retainedEarnings, \"利益剰余金\"],\n ];\n for (const [current, prior, label] of corpAccounts) {\n if (current.opening !== prior.closing) {\n diagnostics.push({\n ruleId: this.meta.id,\n severity: this.meta.severity,\n message: `${label}: 当期首(${formatYen(current.opening)}) ≠ 前期末(${formatYen(prior.closing)})`,\n expected: `${label}の期首残高 = ${formatYen(prior.closing)}`,\n });\n }\n }\n }\n\n return diagnostics;\n },\n};\n","import type { Rule, RuleContext, RuleDiagnostic } from \"../types.js\";\nimport type { Yen } from \"../../models/types.js\";\nimport { formatYen } from \"../../utils/monetary.js\";\n\nconst FIELDS_TO_CHECK: { key: string; label: string }[] = [\n { key: \"revenue\", label: \"売上\" },\n { key: \"totalExpenses\", label: \"経費合計\" },\n { key: \"operatingIncome\", label: \"所得金額\" },\n];\n\n/**\n * continuity/year-over-year-change\n * 前年比で大幅な変動がある場合に警告\n */\nexport const yearOverYearChangeRule: Rule = {\n meta: {\n id: \"continuity/year-over-year-change\",\n name: \"前年比変動チェック\",\n description:\n \"売上・経費・所得が前年比で200%超の増加または80%超の減少がある場合に警告します。前年データが必要です。\",\n severity: \"warning\",\n applicableTo: [\"sole-proprietor\", \"corporate\"],\n },\n\n check(ctx: RuleContext): RuleDiagnostic[] {\n if (!ctx.priorYear) return [];\n if (ctx.taxReturn.returnType === \"individual\") return [];\n if (ctx.priorYear.returnType === \"individual\") return [];\n\n const diagnostics: RuleDiagnostic[] = [];\n const currentPl = ctx.taxReturn.incomeStatement;\n const priorPl = ctx.priorYear.incomeStatement;\n\n for (const { key, label } of FIELDS_TO_CHECK) {\n const current = currentPl[key as keyof typeof currentPl] as Yen;\n const prior = priorPl[key as keyof typeof priorPl] as Yen;\n\n if (prior === 0) continue;\n\n const ratio = current / prior;\n\n if (ratio > 3.0) {\n diagnostics.push({\n ruleId: this.meta.id,\n severity: this.meta.severity,\n message: `${label}が前年比${Math.round(ratio * 100)}%です(${formatYen(prior)} → ${formatYen(current)})`,\n details:\n \"200%を超える大幅な増加があります。記帳内容をご確認ください。\",\n });\n } else if (ratio < 0.2) {\n diagnostics.push({\n ruleId: this.meta.id,\n severity: this.meta.severity,\n message: `${label}が前年比${Math.round(ratio * 100)}%です(${formatYen(prior)} → ${formatYen(current)})`,\n details:\n \"80%を超える大幅な減少があります。記帳内容をご確認ください。\",\n });\n }\n }\n\n return diagnostics;\n },\n};\n","import type { Rule, RuleContext, RuleDiagnostic } from \"../types.js\";\n\nconst DEFAULT_MAX_RATIO = 0.9;\n\n/**\n * home-office/reasonable-ratio\n * 家事按分率の妥当性チェック\n */\nexport const reasonableRatioRule: Rule = {\n meta: {\n id: \"home-office/reasonable-ratio\",\n name: \"家事按分率の妥当性\",\n description:\n \"減価償却資産の事業専用割合(家事按分率)が妥当な範囲内かチェックします。デフォルトの上限は90%です。\",\n severity: \"warning\",\n applicableTo: [\"sole-proprietor\"],\n },\n\n check(ctx: RuleContext): RuleDiagnostic[] {\n if (ctx.taxReturn.returnType !== \"sole-proprietor\") return [];\n const diagnostics: RuleDiagnostic[] = [];\n const assets = ctx.taxReturn.depreciationSchedule.assets;\n\n const ruleConfig = ctx.config.rules[this.meta.id];\n let maxRatio = DEFAULT_MAX_RATIO;\n if (\n Array.isArray(ruleConfig) &&\n typeof ruleConfig[1]?.maxRatio === \"number\"\n ) {\n maxRatio = ruleConfig[1].maxRatio;\n }\n\n for (const asset of assets) {\n if (asset.businessUseRatio > maxRatio) {\n diagnostics.push({\n ruleId: this.meta.id,\n severity: this.meta.severity,\n message: `「${asset.name}」の事業専用割合(${Math.round(asset.businessUseRatio * 100)}%)が上限(${Math.round(maxRatio * 100)}%)を超えています`,\n details:\n \"家事按分率が高すぎる場合、税務調査で否認される可能性があります。実態に即した割合を設定してください。\",\n });\n }\n }\n\n return diagnostics;\n },\n};\n","import { formatYen } from \"../../utils/monetary.js\";\nimport { yen } from \"../../models/types.js\";\nimport type { Rule, RuleContext, RuleDiagnostic } from \"../types.js\";\n\n/**\n * corporate/bs-equation\n * 法人B/S: 資産合計 = 負債合計 + 純資産合計\n */\nexport const corporateBsEquationRule: Rule = {\n meta: {\n id: \"corporate/bs-equation\",\n name: \"法人B/S等式\",\n description: \"資産合計 = 負債合計 + 純資産合計 を検証する\",\n severity: \"error\",\n applicableTo: [\"corporate\"],\n },\n\n check(ctx: RuleContext): RuleDiagnostic[] {\n if (ctx.taxReturn.returnType !== \"corporate\") return [];\n const bs = ctx.taxReturn.balanceSheet;\n const diagnostics: RuleDiagnostic[] = [];\n\n const closingAssets = bs.assetsTotal.closing;\n const closingLiabilities = bs.liabilitiesTotal.closing;\n const closingEquity = bs.equityTotal.closing;\n\n if (closingAssets !== closingLiabilities + closingEquity) {\n diagnostics.push({\n ruleId: this.meta.id,\n severity: this.meta.severity,\n message: `期末残高: 資産合計(${formatYen(closingAssets)}) ≠ 負債合計(${formatYen(closingLiabilities)}) + 純資産合計(${formatYen(closingEquity)})`,\n expected: `資産合計 = ${formatYen(yen(closingLiabilities + closingEquity))}`,\n });\n }\n\n const openingAssets = bs.assetsTotal.opening;\n const openingLiabilities = bs.liabilitiesTotal.opening;\n const openingEquity = bs.equityTotal.opening;\n\n if (openingAssets !== openingLiabilities + openingEquity) {\n diagnostics.push({\n ruleId: this.meta.id,\n severity: this.meta.severity,\n message: `期首残高: 資産合計(${formatYen(openingAssets)}) ≠ 負債合計(${formatYen(openingLiabilities)}) + 純資産合計(${formatYen(openingEquity)})`,\n expected: `資産合計 = ${formatYen(yen(openingLiabilities + openingEquity))}`,\n });\n }\n\n return diagnostics;\n },\n};\n","import { formatYen } from \"../../utils/monetary.js\";\nimport type { Yen } from \"../../models/types.js\";\nimport type { Rule, RuleContext, RuleDiagnostic } from \"../types.js\";\n\n/**\n * corporate/pl-chain\n * 法人P/L: 営業利益→経常利益→税引前当期純利益→当期純利益\n */\nexport const corporatePlChainRule: Rule = {\n meta: {\n id: \"corporate/pl-chain\",\n name: \"法人P/L計算連鎖\",\n description:\n \"営業利益 + 営業外収益 - 営業外費用 = 経常利益、経常利益 + 特別利益 - 特別損失 = 税引前当期純利益、税引前当期純利益 - 法人税等 = 当期純利益 を検証する\",\n severity: \"error\",\n applicableTo: [\"corporate\"],\n },\n\n check(ctx: RuleContext): RuleDiagnostic[] {\n if (ctx.taxReturn.returnType !== \"corporate\") return [];\n const pl = ctx.taxReturn.incomeStatement;\n const diagnostics: RuleDiagnostic[] = [];\n\n // grossProfit = revenue - cogs\n const expectedGross = (pl.revenue - pl.cogs.total) as Yen;\n if (pl.grossProfit !== expectedGross) {\n diagnostics.push({\n ruleId: this.meta.id,\n severity: this.meta.severity,\n message: `売上総利益(${formatYen(pl.grossProfit)}) ≠ 売上高(${formatYen(pl.revenue)}) - 売上原価(${formatYen(pl.cogs.total)})`,\n expected: `売上総利益 = ${formatYen(expectedGross)}`,\n });\n }\n\n // operatingIncome = grossProfit - totalExpenses\n const expectedOperating = (pl.grossProfit - pl.totalExpenses) as Yen;\n if (pl.operatingIncome !== expectedOperating) {\n diagnostics.push({\n ruleId: this.meta.id,\n severity: this.meta.severity,\n message: `営業利益(${formatYen(pl.operatingIncome)}) ≠ 売上総利益(${formatYen(pl.grossProfit)}) - 販管費(${formatYen(pl.totalExpenses)})`,\n expected: `営業利益 = ${formatYen(expectedOperating)}`,\n });\n }\n\n // ordinaryIncome = operatingIncome + nonOperatingIncome - nonOperatingExpenses\n const expectedOrdinary = (pl.operatingIncome + pl.nonOperatingIncome - pl.nonOperatingExpenses) as Yen;\n if (pl.ordinaryIncome !== expectedOrdinary) {\n diagnostics.push({\n ruleId: this.meta.id,\n severity: this.meta.severity,\n message: `経常利益(${formatYen(pl.ordinaryIncome)}) ≠ 営業利益(${formatYen(pl.operatingIncome)}) + 営業外収益(${formatYen(pl.nonOperatingIncome)}) - 営業外費用(${formatYen(pl.nonOperatingExpenses)})`,\n expected: `経常利益 = ${formatYen(expectedOrdinary)}`,\n });\n }\n\n // preTaxIncome = ordinaryIncome + extraordinaryGain - extraordinaryLoss\n const expectedPreTax = (pl.ordinaryIncome + pl.extraordinaryGain - pl.extraordinaryLoss) as Yen;\n if (pl.preTaxIncome !== expectedPreTax) {\n diagnostics.push({\n ruleId: this.meta.id,\n severity: this.meta.severity,\n message: `税引前当期純利益(${formatYen(pl.preTaxIncome)}) ≠ 経常利益(${formatYen(pl.ordinaryIncome)}) + 特別利益(${formatYen(pl.extraordinaryGain)}) - 特別損失(${formatYen(pl.extraordinaryLoss)})`,\n expected: `税引前当期純利益 = ${formatYen(expectedPreTax)}`,\n });\n }\n\n // netIncome = preTaxIncome - corporateTax\n const expectedNet = (pl.preTaxIncome - pl.corporateTax) as Yen;\n if (pl.netIncome !== expectedNet) {\n diagnostics.push({\n ruleId: this.meta.id,\n severity: this.meta.severity,\n message: `当期純利益(${formatYen(pl.netIncome)}) ≠ 税引前当期純利益(${formatYen(pl.preTaxIncome)}) - 法人税等(${formatYen(pl.corporateTax)})`,\n expected: `当期純利益 = ${formatYen(expectedNet)}`,\n });\n }\n\n return diagnostics;\n },\n};\n","import { formatYen } from \"../../utils/monetary.js\";\nimport type { Yen } from \"../../models/types.js\";\nimport type { Rule, RuleContext, RuleDiagnostic } from \"../types.js\";\n\n/**\n * corporate/expense-total\n * 法人販管費の合計検証\n */\nexport const corporateExpenseTotalRule: Rule = {\n meta: {\n id: \"corporate/expense-total\",\n name: \"法人販管費合計チェック\",\n description: \"販売費及び一般管理費の合計が各費目の合計と一致するか検証する\",\n severity: \"error\",\n applicableTo: [\"corporate\"],\n },\n\n check(ctx: RuleContext): RuleDiagnostic[] {\n if (ctx.taxReturn.returnType !== \"corporate\") return [];\n const exp = ctx.taxReturn.incomeStatement.expenses;\n\n const computed = (\n exp.salaries +\n exp.outsourcing +\n exp.retirement +\n exp.rent +\n exp.interest +\n exp.taxes +\n exp.insurance +\n exp.repairs +\n exp.consumables +\n exp.depreciation +\n exp.welfare +\n exp.utilities +\n exp.travel +\n exp.communication +\n exp.advertising +\n exp.entertainment +\n exp.miscellaneous +\n exp.otherExpenses\n ) as Yen;\n\n const totalExpenses = ctx.taxReturn.incomeStatement.totalExpenses;\n\n if (totalExpenses !== computed) {\n return [\n {\n ruleId: this.meta.id,\n severity: this.meta.severity,\n message: `販管費合計(${formatYen(totalExpenses)}) ≠ 各費目の合計(${formatYen(computed)})`,\n expected: `販管費合計 = ${formatYen(computed)}`,\n },\n ];\n }\n\n return [];\n },\n};\n","import { formatYen } from \"../../utils/monetary.js\";\nimport type { Rule, RuleContext, RuleDiagnostic } from \"../types.js\";\n\n/**\n * corporate/bs-pl-bridge\n * B/S当期純利益 = P/L当期純利益\n */\nexport const corporateBsPlBridgeRule: Rule = {\n meta: {\n id: \"corporate/bs-pl-bridge\",\n name: \"法人B/S↔P/L整合性\",\n description:\n \"貸借対照表の当期純利益と損益計算書の当期純利益が一致するか検証する\",\n severity: \"error\",\n applicableTo: [\"corporate\"],\n },\n\n check(ctx: RuleContext): RuleDiagnostic[] {\n if (ctx.taxReturn.returnType !== \"corporate\") return [];\n const bsNetIncome = ctx.taxReturn.balanceSheet.netIncome;\n const plNetIncome = ctx.taxReturn.incomeStatement.netIncome;\n\n if (bsNetIncome !== plNetIncome) {\n return [\n {\n ruleId: this.meta.id,\n severity: this.meta.severity,\n message: `B/S当期純利益(${formatYen(bsNetIncome)}) ≠ P/L当期純利益(${formatYen(plNetIncome)})`,\n expected: `両方とも同一の値であるべき: ${formatYen(plNetIncome)}`,\n },\n ];\n }\n\n return [];\n },\n};\n","import { formatYen } from \"../../utils/monetary.js\";\nimport type { Rule, RuleContext, RuleDiagnostic } from \"../types.js\";\n\n/**\n * corporate/betsu4-accounting-profit\n * 別表四の当期利益 = P/L税引前当期純利益\n */\nexport const betsu4AccountingProfitRule: Rule = {\n meta: {\n id: \"corporate/betsu4-accounting-profit\",\n name: \"別表四↔P/L整合性\",\n description:\n \"別表四の当期利益又は当期欠損の額が損益計算書の税引前当期純利益と一致するか検証する\",\n severity: \"error\",\n applicableTo: [\"corporate\"],\n },\n\n check(ctx: RuleContext): RuleDiagnostic[] {\n if (ctx.taxReturn.returnType !== \"corporate\") return [];\n const scheduleProfit = ctx.taxReturn.incomeAdjustment.accountingProfit;\n const plPreTax = ctx.taxReturn.incomeStatement.preTaxIncome;\n\n if (scheduleProfit !== plPreTax) {\n return [\n {\n ruleId: this.meta.id,\n severity: this.meta.severity,\n message: `別表四の当期利益(${formatYen(scheduleProfit)}) ≠ P/L税引前当期純利益(${formatYen(plPreTax)})`,\n expected: `別表四の当期利益 = ${formatYen(plPreTax)}`,\n },\n ];\n }\n\n return [];\n },\n};\n","import { formatYen } from \"../../utils/monetary.js\";\nimport type { Yen } from \"../../models/types.js\";\nimport type { Rule, RuleContext, RuleDiagnostic } from \"../types.js\";\n\n/**\n * corporate/betsu4-taxable-income\n * 別表四: 当期利益 + 加算 - 減算 = 所得金額\n */\nexport const betsu4TaxableIncomeRule: Rule = {\n meta: {\n id: \"corporate/betsu4-taxable-income\",\n name: \"別表四所得金額計算\",\n description:\n \"別表四の所得金額 = 当期利益 + 加算項目合計 - 減算項目合計 を検証する\",\n severity: \"error\",\n applicableTo: [\"corporate\"],\n },\n\n check(ctx: RuleContext): RuleDiagnostic[] {\n if (ctx.taxReturn.returnType !== \"corporate\") return [];\n const adj = ctx.taxReturn.incomeAdjustment;\n\n const expected = (adj.accountingProfit + adj.addBackTotal - adj.deductionTotal) as Yen;\n\n if (adj.taxableIncome !== expected) {\n return [\n {\n ruleId: this.meta.id,\n severity: this.meta.severity,\n message: `別表四の所得金額(${formatYen(adj.taxableIncome)}) ≠ 当期利益(${formatYen(adj.accountingProfit)}) + 加算(${formatYen(adj.addBackTotal)}) - 減算(${formatYen(adj.deductionTotal)})`,\n expected: `所得金額 = ${formatYen(expected)}`,\n },\n ];\n }\n\n return [];\n },\n};\n","import { formatYen } from \"../../utils/monetary.js\";\nimport type { Rule, RuleContext, RuleDiagnostic } from \"../types.js\";\n\n/**\n * corporate/betsu1-match\n * 別表一の所得金額 = 別表四の所得金額\n */\nexport const betsu1MatchRule: Rule = {\n meta: {\n id: \"corporate/betsu1-match\",\n name: \"別表一↔別表四整合性\",\n description:\n \"別表一(法人税申告書)の所得金額が別表四の所得金額と一致するか検証する\",\n severity: \"error\",\n applicableTo: [\"corporate\"],\n },\n\n check(ctx: RuleContext): RuleDiagnostic[] {\n if (ctx.taxReturn.returnType !== \"corporate\") return [];\n const betsu1Income = ctx.taxReturn.corporateTaxForm.taxableIncome;\n const betsu4Income = ctx.taxReturn.incomeAdjustment.taxableIncome;\n\n if (betsu1Income !== betsu4Income) {\n return [\n {\n ruleId: this.meta.id,\n severity: this.meta.severity,\n message: `別表一の所得金額(${formatYen(betsu1Income)}) ≠ 別表四の所得金額(${formatYen(betsu4Income)})`,\n expected: `別表一の所得金額 = ${formatYen(betsu4Income)}`,\n },\n ];\n }\n\n return [];\n },\n};\n","import { formatYen } from \"../../utils/monetary.js\";\nimport { yen } from \"../../models/types.js\";\nimport type { Rule, RuleContext, RuleDiagnostic } from \"../types.js\";\n\nconst CAPITAL_LIMIT = yen(10_000_000);\n\n/**\n * corporate/capital-under-10m\n * 資本金が1000万円以下であることを確認(マイクロ法人前提)\n */\nexport const capitalUnder10mRule: Rule = {\n meta: {\n id: \"corporate/capital-under-10m\",\n name: \"資本金1000万以下チェック\",\n description:\n \"マイクロ法人として資本金が1,000万円以下であることを確認する。消費税の免税事業者要件にも関連します。\",\n severity: \"warning\",\n applicableTo: [\"corporate\"],\n },\n\n check(ctx: RuleContext): RuleDiagnostic[] {\n if (ctx.taxReturn.returnType !== \"corporate\") return [];\n const capital = ctx.taxReturn.corporateInfo.capitalAmount;\n\n if (capital > CAPITAL_LIMIT) {\n return [\n {\n ruleId: this.meta.id,\n severity: this.meta.severity,\n message: `資本金(${formatYen(capital)})が1,000万円を超えています`,\n details:\n \"資本金1,000万円超の場合、設立初年度から消費税の課税事業者となります。マイクロ法人では通常1,000万円以下に設定します。\",\n expected: `資本金 ≤ ${formatYen(CAPITAL_LIMIT)}`,\n },\n ];\n }\n\n return [];\n },\n};\n","import { formatYen } from \"../../utils/monetary.js\";\nimport { yen } from \"../../models/types.js\";\nimport type { Rule, RuleContext, RuleDiagnostic } from \"../types.js\";\n\n/**\n * corporate/officer-compensation\n * 役員報酬の妥当性チェック\n */\nexport const officerCompensationRule: Rule = {\n meta: {\n id: \"corporate/officer-compensation\",\n name: \"役員報酬妥当性チェック\",\n description:\n \"役員報酬(給料賃金)が売上に対して妥当な範囲内かチェックする。一人法人では給料賃金 = 役員報酬として検証する。\",\n severity: \"warning\",\n applicableTo: [\"corporate\"],\n },\n\n check(ctx: RuleContext): RuleDiagnostic[] {\n if (ctx.taxReturn.returnType !== \"corporate\") return [];\n const diagnostics: RuleDiagnostic[] = [];\n const pl = ctx.taxReturn.incomeStatement;\n const salaries = pl.expenses.salaries;\n\n // 役員報酬が0の場合はスキップ\n if (salaries === 0) return [];\n\n // 役員報酬が売上を超えている場合\n if (salaries > pl.revenue && pl.revenue > 0) {\n diagnostics.push({\n ruleId: this.meta.id,\n severity: this.meta.severity,\n message: `役員報酬(${formatYen(salaries)})が売上高(${formatYen(pl.revenue)})を超えています`,\n details:\n \"役員報酬が売上を超える状態が継続すると債務超過のリスクがあります。\",\n });\n }\n\n // 役員報酬が経常利益を大幅に超えて赤字になっている場合\n if (pl.ordinaryIncome < 0 && salaries > 0) {\n const incomeBeforeSalary = yen(pl.ordinaryIncome + salaries);\n if (incomeBeforeSalary > 0) {\n diagnostics.push({\n ruleId: this.meta.id,\n severity: this.meta.severity,\n message: `役員報酬控除前は黒字(${formatYen(incomeBeforeSalary)})ですが、役員報酬(${formatYen(salaries)})により経常赤字(${formatYen(pl.ordinaryIncome)})となっています`,\n details:\n \"役員報酬の金額が適正か見直しを検討してください。定期同額給与の要件にもご注意ください。\",\n });\n }\n }\n\n return diagnostics;\n },\n};\n","import { formatYen } from \"../../utils/monetary.js\";\nimport { yen } from \"../../models/types.js\";\nimport type { Yen } from \"../../models/types.js\";\nimport type { Rule, RuleContext, RuleDiagnostic } from \"../types.js\";\n\n/**\n * corporate/entertainment-limit\n * 交際費の損金算入限度額チェック(中小法人:年800万円)\n */\nexport const entertainmentLimitRule: Rule = {\n meta: {\n id: \"corporate/entertainment-limit\",\n name: \"交際費損金算入限度\",\n description:\n \"中小法人の交際費の損金算入限度額(年800万円)を超えていないかチェックする。事業年度が12ヶ月未満の場合は月割計算する。\",\n severity: \"warning\",\n applicableTo: [\"corporate\"],\n },\n\n check(ctx: RuleContext): RuleDiagnostic[] {\n if (ctx.taxReturn.returnType !== \"corporate\") return [];\n const entertainment = ctx.taxReturn.incomeStatement.expenses.entertainment;\n\n if (entertainment === 0) return [];\n\n const months = ctx.taxReturn.corporateInfo.fiscalYearMonths;\n const annualLimit = yen(8_000_000);\n const limit = yen(Math.trunc((annualLimit * months) / 12)) as Yen;\n\n if (entertainment > limit) {\n return [\n {\n ruleId: this.meta.id,\n severity: this.meta.severity,\n message: `交際費(${formatYen(entertainment)})が損金算入限度額(${formatYen(limit)})を超えています`,\n details:\n months < 12\n ? `事業年度${months}ヶ月のため、限度額は800万円×${months}/12で計算しています。超過分は損金不算入となります。`\n : \"中小法人の交際費の損金算入限度額は年800万円です。超過分は損金不算入となります。\",\n expected: `交際費 ≤ ${formatYen(limit)}`,\n },\n ];\n }\n\n return [];\n },\n};\n","import { formatYen } from \"../../utils/monetary.js\";\nimport { yen } from \"../../models/types.js\";\nimport type { Rule, RuleContext, RuleDiagnostic } from \"../types.js\";\n\nconst REDUCED_RATE_LIMIT = yen(8_000_000);\n\n/**\n * corporate/small-corp-tax-rate\n * 中小法人の軽減税率適用チェック\n */\nexport const smallCorpTaxRateRule: Rule = {\n meta: {\n id: \"corporate/small-corp-tax-rate\",\n name: \"軽減税率適用チェック\",\n description:\n \"中小法人の所得800万円以下の部分に軽減税率(15%)が適用可能か確認する。資本金1億円以下の法人が対象。\",\n severity: \"info\",\n applicableTo: [\"corporate\"],\n },\n\n check(ctx: RuleContext): RuleDiagnostic[] {\n if (ctx.taxReturn.returnType !== \"corporate\") return [];\n const info = ctx.taxReturn.corporateInfo;\n const taxableIncome = ctx.taxReturn.incomeAdjustment.taxableIncome;\n\n if (!info.isSmallCorp) return [];\n if (taxableIncome <= 0) return [];\n\n if (taxableIncome > REDUCED_RATE_LIMIT) {\n return [\n {\n ruleId: this.meta.id,\n severity: this.meta.severity,\n message: `所得金額(${formatYen(taxableIncome)})が800万円を超えています。800万円以下の部分に軽減税率15%、超過分に23.2%が適用されます。`,\n details: `軽減税率適用分: ${formatYen(REDUCED_RATE_LIMIT)}、通常税率適用分: ${formatYen(yen(taxableIncome - REDUCED_RATE_LIMIT))}`,\n },\n ];\n }\n\n return [];\n },\n};\n","import { formatYen } from \"../../utils/monetary.js\";\nimport { yen } from \"../../models/types.js\";\nimport type { Rule, RuleContext, RuleDiagnostic } from \"../types.js\";\n\n/**\n * corporate/retained-earnings-continuity\n * 利益剰余金の繰越: 期末利益剰余金 = 期首利益剰余金 + 当期純利益\n */\nexport const retainedEarningsContinuityRule: Rule = {\n meta: {\n id: \"corporate/retained-earnings-continuity\",\n name: \"利益剰余金繰越チェック\",\n description:\n \"利益剰余金の期末残高 = 期首残高 + 当期純利益 であることを検証する(配当なしを前提)\",\n severity: \"error\",\n applicableTo: [\"corporate\"],\n },\n\n check(ctx: RuleContext): RuleDiagnostic[] {\n if (ctx.taxReturn.returnType !== \"corporate\") return [];\n const bs = ctx.taxReturn.balanceSheet;\n\n const expected = yen(bs.retainedEarnings.opening + bs.netIncome);\n const actual = bs.retainedEarnings.closing;\n\n if (actual !== expected) {\n return [\n {\n ruleId: this.meta.id,\n severity: this.meta.severity,\n message: `利益剰余金の期末残高(${formatYen(actual)}) ≠ 期首残高(${formatYen(bs.retainedEarnings.opening)}) + 当期純利益(${formatYen(bs.netIncome)})`,\n details:\n \"配当や自己株式取得がある場合はその分を考慮してください。\",\n expected: `利益剰余金の期末残高 = ${formatYen(expected)}`,\n },\n ];\n }\n\n return [];\n },\n};\n","import type { Rule } from \"./types.js\";\n\n// Core rules\nimport { bsEquationRule } from \"./balance-sheet/bs-equation.js\";\nimport { plArithmeticChainRule } from \"./income-statement/pl-arithmetic-chain.js\";\nimport { cogsCalculationRule } from \"./income-statement/cogs-calculation.js\";\nimport { expenseTotalRule } from \"./income-statement/expense-total.js\";\nimport { bsPlBridgeRule } from \"./cross-statement/bs-pl-bridge.js\";\n\n// Balance sheet rules\nimport { openingOwnerEquityRule } from \"./balance-sheet/opening-owner-equity.js\";\nimport { motoireKinFormulaRule } from \"./balance-sheet/motoire-kin-formula.js\";\nimport { nonNegativeCashRule } from \"./balance-sheet/non-negative-cash.js\";\n\n// Deduction rules\nimport { blueDeductionCapRule } from \"./deductions/blue-deduction-cap.js\";\nimport { blueDeductionEligibilityRule } from \"./deductions/blue-deduction-eligibility.js\";\n\n// Depreciation rules\nimport { usefulLifeRatesRule } from \"./depreciation/useful-life-rates.js\";\nimport { smallAssetThresholdRule } from \"./depreciation/small-asset-threshold.js\";\n\n// Cross-statement rules\nimport { decisionToReturnRule } from \"./cross-statement/decision-to-return.js\";\nimport { depreciationSumRule } from \"./cross-statement/depreciation-sum.js\";\n\n// Continuity rules\nimport { openingClosingMatchRule } from \"./continuity/opening-closing-match.js\";\nimport { yearOverYearChangeRule } from \"./continuity/year-over-year-change.js\";\n\n// Home office rules\nimport { reasonableRatioRule } from \"./home-office/reasonable-ratio.js\";\n\n// Corporate rules\nimport {\n corporateBsEquationRule,\n corporatePlChainRule,\n corporateExpenseTotalRule,\n corporateBsPlBridgeRule,\n betsu4AccountingProfitRule,\n betsu4TaxableIncomeRule,\n betsu1MatchRule,\n capitalUnder10mRule,\n officerCompensationRule,\n entertainmentLimitRule,\n smallCorpTaxRateRule,\n retainedEarningsContinuityRule,\n} from \"./corporate/index.js\";\n\nconst ruleRegistry = new Map<string, Rule>();\n\nexport function registerRule(rule: Rule): void {\n ruleRegistry.set(rule.meta.id, rule);\n}\n\nexport function getAllRules(): Rule[] {\n return [...ruleRegistry.values()];\n}\n\nexport function getRule(id: string): Rule | undefined {\n return ruleRegistry.get(id);\n}\n\n// Register individual rules\nregisterRule(bsEquationRule);\nregisterRule(openingOwnerEquityRule);\nregisterRule(motoireKinFormulaRule);\nregisterRule(nonNegativeCashRule);\nregisterRule(plArithmeticChainRule);\nregisterRule(cogsCalculationRule);\nregisterRule(expenseTotalRule);\nregisterRule(bsPlBridgeRule);\nregisterRule(decisionToReturnRule);\nregisterRule(depreciationSumRule);\nregisterRule(blueDeductionCapRule);\nregisterRule(blueDeductionEligibilityRule);\nregisterRule(usefulLifeRatesRule);\nregisterRule(smallAssetThresholdRule);\nregisterRule(openingClosingMatchRule);\nregisterRule(yearOverYearChangeRule);\nregisterRule(reasonableRatioRule);\n\n// Register corporate rules\nregisterRule(corporateBsEquationRule);\nregisterRule(corporatePlChainRule);\nregisterRule(corporateExpenseTotalRule);\nregisterRule(corporateBsPlBridgeRule);\nregisterRule(betsu4AccountingProfitRule);\nregisterRule(betsu4TaxableIncomeRule);\nregisterRule(betsu1MatchRule);\nregisterRule(capitalUnder10mRule);\nregisterRule(officerCompensationRule);\nregisterRule(entertainmentLimitRule);\nregisterRule(smallCorpTaxRateRule);\nregisterRule(retainedEarningsContinuityRule);\n\nexport type { Rule, RuleContext, RuleConfig, ResolvedConfig, RuleDiagnostic, RuleMeta, Severity } from \"./types.js\";\nexport { runRules } from \"./rule-runner.js\";\n","import { readFile } from \"node:fs/promises\";\nimport { resolve } from \"node:path\";\nimport { ConfigError } from \"../utils/errors.js\";\nimport type { ResolvedConfig } from \"../rules/types.js\";\nimport { defaultConfig } from \"./defaults.js\";\nimport { configSchema } from \"./schema.js\";\n\nexport type { ZeicheckConfig } from \"./types.js\";\n\n/**\n * Load configuration from a file path, or use defaults.\n * Merges with defaults so partial configs are fine.\n */\nexport async function loadConfig(configPath?: string): Promise<ResolvedConfig> {\n if (!configPath) {\n // Try to find .zeicheckrc.json in cwd\n const defaultPath = resolve(process.cwd(), \".zeicheckrc.json\");\n try {\n return await readConfigFile(defaultPath);\n } catch {\n return defaultConfig;\n }\n }\n\n return readConfigFile(configPath);\n}\n\nasync function readConfigFile(filePath: string): Promise<ResolvedConfig> {\n let raw: string;\n try {\n raw = await readFile(filePath, \"utf-8\");\n } catch {\n throw new ConfigError(`設定ファイルが見つかりません: ${filePath}`, filePath);\n }\n\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw);\n } catch {\n throw new ConfigError(\n `設定ファイルのJSON解析に失敗しました: ${filePath}`,\n filePath,\n );\n }\n\n const result = configSchema.safeParse(parsed);\n if (!result.success) {\n const issues = result.error.issues\n .map((i) => ` ${i.path.join(\".\")}: ${i.message}`)\n .join(\"\\n\");\n throw new ConfigError(\n `設定ファイルのバリデーションに失敗しました:\\n${issues}`,\n filePath,\n );\n }\n\n return result.data;\n}\n","/**\n * Custom error classes for zeicheck.\n */\n\nexport class ParseError extends Error {\n constructor(message: string, public readonly filePath?: string) {\n super(message);\n this.name = \"ParseError\";\n }\n}\n\nexport class ConfigError extends Error {\n constructor(message: string, public readonly configPath?: string) {\n super(message);\n this.name = \"ConfigError\";\n }\n}\n","import type { ZeicheckConfig } from \"./types.js\";\n\nexport const defaultConfig: ZeicheckConfig = {\n rules: {},\n format: \"stylish\",\n warningsAsErrors: false,\n};\n","import { z } from \"zod\";\n\nconst severitySchema = z.enum([\"error\", \"warning\", \"info\", \"off\"]);\n\nconst ruleValueSchema = z.union([\n severitySchema,\n z.tuple([severitySchema, z.record(z.unknown())]),\n]);\n\nexport const configSchema = z.object({\n rules: z.record(ruleValueSchema).default({}),\n priorYearFile: z.string().optional(),\n format: z.enum([\"stylish\", \"json\"]).default(\"stylish\"),\n warningsAsErrors: z.boolean().default(false),\n});\n\nexport type ConfigInput = z.input<typeof configSchema>;\n","import pc from \"picocolors\";\nimport type { RuleDiagnostic, Severity } from \"../../rules/types.js\";\nimport type { FormatInput, FormatResult, Formatter } from \"./types.js\";\n\nfunction colorSeverity(severity: Severity): string {\n switch (severity) {\n case \"error\":\n return pc.red(severity);\n case \"warning\":\n return pc.yellow(severity);\n case \"info\":\n return pc.blue(severity);\n default:\n return severity;\n }\n}\n\nfunction padRight(str: string, len: number): string {\n return str + \" \".repeat(Math.max(0, len - str.length));\n}\n\nexport const stylishFormatter: Formatter = {\n format(input: FormatInput): FormatResult {\n const { filePath, diagnostics } = input;\n\n let errorCount = 0;\n let warningCount = 0;\n let infoCount = 0;\n\n for (const d of diagnostics) {\n if (d.severity === \"error\") errorCount++;\n else if (d.severity === \"warning\") warningCount++;\n else if (d.severity === \"info\") infoCount++;\n }\n\n if (diagnostics.length === 0) {\n return { output: \"\", errorCount: 0, warningCount: 0, infoCount: 0 };\n }\n\n const lines: string[] = [];\n lines.push(\"\");\n lines.push(pc.underline(filePath));\n lines.push(\"\");\n\n // Compute column widths\n const maxRuleIdLen = Math.max(\n ...diagnostics.map((d) => d.ruleId.length),\n );\n const maxSeverityLen = 7; // \"warning\" is the longest\n\n for (const diag of diagnostics) {\n const ruleId = padRight(diag.ruleId, maxRuleIdLen);\n const severity = padRight(diag.severity, maxSeverityLen);\n lines.push(\n ` ${ruleId} ${colorSeverity(diag.severity as Severity)}${\" \".repeat(maxSeverityLen - diag.severity.length)} ${diag.message}`,\n );\n if (diag.expected) {\n lines.push(\n ` ${\" \".repeat(maxRuleIdLen)} ${\" \".repeat(maxSeverityLen)} ${pc.green(`→ ${diag.expected}`)}`,\n );\n }\n }\n\n lines.push(\"\");\n\n const total = diagnostics.length;\n const summary = `${pc.bold(errorCount > 0 ? pc.red(`✖ ${total} 件の問題`) : `✖ ${total} 件の問題`)} (${errorCount} errors, ${warningCount} warnings)`;\n lines.push(summary);\n\n return {\n output: lines.join(\"\\n\"),\n errorCount,\n warningCount,\n infoCount,\n };\n },\n};\n","import type { FormatInput, FormatResult, Formatter } from \"./types.js\";\n\nexport const jsonFormatter: Formatter = {\n format(input: FormatInput): FormatResult {\n const { filePath, diagnostics } = input;\n\n let errorCount = 0;\n let warningCount = 0;\n let infoCount = 0;\n\n for (const d of diagnostics) {\n if (d.severity === \"error\") errorCount++;\n else if (d.severity === \"warning\") warningCount++;\n else if (d.severity === \"info\") infoCount++;\n }\n\n const output = JSON.stringify(\n {\n filePath,\n diagnostics,\n summary: {\n total: diagnostics.length,\n errors: errorCount,\n warnings: warningCount,\n info: infoCount,\n },\n },\n null,\n 2,\n );\n\n return { output, errorCount, warningCount, infoCount };\n },\n};\n","import type { Formatter } from \"./types.js\";\nimport { stylishFormatter } from \"./stylish.js\";\nimport { jsonFormatter } from \"./json.js\";\n\nexport type { Formatter, FormatInput, FormatResult } from \"./types.js\";\n\nexport function getFormatter(name: string): Formatter {\n switch (name) {\n case \"json\":\n return jsonFormatter;\n case \"stylish\":\n default:\n return stylishFormatter;\n }\n}\n"],"mappings":"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","names":["FormType","readFile","readFile"]}