@classytic/ca-tax 0.0.15 → 0.0.17

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/dist/t2.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { kt as AT1_SCHEDULE_21_POOLS, rt as SCHEDULE_1_LINE_BY_NUMBER } from "./forms.mjs";
1
+ import { Mt as AT1_SCHEDULE_21_POOLS, ot as SCHEDULE_1_LINE_BY_NUMBER } from "./forms.mjs";
2
2
  //#region src/t2/rates/rate-book.ts
3
3
  /**
4
4
  * Resolve the table in effect for `taxYear` — the entry with the greatest
@@ -242,11 +242,6 @@ function computeAlbertaTax(input, rates = AB_TAX_2024) {
242
242
  //#endregion
243
243
  //#region src/t2/at1/filing/at1-schedule-line-items.ts
244
244
  /**
245
- * Schedules the engine computes but cannot yet file, because their line numbers
246
- * have not been transcribed from the specification. Named so the difference
247
- * between "no data" and "not implemented" is visible rather than silent.
248
- */
249
- /**
250
245
  * Schedules this module can put into a filing payload. Exported so callers and
251
246
  * tests share one source of truth — a hard-coded copy in a test drifts the moment
252
247
  * a builder is added, and then quietly stops guarding anything.
@@ -697,6 +692,7 @@ function schedule12Values(input) {
697
692
  alwaysPair("072", "073", d?.limitedPartnership);
698
693
  alwaysPair("056", "057", input.donations?.charitable);
699
694
  alwaysPair("058", "059", input.donations?.gifts);
695
+ alwaysPair("130", "131", input.restrictedInterestAndFinancing);
700
696
  put("054", input.albertaNetIncomeForTax);
701
697
  return {
702
698
  scheduleId: "012",
@@ -724,7 +720,7 @@ const POOL_FIELD_TO_RESULT_KEY = {
724
720
  carryBack: "carriedBack",
725
721
  closing: "closingBalance"
726
722
  };
727
- function schedule21Values(input) {
723
+ function schedule21Values$1(input) {
728
724
  const values = [];
729
725
  const put = (fieldId, value) => values.push({
730
726
  lineItemId: at1LineItemId("021", fieldId),
@@ -827,7 +823,7 @@ function schedule21Values(input) {
827
823
  values
828
824
  };
829
825
  }
830
- function schedule1Values(input) {
826
+ function schedule1Values$1(input) {
831
827
  const values = [];
832
828
  const put = (fieldId, value, occurrence = 1) => values.push({
833
829
  lineItemId: at1LineItemId("001", fieldId, occurrence),
@@ -853,7 +849,7 @@ function schedule1Values(input) {
853
849
  values
854
850
  };
855
851
  }
856
- function schedule2Values(input) {
852
+ function schedule2Values$1(input) {
857
853
  const values = [];
858
854
  const put = (fieldId, value) => {
859
855
  if (value === void 0) return;
@@ -1060,16 +1056,16 @@ function schedule16Values(result) {
1060
1056
  }
1061
1057
  //#endregion
1062
1058
  //#region src/t2/at1/schedules/at4970-ieg-projects.ts
1063
- const nn$34 = (v) => Math.max(0, Math.round(v ?? 0));
1059
+ const nn$36 = (v) => Math.max(0, Math.round(v ?? 0));
1064
1060
  function computeAt4970(input) {
1065
1061
  const projects = input.projects.map((p) => ({
1066
1062
  title: p.title,
1067
1063
  ...p.projectCode !== void 0 ? { projectCode: p.projectCode } : {},
1068
- albertaPortion: nn$34(p.albertaPortion),
1069
- otherPortion: nn$34(p.otherPortion),
1070
- salariesAndWages: nn$34(p.salariesAndWages),
1071
- federalProxyAmount: nn$34(p.federalProxyAmount),
1072
- albertaProxyAmount: nn$34(p.albertaProxyAmount)
1064
+ albertaPortion: nn$36(p.albertaPortion),
1065
+ otherPortion: nn$36(p.otherPortion),
1066
+ salariesAndWages: nn$36(p.salariesAndWages),
1067
+ federalProxyAmount: nn$36(p.federalProxyAmount),
1068
+ albertaProxyAmount: nn$36(p.albertaProxyAmount)
1073
1069
  }));
1074
1070
  const totals = {
1075
1071
  albertaPortion: projects.reduce((s, p) => s + p.albertaPortion, 0),
@@ -1080,7 +1076,7 @@ function computeAt4970(input) {
1080
1076
  };
1081
1077
  const jurisdictions = (input.jurisdictions ?? []).map((j) => ({
1082
1078
  jurisdiction: j.jurisdiction,
1083
- amountIncurred: nn$34(j.amountIncurred)
1079
+ amountIncurred: nn$36(j.amountIncurred)
1084
1080
  }));
1085
1081
  return {
1086
1082
  projects,
@@ -1196,15 +1192,15 @@ function computeAllocationFactor(input) {
1196
1192
  *
1197
1193
  * Whole dollars, pure.
1198
1194
  */
1199
- const nn$33 = (v) => Math.max(0, Math.round(v ?? 0));
1195
+ const nn$35 = (v) => Math.max(0, Math.round(v ?? 0));
1200
1196
  const raw = (v) => Math.round(v ?? 0);
1201
1197
  function computeItc(input, roomCap, issues) {
1202
- const certificatesIssued = nn$33(input.certificatesIssued);
1203
- const carryforwardFromPriorYear = nn$33(input.carryforwardFromPriorYear);
1204
- const expired = nn$33(input.expired);
1198
+ const certificatesIssued = nn$35(input.certificatesIssued);
1199
+ const carryforwardFromPriorYear = nn$35(input.carryforwardFromPriorYear);
1200
+ const expired = nn$35(input.expired);
1205
1201
  const availableBeforeClaim = certificatesIssued + carryforwardFromPriorYear;
1206
1202
  const cap = Math.min(availableBeforeClaim, roomCap);
1207
- const wanted = input.amountApplied != null ? nn$33(input.amountApplied) : cap;
1203
+ const wanted = input.amountApplied != null ? nn$35(input.amountApplied) : cap;
1208
1204
  const amountApplied = Math.max(0, Math.min(wanted, cap));
1209
1205
  const carryforwardToNextYear = availableBeforeClaim - amountApplied - expired;
1210
1206
  if (carryforwardToNextYear < 0) issues.push(`Alberta Schedule 3 (ITC): expired (${expired}) plus the amount applied (${amountApplied}) exceed the available pool (${availableBeforeClaim}) by ${-carryforwardToNextYear}. Check the 100/102/104/106 inputs.`);
@@ -1218,17 +1214,17 @@ function computeItc(input, roomCap, issues) {
1218
1214
  };
1219
1215
  }
