@mudraforge/statutory 2.12.1 → 2.14.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.
Files changed (134) hide show
  1. package/CHANGELOG.md +32 -0
  2. package/README.md +19 -0
  3. package/okf/corporate_ma_restructuring/business_combinations_indas_103/ast.json +20 -0
  4. package/okf/corporate_ma_restructuring/impairment_of_assets_indas_36/ast.json +20 -0
  5. package/okf/corporate_ma_restructuring/loss_carryforward_sec79/ast.json +33 -0
  6. package/okf/corporate_ma_restructuring/share_based_payments_indas_102/ast.json +20 -0
  7. package/okf/corporate_ma_restructuring/slump_sale_50b/ast.json +21 -0
  8. package/okf/corporate_ma_restructuring/tax_clearance_sec281/ast.json +21 -0
  9. package/okf/direct_tax/corporate_tax_115baa_115jb/ast.json +23 -0
  10. package/okf/direct_tax/income_taxes_deferred_tax_indas_12/ast.json +20 -0
  11. package/okf/direct_tax/special_rates_non_filer_206ab/ast.json +26 -0
  12. package/okf/direct_tax/statutory_disallowance_43b/ast.json +35 -0
  13. package/okf/direct_tax/tcs_goods_206c_1h/ast.json +69 -0
  14. package/okf/direct_tax/tds_commission_194h/ast.json +60 -0
  15. package/okf/direct_tax/tds_contractor_194c/ast.json +71 -0
  16. package/okf/direct_tax/tds_ecommerce_194o/ast.json +48 -0
  17. package/okf/direct_tax/tds_goods_194q/ast.json +71 -0
  18. package/okf/direct_tax/tds_goods_393/ast.json +59 -0
  19. package/okf/direct_tax/tds_individual_contract_194m/ast.json +59 -0
  20. package/okf/direct_tax/tds_interest_194a/ast.json +59 -0
  21. package/okf/direct_tax/tds_perquisites_194r/ast.json +47 -0
  22. package/okf/direct_tax/tds_property_194ia/ast.json +70 -0
  23. package/okf/direct_tax/tds_rent_194i/ast.json +60 -0
  24. package/okf/direct_tax/tds_rent_individual_194ib/ast.json +59 -0
  25. package/okf/direct_tax/tds_services_194j/ast.json +60 -0
  26. package/okf/indirect_tax_gst/blocked_itc_17_5/ast.json +26 -0
  27. package/okf/indirect_tax_gst/common_itc_reversal_rule42_43/ast.json +26 -0
  28. package/okf/indirect_tax_gst/composite_mixed_supplies_sec8/ast.json +21 -0
  29. package/okf/indirect_tax_gst/composition_levy_sec10/ast.json +23 -0
  30. package/okf/indirect_tax_gst/credit_debit_notes_sec34/ast.json +21 -0
  31. package/okf/indirect_tax_gst/e_invoicing_rule48_4/ast.json +20 -0
  32. package/okf/indirect_tax_gst/export_services_lut_sec16/ast.json +20 -0
  33. package/okf/indirect_tax_gst/gst_tds_sec51/ast.json +23 -0
  34. package/okf/indirect_tax_gst/itc_eligibility_16_2/ast.json +20 -0
  35. package/okf/indirect_tax_gst/itc_reversal_rule37_37a/ast.json +45 -0
  36. package/okf/indirect_tax_gst/rcm_liability_sec9_3/ast.json +26 -0
  37. package/okf/international_tax/cross_border_remittance_195/ast.json +39 -0
  38. package/okf/international_tax/financial_instruments_ecl_indas_109/ast.json +24 -0
  39. package/okf/international_tax/foreign_exchange_indas_21_109/ast.json +20 -0
  40. package/okf/international_tax/foreign_tax_credit_irc_901_904/ast.json +20 -0
  41. package/okf/international_tax/transfer_pricing_alp_92c/ast.json +25 -0
  42. package/okf/manifest.json +49 -3
  43. package/okf/msme_commercial/delayed_payments_15_16/ast.json +38 -0
  44. package/okf/msme_commercial/enterprise_classification_sec7/ast.json +25 -0
  45. package/okf/msme_commercial/lease_accounting_indas_116/ast.json +20 -0
  46. package/okf/msme_commercial/mca_msme_1_filing/ast.json +20 -0
  47. package/okf/msme_commercial/provisions_contingencies_indas_37/ast.json +20 -0
  48. package/okf/msme_commercial/revenue_recognition_indas_115/ast.json +20 -0
  49. package/okf/msme_commercial/statutory_disclosures_sec22/ast.json +21 -0
  50. package/package.json +16 -4
  51. package/src/calculators.js +139 -3
  52. package/src/constants.js +1 -1
  53. package/src/index.js +16 -2
  54. package/src/payroll.js +506 -0
  55. package/src/usvm/evaluation_vm.js +504 -0
  56. package/src/usvm/index.js +65 -0
  57. package/src/usvm/math_rational.js +165 -0
  58. package/src/usvm/rules/sec_115baa_115jb_mat.json +23 -0
  59. package/src/usvm/rules/sec_192_salary_tds.json +23 -0
  60. package/src/usvm/rules/sec_194a_interest.json +59 -0
  61. package/src/usvm/rules/sec_194c_contractors.json +71 -0
  62. package/src/usvm/rules/sec_194h_commission.json +60 -0
  63. package/src/usvm/rules/sec_194i_rent.json +60 -0
  64. package/src/usvm/rules/sec_194ia_property.json +70 -0
  65. package/src/usvm/rules/sec_194ib_rent_ind.json +59 -0
  66. package/src/usvm/rules/sec_194j_services.json +60 -0
  67. package/src/usvm/rules/sec_194m_contract_ind.json +59 -0
  68. package/src/usvm/rules/sec_194o_ecommerce.json +48 -0
  69. package/src/usvm/rules/sec_194q_goods.json +71 -0
  70. package/src/usvm/rules/sec_194r_perquisites.json +47 -0
  71. package/src/usvm/rules/sec_195_cross_border.json +39 -0
  72. package/src/usvm/rules/sec_206ab_non_filer.json +26 -0
  73. package/src/usvm/rules/sec_206c1h_tcs.json +69 -0
  74. package/src/usvm/rules/sec_281_tax_clearance.json +21 -0
  75. package/src/usvm/rules/sec_393_goods.json +59 -0
  76. package/src/usvm/rules/sec_43bh_disallowance.json +35 -0
  77. package/src/usvm/rules/sec_50b_slump_sale.json +21 -0
  78. package/src/usvm/rules/sec_79_loss_continuity.json +33 -0
  79. package/src/usvm/rules/sec_92c_transfer_pricing.json +25 -0
  80. package/src/usvm/rules/sec_ftc_dtaa_relief.json +20 -0
  81. package/src/usvm/rules/sec_gst_blocked_itc_17_5.json +26 -0
  82. package/src/usvm/rules/sec_gst_composite_mixed_8.json +21 -0
  83. package/src/usvm/rules/sec_gst_composition_levy_10.json +23 -0
  84. package/src/usvm/rules/sec_gst_credit_debit_notes_34.json +21 -0
  85. package/src/usvm/rules/sec_gst_einvoicing_rule48_4.json +20 -0
  86. package/src/usvm/rules/sec_gst_ewaybill_rule138.json +21 -0
  87. package/src/usvm/rules/sec_gst_export_lut_16.json +20 -0
  88. package/src/usvm/rules/sec_gst_itc_eligibility_16_2.json +20 -0
  89. package/src/usvm/rules/sec_gst_itc_reversal_rule37_37a.json +45 -0
  90. package/src/usvm/rules/sec_gst_rcm_liability_9_3.json +26 -0
  91. package/src/usvm/rules/sec_gst_rule42_43_apportionment.json +26 -0
  92. package/src/usvm/rules/sec_gst_tds_sec51.json +23 -0
  93. package/src/usvm/rules/sec_indas102_esop.json +20 -0
  94. package/src/usvm/rules/sec_indas103_mna.json +20 -0
  95. package/src/usvm/rules/sec_indas109_ecl.json +24 -0
  96. package/src/usvm/rules/sec_indas115_revenue.json +20 -0
  97. package/src/usvm/rules/sec_indas116_leases.json +20 -0
  98. package/src/usvm/rules/sec_indas12_deferred_tax.json +20 -0
  99. package/src/usvm/rules/sec_indas21_fx_reval.json +20 -0
  100. package/src/usvm/rules/sec_indas36_impairment.json +20 -0
  101. package/src/usvm/rules/sec_indas37_provisions.json +20 -0
  102. package/src/usvm/rules/sec_msme_classification_sec7.json +25 -0
  103. package/src/usvm/rules/sec_msme_delayed_payments_15_16.json +38 -0
  104. package/src/usvm/rules/sec_msme_disclosures_sec22.json +21 -0
  105. package/src/usvm/rules/sec_msme_mca_form_1.json +20 -0
  106. package/src/usvm/schemas/statutory_ast_schema.js +203 -0
  107. package/src/usvm/usvm_domain_evaluators.js +1021 -0
  108. package/types/index.d.ts +134 -0
  109. package/conformance/README.md +0 -54
  110. package/conformance/fixtures/invalid_malformed_temporal_dates.json +0 -10
  111. package/conformance/fixtures/invalid_missing_effective_period.json +0 -6
  112. package/conformance/fixtures/invalid_missing_section_code.json +0 -9
  113. package/conformance/fixtures/valid_circular_frontmatter.md +0 -16
  114. package/conformance/fixtures/valid_full_section.json +0 -35
  115. package/conformance/fixtures/valid_minimal_section.json +0 -11
  116. package/conformance/test_conformance.js +0 -129
  117. package/docs/ACCOUNTING_ASSURANCE_AUDIT_DOSSIER.md +0 -276
  118. package/docs/ADESHA_ASSURANCE_OVERVIEW.md +0 -166
  119. package/docs/ARCHITECTURE.md +0 -750
  120. package/docs/ARCHITECTURE_DECISIONS.md +0 -138
  121. package/docs/CASE_01_FORM_TEXT.txt +0 -48
  122. package/docs/CATALOG.md +0 -1901
  123. package/docs/CA_PILOT_BENCHMARK_CASES.md +0 -282
  124. package/docs/CORPUS_QUALITY.md +0 -106
  125. package/docs/DATA_LICENSING.md +0 -73
  126. package/docs/DOMAIN_BREADTH_AND_DEPTH_COMPARISON.md +0 -209
  127. package/docs/ENTERPRISE_GOVERNANCE.md +0 -159
  128. package/docs/OKF_MAINTENANCE_SOP.md +0 -286
  129. package/docs/PILOT_EVALUATION_GUIDE.md +0 -214
  130. package/docs/PROVENANCE.md +0 -33
  131. package/docs/VERIFICATION.md +0 -106
  132. package/examples/README.md +0 -56
  133. package/examples/invoice_deduction_trace.json +0 -149
  134. package/examples/simulate_end_to_end_trace.js +0 -106