1220
1216
  function computeCitc(input, roomCap, itcApplied, itcCarryforwardRemaining, issues) {
1221
- const certificatesIssued = nn$33(input.certificatesIssued);
1222
- const carryforwardFromPriorYear = nn$33(input.carryforwardFromPriorYear);
1223
- const expired = nn$33(input.expired);
1217
+ const certificatesIssued = nn$35(input.certificatesIssued);
1218
+ const carryforwardFromPriorYear = nn$35(input.carryforwardFromPriorYear);
1219
+ const expired = nn$35(input.expired);
1224
1220
  const availableBeforeClaim = certificatesIssued + carryforwardFromPriorYear;
1225
1221
  let amountApplied;
1226
1222
  if (itcCarryforwardRemaining > 0) {
1227
1223
  amountApplied = 0;
1228
- if (input.amountApplied != null && nn$33(input.amountApplied) > 0) issues.push(`Alberta Schedule 3 (CITC): a claim of ${nn$33(input.amountApplied)} was requested, but the Investor Tax Credit still has an unused carryforward balance (${itcCarryforwardRemaining}) after this year's application, so line 204 must be nil until ITC is fully drawn down.`);
1224
+ if (input.amountApplied != null && nn$35(input.amountApplied) > 0) issues.push(`Alberta Schedule 3 (CITC): a claim of ${nn$35(input.amountApplied)} was requested, but the Investor Tax Credit still has an unused carryforward balance (${itcCarryforwardRemaining}) after this year's application, so line 204 must be nil until ITC is fully drawn down.`);
1229
1225
  } else {
1230
1226
  const cap = Math.min(availableBeforeClaim, Math.max(0, roomCap - itcApplied));
1231
- const wanted = input.amountApplied != null ? nn$33(input.amountApplied) : cap;
1227
+ const wanted = input.amountApplied != null ? nn$35(input.amountApplied) : cap;
1232
1228
  amountApplied = Math.max(0, Math.min(wanted, cap));
1233
1229
  }
1234
1230
  const carryforwardToNextYear = availableBeforeClaim - amountApplied - expired;
@@ -1247,18 +1243,18 @@ function computeApitc(input, roomCap, issues) {
1247
1243
  const first = input.firstPreceding ?? {};
1248
1244
  const second = input.secondPreceding ?? {};
1249
1245
  const thirdToTenth = input.thirdToTenthPreceding ?? {};
1250
- const currentAvailable = nn$33(current.received);
1251
- const firstAvailable = nn$33(first.availableAtBeginning);
1252
- const secondAvailable = nn$33(second.availableAtBeginning);
1253
- const thirdToTenthAvailable = nn$33(thirdToTenth.availableAtBeginning);
1246
+ const currentAvailable = nn$35(current.received);
1247
+ const firstAvailable = nn$35(first.availableAtBeginning);
1248
+ const secondAvailable = nn$35(second.availableAtBeginning);
1249
+ const thirdToTenthAvailable = nn$35(thirdToTenth.availableAtBeginning);
1254
1250
  const currentCap = Math.round(currentAvailable * .2);
1255
1251
  const firstCap = Math.round(firstAvailable * .3);
1256
1252
  const secondCap = Math.round(secondAvailable * .5);
1257
1253
  const thirdToTenthCap = thirdToTenthAvailable;
1258
- const currentAsk = Math.min(current.amountApplied != null ? nn$33(current.amountApplied) : currentCap, currentCap);
1259
- const firstAsk = Math.min(first.amountApplied != null ? nn$33(first.amountApplied) : firstCap, firstCap);
1260
- const secondAsk = Math.min(second.amountApplied != null ? nn$33(second.amountApplied) : secondCap, secondCap);
1261
- const thirdToTenthAsk = Math.min(thirdToTenth.amountApplied != null ? nn$33(thirdToTenth.amountApplied) : thirdToTenthCap, thirdToTenthCap);
1254
+ const currentAsk = Math.min(current.amountApplied != null ? nn$35(current.amountApplied) : currentCap, currentCap);
1255
+ const firstAsk = Math.min(first.amountApplied != null ? nn$35(first.amountApplied) : firstCap, firstCap);
1256
+ const secondAsk = Math.min(second.amountApplied != null ? nn$35(second.amountApplied) : secondCap, secondCap);
1257
+ const thirdToTenthAsk = Math.min(thirdToTenth.amountApplied != null ? nn$35(thirdToTenth.amountApplied) : thirdToTenthCap, thirdToTenthCap);
1262
1258
  const totalRequested = currentAsk + firstAsk + secondAsk + thirdToTenthAsk;
1263
1259
  let room = Math.max(0, roomCap);
1264
1260
  const allocate = (ask) => {
@@ -1274,7 +1270,7 @@ function computeApitc(input, roomCap, issues) {
1274
1270
  if (totalApplied < totalRequested) issues.push(`Alberta Schedule 3 (APITC): the shared Maximum Allowable Deduction room (${roomCap}) was insufficient to cover ${totalRequested} requested across vintages; ${totalRequested - totalApplied} went unapplied. Allocation prioritized the oldest vintage first (closest to the 10-year expiry) — the spec states only the combined ceiling on 312, not an application order across 304/306/308/310. Supply amountApplied on each vintage directly for exact filing parity.`);
1275
1271
  const totalReceived = currentAvailable;
1276
1272
  const carryforwardFromPriorYear = firstAvailable + secondAvailable + thirdToTenthAvailable;
1277
- const expired = nn$33(input.expiredThisYear);
1273
+ const expired = nn$35(input.expiredThisYear);
1278
1274
  const availableForCarryforward = totalReceived + carryforwardFromPriorYear - totalApplied - expired;
1279
1275
  if (availableForCarryforward < 0) issues.push(`Alberta Schedule 3 (APITC): applied (${totalApplied}) plus expired (${expired}) exceed the available pool (${totalReceived + carryforwardFromPriorYear}) by ${-availableForCarryforward}. Check the 300/302/312/314 inputs.`);
1280
1276
  return {
@@ -1308,11 +1304,11 @@ function computeApitc(input, roomCap, issues) {
1308
1304
  function computeSchedule3(input) {
1309
1305
  const issues = [];
1310
1306
  const mad = input.mad ?? {};
1311
- const line068 = nn$33(mad.taxPayableBeforeDeduction);
1312
- const line070 = nn$33(mad.line070);
1313
- const line071 = nn$33(mad.line071);
1314
- const line072 = nn$33(mad.line072);
1315
- const line074 = nn$33(mad.line074);
1307
+ const line068 = nn$35(mad.taxPayableBeforeDeduction);
1308
+ const line070 = nn$35(mad.line070);
1309
+ const line071 = nn$35(mad.line071);
1310
+ const line072 = nn$35(mad.line072);
1311
+ const line074 = nn$35(mad.line074);
1316
1312
  const room602 = raw(line068) - (line070 + line071 + line072 + line074);
1317
1313
  const itcCitcCap = Math.max(0, room602);
1318
1314
  const itc = computeItc(input.itc ?? {}, itcCitcCap, issues);
@@ -1378,26 +1374,26 @@ function schedule3Values(result) {
1378
1374
  }
1379
1375
  //#endregion
1380
1376
  //#region src/t2/at1/schedules/schedule4-foreign-investment-tax-credit.ts
1381
- const nn$32 = (v) => Math.max(0, v ?? 0);
1377
+ const nn$34 = (v) => Math.max(0, v ?? 0);
1382
1378
  /** Round to 3 decimal places, half-up — the precision the spec directs for D and G. */
1383
1379
  function round3(v) {
1384
1380
  return Math.round((v + Number.EPSILON) * 1e3) / 1e3;
1385
1381
  }
1386
1382
  function computeSchedule4(input) {
1387
1383
  const issues = [];
1388
- const albertaTaxableIncome = nn$32(input.albertaTaxableIncome);
1389
- const royaltyTaxDeduction = nn$32(input.royaltyTaxDeduction);
1384
+ const albertaTaxableIncome = nn$34(input.albertaTaxableIncome);
1385
+ const royaltyTaxDeduction = nn$34(input.royaltyTaxDeduction);
1390
1386
  const allocationFactor = input.allocationFactor ?? 0;
1391
- const basicAlbertaTax = nn$32(input.basicAlbertaTax);
1387
+ const basicAlbertaTax = nn$34(input.basicAlbertaTax);
1392
1388
  const denominator = (albertaTaxableIncome - royaltyTaxDeduction) * allocationFactor;
1393
1389
  const countries = input.countries.map((c) => {
1394
1390
  if (!c.country) issues.push("Alberta Schedule 4: a country code is required for each occurrence (004002).");
1395
- const netForeignInvestmentIncome = nn$32(c.netForeignInvestmentIncome);
1396
- const fedForeignTaxPaid = nn$32(c.fedForeignTaxPaid);
1397
- const fedIta2012Deduction = nn$32(c.fedIta2012Deduction);
1391
+ const netForeignInvestmentIncome = nn$34(c.netForeignInvestmentIncome);
1392
+ const fedForeignTaxPaid = nn$34(c.fedForeignTaxPaid);
1393
+ const fedIta2012Deduction = nn$34(c.fedIta2012Deduction);
1398
1394
  const albertaDeduction = Math.max(c.albertaActa82Deduction ?? fedIta2012Deduction, fedIta2012Deduction);
1399
1395
  const taxPaidNetOfDeduction = Math.max(0, fedForeignTaxPaid - albertaDeduction);
1400
- const federalNonBusinessForeignTaxCredit = nn$32(c.fedNonBusinessForeignTaxCredit);
1396
+ const federalNonBusinessForeignTaxCredit = nn$34(c.fedNonBusinessForeignTaxCredit);
1401
1397
  let incomeProrationAmount;
1402
1398
  if (denominator === 0) {
1403
1399
  incomeProrationAmount = 0;
@@ -1454,7 +1450,7 @@ function schedule4Values(result) {
1454
1450
  }
1455
1451
  //#endregion
1456
1452
  //#region src/t2/at1/schedules/schedule5-royalty-tax-deduction.ts
1457
- const nn$31 = (v) => Math.max(0, Math.round(v ?? 0));
1453
+ const nn$33 = (v) => Math.max(0, Math.round(v ?? 0));
1458
1454
  const num$2 = (v) => Math.round(v ?? 0);
1459
1455
  function processSuccessoredPool(entries, label, issues) {
1460
1456
  return (entries ?? []).map((e, i) => {
@@ -1462,9 +1458,9 @@ function processSuccessoredPool(entries, label, issues) {
1462
1458
  const hasAcquired = e.acquisitionAmount !== void 0;
1463
1459
  if (hasBrought && hasAcquired) issues.push(`Alberta Schedule 5: ${label} occurrence ${i + 1} (${e.vendorName}) has both a pool-brought-forward and an acquisition amount; the spec allows only one per occurrence. Using poolBroughtForward and ignoring acquisitionAmount.`);
1464
1460
  else if (!hasBrought && !hasAcquired) issues.push(`Alberta Schedule 5: ${label} occurrence ${i + 1} (${e.vendorName}) has neither a pool-brought-forward nor an acquisition amount; treating the pool base as zero.`);
1465
- const base = nn$31(hasBrought ? e.poolBroughtForward : e.acquisitionAmount);
1461
+ const base = nn$33(hasBrought ? e.poolBroughtForward : e.acquisitionAmount);
1466
1462
  const baseKind = hasBrought ? "broughtForward" : hasAcquired ? "acquired" : "unspecified";
1467
- const propertyIncome = nn$31(e.propertyIncome);
1463
+ const propertyIncome = nn$33(e.propertyIncome);
1468
1464
  const claim = Math.min(base, propertyIncome);
1469
1465
  return {
1470
1466
  vendorName: e.vendorName,
@@ -1479,11 +1475,11 @@ function processSuccessoredPool(entries, label, issues) {
1479
1475
  }
1480
1476
  function computeAlbertaSchedule5(input) {
1481
1477
  const issues = [];
1482
- const crownCharges = nn$31(input.crownChargesNetOfReimbursements);
1483
- const resourceAllowance = nn$31(input.albertaResourceAllowance ?? input.federalResourceAllowance);
1484
- const reimbursements = nn$31(input.reimbursementsForCrownCharges);
1485
- const predecessorTransfersTotal = (input.predecessorTransfers ?? []).reduce((s, t) => s + nn$31(t.amountTransferred), 0);
1486
- const attributedRoyaltyIncomeCarryForwardIn = nn$31(input.openingUnsuccessoredPoolBalance) + predecessorTransfersTotal;
1478
+ const crownCharges = nn$33(input.crownChargesNetOfReimbursements);
1479
+ const resourceAllowance = nn$33(input.albertaResourceAllowance ?? input.federalResourceAllowance);
1480
+ const reimbursements = nn$33(input.reimbursementsForCrownCharges);
1481
+ const predecessorTransfersTotal = (input.predecessorTransfers ?? []).reduce((s, t) => s + nn$33(t.amountTransferred), 0);
1482
+ const attributedRoyaltyIncomeCarryForwardIn = nn$33(input.openingUnsuccessoredPoolBalance) + predecessorTransfersTotal;
1487
1483
  const unsuccessoredPoolAvailable = crownCharges - resourceAllowance - reimbursements + attributedRoyaltyIncomeCarryForwardIn;
1488
1484
  const hasSuccessoredPools = input.hasSuccessoredPools ?? false;
1489
1485
  if (!hasSuccessoredPools && ((input.secondSuccessoredPools?.length ?? 0) > 0 || (input.firstSuccessoredPools?.length ?? 0) > 0)) issues.push("Alberta Schedule 5: hasSuccessoredPools (005200) is false, but successored pool occurrences were supplied. Per the spec, 005101-005140 must not exist when 005200 = 2 (No); the supplied occurrences were ignored.");
@@ -1496,7 +1492,7 @@ function computeAlbertaSchedule5(input) {
1496
1492
  const crtdMaxClaimable = Math.max(0, Math.min(unsuccessoredPoolAvailable, albertaTaxableIncome - successoredTotal));
1497
1493
  const crtdClaim = input.crtdAmountClaimed != null ? Math.max(0, Math.min(Math.round(input.crtdAmountClaimed), crtdMaxClaimable)) : crtdMaxClaimable;
1498
1494
  const poolAvailableCarryForward = unsuccessoredPoolAvailable - crtdClaim;
1499
- const transferredOnDisposal = nn$31(input.transferredOnDisposal);
1495
+ const transferredOnDisposal = nn$33(input.transferredOnDisposal);
1500
1496
  const uncappedTotal = crtdClaim + successoredTotal;
1501
1497
  const totalRoyaltyTaxDeduction = Math.max(0, Math.min(uncappedTotal, albertaTaxableIncome));
1502
1498
  if (totalRoyaltyTaxDeduction < uncappedTotal && uncappedTotal > albertaTaxableIncome) if (albertaTaxableIncome < 0) issues.push(`Alberta Schedule 5: Alberta taxable income before the deduction (AT1 line 062) is ${albertaTaxableIncome}, which is negative. AT1 line 064 is specified as "005016 + 005140, cannot exceed 000062" with no stated floor; this engine floors the combined deduction at zero rather than reporting a negative Royalty Tax Deduction. The successored-pool claims (005140 = ${successoredTotal}) are computed independently of line 062 and are NOT reduced by this cap — review manually if this scenario occurs.`);
@@ -1606,7 +1602,7 @@ function schedule5Values(result) {
1606
1602
  //#endregion
1607
1603
  //#region src/t2/at1/schedules/schedule6-royalty-tax-credit.ts
1608
1604
  const rd$1 = (v) => Math.round(v ?? 0);
1609
- const nn$30 = (v) => Math.max(0, Math.round(v ?? 0));
1605
+ const nn$32 = (v) => Math.max(0, Math.round(v ?? 0));
1610
1606
  const round4$1 = (v) => Math.round(v * 1e4) / 1e4;
1611
1607
  function computeWeightedAverageRate(quarters, issues) {
1612
1608
  if (quarters.length === 0) {
@@ -1622,11 +1618,11 @@ function computeWeightedAverageRate(quarters, issues) {
1622
1618
  return round4$1(weighted);
1623
1619
  }
1624
1620
  function resolveAllocations(allocations, pool, issues) {
1625
- const totalRequested = allocations.reduce((s, a) => s + nn$30(a.allocatedAmount), 0);
1621
+ const totalRequested = allocations.reduce((s, a) => s + nn$32(a.allocatedAmount), 0);
1626
1622
  if (totalRequested > pool) issues.push(`Alberta Schedule 6: the associated group allocated ${totalRequested} of a Crown Royalty Shelter pool of ${pool} (006034 occurrences exceed the $2,000,000 × (006028/365) limit). Allocations were capped in the order given — the group must agree a valid split.`);
1627
1623
  let remaining = pool;
1628
1624
  return allocations.map((a) => {
1629
- const requestedAmount = nn$30(a.allocatedAmount);
1625
+ const requestedAmount = nn$32(a.allocatedAmount);
1630
1626
  const allocatedAmount = Math.min(requestedAmount, remaining);
1631
1627
  remaining -= allocatedAmount;
1632
1628
  return {
@@ -1749,7 +1745,7 @@ function computeAlbertaSchedule6(input) {
1749
1745
  /** Signed whole-dollar rounding — no floor, several of these lines are marked "+/-". */
1750
1746
  const rd = (v) => Math.round(v ?? 0);
1751
1747
  /** Non-negative whole-dollar rounding, for the "+"-only lines. */
1752
- const nn$29 = (v) => Math.max(0, Math.round(v ?? 0));
1748
+ const nn$31 = (v) => Math.max(0, Math.round(v ?? 0));
1753
1749
  const round4 = (v) => Math.round(v * 1e4) / 1e4;
1754
1750
  function resolvePartnership(p, index, issues) {
1755
1751
  if (!p.name) issues.push(`Alberta Schedule 7: partnership row ${index + 1} has no name (007071 is mandatory for every PITI occurrence).`);
@@ -1758,9 +1754,9 @@ function resolvePartnership(p, index, issues) {
1758
1754
  name: p.name,
1759
1755
  interestPercent: round4(p.interestPercent),
1760
1756
  ...p.fiscalPeriodEnd !== void 0 ? { fiscalPeriodEnd: p.fiscalPeriodEnd } : {},
1761
- shareEligibleForCredit: nn$29(p.shareEligibleForCredit),
1762
- shareOtherRoyaltiesNotEligible: nn$29(p.shareOtherRoyaltiesNotEligible),
1763
- shareOtherCrownChargesEligibleForDeduction: nn$29(p.shareOtherCrownChargesEligibleForDeduction)
1757
+ shareEligibleForCredit: nn$31(p.shareEligibleForCredit),
1758
+ shareOtherRoyaltiesNotEligible: nn$31(p.shareOtherRoyaltiesNotEligible),
1759
+ shareOtherCrownChargesEligibleForDeduction: nn$31(p.shareOtherCrownChargesEligibleForDeduction)
1764
1760
  };
1765
1761
  }
1766
1762
  function resolveAdjustment(a, index, issues) {
@@ -1769,8 +1765,8 @@ function resolveAdjustment(a, index, issues) {
1769
1765
  return {
1770
1766
  ...a.priorProductionPeriodEnd !== void 0 ? { priorProductionPeriodEnd: a.priorProductionPeriodEnd } : {},
1771
1767
  ...a.sourceOfAdjustment !== void 0 ? { sourceOfAdjustment: a.sourceOfAdjustment } : {},
1772
- increase: nn$29(a.increase),
1773
- decrease: nn$29(a.decrease),
1768
+ increase: nn$31(a.increase),
1769
+ decrease: nn$31(a.decrease),
1774
1770
  adjustmentNotEligibleForCredit: rd(a.adjustmentNotEligibleForCredit)
1775
1771
  };
1776
1772
  }
@@ -1790,7 +1786,7 @@ function schedule7LineItemId(fieldId, occurrence = 1) {
1790
1786
  * "Schedule 7, line 061" and gives its formula in full, so it is filed here
1791
1787
  * under that citation rather than omitted for lack of a home row.
1792
1788
  */
1793
- function schedule7Values(result) {
1789
+ function schedule7Values$1(result) {
1794
1790
  const values = [];
1795
1791
  const put = (fieldId, value, occurrence = 1) => values.push({
1796
1792
  lineItemId: schedule7LineItemId(fieldId, occurrence),
@@ -1864,7 +1860,7 @@ function computeAlbertaSchedule7(input) {
1864
1860
  otherNonDeductibleCrownCharges = 0;
1865
1861
  }
1866
1862
  const crownLeaseRentalsCapitalized = rd(input.crownLeaseRentalsCapitalized);
1867
- let otherBalanceSheetDeduction = nn$29(input.otherBalanceSheetDeduction);
1863
+ let otherBalanceSheetDeduction = nn$31(input.otherBalanceSheetDeduction);
1868
1864
  if (!input.otherBalanceSheetDeductionName && otherBalanceSheetDeduction !== 0) {
1869
1865
  issues.push("Alberta Schedule 7: an amount was given for another balance sheet eligible deduction (007029) but no deduction was named (007027). The spec defaults 007029 to zero when no name is given; the amount was zeroed out.");
1870
1866
  otherBalanceSheetDeduction = 0;
@@ -1905,7 +1901,7 @@ function computeAlbertaSchedule7(input) {
1905
1901
  }
1906
1902
  //#endregion
1907
1903
  //#region src/t2/at1/schedules/schedule8-political-contributions.ts
1908
- const nn$28 = (v) => Math.max(0, Math.round(v ?? 0));
1904
+ const nn$30 = (v) => Math.max(0, Math.round(v ?? 0));
1909
1905
  function yearOf(dateIso) {
1910
1906
  if (!dateIso || dateIso.length < 4) return void 0;
1911
1907
  const y = Number(dateIso.slice(0, 4));
@@ -1930,12 +1926,12 @@ function computeSchedule8$1(input) {
1930
1926
  if (!c.dateOfDonation) issues.push(`Alberta Schedule 8: contribution #${i + 1} (${c.name || "unnamed"}) has no date of donation (008006) — the spec requires one for every receipted contribution.`);
1931
1927
  if (!c.receiptNumber) issues.push(`Alberta Schedule 8: contribution #${i + 1} (${c.name || "unnamed"}) has no official receipt number (008004).`);
1932
1928
  });
1933
- const partnershipContributionsTo2003 = nn$28(input.partnershipContributionsTo2003);
1934
- const partnershipContributionsFrom2004 = nn$28(input.partnershipContributionsFrom2004);
1935
- const totalDirect = contributions.reduce((sum, c) => sum + nn$28(c.amount), 0);
1936
- const directTo2003 = contributions.filter((c) => (yearOf(c.dateOfDonation) ?? 0) <= 2003).reduce((sum, c) => sum + nn$28(c.amount), 0);
1937
- const directFrom2004 = contributions.filter((c) => (yearOf(c.dateOfDonation) ?? 9999) >= 2004).reduce((sum, c) => sum + nn$28(c.amount), 0);
1938
- const directIn2004Only = contributions.filter((c) => yearOf(c.dateOfDonation) === 2004).reduce((sum, c) => sum + nn$28(c.amount), 0);
1929
+ const partnershipContributionsTo2003 = nn$30(input.partnershipContributionsTo2003);
1930
+ const partnershipContributionsFrom2004 = nn$30(input.partnershipContributionsFrom2004);
1931
+ const totalDirect = contributions.reduce((sum, c) => sum + nn$30(c.amount), 0);
1932
+ const directTo2003 = contributions.filter((c) => (yearOf(c.dateOfDonation) ?? 0) <= 2003).reduce((sum, c) => sum + nn$30(c.amount), 0);
1933
+ const directFrom2004 = contributions.filter((c) => (yearOf(c.dateOfDonation) ?? 9999) >= 2004).reduce((sum, c) => sum + nn$30(c.amount), 0);
1934
+ const directIn2004Only = contributions.filter((c) => yearOf(c.dateOfDonation) === 2004).reduce((sum, c) => sum + nn$30(c.amount), 0);
1939
1935
  const hasTo2003 = directTo2003 > 0 || partnershipContributionsTo2003 > 0;
1940
1936
  const hasFrom2004 = directFrom2004 > 0 || partnershipContributionsFrom2004 > 0;
1941
1937
  if (!hasTo2003 && !hasFrom2004) return {
@@ -2004,7 +2000,7 @@ function computeSchedule8$1(input) {
2004
2000
  * Does NOT emit jacket line 000074 (the actual tax credit) — that is a
2005
2001
  * jacket line, not a Schedule 8 line. Use `result.credit` for that.
2006
2002
  */
2007
- function schedule8Values(result) {
2003
+ function schedule8Values$1(result) {
2008
2004
  const values = [];
2009
2005
  result.contributions.forEach((c, i) => {
2010
2006
  const n = i + 1;
@@ -2032,7 +2028,7 @@ function schedule8Values(result) {
2032
2028
  }
2033
2029
  //#endregion
2034
2030
  //#region src/t2/at1/schedules/schedule9-sred-tax-credit.ts
2035
- const nn$27 = (v) => Math.max(0, Math.round(v ?? 0));
2031
+ const nn$29 = (v) => Math.max(0, Math.round(v ?? 0));
2036
2032
  /** Signed whole-dollar rounding, for fields the spec marks "+/-". */
2037
2033
  const signed = (v) => Math.round(v);
2038
2034
  /** 009120's flat rate — "lesser of line 009031 and 009108 X 10%". */
@@ -2051,17 +2047,17 @@ function computeSchedule9MaximumExpenditureLimit(daysInTaxYear = 365) {
2051
2047
  }
2052
2048
  function computeAlbertaSchedule9(input) {
2053
2049
  const issues = [];
2054
- const federalQualifiedExpenditures = nn$27(input.federalQualifiedExpenditures);
2055
- const albertaPortionOfExpenditures = nn$27(input.albertaPortionOfExpenditures);
2056
- const federalProxyAmountInAlbertaPortion = nn$27(input.federalProxyAmountInAlbertaPortion);
2057
- const albertaProxyAmount = nn$27(input.albertaProxyAmount);
2058
- const albertaCreditReducingFederalExpense = nn$27(input.albertaCreditReducingFederalExpense);
2059
- const priorYearFederalItcReceived = nn$27(input.priorYearFederalItcReceived);
2060
- const totalAlbertaExpendituresAllYears = nn$27(input.totalAlbertaExpendituresAllYears);
2061
- const totalFederalExpendituresAllYears = nn$27(input.totalFederalExpendituresAllYears);
2062
- const albertaPortionOfRepayments = nn$27(input.albertaPortionOfRepayments);
2063
- const disposalRecapture = nn$27(input.disposalRecapture);
2064
- const priorYearFederalItcAdjustment = nn$27(input.priorYearFederalItcAdjustment);
2050
+ const federalQualifiedExpenditures = nn$29(input.federalQualifiedExpenditures);
2051
+ const albertaPortionOfExpenditures = nn$29(input.albertaPortionOfExpenditures);
2052
+ const federalProxyAmountInAlbertaPortion = nn$29(input.federalProxyAmountInAlbertaPortion);
2053
+ const albertaProxyAmount = nn$29(input.albertaProxyAmount);
2054
+ const albertaCreditReducingFederalExpense = nn$29(input.albertaCreditReducingFederalExpense);
2055
+ const priorYearFederalItcReceived = nn$29(input.priorYearFederalItcReceived);
2056
+ const totalAlbertaExpendituresAllYears = nn$29(input.totalAlbertaExpendituresAllYears);
2057
+ const totalFederalExpendituresAllYears = nn$29(input.totalFederalExpendituresAllYears);
2058
+ const albertaPortionOfRepayments = nn$29(input.albertaPortionOfRepayments);
2059
+ const disposalRecapture = nn$29(input.disposalRecapture);
2060
+ const priorYearFederalItcAdjustment = nn$29(input.priorYearFederalItcAdjustment);
2065
2061
  if (albertaPortionOfExpenditures > federalQualifiedExpenditures) issues.push(`Alberta Schedule 9: the Alberta portion of expenditures (009005 = ${albertaPortionOfExpenditures}) exceeds the federal total (009003 = ${federalQualifiedExpenditures}). 009005 must not exceed 009003.`);
2066
2062
  const priorYearItcAlbertaPortion = totalFederalExpendituresAllYears > 0 ? Math.round(priorYearFederalItcReceived * totalAlbertaExpendituresAllYears / totalFederalExpendituresAllYears) : 0;
2067
2063
  if (totalFederalExpendituresAllYears === 0 && priorYearFederalItcReceived > 0) issues.push("Alberta Schedule 9: a prior-year federal ITC (009015) was supplied but total federal expenditures for those years (009019) is nil, so no Alberta portion (009023) could be allocated. Supply 009019 if a prior-year ITC allocation is expected.");
@@ -2075,7 +2071,7 @@ function computeAlbertaSchedule9(input) {
2075
2071
  if (isAssociated) if (input.allocatedExpenditureLimit === void 0) {
2076
2072
  issues.push("Alberta Schedule 9: the corporation is associated (009100 = 1) but no allocated expenditure limit (009102) was supplied. Complete the Allocation of the Maximum Expenditure Limit (page 3) and pass its result as allocatedExpenditureLimit — see allocateSchedule9ExpenditureLimit.");
2077
2073
  maximumExpenditureLimit = 0;
2078
- } else maximumExpenditureLimit = nn$27(input.allocatedExpenditureLimit);
2074
+ } else maximumExpenditureLimit = nn$29(input.allocatedExpenditureLimit);
2079
2075
  else maximumExpenditureLimit = nonAssociatedMaximumExpenditureLimit;
2080
2076
  if (input.taxationYearEnd !== void 0 && input.taxationYearEnd > "2019-12-31") issues.push(`Alberta Schedule 9: the taxation year end (${input.taxationYearEnd}) falls after ${ALBERTA_SRED_EXPENDITURE_CUTOFF}. The Alberta SR&ED Tax Credit may not be claimed for expenditures carried out in Alberta after that date — confirm albertaPortionOfExpenditures (009005) excludes any post-cutoff spending.`);
2081
2077
  const netCredit = Math.round(Math.min(eligibleExpenditures, maximumExpenditureLimit) * ALBERTA_SRED_TAX_CREDIT_RATE) - disposalRecapture - priorYearFederalItcAdjustment;
@@ -2114,7 +2110,7 @@ function allocateSchedule9ExpenditureLimit(daysInLongestYear, requested) {
2114
2110
  const days = Math.max(0, Math.min(daysInLongestYear, 366));
2115
2111
  const maximumExpenditureLimit = computeSchedule9MaximumExpenditureLimit(days);
2116
2112
  const members = requested.map((m) => {
2117
- const requestedAmount = nn$27(m.allocated);
2113
+ const requestedAmount = nn$29(m.allocated);
2118
2114
  if (requestedAmount > maximumExpenditureLimit) issues.push(`Alberta Schedule 9: ${m.name} was allocated ${requestedAmount}, exceeding the maximum expenditure limit of ${maximumExpenditureLimit} (009240 cannot exceed $4,000,000 x 009206/365). Capped at ${maximumExpenditureLimit}.`);
2119
2115
  return {
2120
2116
  name: m.name,
@@ -2358,7 +2354,7 @@ function schedule9Values(result, group) {
2358
2354
  *
2359
2355
  * Whole dollars, pure functions, no I/O.
2360
2356
  */
2361
- const nn$26 = (v) => Math.max(0, v ?? 0);
2357
+ const nn$28 = (v) => Math.max(0, v ?? 0);
2362
2358
  const num$1 = (v) => v ?? 0;
2363
2359
  const round$1 = (v) => Math.round(v);
2364
2360
  /** `override ?? federal`, tracking whether an Alberta-specific figure was actually entered. */
@@ -2862,7 +2858,7 @@ function computeCfreRegular(entries) {
2862
2858
  const partA = Math.max(CCOGPE_CLAIM_RATE * linear * pool, Math.min(CDE_CLAIM_RATE * linear * pool, foreignResourceIncome, sumForeignResourceIncome));
2863
2859
  const remainder = Math.max(0, pool - partA);
2864
2860
  if (e.globalForeignResourceLimit === void 0) issues.push(`Schedule 15 CFRE regular, country ${e.federal.countryCode} (015293): the "global foreign resource limit for the year designated for that country" (source lines 15703-15711) was not supplied — this quantity has no source anywhere in this engine, so the B-component of the claim is treated as 0 (conservative — the pool may be under-claimed relative to what the corporation is actually entitled to).`);
2865
- const partB = Math.min(remainder, nn$26(e.globalForeignResourceLimit));
2861
+ const partB = Math.min(remainder, nn$28(e.globalForeignResourceLimit));
2866
2862
  claim = claimUpToCap$1(e.claimed, partA + partB, issues, `Schedule 15 CFRE regular, country ${e.federal.countryCode} (015293)`);
2867
2863
  }
2868
2864
  const closingBalance = pool - claim;
@@ -3294,15 +3290,15 @@ function schedule15Values(result) {
3294
3290
  function iegT661SourceLine(taxationYearEnd) {
3295
3291
  return taxationYearEnd >= "2024-12-16" ? "557" : "559";
3296
3292
  }
3297
- const nn$25 = (v) => Math.round(v ?? 0);
3293
+ const nn$27 = (v) => Math.round(v ?? 0);
3298
3294
  /** Line 031 = 005 − 007 + 009 + 011 + 025. Every term but 005 defaults to nil. */
3299
3295
  function computeIegEligibleExpenditures(input) {
3300
- const federalAmount = nn$25(input.federalAmount);
3301
- const albertaPortion = nn$25(input.albertaPortion);
3302
- const federalProxyAmount = nn$25(input.federalProxyAmount);
3303
- const albertaProxyAmount = nn$25(input.albertaProxyAmount);
3304
- const iegReducingFederalExpenditure = nn$25(input.iegReducingFederalExpenditure);
3305
- const repaymentOrContractPayment = nn$25(input.repaymentOrContractPayment);
3296
+ const federalAmount = nn$27(input.federalAmount);
3297
+ const albertaPortion = nn$27(input.albertaPortion);
3298
+ const federalProxyAmount = nn$27(input.federalProxyAmount);
3299
+ const albertaProxyAmount = nn$27(input.albertaProxyAmount);
3300
+ const iegReducingFederalExpenditure = nn$27(input.iegReducingFederalExpenditure);
3301
+ const repaymentOrContractPayment = nn$27(input.repaymentOrContractPayment);
3306
3302
  return {
3307
3303
  federalAmount,
3308
3304
  albertaPortion,
@@ -3522,7 +3518,7 @@ function computeIeg(input) {
3522
3518
  *
3523
3519
  * Whole dollars, pure.
3524
3520
  */
3525
- const nn$24 = (v) => Math.max(0, Math.round(v ?? 0));
3521
+ const nn$26 = (v) => Math.max(0, Math.round(v ?? 0));
3526
3522
  /**
3527
3523
  * The group's taxable capital and base level of spending, from every associated
3528
3524
  * member's own figures.
@@ -3533,11 +3529,11 @@ const nn$24 = (v) => Math.max(0, Math.round(v ?? 0));
3533
3529
  function computeIegGroupFigures(members, priorYears = IEG_2024.PRIOR_YEARS) {
3534
3530
  const issues = [];
3535
3531
  const detail = members.map((m) => {
3536
- const priorYearAlbertaExpenditures = (m.priorYearAlbertaExpenditures ?? []).map(nn$24);
3532
+ const priorYearAlbertaExpenditures = (m.priorYearAlbertaExpenditures ?? []).map(nn$26);
3537
3533
  if (priorYearAlbertaExpenditures.length > priorYears) issues.push(`Alberta Schedule 29: ${m.name} supplied ${priorYearAlbertaExpenditures.length} prior-year expenditure figures, but the base level of spending averages the prior ${priorYears} years. Every figure supplied was included, which raises the base — check that only the prior ${priorYears} taxation years were given.`);
3538
3534
  return {
3539
3535
  name: m.name,
3540
- taxableCapital: nn$24(m.taxableCapital),
3536
+ taxableCapital: nn$26(m.taxableCapital),
3541
3537
  priorYearAlbertaExpenditures,
3542
3538
  priorYearTotal: priorYearAlbertaExpenditures.reduce((a, b) => a + b, 0)
3543
3539
  };
@@ -3564,11 +3560,11 @@ function computeIegGroupFigures(members, priorYears = IEG_2024.PRIOR_YEARS) {
3564
3560
  function allocateIegExpenditureLimit(groupExpenditureLimit, requested) {
3565
3561
  const issues = [];
3566
3562
  const limit = Math.max(0, Math.round(groupExpenditureLimit));
3567
- const totalRequested = requested.reduce((s, a) => s + nn$24(a.allocated), 0);
3563
+ const totalRequested = requested.reduce((s, a) => s + nn$26(a.allocated), 0);
3568
3564
  if (totalRequested > limit) issues.push(`Alberta Schedule 29: the associated group allocated ${totalRequested} of an expenditure limit of ${limit}. The allocation cannot exceed the limit; members were capped in the order given and the group must agree a valid split.`);
3569
3565
  let remaining = limit;
3570
3566
  const allocations = requested.map((a) => {
3571
- const allocated = Math.min(nn$24(a.allocated), remaining);
3567
+ const allocated = Math.min(nn$26(a.allocated), remaining);
3572
3568
  remaining -= allocated;
3573
3569
  return {
3574
3570
  name: a.name,
@@ -3602,10 +3598,10 @@ function allocateIegEvenly(groupExpenditureLimit, names) {
3602
3598
  })));
3603
3599
  }
3604
3600
  function computeAgreementMember(m, index, issues) {
3605
- const allocatedExpenditureLimit = nn$24(m.allocatedExpenditureLimit);
3606
- const currentYearExpenditures = nn$24(m.currentYearExpenditures);
3607
- const priorYear1 = nn$24(m.priorYear1);
3608
- const priorYear2 = nn$24(m.priorYear2);
3601
+ const allocatedExpenditureLimit = nn$26(m.allocatedExpenditureLimit);
3602
+ const currentYearExpenditures = nn$26(m.currentYearExpenditures);
3603
+ const priorYear1 = nn$26(m.priorYear1);
3604
+ const priorYear2 = nn$26(m.priorYear2);
3609
3605
  const base = Math.round((priorYear1 + priorYear2) / 2);
3610
3606
  const individualMaximumAllowedAmount = currentYearExpenditures - base;
3611
3607
  const days = Math.max(0, Math.min(m.daysInTaxYear ?? 365, 366));
@@ -3624,7 +3620,7 @@ function computeAgreementMember(m, index, issues) {
3624
3620
  currentYearExpenditures,
3625
3621
  priorYear1,
3626
3622
  priorYear2,
3627
- taxableCapitalPriorYear: nn$24(m.taxableCapitalPriorYear),
3623
+ taxableCapitalPriorYear: nn$26(m.taxableCapitalPriorYear),
3628
3624
  hasAlbertaPermanentEstablishment,
3629
3625
  individualMaximumAllowedAmount,
3630
3626
  allocatedAllowedAmount
@@ -3752,10 +3748,10 @@ function computeAlbertaReturn(input) {
3752
3748
  const schedulePayloads = [];
3753
3749
  const sched = input.schedules;
3754
3750
  if (sched?.smallBusinessDeduction) {
3755
- schedulePayloads.push(schedule1Values(sched.smallBusinessDeduction));
3751
+ schedulePayloads.push(schedule1Values$1(sched.smallBusinessDeduction));
3756
3752
  issues.push(...sched.smallBusinessDeduction.result.issues);
3757
3753
  }
3758
- if (sched?.allocation) schedulePayloads.push(schedule2Values(sched.allocation));
3754
+ if (sched?.allocation) schedulePayloads.push(schedule2Values$1(sched.allocation));
3759
3755
  if (sched?.otherDeductionsCredits) {
3760
3756
  schedulePayloads.push(schedule3Values(sched.otherDeductionsCredits));
3761
3757
  issues.push(...sched.otherDeductionsCredits.issues);
@@ -3773,11 +3769,11 @@ function computeAlbertaReturn(input) {
3773
3769
  issues.push(...sched.royaltyTaxCredit.issues);
3774
3770
  }
3775
3771
  if (sched?.royaltySupplemental) {
3776
- schedulePayloads.push(schedule7Values(sched.royaltySupplemental));
3772
+ schedulePayloads.push(schedule7Values$1(sched.royaltySupplemental));
3777
3773
  issues.push(...sched.royaltySupplemental.issues);
3778
3774
  }
3779
3775
  if (sched?.politicalContributions) {
3780
- schedulePayloads.push(schedule8Values(sched.politicalContributions));
3776
+ schedulePayloads.push(schedule8Values$1(sched.politicalContributions));
3781
3777
  issues.push(...sched.politicalContributions.issues);
3782
3778
  }
3783
3779
  if (sched?.sredTaxCredit) {
@@ -3812,7 +3808,7 @@ function computeAlbertaReturn(input) {
3812
3808
  issues.push(...sched.donations.gifts?.issues ?? []);
3813
3809
  }
3814
3810
  if (sched?.losses) {
3815
- schedulePayloads.push(schedule21Values(sched.losses));
3811
+ schedulePayloads.push(schedule21Values$1(sched.losses));
3816
3812
  issues.push(...sched.losses.limitedPartnershipLosses?.issues ?? []);
3817
3813
  issues.push(...sched.losses.nonCapitalByYearOfOrigin?.issues ?? []);
3818
3814
  issues.push(...sched.losses.otherLossesByYearOfOrigin?.issues ?? []);
@@ -4648,6 +4644,128 @@ function toRsiHeader(data) {
4648
4644
  };
4649
4645
  }
4650
4646
  //#endregion
4647
+ //#region src/t2/at1/filing/at1-transmitter-validation.ts
4648
+ /**
4649
+ * §3.2.1.18 — the characters TRA accepts anywhere on the AT1 RSI.
4650
+ *
4651
+ * Latin letters, digits, space, the listed punctuation, and the accented Latin
4652
+ * set. The accented characters are given in the spec as a literal glyph list
4653
+ * that `pdftotext` cannot round-trip, so they are expressed here as the
4654
+ * Latin-1 supplement range they come from (À-ÿ) rather than transcribed
4655
+ * one by one from mojibake.
4656
+ */
4657
+ const ALLOWABLE = /^[A-Za-z0-9 \-'/&*#!@+=?$%()_;:",.<>~`^{}[\]|\\À-ÿ]*$/;
4658
+ /** Canadian provinces and territories, per the spec's province table. */
4659
+ const CA_PROVINCES = /* @__PURE__ */ new Set([
4660
+ "AB",
4661
+ "BC",
4662
+ "MB",
4663
+ "NB",
4664
+ "NL",
4665
+ "NS",
4666
+ "NT",
4667
+ "NU",
4668
+ "ON",
4669
+ "PE",
4670
+ "QC",
4671
+ "SK",
4672
+ "YT"
4673
+ ]);
4674
+ /** A9A 9A9, with or without the space. */
4675
+ const CA_POSTAL = /^[A-Za-z]\d[A-Za-z][ ]?\d[A-Za-z]\d$/;
4676
+ /** Five digits, or nine as 12345-6789 / 123456789. */
4677
+ const US_ZIP = /^\d{5}(-?\d{4})?$/;
4678
+ /** Deliberately permissive: TRA checks format and length, not deliverability. */
4679
+ const EMAIL = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
4680
+ /**
4681
+ * The dev placeholder certification code. Blocked because TRA validates the
4682
+ * SCC against its own registry (20010), so `AB0000` cannot succeed — unlike
4683
+ * the serial number, where the rule is presence only (20013) and `SR_DEV` is
4684
+ * a legitimate, if unlovely, value. Only rules TRA actually applies are
4685
+ * enforced here; being stricter than TRA would refuse returns TRA accepts.
4686
+ */
4687
+ const PLACEHOLDER_CERT_CODE = "AB0000";
4688
+ function validateAt1Transmitter(info) {
4689
+ const defects = [];
4690
+ const add = (field, traCode, message) => defects.push({
4691
+ field,
4692
+ traCode,
4693
+ message
4694
+ });
4695
+ /** Present, within `max` characters, and drawn from the allowable set. */
4696
+ const text = (value, field, traCode, label, max, required = true) => {
4697
+ const v = (value ?? "").trim();
4698
+ if (v === "") {
4699
+ if (required) add(field, traCode, `${label} must be provided.`);
4700
+ return;
4701
+ }
4702
+ if (v.length > max) add(field, traCode, `${label} must not exceed ${max} characters (is ${v.length}).`);
4703
+ if (!ALLOWABLE.test(v)) add(field, "20145", `${label} contains a character TRA does not accept — see the allowable set in specification §3.2.1.18.`);
4704
+ };
4705
+ if (!info.softwareCertCode?.trim()) add("softwareCertCode", "20010", "The TRA-issued Software Certification Code must be provided.");
4706
+ else if (info.softwareCertCode.trim() === PLACEHOLDER_CERT_CODE) add("softwareCertCode", "20010", `The Software Certification Code is still the development placeholder "${info.softwareCertCode}". Set TRA_SOFTWARE_CERT_CODE to the code TRA issued at certification.`);
4707
+ if (!info.webServiceVersion?.trim()) add("webServiceVersion", "20011", "Web Service Version must be provided.");
4708
+ if (!info.softwareVersion?.trim()) add("softwareVersion", "20012", "Software Version must be provided.");
4709
+ if (!info.serialNumber?.trim()) add("serialNumber", "20013", "Software Serial Number must be provided.");
4710
+ const isThirdParty = info.thirdPartyIndicator === "1";
4711
+ if (info.thirdPartyIndicator !== "1" && info.thirdPartyIndicator !== "2") add("thirdPartyIndicator", "20065", "Third Party Service Provider Indicator must be \"1\" (yes) or \"2\" (no).");
4712
+ text(info.legalName, "legalName", "20070", "Organization Legal Name", 70, isThirdParty);
4713
+ if (isThirdParty && !info.organizationType) add("organizationType", "20080", "Type of Organization must be CORPORATION, PARTNERSHIP or INDIVIDUAL when filing as a third party.");
4714
+ const c = info.contact;
4715
+ text(c?.firstName, "contact.firstName", "20085", "Contact First Name", 35);
4716
+ text(c?.lastName, "contact.lastName", "20090", "Contact Last Name", 35);
4717
+ text(c?.position, "contact.position", "20095", "Position", 40);
4718
+ const phone = (c?.phone ?? "").trim();
4719
+ const phoneDigits = phone.replace(/\D/g, "");
4720
+ if (phone === "") add("contact.phone", "20100", "Phone Number must be provided.");
4721
+ else if (phoneDigits.length < 10 || phoneDigits.length > 15) add("contact.phone", "20100", `Phone Number must be 10 to 15 digits (is ${phoneDigits.length}).`);
4722
+ else if (new Set(phoneDigits).size === 1) add("contact.phone", "20100", `Phone Number "${phone}" is a placeholder, not a number TRA will accept. Set TRANSMITTER_PHONE to the filer's real phone number.`);
4723
+ const email = (c?.email ?? "").trim();
4724
+ if (email === "") add("contact.email", "20110", "Email Address must be provided.");
4725
+ else if (email.length > 50) add("contact.email", "20110", `Email Address must not exceed 50 characters (is ${email.length}).`);
4726
+ else if (!EMAIL.test(email)) add("contact.email", "20110", `Email Address "${email}" is not a valid format.`);
4727
+ const a = info.address;
4728
+ if (isThirdParty && !a) add("address", "20115", "A third-party filer must supply a mailing address.");
4729
+ else if (a) {
4730
+ text(a.street, "address.street", "20115", "Address Line 1", 35);
4731
+ if (a.line2?.trim()) {
4732
+ text(a.line2, "address.line2", "20120", "Address Line 2", 35, false);
4733
+ if (a.line2.trim().toUpperCase() === (a.street ?? "").trim().toUpperCase()) add("address.line2", "20120", "Address Line 2 cannot repeat Address Line 1.");
4734
+ }
4735
+ text(a.city, "address.city", "20125", "City", 35);
4736
+ const country = (a.country ?? "").trim().toUpperCase();
4737
+ const province = (a.province ?? "").trim().toUpperCase();
4738
+ const postal = (a.postalCode ?? "").trim();
4739
+ if (country === "") add("address.country", "20140", "Country must be provided.");
4740
+ else if (!/^[A-Z]{2}$/.test(country)) add("address.country", "20140", `Country must be a two-character code accepted by Canada Post (is "${a.country}").`);
4741
+ if (country === "CA" || country === "US") {
4742
+ if (province === "") add("address.province", "20130", `Province must be provided when the country is ${country}.`);
4743
+ else if (country === "CA" && !CA_PROVINCES.has(province)) add("address.province", "20130", `"${a.province}" is not a Canadian province or territory code.`);
4744
+ else if (country === "US" && !/^[A-Z]{2}$/.test(province)) add("address.province", "20130", `"${a.province}" is not a two-letter US state code.`);
4745
+ if (postal === "") add("address.postalCode", "20135", `Postal Code must be provided when the country is ${country}.`);
4746
+ else if (country === "CA" && !CA_POSTAL.test(postal)) add("address.postalCode", "20135", `Postal Code "${postal}" is not in Canadian A9A 9A9 format.`);
4747
+ else if (country === "US" && !US_ZIP.test(postal)) add("address.postalCode", "20135", `Postal Code "${postal}" is not a 5- or 9-digit US ZIP.`);
4748
+ } else if (country !== "") {
4749
+ if (province !== "") add("address.province", "20130", "Province must be blank when the country is not CA or US.");
4750
+ if (postal !== "") add("address.postalCode", "20135", "Postal Code must be blank when the country is not CA or US.");
4751
+ }
4752
+ }
4753
+ return defects;
4754
+ }
4755
+ var At1TransmitterInvalidError = class extends Error {
4756
+ defects;
4757
+ constructor(defects) {
4758
+ super(`AT1 cannot be transmitted: the filer (transmitter) configuration would be rejected by TRA — ` + defects.map((d) => `${d.field} [TRA ${d.traCode}]: ${d.message}`).join(" ") + " These are deployment settings, not anything on the return.");
4759
+ this.name = "At1TransmitterInvalidError";
4760
+ this.defects = defects;
4761
+ }
4762
+ };
4763
+ /** Throw unless every filer-detail rule TRA applies is satisfied. */
4764
+ function assertAt1TransmitterValid(info) {
4765
+ const defects = validateAt1Transmitter(info);
4766
+ if (defects.length > 0) throw new At1TransmitterInvalidError(defects);
4767
+ }
4768
+ //#endregion
4651
4769
  //#region src/t2/schedules/loss-carryback.ts
4652
4770
  var LossCarrybackError = class extends Error {
4653
4771
  constructor(message) {
@@ -5675,33 +5793,33 @@ function computeAlbertaSchedule13(input) {
5675
5793
  }
5676
5794
  //#endregion
5677
5795
  //#region src/t2/at1/schedules/schedule16-sred.ts
5678
- const nn$23 = (v) => Math.max(0, Math.round(v ?? 0));
5796
+ const nn$25 = (v) => Math.max(0, Math.round(v ?? 0));
5679
5797
  /**
5680
5798
  * Line 016004 for federal T661 versions from 2008 onward: lines 429 + 431 + 432.
5681
5799
  * The 2007-and-earlier form used a single line 430, which can be passed to
5682
5800
  * `assistance` directly.
5683
5801
  */
5684
5802
  function assistanceFrom(line429, line431, line432) {
5685
- return nn$23(line429) + nn$23(line431) + nn$23(line432);
5803
+ return nn$25(line429) + nn$25(line431) + nn$25(line432);
5686
5804
  }
5687
5805
  function computeAlbertaSchedule16(input) {
5688
5806
  const issues = [];
5689
- const currentYearExpenditures = nn$23(input.currentYearExpenditures);
5690
- const assistance = nn$23(input.assistance);
5691
- const priorYearItcClaimed = nn$23(input.priorYearItcClaimed);
5692
- const saleOfCapitalAssetsAndOther = nn$23(input.saleOfCapitalAssetsAndOther);
5693
- const assistanceRepayments = nn$23(input.assistanceRepayments);
5694
- const openingPoolBalance = nn$23(input.openingPoolBalance);
5695
- const poolTransferredIn = nn$23(input.poolTransferredIn);
5696
- const priorYearItcRecaptured = nn$23(input.priorYearItcRecaptured);
5807
+ const currentYearExpenditures = nn$25(input.currentYearExpenditures);
5808
+ const assistance = nn$25(input.assistance);
5809
+ const priorYearItcClaimed = nn$25(input.priorYearItcClaimed);
5810
+ const saleOfCapitalAssetsAndOther = nn$25(input.saleOfCapitalAssetsAndOther);
5811
+ const assistanceRepayments = nn$25(input.assistanceRepayments);
5812
+ const openingPoolBalance = nn$25(input.openingPoolBalance);
5813
+ const poolTransferredIn = nn$25(input.poolTransferredIn);
5814
+ const priorYearItcRecaptured = nn$25(input.priorYearItcRecaptured);
5697
5815
  const totalDeductions = assistance + priorYearItcClaimed + saleOfCapitalAssetsAndOther;
5698
5816
  const totalAdditions = assistanceRepayments + openingPoolBalance + poolTransferredIn + priorYearItcRecaptured;
5699
5817
  const subtotal = currentYearExpenditures - totalDeductions + totalAdditions;
5700
5818
  const deductionAvailable = Math.max(0, subtotal);
5701
5819
  if (subtotal < 0) issues.push(`Alberta Schedule 16: assistance, prior-year credits and asset sales exceed the SR&ED expenditures by ${-subtotal}. No pool deduction is available and the pool carries forward at nil.`);
5702
5820
  const amountClaimed = input.amountClaimed != null ? Math.max(0, Math.min(Math.round(input.amountClaimed), deductionAvailable)) : deductionAvailable;
5703
- const openingDiffers = input.federalOpeningPoolBalance !== void 0 && nn$23(input.federalOpeningPoolBalance) !== openingPoolBalance;
5704
- const claimDiffers = input.federalAmountClaimed !== void 0 && nn$23(input.federalAmountClaimed) !== amountClaimed;
5821
+ const openingDiffers = input.federalOpeningPoolBalance !== void 0 && nn$25(input.federalOpeningPoolBalance) !== openingPoolBalance;
5822
+ const claimDiffers = input.federalAmountClaimed !== void 0 && nn$25(input.federalAmountClaimed) !== amountClaimed;
5705
5823
  const formRequired = openingDiffers || claimDiffers;
5706
5824
  const formPermitted = (input.reportsDifferentAlbertaIncome ?? false) || (input.electsDifferentDiscretionaryAmounts ?? false);
5707
5825
  if (formRequired && !formPermitted) issues.push("Alberta Schedule 16: the SR&ED opening pool balance or the deduction claimed differs from federal, so the form is required, but neither line 000060 nor 000061 is set to 1. Set line 000061 and file a Schedule 12.");
@@ -5829,10 +5947,10 @@ const AT1_RESERVE_LINES = Object.freeze({
5829
5947
  closing: "017077"
5830
5948
  }
5831
5949
  });
5832
- const nn$22 = (v) => Math.max(0, Math.round(v ?? 0));
5950
+ const nn$24 = (v) => Math.max(0, Math.round(v ?? 0));
5833
5951
  /** `undefined` falls back to federal; a `0` is a real Alberta override. */
5834
5952
  function pick(alberta, federal) {
5835
- return nn$22(alberta !== void 0 ? alberta : federal);
5953
+ return nn$24(alberta !== void 0 ? alberta : federal);
5836
5954
  }
5837
5955
  function computeAlbertaSchedule17(input) {
5838
5956
  const issues = [];
@@ -5935,7 +6053,7 @@ const AT1_DISPOSITION_CATEGORIES = [
5935
6053
  * Line 018076 then applies the inclusion rate once, to the total.
5936
6054
  */
5937
6055
  const SECTION_34_2_GROSS_UP = 2;
5938
- const nn$21 = (v) => Math.max(0, v ?? 0);
6056
+ const nn$23 = (v) => Math.max(0, v ?? 0);
5939
6057
  const num = (v) => v ?? 0;
5940
6058
  /** Merge one category: an omitted Alberta field takes federal; a `0` overrides. */
5941
6059
  function mergeCategory(federal, alberta) {
@@ -5946,9 +6064,9 @@ function mergeCategory(federal, alberta) {
5946
6064
  const o = f.outlays;
5947
6065
  return {
5948
6066
  totals: {
5949
- proceeds: nn$21(p),
6067
+ proceeds: nn$23(p),
5950
6068
  acb: num(c),
5951
- outlays: nn$21(o)
6069
+ outlays: nn$23(o)
5952
6070
  },
5953
6071
  differs: a.proceeds !== void 0 || a.acb !== void 0
5954
6072
  };
@@ -5970,17 +6088,17 @@ function computeAlbertaSchedule18(input) {
5970
6088
  const gainOf = (c) => categories.find((x) => x.category === c)?.gain ?? 0;
5971
6089
  const personalUseGain = gainOf("personalUse");
5972
6090
  const listedPersonalGain = gainOf("listedPersonal");
5973
- const lppLossesApplied = listedPersonalGain > 0 ? Math.min(nn$21(input.unappliedLppLosses), listedPersonalGain) : 0;
6091
+ const lppLossesApplied = listedPersonalGain > 0 ? Math.min(nn$23(input.unappliedLppLosses), listedPersonalGain) : 0;
5974
6092
  const ordinaryGains = gainOf("shares") + gainOf("realEstate") + gainOf("bonds") + gainOf("otherProperties");
5975
6093
  const lppComponent = listedPersonalGain >= 0 ? listedPersonalGain - lppLossesApplied : 0;
5976
- const reserveOpening = nn$21(input.albertaReserveOpening ?? input.federalReserveOpening);
5977
- const reserveClosing = nn$21(input.albertaReserveClosing ?? input.federalReserveClosing);
5978
- const netBeforeInclusionRate = ordinaryGains + personalUseGain + lppComponent + nn$21(input.capitalGainsDividends) + reserveOpening - reserveClosing - nn$21(input.gainOnDonatedSecurities) - nn$21(input.gainOnDonatedEcologicalLand) + Math.min(nn$21(input.exemptionThreshold), nn$21(input.capitalGainsFromActualProperty)) + 2 * nn$21(input.section342TaxableCapitalGains) - 2 * nn$21(input.section342AllowableCapitalLosses);
6094
+ const reserveOpening = nn$23(input.albertaReserveOpening ?? input.federalReserveOpening);
6095
+ const reserveClosing = nn$23(input.albertaReserveClosing ?? input.federalReserveClosing);
6096
+ const netBeforeInclusionRate = ordinaryGains + personalUseGain + lppComponent + nn$23(input.capitalGainsDividends) + reserveOpening - reserveClosing - nn$23(input.gainOnDonatedSecurities) - nn$23(input.gainOnDonatedEcologicalLand) + Math.min(nn$23(input.exemptionThreshold), nn$23(input.capitalGainsFromActualProperty)) + 2 * nn$23(input.section342TaxableCapitalGains) - 2 * nn$23(input.section342AllowableCapitalLosses);
5979
6097
  const taxableCapitalGain = Math.max(0, Math.round(inclusionRate * netBeforeInclusionRate));
5980
6098
  const abil = (input.abilEntries ?? []).map((e) => ({
5981
6099
  name: e.name,
5982
6100
  kind: e.kind,
5983
- businessInvestmentLoss: nn$21(e.proceeds) - (nn$21(e.acb) + nn$21(e.outlays))
6101
+ businessInvestmentLoss: nn$23(e.proceeds) - (nn$23(e.acb) + nn$23(e.outlays))
5984
6102
  }));
5985
6103
  const totalBil = abil.reduce((s, e) => s + Math.min(0, e.businessInvestmentLoss), 0);
5986
6104
  const allowableBusinessInvestmentLoss = -Math.round(inclusionRate * -totalBil);
@@ -6011,7 +6129,7 @@ function computeAlbertaSchedule18(input) {
6011
6129
  }
6012
6130
  //#endregion
6013
6131
  //#region src/t2/at1/schedules/schedule20-donations.ts
6014
- const nn$20 = (v) => Math.max(0, v ?? 0);
6132
+ const nn$22 = (v) => Math.max(0, v ?? 0);
6015
6133
  /**
6016
6134
  * Alberta figures default to federal, per-field. A `0` entered on the Alberta
6017
6135
  * side is a real override and must not be swallowed by the default, so the
@@ -6036,11 +6154,11 @@ function resolveCarryforward(federal, alberta) {
6036
6154
  return out;
6037
6155
  }
6038
6156
  function computeSchedule20(input) {
6039
- const openingBalance = nn$20(input.openingBalance);
6040
- const expired = nn$20(input.expired);
6041
- const transferredIn = nn$20(input.transferredIn);
6042
- const currentYearGifts = nn$20(input.currentYearGifts);
6043
- const acquisitionOfControlAdjustment = nn$20(input.acquisitionOfControlAdjustment);
6157
+ const openingBalance = nn$22(input.openingBalance);
6158
+ const expired = nn$22(input.expired);
6159
+ const transferredIn = nn$22(input.transferredIn);
6160
+ const currentYearGifts = nn$22(input.currentYearGifts);
6161
+ const acquisitionOfControlAdjustment = nn$22(input.acquisitionOfControlAdjustment);
6044
6162
  const availableBeforeClaim = Math.max(0, openingBalance - expired + transferredIn + currentYearGifts - acquisitionOfControlAdjustment);
6045
6163
  const issues = [];
6046
6164
  let ceiling;
@@ -6111,12 +6229,12 @@ function computeSchedule20(input) {
6111
6229
  const AT1_DONATION_INCOME_RATE = .75;
6112
6230
  /** Gains and recapture on gifted capital property add back at 25%. */
6113
6231
  const AT1_DONATION_GAIN_RATE = .25;
6114
- const nn$19 = (v) => Math.max(0, v ?? 0);
6232
+ const nn$21 = (v) => Math.max(0, v ?? 0);
6115
6233
  function computeDonationMaximum(input) {
6116
6234
  const incomeComponent = Math.round(AT1_DONATION_INCOME_RATE * Math.max(0, input.albertaNetIncomeForTax));
6117
- const lesserOfProceedsAndCost = Math.min(nn$19(input.proceedsNetOfOutlays), nn$19(input.capitalCost));
6118
- const allowableRecapture = Math.min(nn$19(input.recaptureOnGifts), lesserOfProceedsAndCost);
6119
- const gainsComponent = Math.round(AT1_DONATION_GAIN_RATE * (nn$19(input.taxableCapitalGainsOnGifts) + nn$19(input.deemedGiftGains) + allowableRecapture));
6235
+ const lesserOfProceedsAndCost = Math.min(nn$21(input.proceedsNetOfOutlays), nn$21(input.capitalCost));
6236
+ const allowableRecapture = Math.min(nn$21(input.recaptureOnGifts), lesserOfProceedsAndCost);
6237
+ const gainsComponent = Math.round(AT1_DONATION_GAIN_RATE * (nn$21(input.taxableCapitalGainsOnGifts) + nn$21(input.deemedGiftGains) + allowableRecapture));
6120
6238
  return {
6121
6239
  incomeComponent,
6122
6240
  lesserOfProceedsAndCost,
@@ -6209,6 +6327,37 @@ function computeLossSchedule(input) {
6209
6327
  };
6210
6328
  }
6211
6329
  //#endregion
6330
+ //#region src/t2/at1/schedules/schedule21-rife.ts
6331
+ function computeRifeContinuity(input = {}) {
6332
+ const openingBalance = Math.max(0, input.openingBalance ?? 0);
6333
+ const transferredOnWindUp = Math.max(0, input.transferredOnWindUp ?? 0);
6334
+ const acquisitionOfControlAdjustment = Math.max(0, input.acquisitionOfControlAdjustment ?? 0);
6335
+ const currentYearRife = Math.max(0, input.currentYearRife ?? 0);
6336
+ const excessCapacity = Math.max(0, input.excessCapacity ?? 0);
6337
+ const receivedCapacity = Math.max(0, input.receivedCapacity ?? 0);
6338
+ const rifeFromPreviousYears = Math.max(0, openingBalance + transferredOnWindUp - acquisitionOfControlAdjustment);
6339
+ const totalCapacity = excessCapacity + receivedCapacity;
6340
+ const maxDeductible = Math.max(0, Math.min(rifeFromPreviousYears, totalCapacity));
6341
+ const issues = [];
6342
+ const requestedClaim = Math.max(0, input.deductedClaim ?? maxDeductible);
6343
+ if (requestedClaim > maxDeductible) issues.push(`Line 240 (RIFE deducted, ${requestedClaim}) cannot exceed line 350 (${maxDeductible}). Capped at ${maxDeductible}.`);
6344
+ const deducted = Math.min(requestedClaim, maxDeductible);
6345
+ return {
6346
+ openingBalance,
6347
+ transferredOnWindUp,
6348
+ acquisitionOfControlAdjustment,
6349
+ currentYearRife,
6350
+ rifeFromPreviousYears,
6351
+ excessCapacity,
6352
+ receivedCapacity,
6353
+ totalCapacity,
6354
+ maxDeductible,
6355
+ deducted,
6356
+ closingBalance: openingBalance + transferredOnWindUp - acquisitionOfControlAdjustment + currentYearRife - deducted,
6357
+ issues
6358
+ };
6359
+ }
6360
+ //#endregion
6212
6361
  //#region src/t2/at1/schedules/schedule21-year-of-origin.ts
6213
6362
  function sumRows(rows) {
6214
6363
  const sum = (f) => rows.reduce((s, r) => s + f(r), 0);
@@ -6458,6 +6607,241 @@ const T2_CERTIFICATION_FIXTURES = [
6458
6607
  }
6459
6608
  ];
6460
6609
  //#endregion
6610
+ //#region src/t2/filing/t2-schedule-line-items.ts
6611
+ /**
6612
+ * Federal T2 — the per-schedule, per-line breakdown of a computed return.
6613
+ *
6614
+ * Alberta has had this since the AT1 filing path was built
6615
+ * (`at1-schedule-line-items.ts`): every schedule's result turned into a flat
6616
+ * list of `{lineItemId, value}` pairs, persisted with the computed return, and
6617
+ * read back by the paper Form Views so a preparer sees the actual figure
6618
+ * against the actual line. Federal had nothing equivalent. Its computed return
6619
+ * carried only summary fields under symbolic names — `netIncomeForTax`,
6620
+ * `ccaClaimed` — which no form can be keyed by, so every federal paper view
6621
+ * rendered "not available" against every computed line of every schedule.
6622
+ *
6623
+ * ── The rule this file follows, and why it is strict ────────────────────────
6624
+ *
6625
+ * A value is emitted ONLY where the line it belongs on is recorded in code:
6626
+ * carried in the data (Schedule 1's own `Schedule1Line.line`), exported as a
6627
+ * named constant (`SCHEDULE_8_CCA_LINE`), or stated in the result type's own
6628
+ * doc comment. Nothing here is a line number typed from memory or inferred from
6629
+ * a caption that looks close.
6630
+ *
6631
+ * The reason is the failure this repository keeps hitting: a figure filed under
6632
+ * the wrong line is not a missing figure, it is a WRONG return, and it looks
6633
+ * completely correct on screen. Schedule 4's jacket references claimed lines 150
6634
+ * and 250 where the form prints 130 and 225; Schedule 33's own result type said
6635
+ * line 690 where the form has 790. Both were plausible, both were wrong, and
6636
+ * neither was caught by a type.
6637
+ *
6638
+ * So a schedule whose result has no recorded line mapping produces NO entry
6639
+ * rather than a guessed one, and the paper view keeps saying "not available"
6640
+ * for it. That is the honest state, and it is visibly incomplete, which is what
6641
+ * makes it safe to extend one verified line at a time.
6642
+ *
6643
+ * ── Identifier shape ────────────────────────────────────────────────────────
6644
+ *
6645
+ * Six characters: the three-digit CRA line, then a three-digit occurrence.
6646
+ * Alberta uses nine (`SSSFFFOOO`) because a TRA line item id names its schedule
6647
+ * too; a federal line number is already unique across the whole return, so the
6648
+ * schedule is carried once on the envelope instead of repeated on every row.
6649
+ * The trailing occurrence exists for the grid forms, where one line number
6650
+ * repeats down a column — Schedule 8 has one row per capital cost allowance
6651
+ * class, all of them line 217.
6652
+ */
6653
+ /** `LLLOOO` — three-digit CRA line, three-digit occurrence. Occurrence is 1-based. */
6654
+ function t2LineItemId(line, occurrence = 1) {
6655
+ return `${line}${String(occurrence).padStart(3, "0")}`;
6656
+ }
6657
+ /**
6658
+ * Split a federal line item id back into its line and occurrence.
6659
+ *
6660
+ * Returns `undefined` for anything that is not six digits, so a caller handed
6661
+ * an Alberta nine-digit id (or a malformed one) drops it rather than reading
6662
+ * the first three characters as a line number and displaying a figure against
6663
+ * a line it does not belong to.
6664
+ */
6665
+ function parseT2LineItemId(lineItemId) {
6666
+ if (!/^\d{6}$/.test(lineItemId)) return void 0;
6667
+ return {
6668
+ line: lineItemId.slice(0, 3),
6669
+ occurrence: Number(lineItemId.slice(3, 6))
6670
+ };
6671
+ }
6672
+ /** Drop entries with no value, so an absent figure stays absent rather than becoming 0. */
6673
+ const present = (values) => values.filter((v) => v !== null);
6674
+ /** One value, or `null` when the figure was not computed. */
6675
+ const at = (line, value, occurrence = 1) => value === void 0 ? null : {
6676
+ lineItemId: t2LineItemId(line, occurrence),
6677
+ value
6678
+ };
6679
+ /**
6680
+ * Schedule 1 — the only federal schedule that needs no line table here.
6681
+ *
6682
+ * `Schedule1Line` carries its own `line`, and has since the schedule was built,
6683
+ * precisely because "a reconciling item recorded only as a description with an
6684
+ * amount has nowhere to go on the wire". Reading it back out is the whole job.
6685
+ *
6686
+ * A line may legitimately repeat: the form provides open rows (135, 295, 395,
6687
+ * 495) for items it does not name, and a return can carry several. Those get
6688
+ * successive occurrences rather than being summed, so the paper view can show
6689
+ * each on its own row. A line with no number is skipped — `assertSchedule1Fileable`
6690
+ * is what refuses the return over it, not this.
6691
+ */
6692
+ function schedule1Values(r) {
6693
+ const values = [];
6694
+ const seen = /* @__PURE__ */ new Map();
6695
+ for (const l of [...r.additions, ...r.deductions]) {
6696
+ if (!l.line) continue;
6697
+ const occurrence = (seen.get(l.line) ?? 0) + 1;
6698
+ seen.set(l.line, occurrence);
6699
+ values.push({
6700
+ lineItemId: t2LineItemId(l.line, occurrence),
6701
+ value: l.amount
6702
+ });
6703
+ }
6704
+ values.push({
6705
+ lineItemId: t2LineItemId("500"),
6706
+ value: r.totalAdditions
6707
+ });
6708
+ values.push({
6709
+ lineItemId: t2LineItemId("510"),
6710
+ value: r.totalDeductions
6711
+ });
6712
+ return {
6713
+ scheduleId: "T2SCH1",
6714
+ values
6715
+ };
6716
+ }
6717
+ /** Schedule 2 — the donation claim. Only line 210 is a named constant. */
6718
+ function schedule2Values(r) {
6719
+ return {
6720
+ scheduleId: "T2SCH2",
6721
+ values: present([at("210", r.donationsClaimed)])
6722
+ };
6723
+ }
6724
+ /**
6725
+ * Schedule 7 — the adjusted aggregate investment income that grinds the
6726
+ * business limit. Line 745 is exported by the form module; the rest of Part 2's
6727
+ * working lines are not recorded anywhere, so they are not emitted.
6728
+ */
6729
+ function schedule7Values(r) {
6730
+ return {
6731
+ scheduleId: "T2SCH7",
6732
+ values: present([at("745", r.adjustedAggregateInvestmentIncome)])
6733
+ };
6734
+ }
6735
+ /**
6736
+ * Schedule 8 — capital cost allowance, one occurrence per class.
6737
+ *
6738
+ * Only the three lines the form module exports are emitted: recapture (213),
6739
+ * terminal loss (215) and the claim (217). The grid's other twenty columns are
6740
+ * either intermediate arithmetic the form shows without numbering, or columns
6741
+ * whose number this package has not recorded — see `SCHEDULE_8_COLUMNS`.
6742
+ */
6743
+ function schedule8Values(r) {
6744
+ const values = [];
6745
+ r.classes.forEach((c, i) => {
6746
+ const occurrence = i + 1;
6747
+ values.push(...present([
6748
+ at("213", c.recapture, occurrence),
6749
+ at("215", c.terminalLoss, occurrence),
6750
+ at("217", c.ccaClaimed, occurrence)
6751
+ ]));
6752
+ });
6753
+ return {
6754
+ scheduleId: "T2SCH8",
6755
+ values
6756
+ };
6757
+ }
6758
+ /**
6759
+ * Schedule 21 — the two foreign tax credits.
6760
+ *
6761
+ * These land on different jacket lines (632 non-business, 636 business) and the
6762
+ * form module's own doc comment warns that swapping them "is not cosmetic".
6763
+ * Both come from named constants for exactly that reason.
6764
+ */
6765
+ function schedule21Values(r) {
6766
+ return {
6767
+ scheduleId: "T2SCH21",
6768
+ values: present([at("180", r.nonBusinessFtc), at("280", r.businessFtc)])
6769
+ };
6770
+ }
6771
+ /**
6772
+ * Schedule 33 — taxable capital.
6773
+ *
6774
+ * The four figures whose lines the result type states: capital (190), the
6775
+ * investment allowance (490), taxable capital (500) and taxable capital
6776
+ * employed in Canada (790, from the form module's constant — the result type's
6777
+ * comment used to say 690, which is not a line of this form).
6778
+ */
6779
+ function schedule33Values(r) {
6780
+ return {
6781
+ scheduleId: "T2SCH33",
6782
+ values: present([
6783
+ at("190", r.capital),
6784
+ at("490", r.investmentAllowance),
6785
+ at("500", r.taxableCapital),
6786
+ at("790", r.taxableCapitalEmployedInCanada)
6787
+ ])
6788
+ };
6789
+ }
6790
+ /** Schedule 53 — the closing general rate income pool. */
6791
+ function schedule53Values(r) {
6792
+ return {
6793
+ scheduleId: "T2SCH53",
6794
+ values: present([at("590", r.closingGrip)])
6795
+ };
6796
+ }
6797
+ /**
6798
+ * Schedule 55 — Part III.1 tax.
6799
+ *
6800
+ * The result type states "20% of amount B (s.185.1(1)(a)) — line 190 / line
6801
+ * 290". Two lines for one figure because the form splits by corporation type:
6802
+ * Part 1 (line 190) for CCPCs and deposit insurance corporations, Part 2 (line
6803
+ * 290) for everyone else. Nothing in the result says which part applied, so the
6804
+ * base tax is emitted against BOTH and the paper view shows it under whichever
6805
+ * part the reader is looking at, rather than this file picking one and being
6806
+ * wrong for half of all filers.
6807
+ */
6808
+ function schedule55Values(r) {
6809
+ return {
6810
+ scheduleId: "T2SCH55",
6811
+ values: present([at("190", r.baseTax), at("290", r.baseTax)])
6812
+ };
6813
+ }
6814
+ /** The jacket — the three headline figures the form module names. */
6815
+ function jacketValues(r) {
6816
+ return {
6817
+ scheduleId: "T2",
6818
+ values: present([
6819
+ at("300", r.netIncomeForTax),
6820
+ at("360", r.taxableIncome),
6821
+ at("770", r.totalFederalTax)
6822
+ ])
6823
+ };
6824
+ }
6825
+ /**
6826
+ * Every schedule's filed line items for one computed federal return.
6827
+ *
6828
+ * A schedule that was not computed is ABSENT, not present and empty — the same
6829
+ * rule Alberta's assembler follows. An empty schedule on a return says "this
6830
+ * schedule was completed and everything on it is nil", which is a different
6831
+ * statement from "this schedule does not apply", and only one of them is true.
6832
+ */
6833
+ function federalSchedulePayloads(r) {
6834
+ const payloads = [jacketValues(r), schedule1Values(r.schedule1)];
6835
+ if (r.donations) payloads.push(schedule2Values(r.donations));
6836
+ if (r.adjustedAggregateInvestmentIncomeSchedule) payloads.push(schedule7Values(r.adjustedAggregateInvestmentIncomeSchedule));
6837
+ if (r.cca) payloads.push(schedule8Values(r.cca));
6838
+ if (r.foreignTaxCredit) payloads.push(schedule21Values(r.foreignTaxCredit));
6839
+ if (r.taxableCapitalSchedule) payloads.push(schedule33Values(r.taxableCapitalSchedule));
6840
+ if (r.grip) payloads.push(schedule53Values(r.grip));
6841
+ if (r.partIII1) payloads.push(schedule55Values(r.partIII1));
6842
+ return payloads.filter((p) => p.values.length > 0);
6843
+ }
6844
+ //#endregion
6461
6845
  //#region src/t2/rates/corporate-rates.ts
6462
6846
  /**
6463
6847
  * Federal corporate-tax rate table — the Part I rate stack, the small-business
@@ -6560,12 +6944,12 @@ function computeSBD(input, rates = CORP_TAX_2024) {
6560
6944
  sbdAmount: Math.round(rates.SBD_RATE * sbdIncome)
6561
6945
  };
6562
6946
  }
6563
- const nn$18 = (v) => v ?? 0;
6947
+ const nn$20 = (v) => v ?? 0;
6564
6948
  function computeAggregateInvestmentIncome(input) {
6565
- const amountA = nn$18(input.allowableCapitalLosses) + nn$18(input.netCapitalLossesClaimed);
6566
- const amountB = Math.max(0, nn$18(input.taxableCapitalGains) - amountA);
6567
- const amountC = nn$18(input.exemptIncome) + nn$18(input.agriInvestFundReceived) + nn$18(input.taxableDividendsDeductible) + nn$18(input.trustPropertyIncome);
6568
- const amountD = nn$18(input.incomeFromProperty) - amountC;
6949
+ const amountA = nn$20(input.allowableCapitalLosses) + nn$20(input.netCapitalLossesClaimed);
6950
+ const amountB = Math.max(0, nn$20(input.taxableCapitalGains) - amountA);
6951
+ const amountC = nn$20(input.exemptIncome) + nn$20(input.agriInvestFundReceived) + nn$20(input.taxableDividendsDeductible) + nn$20(input.trustPropertyIncome);
6952
+ const amountD = nn$20(input.incomeFromProperty) - amountC;
6569
6953
  const amountE = amountB + amountD;
6570
6954
  return {
6571
6955
  amountA,
@@ -6573,20 +6957,20 @@ function computeAggregateInvestmentIncome(input) {
6573
6957
  amountC,
6574
6958
  amountD,
6575
6959
  amountE,
6576
- aggregateInvestmentIncome: Math.max(0, amountE - nn$18(input.lossesFromProperty))
6960
+ aggregateInvestmentIncome: Math.max(0, amountE - nn$20(input.lossesFromProperty))
6577
6961
  };
6578
6962
  }
6579
6963
  function computeAdjustedAggregateInvestmentIncome(input) {
6580
- const amountF = Math.max(0, nn$18(input.taxableCapitalGains) - nn$18(input.allowableCapitalLosses));
6581
- const amountG = nn$18(input.exemptIncome) + nn$18(input.agriInvestFundReceived) + nn$18(input.dividendsFromConnectedCorporations) + nn$18(input.trustPropertyIncome);
6582
- const amountH = nn$18(input.incomeFromProperty) - amountG;
6964
+ const amountF = Math.max(0, nn$20(input.taxableCapitalGains) - nn$20(input.allowableCapitalLosses));
6965
+ const amountG = nn$20(input.exemptIncome) + nn$20(input.agriInvestFundReceived) + nn$20(input.dividendsFromConnectedCorporations) + nn$20(input.trustPropertyIncome);
6966
+ const amountH = nn$20(input.incomeFromProperty) - amountG;
6583
6967
  const amountI = amountF + amountH;
6584
6968
  return {
6585
6969
  amountF,
6586
6970
  amountG,
6587
6971
  amountH,
6588
6972
  amountI,
6589
- adjustedAggregateInvestmentIncome: Math.max(0, amountI - nn$18(input.lossesFromProperty) + nn$18(input.subsection91_4Deduction))
6973
+ adjustedAggregateInvestmentIncome: Math.max(0, amountI - nn$20(input.lossesFromProperty) + nn$20(input.subsection91_4Deduction))
6590
6974
  };
6591
6975
  }
6592
6976
  //#endregion
@@ -6827,6 +7211,165 @@ function isSchedule5Province(code) {
6827
7211
  return code in PROVINCE_RATES_2024;
6828
7212
  }
6829
7213
  //#endregion
7214
+ //#region src/t2/schedules/eifel-adjusted-taxable-income.ts
7215
+ /**
7216
+ * ITA subsection 18.2(1) — **adjusted taxable income**, the base the EIFEL
7217
+ * ceiling is computed on.
7218
+ *
7219
+ * `eifel-limitation.ts` took this as a required input because deriving it
7220
+ * partially would produce a plausible figure from an incomplete definition. This
7221
+ * derives it, and is explicit about the components it does and does not cover.
7222
+ *
7223
+ * ── What it is ──────────────────────────────────────────────────────────────
7224
+ *
7225
+ * An EBITDA-like measure, built from taxable income by adding back the things the
7226
+ * regime is measuring against and removing the things that would double-count.
7227
+ *
7228
+ * ATI = A + B − C
7229
+ *
7230
+ * A = D − E the income base
7231
+ * B the ADD-BACKS
7232
+ * C the REDUCTIONS
7233
+ *
7234
+ * **The add-backs include the interest and financing expenses themselves.** That
7235
+ * is the point of the measure and the thing to hold on to: the ceiling is a
7236
+ * percentage of income computed *before* the very expenses being limited, so a
7237
+ * corporation cannot shrink its own ceiling by borrowing more.
7238
+ *
7239
+ * ── A — the income base (D − E) ─────────────────────────────────────────────
7240
+ *
7241
+ * **D** is taxable income for the year, determined **without regard to** s.18.2(2)
7242
+ * itself, paragraphs 12(1)(l.2) and 111(1)(a.1), and clause 95(2)(f.11)(ii)(D) —
7243
+ * a non-resident uses taxable income earned in Canada on the same basis. The
7244
+ * circularity is deliberate: the limitation cannot be an input to its own base.
7245
+ *
7246
+ * **E** subtracts the year's non-capital loss on the same basis, any amount
7247
+ * claimed under paragraph 111(1)(a) that did not actually reduce taxable income,
7248
+ * and a controlled-foreign-affiliate component (`T × U ÷ V`).
7249
+ *
7250
+ * ── B — the add-backs ───────────────────────────────────────────────────────
7251
+ *
7252
+ * (a) interest and financing expenses for the year
7253
+ * (b) capital cost allowance and resource deductions — paragraph 20(1)(a),
7254
+ * 59.1(a) and subsections 66(4), 66.1(2)/(3), 66.2(2), 66.21(4), 66.4(2),
7255
+ * 66.7(1)-(5)
7256
+ * (c) terminal losses — subsection 20(16)
7257
+ * (d) the taxpayer's share of a partnership's 20(1)(a) and 20(16) deductions
7258
+ * (e) the portion of a paragraph 111(1)(e) limited-partnership-loss claim
7259
+ * attributable to those amounts
7260
+ *
7261
+ * ── C — the reductions ──────────────────────────────────────────────────────
7262
+ *
7263
+ * (a) interest and financing revenues
7264
+ * (b) recapture — subsection 13(1)
7265
+ * (c) the taxpayer's share of a partnership's 13(1) inclusion
7266
+ * (d) resource inclusions — subsections 59(1), 59(3.2), paragraph 59.1(b)
7267
+ * (e) for a corporation, a grossed-up foreign tax credit amount:
7268
+ * **100/28** of what would be deductible under s.126(1), and
7269
+ * the s.126(2) amounts times the relevant factor
7270
+ *
7271
+ * ── Not modelled ────────────────────────────────────────────────────────────
7272
+ *
7273
+ * The trust variant of C(e), and the later paragraphs of B and C dealing with
7274
+ * foreign affiliate income and exempt interest. Each is available as an explicit
7275
+ * `otherAdditions` / `otherReductions` input rather than silently omitted, so a
7276
+ * preparer with one of those amounts can still arrive at the right figure and the
7277
+ * engine does not pretend the definition is shorter than it is.
7278
+ *
7279
+ * Source: `research/sources/legislation/ITA-section-18.2-EIFEL.txt`.
7280
+ *
7281
+ * Pure, whole dollars.
7282
+ */
7283
+ /** C(e)(i) — s.126(1) amounts are grossed up by 100/28. */
7284
+ const FOREIGN_TAX_CREDIT_GROSS_UP = 100 / 28;
7285
+ const nn$19 = (v) => Math.max(0, Math.round(v ?? 0));
7286
+ function computeAdjustedTaxableIncome(input) {
7287
+ const issues = [];
7288
+ const e = nn$19(input.nonCapitalLossForYear) + nn$19(input.lossClaimNotReducingTaxableIncome) + nn$19(input.foreignAccrualPropertyLossComponent);
7289
+ const incomeBase = Math.round(input.taxableIncome) - e;
7290
+ const totalAdditions = nn$19(input.interestAndFinancingExpenses) + nn$19(input.capitalCostAllowance) + nn$19(input.resourceDeductions) + nn$19(input.terminalLoss) + nn$19(input.partnershipCapitalAndTerminalShare) + nn$19(input.limitedPartnershipLossPortion) + nn$19(input.partVI1TaxDeduction) + nn$19(input.lossPortionDerivedFromIfe) + nn$19(input.exemptIfeActivityLoss) + nn$19(input.otherAdditions);
7291
+ const totalReductions = nn$19(input.interestAndFinancingRevenues) + nn$19(input.recapture) + nn$19(input.partnershipRecaptureShare) + nn$19(input.resourceInclusions) + Math.round(FOREIGN_TAX_CREDIT_GROSS_UP * nn$19(input.section126_1ForeignTaxCredits)) + nn$19(input.section126_2GrossedUp) + nn$19(input.exemptIfeActivityIncome) + nn$19(input.otherReductions);
7292
+ const adjustedTaxableIncome = incomeBase + totalAdditions - totalReductions;
7293
+ if (adjustedTaxableIncome < 0) issues.push(`EIFEL: adjusted taxable income is negative (${adjustedTaxableIncome}), so the ceiling is nil and every interest and financing expense is denied. Check that the loss and add-back figures are complete before filing on that basis.`);
7294
+ if (input.interestAndFinancingExpenses === void 0) issues.push("EIFEL: no interest and financing expenses were added back to adjusted taxable income. They are paragraph (a) of the add-backs, and omitting them understates the ceiling — which denies more expense than the rules require.");
7295
+ return {
7296
+ incomeBase,
7297
+ totalAdditions,
7298
+ totalReductions,
7299
+ adjustedTaxableIncome,
7300
+ issues
7301
+ };
7302
+ }
7303
+ //#endregion
7304
+ //#region src/t2/schedules/eifel-capacity.ts
7305
+ const nn$18 = (v) => Math.max(0, Math.round(v ?? 0));
7306
+ /**
7307
+ * Part 2O on its own — the total of lines 159 to 162.
7308
+ *
7309
+ * Exported separately because of the order the form imposes: line 159 is the
7310
+ * denial from Part 2L, which cannot be computed until Parts 2G-2J have supplied
7311
+ * `excessReceivedCapacity` and `absorbedCapacity` to Part 2K. A caller running
7312
+ * the whole chain therefore computes capacity, then the limitation, then calls
7313
+ * this — rather than computing capacity twice.
7314
+ */
7315
+ function computeRifeUnderSubsection111_8(input) {
7316
+ return nn$18(input.excessInterestAndFinancingExpenses) + nn$18(input.partnershipIfeAddBack) + nn$18(input.clause95FapiAmountI) + nn$18(input.clause95FapiAmountII);
7317
+ }
7318
+ function computeEifelCapacity(input) {
7319
+ const issues = [];
7320
+ const ati = Math.round(input.adjustedTaxableIncome);
7321
+ const atiFloored = Math.max(0, ati);
7322
+ const ife = nn$18(input.interestAndFinancingExpenses);
7323
+ const ifr = nn$18(input.interestAndFinancingRevenues);
7324
+ const ratio = input.ratioOfPermissibleExpenses;
7325
+ const usedGroupRatio = input.hasGroupRatioElection === true;
7326
+ const receivedCapacity = (input.receivedCapacity ?? []).reduce((s, r) => s + nn$18(r.amount), 0);
7327
+ const permittedAmount = usedGroupRatio ? 0 : Math.round(atiFloored * ratio);
7328
+ const revenueOverExpense = usedGroupRatio ? 0 : Math.max(0, ifr - ife);
7329
+ const negativeAtiAbsolute = usedGroupRatio ? 0 : ati < 0 ? Math.abs(ati) : 0;
7330
+ const negativeAtiOffset = Math.min(revenueOverExpense, negativeAtiAbsolute);
7331
+ const negativeAtiOffsetAtRatio = Math.round(negativeAtiOffset * ratio);
7332
+ const revenueCapacity = usedGroupRatio ? 0 : Math.max(0, ifr - negativeAtiOffsetAtRatio);
7333
+ const totalCapacityBeforeExpenses = permittedAmount + revenueCapacity;
7334
+ const excessCapacityBeforeRife = usedGroupRatio ? 0 : Math.max(0, totalCapacityBeforeExpenses - ife);
7335
+ const rifeFromPreviousYears = nn$18(input.rifeFromPreviousYears);
7336
+ const rifeCapacityAvailable = excessCapacityBeforeRife + receivedCapacity;
7337
+ const rifeDeductible = Math.min(rifeFromPreviousYears, rifeCapacityAvailable);
7338
+ const excessCapacityForYear = Math.max(0, excessCapacityBeforeRife - rifeDeductible);
7339
+ const vintages = input.priorYearExcessCapacity ?? [];
7340
+ for (const v of vintages) if (v.yearsAgo < 1 || v.yearsAgo > 3) issues.push(`EIFEL: an excess-capacity vintage was supplied for ${v.yearsAgo} year(s) ago, but Schedule 130 Part 2I only carries the three immediately preceding years. It was ignored.`);
7341
+ const priorYearUnusedCapacity = vintages.filter((v) => v.yearsAgo >= 1 && v.yearsAgo <= 3).reduce((s, v) => s + Math.max(0, nn$18(v.excessCapacity) - nn$18(v.previouslyTransferred) - nn$18(v.previouslyAbsorbed)), 0);
7342
+ const cumulativeUnusedExcessCapacityBeforeAbsorption = priorYearUnusedCapacity + excessCapacityForYear;
7343
+ const absorbedShelter = (usedGroupRatio ? nn$18(input.groupRatioAmount) : Math.round(atiFloored * ratio)) + ifr;
7344
+ const absorbedRoom = Math.max(0, ife - absorbedShelter);
7345
+ const absorbedCapacity = Math.min(cumulativeUnusedExcessCapacityBeforeAbsorption, absorbedRoom);
7346
+ const cumulativeUnusedExcessCapacity = Math.max(0, cumulativeUnusedExcessCapacityBeforeAbsorption - absorbedCapacity);
7347
+ const excessReceivedCapacity = Math.max(0, receivedCapacity - rifeDeductible);
7348
+ const rifeForYear = computeRifeUnderSubsection111_8(input);
7349
+ if (usedGroupRatio && input.groupRatioAmount === void 0) issues.push("EIFEL: a group ratio election under subsection 18.21(2) was declared but no allocated group ratio amount was supplied, so absorbed capacity was computed with nil group ratio shelter — which absorbs more capacity than the election allows.");
7350
+ return {
7351
+ receivedCapacity,
7352
+ permittedAmount,
7353
+ revenueOverExpense,
7354
+ negativeAtiAbsolute,
7355
+ negativeAtiOffset,
7356
+ negativeAtiOffsetAtRatio,
7357
+ revenueCapacity,
7358
+ totalCapacityBeforeExpenses,
7359
+ excessCapacityBeforeRife,
7360
+ excessCapacityForYear,
7361
+ rifeCapacityAvailable,
7362
+ rifeDeductible,
7363
+ priorYearUnusedCapacity,
7364
+ cumulativeUnusedExcessCapacityBeforeAbsorption,
7365
+ cumulativeUnusedExcessCapacity,
7366
+ absorbedCapacity,
7367
+ excessReceivedCapacity,
7368
+ rifeForYear,
7369
+ issues
7370
+ };
7371
+ }
7372
+ //#endregion
6830
7373
  //#region src/t2/schedules/eifel-excluded-entity.ts
6831
7374
  /**
6832
7375
  * EIFEL — excessive interest and financing expenses limitation (s.18.2, 18.21).
@@ -6888,7 +7431,7 @@ function assessEifel(input, thresholds) {
6888
7431
  if (input.domesticExceptionApplies === true) return exclude("domestic");
6889
7432
  const issues = [];
6890
7433
  if (ife == null) issues.push("EIFEL: net interest and financing expenses were not provided, and the small-CCPC exception does not apply. The excluded-entity status cannot be established, so the return cannot be filed.");
6891
- else issues.push(`EIFEL: the corporation is not an excluded entity (net interest and financing expenses of ${ife} exceed the de minimis threshold and no other exception applies). The interest restriction under s.18.2 is required and is not computed by this engine refer this return to a qualified practitioner.`);
7434
+ else issues.push(`EIFEL: the corporation is not an excluded entity (net interest and financing expenses of ${ife} exceed the de minimis threshold and no other exception applies). The restriction under s.18.2 is computed — Schedule 130 Parts 2F-2L — but from figures that must be supplied rather than derived (gross IFE and IFR, received capacity, prior-year excess capacity, any group ratio amount), and several parts of the schedule are not modelled at all: exempt IFE, capitalized IFE, the partnership and controlled-foreign-affiliate components, and capacity transfers under s.18.2(4). Have this return reviewed by a qualified practitioner before filing.`);
6892
7435
  return {
6893
7436
  inForce: true,
6894
7437
  isExcludedEntity: false,
@@ -6898,40 +7441,323 @@ function assessEifel(input, thresholds) {
6898
7441
  };
6899
7442
  }
6900
7443
  //#endregion
6901
- //#region src/t2/schedules/part-vi-1-deduction.ts
6902
- const PART_VI_1_DEDUCTION_BANDS = [
6903
- {
6904
- from: "0000-01-01",
6905
- multiple: 3
6906
- },
6907
- {
6908
- from: "2010-01-01",
6909
- multiple: 3.2
6910
- },
6911
- {
6912
- from: "2012-01-01",
6913
- multiple: 3.5
6914
- }
6915
- ];
6916
- function utcDay$1(iso) {
6917
- return Date.parse(`${iso.slice(0, 10)}T00:00:00Z`);
7444
+ //#region src/t2/schedules/eifel-ife.ts
7445
+ const nn$17 = (v) => Math.max(0, Math.round(v ?? 0));
7446
+ const sum = (rows, pick) => rows.reduce((s, r) => s + pick(r), 0);
7447
+ function computeExemptIfe(rows) {
7448
+ return {
7449
+ totalExemptIfe: sum(rows, (r) => nn$17(r.ifeIncurred)),
7450
+ incomeFromExemptActivities: sum(rows, (r) => nn$17(r.incomeFromFundedActivities)),
7451
+ lossFromExemptActivities: sum(rows, (r) => nn$17(r.lossFromFundedActivities))
7452
+ };
6918
7453
  }
6919
- /** The multiple in force for a taxation year ending on `taxYearEnd`. */
6920
- function partVI1DeductionMultiple(taxYearEnd, bands = PART_VI_1_DEDUCTION_BANDS) {
6921
- const end = utcDay$1(taxYearEnd);
6922
- if (Number.isNaN(end)) return 0;
6923
- let multiple = 0;
6924
- for (const band of [...bands].sort((a, b) => utcDay$1(a.from) - utcDay$1(b.from))) if (end >= utcDay$1(band.from)) multiple = band.multiple;
6925
- return multiple;
7454
+ function computeBorrowings(rows) {
7455
+ return {
7456
+ interestPaidOrPayable: sum(rows, (r) => nn$17(r.interestPaidOrPayable)),
7457
+ fundingCostAmounts: sum(rows, (r) => nn$17(r.fundingCostAmounts)),
7458
+ costReducingAmounts: sum(rows, (r) => nn$17(r.costReducingAmounts))
7459
+ };
6926
7460
  }
6927
- /**
6928
- * The paragraph 110(1)(k) deduction.
6929
- *
6930
- * An unreadable year end yields nil and says so, rather than defaulting to the
6931
- * current multiple — guessing the year would misstate taxable income, and this
6932
- * deduction is large relative to the tax it follows.
6933
- */
6934
- function computePartVI1Deduction(partVI1Tax, taxYearEnd, bands = PART_VI_1_DEDUCTION_BANDS) {
7461
+ function computeLoans(rows) {
7462
+ return {
7463
+ returnAmounts: sum(rows, (r) => nn$17(r.returnAmounts)),
7464
+ returnReducingAmounts: sum(rows, (r) => nn$17(r.returnReducingAmounts))
7465
+ };
7466
+ }
7467
+ function computePartnershipIfe(rows) {
7468
+ const computed = rows.map((r) => ({
7469
+ ...r.partnershipName !== void 0 ? { partnershipName: r.partnershipName } : {},
7470
+ includedAmount: Math.max(0, nn$17(r.shareOfPartnershipIfe) - nn$17(r.portionUnderParagraph12_1_l1) - nn$17(r.portionDeniedBySubsection96_2_1))
7471
+ }));
7472
+ return {
7473
+ rows: computed,
7474
+ totalIncluded: sum(computed, (r) => r.includedAmount)
7475
+ };
7476
+ }
7477
+ function computeCapitalizedIfe(rows) {
7478
+ const issues = [];
7479
+ const computed = rows.map((r) => {
7480
+ const ifeInUcc = Math.max(0, nn$17(r.ifeInOpeningUcc) + Math.round(r.ifeInAcquisitionsAndDispositions ?? 0));
7481
+ const requested = nn$17(r.ifeInCca);
7482
+ if (requested > ifeInUcc) issues.push(`EIFEL: capitalized IFE in CCA${r.ccaClass ? ` for class ${r.ccaClass}` : ""} (${requested}) cannot exceed the IFE in the pool (${ifeInUcc}). Capped.`);
7483
+ const ifeInCca = Math.min(requested, ifeInUcc);
7484
+ return {
7485
+ ...r.ccaClass !== void 0 ? { ccaClass: r.ccaClass } : {},
7486
+ ifeInUcc,
7487
+ ifeInCca,
7488
+ closingIfeInUcc: Math.max(0, ifeInUcc - ifeInCca)
7489
+ };
7490
+ });
7491
+ return {
7492
+ rows: computed,
7493
+ totalIfeInTerminalLoss: sum(rows, (r) => nn$17(r.ifeInTerminalLoss)),
7494
+ totalIfeInCca: sum(computed, (r) => r.ifeInCca),
7495
+ issues
7496
+ };
7497
+ }
7498
+ function computeResourceIfe(rows) {
7499
+ const issues = [];
7500
+ const computed = rows.map((r) => {
7501
+ const ifeAvailable = Math.max(0, nn$17(r.ifeInOpeningBalance) + Math.round(r.ifeAddedOrDeducted ?? 0));
7502
+ const requested = nn$17(r.ifeInCurrentYearClaim);
7503
+ if (requested > ifeAvailable) issues.push(`EIFEL: IFE claimed in the ${r.pool} pool (${requested}) cannot exceed the IFE available before the claim (${ifeAvailable}). Capped.`);
7504
+ const ifeClaimed = Math.min(requested, ifeAvailable);
7505
+ return {
7506
+ pool: r.pool,
7507
+ ifeAvailable,
7508
+ ifeClaimed,
7509
+ closing: Math.max(0, ifeAvailable - ifeClaimed)
7510
+ };
7511
+ });
7512
+ return {
7513
+ rows: computed,
7514
+ totalIfeInResourceClaims: sum(computed, (r) => r.ifeClaimed),
7515
+ issues
7516
+ };
7517
+ }
7518
+ function computeInterestAndFinancingExpenses(input) {
7519
+ const variableA = nn$17(input.interestOnBorrowings) + nn$17(input.otherInterest) + nn$17(input.subsection20_1_eAmounts) + nn$17(input.ifeInCca) + nn$17(input.ifeInResourceExpenses) + nn$17(input.ifeInTerminalLoss) + nn$17(input.fundingCostAmounts) + nn$17(input.fundingCostLoss) + nn$17(input.fundingCostCapitalLoss) + nn$17(input.feeGivingRiseToIfe) + nn$17(input.feeReducingIfe) + nn$17(input.leaseFinancingAmount) + nn$17(input.partnershipShare) + nn$17(input.reinstatedPartnershipLoss) + nn$17(input.affiliateRaife);
7520
+ const variableB = nn$17(input.costReducingAmounts) + nn$17(input.costReducingGain) + nn$17(input.costReducingPartnershipShare);
7521
+ return {
7522
+ variableA,
7523
+ variableB,
7524
+ totalIfe: Math.max(0, variableA - variableB)
7525
+ };
7526
+ }
7527
+ function computeInterestAndFinancingRevenues(input) {
7528
+ const variableA = nn$17(input.interestReceived) + nn$17(input.subsection12_9Amounts) + nn$17(input.guaranteeFees) + nn$17(input.returnAmounts) + nn$17(input.returnGain) + nn$17(input.leaseFinancingAmount) + nn$17(input.partnershipShare) + nn$17(input.affiliateRaifr);
7529
+ const variableB = nn$17(input.returnReducingAmounts) + nn$17(input.returnReducingLoss) + nn$17(input.returnReducingCapitalLoss) + nn$17(input.returnReducingPartnershipShare) + nn$17(input.shelteredByForeignTaxRelief) + nn$17(input.exemptFromPartITax);
7530
+ return {
7531
+ variableA,
7532
+ variableB,
7533
+ totalIfr: Math.max(0, variableA - variableB)
7534
+ };
7535
+ }
7536
+ function computeLossPortionFromIfe(rows) {
7537
+ const issues = [];
7538
+ const computed = rows.map((r) => {
7539
+ const loss = nn$17(r.nonCapitalLoss);
7540
+ const variableJ = Math.min(loss, nn$17(r.variableJSecondAmount));
7541
+ if (loss === 0) {
7542
+ if (nn$17(r.amountDeducted) > 0) issues.push(`EIFEL: a loss deducted under paragraph 111(1)(a)${r.taxYearOfOrigin ? ` from ${r.taxYearOfOrigin}` : ""} was supplied with a nil non-capital loss for that year, so the IFE-attributable portion cannot be apportioned. It contributed nothing.`);
7543
+ return {
7544
+ ...r.taxYearOfOrigin !== void 0 ? { taxYearOfOrigin: r.taxYearOfOrigin } : {},
7545
+ variableJ,
7546
+ attributableToIfe: 0
7547
+ };
7548
+ }
7549
+ return {
7550
+ ...r.taxYearOfOrigin !== void 0 ? { taxYearOfOrigin: r.taxYearOfOrigin } : {},
7551
+ variableJ,
7552
+ attributableToIfe: Math.round(nn$17(r.amountDeducted) * variableJ / loss)
7553
+ };
7554
+ });
7555
+ return {
7556
+ rows: computed,
7557
+ totalAttributableToIfe: sum(computed, (r) => r.attributableToIfe),
7558
+ issues
7559
+ };
7560
+ }
7561
+ /**
7562
+ * The amount actually denied, and the amount actually added back on Schedule 1
7563
+ * line 251.
7564
+ *
7565
+ * This is NOT simply "the shortfall". Part 2K computes a **proportion** (amount
7566
+ * G) and Part 2L applies it to a base that deliberately excludes two things
7567
+ * already counted elsewhere:
7568
+ *
7569
+ * 141 variable A of IFE
7570
+ * 142 less the partnership share (Part 1E amount A) — denied instead through
7571
+ * the paragraph 12(1)(l.2) add-back in Part 2N
7572
+ * 143 less a CFA's relevant affiliate IFE — denied instead through
7573
+ * clause 95(2)(f.11)(ii)(D) in Part 2M
7574
+ *
7575
+ * With neither of those present the base is variable A and the result equals
7576
+ * the raw shortfall, which is why a simple corporation sees no difference. With
7577
+ * either present, using the shortfall directly double-counts the denial.
7578
+ */
7579
+ function computeExcessIfe(input) {
7580
+ const base = Math.max(0, nn$17(input.variableAOfIfe) - nn$17(input.partnershipShare) - nn$17(input.affiliateRaife));
7581
+ return {
7582
+ base,
7583
+ excessIfe: Math.round(base * Math.max(0, input.deniedProportion))
7584
+ };
7585
+ }
7586
+ /**
7587
+ * Part 2N line 158 — the partnership IFE add-back under paragraph 12(1)(l.2):
7588
+ * the Part 1E total (line 156) at the Part 2K proportion (line 157). Feeds
7589
+ * Schedule 1 **line 252** and Part 2O **line 160**.
7590
+ */
7591
+ function computePartnershipIfeAddBack(partnershipShare, deniedProportion) {
7592
+ return Math.round(nn$17(partnershipShare) * Math.max(0, deniedProportion));
7593
+ }
7594
+ /**
7595
+ * @param deniedProportion Amount G from Part 2K — the proportion of each
7596
+ * expense denied under subsection 18.2(2). This is why Part 2M runs after the
7597
+ * limitation rather than before it.
7598
+ */
7599
+ function computeClause95Amounts(denied, included, deniedProportion) {
7600
+ return {
7601
+ deniedUnderSubclauseI: sum(denied, (r) => Math.round(nn$17(r.variableAForAffiliate) * deniedProportion * (r.specifiedParticipatingPercentage ?? 0))),
7602
+ includedUnderSubclauseII: sum(included, (r) => Math.round(nn$17(r.amountInAffiliateFapi) * (r.specifiedParticipatingPercentage ?? 0)))
7603
+ };
7604
+ }
7605
+ //#endregion
7606
+ //#region src/t2/schedules/eifel-limitation.ts
7607
+ /**
7608
+ * ITA subsection 18.2(2) — the excessive interest and financing expenses
7609
+ * limitation itself.
7610
+ *
7611
+ * `eifel-excluded-entity.ts` decides **whether** the regime applies. This decides
7612
+ * **how much** it denies, which was previously left unbuilt on the grounds that
7613
+ * computing it from an unbuilt definition would be confidently wrong.
7614
+ *
7615
+ * ── The provision ───────────────────────────────────────────────────────────
7616
+ *
7617
+ * s.18.2(2) denies a *proportion* of each interest and financing expense:
7618
+ *
7619
+ * (A − (B + C + D + E)) ÷ F
7620
+ *
7621
+ * A the taxpayer's interest and financing expenses for the year
7622
+ * B the group-ratio amount under s.18.21(2) where that applies, otherwise
7623
+ * **G × H** — the ratio of permissible expenses times adjusted taxable income
7624
+ * C the taxpayer's interest and financing revenues for the year
7625
+ * D received capacity, to the extent it exceeds the amount deductible under
7626
+ * paragraph 111(1)(a.1)
7627
+ * E absorbed capacity
7628
+ * F ordinarily the same figure as A
7629
+ *
7630
+ * Because F is A in the ordinary case, the *amount* denied is simply
7631
+ *
7632
+ * denied = A − (B + C + D + E), floored at nil
7633
+ *
7634
+ * which is the form this module computes, while still reporting the proportion —
7635
+ * the statute denies a fraction of *each* expense, and a preparer allocating the
7636
+ * denial across expense lines needs the fraction rather than the total.
7637
+ *
7638
+ * ── The ratio of permissible expenses ───────────────────────────────────────
7639
+ *
7640
+ * Keyed off when the taxation year **BEGINS**, not when it ends:
7641
+ *
7642
+ * begins on or after 2023-10-01 and before 2024-01-01 → **40%**
7643
+ * begins on or after 2024-01-01 → **30%**
7644
+ *
7645
+ * The 40% band is transitional and narrow — one quarter — and it does **not**
7646
+ * apply when determining cumulative unused excess capacity for a year beginning
7647
+ * on or after 1 January 2024. That carve-out is not modelled; excess-capacity
7648
+ * carry-forward is a separate mechanism this module does not compute.
7649
+ *
7650
+ * ── What this module does NOT compute ───────────────────────────────────────
7651
+ *
7652
+ * **Adjusted taxable income** is an input to THIS module, not a derivation — it
7653
+ * is a build-up from taxable income through a dozen add-backs and reductions,
7654
+ * and deriving it partially here would produce a plausible number from an
7655
+ * incomplete definition. It is therefore **required**, and an absent one denies
7656
+ * nothing while saying so. `eifel-adjusted-taxable-income.ts` derives it
7657
+ * (Schedule 130 Part 2F), and `computeFederalT2` feeds that result in.
7658
+ *
7659
+ * Likewise the received and absorbed capacity amounts, which come from the
7660
+ * excess-capacity regime — `eifel-capacity.ts` computes those (Parts 1A and
7661
+ * 2G-2J), and the engine threads them in as `excessReceivedCapacity` (Part 2K
7662
+ * amount C) and `absorbedCapacity` (Part 2H amount D). The group-ratio election
7663
+ * under s.18.21 remains a preparer assertion.
7664
+ *
7665
+ * Source: `research/sources/legislation/ITA-section-18.2-EIFEL.txt`.
7666
+ *
7667
+ * Pure, whole dollars.
7668
+ */
7669
+ /** The ratio bands, keyed off the taxation year START. */
7670
+ const EIFEL_TRANSITIONAL_RATIO = .4;
7671
+ const EIFEL_STANDARD_RATIO = .3;
7672
+ /** The regime's first day — years beginning before this are outside it. */
7673
+ const EIFEL_FIRST_YEAR_START = "2023-10-01";
7674
+ /** The transitional 40% band ends when years beginning in 2024 start. */
7675
+ const EIFEL_STANDARD_RATIO_FROM = "2024-01-01";
7676
+ const nn$16 = (v) => Math.max(0, Math.round(v ?? 0));
7677
+ function utcDay$1(iso) {
7678
+ return Date.parse(`${iso.slice(0, 10)}T00:00:00Z`);
7679
+ }
7680
+ /**
7681
+ * The ratio of permissible expenses for a year beginning on `taxYearStart`.
7682
+ * Returns 0 for a year beginning before the regime applies at all.
7683
+ */
7684
+ function ratioOfPermissibleExpenses(taxYearStart) {
7685
+ const start = utcDay$1(taxYearStart);
7686
+ if (Number.isNaN(start) || start < utcDay$1("2023-10-01")) return 0;
7687
+ return start < utcDay$1("2024-01-01") ? EIFEL_TRANSITIONAL_RATIO : EIFEL_STANDARD_RATIO;
7688
+ }
7689
+ function computeEifelLimitation(input) {
7690
+ const issues = [];
7691
+ const ife = nn$16(input.interestAndFinancingExpenses);
7692
+ const nil = (ratio) => ({
7693
+ ratioOfPermissibleExpenses: ratio,
7694
+ permittedAmount: 0,
7695
+ usedGroupRatio: false,
7696
+ totalShelter: 0,
7697
+ deniedAmount: 0,
7698
+ deniedProportion: 0,
7699
+ deductibleAmount: ife,
7700
+ issues
7701
+ });
7702
+ const ratio = ratioOfPermissibleExpenses(input.taxYearStart);
7703
+ if (ratio === 0) {
7704
+ issues.push(`EIFEL: the taxation year beginning ${input.taxYearStart} is before the regime applies (${EIFEL_FIRST_YEAR_START}), so nothing is denied.`);
7705
+ return nil(0);
7706
+ }
7707
+ const usedGroupRatio = input.groupRatioAmount !== void 0;
7708
+ if (!usedGroupRatio && input.adjustedTaxableIncome === void 0) {
7709
+ issues.push("EIFEL: adjusted taxable income was not supplied, so no interest and financing expense was denied. The limitation cannot be computed without it — the figure is a build-up from taxable income that this engine does not derive, and it must be supplied or the return reviewed by hand.");
7710
+ return nil(ratio);
7711
+ }
7712
+ const permittedAmount = usedGroupRatio ? nn$16(input.groupRatioAmount) : Math.round(ratio * Math.max(0, input.adjustedTaxableIncome ?? 0));
7713
+ const totalShelter = permittedAmount + nn$16(input.interestAndFinancingRevenues) + nn$16(input.excessReceivedCapacity) + nn$16(input.absorbedCapacity);
7714
+ const deniedAmount = Math.max(0, ife - totalShelter);
7715
+ return {
7716
+ ratioOfPermissibleExpenses: ratio,
7717
+ permittedAmount,
7718
+ usedGroupRatio,
7719
+ totalShelter,
7720
+ deniedAmount,
7721
+ deniedProportion: ife > 0 ? deniedAmount / ife : 0,
7722
+ deductibleAmount: ife - deniedAmount,
7723
+ issues
7724
+ };
7725
+ }
7726
+ //#endregion
7727
+ //#region src/t2/schedules/part-vi-1-deduction.ts
7728
+ const PART_VI_1_DEDUCTION_BANDS = [
7729
+ {
7730
+ from: "0000-01-01",
7731
+ multiple: 3
7732
+ },
7733
+ {
7734
+ from: "2010-01-01",
7735
+ multiple: 3.2
7736
+ },
7737
+ {
7738
+ from: "2012-01-01",
7739
+ multiple: 3.5
7740
+ }
7741
+ ];
7742
+ function utcDay(iso) {
7743
+ return Date.parse(`${iso.slice(0, 10)}T00:00:00Z`);
7744
+ }
7745
+ /** The multiple in force for a taxation year ending on `taxYearEnd`. */
7746
+ function partVI1DeductionMultiple(taxYearEnd, bands = PART_VI_1_DEDUCTION_BANDS) {
7747
+ const end = utcDay(taxYearEnd);
7748
+ if (Number.isNaN(end)) return 0;
7749
+ let multiple = 0;
7750
+ for (const band of [...bands].sort((a, b) => utcDay(a.from) - utcDay(b.from))) if (end >= utcDay(band.from)) multiple = band.multiple;
7751
+ return multiple;
7752
+ }
7753
+ /**
7754
+ * The paragraph 110(1)(k) deduction.
7755
+ *
7756
+ * An unreadable year end yields nil and says so, rather than defaulting to the
7757
+ * current multiple — guessing the year would misstate taxable income, and this
7758
+ * deduction is large relative to the tax it follows.
7759
+ */
7760
+ function computePartVI1Deduction(partVI1Tax, taxYearEnd, bands = PART_VI_1_DEDUCTION_BANDS) {
6935
7761
  const issues = [];
6936
7762
  const tax = Math.max(0, Math.round(partVI1Tax));
6937
7763
  const multiple = partVI1DeductionMultiple(taxYearEnd, bands);
@@ -7080,10 +7906,10 @@ function assertSchedule1Fileable(result) {
7080
7906
  }
7081
7907
  //#endregion
7082
7908
  //#region src/t2/schedules/schedule2-donations.ts
7083
- const nn$17 = (v) => Math.max(0, v ?? 0);
7909
+ const nn$15 = (v) => Math.max(0, v ?? 0);
7084
7910
  function computeSchedule2(input, rates) {
7085
- const openingDonationPool = nn$17(input.openingDonationPool);
7086
- const currentYearDonations = nn$17(input.currentYearDonations);
7911
+ const openingDonationPool = nn$15(input.openingDonationPool);
7912
+ const currentYearDonations = nn$15(input.currentYearDonations);
7087
7913
  const available = openingDonationPool + currentYearDonations;
7088
7914
  const deductionLimit = Math.max(0, Math.round(rates.DONATION_INCOME_LIMIT_RATE * input.netIncomeForTax));
7089
7915
  const donationsClaimed = Math.min(available, deductionLimit);
@@ -7122,25 +7948,25 @@ function computeSchedule2(input, rates) {
7122
7948
  const PART_IV_RATE = 115 / 300;
7123
7949
  /** 30⅔% — the refundable portion of Part I tax on aggregate investment income. */
7124
7950
  const REFUNDABLE_PART_I_RATE = 92 / 300;
7125
- const nn$16 = (v) => Math.max(0, v ?? 0);
7951
+ const nn$14 = (v) => Math.max(0, v ?? 0);
7126
7952
  const DEFAULT_PART4_RATES = {
7127
7953
  PART_IV_RATE,
7128
7954
  REFUNDABLE_PART_I_RATE
7129
7955
  };
7130
7956
  function computePart4Rdtoh(input, rates = DEFAULT_PART4_RATES) {
7131
- const portfolio = nn$16(input.portfolioDividendsReceived);
7132
- const eligible = Math.min(portfolio, nn$16(input.eligiblePortfolioDividends));
7957
+ const portfolio = nn$14(input.portfolioDividendsReceived);
7958
+ const eligible = Math.min(portfolio, nn$14(input.eligiblePortfolioDividends));
7133
7959
  const nonEligible = portfolio - eligible;
7134
- const aaii = nn$16(input.aggregateInvestmentIncome);
7960
+ const aaii = nn$14(input.aggregateInvestmentIncome);
7135
7961
  const partIvOnEligible = Math.round(eligible * rates.PART_IV_RATE);
7136
7962
  const partIvOnNonEligible = Math.round(nonEligible * rates.PART_IV_RATE);
7137
7963
  const partIvTax = partIvOnEligible + partIvOnNonEligible;
7138
7964
  const refundablePartI = Math.round(aaii * rates.REFUNDABLE_PART_I_RATE);
7139
7965
  const erdtohAddition = partIvOnEligible;
7140
7966
  const nerdtohAddition = partIvOnNonEligible + refundablePartI;
7141
- const erdtohClosing = nn$16(input.openingErdtoh) + erdtohAddition;
7142
- const nerdtohClosing = nn$16(input.openingNerdtoh) + nerdtohAddition;
7143
- const refundClaim = Math.round(nn$16(input.taxableDividendsPaid) * PART_IV_RATE);
7967
+ const erdtohClosing = nn$14(input.openingErdtoh) + erdtohAddition;
7968
+ const nerdtohClosing = nn$14(input.openingNerdtoh) + nerdtohAddition;
7969
+ const refundClaim = Math.round(nn$14(input.taxableDividendsPaid) * PART_IV_RATE);
7144
7970
  return {
7145
7971
  partIvTax,
7146
7972
  refundablePartI,
@@ -7304,7 +8130,7 @@ const PROVINCE_NAMES = {
7304
8130
  AB: "Alberta",
7305
8131
  QC: "Quebec"
7306
8132
  };
7307
- const nn$15 = (v) => Math.max(0, v ?? 0);
8133
+ const nn$13 = (v) => Math.max(0, v ?? 0);
7308
8134
  function computeProvincialAllocation(input, rates = PROVINCE_RATES_2024) {
7309
8135
  const byProvince = /* @__PURE__ */ new Map();
7310
8136
  for (const pe of input.permanentEstablishments) {
@@ -7313,8 +8139,8 @@ function computeProvincialAllocation(input, rates = PROVINCE_RATES_2024) {
7313
8139
  grossRevenue: 0,
7314
8140
  salariesWages: 0
7315
8141
  };
7316
- cur.grossRevenue += nn$15(pe.grossRevenue);
7317
- cur.salariesWages += nn$15(pe.salariesWages);
8142
+ cur.grossRevenue += nn$13(pe.grossRevenue);
8143
+ cur.salariesWages += nn$13(pe.salariesWages);
7318
8144
  byProvince.set(key, cur);
7319
8145
  }
7320
8146
  const totalRevenue = [...byProvince.values()].reduce((s, p) => s + p.grossRevenue, 0);
@@ -7458,7 +8284,7 @@ function computeSchedule6(dispositions, inclusionRate) {
7458
8284
  *
7459
8285
  * Whole dollars, pure functions, no I/O.
7460
8286
  */
7461
- const nn$14 = (v) => Math.max(0, v ?? 0);
8287
+ const nn$12 = (v) => Math.max(0, v ?? 0);
7462
8288
  const round = (v) => Math.round(v);
7463
8289
  /** CDE/CCOGPE-style short-tax-year proration: full rate at ≥357 days, else rate × days/365. */
7464
8290
  function stepYearFactor(daysInTaxYear) {
@@ -7493,13 +8319,13 @@ function forcedOrCappedClaim(requested, subtotal, issues, label) {
7493
8319
  }
7494
8320
  function computeDepletion(input = {}) {
7495
8321
  const issues = [];
7496
- const edaRegularPool = nn$14(input.edaRegularOpening);
8322
+ const edaRegularPool = nn$12(input.edaRegularOpening);
7497
8323
  const edaRegularClaim = claimUpToCap(input.edaRegularClaim, edaRegularPool, issues, "Schedule 12 EDA regular (115)");
7498
8324
  const edaRegularClosing = edaRegularPool - edaRegularClaim;
7499
- const edaSuccessorPool = nn$14(input.edaSuccessorOpening);
8325
+ const edaSuccessorPool = nn$12(input.edaSuccessorOpening);
7500
8326
  const edaSuccessorClaim = claimUpToCap(input.edaSuccessorClaim, edaSuccessorPool, issues, "Schedule 12 EDA successor (140)");
7501
8327
  const edaSuccessorClosing = edaSuccessorPool - edaSuccessorClaim;
7502
- const cmedbPool = nn$14(input.cmedbOpening);
8328
+ const cmedbPool = nn$12(input.cmedbOpening);
7503
8329
  const cmedbClaim = claimUpToCap(input.cmedbClaim, cmedbPool, issues, "Schedule 12 CMEDB (170)");
7504
8330
  return {
7505
8331
  edaRegularPool,
@@ -7517,10 +8343,10 @@ function computeDepletion(input = {}) {
7517
8343
  }
7518
8344
  function computeCee(input = {}) {
7519
8345
  const issues = [];
7520
- const regularSubtotal = nn$14(input.regularOpening) + nn$14(input.regularCurrentYearExpenses) + nn$14(input.regularOtherAdditions) - nn$14(input.regularGovernmentAssistance) - nn$14(input.regularOtherDeductions);
8346
+ const regularSubtotal = nn$12(input.regularOpening) + nn$12(input.regularCurrentYearExpenses) + nn$12(input.regularOtherAdditions) - nn$12(input.regularGovernmentAssistance) - nn$12(input.regularOtherDeductions);
7521
8347
  const regularClaim = forcedOrCappedClaim(input.regularClaim, regularSubtotal, issues, "Schedule 12 CEE regular (245)");
7522
8348
  const regularClosing = regularSubtotal > 0 ? regularSubtotal - regularClaim : 0;
7523
- const successorSubtotal = nn$14(input.successorOpening) - nn$14(input.successorOtherDeductions);
8349
+ const successorSubtotal = nn$12(input.successorOpening) - nn$12(input.successorOtherDeductions);
7524
8350
  const successorClaim = forcedOrCappedClaim(input.successorClaim, successorSubtotal, issues, "Schedule 12 CEE successor (295)");
7525
8351
  return {
7526
8352
  regularSubtotal,
@@ -7542,15 +8368,15 @@ function computeCde(input = {}, daysInTaxYear, cogpe = {
7542
8368
  successorSubtotal: 0
7543
8369
  }) {
7544
8370
  const issues = [];
7545
- const regularCreditBalance = cogpe.regularSubtotal < 0 ? round(cogpe.regularSubtotal) : nn$14(input.regularCreditBalanceInCogpePool);
7546
- const regularSubtotal = nn$14(input.regularOpening) + nn$14(input.regularCurrentYearExpenses) + nn$14(input.regularOtherAdditions) - nn$14(input.regularGovernmentAssistance) - nn$14(input.regularReceivableOnDisposition) - regularCreditBalance - nn$14(input.regularOtherDeductions);
7547
- const rcdePortion = Math.min(nn$14(input.regularCurrentYearExpenses), Math.max(0, regularSubtotal));
8371
+ const regularCreditBalance = cogpe.regularSubtotal < 0 ? round(cogpe.regularSubtotal) : nn$12(input.regularCreditBalanceInCogpePool);
8372
+ const regularSubtotal = nn$12(input.regularOpening) + nn$12(input.regularCurrentYearExpenses) + nn$12(input.regularOtherAdditions) - nn$12(input.regularGovernmentAssistance) - nn$12(input.regularReceivableOnDisposition) - regularCreditBalance - nn$12(input.regularOtherDeductions);
8373
+ const rcdePortion = Math.min(nn$12(input.regularCurrentYearExpenses), Math.max(0, regularSubtotal));
7548
8374
  const regularCap = CDE_BASE_RATE * stepYearFactor(daysInTaxYear) * regularSubtotal + CDE_RCDE_BONUS_RATE * stepYearFactor(daysInTaxYear) * rcdePortion;
7549
8375
  const regularClaim = regularSubtotal > 0 ? claimUpToCap(input.regularClaim, regularCap, issues, "Schedule 12 CDE regular (345)") : 0;
7550
8376
  const regularClosing = Math.max(0, regularSubtotal - regularClaim);
7551
8377
  if (regularSubtotal < 0) issues.push("Schedule 12 CDE regular (345): the pool subtotal is negative — per the form, include it as income in \"Other additions\" on Schedule 1 (this module does not auto-apply that; add a manual Schedule 1 addition for the negative amount).");
7552
- const successorCreditBalance = cogpe.successorSubtotal < 0 ? round(cogpe.successorSubtotal) : nn$14(input.successorCreditBalanceInCogpePool);
7553
- const successorSubtotal = nn$14(input.successorOpening) - successorCreditBalance - nn$14(input.successorOtherDeductions);
8378
+ const successorCreditBalance = cogpe.successorSubtotal < 0 ? round(cogpe.successorSubtotal) : nn$12(input.successorCreditBalanceInCogpePool);
8379
+ const successorSubtotal = nn$12(input.successorOpening) - successorCreditBalance - nn$12(input.successorOtherDeductions);
7554
8380
  const successorCap = CDE_BASE_RATE * stepYearFactor(daysInTaxYear) * successorSubtotal;
7555
8381
  const successorClaim = successorSubtotal > 0 ? claimUpToCap(input.successorClaim, successorCap, issues, "Schedule 12 CDE successor (395)") : 0;
7556
8382
  return {
@@ -7570,13 +8396,13 @@ const COGPE_BASE_RATE = .1;
7570
8396
  const COGPE_RCOGPE_BONUS_RATE = .05;
7571
8397
  function computeCogpe(input = {}, daysInTaxYear) {
7572
8398
  const issues = [];
7573
- const regularSubtotal = nn$14(input.regularOpening) + nn$14(input.regularCurrentYearExpenses) + nn$14(input.regularOtherAdditions) - nn$14(input.regularReceivableOnDisposition) - nn$14(input.regularGovernmentAssistance) - nn$14(input.regularOtherDeductions);
7574
- const rcogpePortion = Math.min(nn$14(input.regularCurrentYearExpenses), Math.max(0, regularSubtotal));
8399
+ const regularSubtotal = nn$12(input.regularOpening) + nn$12(input.regularCurrentYearExpenses) + nn$12(input.regularOtherAdditions) - nn$12(input.regularReceivableOnDisposition) - nn$12(input.regularGovernmentAssistance) - nn$12(input.regularOtherDeductions);
8400
+ const rcogpePortion = Math.min(nn$12(input.regularCurrentYearExpenses), Math.max(0, regularSubtotal));
7575
8401
  const regularCap = COGPE_BASE_RATE * stepYearFactor(daysInTaxYear) * regularSubtotal + COGPE_RCOGPE_BONUS_RATE * stepYearFactor(daysInTaxYear) * rcogpePortion;
7576
8402
  const regularClaim = regularSubtotal > 0 ? claimUpToCap(input.regularClaim, regularCap, issues, "Schedule 12 COGPE regular (445)") : 0;
7577
8403
  const regularClosing = regularSubtotal > 0 ? regularSubtotal - regularClaim : 0;
7578
8404
  if (regularSubtotal < 0) issues.push("Schedule 12 COGPE regular (445): the pool subtotal is negative. Per the form this carries to CDE regular line 330 (no s.66.7(4)(a)(iii) designation) or CDE successor line 380 (with a designation) — computeCde auto-applies the 330 route unconditionally when this subtotal is negative; confirm the designation status before relying on that routing.");
7579
- const successorSubtotal = nn$14(input.successorOpening) - nn$14(input.successorReceivableOnDisposition) - nn$14(input.successorOtherDeductions);
8405
+ const successorSubtotal = nn$12(input.successorOpening) - nn$12(input.successorReceivableOnDisposition) - nn$12(input.successorOtherDeductions);
7580
8406
  const successorCap = COGPE_BASE_RATE * stepYearFactor(daysInTaxYear) * successorSubtotal;
7581
8407
  const successorClaim = successorSubtotal > 0 ? claimUpToCap(input.successorClaim, successorCap, issues, "Schedule 12 COGPE successor (495)") : 0;
7582
8408
  const successorClosing = Math.max(0, successorSubtotal - successorClaim);
@@ -7595,18 +8421,18 @@ function computeCogpe(input = {}, daysInTaxYear) {
7595
8421
  /** Part 7 — Foreign exploration and development expenses (pre-2001 tax years; still a real, if rare, carryforward). */
7596
8422
  function computeForeignExploration(input = {}, daysInTaxYear) {
7597
8423
  const issues = [];
7598
- const regularPool = nn$14(input.regularOpening) - nn$14(input.regularOtherDeductions);
8424
+ const regularPool = nn$12(input.regularOpening) - nn$12(input.regularOtherDeductions);
7599
8425
  let regularClaim = 0;
7600
8426
  if (regularPool < 0) issues.push("Schedule 12 FEDE regular (520): the pool balance is negative — include it as income in \"Other additions\" on Schedule 1 (not auto-applied by this module).");
7601
8427
  else if (regularPool > 0) {
7602
- const cap = Math.max(COGPE_BASE_RATE * stepYearFactor(daysInTaxYear) * regularPool, nn$14(input.regularForeignResourceIncome));
8428
+ const cap = Math.max(COGPE_BASE_RATE * stepYearFactor(daysInTaxYear) * regularPool, nn$12(input.regularForeignResourceIncome));
7603
8429
  regularClaim = claimUpToCap(input.regularClaim, Math.min(regularPool, cap), issues, "Schedule 12 FEDE regular (520)");
7604
8430
  }
7605
8431
  const regularClosing = regularPool - regularClaim;
7606
- const successorPool = nn$14(input.successorOpening) - nn$14(input.successorOtherDeductions);
8432
+ const successorPool = nn$12(input.successorOpening) - nn$12(input.successorOtherDeductions);
7607
8433
  let successorClaim = 0;
7608
8434
  if (successorPool < 0) issues.push("Schedule 12 FEDE successor (570): the pool balance is negative — include it as income in \"Other additions\" on Schedule 1 (not auto-applied by this module).");
7609
- else if (successorPool > 0) successorClaim = claimUpToCap(input.successorClaim, Math.min(successorPool, nn$14(input.successorForeignResourceIncome)), issues, "Schedule 12 FEDE successor (570)");
8435
+ else if (successorPool > 0) successorClaim = claimUpToCap(input.successorClaim, Math.min(successorPool, nn$12(input.successorForeignResourceIncome)), issues, "Schedule 12 FEDE successor (570)");
7610
8436
  const successorClosing = successorPool - successorClaim;
7611
8437
  return {
7612
8438
  regularPool,
@@ -7621,10 +8447,10 @@ function computeForeignExploration(input = {}, daysInTaxYear) {
7621
8447
  /** Part 8 — specified foreign exploration/development, regular OR successor (call once per column; rates are identical). */
7622
8448
  function computeSpecifiedForeignExploration(input = {}, label) {
7623
8449
  const issues = [];
7624
- const pool = nn$14(input.openingBalance) - nn$14(input.otherDeductions);
8450
+ const pool = nn$12(input.openingBalance) - nn$12(input.otherDeductions);
7625
8451
  let claim = 0;
7626
8452
  if (pool < 0) issues.push(`${label}: a country-level pool is negative — include it as income on Schedule 1 manually.`);
7627
- else if (pool > 0) claim = claimUpToCap(input.claim, Math.min(pool, Math.max(nn$14(input.foreignResourceIncome), pool)), issues, label);
8453
+ else if (pool > 0) claim = claimUpToCap(input.claim, Math.min(pool, Math.max(nn$12(input.foreignResourceIncome), pool)), issues, label);
7628
8454
  return {
7629
8455
  pool,
7630
8456
  claim,
@@ -7635,12 +8461,12 @@ function computeSpecifiedForeignExploration(input = {}, label) {
7635
8461
  /** Part 9 — cumulative foreign resource expenses, regular OR successor. */
7636
8462
  function computeCumulativeForeignResource(input = {}, daysInTaxYear, label) {
7637
8463
  const issues = [];
7638
- const pool = nn$14(input.openingBalance) + nn$14(input.currentYearExpenses) - nn$14(input.otherDeductions);
8464
+ const pool = nn$12(input.openingBalance) + nn$12(input.currentYearExpenses) - nn$12(input.otherDeductions);
7639
8465
  let claim = 0;
7640
8466
  if (pool < 0) issues.push(`${label}: a country-level pool is negative — include it as income on Schedule 1 manually.`);
7641
8467
  else if (pool > 0) {
7642
- const a = Math.max(.1 * stepYearFactor(daysInTaxYear) * pool, Math.min(.3 * stepYearFactor(daysInTaxYear) * pool, nn$14(input.foreignResourceIncome)));
7643
- const cap = a + Math.min(pool - a, nn$14(input.foreignResourceIncome));
8468
+ const a = Math.max(.1 * stepYearFactor(daysInTaxYear) * pool, Math.min(.3 * stepYearFactor(daysInTaxYear) * pool, nn$12(input.foreignResourceIncome)));
8469
+ const cap = a + Math.min(pool - a, nn$12(input.foreignResourceIncome));
7644
8470
  claim = claimUpToCap(input.claim, Math.min(pool, cap), issues, label);
7645
8471
  }
7646
8472
  return {
@@ -7694,15 +8520,15 @@ function computeSchedule12ResourceDeductions(input) {
7694
8520
  }
7695
8521
  //#endregion
7696
8522
  //#region src/t2/schedules/schedule13-reserves.ts
7697
- const nn$13 = (v) => Math.max(0, Math.round(v ?? 0));
8523
+ const nn$11 = (v) => Math.max(0, Math.round(v ?? 0));
7698
8524
  function computeSchedule13(rows = []) {
7699
8525
  let totalOpening = 0;
7700
8526
  let totalTransfer = 0;
7701
8527
  let totalClosing = 0;
7702
8528
  for (const r of rows) {
7703
- totalOpening += nn$13(r.opening);
7704
- totalTransfer += nn$13(r.transfer);
7705
- totalClosing += nn$13(r.closing);
8529
+ totalOpening += nn$11(r.opening);
8530
+ totalTransfer += nn$11(r.transfer);
8531
+ totalClosing += nn$11(r.closing);
7706
8532
  }
7707
8533
  const schedule1Addition = totalOpening + totalTransfer;
7708
8534
  const schedule1Deduction = totalClosing;
@@ -7717,15 +8543,15 @@ function computeSchedule13(rows = []) {
7717
8543
  }
7718
8544
  //#endregion
7719
8545
  //#region src/t2/schedules/schedule21-foreign-tax-credit.ts
7720
- const nn$12 = (v) => Math.max(0, v ?? 0);
8546
+ const nn$10 = (v) => Math.max(0, v ?? 0);
7721
8547
  function computeSchedule21(input) {
7722
8548
  const taxableIncome = input.taxableIncome;
7723
- const partITax = nn$12(input.partITax);
7724
- const fNonBizIncome = nn$12(input.foreignNonBusinessIncome);
7725
- const fNonBizTax = nn$12(input.foreignNonBusinessTaxPaid);
7726
- const fBizIncome = nn$12(input.foreignBusinessIncome);
7727
- const fBizTax = nn$12(input.foreignBusinessTaxPaid);
7728
- const openingPool = nn$12(input.openingBusinessFtcPool);
8549
+ const partITax = nn$10(input.partITax);
8550
+ const fNonBizIncome = nn$10(input.foreignNonBusinessIncome);
8551
+ const fNonBizTax = nn$10(input.foreignNonBusinessTaxPaid);
8552
+ const fBizIncome = nn$10(input.foreignBusinessIncome);
8553
+ const fBizTax = nn$10(input.foreignBusinessTaxPaid);
8554
+ const openingPool = nn$10(input.openingBusinessFtcPool);
7729
8555
  if (taxableIncome <= 0 || partITax <= 0) return {
7730
8556
  nonBusinessFtc: 0,
7731
8557
  businessFtc: 0,
@@ -7795,11 +8621,11 @@ function allocateEvenly(count, totalLimit = DEFAULT_BUSINESS_LIMIT) {
7795
8621
  }
7796
8622
  //#endregion
7797
8623
  //#region src/t2/schedules/schedule27-zetm.ts
7798
- const nn$11 = (v) => Math.max(0, v ?? 0);
8624
+ const nn$9 = (v) => Math.max(0, v ?? 0);
7799
8625
  function computeZetm(input, rates) {
7800
- const sbdIncome = nn$11(input.sbdIncome);
7801
- const generalRateIncome = nn$11(input.generalRateIncome);
7802
- const zetmIncome = Math.min(nn$11(input.zetmIncome), sbdIncome + generalRateIncome);
8626
+ const sbdIncome = nn$9(input.sbdIncome);
8627
+ const generalRateIncome = nn$9(input.generalRateIncome);
8628
+ const zetmIncome = Math.min(nn$9(input.zetmIncome), sbdIncome + generalRateIncome);
7803
8629
  const zetmSbdIncome = Math.min(zetmIncome, sbdIncome);
7804
8630
  const zetmGeneralIncome = Math.min(zetmIncome - zetmSbdIncome, generalRateIncome);
7805
8631
  const sbdDifferential = Math.max(0, input.sbdEffectiveRate - rates.ZETM_SBD_RATE);
@@ -7872,13 +8698,13 @@ function computeZetm(input, rates) {
7872
8698
  */
7873
8699
  /** s.127(27)-(29) — the recapture window. */
7874
8700
  const ITC_RECAPTURE_PERIOD_YEARS = 20;
7875
- const nn$10 = (v) => Math.max(0, Math.round(v ?? 0));
8701
+ const nn$8 = (v) => Math.max(0, Math.round(v ?? 0));
7876
8702
  function computeItcRecapture(items) {
7877
8703
  const issues = [];
7878
8704
  const results = items.map((item) => {
7879
8705
  const label = item.description ? ` (${item.description})` : "";
7880
8706
  const usedFairMarketValue = item.armsLengthProceeds === void 0;
7881
- const dispositionValue = usedFairMarketValue ? nn$10(item.fairMarketValue) : nn$10(item.armsLengthProceeds);
8707
+ const dispositionValue = usedFairMarketValue ? nn$8(item.fairMarketValue) : nn$8(item.armsLengthProceeds);
7882
8708
  if (usedFairMarketValue && item.fairMarketValue === void 0) issues.push(`ITC recapture${label}: neither arm's length proceeds nor a fair market value was supplied, so the recapture computed as nil. A disposition or conversion needs one of the two.`);
7883
8709
  const outsideRecapturePeriod = item.yearsSinceCredit !== void 0 && item.yearsSinceCredit > 20;
7884
8710
  const base = {
@@ -7891,12 +8717,12 @@ function computeItcRecapture(items) {
7891
8717
  outsideRecapturePeriod
7892
8718
  };
7893
8719
  if (outsideRecapturePeriod) return base;
7894
- const ownRecapture = Math.min(nn$10(item.itcEarned), Math.round(Math.max(0, item.itcRate) * dispositionValue));
8720
+ const ownRecapture = Math.min(nn$8(item.itcEarned), Math.round(Math.max(0, item.itcRate) * dispositionValue));
7895
8721
  let transferredRecapture = 0;
7896
8722
  if (item.transferred) {
7897
8723
  const t = item.transferred;
7898
- const formula = Math.round(Math.max(0, t.transfereeItcRate) * dispositionValue) - nn$10(t.alreadyRecaptured);
7899
- transferredRecapture = Math.max(0, Math.min(nn$10(t.transfereeItcEarned), formula));
8724
+ const formula = Math.round(Math.max(0, t.transfereeItcRate) * dispositionValue) - nn$8(t.alreadyRecaptured);
8725
+ transferredRecapture = Math.max(0, Math.min(nn$8(t.transfereeItcEarned), formula));
7900
8726
  }
7901
8727
  return {
7902
8728
  ...base,
@@ -7913,9 +8739,9 @@ function computeItcRecapture(items) {
7913
8739
  }
7914
8740
  //#endregion
7915
8741
  //#region src/t2/schedules/schedule31-sred-itc.ts
7916
- const nn$9 = (v) => Math.max(0, v ?? 0);
8742
+ const nn$7 = (v) => Math.max(0, v ?? 0);
7917
8743
  function computeSchedule31(input, rates) {
7918
- const qualifiedExpenditures = nn$9(input.qualifiedExpenditures);
8744
+ const qualifiedExpenditures = nn$7(input.qualifiedExpenditures);
7919
8745
  const isCcpc = input.isCcpc ?? false;
7920
8746
  const expenditureLimit = input.expenditureLimit ?? rates.SRED_EXPENDITURE_LIMIT;
7921
8747
  const enhancedBase = isCcpc ? Math.min(qualifiedExpenditures, expenditureLimit) : 0;
@@ -7924,8 +8750,8 @@ function computeSchedule31(input, rates) {
7924
8750
  const basicItc = Math.round(rates.SRED_ITC_BASIC_RATE * basicBase);
7925
8751
  const itcEarned = enhancedItc + basicItc;
7926
8752
  const refundableItc = enhancedItc;
7927
- const availableNonRefundable = basicItc + nn$9(input.openingItcPool);
7928
- const itcAppliedAgainstTax = Math.min(availableNonRefundable, nn$9(input.partITaxAvailable));
8753
+ const availableNonRefundable = basicItc + nn$7(input.openingItcPool);
8754
+ const itcAppliedAgainstTax = Math.min(availableNonRefundable, nn$7(input.partITaxAvailable));
7929
8755
  return {
7930
8756
  qualifiedExpenditures,
7931
8757
  expenditureLimit,
@@ -7964,17 +8790,17 @@ function computeSchedule31(input, rates) {
7964
8790
  /** The large-corporation filing / grind threshold (s.181.5, s.125(5.1)). */
7965
8791
  const LARGE_CORPORATION_THRESHOLD = 1e7;
7966
8792
  const n$1 = (v) => Math.round(v ?? 0);
7967
- const nn$8 = (v) => Math.max(0, Math.round(v ?? 0));
8793
+ const nn$6 = (v) => Math.max(0, Math.round(v ?? 0));
7968
8794
  function computeTaxableCapital(input = {}) {
7969
- const additions = nn$8(input.reservesNotDeducted) + nn$8(input.capitalStock) + n$1(input.retainedEarnings) + nn$8(input.contributedSurplus) + nn$8(input.otherSurpluses) + nn$8(input.deferredForexGains) + nn$8(input.loansAndAdvances) + nn$8(input.bondsAndDebentures) + nn$8(input.dividendsDeclaredUnpaid) + nn$8(input.otherLongTermDebt) + nn$8(input.partnershipInterest);
7970
- const deductions = nn$8(input.deferredTaxDebit) + nn$8(input.deficitInEquity) + nn$8(input.patronageDeducted) + nn$8(input.deferredForexLosses);
8795
+ const additions = nn$6(input.reservesNotDeducted) + nn$6(input.capitalStock) + n$1(input.retainedEarnings) + nn$6(input.contributedSurplus) + nn$6(input.otherSurpluses) + nn$6(input.deferredForexGains) + nn$6(input.loansAndAdvances) + nn$6(input.bondsAndDebentures) + nn$6(input.dividendsDeclaredUnpaid) + nn$6(input.otherLongTermDebt) + nn$6(input.partnershipInterest);
8796
+ const deductions = nn$6(input.deferredTaxDebit) + nn$6(input.deficitInEquity) + nn$6(input.patronageDeducted) + nn$6(input.deferredForexLosses);
7971
8797
  const capital = Math.max(0, additions - deductions);
7972
- const investmentAllowance = nn$8(input.sharesOfOtherCorporations) + nn$8(input.loansToOtherCorporations) + nn$8(input.bondsOfOtherCorporations) + nn$8(input.longTermDebtOfFinancialInstitution) + nn$8(input.dividendsReceivable) + nn$8(input.partnershipObligations) + nn$8(input.partnershipInterestAsset);
8798
+ const investmentAllowance = nn$6(input.sharesOfOtherCorporations) + nn$6(input.loansToOtherCorporations) + nn$6(input.bondsOfOtherCorporations) + nn$6(input.longTermDebtOfFinancialInstitution) + nn$6(input.dividendsReceivable) + nn$6(input.partnershipObligations) + nn$6(input.partnershipInterestAsset);
7973
8799
  const taxableCapital = Math.max(0, capital - investmentAllowance);
7974
8800
  let ratio = 1;
7975
8801
  if (input.taxableIncomeEarnedInCanada !== void 0 && input.taxableIncome !== void 0) {
7976
8802
  const denom = input.taxableIncome > 0 ? input.taxableIncome : 1e3;
7977
- ratio = Math.max(0, Math.min(1, nn$8(input.taxableIncomeEarnedInCanada) / denom));
8803
+ ratio = Math.max(0, Math.min(1, nn$6(input.taxableIncomeEarnedInCanada) / denom));
7978
8804
  }
7979
8805
  const taxableCapitalEmployedInCanada = Math.round(taxableCapital * ratio);
7980
8806
  return {
@@ -7987,18 +8813,18 @@ function computeTaxableCapital(input = {}) {
7987
8813
  }
7988
8814
  //#endregion
7989
8815
  //#region src/t2/schedules/schedule43-part6-1.ts
7990
- const nn$7 = (v) => Math.max(0, v ?? 0);
8816
+ const nn$5 = (v) => Math.max(0, v ?? 0);
7991
8817
  function computeSchedule43(input, rates) {
7992
- const shortTerm = nn$7(input.shortTermPreferredDividends);
7993
- const other = nn$7(input.otherPreferredDividends);
8818
+ const shortTerm = nn$5(input.shortTermPreferredDividends);
8819
+ const other = nn$5(input.otherPreferredDividends);
7994
8820
  const issues = [];
7995
8821
  let dividendAllowance;
7996
8822
  if (input.isAssociated === true) if (input.allocatedAllowance == null) {
7997
8823
  dividendAllowance = 0;
7998
8824
  if (shortTerm + other > 0) issues.push("Associated corporation: the Part VI.1 dividend allowance is nil unless the group files an allocation agreement (s.191.1(3)). Enter the allocated amount or the full dividend is taxable.");
7999
- } else dividendAllowance = Math.min(nn$7(input.allocatedAllowance), rates.DIVIDEND_ALLOWANCE);
8825
+ } else dividendAllowance = Math.min(nn$5(input.allocatedAllowance), rates.DIVIDEND_ALLOWANCE);
8000
8826
  else dividendAllowance = rates.DIVIDEND_ALLOWANCE;
8001
- const priorExcess = Math.max(0, nn$7(input.priorYearPreferredDividends) - rates.ALLOWANCE_GRIND_THRESHOLD);
8827
+ const priorExcess = Math.max(0, nn$5(input.priorYearPreferredDividends) - rates.ALLOWANCE_GRIND_THRESHOLD);
8002
8828
  dividendAllowance = Math.max(0, dividendAllowance - priorExcess);
8003
8829
  const shortTermTaxable = Math.max(0, shortTerm - dividendAllowance);
8004
8830
  const allowanceLeft = Math.max(0, dividendAllowance - shortTerm);
@@ -8021,12 +8847,12 @@ function computeSchedule43(input, rates) {
8021
8847
  }
8022
8848
  //#endregion
8023
8849
  //#region src/t2/schedules/schedule53-grip.ts
8024
- const nn$6 = (v) => Math.max(0, v ?? 0);
8850
+ const nn$4 = (v) => Math.max(0, v ?? 0);
8025
8851
  function computeGrip(input, gripFactor = .72) {
8026
- const openingGrip = nn$6(input.openingGrip);
8852
+ const openingGrip = nn$4(input.openingGrip);
8027
8853
  const generalRateAddition = Math.round(gripFactor * Math.max(0, input.generalRateIncome));
8028
- const eligibleDividendsReceived = nn$6(input.eligibleDividendsReceived);
8029
- const eligibleDividendsDesignated = nn$6(input.eligibleDividendsDesignated);
8854
+ const eligibleDividendsReceived = nn$4(input.eligibleDividendsReceived);
8855
+ const eligibleDividendsDesignated = nn$4(input.eligibleDividendsDesignated);
8030
8856
  const gripBeforeDesignation = openingGrip + generalRateAddition + eligibleDividendsReceived;
8031
8857
  const excessiveDesignation = Math.max(0, eligibleDividendsDesignated - gripBeforeDesignation);
8032
8858
  return {
@@ -8128,24 +8954,24 @@ function computeGrip(input, gripFactor = .72) {
8128
8954
  const LRIP_INVESTMENT_INCOME_FACTOR = .8;
8129
8955
  /** Line 160 — the investment corporation deduction enters the pool at four times its value. */
8130
8956
  const LRIP_INVESTMENT_CORPORATION_MULTIPLE = 4;
8131
- const nn$5 = (v) => Math.max(0, Math.round(v ?? 0));
8957
+ const nn$3 = (v) => Math.max(0, Math.round(v ?? 0));
8132
8958
  const sn = (v) => Math.round(v ?? 0);
8133
8959
  function computeSchedule54(input) {
8134
8960
  const issues = [];
8135
- const openingLrip = nn$5(input.openingLrip);
8136
- const investmentIncomeAddition = Math.round(LRIP_INVESTMENT_INCOME_FACTOR * nn$5(input.priorYearAggregateInvestmentIncome));
8137
- const investmentCorporationAddition = 4 * nn$5(input.priorYearInvestmentCorporationDeduction);
8961
+ const openingLrip = nn$3(input.openingLrip);
8962
+ const investmentIncomeAddition = Math.round(LRIP_INVESTMENT_INCOME_FACTOR * nn$3(input.priorYearAggregateInvestmentIncome));
8963
+ const investmentCorporationAddition = 4 * nn$3(input.priorYearInvestmentCorporationDeduction);
8138
8964
  const lripBeforeDividends = openingLrip + investmentIncomeAddition + investmentCorporationAddition;
8139
8965
  const ordered = [...input.dividendEvents ?? []].sort((a, b) => a.date.localeCompare(b.date));
8140
8966
  const events = [];
8141
8967
  let designationsSoFar = 0;
8142
8968
  for (const e of ordered) {
8143
- const poolBeforeReductions = lripBeforeDividends + nn$5(e.dividendsReceivableBefore) + sn(e.adjustmentsBefore);
8969
+ const poolBeforeReductions = lripBeforeDividends + nn$3(e.dividendsReceivableBefore) + sn(e.adjustmentsBefore);
8144
8970
  const derivedPrior = designationsSoFar;
8145
- const excessiveDesignationsBefore = e.excessiveDesignationsBefore !== void 0 ? nn$5(e.excessiveDesignationsBefore) : derivedPrior;
8146
- if (e.excessiveDesignationsBefore !== void 0 && nn$5(e.excessiveDesignationsBefore) !== derivedPrior) issues.push(`Schedule 54: for the dividend dated ${e.date}, line 250 was given as ${nn$5(e.excessiveDesignationsBefore)} but the earlier rows of this schedule total ${derivedPrior}. The supplied figure has been used; confirm which is right before filing, because line 250 feeds every later row.`);
8147
- const lripAtDate = Math.max(0, poolBeforeReductions - nn$5(e.dividendsPayableBefore) - excessiveDesignationsBefore);
8148
- const eligibleDividendsPaid = nn$5(e.eligibleDividendsPaid);
8971
+ const excessiveDesignationsBefore = e.excessiveDesignationsBefore !== void 0 ? nn$3(e.excessiveDesignationsBefore) : derivedPrior;
8972
+ if (e.excessiveDesignationsBefore !== void 0 && nn$3(e.excessiveDesignationsBefore) !== derivedPrior) issues.push(`Schedule 54: for the dividend dated ${e.date}, line 250 was given as ${nn$3(e.excessiveDesignationsBefore)} but the earlier rows of this schedule total ${derivedPrior}. The supplied figure has been used; confirm which is right before filing, because line 250 feeds every later row.`);
8973
+ const lripAtDate = Math.max(0, poolBeforeReductions - nn$3(e.dividendsPayableBefore) - excessiveDesignationsBefore);
8974
+ const eligibleDividendsPaid = nn$3(e.eligibleDividendsPaid);
8149
8975
  const excessiveDesignation = Math.max(0, Math.min(lripAtDate, eligibleDividendsPaid));
8150
8976
  events.push({
8151
8977
  date: e.date,
@@ -8158,8 +8984,8 @@ function computeSchedule54(input) {
8158
8984
  designationsSoFar += excessiveDesignation;
8159
8985
  }
8160
8986
  const totalExcessiveDesignation = events.reduce((s, e) => s + e.excessiveDesignation, 0);
8161
- const poolIncludingReceipts = lripBeforeDividends + nn$5(input.dividendsReceivableInYear) + sn(input.adjustmentsInYear);
8162
- const totalReductions = nn$5(input.dividendsPayableInYear) + totalExcessiveDesignation;
8987
+ const poolIncludingReceipts = lripBeforeDividends + nn$3(input.dividendsReceivableInYear) + sn(input.adjustmentsInYear);
8988
+ const totalReductions = nn$3(input.dividendsPayableInYear) + totalExcessiveDesignation;
8163
8989
  const closingLrip = Math.max(0, poolIncludingReceipts - totalReductions);
8164
8990
  if (totalExcessiveDesignation > 0) issues.push(`Schedule 54: ${totalExcessiveDesignation} of eligible dividends were designated while low rate income pool remained, so they are excessive eligible dividend designations. Carry this to amount C of Schedule 55, where it bears Part III.1 tax at 20% unless an election under subsection 185.1(2) is made.`);
8165
8991
  return {
@@ -8177,7 +9003,7 @@ function computeSchedule54(input) {
8177
9003
  }
8178
9004
  //#endregion
8179
9005
  //#region src/t2/schedules/schedule55-part3-1.ts
8180
- const nn$4 = (v) => Math.max(0, v ?? 0);
9006
+ const nn$2 = (v) => Math.max(0, v ?? 0);
8181
9007
  /**
8182
9008
  * Compute Part III.1 tax.
8183
9009
  *
@@ -8186,10 +9012,10 @@ const nn$4 = (v) => Math.max(0, v ?? 0);
8186
9012
  */
8187
9013
  function computeSchedule55(input, baseRate = .2, paragraphCRate = .1) {
8188
9014
  const issues = [];
8189
- const excessiveDesignation = nn$4(input.excessiveDesignation);
9015
+ const excessiveDesignation = nn$2(input.excessiveDesignation);
8190
9016
  const arisesUnderParagraphC = input.arisesUnderParagraphC === true;
8191
9017
  const electionAvailable = !arisesUnderParagraphC;
8192
- const claimed = input.electedAmount !== void 0 ? nn$4(input.electedAmount) : input.electsMaximum === true ? excessiveDesignation : 0;
9018
+ const claimed = input.electedAmount !== void 0 ? nn$2(input.electedAmount) : input.electsMaximum === true ? excessiveDesignation : 0;
8193
9019
  if (claimed > 0 && !electionAvailable) issues.push(`Part III.1: a subsection 185.1(2) election of ${claimed} was claimed, but the election is not available where the excess arises under paragraph (c) of the section 89(1) definition. The full ${excessiveDesignation} remains taxable at ${(baseRate + paragraphCRate) * 100}%.`);
8194
9020
  let reclassifiedAsOrdinary = electionAvailable ? Math.min(claimed, excessiveDesignation) : 0;
8195
9021
  if (electionAvailable && claimed > excessiveDesignation) {
@@ -8456,76 +9282,266 @@ function computeFederalT2(input) {
8456
9282
  ref: "s.66(4)/66.7(2)"
8457
9283
  });
8458
9284
  }
8459
- const schedule1 = computeSchedule1({
8460
- bookNetIncome: input.bookNetIncome,
8461
- ...schedule1Additions.length ? { additions: schedule1Additions } : {},
8462
- ...schedule1Deductions.length ? { deductions: schedule1Deductions } : {}
8463
- });
8464
- const partVI1 = input.preferredShareDividends && ((input.preferredShareDividends.shortTermPreferredDividends ?? 0) > 0 || (input.preferredShareDividends.otherPreferredDividends ?? 0) > 0) ? computeSchedule43(input.preferredShareDividends, {
8465
- SHORT_TERM_RATE: rates.PART_VI_1_SHORT_TERM_RATE,
8466
- ELECTED_RATE: rates.PART_VI_1_ELECTED_RATE,
8467
- BASE_RATE: rates.PART_VI_1_BASE_RATE,
8468
- DIVIDEND_ALLOWANCE: rates.PART_VI_1_DIVIDEND_ALLOWANCE,
8469
- ALLOWANCE_GRIND_THRESHOLD: rates.PART_VI_1_ALLOWANCE_GRIND_THRESHOLD
8470
- }) : void 0;
8471
- const partVI1Deduction = partVI1 ? computePartVI1Deduction(partVI1.partVI1Tax, isoDay(input.periodEnd)) : void 0;
8472
- const donations = input.charitableDonations !== void 0 || input.openingDonationPool !== void 0 ? computeSchedule2({
8473
- ...input.openingDonationPool !== void 0 ? { openingDonationPool: input.openingDonationPool } : {},
8474
- ...input.charitableDonations !== void 0 ? { currentYearDonations: input.charitableDonations } : {},
8475
- netIncomeForTax: schedule1.netIncomeForTax
8476
- }, rates) : void 0;
8477
- const culturalEcologicalGiftsClaimed = Math.max(0, input.culturalEcologicalGifts ?? 0);
8478
- const divisionCDeductions = [
8479
- ...donations && donations.donationsClaimed > 0 ? [{
8480
- line: "112",
8481
- label: "Charitable donations and gifts from Schedule 2",
8482
- amount: donations.donationsClaimed,
8483
- ref: "s.110.1"
8484
- }] : [],
8485
- ...culturalEcologicalGiftsClaimed > 0 ? [{
8486
- line: "112",
8487
- label: "Gifts of certified cultural property and ecologically sensitive land from Schedule 2",
8488
- amount: culturalEcologicalGiftsClaimed,
8489
- ref: "s.110.1(1)(b)/(c) not subject to the 75% income limit"
8490
- }] : [],
8491
- ...partVI1Deduction && partVI1Deduction.deduction > 0 ? [{
8492
- line: "325",
8493
- label: "Part VI.1 tax deduction",
8494
- amount: partVI1Deduction.deduction,
8495
- ref: `s.110(1)(k) ${partVI1Deduction.multiple}× Part VI.1 tax payable`
8496
- }] : [],
8497
- ...input.divisionCDeductions ?? []
8498
- ];
8499
- const taxableIncomeCalc = computeTaxableIncome({
8500
- netIncomeForTax: schedule1.netIncomeForTax,
8501
- ...divisionCDeductions.length ? { deductions: divisionCDeductions } : {}
8502
- });
8503
- const currentYearNonCapitalLoss = Math.max(0, -schedule1.netIncomeForTax);
8504
- const lossCarryback = input.lossCarrybacks?.length ? computeLossCarryback({
8505
- currentYearLoss: currentYearNonCapitalLoss,
8506
- carrybacks: input.lossCarrybacks
8507
- }) : void 0;
8508
- const nonCapitalCarriedBack = lossCarryback ? lossCarryback.totalCarriedBack : input.nonCapitalLossCarriedBack;
8509
- const losses = computeSchedule4Losses({
8510
- ...input.openingNonCapitalLoss !== void 0 ? { openingNonCapitalLoss: input.openingNonCapitalLoss } : {},
8511
- ...input.openingNetCapitalLoss !== void 0 ? { openingNetCapitalLoss: input.openingNetCapitalLoss } : {},
8512
- netIncomeForTax: schedule1.netIncomeForTax,
8513
- taxableIncomeBeforeLosses: taxableIncomeCalc.taxableIncome,
8514
- ...capitalGains ? { taxableCapitalGains: capitalGains.taxableCapitalGain } : input.taxableCapitalGains !== void 0 ? { taxableCapitalGains: input.taxableCapitalGains } : {},
8515
- ...input.nonCapitalLossToApply !== void 0 ? { nonCapitalLossToApply: input.nonCapitalLossToApply } : {},
8516
- ...input.netCapitalLossToApply !== void 0 ? { netCapitalLossToApply: input.netCapitalLossToApply } : {},
8517
- ...nonCapitalCarriedBack !== void 0 ? { nonCapitalCarriedBack } : {},
8518
- ...input.nonCapitalLossExpired !== void 0 ? { nonCapitalExpired: input.nonCapitalLossExpired } : {},
8519
- ...input.netCapitalLossExpired !== void 0 ? { netCapitalExpired: input.netCapitalLossExpired } : {},
8520
- ...capitalGains && capitalGains.currentYearNetCapitalLoss > 0 ? { currentYearNetCapitalLoss: capitalGains.currentYearNetCapitalLoss } : input.currentYearNetCapitalLoss !== void 0 ? { currentYearNetCapitalLoss: input.currentYearNetCapitalLoss } : {}
9285
+ /**
9286
+ * Schedule 1 → net income → Division C → taxable income → Schedule 33, as a
9287
+ * closure, because EIFEL makes it run **twice**.
9288
+ *
9289
+ * Subsection 18.2(1) defines adjusted taxable income from taxable income
9290
+ * "determined without regard to subsection 18.2(2), paragraphs 12(1)(l.2)
9291
+ * and 111(1)(a.1)" — and those three are exactly the three adjustments the
9292
+ * EIFEL computation produces (Schedule 1 lines 251 and 252, and the jacket
9293
+ * line 336 deduction). So the limitation cannot be an input to the base it
9294
+ * is computed from: the first pass supplies that base, the EIFEL chain runs
9295
+ * on it, and the second pass applies the three adjustments it produced.
9296
+ *
9297
+ * Every step in here is a pure function of its arguments, so running it
9298
+ * twice costs only arithmetic and cannot drift between the passes which
9299
+ * is the reason it is one closure rather than two copies of the sequence.
9300
+ */
9301
+ const runIncomeSequence = (eifelAdjustments) => {
9302
+ const passAdditions = eifelAdjustments ? [...schedule1Additions, ...eifelAdjustments.additions] : schedule1Additions;
9303
+ const schedule1 = computeSchedule1({
9304
+ bookNetIncome: input.bookNetIncome,
9305
+ ...passAdditions.length ? { additions: passAdditions } : {},
9306
+ ...schedule1Deductions.length ? { deductions: schedule1Deductions } : {}
9307
+ });
9308
+ const partVI1 = input.preferredShareDividends && ((input.preferredShareDividends.shortTermPreferredDividends ?? 0) > 0 || (input.preferredShareDividends.otherPreferredDividends ?? 0) > 0) ? computeSchedule43(input.preferredShareDividends, {
9309
+ SHORT_TERM_RATE: rates.PART_VI_1_SHORT_TERM_RATE,
9310
+ ELECTED_RATE: rates.PART_VI_1_ELECTED_RATE,
9311
+ BASE_RATE: rates.PART_VI_1_BASE_RATE,
9312
+ DIVIDEND_ALLOWANCE: rates.PART_VI_1_DIVIDEND_ALLOWANCE,
9313
+ ALLOWANCE_GRIND_THRESHOLD: rates.PART_VI_1_ALLOWANCE_GRIND_THRESHOLD
9314
+ }) : void 0;
9315
+ const partVI1Deduction = partVI1 ? computePartVI1Deduction(partVI1.partVI1Tax, isoDay(input.periodEnd)) : void 0;
9316
+ const donations = input.charitableDonations !== void 0 || input.openingDonationPool !== void 0 ? computeSchedule2({
9317
+ ...input.openingDonationPool !== void 0 ? { openingDonationPool: input.openingDonationPool } : {},
9318
+ ...input.charitableDonations !== void 0 ? { currentYearDonations: input.charitableDonations } : {},
9319
+ netIncomeForTax: schedule1.netIncomeForTax
9320
+ }, rates) : void 0;
9321
+ const culturalEcologicalGiftsClaimed = Math.max(0, input.culturalEcologicalGifts ?? 0);
9322
+ const divisionCDeductions = [
9323
+ ...donations && donations.donationsClaimed > 0 ? [{
9324
+ line: "112",
9325
+ label: "Charitable donations and gifts from Schedule 2",
9326
+ amount: donations.donationsClaimed,
9327
+ ref: "s.110.1"
9328
+ }] : [],
9329
+ ...culturalEcologicalGiftsClaimed > 0 ? [{
9330
+ line: "112",
9331
+ label: "Gifts of certified cultural property and ecologically sensitive land from Schedule 2",
9332
+ amount: culturalEcologicalGiftsClaimed,
9333
+ ref: "s.110.1(1)(b)/(c) not subject to the 75% income limit"
9334
+ }] : [],
9335
+ ...partVI1Deduction && partVI1Deduction.deduction > 0 ? [{
9336
+ line: "325",
9337
+ label: "Part VI.1 tax deduction",
9338
+ amount: partVI1Deduction.deduction,
9339
+ ref: `s.110(1)(k) — ${partVI1Deduction.multiple}× Part VI.1 tax payable`
9340
+ }] : [],
9341
+ ...input.divisionCDeductions ?? [],
9342
+ ...eifelAdjustments?.deductions ?? []
9343
+ ];
9344
+ const taxableIncomeCalc = computeTaxableIncome({
9345
+ netIncomeForTax: schedule1.netIncomeForTax,
9346
+ ...divisionCDeductions.length ? { deductions: divisionCDeductions } : {}
9347
+ });
9348
+ const currentYearNonCapitalLoss = Math.max(0, -schedule1.netIncomeForTax);
9349
+ const lossCarryback = input.lossCarrybacks?.length ? computeLossCarryback({
9350
+ currentYearLoss: currentYearNonCapitalLoss,
9351
+ carrybacks: input.lossCarrybacks
9352
+ }) : void 0;
9353
+ const nonCapitalCarriedBack = lossCarryback ? lossCarryback.totalCarriedBack : input.nonCapitalLossCarriedBack;
9354
+ const losses = computeSchedule4Losses({
9355
+ ...input.openingNonCapitalLoss !== void 0 ? { openingNonCapitalLoss: input.openingNonCapitalLoss } : {},
9356
+ ...input.openingNetCapitalLoss !== void 0 ? { openingNetCapitalLoss: input.openingNetCapitalLoss } : {},
9357
+ netIncomeForTax: schedule1.netIncomeForTax,
9358
+ taxableIncomeBeforeLosses: taxableIncomeCalc.taxableIncome,
9359
+ ...capitalGains ? { taxableCapitalGains: capitalGains.taxableCapitalGain } : input.taxableCapitalGains !== void 0 ? { taxableCapitalGains: input.taxableCapitalGains } : {},
9360
+ ...input.nonCapitalLossToApply !== void 0 ? { nonCapitalLossToApply: input.nonCapitalLossToApply } : {},
9361
+ ...input.netCapitalLossToApply !== void 0 ? { netCapitalLossToApply: input.netCapitalLossToApply } : {},
9362
+ ...nonCapitalCarriedBack !== void 0 ? { nonCapitalCarriedBack } : {},
9363
+ ...input.nonCapitalLossExpired !== void 0 ? { nonCapitalExpired: input.nonCapitalLossExpired } : {},
9364
+ ...input.netCapitalLossExpired !== void 0 ? { netCapitalExpired: input.netCapitalLossExpired } : {},
9365
+ ...capitalGains && capitalGains.currentYearNetCapitalLoss > 0 ? { currentYearNetCapitalLoss: capitalGains.currentYearNetCapitalLoss } : input.currentYearNetCapitalLoss !== void 0 ? { currentYearNetCapitalLoss: input.currentYearNetCapitalLoss } : {}
9366
+ });
9367
+ const taxableIncome = Math.max(0, taxableIncomeCalc.taxableIncome - losses.totalApplied);
9368
+ const associatedAllocation = input.associatedMembers ? computeBusinessLimitAllocation({ members: input.associatedMembers }) : void 0;
9369
+ const taxableCapitalSchedule = input.taxableCapitalDetail ? computeTaxableCapital({
9370
+ ...input.taxableCapitalDetail,
9371
+ ...input.taxableCapitalDetail.taxableIncome === void 0 ? { taxableIncome } : {}
9372
+ }) : void 0;
9373
+ return {
9374
+ schedule1,
9375
+ partVI1,
9376
+ partVI1Deduction,
9377
+ donations,
9378
+ culturalEcologicalGiftsClaimed,
9379
+ divisionCDeductions,
9380
+ taxableIncomeCalc,
9381
+ currentYearNonCapitalLoss,
9382
+ lossCarryback,
9383
+ nonCapitalCarriedBack,
9384
+ losses,
9385
+ taxableIncome,
9386
+ associatedAllocation,
9387
+ taxableCapitalSchedule,
9388
+ grindTaxableCapital: input.taxableCapital ?? taxableCapitalSchedule?.taxableCapitalEmployedInCanada
9389
+ };
9390
+ };
9391
+ const provisional = runIncomeSequence();
9392
+ const eifel = assessEifel({
9393
+ taxYearStart: isoDay(input.periodStart ?? input.period?.start),
9394
+ ...(input.eifel?.isCcpc ?? input.isCcpc) !== void 0 ? { isCcpc: input.eifel?.isCcpc ?? input.isCcpc } : {},
9395
+ ...(() => {
9396
+ const tc = input.eifel?.groupTaxableCapital ?? provisional.taxableCapitalSchedule?.taxableCapitalEmployedInCanada ?? input.taxableCapital;
9397
+ return tc !== void 0 ? { groupTaxableCapital: tc } : {};
9398
+ })(),
9399
+ ...input.eifel?.netInterestAndFinancingExpenses !== void 0 ? { netInterestAndFinancingExpenses: input.eifel.netInterestAndFinancingExpenses } : {},
9400
+ ...input.eifel?.domesticExceptionApplies !== void 0 ? { domesticExceptionApplies: input.eifel.domesticExceptionApplies } : {}
9401
+ }, {
9402
+ SMALL_CCPC_TAXABLE_CAPITAL: rates.EIFEL_SMALL_CCPC_TAXABLE_CAPITAL,
9403
+ DE_MINIMIS_NET_IFE: rates.EIFEL_DE_MINIMIS_NET_IFE
8521
9404
  });
8522
- const taxableIncome = Math.max(0, taxableIncomeCalc.taxableIncome - losses.totalApplied);
8523
- const associatedAllocation = input.associatedMembers ? computeBusinessLimitAllocation({ members: input.associatedMembers }) : void 0;
8524
- const taxableCapitalSchedule = input.taxableCapitalDetail ? computeTaxableCapital({
8525
- ...input.taxableCapitalDetail,
8526
- ...input.taxableCapitalDetail.taxableIncome === void 0 ? { taxableIncome } : {}
8527
- }) : void 0;
8528
- const grindTaxableCapital = input.taxableCapital ?? taxableCapitalSchedule?.taxableCapitalEmployedInCanada;
9405
+ const eifelChain = (() => {
9406
+ if (!eifel.requiresLimitation) return null;
9407
+ const e = input.eifel;
9408
+ const taxYearStart = isoDay(input.periodStart ?? input.period?.start);
9409
+ const exemptIfe = computeExemptIfe(e?.exemptIfe ?? []);
9410
+ const borrowings = computeBorrowings(e?.borrowings ?? []);
9411
+ const loans = computeLoans(e?.loans ?? []);
9412
+ const partnership = computePartnershipIfe(e?.partnershipIfe ?? []);
9413
+ const capitalized = computeCapitalizedIfe(e?.capitalizedIfe ?? []);
9414
+ const resourceIfe = computeResourceIfe(e?.resourceIfe ?? []);
9415
+ const lossPortion = computeLossPortionFromIfe(e?.lossPortionFromIfe ?? []);
9416
+ const ife = computeInterestAndFinancingExpenses({
9417
+ ...e?.ifeDetail ?? {},
9418
+ interestOnBorrowings: borrowings.interestPaidOrPayable,
9419
+ ifeInCca: capitalized.totalIfeInCca,
9420
+ ifeInResourceExpenses: resourceIfe.totalIfeInResourceClaims,
9421
+ ifeInTerminalLoss: capitalized.totalIfeInTerminalLoss,
9422
+ fundingCostAmounts: borrowings.fundingCostAmounts,
9423
+ partnershipShare: partnership.totalIncluded,
9424
+ costReducingAmounts: borrowings.costReducingAmounts
9425
+ });
9426
+ const ifr = computeInterestAndFinancingRevenues({
9427
+ ...e?.ifrDetail ?? {},
9428
+ returnAmounts: loans.returnAmounts,
9429
+ returnReducingAmounts: loans.returnReducingAmounts
9430
+ });
9431
+ const eifelIfe = e?.interestAndFinancingExpenses ?? ife.totalIfe;
9432
+ const eifelIfr = e?.interestAndFinancingRevenues ?? ifr.totalIfr;
9433
+ const ati = computeAdjustedTaxableIncome({
9434
+ ...e?.adjustedTaxableIncomeDetail ?? {},
9435
+ taxableIncome: provisional.taxableIncome,
9436
+ nonCapitalLossForYear: provisional.currentYearNonCapitalLoss,
9437
+ lossClaimNotReducingTaxableIncome: Math.max(0, provisional.losses.totalApplied - Math.max(0, provisional.taxableIncomeCalc.taxableIncome)),
9438
+ interestAndFinancingExpenses: eifelIfe,
9439
+ capitalCostAllowance: cca?.totalCca ?? 0,
9440
+ resourceDeductions: resourceDeductions ? resourceDeductions.depletionClaim + resourceDeductions.ceeClaim + resourceDeductions.cdeClaim + resourceDeductions.cogpeClaim + resourceDeductions.foreignClaim : 0,
9441
+ terminalLoss: cca?.totalTerminalLoss ?? 0,
9442
+ partVI1TaxDeduction: provisional.partVI1Deduction?.deduction ?? 0,
9443
+ lossPortionDerivedFromIfe: lossPortion.totalAttributableToIfe,
9444
+ exemptIfeActivityLoss: exemptIfe.lossFromExemptActivities,
9445
+ exemptIfeActivityIncome: exemptIfe.incomeFromExemptActivities,
9446
+ interestAndFinancingRevenues: eifelIfr,
9447
+ recapture: cca?.totalRecapture ?? 0
9448
+ });
9449
+ const resolvedAti = e?.adjustedTaxableIncome ?? ati.adjustedTaxableIncome;
9450
+ const capacityBase = computeEifelCapacity({
9451
+ adjustedTaxableIncome: resolvedAti,
9452
+ interestAndFinancingExpenses: eifelIfe,
9453
+ interestAndFinancingRevenues: eifelIfr,
9454
+ ratioOfPermissibleExpenses: ratioOfPermissibleExpenses(taxYearStart),
9455
+ ...e?.hasGroupRatioElection !== void 0 ? { hasGroupRatioElection: e.hasGroupRatioElection } : {},
9456
+ ...e?.groupRatioAmount !== void 0 ? { groupRatioAmount: e.groupRatioAmount } : {},
9457
+ ...e?.receivedCapacity ? { receivedCapacity: e.receivedCapacity } : {},
9458
+ ...e?.rifeFromPreviousYears !== void 0 ? { rifeFromPreviousYears: e.rifeFromPreviousYears } : {},
9459
+ ...e?.priorYearExcessCapacity ? { priorYearExcessCapacity: e.priorYearExcessCapacity } : {}
9460
+ });
9461
+ const limitation = computeEifelLimitation({
9462
+ interestAndFinancingExpenses: eifelIfe,
9463
+ adjustedTaxableIncome: resolvedAti,
9464
+ interestAndFinancingRevenues: eifelIfr,
9465
+ excessReceivedCapacity: capacityBase.excessReceivedCapacity,
9466
+ absorbedCapacity: capacityBase.absorbedCapacity,
9467
+ ...e?.hasGroupRatioElection && e?.groupRatioAmount !== void 0 ? { groupRatioAmount: e.groupRatioAmount } : {},
9468
+ taxYearStart
9469
+ });
9470
+ const { excessIfe } = computeExcessIfe({
9471
+ variableAOfIfe: e?.interestAndFinancingExpenses ?? ife.variableA,
9472
+ partnershipShare: partnership.totalIncluded,
9473
+ ...e?.ifeDetail?.affiliateRaife !== void 0 ? { affiliateRaife: e.ifeDetail.affiliateRaife } : {},
9474
+ deniedProportion: limitation.deniedProportion
9475
+ });
9476
+ const partnershipIfeAddBack = e?.partnershipIfeAddBack ?? computePartnershipIfeAddBack(partnership.totalIncluded, limitation.deniedProportion);
9477
+ const clause95 = computeClause95Amounts(e?.clause95Denied ?? [], e?.clause95Included ?? [], limitation.deniedProportion);
9478
+ return {
9479
+ ati,
9480
+ limitation,
9481
+ capacity: {
9482
+ ...capacityBase,
9483
+ rifeForYear: computeRifeUnderSubsection111_8({
9484
+ excessInterestAndFinancingExpenses: excessIfe,
9485
+ partnershipIfeAddBack,
9486
+ clause95FapiAmountI: e?.clause95FapiAmountI ?? clause95.deniedUnderSubclauseI,
9487
+ clause95FapiAmountII: e?.clause95FapiAmountII ?? clause95.includedUnderSubclauseII
9488
+ }),
9489
+ issues: [
9490
+ ...capacityBase.issues,
9491
+ ...capitalized.issues,
9492
+ ...resourceIfe.issues,
9493
+ ...lossPortion.issues
9494
+ ]
9495
+ },
9496
+ ife,
9497
+ ifr,
9498
+ excessIfe,
9499
+ partnershipIfeAddBack
9500
+ };
9501
+ })();
9502
+ /**
9503
+ * A return inside the regime that never supplied its GROSS interest and
9504
+ * financing expenses computes a denial of nil — which looks like "nothing was
9505
+ * restricted" and is really "nothing was measured". The group NET figure that
9506
+ * settled the de-minimis test above is not a substitute: it is a different
9507
+ * figure, for a different purpose, at group level.
9508
+ */
9509
+ const eifelWithIssues = eifel.requiresLimitation && !((eifelChain?.ife.totalIfe ?? 0) > 0) ? {
9510
+ ...eifel,
9511
+ issues: [...eifel.issues, "EIFEL: the corporation is inside the regime but its gross interest and financing expenses (Schedule 130 Part 2A line 045) were not supplied, so the limitation measured nothing and denied nothing. Supply that figure — the group net figure used for the de minimis test is not the same amount."]
9512
+ } : eifel;
9513
+ /**
9514
+ * The three adjustments the EIFEL computation produces, on the lines the
9515
+ * forms name for them:
9516
+ *
9517
+ * Schedule 1 line 251 the denial under s.18.2(2) (Part 2L amount B)
9518
+ * Schedule 1 line 252 the 12(1)(l.2) partnership add-back (Part 2N)
9519
+ * jacket line 336 the 111(1)(a.1) RIFE deduction (Part 2J amount B)
9520
+ *
9521
+ * Each is one of the three things adjusted taxable income is defined to
9522
+ * disregard, which is why applying them needs the second pass below rather
9523
+ * than being folded into the first.
9524
+ */
9525
+ const eifelAdjustments = eifelChain ? {
9526
+ additions: [...eifelChain.excessIfe > 0 ? [{
9527
+ line: "251",
9528
+ label: "Excess IFE under subsection 18.2(2) from Schedule 130",
9529
+ amount: eifelChain.excessIfe,
9530
+ ref: "s.18.2(2)"
9531
+ }] : [], ...eifelChain.partnershipIfeAddBack > 0 ? [{
9532
+ line: "252",
9533
+ label: "Partnership IFE add-back under paragraph 12(1)(l.2) from Schedule 130",
9534
+ amount: eifelChain.partnershipIfeAddBack,
9535
+ ref: "s.12(1)(l.2)"
9536
+ }] : []],
9537
+ deductions: eifelChain.capacity.rifeDeductible > 0 ? [{
9538
+ line: "336",
9539
+ label: "Restricted interest and financing expenses from Schedule 4",
9540
+ amount: eifelChain.capacity.rifeDeductible,
9541
+ ref: "s.111(1)(a.1)"
9542
+ }] : []
9543
+ } : void 0;
9544
+ const { schedule1, partVI1, partVI1Deduction, donations, taxableIncomeCalc, lossCarryback, losses, taxableIncome, associatedAllocation, taxableCapitalSchedule, grindTaxableCapital } = ((eifelAdjustments?.additions.length ?? 0) > 0 || (eifelAdjustments?.deductions.length ?? 0) > 0) && eifelAdjustments ? runIncomeSequence(eifelAdjustments) : provisional;
8529
9545
  const adjustedAggregateInvestmentIncomeSchedule = input.adjustedAggregateInvestmentIncomeDetail ? computeAdjustedAggregateInvestmentIncome(input.adjustedAggregateInvestmentIncomeDetail) : void 0;
8530
9546
  const resolvedAaii = input.aaii ?? adjustedAggregateInvestmentIncomeSchedule?.adjustedAggregateInvestmentIncome;
8531
9547
  const aggregateInvestmentIncomeSchedule = input.aggregateInvestmentIncomeDetail ? computeAggregateInvestmentIncome(input.aggregateInvestmentIncomeDetail) : void 0;
@@ -8617,19 +9633,6 @@ function computeFederalT2(input) {
8617
9633
  ...input.provincialAllocationFactor !== void 0 ? { allocationFactor: input.provincialAllocationFactor } : {}
8618
9634
  }, provinceRates) : void 0;
8619
9635
  const totalTax = totalFederalTax + (provincialAllocation?.totalProvincialTax ?? provincial?.provincialTax ?? 0);
8620
- const eifel = assessEifel({
8621
- taxYearStart: isoDay(input.periodStart ?? input.period?.start),
8622
- ...(input.eifel?.isCcpc ?? input.isCcpc) !== void 0 ? { isCcpc: input.eifel?.isCcpc ?? input.isCcpc } : {},
8623
- ...(() => {
8624
- const tc = input.eifel?.groupTaxableCapital ?? taxableCapitalSchedule?.taxableCapitalEmployedInCanada ?? input.taxableCapital;
8625
- return tc !== void 0 ? { groupTaxableCapital: tc } : {};
8626
- })(),
8627
- ...input.eifel?.netInterestAndFinancingExpenses !== void 0 ? { netInterestAndFinancingExpenses: input.eifel.netInterestAndFinancingExpenses } : {},
8628
- ...input.eifel?.domesticExceptionApplies !== void 0 ? { domesticExceptionApplies: input.eifel.domesticExceptionApplies } : {}
8629
- }, {
8630
- SMALL_CCPC_TAXABLE_CAPITAL: rates.EIFEL_SMALL_CCPC_TAXABLE_CAPITAL,
8631
- DE_MINIMIS_NET_IFE: rates.EIFEL_DE_MINIMIS_NET_IFE
8632
- });
8633
9636
  const internetBusiness = input.internetBusiness ? normalizeSchedule88(input.internetBusiness) : void 0;
8634
9637
  const firstReturn = input.firstReturn ? computeSchedule101(input.firstReturn) : void 0;
8635
9638
  return {
@@ -8657,7 +9660,14 @@ function computeFederalT2(input) {
8657
9660
  ...partIII1 ? { partIII1 } : {},
8658
9661
  ...partVI1 ? { partVI1 } : {},
8659
9662
  ...partVI1Deduction ? { partVI1Deduction } : {},
8660
- eifel,
9663
+ eifel: eifelWithIssues,
9664
+ ...eifelChain ? {
9665
+ eifelAdjustedTaxableIncome: eifelChain.ati,
9666
+ eifelLimitation: eifelChain.limitation,
9667
+ eifelCapacity: eifelChain.capacity,
9668
+ eifelIfe: eifelChain.ife,
9669
+ eifelIfr: eifelChain.ifr
9670
+ } : {},
8661
9671
  ...internetBusiness ? { internetBusiness } : {},
8662
9672
  ...firstReturn ? { firstReturn } : {},
8663
9673
  ...sredItc ? { sredItc } : {},
@@ -8672,7 +9682,20 @@ function computeFederalT2(input) {
8672
9682
  taxableIncome,
8673
9683
  federalTaxPayable: partI.partITaxPayable,
8674
9684
  totalFederalTax,
8675
- totalTax
9685
+ totalTax,
9686
+ schedulePayloads: federalSchedulePayloads({
9687
+ schedule1,
9688
+ netIncomeForTax: schedule1.netIncomeForTax,
9689
+ taxableIncome,
9690
+ totalFederalTax,
9691
+ ...donations ? { donations } : {},
9692
+ ...adjustedAggregateInvestmentIncomeSchedule ? { adjustedAggregateInvestmentIncomeSchedule } : {},
9693
+ ...cca ? { cca } : {},
9694
+ ...foreignTaxCredit ? { foreignTaxCredit } : {},
9695
+ ...taxableCapitalSchedule ? { taxableCapitalSchedule } : {},
9696
+ ...grip ? { grip } : {},
9697
+ ...partIII1 ? { partIII1 } : {}
9698
+ })
8676
9699
  };
8677
9700
  }
8678
9701
  //#endregion
@@ -8910,7 +9933,7 @@ function computeQuebecTax(input, rates = QC_TAX_2024) {
8910
9933
  }
8911
9934
  //#endregion
8912
9935
  //#region src/t2/co17/schedules/quebec-allocation.ts
8913
- const nn$3 = (v) => Math.max(0, v ?? 0);
9936
+ const nn$1 = (v) => Math.max(0, v ?? 0);
8914
9937
  function computeQuebecAllocationFactor(establishments, quebecCode = "QC") {
8915
9938
  let quebecRevenue = 0;
8916
9939
  let totalRevenue = 0;
@@ -8919,8 +9942,8 @@ function computeQuebecAllocationFactor(establishments, quebecCode = "QC") {
8919
9942
  let quebecCount = 0;
8920
9943
  const total = establishments.length;
8921
9944
  for (const pe of establishments) {
8922
- const rev = nn$3(pe.grossRevenue);
8923
- const pay = nn$3(pe.salariesWages);
9945
+ const rev = nn$1(pe.grossRevenue);
9946
+ const pay = nn$1(pe.salariesWages);
8924
9947
  totalRevenue += rev;
8925
9948
  totalSalaries += pay;
8926
9949
  if (pe.province === quebecCode) {
@@ -9408,215 +10431,6 @@ function computeT2Settlement(input) {
9408
10431
  };
9409
10432
  }
9410
10433
  //#endregion
9411
- //#region src/t2/schedules/eifel-adjusted-taxable-income.ts
9412
- /**
9413
- * ITA subsection 18.2(1) — **adjusted taxable income**, the base the EIFEL
9414
- * ceiling is computed on.
9415
- *
9416
- * `eifel-limitation.ts` took this as a required input because deriving it
9417
- * partially would produce a plausible figure from an incomplete definition. This
9418
- * derives it, and is explicit about the components it does and does not cover.
9419
- *
9420
- * ── What it is ──────────────────────────────────────────────────────────────
9421
- *
9422
- * An EBITDA-like measure, built from taxable income by adding back the things the
9423
- * regime is measuring against and removing the things that would double-count.
9424
- *
9425
- * ATI = A + B − C
9426
- *
9427
- * A = D − E the income base
9428
- * B the ADD-BACKS
9429
- * C the REDUCTIONS
9430
- *
9431
- * **The add-backs include the interest and financing expenses themselves.** That
9432
- * is the point of the measure and the thing to hold on to: the ceiling is a
9433
- * percentage of income computed *before* the very expenses being limited, so a
9434
- * corporation cannot shrink its own ceiling by borrowing more.
9435
- *
9436
- * ── A — the income base (D − E) ─────────────────────────────────────────────
9437
- *
9438
- * **D** is taxable income for the year, determined **without regard to** s.18.2(2)
9439
- * itself, paragraphs 12(1)(l.2) and 111(1)(a.1), and clause 95(2)(f.11)(ii)(D) —
9440
- * a non-resident uses taxable income earned in Canada on the same basis. The
9441
- * circularity is deliberate: the limitation cannot be an input to its own base.
9442
- *
9443
- * **E** subtracts the year's non-capital loss on the same basis, any amount
9444
- * claimed under paragraph 111(1)(a) that did not actually reduce taxable income,
9445
- * and a controlled-foreign-affiliate component (`T × U ÷ V`).
9446
- *
9447
- * ── B — the add-backs ───────────────────────────────────────────────────────
9448
- *
9449
- * (a) interest and financing expenses for the year
9450
- * (b) capital cost allowance and resource deductions — paragraph 20(1)(a),
9451
- * 59.1(a) and subsections 66(4), 66.1(2)/(3), 66.2(2), 66.21(4), 66.4(2),
9452
- * 66.7(1)-(5)
9453
- * (c) terminal losses — subsection 20(16)
9454
- * (d) the taxpayer's share of a partnership's 20(1)(a) and 20(16) deductions
9455
- * (e) the portion of a paragraph 111(1)(e) limited-partnership-loss claim
9456
- * attributable to those amounts
9457
- *
9458
- * ── C — the reductions ──────────────────────────────────────────────────────
9459
- *
9460
- * (a) interest and financing revenues
9461
- * (b) recapture — subsection 13(1)
9462
- * (c) the taxpayer's share of a partnership's 13(1) inclusion
9463
- * (d) resource inclusions — subsections 59(1), 59(3.2), paragraph 59.1(b)
9464
- * (e) for a corporation, a grossed-up foreign tax credit amount:
9465
- * **100/28** of what would be deductible under s.126(1), and
9466
- * the s.126(2) amounts times the relevant factor
9467
- *
9468
- * ── Not modelled ────────────────────────────────────────────────────────────
9469
- *
9470
- * The trust variant of C(e), and the later paragraphs of B and C dealing with
9471
- * foreign affiliate income and exempt interest. Each is available as an explicit
9472
- * `otherAdditions` / `otherReductions` input rather than silently omitted, so a
9473
- * preparer with one of those amounts can still arrive at the right figure and the
9474
- * engine does not pretend the definition is shorter than it is.
9475
- *
9476
- * Source: `research/sources/legislation/ITA-section-18.2-EIFEL.txt`.
9477
- *
9478
- * Pure, whole dollars.
9479
- */
9480
- /** C(e)(i) — s.126(1) amounts are grossed up by 100/28. */
9481
- const FOREIGN_TAX_CREDIT_GROSS_UP = 100 / 28;
9482
- const nn$2 = (v) => Math.max(0, Math.round(v ?? 0));
9483
- function computeAdjustedTaxableIncome(input) {
9484
- const issues = [];
9485
- const e = nn$2(input.nonCapitalLossForYear) + nn$2(input.lossClaimNotReducingTaxableIncome) + nn$2(input.foreignAccrualPropertyLossComponent);
9486
- const incomeBase = Math.round(input.taxableIncome) - e;
9487
- const totalAdditions = nn$2(input.interestAndFinancingExpenses) + nn$2(input.capitalCostAllowance) + nn$2(input.resourceDeductions) + nn$2(input.terminalLoss) + nn$2(input.partnershipCapitalAndTerminalShare) + nn$2(input.limitedPartnershipLossPortion) + nn$2(input.otherAdditions);
9488
- const totalReductions = nn$2(input.interestAndFinancingRevenues) + nn$2(input.recapture) + nn$2(input.partnershipRecaptureShare) + nn$2(input.resourceInclusions) + Math.round(FOREIGN_TAX_CREDIT_GROSS_UP * nn$2(input.section126_1ForeignTaxCredits)) + nn$2(input.section126_2GrossedUp) + nn$2(input.otherReductions);
9489
- const adjustedTaxableIncome = incomeBase + totalAdditions - totalReductions;
9490
- if (adjustedTaxableIncome < 0) issues.push(`EIFEL: adjusted taxable income is negative (${adjustedTaxableIncome}), so the ceiling is nil and every interest and financing expense is denied. Check that the loss and add-back figures are complete before filing on that basis.`);
9491
- if (input.interestAndFinancingExpenses === void 0) issues.push("EIFEL: no interest and financing expenses were added back to adjusted taxable income. They are paragraph (a) of the add-backs, and omitting them understates the ceiling — which denies more expense than the rules require.");
9492
- return {
9493
- incomeBase,
9494
- totalAdditions,
9495
- totalReductions,
9496
- adjustedTaxableIncome,
9497
- issues
9498
- };
9499
- }
9500
- //#endregion
9501
- //#region src/t2/schedules/eifel-limitation.ts
9502
- /**
9503
- * ITA subsection 18.2(2) — the excessive interest and financing expenses
9504
- * limitation itself.
9505
- *
9506
- * `eifel-excluded-entity.ts` decides **whether** the regime applies. This decides
9507
- * **how much** it denies, which was previously left unbuilt on the grounds that
9508
- * computing it from an unbuilt definition would be confidently wrong.
9509
- *
9510
- * ── The provision ───────────────────────────────────────────────────────────
9511
- *
9512
- * s.18.2(2) denies a *proportion* of each interest and financing expense:
9513
- *
9514
- * (A − (B + C + D + E)) ÷ F
9515
- *
9516
- * A the taxpayer's interest and financing expenses for the year
9517
- * B the group-ratio amount under s.18.21(2) where that applies, otherwise
9518
- * **G × H** — the ratio of permissible expenses times adjusted taxable income
9519
- * C the taxpayer's interest and financing revenues for the year
9520
- * D received capacity, to the extent it exceeds the amount deductible under
9521
- * paragraph 111(1)(a.1)
9522
- * E absorbed capacity
9523
- * F ordinarily the same figure as A
9524
- *
9525
- * Because F is A in the ordinary case, the *amount* denied is simply
9526
- *
9527
- * denied = A − (B + C + D + E), floored at nil
9528
- *
9529
- * which is the form this module computes, while still reporting the proportion —
9530
- * the statute denies a fraction of *each* expense, and a preparer allocating the
9531
- * denial across expense lines needs the fraction rather than the total.
9532
- *
9533
- * ── The ratio of permissible expenses ───────────────────────────────────────
9534
- *
9535
- * Keyed off when the taxation year **BEGINS**, not when it ends:
9536
- *
9537
- * begins on or after 2023-10-01 and before 2024-01-01 → **40%**
9538
- * begins on or after 2024-01-01 → **30%**
9539
- *
9540
- * The 40% band is transitional and narrow — one quarter — and it does **not**
9541
- * apply when determining cumulative unused excess capacity for a year beginning
9542
- * on or after 1 January 2024. That carve-out is not modelled; excess-capacity
9543
- * carry-forward is a separate mechanism this module does not compute.
9544
- *
9545
- * ── What this module does NOT compute ───────────────────────────────────────
9546
- *
9547
- * **Adjusted taxable income** is an input, not a derivation. Its definition is a
9548
- * build-up from taxable income through a dozen add-backs and reductions —
9549
- * interest and financing expenses, capital cost allowance, resource deductions,
9550
- * loss claims with their own nested formulas — each with its own defined term. A
9551
- * partial implementation would produce a plausible number from an incomplete
9552
- * definition, which is precisely the failure this module was deferred to avoid.
9553
- * It is therefore **required**, and an absent one denies nothing while saying so.
9554
- *
9555
- * Likewise the group-ratio election under s.18.21, and the received/absorbed
9556
- * capacity amounts, which come from the excess-capacity regime.
9557
- *
9558
- * Source: `research/sources/legislation/ITA-section-18.2-EIFEL.txt`.
9559
- *
9560
- * Pure, whole dollars.
9561
- */
9562
- /** The ratio bands, keyed off the taxation year START. */
9563
- const EIFEL_TRANSITIONAL_RATIO = .4;
9564
- const EIFEL_STANDARD_RATIO = .3;
9565
- /** The regime's first day — years beginning before this are outside it. */
9566
- const EIFEL_FIRST_YEAR_START = "2023-10-01";
9567
- /** The transitional 40% band ends when years beginning in 2024 start. */
9568
- const EIFEL_STANDARD_RATIO_FROM = "2024-01-01";
9569
- const nn$1 = (v) => Math.max(0, Math.round(v ?? 0));
9570
- function utcDay(iso) {
9571
- return Date.parse(`${iso.slice(0, 10)}T00:00:00Z`);
9572
- }
9573
- /**
9574
- * The ratio of permissible expenses for a year beginning on `taxYearStart`.
9575
- * Returns 0 for a year beginning before the regime applies at all.
9576
- */
9577
- function ratioOfPermissibleExpenses(taxYearStart) {
9578
- const start = utcDay(taxYearStart);
9579
- if (Number.isNaN(start) || start < utcDay("2023-10-01")) return 0;
9580
- return start < utcDay("2024-01-01") ? EIFEL_TRANSITIONAL_RATIO : EIFEL_STANDARD_RATIO;
9581
- }
9582
- function computeEifelLimitation(input) {
9583
- const issues = [];
9584
- const ife = nn$1(input.interestAndFinancingExpenses);
9585
- const nil = (ratio) => ({
9586
- ratioOfPermissibleExpenses: ratio,
9587
- permittedAmount: 0,
9588
- usedGroupRatio: false,
9589
- totalShelter: 0,
9590
- deniedAmount: 0,
9591
- deniedProportion: 0,
9592
- deductibleAmount: ife,
9593
- issues
9594
- });
9595
- const ratio = ratioOfPermissibleExpenses(input.taxYearStart);
9596
- if (ratio === 0) {
9597
- issues.push(`EIFEL: the taxation year beginning ${input.taxYearStart} is before the regime applies (${EIFEL_FIRST_YEAR_START}), so nothing is denied.`);
9598
- return nil(0);
9599
- }
9600
- const usedGroupRatio = input.groupRatioAmount !== void 0;
9601
- if (!usedGroupRatio && input.adjustedTaxableIncome === void 0) {
9602
- issues.push("EIFEL: adjusted taxable income was not supplied, so no interest and financing expense was denied. The limitation cannot be computed without it — the figure is a build-up from taxable income that this engine does not derive, and it must be supplied or the return reviewed by hand.");
9603
- return nil(ratio);
9604
- }
9605
- const permittedAmount = usedGroupRatio ? nn$1(input.groupRatioAmount) : Math.round(ratio * Math.max(0, input.adjustedTaxableIncome ?? 0));
9606
- const totalShelter = permittedAmount + nn$1(input.interestAndFinancingRevenues) + nn$1(input.excessReceivedCapacity) + nn$1(input.absorbedCapacity);
9607
- const deniedAmount = Math.max(0, ife - totalShelter);
9608
- return {
9609
- ratioOfPermissibleExpenses: ratio,
9610
- permittedAmount,
9611
- usedGroupRatio,
9612
- totalShelter,
9613
- deniedAmount,
9614
- deniedProportion: ife > 0 ? deniedAmount / ife : 0,
9615
- deductibleAmount: ife - deniedAmount,
9616
- issues
9617
- };
9618
- }
9619
- //#endregion
9620
10434
  //#region src/t2/schedules/schedule27-mp.ts
9621
10435
  /**
9622
10436
  * T2 Schedule 27 — Canadian Manufacturing and Processing Profits Deduction
@@ -9794,4 +10608,4 @@ function computeMpDeduction(input, rates = MP_RATES_2024) {
9794
10608
  };
9795
10609
  }
9796
10610
  //#endregion
9797
- export { computeCde as $, toRsiSchedule as $n, ALBERTA_SRED_PROGRAM_START as $r, computeOtherLossByYearOfOrigin as $t, formatConformanceReport as A, schedule1Values as Ai, computeClass141RecaptureReduction as An, computeIeg as Ar, assessEifel as At, computeSchedule54 as B, AB_TAX_2024 as Bi, albertaCurrentYearLoss as Bn, computeCeeRegular as Br, netCapitalLossApplied as Bt, computeQuebecAllocationFactor as C, schedule10Values as Ci, CLASS_14_1_RECAPTURE_REDUCTION_RATE as Cn, at1Engine as Cr, mealsAndEntertainmentAddBack as Ct, resolveQuebecTaxRates as D, schedule16Values as Di, computeClass13 as Dn, computeIegAgreement as Dr, computePartVI1Deduction as Dt, QC_TAX_RATE_BOOK as E, schedule13Values as Ei, MIN_LEASEHOLD_PERIODS as En, allocateIegExpenditureLimit as Er, PART_VI_1_DEDUCTION_BANDS as Et, SCHEDULE_88_MAX_URLS as F, schedule4970Values as Fi, resolveCcaRates as Fn, computeAlbertaSchedule15 as Fr, blendProvinceRateTable as Ft, computeSchedule31 as G, hasExactRateYear as Gi, albertaTerminalLossDifference as Gn, computeEdaRegular as Gr, computeAggregateInvestmentIncome as Gt, computeSchedule43 as H, resolveAlbertaTaxRates as Hi, albertaRecaptureDifference as Hn, computeCfreRegular as Hr, computeCcpcActiveBusinessTax as Ht, normalizeSchedule88 as I, computeAlbertaTax as Ii, albertaAbilDifference as In, computeCcogpeRegular as Ir, dayWeightedRate as It, computeZetm as J, LossCarrybackError as Jn, computeFedeSuccessor as Jr, CORP_TAX_2024 as Jt, ITC_RECAPTURE_PERIOD_YEARS as K, latestRateYear as Ki, computeSchedule12 as Kn, computeEdaSuccessor as Kr, computeBusinessLimit as Kt, computeSchedule55 as L, computeAlbertaSbd as Li, albertaCapitalGainDifference as Ln, computeCcogpeSuccessor as Lr, charitableDonationsDeduction as Lt, runConformanceSuite as M, schedule21Values as Mi, CCA_DECLINING_BALANCE_RATES_2024 as Mn, computeIegReductionFactor as Mr, PROVINCE_RATE_BOOK as Mt, computeFederalT2 as N, schedule29Values as Ni, CCA_RATE_BOOK as Nn, computeIegEligibleExpenditures as Nr, isSchedule5Province as Nt, T2_LINE_META as O, schedule17Values as Oi, computeClass14 as On, computeIegGroupFigures as Or, partVI1DeductionMultiple as Ot, computeSchedule101 as P, schedule2Values as Pi, isDecliningBalanceClass as Pn, iegT661SourceLine as Pr, resolveProvinceRates as Pt, computeSchedule13 as Q, toRsiLineItems as Qn, ALBERTA_SRED_EXPENDITURE_CUTOFF as Qr, computeNonCapitalLossByYearOfOrigin as Qt, LRIP_INVESTMENT_CORPORATION_MULTIPLE as R, AB_GENERAL_RATE_BANDS as Ri, albertaCcaDifference as Rn, computeCdeRegular as Rr, computeTaxableIncome as Rt, computeQuebecReturn as S, at1LineItemId as Si, CLASS_14_1_MINIMUM_DEDUCTION as Sn, xmlEscape as Sr, incomeTaxProvisionAddBack as St, QC_TAX_2024 as T, schedule12Values as Ti, MAX_LEASEHOLD_PERIODS as Tn, allocateIegEvenly as Tr, terminalLossDeduction as Tt, LARGE_CORPORATION_THRESHOLD as U, earliestRateYear as Ui, albertaReserveDifference as Un, computeCfreSuccessor as Ur, computePartITax as Ut, computeGrip as V, AB_TAX_RATE_BOOK as Vi, albertaDispositionAdjustments as Vn, computeCeeSuccessor as Vr, nonCapitalLossApplied as Vt, computeTaxableCapital as W, extendRateBook as Wi, albertaResourceDeductionDifference as Wn, computeCmedb as Wr, computeAdjustedAggregateInvestmentIncome as Wt, computeBusinessLimitAllocation as X, toRsiHeader as Xn, computeSfedeCountrySuccessor as Xr, resolveCorpTaxRates as Xt, allocateEvenly as Y, computeLossCarryback as Yn, computeSfedeCountryRegular as Yr, CORP_TAX_RATE_BOOK as Yt, computeSchedule21 as Z, toRsiJacketSchedules as Zn, schedule15Values as Zr, T2_CERTIFICATION_FIXTURES as Zt, computeT2Settlement as _, SINGLE_JURISDICTION_ALBERTA_FACTOR as _i, computeAlbertaSchedule13 as _n, assertAt1MandatoryComplete as _r, assertSchedule1Fileable as _t, computeCanadianMPProfits as a, computeSchedule8$1 as ai, AT1_DONATION_INCOME_RATE as an, formatRsiAmount as ar, computeSchedule12ResourceDeductions as at, renderCo17DraftReturn as b, AT1_SCHEDULES_WITHOUT_BUILDERS as bi, computeCcaSchedule as bn, at1TaxPayableDeductions as br, deferredIncomeTaxProvisionAddBack as bt, computeSmallManufacturerTest as c, schedule7Values as ci, AT1_DISPOSITION_CATEGORIES as cn, renderAt1Rsi as cr, computeProvincialAllocation as ct, EIFEL_STANDARD_RATIO_FROM as d, computeAlbertaSchedule5 as di, AT1_RESERVE_KINDS as dn, renderAt1NetFile as dr, PART_IV_RATE as dt, ALBERTA_SRED_TAX_CREDIT_RATE as ei, computeLossSchedule as en, RSI_COLUMN_GAP as er, computeCee as et, EIFEL_TRANSITIONAL_RATIO as f, schedule5Values as fi, AT1_RESERVE_LINES as fn, AT1_CRITICAL_MANDATORY_FIELDS as fr, REFUNDABLE_PART_I_RATE as ft, computeAdjustedTaxableIncome as g, schedule3Values as gi, computeAlbertaSchedule16 as gn, albertaBalanceUnpaid as gr, amortizationAddBack as gt, FOREIGN_TAX_CREDIT_GROSS_UP as h, computeSchedule3 as hi, assistanceFrom as hn, At1TaxPayableMismatchError as hr, Schedule1NotFileableError as ht, SMALL_MANUFACTURER_INCOME_THRESHOLD as i, schedule9Values as ii, AT1_DONATION_GAIN_RATE as in, RsiLineItemError as ir, computeForeignExploration as it, runConformance as j, schedule20Values as ji, leaseholdPeriods as jn, computeIegBaseAmount as jr, PROVINCE_RATES_2024 as jt, foldT2Lines as k, schedule18Values as ki, computeClass141AdditionalAllowance as kn, IEG_2024 as kr, EIFEL_EFFECTIVE_FROM as kt, EIFEL_FIRST_YEAR_START as l, computeAlbertaSchedule6 as li, SECTION_34_2_GROSS_UP as ln, renderRsiHeader as lr, computeSchedule5 as lt, ratioOfPermissibleExpenses as m, schedule4Values as mi, computeAlbertaSchedule17 as mn, At1MandatoryFieldMissingError as mr, computeSchedule2 as mt, MP_GROSS_REVENUE_THRESHOLD as n, computeAlbertaSchedule9 as ni, computeLimitedPartnershipLossRow as nn, RSI_NEGATIVE_PREFIX as nr, computeCumulativeForeignResource as nt, computeMpDeduction as o, schedule8Values as oi, computeDonationMaximum as on, formatRsiDate as or, computeSpecifiedForeignExploration as ot, computeEifelLimitation as p, computeSchedule4 as pi, AT1_RESERVE_TOTAL_LINES as pn, At1CriticalFieldMissingError as pr, computePart4Rdtoh as pt, computeItcRecapture as q, resolveRates as qi, reconcileAlbertaNetIncome as qn, computeFedeRegular as qr, computeSBD as qt, MP_RATES_2024 as r, computeSchedule9MaximumExpenditureLimit as ri, computeLimitedPartnershipLosses as rn, RSI_WORD_GAP as rr, computeDepletion as rt, computePart2MPProfits as s, computeAlbertaSchedule7 as si, computeSchedule20 as sn, formatRsiText as sr, computeSchedule6 as st, MP_EXCLUDED_ACTIVITIES as t, allocateSchedule9ExpenditureLimit as ti, computeLossContinuity as tn, RSI_DELIMITER as tr, computeCogpe as tt, EIFEL_STANDARD_RATIO as u, schedule6Values as ui, computeAlbertaSchedule18 as un, renderRsiLineItem as ur, computeSchedule4Losses as ut, renderT2DraftReturn as v, computeAllocationFactor as vi, UnsupportedCcaClassError as vn, assertAt1TaxPayableReconciles as vr, ccaDeduction as vt, computeQuebecTax as w, schedule12LossDeductions as wi, CLASS_14_1_TRANSITIONAL_RATE as wn, computeAlbertaReturn as wr, recaptureAddBack as wt, co17Engine as x, AT1_SCHEDULES_WITH_BUILDERS as xi, computeSchedule8 as xn, at1YesNo as xr, findSchedule1LineDefects as xt, t2Engine as y, computeAt4970 as yi, computeCcaClass as yn, assertCriticalFields as yr, computeSchedule1 as yt, LRIP_INVESTMENT_INCOME_FACTOR as z, computeDayWeightedGeneralTax as zi, albertaCcaScheduleAdjustments as zn, computeCdeSuccessor as zr, dividendsDeductibleS112 as zt };
10611
+ export { computeSchedule6 as $, schedule21Values$1 as $i, resolveCcaRates as $n, computeIegReductionFactor as $r, dividendsDeductibleS112 as $t, LRIP_INVESTMENT_CORPORATION_MULTIPLE as A, computeAlbertaSchedule6 as Ai, AT1_RESERVE_LINES as An, renderRsiHeader as Ar, computeExcessIfe as At, computeZetm as B, computeAt4970 as Bi, CLASS_14_1_MINIMUM_DEDUCTION as Bn, assertCriticalFields as Br, assessEifel as Bt, runConformance as C, computeAlbertaSchedule9 as Ci, AT1_DONATION_INCOME_RATE as Cn, RSI_NEGATIVE_PREFIX as Cr, EIFEL_STANDARD_RATIO_FROM as Ct, SCHEDULE_88_MAX_URLS as D, schedule8Values$1 as Di, SECTION_34_2_GROSS_UP as Dn, formatRsiDate as Dr, computeBorrowings as Dt, computeSchedule101 as E, computeSchedule8$1 as Ei, AT1_DISPOSITION_CATEGORIES as En, formatRsiAmount as Er, ratioOfPermissibleExpenses as Et, LARGE_CORPORATION_THRESHOLD as F, schedule4Values as Fi, computeAlbertaSchedule13 as Fn, At1MandatoryFieldMissingError as Fr, computeLossPortionFromIfe as Ft, computeCde as G, schedule12LossDeductions as Gi, computeClass13 as Gn, computeAlbertaReturn as Gr, PROVINCE_RATES_2024 as Gt, computeBusinessLimitAllocation as H, AT1_SCHEDULES_WITH_BUILDERS as Hi, CLASS_14_1_TRANSITIONAL_RATE as Hn, at1YesNo as Hr, computeRifeUnderSubsection111_8 as Ht, computeTaxableCapital as I, computeSchedule3 as Ii, UnsupportedCcaClassError as In, At1TaxPayableMismatchError as Ir, computePartnershipIfe as It, computeCumulativeForeignResource as J, schedule16Values as Ji, computeClass141RecaptureReduction as Jn, computeIegAgreement as Jr, resolveProvinceRates as Jt, computeCee as K, schedule12Values as Ki, computeClass14 as Kn, allocateIegEvenly as Kr, PROVINCE_RATE_BOOK as Kt, computeSchedule31 as L, schedule3Values as Li, computeCcaClass as Ln, albertaBalanceUnpaid as Lr, computePartnershipIfeAddBack as Lt, computeSchedule54 as M, computeAlbertaSchedule5 as Mi, computeAlbertaSchedule17 as Mn, renderAt1NetFile as Mr, computeInterestAndFinancingExpenses as Mt, computeGrip as N, schedule5Values as Ni, assistanceFrom as Nn, AT1_CRITICAL_MANDATORY_FIELDS as Nr, computeInterestAndFinancingRevenues as Nt, normalizeSchedule88 as O, computeAlbertaSchedule7 as Oi, computeAlbertaSchedule18 as On, formatRsiText as Or, computeCapitalizedIfe as Ot, computeSchedule43 as P, computeSchedule4 as Pi, computeAlbertaSchedule16 as Pn, At1CriticalFieldMissingError as Pr, computeLoans as Pt, computeSpecifiedForeignExploration as Q, schedule20Values as Qi, isDecliningBalanceClass as Qn, computeIegBaseAmount as Qr, computeTaxableIncome as Qt, ITC_RECAPTURE_PERIOD_YEARS as R, SINGLE_JURISDICTION_ALBERTA_FACTOR as Ri, computeCcaSchedule as Rn, assertAt1MandatoryComplete as Rr, computeResourceIfe as Rt, formatConformanceReport as S, allocateSchedule9ExpenditureLimit as Si, AT1_DONATION_GAIN_RATE as Sn, RSI_DELIMITER as Sr, EIFEL_STANDARD_RATIO as St, computeFederalT2 as T, schedule9Values as Ti, computeSchedule20 as Tn, RsiLineItemError as Tr, computeEifelLimitation as Tt, computeSchedule21 as U, at1LineItemId as Ui, MAX_LEASEHOLD_PERIODS as Un, xmlEscape as Ur, FOREIGN_TAX_CREDIT_GROSS_UP as Ut, allocateEvenly as V, AT1_SCHEDULES_WITHOUT_BUILDERS as Vi, CLASS_14_1_RECAPTURE_REDUCTION_RATE as Vn, at1TaxPayableDeductions as Vr, computeEifelCapacity as Vt, computeSchedule13 as W, schedule10Values as Wi, MIN_LEASEHOLD_PERIODS as Wn, at1Engine as Wr, computeAdjustedTaxableIncome as Wt, computeForeignExploration as X, schedule18Values as Xi, CCA_DECLINING_BALANCE_RATES_2024 as Xn, IEG_2024 as Xr, dayWeightedRate as Xt, computeDepletion as Y, schedule17Values as Yi, leaseholdPeriods as Yn, computeIegGroupFigures as Yr, blendProvinceRateTable as Yt, computeSchedule12ResourceDeductions as Z, schedule1Values$1 as Zi, CCA_RATE_BOOK as Zn, computeIeg as Zr, charitableDonationsDeduction as Zt, QC_TAX_2024 as _, computeSfedeCountrySuccessor as _i, computeRifeContinuity as _n, toRsiHeader as _r, terminalLossDeduction as _t, computeCanadianMPProfits as a, AB_GENERAL_RATE_BANDS as aa, computeCdeRegular as ai, computeAggregateInvestmentIncome as an, albertaDispositionAdjustments as ar, computePart4Rdtoh as at, T2_LINE_META as b, ALBERTA_SRED_PROGRAM_START as bi, computeLimitedPartnershipLossRow as bn, toRsiSchedule as br, partVI1DeductionMultiple as bt, computeSmallManufacturerTest as c, AB_TAX_RATE_BOOK as ca, computeCeeSuccessor as ci, CORP_TAX_2024 as cn, albertaResourceDeductionDifference as cr, amortizationAddBack as ct, t2Engine as d, extendRateBook as da, computeCmedb as di, federalSchedulePayloads as dn, reconcileAlbertaNetIncome as dr, computeSchedule1 as dt, schedule29Values as ea, computeIegEligibleExpenditures as ei, netCapitalLossApplied as en, albertaAbilDifference as er, computeProvincialAllocation as et, renderCo17DraftReturn as f, hasExactRateYear as fa, computeEdaRegular as fi, parseT2LineItemId as fn, LossCarrybackError as fr, deferredIncomeTaxProvisionAddBack as ft, computeQuebecTax as g, computeSfedeCountryRegular as gi, computeOtherLossByYearOfOrigin as gn, validateAt1Transmitter as gr, recaptureAddBack as gt, computeQuebecAllocationFactor as h, computeFedeSuccessor as hi, computeNonCapitalLossByYearOfOrigin as hn, assertAt1TransmitterValid as hr, mealsAndEntertainmentAddBack as ht, SMALL_MANUFACTURER_INCOME_THRESHOLD as i, computeAlbertaSbd as ia, computeCcogpeSuccessor as ii, computeAdjustedAggregateInvestmentIncome as in, albertaCurrentYearLoss as ir, REFUNDABLE_PART_I_RATE as it, LRIP_INVESTMENT_INCOME_FACTOR as j, schedule6Values as ji, AT1_RESERVE_TOTAL_LINES as jn, renderRsiLineItem as jr, computeExemptIfe as jt, computeSchedule55 as k, schedule7Values$1 as ki, AT1_RESERVE_KINDS as kn, renderAt1Rsi as kr, computeClause95Amounts as kt, computeT2Settlement as l, resolveAlbertaTaxRates as la, computeCfreRegular as li, CORP_TAX_RATE_BOOK as ln, albertaTerminalLossDifference as lr, assertSchedule1Fileable as lt, computeQuebecReturn as m, resolveRates as ma, computeFedeRegular as mi, T2_CERTIFICATION_FIXTURES as mn, At1TransmitterInvalidError as mr, incomeTaxProvisionAddBack as mt, MP_GROSS_REVENUE_THRESHOLD as n, schedule4970Values as na, computeAlbertaSchedule15 as ni, computeCcpcActiveBusinessTax as nn, albertaCcaDifference as nr, computeSchedule4Losses as nt, computeMpDeduction as o, computeDayWeightedGeneralTax as oa, computeCdeSuccessor as oi, computeBusinessLimit as on, albertaRecaptureDifference as or, computeSchedule2 as ot, co17Engine as p, latestRateYear as pa, computeEdaSuccessor as pi, t2LineItemId as pn, computeLossCarryback as pr, findSchedule1LineDefects as pt, computeCogpe as q, schedule13Values as qi, computeClass141AdditionalAllowance as qn, allocateIegExpenditureLimit as qr, isSchedule5Province as qt, MP_RATES_2024 as r, computeAlbertaTax as ra, computeCcogpeRegular as ri, computePartITax as rn, albertaCcaScheduleAdjustments as rr, PART_IV_RATE as rt, computePart2MPProfits as s, AB_TAX_2024 as sa, computeCeeRegular as si, computeSBD as sn, albertaReserveDifference as sr, Schedule1NotFileableError as st, MP_EXCLUDED_ACTIVITIES as t, schedule2Values$1 as ta, iegT661SourceLine as ti, nonCapitalLossApplied as tn, albertaCapitalGainDifference as tr, computeSchedule5 as tt, renderT2DraftReturn as u, earliestRateYear as ua, computeCfreSuccessor as ui, resolveCorpTaxRates as un, computeSchedule12 as ur, ccaDeduction as ut, QC_TAX_RATE_BOOK as v, schedule15Values as vi, computeLossSchedule as vn, toRsiJacketSchedules as vr, PART_VI_1_DEDUCTION_BANDS as vt, runConformanceSuite as w, computeSchedule9MaximumExpenditureLimit as wi, computeDonationMaximum as wn, RSI_WORD_GAP as wr, EIFEL_TRANSITIONAL_RATIO as wt, foldT2Lines as x, ALBERTA_SRED_TAX_CREDIT_RATE as xi, computeLimitedPartnershipLosses as xn, RSI_COLUMN_GAP as xr, EIFEL_FIRST_YEAR_START as xt, resolveQuebecTaxRates as y, ALBERTA_SRED_EXPENDITURE_CUTOFF as yi, computeLossContinuity as yn, toRsiLineItems as yr, computePartVI1Deduction as yt, computeItcRecapture as z, computeAllocationFactor as zi, computeSchedule8 as zn, assertAt1TaxPayableReconciles as zr, EIFEL_EFFECTIVE_FROM as zt };