@@ -0,0 +1,1021 @@
1
+ /**
2
+ * MUDRAFORGE UNIVERSAL STATUTORY VIRTUAL MACHINE (USVM) - DOMAIN EVALUATORS
3
+ * Implements pure evaluation handlers for advanced statutory archetypes:
4
+ * - MSMED Section 15/16 3x Bank Compounding
5
+ * - Section 43B(h) March 31 Fiscal Boundary Engine
6
+ * - MSMED Section 7 Enterprise Classification
7
+ * - CGST Rule 37 180-Day ITC Reversal & Rule 37A Supplier Non-Filing
8
+ * - CGST Rule 42/43 Input & Capital Goods Common Credit Apportionment
9
+ * - International Section 195/393 Cross-Border DTAA Treaty Matrix
10
+ * - Transfer Pricing Section 92C & Rule 10CA Percentile ALP
11
+ * - Section 79 Loss Carryforward & Voting Continuity
12
+ * - Section 281 Tax Clearance & Void Asset Transfer
13
+ *
14
+ * Strict Statutory Invariant: Every evaluation stamps isAuthorizedToDisburse: false.
15
+ */
16
+
17
+ import {
18
+ roundToPaisa,
19
+ roundSection288B,
20
+ cleanNumericAmount,
21
+ calculateMsmeCompoundInterest,
22
+ evaluateSection43bH,
23
+ calculateItcReversalRule37,
24
+ calculateRule37ASupplierNonFilingReversal,
25
+ calculateGstItcApportionmentRule42_43,
26
+ evaluateCrossBorderRemittance,
27
+ calculateTransferPricingAlp,
28
+ evaluateSection79LossContinuity,
29
+ evaluateSection281TaxClearance,
30
+ revalueForeignExchangeIndAs109,
31
+ calculateCorporateTaxMatVsConcessional,
32
+ generateMsme1AndScheduleThreeAging,
33
+ calculateRevenueAllocationIndAs115,
34
+ calculateLeaseAmortizationIndAs116,
35
+ calculateExpectedCreditLossIndAs109,
36
+ calculateEsopAmortizationIndAs102,
37
+ calculateDeferredTaxIndAs12,
38
+ evaluateProvisionsAndContingenciesIndAs37,
39
+ calculateForeignCurrencyIndAs21,
40
+ calculateImpairmentIndAs36,
41
+ calculateBusinessCombinationsIndAs103
42
+ } from '../calculators.js';
43
+
44
+ import {
45
+ evaluateSalaryTds
46
+ } from '../payroll.js';
47
+
48
+ /**
49
+ * Evaluates MSMED Section 15/16 Compound Interest at 3x RBI Bank Rate.
50
+ */
51
+ export function evaluateMsmeDelayedPaymentCompoundInterest(ruleAst, facts, trace = []) {
52
+ trace.push(`USVM evaluating MSMED Section 15/16 delayed payments compounding`);
53
+ const principal = facts.principal ?? facts.invoiceAmount ?? facts.consideration ?? 0;
54
+ const rbiBankRate = facts.rbiBankRate ?? ruleAst.computation?.defaultBankRate ?? 0.0675;
55
+
56
+ const res = calculateMsmeCompoundInterest({
57
+ principal,
58
+ acceptanceDate: facts.acceptanceDate || null,
59
+ deliveryDate: facts.deliveryDate || null,
60
+ writtenObjectionDate: facts.writtenObjectionDate || null,
61
+ objectionRemovalDate: facts.objectionRemovalDate || null,
62
+ agreedPaymentDate: facts.agreedPaymentDate || null,
63
+ hasWrittenAgreement: facts.hasWrittenAgreement,
64
+ vendorNicCode: facts.vendorNicCode || facts.nicCode || null,
65
+ nicCode: facts.nicCode || facts.vendorNicCode || null,
66
+ supplierType: facts.supplierType || null,
67
+ isTrader: facts.isTrader,
68
+ dueDate: facts.dueDate || null,
69
+ accrualStartDate: facts.accrualStartDate || null,
70
+ paymentDate: facts.paymentDate || facts.transactionDate || new Date().toISOString(),
71
+ rbiBankRate,
72
+ dateConvention: facts.dateConvention || 'START_DATE_INCLUSIVE',
73
+ commenceDayAfter: facts.commenceDayAfter || false,
74
+ includePaymentDate: facts.includePaymentDate || false
75
+ });
76
+
77
+ return {
78
+ ...res,
79
+ ruleId: ruleAst.sectionId,
80
+ ruleVersion: ruleAst.version,
81
+ governingStatute: ruleAst.governingStatute,
82
+ governingSection: ruleAst.statutorySection,
83
+ isAuthorizedToDisburse: false, // Fiduciary invariant
84
+ executionTrace: trace
85
+ };
86
+ }
87
+
88
+ /**
89
+ * Evaluates Section 43B(h) Temporal & Fiscal Boundary State Machine.
90
+ */
91
+ export function evaluateSection43bHFiscalBoundary(ruleAst, facts, trace = []) {
92
+ trace.push(`USVM evaluating Section 43B(h) fiscal year boundary`);
93
+ const res = evaluateSection43bH({
94
+ invoiceDate: facts.invoiceDate || facts.transactionDate || facts.creditDate,
95
+ acceptanceDate: facts.acceptanceDate || null,
96
+ agreedTermsDays: facts.agreedTermsDays || null,
97
+ disputeStartDate: facts.disputeStartDate || null,
98
+ disputeEndDate: facts.disputeEndDate || null,
99
+ paymentDate: facts.paymentDate || null,
100
+ fyEndDate: facts.fyEndDate || null,
101
+ supplierType: facts.supplierType || 'MANUFACTURER',
102
+ nicCode: facts.nicCode || facts.vendorNicCode || null
103
+ });
104
+
105
+ return {
106
+ ...res,
107
+ ruleId: ruleAst.sectionId,
108
+ ruleVersion: ruleAst.version,
109
+ governingStatute: ruleAst.governingStatute,
110
+ governingSection: ruleAst.statutorySection,
111
+ isAuthorizedToDisburse: false,
112
+ executionTrace: trace
113
+ };
114
+ }
115
+
116
+ /**
117
+ * Evaluates Section 7 MSME Enterprise Classification (Micro / Small / Medium).
118
+ */
119
+ export function evaluateMsmeEnterpriseClassification(ruleAst, facts, trace = []) {
120
+ trace.push(`USVM evaluating MSME Section 7 classification criteria`);
121
+ const plantAndMachinery = Number(facts.plantAndMachineryInr ?? facts.investmentInPpmInr ?? 0);
122
+ const turnover = Number(facts.turnoverInr ?? 0);
123
+
124
+ let enterpriseCategory = 'LARGE';
125
+ let statutoryBasis = '';
126
+
127
+ // Micro: Plant/Machinery <= 1 Cr AND Turnover <= 5 Cr
128
+ if (plantAndMachinery <= 10000000 && turnover <= 50000000) {
129
+ enterpriseCategory = 'MICRO';
130
+ statutoryBasis = 'Investment <= 1 Crore and Turnover <= 5 Crores under Section 7(1) of MSMED Act, 2006';
131
+ } else if (plantAndMachinery <= 100000000 && turnover <= 500000000) {
132
+ enterpriseCategory = 'SMALL';
133
+ statutoryBasis = 'Investment <= 10 Crores and Turnover <= 50 Crores under Section 7(1) of MSMED Act, 2006';
134
+ } else if (plantAndMachinery <= 500000000 && turnover <= 2500000000) {
135
+ enterpriseCategory = 'MEDIUM';
136
+ statutoryBasis = 'Investment <= 50 Crores and Turnover <= 250 Crores under Section 7(1) of MSMED Act, 2006';
137
+ } else {
138
+ enterpriseCategory = 'LARGE';
139
+ statutoryBasis = 'Investment > 50 Crores or Turnover > 250 Crores exceeds MSME ceiling';
140
+ }
141
+
142
+ return {
143
+ enterpriseCategory,
144
+ isMicroOrSmall: enterpriseCategory === 'MICRO' || enterpriseCategory === 'SMALL',
145
+ isMedium: enterpriseCategory === 'MEDIUM',
146
+ isMsme: enterpriseCategory !== 'LARGE',
147
+ plantAndMachineryInr: plantAndMachinery,
148
+ turnoverInr: turnover,
149
+ statutoryBasis,
150
+ ruleId: ruleAst.sectionId,
151
+ ruleVersion: ruleAst.version,
152
+ governingStatute: ruleAst.governingStatute,
153
+ governingSection: ruleAst.statutorySection,
154
+ isAuthorizedToDisburse: false,
155
+ executionTrace: trace
156
+ };
157
+ }
158
+
159
+ /**
160
+ * Evaluates CGST Rule 37 180-Day Non-Payment Proportional ITC Reversal.
161
+ */
162
+ export function evaluateGstRule37ProportionalReversal(ruleAst, facts, trace = []) {
163
+ trace.push(`USVM evaluating CGST Rule 37 180-day ITC reversal`);
164
+ const res = calculateItcReversalRule37({
165
+ invoiceNumber: facts.invoiceNumber || 'INV-UNKNOWN',
166
+ invoiceDate: facts.invoiceDate || facts.transactionDate,
167
+ calculationDate: facts.calculationDate || facts.paymentDate || new Date().toISOString().slice(0, 10),
168
+ invoiceAmount: facts.invoiceAmount ?? facts.grossAmountInr ?? 0,
169
+ taxAmount: facts.taxAmount ?? facts.itcClaimedInr ?? 0,
170
+ paidAmount: facts.paidAmount ?? facts.valuePaidInr ?? 0,
171
+ itcAvailmentDate: facts.itcAvailmentDate || null,
172
+ isRcm: facts.isRcm === true,
173
+ isScheduleISupply: facts.isScheduleISupply === true,
174
+ annualInterestRatePercent: facts.annualInterestRatePercent ?? ruleAst.computation?.annualInterestRatePercent ?? 18.0
175
+ });
176
+
177
+ return {
178
+ ...res,
179
+ ruleId: ruleAst.sectionId,
180
+ ruleVersion: ruleAst.version,
181
+ governingStatute: ruleAst.governingStatute,
182
+ governingSection: ruleAst.statutorySection,
183
+ isAuthorizedToDisburse: false,
184
+ executionTrace: trace
185
+ };
186
+ }
187
+
188
+ /**
189
+ * Evaluates CGST Rule 37A Supplier GSTR-3B Non-Filing Reversal.
190
+ */
191
+ export function evaluateGstRule37ASupplierNonFiling(ruleAst, facts, trace = []) {
192
+ trace.push(`USVM evaluating CGST Rule 37A supplier non-filing cutover`);
193
+ const res = calculateRule37ASupplierNonFilingReversal({
194
+ financialYear: facts.financialYear || '2024-25',
195
+ supplierGstin: facts.supplierGstin || 'UNKNOWN',
196
+ itcClaimedInr: facts.itcClaimedInr ?? facts.taxAmount ?? 0,
197
+ hasSupplierFiledGstr3B: facts.hasSupplierFiledGstr3B === true,
198
+ currentEvaluationDate: facts.currentEvaluationDate || facts.transactionDate || new Date().toISOString().slice(0, 10),
199
+ subsequentFilingDate: facts.subsequentFilingDate || null
200
+ });
201
+
202
+ return {
203
+ ...res,
204
+ ruleId: ruleAst.sectionId,
205
+ ruleVersion: ruleAst.version,
206
+ governingStatute: ruleAst.governingStatute,
207
+ governingSection: ruleAst.statutorySection,
208
+ isAuthorizedToDisburse: false,
209
+ executionTrace: trace
210
+ };
211
+ }
212
+
213
+ /**
214
+ * Evaluates CGST Rule 42/43 Common ITC Apportionment and Exempt Ratio Reversal.
215
+ */
216
+ export function evaluateGstRule42CommonCreditApportionment(ruleAst, facts, trace = []) {
217
+ trace.push(`USVM evaluating CGST Rule 42/43 common credit apportionment`);
218
+ const res = calculateGstItcApportionmentRule42_43({
219
+ taxPeriod: facts.taxPeriod || null,
220
+ financialYear: facts.financialYear || '2025-26',
221
+ totalInputTaxCreditT: facts.totalInputTaxCreditT ?? facts.totalItc ?? facts.taxAmount,
222
+ exclusiveNonBusinessT1: facts.exclusiveNonBusinessT1 || 0,
223
+ exclusiveExemptT2: facts.exclusiveExemptT2 || 0,
224
+ blockedSection17_5_T3: facts.blockedSection17_5_T3 || 0,
225
+ exclusiveTaxableT4: facts.exclusiveTaxableT4 || 0,
226
+ exemptTurnoverE: facts.exemptTurnoverE || 0,
227
+ totalTurnoverF: facts.totalTurnoverF || 0,
228
+ capitalGoodsCommonCreditA: facts.capitalGoodsCommonCreditA || 0,
229
+ capitalGoodsPriorQuartersExempt: facts.capitalGoodsPriorQuartersExempt || 0,
230
+ isAnnualTrueUp: facts.isAnnualTrueUp === true,
231
+ annualExemptTurnover: facts.annualExemptTurnover || null,
232
+ annualTotalTurnover: facts.annualTotalTurnover || null,
233
+ sumOfMonthlyReversalsD1: facts.sumOfMonthlyReversalsD1 || 0,
234
+ isRealEstateProject: facts.isRealEstateProject === true
235
+ });
236
+
237
+ return {
238
+ ...res,
239
+ ruleId: ruleAst.sectionId,
240
+ ruleVersion: ruleAst.version,
241
+ governingStatute: ruleAst.governingStatute,
242
+ governingSection: ruleAst.statutorySection,
243
+ isAuthorizedToDisburse: false,
244
+ executionTrace: trace
245
+ };
246
+ }
247
+
248
+ /**
249
+ * Evaluates Section 195/393 Cross-Border Remittance & DTAA Form Matrix.
250
+ */
251
+ export function evaluateCrossBorderDtaaMatrix(ruleAst, facts, temporal, trace = []) {
252
+ trace.push(`USVM evaluating Section 195/393 cross-border remittance`);
253
+ const res = evaluateCrossBorderRemittance({
254
+ amountUsd: facts.amountUsd ?? (facts.amountInr ? facts.amountInr / (facts.fxRate || 83.5) : 0),
255
+ fxRate: facts.fxRate || 83.5,
256
+ transactionDate: facts.transactionDate || temporal?.crystallizedDate || new Date().toISOString(),
257
+ country: facts.country || null,
258
+ isAutomatedCloudInfra: facts.isAutomatedCloudInfra !== false,
259
+ hasHumanTechnicalServices: facts.hasHumanTechnicalServices === true,
260
+ hasTrc: facts.hasTrc === true,
261
+ hasNoPe: facts.hasNoPe === true,
262
+ hasForm10F: facts.hasForm10F === true,
263
+ hasAoCertificate: facts.hasAoCertificate === true
264
+ });
265
+
266
+ return {
267
+ ...res,
268
+ ruleId: ruleAst.sectionId,
269
+ ruleVersion: ruleAst.version,
270
+ governingStatute: ruleAst.governingStatute,
271
+ governingSection: ruleAst.statutorySection,
272
+ isAuthorizedToDisburse: false,
273
+ executionTrace: trace
274
+ };
275
+ }
276
+
277
+ /**
278
+ * Evaluates Section 92C & Rule 10CA Transfer Pricing Percentile Range & ALP.
279
+ */
280
+ export function evaluateTransferPricingPercentileAlp(ruleAst, facts, trace = []) {
281
+ trace.push(`USVM evaluating Section 92C & Rule 10CA Transfer Pricing ALP`);
282
+ const res = calculateTransferPricingAlp({
283
+ transactionDescription: facts.transactionDescription || 'International Transaction with Associated Enterprise',
284
+ testedParty: facts.testedParty || 'Indian Enterprise',
285
+ associatedEnterpriseName: facts.associatedEnterpriseName || 'Foreign AE',
286
+ isAssociatedEnterprise: facts.isAssociatedEnterprise !== false,
287
+ internationalTransactionAmountInr: facts.internationalTransactionAmountInr ?? facts.amountInr ?? 0,
288
+ testedPartyOperatingMarginPercent: facts.testedPartyOperatingMarginPercent ?? facts.marginPercent ?? 0,
289
+ isWholesaleTrading: facts.isWholesaleTrading === true,
290
+ comparablesData: facts.comparablesData || [],
291
+ transferPricingMethod: facts.transferPricingMethod || 'TNMM'
292
+ });
293
+
294
+ return {
295
+ ...res,
296
+ ruleId: ruleAst.sectionId,
297
+ ruleVersion: ruleAst.version,
298
+ governingStatute: ruleAst.governingStatute,
299
+ governingSection: ruleAst.statutorySection,
300
+ isAuthorizedToDisburse: false,
301
+ executionTrace: trace
302
+ };
303
+ }
304
+
305
+ /**
306
+ * Evaluates Section 79 Loss Carryforward & Voting Continuity.
307
+ */
308
+ export function evaluateSection79VotingContinuity(ruleAst, facts, trace = []) {
309
+ trace.push(`USVM evaluating Section 79 voting continuity`);
310
+ const res = evaluateSection79LossContinuity({
311
+ companyType: facts.companyType || 'CLOSELY_HELD_COMPANY',
312
+ isDpiitRecognizedStartup: facts.isDpiitRecognizedStartup === true,
313
+ isIbcResolutionPlan: facts.isIbcResolutionPlan === true,
314
+ accumulatedBroughtForwardLossInr: facts.accumulatedBroughtForwardLossInr || 0,
315
+ unabsorbedDepreciationInr: facts.unabsorbedDepreciationInr || 0,
316
+ shareholdingInLossYear: facts.shareholdingInLossYear || [],
317
+ shareholdingInSetOffYear: facts.shareholdingInSetOffYear || [],
318
+ votingPowerHeldByOriginalShareholdersPercent: facts.votingPowerHeldByOriginalShareholdersPercent ?? null
319
+ });
320
+
321
+ return {
322
+ ...res,
323
+ ruleId: ruleAst.sectionId,
324
+ ruleVersion: ruleAst.version,
325
+ governingStatute: ruleAst.governingStatute,
326
+ governingSection: ruleAst.statutorySection,
327
+ isAuthorizedToDisburse: false,
328
+ executionTrace: trace
329
+ };
330
+ }
331
+
332
+ /**
333
+ * Evaluates Section 281 Void Transfer of Assets during Tax Proceedings.
334
+ */
335
+ export function evaluateSection281VoidTransfer(ruleAst, facts, trace = []) {
336
+ trace.push(`USVM evaluating Section 281 tax clearance`);
337
+ const res = evaluateSection281TaxClearance({
338
+ assetType: facts.assetType || 'IMMOVABLE_PROPERTY',
339
+ assetDescription: facts.assetDescription || 'Commercial Asset / Undertaking',
340
+ assetValueInr: facts.assetValueInr ?? facts.consideration ?? 0,
341
+ transferNature: facts.transferNature || 'SALE',
342
+ hasPendingProceedings: facts.hasPendingProceedings === true,
343
+ pendingProceedings: facts.pendingProceedings || [],
344
+ hasOutstandingDemand: facts.hasOutstandingDemand === true,
345
+ outstandingDemandInr: facts.outstandingDemandInr || 0,
346
+ hasPriorAoPermission: facts.hasPriorAoPermission === true,
347
+ aoPermissionReference: facts.aoPermissionReference || null,
348
+ aoPermissionDate: facts.aoPermissionDate || null,
349
+ hasAdequateConsideration: facts.hasAdequateConsideration !== false,
350
+ hasNoticeOfProceedingsOrDemand: facts.hasNoticeOfProceedingsOrDemand === true,
351
+ alternativeSecurityFurnishedInr: facts.alternativeSecurityFurnishedInr || 0
352
+ });
353
+
354
+ return {
355
+ ...res,
356
+ ruleId: ruleAst.sectionId,
357
+ ruleVersion: ruleAst.version,
358
+ governingStatute: ruleAst.governingStatute,
359
+ governingSection: ruleAst.statutorySection,
360
+ isAuthorizedToDisburse: false,
361
+ executionTrace: trace
362
+ };
363
+ }
364
+
365
+ /**
366
+ * Evaluates Corporate Tax Section 115BAA vs MAT Section 115JB.
367
+ */
368
+ export function evaluateCorporateTaxMatVsConcessionalUsvm(ruleAst, facts, trace = []) {
369
+ trace.push('USVM evaluating Corporate Tax Section 115BAA vs MAT 115JB');
370
+ const res = calculateCorporateTaxMatVsConcessional({
371
+ netProfitBeforeTaxInr: facts.netProfitBeforeTaxInr ?? facts.profitBeforeTaxInr ?? 0,
372
+ additionsBookProfitInr: facts.additionsBookProfitInr || 0,
373
+ deductionsBookProfitInr: facts.deductionsBookProfitInr || 0,
374
+ deductionsChapterVIAInr: facts.deductionsChapterVIAInr || 0,
375
+ unabsorbedDepreciationInr: facts.unabsorbedDepreciationInr || 0,
376
+ broughtForwardLossInr: facts.broughtForwardLossInr || 0,
377
+ turnoverPriorYearInr: facts.turnoverPriorYearInr || 0,
378
+ isDomesticCompany: facts.isDomesticCompany !== false
379
+ });
380
+ return {
381
+ ...res,
382
+ ruleId: ruleAst.sectionId,
383
+ ruleVersion: ruleAst.version,
384
+ governingStatute: ruleAst.governingStatute,
385
+ governingSection: ruleAst.statutorySection,
386
+ isAuthorizedToDisburse: false,
387
+ executionTrace: trace
388
+ };
389
+ }
390
+
391
+ /**
392
+ * Evaluates Salary TDS Section 192 / Section 392.
393
+ */
394
+ export function evaluateSalaryProgressiveTds(ruleAst, facts, trace = []) {
395
+ trace.push('USVM evaluating Salary TDS Section 192 / Section 392');
396
+ const res = evaluateSalaryTds({
397
+ annualGrossSalaryInr: facts.annualGrossSalaryInr ?? facts.grossSalaryInr ?? 0,
398
+ regime: facts.regime || 'NEW',
399
+ hraExemptionInr: facts.hraExemptionInr || 0,
400
+ section80CDeductionsInr: facts.section80CDeductionsInr || 0,
401
+ section80DDeductionsInr: facts.section80DDeductionsInr || 0,
402
+ otherDeductionsChapterVIAInr: facts.otherDeductionsChapterVIAInr || 0,
403
+ priorTdsDeductedInr: facts.priorTdsDeductedInr || 0,
404
+ remainingMonthsInFy: facts.remainingMonthsInFy || 12
405
+ });
406
+ return {
407
+ ...res,
408
+ ruleId: ruleAst.sectionId,
409
+ ruleVersion: ruleAst.version,
410
+ governingStatute: ruleAst.governingStatute,
411
+ governingSection: ruleAst.statutorySection,
412
+ isAuthorizedToDisburse: false,
413
+ executionTrace: trace
414
+ };
415
+ }
416
+
417
+ /**
418
+ * Evaluates Section 206AB Non-Filer Penal Rate.
419
+ */
420
+ export function evaluateNonFilerPenalRate206AB(ruleAst, facts, trace = []) {
421
+ trace.push('USVM evaluating Section 206AB non-filer rate');
422
+ const txDate = String(facts.transactionDate || facts.creditDate || facts.paymentDate || '2025-01-01');
423
+ const isOmitted = txDate >= '2025-04-01';
424
+ const baseRatePercent = Number(facts.standardRatePercent ?? facts.baseRatePercent ?? 2.0);
425
+ const effectiveRatePercent = isOmitted ? baseRatePercent : Math.max(5.0, baseRatePercent * 2);
426
+ const amountInr = Number(facts.invoiceAmount ?? facts.grossAmountInr ?? 0);
427
+ const calculatedTdsInr = roundToPaisa((amountInr * effectiveRatePercent) / 100);
428
+
429
+ return {
430
+ status: isOmitted ? 'SUNSET_OMITTED_FA_2025' : 'PENAL_RATE_APPLIED',
431
+ isOmittedFinanceAct2025: isOmitted,
432
+ baseRatePercent,
433
+ effectiveRatePercent,
434
+ amountInr,
435
+ calculatedTdsInr,
436
+ statutoryDisposition: isOmitted ? 'SECTION_206AB_OMITTED_USE_STANDARD_RATE' : 'SECTION_206AB_HIGHER_RATE_MANDATORY',
437
+ ruleId: ruleAst.sectionId,
438
+ ruleVersion: ruleAst.version,
439
+ governingStatute: ruleAst.governingStatute,
440
+ governingSection: ruleAst.statutorySection,
441
+ isAuthorizedToDisburse: false,
442
+ executionTrace: trace
443
+ };
444
+ }
445
+
446
+ /**
447
+ * Evaluates Ind AS 12 Deferred Taxes.
448
+ */
449
+ export function evaluateDeferredTaxIndAs12Usvm(ruleAst, facts, trace = []) {
450
+ trace.push('USVM evaluating Ind AS 12 Deferred Tax');
451
+ const res = calculateDeferredTaxIndAs12({
452
+ accountingProfitInr: facts.accountingProfitInr || 0,
453
+ permanentDifferencesInr: facts.permanentDifferencesInr || 0,
454
+ temporaryTaxableDifferencesInr: facts.temporaryTaxableDifferencesInr || 0,
455
+ temporaryDeductibleDifferencesInr: facts.temporaryDeductibleDifferencesInr || 0,
456
+ enactedTaxRatePercent: facts.enactedTaxRatePercent || 25.17,
457
+ futureExpectedRatePercent: facts.futureExpectedRatePercent || 25.17
458
+ });
459
+ return {
460
+ ...res,
461
+ ruleId: ruleAst.sectionId,
462
+ ruleVersion: ruleAst.version,
463
+ governingStatute: ruleAst.governingStatute,
464
+ governingSection: ruleAst.statutorySection,
465
+ isAuthorizedToDisburse: false,
466
+ executionTrace: trace
467
+ };
468
+ }
469
+
470
+ /**
471
+ * Evaluates CGST Section 17(5) Blocked ITC.
472
+ */
473
+ export function evaluateBlockedCreditSection17_5(ruleAst, facts, trace = []) {
474
+ trace.push('USVM evaluating CGST Section 17(5) blocked credit');
475
+ const category = String(facts.expenseCategory || facts.category || '').toUpperCase();
476
+ const blockedCategories = ['MOTOR_VEHICLE', 'FOOD_AND_BEVERAGES', 'OUTDOOR_CATERING', 'CLUB_MEMBERSHIP', 'HEALTH_FITNESS', 'PERSONAL_CONSUMPTION', 'LOST_STOLEN_GOODS', 'FREE_SAMPLES'];
477
+ const isBlocked = blockedCategories.some(c => category.includes(c));
478
+ const taxAmount = Number(facts.taxAmount ?? facts.itcAmount ?? 0);
479
+
480
+ return {
481
+ status: isBlocked ? 'BLOCKED_ITC_INELIGIBLE' : 'ELIGIBLE_ITC',
482
+ isBlocked,
483
+ blockedCategory: isBlocked ? category : null,
484
+ itcBlockedInr: isBlocked ? taxAmount : 0,
485
+ itcEligibleInr: isBlocked ? 0 : taxAmount,
486
+ governingSection: 'CGST Act, 2017 Section 17(5)',
487
+ ruleId: ruleAst.sectionId,
488
+ ruleVersion: ruleAst.version,
489
+ isAuthorizedToDisburse: false,
490
+ executionTrace: trace
491
+ };
492
+ }
493
+
494
+ /**
495
+ * Evaluates CGST Section 16(2) ITC Eligibility Conditions.
496
+ */
497
+ export function evaluateItcEligibilitySection16_2(ruleAst, facts, trace = []) {
498
+ trace.push('USVM evaluating CGST Section 16(2) ITC eligibility conditions');
499
+ const hasTaxInvoice = facts.hasTaxInvoice !== false;
500
+ const hasReceivedGoods = facts.hasReceivedGoods !== false;
501
+ const isTaxPaidBySupplier = facts.isTaxPaidBySupplier !== false;
502
+ const hasFurnishedReturn = facts.hasFurnishedReturn !== false;
503
+
504
+ const allConditionsSatisfied = hasTaxInvoice && hasReceivedGoods && isTaxPaidBySupplier && hasFurnishedReturn;
505
+ const taxAmount = Number(facts.taxAmount ?? facts.itcAmount ?? 0);
506
+
507
+ return {
508
+ status: allConditionsSatisfied ? 'ITC_ELIGIBLE' : 'ITC_INELIGIBLE_CONDITIONS_UNMET',
509
+ isEligible: allConditionsSatisfied,
510
+ itcEligibleInr: allConditionsSatisfied ? taxAmount : 0,
511
+ itcIneligibleInr: allConditionsSatisfied ? 0 : taxAmount,
512
+ failedConditions: [
513
+ !hasTaxInvoice ? 'MISSING_TAX_INVOICE' : null,
514
+ !hasReceivedGoods ? 'GOODS_SERVICES_NOT_RECEIVED' : null,
515
+ !isTaxPaidBySupplier ? 'TAX_NOT_PAID_TO_GOVERNMENT' : null,
516
+ !hasFurnishedReturn ? 'GSTR3B_RETURN_NOT_FURNISHED' : null
517
+ ].filter(Boolean),
518
+ ruleId: ruleAst.sectionId,
519
+ ruleVersion: ruleAst.version,
520
+ isAuthorizedToDisburse: false,
521
+ executionTrace: trace
522
+ };
523
+ }
524
+
525
+ /**
526
+ * Evaluates CGST Section 9(3) Reverse Charge Mechanism.
527
+ */
528
+ export function evaluateRcmLiabilitySection9_3(ruleAst, facts, trace = []) {
529
+ trace.push('USVM evaluating CGST Section 9(3) Reverse Charge Mechanism');
530
+ const serviceType = String(facts.serviceType || facts.natureOfSupply || '').toUpperCase();
531
+ const rcmList = ['GTA', 'GOODS_TRANSPORT', 'LEGAL_SERVICES', 'ADVOCATE', 'DIRECTOR', 'RECOVERY_AGENT', 'SECURITY_SERVICES'];
532
+ const isRcmApplicable = rcmList.some(r => serviceType.includes(r));
533
+ const amountInr = Number(facts.invoiceAmount ?? facts.grossAmountInr ?? 0);
534
+ const rcmRatePercent = Number(facts.rcmRatePercent || 5.0);
535
+ const rcmTaxInr = isRcmApplicable ? roundToPaisa((amountInr * rcmRatePercent) / 100) : 0;
536
+
537
+ return {
538
+ status: isRcmApplicable ? 'RCM_TAX_PAYABLE_BY_RECIPIENT' : 'FORWARD_CHARGE_REGULAR',
539
+ isRcmApplicable,
540
+ recipientRcmLiabilityInr: rcmTaxInr,
541
+ cashLedgerPaymentMandatory: isRcmApplicable,
542
+ governingSection: 'CGST Act, 2017 Section 9(3)',
543
+ ruleId: ruleAst.sectionId,
544
+ ruleVersion: ruleAst.version,
545
+ isAuthorizedToDisburse: false,
546
+ executionTrace: trace
547
+ };
548
+ }
549
+
550
+ /**
551
+ * Evaluates CGST Section 8 Composite & Mixed Supplies.
552
+ */
553
+ export function evaluateCompositeMixedSuppliesSection8(ruleAst, facts, trace = []) {
554
+ trace.push('USVM evaluating CGST Section 8 composite vs mixed supply');
555
+ const supplyType = String(facts.supplyType || 'COMPOSITE').toUpperCase();
556
+ const isComposite = supplyType === 'COMPOSITE';
557
+ const amountInr = Number(facts.invoiceAmount ?? facts.grossAmountInr ?? 0);
558
+ const applicableRatePercent = isComposite
559
+ ? Number(facts.principalSupplyRatePercent || 18.0)
560
+ : Number(facts.highestItemRatePercent || 28.0);
561
+
562
+ const taxAmountInr = roundToPaisa((amountInr * applicableRatePercent) / 100);
563
+
564
+ return {
565
+ status: 'SUCCESS',
566
+ supplyType: isComposite ? 'COMPOSITE_SUPPLY' : 'MIXED_SUPPLY',
567
+ applicableRatePercent,
568
+ taxAmountInr,
569
+ governingSection: 'CGST Act, 2017 Section 8',
570
+ ruleId: ruleAst.sectionId,
571
+ ruleVersion: ruleAst.version,
572
+ isAuthorizedToDisburse: false,
573
+ executionTrace: trace
574
+ };
575
+ }
576
+
577
+ /**
578
+ * Evaluates CGST Section 10 Composition Levy.
579
+ */
580
+ export function evaluateCompositionLevySection10(ruleAst, facts, trace = []) {
581
+ trace.push('USVM evaluating CGST Section 10 Composition Levy');
582
+ const turnoverInr = Number(facts.aggregateTurnoverInr || 0);
583
+ const isEligible = turnoverInr <= 15000000;
584
+ const businessType = String(facts.businessType || 'TRADER').toUpperCase();
585
+ let ratePercent = 1.0;
586
+ if (businessType === 'RESTAURANT') ratePercent = 5.0;
587
+ else if (businessType === 'SERVICE') ratePercent = 6.0;
588
+
589
+ const compositionTaxInr = isEligible ? roundToPaisa((turnoverInr * ratePercent) / 100) : null;
590
+
591
+ return {
592
+ status: isEligible ? 'COMPOSITION_ELIGIBLE' : 'INELIGIBLE_TURNOVER_EXCEEDED',
593
+ isEligible,
594
+ applicableRatePercent: isEligible ? ratePercent : null,
595
+ compositionTaxInr,
596
+ governingSection: 'CGST Act, 2017 Section 10',
597
+ ruleId: ruleAst.sectionId,
598
+ ruleVersion: ruleAst.version,
599
+ isAuthorizedToDisburse: false,
600
+ executionTrace: trace
601
+ };
602
+ }
603
+
604
+ /**
605
+ * Evaluates CGST Section 34 Credit and Debit Note Timelines.
606
+ */
607
+ export function evaluateCreditDebitNotesSection34(ruleAst, facts, trace = []) {
608
+ trace.push('USVM evaluating CGST Section 34 Credit Note adjustment timelines');
609
+ const noteDate = String(facts.creditNoteDate || facts.transactionDate || '2025-01-01');
610
+ const cutoffDate = String(facts.cutoffDate || '2025-11-30');
611
+ const isWithinTimelines = noteDate <= cutoffDate;
612
+
613
+ return {
614
+ status: isWithinTimelines ? 'WITHIN_STATUTORY_DEADLINE' : 'EXPIRED_POST_NOVEMBER_CUTOFF',
615
+ isWithinTimelines,
616
+ creditNoteDate: noteDate,
617
+ statutoryCutoffDate: cutoffDate,
618
+ governingSection: 'CGST Act, 2017 Section 34(2)',
619
+ ruleId: ruleAst.sectionId,
620
+ ruleVersion: ruleAst.version,
621
+ isAuthorizedToDisburse: false,
622
+ executionTrace: trace
623
+ };
624
+ }
625
+
626
+ /**
627
+ * Evaluates IGST Section 16 Zero-Rated Export with LUT.
628
+ */
629
+ export function evaluateExportLutSection16(ruleAst, facts, trace = []) {
630
+ trace.push('USVM evaluating IGST Section 16 export of services under LUT');
631
+ const hasValidLut = facts.hasValidLut !== false;
632
+ const exportAmountInr = Number(facts.exportAmountInr ?? facts.invoiceAmount ?? 0);
633
+
634
+ return {
635
+ status: hasValidLut ? 'ZERO_RATED_LUT_AUTHORIZED' : 'EXPORT_WITH_PAYMENT_REQUIRED',
636
+ hasValidLut,
637
+ exportAmountInr,
638
+ igstPayableInr: hasValidLut ? 0 : roundToPaisa((exportAmountInr * 18) / 100),
639
+ governingSection: 'IGST Act, 2017 Section 16',
640
+ ruleId: ruleAst.sectionId,
641
+ ruleVersion: ruleAst.version,
642
+ isAuthorizedToDisburse: false,
643
+ executionTrace: trace
644
+ };
645
+ }
646
+
647
+ /**
648
+ * Evaluates CGST Rule 48(4) E-Invoicing Mandate.
649
+ */
650
+ export function evaluateEInvoicingRule48_4(ruleAst, facts, trace = []) {
651
+ trace.push('USVM evaluating CGST Rule 48(4) e-invoicing mandate');
652
+ const turnoverInr = Number(facts.aggregateTurnoverInr || 0);
653
+ const isEInvoicingMandatory = turnoverInr > 50000000; // 5 Cr
654
+
655
+ return {
656
+ status: isEInvoicingMandatory ? 'EINVOICING_MANDATORY_IRN_REQUIRED' : 'EXEMPT_BELOW_TURNOVER_THRESHOLD',
657
+ isEInvoicingMandatory,
658
+ turnoverInr,
659
+ governingSection: 'CGST Rules, 2017 Rule 48(4)',
660
+ ruleId: ruleAst.sectionId,
661
+ ruleVersion: ruleAst.version,
662
+ isAuthorizedToDisburse: false,
663
+ executionTrace: trace
664
+ };
665
+ }
666
+
667
+ /**
668
+ * Evaluates CGST Rule 138 E-Way Bill Consignment Threshold.
669
+ */
670
+ export function evaluateEWayBillRule138(ruleAst, facts, trace = []) {
671
+ trace.push('USVM evaluating CGST Rule 138 e-way bill threshold');
672
+ const consignmentValueInr = Number(facts.consignmentValueInr ?? facts.invoiceAmount ?? 0);
673
+ const isEWayBillRequired = consignmentValueInr > 50000;
674
+
675
+ return {
676
+ status: isEWayBillRequired ? 'EWAYBILL_GENERATION_MANDATORY' : 'EXEMPT_BELOW_50K_THRESHOLD',
677
+ isEWayBillRequired,
678
+ consignmentValueInr,
679
+ governingSection: 'CGST Rules, 2017 Rule 138',
680
+ ruleId: ruleAst.sectionId,
681
+ ruleVersion: ruleAst.version,
682
+ isAuthorizedToDisburse: false,
683
+ executionTrace: trace
684
+ };
685
+ }
686
+
687
+ /**
688
+ * Evaluates CGST Section 51 GST TDS Deduction.
689
+ */
690
+ export function evaluateGstTdsSection51(ruleAst, facts, trace = []) {
691
+ trace.push('USVM evaluating CGST Section 51 GST TDS');
692
+ const contractValueInr = Number(facts.contractValueInr || 0);
693
+ const invoiceAmountInr = Number(facts.invoiceAmount ?? facts.paymentAmountInr ?? 0);
694
+ const isGovernmentRecipient = facts.isGovernmentRecipient === true || facts.isGovernmentDeductor === true;
695
+ const isThresholdBreached = contractValueInr > 250000;
696
+ const isDeductible = isGovernmentRecipient && isThresholdBreached;
697
+
698
+ const cgstTdsInr = isDeductible ? roundToPaisa((invoiceAmountInr * 1) / 100) : 0;
699
+ const sgstTdsInr = isDeductible ? roundToPaisa((invoiceAmountInr * 1) / 100) : 0;
700
+
701
+ return {
702
+ status: isDeductible ? 'GST_TDS_MANDATORY' : 'NOT_APPLICABLE',
703
+ isDeductible,
704
+ cgstTdsInr,
705
+ sgstTdsInr,
706
+ totalGstTdsInr: roundToPaisa(cgstTdsInr + sgstTdsInr),
707
+ governingSection: 'CGST Act, 2017 Section 51',
708
+ ruleId: ruleAst.sectionId,
709
+ ruleVersion: ruleAst.version,
710
+ isAuthorizedToDisburse: false,
711
+ executionTrace: trace
712
+ };
713
+ }
714
+
715
+ /**
716
+ * Evaluates MCA Form MSME-1 Aging & Reporting.
717
+ */
718
+ export function evaluateMcaMsme1Aging(ruleAst, facts, trace = []) {
719
+ trace.push('USVM evaluating MCA Form MSME-1 45-day overdue aging');
720
+ const res = generateMsme1AndScheduleThreeAging({
721
+ asOfDate: facts.asOfDate || new Date().toISOString().slice(0, 10),
722
+ payables: facts.payables || []
723
+ });
724
+
725
+ return {
726
+ ...res,
727
+ ruleId: ruleAst.sectionId,
728
+ ruleVersion: ruleAst.version,
729
+ governingStatute: ruleAst.governingStatute,
730
+ governingSection: ruleAst.statutorySection,
731
+ isAuthorizedToDisburse: false,
732
+ executionTrace: trace
733
+ };
734
+ }
735
+
736
+ /**
737
+ * Evaluates MSMED Section 22 Annual Disclosures.
738
+ */
739
+ export function evaluateMsmeDisclosuresSection22(ruleAst, facts, trace = []) {
740
+ trace.push('USVM evaluating MSMED Section 22 balance sheet note disclosures');
741
+ const principalDueInr = Number(facts.principalDueInr ?? facts.unpaidPrincipalInr ?? 0);
742
+ const interestAccruedInr = Number(facts.interestAccruedInr ?? facts.unpaidInterestInr ?? 0);
743
+
744
+ const disclosures = [
745
+ 'Principal and interest unpaid as at year end',
746
+ 'Interest paid u/s 16 during the year',
747
+ 'Interest due and payable for delay without payment u/s 16',
748
+ 'Interest accrued and remaining unpaid at end of each accounting year'
749
+ ];
750
+
751
+ return {
752
+ status: 'SUCCESS',
753
+ principalDueInr,
754
+ interestAccruedInr,
755
+ disclosuresRequired: disclosures,
756
+ isDisclosureMandatory: true,
757
+ governingSection: 'MSMED Act, 2006 Section 22',
758
+ ruleId: ruleAst.sectionId,
759
+ ruleVersion: ruleAst.version,
760
+ isAuthorizedToDisburse: false,
761
+ executionTrace: trace
762
+ };
763
+ }
764
+
765
+ /**
766
+ * Evaluates Ind AS 116 Lease Amortization.
767
+ */
768
+ export function evaluateLeaseAmortizationIndAs116Usvm(ruleAst, facts, trace = []) {
769
+ trace.push('USVM evaluating Ind AS 116 Lease Amortization');
770
+ const res = calculateLeaseAmortizationIndAs116({
771
+ leaseTermMonths: facts.leaseTermMonths || 36,
772
+ annualDiscountRatePercent: facts.annualDiscountRatePercent || 8.5,
773
+ monthlyLeasePaymentInr: facts.monthlyLeasePaymentInr || 100000,
774
+ initialDirectCostsInr: facts.initialDirectCostsInr || 0,
775
+ leaseIncentivesReceivedInr: facts.leaseIncentivesReceivedInr || 0
776
+ });
777
+
778
+ return {
779
+ ...res,
780
+ ruleId: ruleAst.sectionId,
781
+ ruleVersion: ruleAst.version,
782
+ governingStatute: ruleAst.governingStatute,
783
+ governingSection: ruleAst.statutorySection,
784
+ isAuthorizedToDisburse: false,
785
+ executionTrace: trace
786
+ };
787
+ }
788
+
789
+ /**
790
+ * Evaluates Ind AS 115 Revenue Allocation.
791
+ */
792
+ export function evaluateRevenueAllocationIndAs115Usvm(ruleAst, facts, trace = []) {
793
+ trace.push('USVM evaluating Ind AS 115 Revenue Allocation');
794
+ const res = calculateRevenueAllocationIndAs115({
795
+ transactionPriceInr: facts.transactionPriceInr || 1000000,
796
+ performanceObligations: facts.performanceObligations || [],
797
+ variableConsiderationConstraintInr: facts.variableConsiderationConstraintInr || 0,
798
+ significantFinancingRatePercent: facts.significantFinancingRatePercent || 0,
799
+ financingPeriodMonths: facts.financingPeriodMonths || 0
800
+ });
801
+
802
+ return {
803
+ ...res,
804
+ ruleId: ruleAst.sectionId,
805
+ ruleVersion: ruleAst.version,
806
+ governingStatute: ruleAst.governingStatute,
807
+ governingSection: ruleAst.statutorySection,
808
+ isAuthorizedToDisburse: false,
809
+ executionTrace: trace
810
+ };
811
+ }
812
+
813
+ /**
814
+ * Evaluates Ind AS 37 Provisions and Contingencies.
815
+ */
816
+ export function evaluateProvisionsAndContingenciesIndAs37Usvm(ruleAst, facts, trace = []) {
817
+ trace.push('USVM evaluating Ind AS 37 Provisions & Contingencies');
818
+ const res = evaluateProvisionsAndContingenciesIndAs37({
819
+ obligationType: facts.obligationType || 'LEGAL_DISPUTE',
820
+ probabilityAssessment: facts.probabilityAssessment || 'PROBABLE',
821
+ probabilityPercent: facts.probabilityPercent ?? 75,
822
+ bestEstimateAmountInr: facts.bestEstimateAmountInr || 500000,
823
+ minRangeAmountInr: facts.minRangeAmountInr || 300000,
824
+ maxRangeAmountInr: facts.maxRangeAmountInr || 700000,
825
+ reimbursementExpectedInr: facts.reimbursementExpectedInr || 0,
826
+ discountRatePercent: facts.discountRatePercent || 0,
827
+ timeHorizonYears: facts.timeHorizonYears || 1
828
+ });
829
+
830
+ return {
831
+ ...res,
832
+ ruleId: ruleAst.sectionId,
833
+ ruleVersion: ruleAst.version,
834
+ governingStatute: ruleAst.governingStatute,
835
+ governingSection: ruleAst.statutorySection,
836
+ isAuthorizedToDisburse: false,
837
+ executionTrace: trace
838
+ };
839
+ }
840
+
841
+ /**
842
+ * Evaluates Ind AS 21 & 109 Foreign Exchange Revaluation.
843
+ */
844
+ export function evaluateForeignExchangeRevaluationUsvm(ruleAst, facts, trace = []) {
845
+ trace.push('USVM evaluating Ind AS 21 & 109 Foreign Exchange Revaluation');
846
+ const res = calculateForeignCurrencyIndAs21({
847
+ originalForeignAmount: facts.originalForeignAmount || 10000,
848
+ originalSpotRate: facts.originalSpotRate || 82.5,
849
+ closingSpotRate: facts.closingSpotRate || 83.5,
850
+ isMonetaryItem: facts.isMonetaryItem !== false,
851
+ isHedgingDesignated: facts.isHedgingDesignated === true,
852
+ hedgeEffectivenessRatio: facts.hedgeEffectivenessRatio || 1.0,
853
+ foreignCurrency: facts.foreignCurrency || 'USD'
854
+ });
855
+
856
+ return {
857
+ ...res,
858
+ ruleId: ruleAst.sectionId,
859
+ ruleVersion: ruleAst.version,
860
+ governingStatute: ruleAst.governingStatute,
861
+ governingSection: ruleAst.statutorySection,
862
+ isAuthorizedToDisburse: false,
863
+ executionTrace: trace
864
+ };
865
+ }
866
+
867
+ /**
868
+ * Evaluates Ind AS 109 Expected Credit Loss.
869
+ */
870
+ export function evaluateExpectedCreditLossIndAs109Usvm(ruleAst, facts, trace = []) {
871
+ trace.push('USVM evaluating Ind AS 109 Expected Credit Loss');
872
+ const res = calculateExpectedCreditLossIndAs109({
873
+ grossCarryingAmountInr: facts.grossCarryingAmountInr || 1000000,
874
+ isCreditImpaired: facts.isCreditImpaired === true,
875
+ isSignificantIncreaseInCreditRisk: facts.isSignificantIncreaseInCreditRisk === true,
876
+ pdStage1Percent: facts.pdStage1Percent || 1.5,
877
+ pdStage2Percent: facts.pdStage2Percent || 5.0,
878
+ lgdPercent: facts.lgdPercent || 40.0,
879
+ forwardLookingMacroFactorPercent: facts.forwardLookingMacroFactorPercent || 1.0
880
+ });
881
+
882
+ return {
883
+ ...res,
884
+ ruleId: ruleAst.sectionId,
885
+ ruleVersion: ruleAst.version,
886
+ governingStatute: ruleAst.governingStatute,
887
+ governingSection: ruleAst.statutorySection,
888
+ isAuthorizedToDisburse: false,
889
+ executionTrace: trace
890
+ };
891
+ }
892
+
893
+ /**
894
+ * Evaluates Foreign Tax Credit Relief (IRC §§ 901/904 / DTAA Art 23).
895
+ */
896
+ export function evaluateForeignTaxCreditRelief(ruleAst, facts, trace = []) {
897
+ trace.push('USVM evaluating Foreign Tax Credit relief limitation');
898
+ const foreignIncomeInr = Number(facts.foreignIncomeInr || 0);
899
+ const foreignTaxPaidInr = Number(facts.foreignTaxPaidInr || 0);
900
+ const domesticTaxOnForeignIncomeInr = Number(facts.domesticTaxOnForeignIncomeInr || 0);
901
+
902
+ const allowableFtcInr = Math.min(foreignTaxPaidInr, domesticTaxOnForeignIncomeInr);
903
+
904
+ return {
905
+ status: 'SUCCESS',
906
+ foreignIncomeInr,
907
+ foreignTaxPaidInr,
908
+ domesticTaxOnForeignIncomeInr,
909
+ allowableForeignTaxCreditInr: allowableFtcInr,
910
+ excessUncreditedForeignTaxInr: Math.max(0, foreignTaxPaidInr - allowableFtcInr),
911
+ governingStatute: 'US IRC §§ 901/904 & Income-tax Act Section 90/91',
912
+ ruleId: ruleAst.sectionId,
913
+ ruleVersion: ruleAst.version,
914
+ isAuthorizedToDisburse: false,
915
+ executionTrace: trace
916
+ };
917
+ }
918
+
919
+ /**
920
+ * Evaluates Section 50B Slump Sale Net Worth & Capital Gains.
921
+ */
922
+ export function evaluateSlumpSaleSection50B(ruleAst, facts, trace = []) {
923
+ trace.push('USVM evaluating Section 50B Slump Sale Net Worth');
924
+ const slumpSaleConsiderationInr = Number(facts.slumpSaleConsiderationInr ?? facts.invoiceAmount ?? 0);
925
+ const bookValueOfAssetsInr = Number(facts.bookValueOfAssetsInr || 0);
926
+ const liabilitiesInr = Number(facts.liabilitiesInr || 0);
927
+ const netWorthInr = facts.netWorthInr !== undefined
928
+ ? Number(facts.netWorthInr)
929
+ : Math.max(0, bookValueOfAssetsInr - liabilitiesInr);
930
+ const capitalGainInr = Math.max(0, slumpSaleConsiderationInr - netWorthInr);
931
+ const isLongTerm = facts.holdingPeriodMonths !== undefined
932
+ ? facts.holdingPeriodMonths >= 36
933
+ : (facts.undertakingAgeYears !== undefined ? facts.undertakingAgeYears >= 3 : true);
934
+
935
+ return {
936
+ status: 'SUCCESS',
937
+ slumpSaleConsiderationInr,
938
+ netWorthInr,
939
+ capitalGainInr,
940
+ isLongTermCapitalGain: isLongTerm,
941
+ governingSection: 'Income-tax Act, 1961 Section 50B read with Rule 11UAE',
942
+ ruleId: ruleAst.sectionId,
943
+ ruleVersion: ruleAst.version,
944
+ isAuthorizedToDisburse: false,
945
+ executionTrace: trace
946
+ };
947
+ }
948
+
949
+ /**
950
+ * Evaluates Ind AS 103 Business Combinations.
951
+ */
952
+ export function evaluateBusinessCombinationsIndAs103Usvm(ruleAst, facts, trace = []) {
953
+ trace.push('USVM evaluating Ind AS 103 Business Combinations');
954
+ const res = calculateBusinessCombinationsIndAs103({
955
+ purchaseConsiderationInr: facts.purchaseConsiderationInr || 10000000,
956
+ fairValueOfNetIdentifiableAssetsInr: facts.fairValueOfNetIdentifiableAssetsInr || 8000000,
957
+ nonControllingInterestValueInr: facts.nonControllingInterestValueInr || 0,
958
+ nciValuationMethod: facts.nciValuationMethod || 'PROPORTIONATE_SHARE',
959
+ previouslyHeldEquityFairValueInr: facts.previouslyHeldEquityFairValueInr || 0,
960
+ acquisitionRelatedCostsInr: facts.acquisitionRelatedCostsInr || 0
961
+ });
962
+
963
+ return {
964
+ ...res,
965
+ ruleId: ruleAst.sectionId,
966
+ ruleVersion: ruleAst.version,
967
+ governingStatute: ruleAst.governingStatute,
968
+ governingSection: ruleAst.statutorySection,
969
+ isAuthorizedToDisburse: false,
970
+ executionTrace: trace
971
+ };
972
+ }
973
+
974
+ /**
975
+ * Evaluates Ind AS 36 Impairment of Assets.
976
+ */
977
+ export function evaluateImpairmentIndAs36Usvm(ruleAst, facts, trace = []) {
978
+ trace.push('USVM evaluating Ind AS 36 Impairment of Assets');
979
+ const res = calculateImpairmentIndAs36({
980
+ carryingAmountCguInr: facts.carryingAmountCguInr || 5000000,
981
+ fairValueLessCostsOfDisposalInr: facts.fairValueLessCostsOfDisposalInr || 4000000,
982
+ valueInUseInr: facts.valueInUseInr || 4500000,
983
+ allocatedGoodwillInr: facts.allocatedGoodwillInr || 500000,
984
+ cguAssetsList: facts.cguAssetsList || []
985
+ });
986
+
987
+ return {
988
+ ...res,
989
+ ruleId: ruleAst.sectionId,
990
+ ruleVersion: ruleAst.version,
991
+ governingStatute: ruleAst.governingStatute,
992
+ governingSection: ruleAst.statutorySection,
993
+ isAuthorizedToDisburse: false,
994
+ executionTrace: trace
995
+ };
996
+ }
997
+
998
+ /**
999
+ * Evaluates Ind AS 102 Share-Based Payments (ESOP).
1000
+ */
1001
+ export function evaluateShareBasedPaymentsIndAs102Usvm(ruleAst, facts, trace = []) {
1002
+ trace.push('USVM evaluating Ind AS 102 Share-Based Payments (ESOP)');
1003
+ const res = calculateEsopAmortizationIndAs102({
1004
+ optionsGrantedCount: facts.optionsGrantedCount || 10000,
1005
+ grantDateFairValuePerOptionInr: facts.grantDateFairValuePerOptionInr || 50,
1006
+ vestingPeriodYears: facts.vestingPeriodYears || 3,
1007
+ expectedForfeitureRatePercent: facts.expectedForfeitureRatePercent || 5,
1008
+ exercisePriceInr: facts.exercisePriceInr || 100,
1009
+ currentMarketPriceInr: facts.currentMarketPriceInr || 150
1010
+ });
1011
+
1012
+ return {
1013
+ ...res,
1014
+ ruleId: ruleAst.sectionId,
1015
+ ruleVersion: ruleAst.version,
1016
+ governingStatute: ruleAst.governingStatute,
1017
+ governingSection: ruleAst.statutorySection,
1018
+ isAuthorizedToDisburse: false,
1019
+ executionTrace: trace
1020
+ };
1021
+ }