@classytic/ca-tax 0.0.15 → 0.0.18

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;
@@ -928,13 +924,20 @@ function schedule10Values(input) {
928
924
  put("040", input.otherLoss.result.remainingLoss);
929
925
  }
930
926
  if (input.capital) {
931
- const rate = input.inclusionRate ?? .5;
932
927
  put("042", input.capital.currentYearLoss);
933
- for (const [f, c] of zip([
928
+ const rateFields = [
929
+ "043",
930
+ "045",
931
+ "047"
932
+ ];
933
+ const grossFields = [
934
934
  "044",
935
935
  "046",
936
936
  "048"
937
- ], input.capital.carrybacks)) put(f, Math.round(rate * c.amount));
937
+ ];
938
+ for (const [f, c] of zip(rateFields, input.capital.carrybacks)) put(f, (c.inclusionRate ?? input.inclusionRate ?? .5).toFixed(6));
939
+ for (const [f, c] of zip(grossFields, input.capital.carrybacks)) put(f, c.amount);
940
+ put("050", input.capital.remainingLoss);
938
941
  }
939
942
  return {
940
943
  scheduleId: "010",
@@ -1060,16 +1063,16 @@ function schedule16Values(result) {
1060
1063
  }
1061
1064
  //#endregion
1062
1065
  //#region src/t2/at1/schedules/at4970-ieg-projects.ts
1063
- const nn$34 = (v) => Math.max(0, Math.round(v ?? 0));
1066
+ const nn$31 = (v) => Math.max(0, Math.round(v ?? 0));
1064
1067
  function computeAt4970(input) {
1065
1068
  const projects = input.projects.map((p) => ({
1066
1069
  title: p.title,
1067
1070
  ...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)
1071
+ albertaPortion: nn$31(p.albertaPortion),
1072
+ otherPortion: nn$31(p.otherPortion),
1073
+ salariesAndWages: nn$31(p.salariesAndWages),
1074
+ federalProxyAmount: nn$31(p.federalProxyAmount),
1075
+ albertaProxyAmount: nn$31(p.albertaProxyAmount)
1073
1076
  }));
1074
1077
  const totals = {
1075
1078
  albertaPortion: projects.reduce((s, p) => s + p.albertaPortion, 0),
@@ -1080,7 +1083,7 @@ function computeAt4970(input) {
1080
1083
  };
1081
1084
  const jurisdictions = (input.jurisdictions ?? []).map((j) => ({
1082
1085
  jurisdiction: j.jurisdiction,
1083
- amountIncurred: nn$34(j.amountIncurred)
1086
+ amountIncurred: nn$31(j.amountIncurred)
1084
1087
  }));
1085
1088
  return {
1086
1089
  projects,
@@ -1196,15 +1199,15 @@ function computeAllocationFactor(input) {
1196
1199
  *
1197
1200
  * Whole dollars, pure.
1198
1201
  */
1199
- const nn$33 = (v) => Math.max(0, Math.round(v ?? 0));
1202
+ const nn$30 = (v) => Math.max(0, Math.round(v ?? 0));
1200
1203
  const raw = (v) => Math.round(v ?? 0);
1201
1204
  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);
1205
+ const certificatesIssued = nn$30(input.certificatesIssued);
1206
+ const carryforwardFromPriorYear = nn$30(input.carryforwardFromPriorYear);
1207
+ const expired = nn$30(input.expired);
1205
1208
  const availableBeforeClaim = certificatesIssued + carryforwardFromPriorYear;
1206
1209
  const cap = Math.min(availableBeforeClaim, roomCap);
1207
- const wanted = input.amountApplied != null ? nn$33(input.amountApplied) : cap;
1210
+ const wanted = input.amountApplied != null ? nn$30(input.amountApplied) : cap;
1208
1211
  const amountApplied = Math.max(0, Math.min(wanted, cap));
1209
1212
  const carryforwardToNextYear = availableBeforeClaim - amountApplied - expired;
1210
1213
  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 +1221,17 @@ function computeItc(input, roomCap, issues) {
1218
1221
  };
1219
1222
  }
1220
1223
  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);
1224
+ const certificatesIssued = nn$30(input.certificatesIssued);
1225
+ const carryforwardFromPriorYear = nn$30(input.carryforwardFromPriorYear);
1226
+ const expired = nn$30(input.expired);
1224
1227
  const availableBeforeClaim = certificatesIssued + carryforwardFromPriorYear;
1225
1228
  let amountApplied;
1226
1229
  if (itcCarryforwardRemaining > 0) {
1227
1230
  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.`);
1231
+ if (input.amountApplied != null && nn$30(input.amountApplied) > 0) issues.push(`Alberta Schedule 3 (CITC): a claim of ${nn$30(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
1232
  } else {
1230
1233
  const cap = Math.min(availableBeforeClaim, Math.max(0, roomCap - itcApplied));
1231
- const wanted = input.amountApplied != null ? nn$33(input.amountApplied) : cap;
1234
+ const wanted = input.amountApplied != null ? nn$30(input.amountApplied) : cap;
1232
1235
  amountApplied = Math.max(0, Math.min(wanted, cap));
1233
1236
  }
1234
1237
  const carryforwardToNextYear = availableBeforeClaim - amountApplied - expired;
@@ -1247,18 +1250,18 @@ function computeApitc(input, roomCap, issues) {
1247
1250
  const first = input.firstPreceding ?? {};
1248
1251
  const second = input.secondPreceding ?? {};
1249
1252
  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);
1253
+ const currentAvailable = nn$30(current.received);
1254
+ const firstAvailable = nn$30(first.availableAtBeginning);
1255
+ const secondAvailable = nn$30(second.availableAtBeginning);
1256
+ const thirdToTenthAvailable = nn$30(thirdToTenth.availableAtBeginning);
1254
1257
  const currentCap = Math.round(currentAvailable * .2);
1255
1258
  const firstCap = Math.round(firstAvailable * .3);
1256
1259
  const secondCap = Math.round(secondAvailable * .5);
1257
1260
  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);
1261
+ const currentAsk = Math.min(current.amountApplied != null ? nn$30(current.amountApplied) : currentCap, currentCap);
1262
+ const firstAsk = Math.min(first.amountApplied != null ? nn$30(first.amountApplied) : firstCap, firstCap);
1263
+ const secondAsk = Math.min(second.amountApplied != null ? nn$30(second.amountApplied) : secondCap, secondCap);
1264
+ const thirdToTenthAsk = Math.min(thirdToTenth.amountApplied != null ? nn$30(thirdToTenth.amountApplied) : thirdToTenthCap, thirdToTenthCap);
1262
1265
  const totalRequested = currentAsk + firstAsk + secondAsk + thirdToTenthAsk;
1263
1266
  let room = Math.max(0, roomCap);
1264
1267
  const allocate = (ask) => {
@@ -1274,7 +1277,7 @@ function computeApitc(input, roomCap, issues) {
1274
1277
  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
1278
  const totalReceived = currentAvailable;
1276
1279
  const carryforwardFromPriorYear = firstAvailable + secondAvailable + thirdToTenthAvailable;
1277
- const expired = nn$33(input.expiredThisYear);
1280
+ const expired = nn$30(input.expiredThisYear);
1278
1281
  const availableForCarryforward = totalReceived + carryforwardFromPriorYear - totalApplied - expired;
1279
1282
  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
1283
  return {
@@ -1308,11 +1311,11 @@ function computeApitc(input, roomCap, issues) {
1308
1311
  function computeSchedule3(input) {
1309
1312
  const issues = [];
1310
1313
  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);
1314
+ const line068 = nn$30(mad.taxPayableBeforeDeduction);
1315
+ const line070 = nn$30(mad.line070);
1316
+ const line071 = nn$30(mad.line071);
1317
+ const line072 = nn$30(mad.line072);
1318
+ const line074 = nn$30(mad.line074);
1316
1319
  const room602 = raw(line068) - (line070 + line071 + line072 + line074);
1317
1320
  const itcCitcCap = Math.max(0, room602);
1318
1321
  const itc = computeItc(input.itc ?? {}, itcCitcCap, issues);
@@ -1378,26 +1381,26 @@ function schedule3Values(result) {
1378
1381
  }
1379
1382
  //#endregion
1380
1383
  //#region src/t2/at1/schedules/schedule4-foreign-investment-tax-credit.ts
1381
- const nn$32 = (v) => Math.max(0, v ?? 0);
1384
+ const nn$29 = (v) => Math.max(0, v ?? 0);
1382
1385
  /** Round to 3 decimal places, half-up — the precision the spec directs for D and G. */
1383
1386
  function round3(v) {
1384
1387
  return Math.round((v + Number.EPSILON) * 1e3) / 1e3;
1385
1388
  }
1386
1389
  function computeSchedule4(input) {
1387
1390
  const issues = [];
1388
- const albertaTaxableIncome = nn$32(input.albertaTaxableIncome);
1389
- const royaltyTaxDeduction = nn$32(input.royaltyTaxDeduction);
1391
+ const albertaTaxableIncome = nn$29(input.albertaTaxableIncome);
1392
+ const royaltyTaxDeduction = nn$29(input.royaltyTaxDeduction);
1390
1393
  const allocationFactor = input.allocationFactor ?? 0;
1391
- const basicAlbertaTax = nn$32(input.basicAlbertaTax);
1394
+ const basicAlbertaTax = nn$29(input.basicAlbertaTax);
1392
1395
  const denominator = (albertaTaxableIncome - royaltyTaxDeduction) * allocationFactor;
1393
1396
  const countries = input.countries.map((c) => {
1394
1397
  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);
1398
+ const netForeignInvestmentIncome = nn$29(c.netForeignInvestmentIncome);
1399
+ const fedForeignTaxPaid = nn$29(c.fedForeignTaxPaid);
1400
+ const fedIta2012Deduction = nn$29(c.fedIta2012Deduction);
1398
1401
  const albertaDeduction = Math.max(c.albertaActa82Deduction ?? fedIta2012Deduction, fedIta2012Deduction);
1399
1402
  const taxPaidNetOfDeduction = Math.max(0, fedForeignTaxPaid - albertaDeduction);
1400
- const federalNonBusinessForeignTaxCredit = nn$32(c.fedNonBusinessForeignTaxCredit);
1403
+ const federalNonBusinessForeignTaxCredit = nn$29(c.fedNonBusinessForeignTaxCredit);
1401
1404
  let incomeProrationAmount;
1402
1405
  if (denominator === 0) {
1403
1406
  incomeProrationAmount = 0;
@@ -1453,765 +1456,6 @@ function schedule4Values(result) {
1453
1456
  };
1454
1457
  }
1455
1458
  //#endregion
1456
- //#region src/t2/at1/schedules/schedule5-royalty-tax-deduction.ts
1457
- const nn$31 = (v) => Math.max(0, Math.round(v ?? 0));
1458
- const num$2 = (v) => Math.round(v ?? 0);
1459
- function processSuccessoredPool(entries, label, issues) {
1460
- return (entries ?? []).map((e, i) => {
1461
- const hasBrought = e.poolBroughtForward !== void 0;
1462
- const hasAcquired = e.acquisitionAmount !== void 0;
1463
- 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
- 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);
1466
- const baseKind = hasBrought ? "broughtForward" : hasAcquired ? "acquired" : "unspecified";
1467
- const propertyIncome = nn$31(e.propertyIncome);
1468
- const claim = Math.min(base, propertyIncome);
1469
- return {
1470
- vendorName: e.vendorName,
1471
- dateOfEvent: e.dateOfEvent,
1472
- base,
1473
- baseKind,
1474
- propertyIncome,
1475
- claim,
1476
- carryForwardBeforeTransfer: base - claim
1477
- };
1478
- });
1479
- }
1480
- function computeAlbertaSchedule5(input) {
1481
- 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;
1487
- const unsuccessoredPoolAvailable = crownCharges - resourceAllowance - reimbursements + attributedRoyaltyIncomeCarryForwardIn;
1488
- const hasSuccessoredPools = input.hasSuccessoredPools ?? false;
1489
- 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.");
1490
- const secondSuccessoredPools = hasSuccessoredPools ? processSuccessoredPool(input.secondSuccessoredPools, "second successored (SSPI)", issues) : [];
1491
- const firstSuccessoredPools = hasSuccessoredPools ? processSuccessoredPool(input.firstSuccessoredPools, "first successored (FSPI)", issues) : [];
1492
- const secondSuccessoredSubtotal = secondSuccessoredPools.reduce((s, e) => s + e.carryForwardBeforeTransfer, 0);
1493
- const firstSuccessoredSubtotal = firstSuccessoredPools.reduce((s, e) => s + e.carryForwardBeforeTransfer, 0);
1494
- const successoredTotal = secondSuccessoredPools.reduce((s, e) => s + e.claim, 0) + firstSuccessoredPools.reduce((s, e) => s + e.claim, 0);
1495
- const albertaTaxableIncome = num$2(input.albertaTaxableIncomeBeforeDeduction);
1496
- const crtdMaxClaimable = Math.max(0, Math.min(unsuccessoredPoolAvailable, albertaTaxableIncome - successoredTotal));
1497
- const crtdClaim = input.crtdAmountClaimed != null ? Math.max(0, Math.min(Math.round(input.crtdAmountClaimed), crtdMaxClaimable)) : crtdMaxClaimable;
1498
- const poolAvailableCarryForward = unsuccessoredPoolAvailable - crtdClaim;
1499
- const transferredOnDisposal = nn$31(input.transferredOnDisposal);
1500
- const uncappedTotal = crtdClaim + successoredTotal;
1501
- const totalRoyaltyTaxDeduction = Math.max(0, Math.min(uncappedTotal, albertaTaxableIncome));
1502
- 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.`);
1503
- else issues.push(`Alberta Schedule 5: the combined Royalty Tax Deduction (005016 + 005140 = ${uncappedTotal}) exceeds Alberta taxable income before the deduction (AT1 line 062 = ${albertaTaxableIncome}); AT1 line 064 is capped at ${totalRoyaltyTaxDeduction} per the spec.`);
1504
- const netOfResourceAllowance = crownCharges - resourceAllowance;
1505
- const carryForwardRaw = netOfResourceAllowance >= 0 ? netOfResourceAllowance + attributedRoyaltyIncomeCarryForwardIn - totalRoyaltyTaxDeduction - transferredOnDisposal : attributedRoyaltyIncomeCarryForwardIn - totalRoyaltyTaxDeduction - transferredOnDisposal;
1506
- const attributedRoyaltyIncomeCarryForwardOut = Math.max(0, carryForwardRaw);
1507
- if (input.poolTransfer) {
1508
- const { type, acquirerName } = input.poolTransfer;
1509
- if ((type === 1 || type === 2) && !acquirerName) issues.push("Alberta Schedule 5: pool transfer type (005026) is 1 or 2, but the acquiring corporation's legal name (005027) is missing.");
1510
- if (type === 3 && acquirerName) issues.push("Alberta Schedule 5: pool transfer type (005026) is 3 (no transfer), but an acquiring corporation name (005027) was supplied. Per the spec, 005027 must be blank when 005026 = 3.");
1511
- }
1512
- if (input.changeInControlEndedPrecedingYear !== void 0 && input.at1TaxYearEndChanged !== void 0 && input.at1TaxYearEndChangeReason !== void 0) {
1513
- const cicChangedYearEnd = input.at1TaxYearEndChanged && input.at1TaxYearEndChangeReason === 2;
1514
- if (input.changeInControlEndedPrecedingYear !== cicChangedYearEnd) issues.push(`Alberta Schedule 5: 005100 (change in control ended the preceding taxation year) is ${input.changeInControlEndedPrecedingYear}, which is inconsistent with AT1 core 000038/000039 (tax year end changed due to change in control = ${cicChangedYearEnd}). Per the spec, these must agree in both directions.`);
1515
- }
1516
- const formRequired = crownCharges > 0 || attributedRoyaltyIncomeCarryForwardIn > 0 || hasSuccessoredPools;
1517
- return {
1518
- crownCharges,
1519
- resourceAllowance,
1520
- reimbursements,
1521
- predecessorTransfersTotal,
1522
- attributedRoyaltyIncomeCarryForwardIn,
1523
- unsuccessoredPoolAvailable,
1524
- crtdMaxClaimable,
1525
- crtdClaim,
1526
- poolAvailableCarryForward,
1527
- transferredOnDisposal,
1528
- secondSuccessoredPools,
1529
- firstSuccessoredPools,
1530
- secondSuccessoredSubtotal,
1531
- firstSuccessoredSubtotal,
1532
- successoredTotal,
1533
- totalRoyaltyTaxDeduction,
1534
- attributedRoyaltyIncomeCarryForwardOut,
1535
- ...input.poolTransfer !== void 0 ? { poolTransfer: input.poolTransfer } : {},
1536
- ...input.changeInControlEndedPrecedingYear !== void 0 ? { changeInControlEndedPrecedingYear: input.changeInControlEndedPrecedingYear } : {},
1537
- formRequired,
1538
- issues
1539
- };
1540
- }
1541
- /** `005` + field id + 3-digit occurrence — the nine-digit AT1 line item id. */
1542
- function schedule5LineItemId(fieldId, occurrence = 1) {
1543
- return `005${fieldId}${String(occurrence).padStart(3, "0")}`;
1544
- }
1545
- function putSuccessoredPool(values, entries, fields) {
1546
- entries.forEach((e, i) => {
1547
- const n = i + 1;
1548
- const put = (fieldId, value) => values.push({
1549
- lineItemId: schedule5LineItemId(fieldId, n),
1550
- value
1551
- });
1552
- put(fields.vendorName, e.vendorName);
1553
- put(fields.dateOfEvent, e.dateOfEvent);
1554
- if (e.baseKind === "broughtForward") put(fields.broughtForward, e.base);
1555
- else if (e.baseKind === "acquired") put(fields.acquired, e.base);
1556
- put(fields.propertyIncome, e.propertyIncome);
1557
- put(fields.claim, e.claim);
1558
- put(fields.carryForward, e.carryForwardBeforeTransfer);
1559
- });
1560
- }
1561
- function schedule5Values(result) {
1562
- const values = [];
1563
- const put = (fieldId, value) => values.push({
1564
- lineItemId: schedule5LineItemId(fieldId),
1565
- value
1566
- });
1567
- put("001", result.crownCharges);
1568
- put("005", result.resourceAllowance);
1569
- put("007", result.reimbursements);
1570
- put("011", result.attributedRoyaltyIncomeCarryForwardIn);
1571
- put("016", result.crtdClaim);
1572
- put("017", result.poolAvailableCarryForward);
1573
- put("023", result.transferredOnDisposal);
1574
- put("025", result.attributedRoyaltyIncomeCarryForwardOut);
1575
- if (result.poolTransfer) {
1576
- put("026", result.poolTransfer.type);
1577
- if (result.poolTransfer.acquirerName) put("027", result.poolTransfer.acquirerName);
1578
- }
1579
- if (result.changeInControlEndedPrecedingYear !== void 0) put("100", result.changeInControlEndedPrecedingYear ? 1 : 2);
1580
- putSuccessoredPool(values, result.secondSuccessoredPools, {
1581
- vendorName: "101",
1582
- dateOfEvent: "103",
1583
- broughtForward: "105",
1584
- acquired: "107",
1585
- propertyIncome: "109",
1586
- claim: "111",
1587
- carryForward: "113"
1588
- });
1589
- put("115", result.secondSuccessoredSubtotal);
1590
- putSuccessoredPool(values, result.firstSuccessoredPools, {
1591
- vendorName: "121",
1592
- dateOfEvent: "123",
1593
- broughtForward: "125",
1594
- acquired: "127",
1595
- propertyIncome: "129",
1596
- claim: "131",
1597
- carryForward: "133"
1598
- });
1599
- put("135", result.firstSuccessoredSubtotal);
1600
- put("140", result.successoredTotal);
1601
- return {
1602
- scheduleId: "005",
1603
- values
1604
- };
1605
- }
1606
- //#endregion
1607
- //#region src/t2/at1/schedules/schedule6-royalty-tax-credit.ts
1608
- const rd$1 = (v) => Math.round(v ?? 0);
1609
- const nn$30 = (v) => Math.max(0, Math.round(v ?? 0));
1610
- const round4$1 = (v) => Math.round(v * 1e4) / 1e4;
1611
- function computeWeightedAverageRate(quarters, issues) {
1612
- if (quarters.length === 0) {
1613
- issues.push("Alberta Schedule 6: no quarters were supplied for the weighted average rate (006008 is mandatory). Defaulted to 0 — supply the RTC quarterly rate(s) from Alberta Treasury Board and Finance's published rate table.");
1614
- return 0;
1615
- }
1616
- const totalDays = quarters.reduce((s, q) => s + Math.max(0, q.days), 0);
1617
- if (totalDays <= 0) {
1618
- issues.push("Alberta Schedule 6: the quarters supplied for 006008 total zero days.");
1619
- return 0;
1620
- }
1621
- const weighted = quarters.reduce((s, q) => s + Math.max(0, q.days) / totalDays * q.rate, 0);
1622
- return round4$1(weighted);
1623
- }
1624
- function resolveAllocations(allocations, pool, issues) {
1625
- const totalRequested = allocations.reduce((s, a) => s + nn$30(a.allocatedAmount), 0);
1626
- 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
- let remaining = pool;
1628
- return allocations.map((a) => {
1629
- const requestedAmount = nn$30(a.allocatedAmount);
1630
- const allocatedAmount = Math.min(requestedAmount, remaining);
1631
- remaining -= allocatedAmount;
1632
- return {
1633
- name: a.name,
1634
- ...a.albertaCan !== void 0 ? { albertaCan: a.albertaCan } : {},
1635
- allocatedAmount,
1636
- requestedAmount
1637
- };
1638
- });
1639
- }
1640
- function schedule6LineItemId(fieldId, occurrence = 1) {
1641
- return `006${fieldId}${String(occurrence).padStart(3, "0")}`;
1642
- }
1643
- /**
1644
- * Emits every field this module's own MAPPINGS transcription actually defines
1645
- * a number for: 006002/004/006/008, and — only when the corporation is
1646
- * associated — the ACRS section (006022-028) and the AACRS allocation table
1647
- * (006030-034, one occurrence per row).
1648
- *
1649
- * ── No credit amount is filed here, because none exists on this schedule ────
1650
- *
1651
- * See the module docstring's "CONFIRMED: there is no 'credit' dollar amount
1652
- * to compute here" section — the Alberta Royalty Tax Credit is an instalment
1653
- * program (AT1 jacket line 000082, the shared "Payments & Instalments"
1654
- * schedule), not a value Schedule 6 computes and files. This builder emits
1655
- * exactly the three components the schedule DOES define (006004, 006006,
1656
- * 006008) plus the ACRS/AACRS detail when associated — matching
1657
- * `schedule3Values`'s `At1ScheduleDataLike` shape exactly: `{ scheduleId,
1658
- * values }`.
1659
- */
1660
- function schedule6Values(result) {
1661
- const values = [];
1662
- const put = (fieldId, value, occurrence = 1) => values.push({
1663
- lineItemId: schedule6LineItemId(fieldId, occurrence),
1664
- value
1665
- });
1666
- put("002", result.associatedWithCrownRoyaltyCorporations ? 1 : 2);
1667
- put("004", result.albertaCrownRoyaltyIncurred);
1668
- put("006", result.crownRoyaltyShelter);
1669
- put("008", result.weightedAverageRate);
1670
- if (result.associatedWithCrownRoyaltyCorporations && result.longestAssociatedYear) {
1671
- if (result.longestAssociatedYear.albertaCan !== void 0) values.push({
1672
- lineItemId: schedule6LineItemId("022"),
1673
- value: result.longestAssociatedYear.albertaCan
1674
- });
1675
- if (result.longestAssociatedYear.taxationYearBeginning !== void 0) values.push({
1676
- lineItemId: schedule6LineItemId("024"),
1677
- value: result.longestAssociatedYear.taxationYearBeginning
1678
- });
1679
- if (result.longestAssociatedYear.taxationYearEnding !== void 0) values.push({
1680
- lineItemId: schedule6LineItemId("026"),
1681
- value: result.longestAssociatedYear.taxationYearEnding
1682
- });
1683
- put("028", result.longestAssociatedYear.days);
1684
- result.allocations.forEach((a, i) => {
1685
- const occurrence = i + 1;
1686
- values.push({
1687
- lineItemId: schedule6LineItemId("030", occurrence),
1688
- value: a.name
1689
- });
1690
- if (a.albertaCan !== void 0) values.push({
1691
- lineItemId: schedule6LineItemId("032", occurrence),
1692
- value: a.albertaCan
1693
- });
1694
- put("034", a.allocatedAmount, occurrence);
1695
- });
1696
- }
1697
- return {
1698
- scheduleId: "006",
1699
- values
1700
- };
1701
- }
1702
- function computeAlbertaSchedule6(input) {
1703
- const issues = [];
1704
- const associatedWithCrownRoyaltyCorporations = input.associatedWithCrownRoyaltyCorporations ?? false;
1705
- const albertaCrownRoyaltyIncurred = rd$1(input.albertaCrownRoyaltyIncurred);
1706
- const weightedAverageRate = computeWeightedAverageRate(input.quarters ?? [], issues);
1707
- const formRequired = albertaCrownRoyaltyIncurred > 0;
1708
- if (!associatedWithCrownRoyaltyCorporations) {
1709
- const days = Math.max(0, Math.min(input.taxationYearDays ?? 365, 365));
1710
- return {
1711
- associatedWithCrownRoyaltyCorporations,
1712
- albertaCrownRoyaltyIncurred,
1713
- crownRoyaltyShelter: Math.round(2e6 * (days / 365)),
1714
- weightedAverageRate,
1715
- aggregateShelterPool: 0,
1716
- allocations: [],
1717
- totalAllocated: 0,
1718
- formRequired,
1719
- issues
1720
- };
1721
- }
1722
- if (!input.longestAssociatedYear) issues.push("Alberta Schedule 6: the corporation is associated with one or more corporations that incurred Alberta Crown Royalty (006002 = 1), but no ACRS data (006022-006028, the associated corporation with the longest taxation year) was supplied. The Crown Royalty Shelter pool defaulted to zero.");
1723
- const days = Math.max(0, Math.min(input.longestAssociatedYear?.days ?? 0, 365));
1724
- const aggregateShelterPool = Math.round(2e6 * (days / 365));
1725
- const rawAllocations = input.allocations ?? [];
1726
- if (rawAllocations.length === 0) issues.push("Alberta Schedule 6: the corporation is associated (006002 = 1), but no AACRS allocation rows (006030-006034) were supplied. This filer's own Crown Royalty Shelter (006006) defaulted to zero.");
1727
- const allocations = resolveAllocations(rawAllocations, aggregateShelterPool, issues);
1728
- const totalAllocated = allocations.reduce((s, a) => s + a.allocatedAmount, 0);
1729
- return {
1730
- associatedWithCrownRoyaltyCorporations,
1731
- albertaCrownRoyaltyIncurred,
1732
- crownRoyaltyShelter: allocations[0]?.allocatedAmount ?? 0,
1733
- weightedAverageRate,
1734
- longestAssociatedYear: {
1735
- ...input.longestAssociatedYear?.albertaCan !== void 0 ? { albertaCan: input.longestAssociatedYear.albertaCan } : {},
1736
- ...input.longestAssociatedYear?.taxationYearBeginning !== void 0 ? { taxationYearBeginning: input.longestAssociatedYear.taxationYearBeginning } : {},
1737
- ...input.longestAssociatedYear?.taxationYearEnding !== void 0 ? { taxationYearEnding: input.longestAssociatedYear.taxationYearEnding } : {},
1738
- days
1739
- },
1740
- aggregateShelterPool,
1741
- allocations,
1742
- totalAllocated,
1743
- formRequired,
1744
- issues
1745
- };
1746
- }
1747
- //#endregion
1748
- //#region src/t2/at1/schedules/schedule7-royalty-supplemental.ts
1749
- /** Signed whole-dollar rounding — no floor, several of these lines are marked "+/-". */
1750
- const rd = (v) => Math.round(v ?? 0);
1751
- /** Non-negative whole-dollar rounding, for the "+"-only lines. */
1752
- const nn$29 = (v) => Math.max(0, Math.round(v ?? 0));
1753
- const round4 = (v) => Math.round(v * 1e4) / 1e4;
1754
- function resolvePartnership(p, index, issues) {
1755
- if (!p.name) issues.push(`Alberta Schedule 7: partnership row ${index + 1} has no name (007071 is mandatory for every PITI occurrence).`);
1756
- if (p.interestPercent < 0 || p.interestPercent > 1) issues.push(`Alberta Schedule 7: ${p.name || `partnership row ${index + 1}`} has an interest of ${p.interestPercent}, expected a decimal between 0 and 1 (007073, e.g. .7500 for 75%).`);
1757
- return {
1758
- name: p.name,
1759
- interestPercent: round4(p.interestPercent),
1760
- ...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)
1764
- };
1765
- }
1766
- function resolveAdjustment(a, index, issues) {
1767
- if (!a.priorProductionPeriodEnd) issues.push(`Alberta Schedule 7: prior-year adjustment row ${index + 1} has no prior production period (007083 is mandatory for every ACRA occurrence).`);
1768
- if (a.sourceOfAdjustment !== 1 && a.sourceOfAdjustment !== 2) issues.push(`Alberta Schedule 7: prior-year adjustment row ${index + 1} has no valid source code (007085 must be 1 = Dept. of Resource Development or 2 = Operator).`);
1769
- return {
1770
- ...a.priorProductionPeriodEnd !== void 0 ? { priorProductionPeriodEnd: a.priorProductionPeriodEnd } : {},
1771
- ...a.sourceOfAdjustment !== void 0 ? { sourceOfAdjustment: a.sourceOfAdjustment } : {},
1772
- increase: nn$29(a.increase),
1773
- decrease: nn$29(a.decrease),
1774
- adjustmentNotEligibleForCredit: rd(a.adjustmentNotEligibleForCredit)
1775
- };
1776
- }
1777
- function schedule7LineItemId(fieldId, occurrence = 1) {
1778
- return `007${fieldId}${String(occurrence).padStart(3, "0")}`;
1779
- }
1780
- /**
1781
- * Emits CPI (007003-029), the computed totals 007051 and 007061, and the two
1782
- * repeating sections — PITI (007071-081, one occurrence per partnership) and
1783
- * ACRA (007083-091, one occurrence per prior-year adjustment).
1784
- *
1785
- * 007061 is filed even though it has no defining row of its own anywhere in
1786
- * this schedule's MAPPINGS block (spec lines 6654-7251) — see the module
1787
- * docstring's "Two totals with NO defining row of their own in this MAPPINGS
1788
- * table" section. It is a real Schedule 7 output line: AT1 Schedule 5's own
1789
- * field 005001 definition (spec lines 5237-5248) names it explicitly as
1790
- * "Schedule 7, line 061" and gives its formula in full, so it is filed here
1791
- * under that citation rather than omitted for lack of a home row.
1792
- */
1793
- function schedule7Values(result) {
1794
- const values = [];
1795
- const put = (fieldId, value, occurrence = 1) => values.push({
1796
- lineItemId: schedule7LineItemId(fieldId, occurrence),
1797
- value
1798
- });
1799
- put("003", result.eligibleCrownRoyalty);
1800
- put("005", result.otherRoyaltiesNotEligible);
1801
- put("007", result.royaltyPaidToOtherJurisdictions);
1802
- put("009", result.nonDeductibleCrownLeaseRentals);
1803
- put("011", result.mineralTaxes);
1804
- put("013", result.saskatchewanResourcesSurcharge);
1805
- result.otherNonDeductibleCrownChargeTypes.forEach((name, i) => {
1806
- values.push({
1807
- lineItemId: schedule7LineItemId(String(14 + i).padStart(3, "0")),
1808
- value: name
1809
- });
1810
- });
1811
- put("017", result.otherNonDeductibleCrownCharges);
1812
- put("025", result.crownLeaseRentalsCapitalized);
1813
- if (result.otherBalanceSheetDeductionName !== void 0) values.push({
1814
- lineItemId: schedule7LineItemId("027"),
1815
- value: result.otherBalanceSheetDeductionName
1816
- });
1817
- put("029", result.otherBalanceSheetDeduction);
1818
- result.partnerships.forEach((p, i) => {
1819
- const occurrence = i + 1;
1820
- values.push({
1821
- lineItemId: schedule7LineItemId("071", occurrence),
1822
- value: p.name
1823
- });
1824
- put("073", p.interestPercent, occurrence);
1825
- if (p.fiscalPeriodEnd !== void 0) values.push({
1826
- lineItemId: schedule7LineItemId("075", occurrence),
1827
- value: p.fiscalPeriodEnd
1828
- });
1829
- put("077", p.shareEligibleForCredit, occurrence);
1830
- put("079", p.shareOtherRoyaltiesNotEligible, occurrence);
1831
- put("081", p.shareOtherCrownChargesEligibleForDeduction, occurrence);
1832
- });
1833
- result.priorYearAdjustments.forEach((a, i) => {
1834
- const occurrence = i + 1;
1835
- if (a.priorProductionPeriodEnd !== void 0) values.push({
1836
- lineItemId: schedule7LineItemId("083", occurrence),
1837
- value: a.priorProductionPeriodEnd
1838
- });
1839
- if (a.sourceOfAdjustment !== void 0) put("085", a.sourceOfAdjustment, occurrence);
1840
- put("087", a.increase, occurrence);
1841
- put("089", a.decrease, occurrence);
1842
- put("091", a.adjustmentNotEligibleForCredit, occurrence);
1843
- });
1844
- put("051", result.totalAdjustments);
1845
- put("061", result.crownChargesNetOfReimbursements);
1846
- return {
1847
- scheduleId: "007",
1848
- values
1849
- };
1850
- }
1851
- function computeAlbertaSchedule7(input) {
1852
- const issues = [];
1853
- const eligibleCrownRoyalty = rd(input.eligibleCrownRoyalty);
1854
- const otherRoyaltiesNotEligible = rd(input.otherRoyaltiesNotEligible);
1855
- const royaltyPaidToOtherJurisdictions = rd(input.royaltyPaidToOtherJurisdictions);
1856
- const nonDeductibleCrownLeaseRentals = rd(input.nonDeductibleCrownLeaseRentals);
1857
- const mineralTaxes = rd(input.mineralTaxes);
1858
- const saskatchewanResourcesSurcharge = rd(input.saskatchewanResourcesSurcharge);
1859
- const otherNonDeductibleCrownChargeTypes = (input.otherNonDeductibleCrownChargeTypes ?? []).slice(0, 3);
1860
- if ((input.otherNonDeductibleCrownChargeTypes?.length ?? 0) > 3) issues.push("Alberta Schedule 7: more than three other non-deductible crown charge types were supplied (007014/015/016 allow three); only the first three were kept.");
1861
- let otherNonDeductibleCrownCharges = rd(input.otherNonDeductibleCrownCharges);
1862
- if (otherNonDeductibleCrownChargeTypes.length === 0 && otherNonDeductibleCrownCharges !== 0) {
1863
- issues.push("Alberta Schedule 7: an amount was given for other non-deductible crown charges (007017) but no charge type was named (007014/015/016). The spec defaults 007017 to zero when no type is named; the amount was zeroed out.");
1864
- otherNonDeductibleCrownCharges = 0;
1865
- }
1866
- const crownLeaseRentalsCapitalized = rd(input.crownLeaseRentalsCapitalized);
1867
- let otherBalanceSheetDeduction = nn$29(input.otherBalanceSheetDeduction);
1868
- if (!input.otherBalanceSheetDeductionName && otherBalanceSheetDeduction !== 0) {
1869
- 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
- otherBalanceSheetDeduction = 0;
1871
- }
1872
- const partnerships = (input.partnerships ?? []).map((p, i) => resolvePartnership(p, i, issues));
1873
- const totalPartnershipShareEligibleForCredit = partnerships.reduce((s, p) => s + p.shareEligibleForCredit, 0);
1874
- const totalPartnershipShareOtherRoyaltiesNotEligible = partnerships.reduce((s, p) => s + p.shareOtherRoyaltiesNotEligible, 0);
1875
- const totalPartnershipShareOtherCrownCharges = partnerships.reduce((s, p) => s + p.shareOtherCrownChargesEligibleForDeduction, 0);
1876
- const priorYearAdjustments = (input.priorYearAdjustments ?? []).map((a, i) => resolveAdjustment(a, i, issues));
1877
- const totalIncrease = priorYearAdjustments.reduce((s, a) => s + a.increase, 0);
1878
- const totalDecrease = priorYearAdjustments.reduce((s, a) => s + a.decrease, 0);
1879
- const totalAdjustmentNotEligible = priorYearAdjustments.reduce((s, a) => s + a.adjustmentNotEligibleForCredit, 0);
1880
- const totalAdjustments = priorYearAdjustments.length === 0 ? 0 : totalIncrease - totalDecrease + totalAdjustmentNotEligible;
1881
- const crownChargesNetOfReimbursements = eligibleCrownRoyalty + otherRoyaltiesNotEligible + royaltyPaidToOtherJurisdictions + nonDeductibleCrownLeaseRentals + mineralTaxes + saskatchewanResourcesSurcharge + otherNonDeductibleCrownCharges + crownLeaseRentalsCapitalized + otherBalanceSheetDeduction + totalPartnershipShareEligibleForCredit + totalPartnershipShareOtherRoyaltiesNotEligible + totalPartnershipShareOtherCrownCharges - totalAdjustments;
1882
- const albertaCrownRoyaltyForSchedule6 = eligibleCrownRoyalty + totalPartnershipShareEligibleForCredit - totalIncrease + totalDecrease;
1883
- return {
1884
- eligibleCrownRoyalty,
1885
- otherRoyaltiesNotEligible,
1886
- royaltyPaidToOtherJurisdictions,
1887
- nonDeductibleCrownLeaseRentals,
1888
- mineralTaxes,
1889
- saskatchewanResourcesSurcharge,
1890
- otherNonDeductibleCrownChargeTypes,
1891
- otherNonDeductibleCrownCharges,
1892
- crownLeaseRentalsCapitalized,
1893
- ...input.otherBalanceSheetDeductionName !== void 0 ? { otherBalanceSheetDeductionName: input.otherBalanceSheetDeductionName } : {},
1894
- otherBalanceSheetDeduction,
1895
- partnerships,
1896
- totalPartnershipShareEligibleForCredit,
1897
- totalPartnershipShareOtherRoyaltiesNotEligible,
1898
- totalPartnershipShareOtherCrownCharges,
1899
- priorYearAdjustments,
1900
- totalAdjustments,
1901
- crownChargesNetOfReimbursements,
1902
- albertaCrownRoyaltyForSchedule6,
1903
- issues
1904
- };
1905
- }
1906
- //#endregion
1907
- //#region src/t2/at1/schedules/schedule8-political-contributions.ts
1908
- const nn$28 = (v) => Math.max(0, Math.round(v ?? 0));
1909
- function yearOf(dateIso) {
1910
- if (!dateIso || dateIso.length < 4) return void 0;
1911
- const y = Number(dateIso.slice(0, 4));
1912
- return Number.isFinite(y) ? y : void 0;
1913
- }
1914
- /** Tiered rate for the "all made in 2003 or earlier" branch. */
1915
- function tierTo2003(a) {
1916
- if (a <= 150) return a * .75;
1917
- if (a <= 825) return 112.5 + (a - 150) * .5;
1918
- return 450 + (a - 825) * .333;
1919
- }
1920
- /** Tiered rate for the "all made in 2004 or later" branch. */
1921
- function tierFrom2004(a) {
1922
- if (a <= 200) return a * .75;
1923
- if (a <= 900) return 150 + (a - 200) * .5;
1924
- return 600 + (a - 900) * .333;
1925
- }
1926
- function computeSchedule8$1(input) {
1927
- const issues = [];
1928
- const contributions = input.contributions ?? [];
1929
- contributions.forEach((c, i) => {
1930
- 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
- if (!c.receiptNumber) issues.push(`Alberta Schedule 8: contribution #${i + 1} (${c.name || "unnamed"}) has no official receipt number (008004).`);
1932
- });
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);
1939
- const hasTo2003 = directTo2003 > 0 || partnershipContributionsTo2003 > 0;
1940
- const hasFrom2004 = directFrom2004 > 0 || partnershipContributionsFrom2004 > 0;
1941
- if (!hasTo2003 && !hasFrom2004) return {
1942
- contributions,
1943
- partnershipContributionsTo2003,
1944
- partnershipContributionsFrom2004,
1945
- period: "none",
1946
- creditBeforeCeiling: 0,
1947
- credit: 0,
1948
- issues
1949
- };
1950
- const taxYearBeginYear = yearOf(input.taxYearBegin);
1951
- const taxYearEndYear = yearOf(input.taxYearEnd);
1952
- const taxYearStraddles2003to2004 = taxYearBeginYear === 2003 && taxYearEndYear === 2004;
1953
- const ceiling = input.remainingBasicTax;
1954
- let period;
1955
- let rawCredit;
1956
- let credit;
1957
- if (hasTo2003 && !hasFrom2004) {
1958
- period = "to-2003";
1959
- rawCredit = tierTo2003(totalDirect + partnershipContributionsTo2003);
1960
- if (ceiling == null) {
1961
- issues.push("Alberta Schedule 8: remainingBasicTax (000068 − (000070+000071+000072)) was not supplied, so no political contributions credit can be claimed for the 2003-or-earlier rate period.");
1962
- credit = 0;
1963
- } else credit = Math.max(0, Math.round(Math.min(rawCredit, 750, ceiling)));
1964
- } else if (hasFrom2004 && !hasTo2003) {
1965
- period = "from-2004";
1966
- rawCredit = tierFrom2004(totalDirect + partnershipContributionsFrom2004);
1967
- if (ceiling == null) {
1968
- issues.push("Alberta Schedule 8: remainingBasicTax (000068 − (000070+000071+000072)) was not supplied, so no political contributions credit can be claimed for the 2004-or-later rate period.");
1969
- credit = 0;
1970
- } else credit = Math.max(0, Math.round(Math.min(rawCredit, 1e3, ceiling)));
1971
- } else if (taxYearStraddles2003to2004) {
1972
- period = "straddle-2003-2004";
1973
- const x = directIn2004Only + partnershipContributionsFrom2004;
1974
- const y = totalDirect + partnershipContributionsTo2003 + partnershipContributionsFrom2004;
1975
- const a = Math.min(y, 150);
1976
- const b = Math.min(Math.max(0, x - a), 50);
1977
- const c = Math.min(Math.max(0, y - (a + b)), 675);
1978
- const d = Math.min(Math.max(0, x - (a + b + c)), 225);
1979
- const e = Math.min(Math.max(0, y - (a + b + c + d)), 900);
1980
- const f = Math.min(Math.max(0, x - (a + b + c + d + e)), 300);
1981
- rawCredit = .75 * a + .75 * b + .5 * c + .5 * d + e / 3 + f / 3;
1982
- credit = Math.max(0, Math.round(rawCredit));
1983
- } else {
1984
- period = "none";
1985
- rawCredit = 0;
1986
- credit = 0;
1987
- issues.push("Alberta Schedule 8: contributions span both the 2003-or-earlier and 2004-or-later rate periods, but the tax year does not begin in 2003 and end in 2004 — the spec only defines a mixed-period formula for that straddling tax year. No credit computed.");
1988
- }
1989
- return {
1990
- contributions,
1991
- partnershipContributionsTo2003,
1992
- partnershipContributionsFrom2004,
1993
- period,
1994
- creditBeforeCeiling: Math.round(rawCredit),
1995
- credit,
1996
- issues
1997
- };
1998
- }
1999
- /**
2000
- * Net File line items for AT1 Schedule 8: one PCD occurrence per contribution
2001
- * (002 name, 004 receipt number, 006 date, 008 amount), plus the two APC
2002
- * partnership totals (012, 013).
2003
- *
2004
- * Does NOT emit jacket line 000074 (the actual tax credit) — that is a
2005
- * jacket line, not a Schedule 8 line. Use `result.credit` for that.
2006
- */
2007
- function schedule8Values(result) {
2008
- const values = [];
2009
- result.contributions.forEach((c, i) => {
2010
- const n = i + 1;
2011
- const put = (fieldId, value) => values.push({
2012
- lineItemId: at1LineItemId("008", fieldId, n),
2013
- value
2014
- });
2015
- put("002", c.name);
2016
- put("004", c.receiptNumber);
2017
- put("006", c.dateOfDonation);
2018
- put("008", Math.max(0, Math.round(c.amount)));
2019
- });
2020
- values.push({
2021
- lineItemId: at1LineItemId("008", "012"),
2022
- value: result.partnershipContributionsTo2003
2023
- });
2024
- values.push({
2025
- lineItemId: at1LineItemId("008", "013"),
2026
- value: result.partnershipContributionsFrom2004
2027
- });
2028
- return {
2029
- scheduleId: "008",
2030
- values
2031
- };
2032
- }
2033
- //#endregion
2034
- //#region src/t2/at1/schedules/schedule9-sred-tax-credit.ts
2035
- const nn$27 = (v) => Math.max(0, Math.round(v ?? 0));
2036
- /** Signed whole-dollar rounding, for fields the spec marks "+/-". */
2037
- const signed = (v) => Math.round(v);
2038
- /** 009120's flat rate — "lesser of line 009031 and 009108 X 10%". */
2039
- const ALBERTA_SRED_TAX_CREDIT_RATE = .1;
2040
- /** Alberta's SR&ED program did not exist before this date (line 009104's note). */
2041
- const ALBERTA_SRED_PROGRAM_START = "2009-01-01";
2042
- /** Alberta SR&ED expenditures carried out after this date are not eligible (module docstring). */
2043
- const ALBERTA_SRED_EXPENDITURE_CUTOFF = "2019-12-31";
2044
- /**
2045
- * 009104 / 009206's day-prorated $4,000,000 expenditure limit. Days are clamped
2046
- * to [0, 366] — 366 only for a year genuinely spanning a February 29, per the
2047
- * spec's own note.
2048
- */
2049
- function computeSchedule9MaximumExpenditureLimit(daysInTaxYear = 365) {
2050
- return Math.round(4e6 * (Math.max(0, Math.min(daysInTaxYear, 366)) / 365));
2051
- }
2052
- function computeAlbertaSchedule9(input) {
2053
- 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);
2065
- 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
- const priorYearItcAlbertaPortion = totalFederalExpendituresAllYears > 0 ? Math.round(priorYearFederalItcReceived * totalAlbertaExpendituresAllYears / totalFederalExpendituresAllYears) : 0;
2067
- 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.");
2068
- const derivedEligibleExpenditures = albertaPortionOfExpenditures - federalProxyAmountInAlbertaPortion + albertaProxyAmount + albertaCreditReducingFederalExpense - priorYearItcAlbertaPortion + albertaPortionOfRepayments;
2069
- const eligibleExpenditures = input.eligibleExpenditures !== void 0 ? signed(input.eligibleExpenditures) : derivedEligibleExpenditures;
2070
- if (input.eligibleExpenditures === void 0) issues.push(`Alberta Schedule 9: line 009031 ("Total eligible expenditures for Alberta purposes") has no formula in the TRA spec's mapping tables (the text jumps from 009025 to 009040). Derived here as 005 − 007 + 009 + 011 − 023 + 025 = ${derivedEligibleExpenditures}, from the lines the spec captions unambiguously "Deduct"/"Add". Supply eligibleExpenditures directly to override with the authoritative figure — see the Guide to Claiming the Alberta SR&ED Tax Credit.`);
2071
- if (input.fieldOfScience === void 0) issues.push("Alberta Schedule 9: line 009040 (primary field of science or technology) is mandatory on the live form and was not supplied.");
2072
- const isAssociated = input.isAssociated ?? false;
2073
- const nonAssociatedMaximumExpenditureLimit = computeSchedule9MaximumExpenditureLimit(input.daysInTaxYear ?? 365);
2074
- let maximumExpenditureLimit;
2075
- if (isAssociated) if (input.allocatedExpenditureLimit === void 0) {
2076
- 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
- maximumExpenditureLimit = 0;
2078
- } else maximumExpenditureLimit = nn$27(input.allocatedExpenditureLimit);
2079
- else maximumExpenditureLimit = nonAssociatedMaximumExpenditureLimit;
2080
- 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
- const netCredit = Math.round(Math.min(eligibleExpenditures, maximumExpenditureLimit) * ALBERTA_SRED_TAX_CREDIT_RATE) - disposalRecapture - priorYearFederalItcAdjustment;
2082
- return {
2083
- federalQualifiedExpenditures,
2084
- albertaPortionOfExpenditures,
2085
- federalProxyAmountInAlbertaPortion,
2086
- albertaProxyAmount,
2087
- albertaCreditReducingFederalExpense,
2088
- priorYearFederalItcReceived,
2089
- totalAlbertaExpendituresAllYears,
2090
- totalFederalExpendituresAllYears,
2091
- priorYearItcAlbertaPortion,
2092
- albertaPortionOfRepayments,
2093
- eligibleExpenditures,
2094
- derivedEligibleExpenditures,
2095
- fieldOfScience: input.fieldOfScience,
2096
- isAssociated,
2097
- nonAssociatedMaximumExpenditureLimit,
2098
- maximumExpenditureLimit,
2099
- disposalRecapture,
2100
- priorYearFederalItcAdjustment,
2101
- netCredit,
2102
- issues
2103
- };
2104
- }
2105
- /**
2106
- * Allocate the day-prorated $4,000,000 maximum expenditure limit among an
2107
- * associated group (page 3). Per the spec, EACH occurrence of 009240 and the
2108
- * SUM of all occurrences are independently capped at the limit — unlike a
2109
- * running-remainder split, one member requesting more than the limit does not
2110
- * consume another member's room; it is simply capped and flagged.
2111
- */
2112
- function allocateSchedule9ExpenditureLimit(daysInLongestYear, requested) {
2113
- const issues = [];
2114
- const days = Math.max(0, Math.min(daysInLongestYear, 366));
2115
- const maximumExpenditureLimit = computeSchedule9MaximumExpenditureLimit(days);
2116
- const members = requested.map((m) => {
2117
- const requestedAmount = nn$27(m.allocated);
2118
- 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
- return {
2120
- name: m.name,
2121
- ...m.albertaCan !== void 0 ? { albertaCan: m.albertaCan } : {},
2122
- allocated: Math.min(requestedAmount, maximumExpenditureLimit)
2123
- };
2124
- });
2125
- const totalAllocated = members.reduce((s, m) => s + m.allocated, 0);
2126
- if (totalAllocated > maximumExpenditureLimit) issues.push(`Alberta Schedule 9: the associated group allocated a total of ${totalAllocated}, exceeding the maximum expenditure limit of ${maximumExpenditureLimit} (the sum of all 009240 occurrences cannot exceed $4,000,000 x 009206/365). The group must agree a valid split.`);
2127
- return {
2128
- daysInLongestYear: days,
2129
- maximumExpenditureLimit,
2130
- members,
2131
- totalAllocated,
2132
- claimantAllocatedAmount: members[0]?.allocated ?? 0,
2133
- unallocated: Math.max(0, maximumExpenditureLimit - totalAllocated),
2134
- issues
2135
- };
2136
- }
2137
- function schedule9LineItemId(fieldId, occurrence = 1) {
2138
- return `009${fieldId}${String(occurrence).padStart(3, "0")}`;
2139
- }
2140
- /**
2141
- * Field ids per the spec transcription in the module docstring: 003-025 (the
2142
- * expenditure buildup), 040 (field of science), 100-120 (the credit
2143
- * calculation), and — when `group` is supplied — 200-240 (page 3's
2144
- * allocation). Line 031 has no confirmed transmitted status of its own (see
2145
- * the module docstring's "line 009031 has no formula in the spec text"), but
2146
- * is filed anyway alongside 106 since both carry the identical "Total
2147
- * eligible expenditures for Alberta purposes" figure per the spec's own
2148
- * cross-reference ("106 ... Value must equal 009031").
2149
- */
2150
- function schedule9Values(result, group) {
2151
- const values = [];
2152
- const put = (fieldId, value) => values.push({
2153
- lineItemId: schedule9LineItemId(fieldId),
2154
- value
2155
- });
2156
- put("003", result.federalQualifiedExpenditures);
2157
- put("005", result.albertaPortionOfExpenditures);
2158
- put("007", result.federalProxyAmountInAlbertaPortion);
2159
- put("009", result.albertaProxyAmount);
2160
- put("011", result.albertaCreditReducingFederalExpense);
2161
- put("015", result.priorYearFederalItcReceived);
2162
- put("017", result.totalAlbertaExpendituresAllYears);
2163
- put("019", result.totalFederalExpendituresAllYears);
2164
- put("023", result.priorYearItcAlbertaPortion);
2165
- put("025", result.albertaPortionOfRepayments);
2166
- put("031", result.eligibleExpenditures);
2167
- if (result.fieldOfScience !== void 0) put("040", result.fieldOfScience);
2168
- put("100", result.isAssociated ? 1 : 2);
2169
- if (result.isAssociated) put("102", result.maximumExpenditureLimit);
2170
- else put("104", result.nonAssociatedMaximumExpenditureLimit);
2171
- put("106", result.eligibleExpenditures);
2172
- put("108", result.maximumExpenditureLimit);
2173
- put("112", result.disposalRecapture);
2174
- put("116", result.priorYearFederalItcAdjustment);
2175
- put("120", result.netCredit);
2176
- if (group) {
2177
- if (group.longestYearCan !== void 0) values.push({
2178
- lineItemId: schedule9LineItemId("200"),
2179
- value: group.longestYearCan
2180
- });
2181
- if (group.longestYearBegin !== void 0) values.push({
2182
- lineItemId: schedule9LineItemId("202"),
2183
- value: group.longestYearBegin
2184
- });
2185
- if (group.longestYearEnd !== void 0) values.push({
2186
- lineItemId: schedule9LineItemId("204"),
2187
- value: group.longestYearEnd
2188
- });
2189
- values.push({
2190
- lineItemId: schedule9LineItemId("206"),
2191
- value: group.allocation.daysInLongestYear
2192
- });
2193
- group.allocation.members.forEach((m, i) => {
2194
- const occurrence = i + 1;
2195
- values.push({
2196
- lineItemId: schedule9LineItemId("220", occurrence),
2197
- value: m.name
2198
- });
2199
- if (m.albertaCan !== void 0) values.push({
2200
- lineItemId: schedule9LineItemId("230", occurrence),
2201
- value: m.albertaCan
2202
- });
2203
- values.push({
2204
- lineItemId: schedule9LineItemId("240", occurrence),
2205
- value: m.allocated
2206
- });
2207
- });
2208
- }
2209
- return {
2210
- scheduleId: "009",
2211
- values
2212
- };
2213
- }
2214
- //#endregion
2215
1459
  //#region src/t2/at1/schedules/schedule15-resource-related-deductions.ts
2216
1460
  /**
2217
1461
  * Alberta AT1 Schedule 15 — Alberta Resource Related Deductions.
@@ -2358,7 +1602,7 @@ function schedule9Values(result, group) {
2358
1602
  *
2359
1603
  * Whole dollars, pure functions, no I/O.
2360
1604
  */
2361
- const nn$26 = (v) => Math.max(0, v ?? 0);
1605
+ const nn$28 = (v) => Math.max(0, v ?? 0);
2362
1606
  const num$1 = (v) => v ?? 0;
2363
1607
  const round$1 = (v) => Math.round(v);
2364
1608
  /** `override ?? federal`, tracking whether an Alberta-specific figure was actually entered. */
@@ -2862,7 +2106,7 @@ function computeCfreRegular(entries) {
2862
2106
  const partA = Math.max(CCOGPE_CLAIM_RATE * linear * pool, Math.min(CDE_CLAIM_RATE * linear * pool, foreignResourceIncome, sumForeignResourceIncome));
2863
2107
  const remainder = Math.max(0, pool - partA);
2864
2108
  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));
2109
+ const partB = Math.min(remainder, nn$28(e.globalForeignResourceLimit));
2866
2110
  claim = claimUpToCap$1(e.claimed, partA + partB, issues, `Schedule 15 CFRE regular, country ${e.federal.countryCode} (015293)`);
2867
2111
  }
2868
2112
  const closingBalance = pool - claim;
@@ -3294,15 +2538,15 @@ function schedule15Values(result) {
3294
2538
  function iegT661SourceLine(taxationYearEnd) {
3295
2539
  return taxationYearEnd >= "2024-12-16" ? "557" : "559";
3296
2540
  }
3297
- const nn$25 = (v) => Math.round(v ?? 0);
2541
+ const nn$27 = (v) => Math.round(v ?? 0);
3298
2542
  /** Line 031 = 005 − 007 + 009 + 011 + 025. Every term but 005 defaults to nil. */
3299
2543
  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);
2544
+ const federalAmount = nn$27(input.federalAmount);
2545
+ const albertaPortion = nn$27(input.albertaPortion);
2546
+ const federalProxyAmount = nn$27(input.federalProxyAmount);
2547
+ const albertaProxyAmount = nn$27(input.albertaProxyAmount);
2548
+ const iegReducingFederalExpenditure = nn$27(input.iegReducingFederalExpenditure);
2549
+ const repaymentOrContractPayment = nn$27(input.repaymentOrContractPayment);
3306
2550
  return {
3307
2551
  federalAmount,
3308
2552
  albertaPortion,
@@ -3522,7 +2766,7 @@ function computeIeg(input) {
3522
2766
  *
3523
2767
  * Whole dollars, pure.
3524
2768
  */
3525
- const nn$24 = (v) => Math.max(0, Math.round(v ?? 0));
2769
+ const nn$26 = (v) => Math.max(0, Math.round(v ?? 0));
3526
2770
  /**
3527
2771
  * The group's taxable capital and base level of spending, from every associated
3528
2772
  * member's own figures.
@@ -3533,11 +2777,11 @@ const nn$24 = (v) => Math.max(0, Math.round(v ?? 0));
3533
2777
  function computeIegGroupFigures(members, priorYears = IEG_2024.PRIOR_YEARS) {
3534
2778
  const issues = [];
3535
2779
  const detail = members.map((m) => {
3536
- const priorYearAlbertaExpenditures = (m.priorYearAlbertaExpenditures ?? []).map(nn$24);
2780
+ const priorYearAlbertaExpenditures = (m.priorYearAlbertaExpenditures ?? []).map(nn$26);
3537
2781
  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
2782
  return {
3539
2783
  name: m.name,
3540
- taxableCapital: nn$24(m.taxableCapital),
2784
+ taxableCapital: nn$26(m.taxableCapital),
3541
2785
  priorYearAlbertaExpenditures,
3542
2786
  priorYearTotal: priorYearAlbertaExpenditures.reduce((a, b) => a + b, 0)
3543
2787
  };
@@ -3564,11 +2808,11 @@ function computeIegGroupFigures(members, priorYears = IEG_2024.PRIOR_YEARS) {
3564
2808
  function allocateIegExpenditureLimit(groupExpenditureLimit, requested) {
3565
2809
  const issues = [];
3566
2810
  const limit = Math.max(0, Math.round(groupExpenditureLimit));
3567
- const totalRequested = requested.reduce((s, a) => s + nn$24(a.allocated), 0);
2811
+ const totalRequested = requested.reduce((s, a) => s + nn$26(a.allocated), 0);
3568
2812
  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
2813
  let remaining = limit;
3570
2814
  const allocations = requested.map((a) => {
3571
- const allocated = Math.min(nn$24(a.allocated), remaining);
2815
+ const allocated = Math.min(nn$26(a.allocated), remaining);
3572
2816
  remaining -= allocated;
3573
2817
  return {
3574
2818
  name: a.name,
@@ -3602,10 +2846,10 @@ function allocateIegEvenly(groupExpenditureLimit, names) {
3602
2846
  })));
3603
2847
  }
3604
2848
  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);
2849
+ const allocatedExpenditureLimit = nn$26(m.allocatedExpenditureLimit);
2850
+ const currentYearExpenditures = nn$26(m.currentYearExpenditures);
2851
+ const priorYear1 = nn$26(m.priorYear1);
2852
+ const priorYear2 = nn$26(m.priorYear2);
3609
2853
  const base = Math.round((priorYear1 + priorYear2) / 2);
3610
2854
  const individualMaximumAllowedAmount = currentYearExpenditures - base;
3611
2855
  const days = Math.max(0, Math.min(m.daysInTaxYear ?? 365, 366));
@@ -3624,7 +2868,7 @@ function computeAgreementMember(m, index, issues) {
3624
2868
  currentYearExpenditures,
3625
2869
  priorYear1,
3626
2870
  priorYear2,
3627
- taxableCapitalPriorYear: nn$24(m.taxableCapitalPriorYear),
2871
+ taxableCapitalPriorYear: nn$26(m.taxableCapitalPriorYear),
3628
2872
  hasAlbertaPermanentEstablishment,
3629
2873
  individualMaximumAllowedAmount,
3630
2874
  allocatedAllowedAmount
@@ -3752,10 +2996,10 @@ function computeAlbertaReturn(input) {
3752
2996
  const schedulePayloads = [];
3753
2997
  const sched = input.schedules;
3754
2998
  if (sched?.smallBusinessDeduction) {
3755
- schedulePayloads.push(schedule1Values(sched.smallBusinessDeduction));
2999
+ schedulePayloads.push(schedule1Values$1(sched.smallBusinessDeduction));
3756
3000
  issues.push(...sched.smallBusinessDeduction.result.issues);
3757
3001
  }
3758
- if (sched?.allocation) schedulePayloads.push(schedule2Values(sched.allocation));
3002
+ if (sched?.allocation) schedulePayloads.push(schedule2Values$1(sched.allocation));
3759
3003
  if (sched?.otherDeductionsCredits) {
3760
3004
  schedulePayloads.push(schedule3Values(sched.otherDeductionsCredits));
3761
3005
  issues.push(...sched.otherDeductionsCredits.issues);
@@ -3764,26 +3008,6 @@ function computeAlbertaReturn(input) {
3764
3008
  schedulePayloads.push(schedule4Values(sched.foreignInvestmentTaxCredit));
3765
3009
  issues.push(...sched.foreignInvestmentTaxCredit.issues);
3766
3010
  }
3767
- if (sched?.royaltyTaxDeduction) {
3768
- schedulePayloads.push(schedule5Values(sched.royaltyTaxDeduction));
3769
- issues.push(...sched.royaltyTaxDeduction.issues);
3770
- }
3771
- if (sched?.royaltyTaxCredit) {
3772
- schedulePayloads.push(schedule6Values(sched.royaltyTaxCredit));
3773
- issues.push(...sched.royaltyTaxCredit.issues);
3774
- }
3775
- if (sched?.royaltySupplemental) {
3776
- schedulePayloads.push(schedule7Values(sched.royaltySupplemental));
3777
- issues.push(...sched.royaltySupplemental.issues);
3778
- }
3779
- if (sched?.politicalContributions) {
3780
- schedulePayloads.push(schedule8Values(sched.politicalContributions));
3781
- issues.push(...sched.politicalContributions.issues);
3782
- }
3783
- if (sched?.sredTaxCredit) {
3784
- schedulePayloads.push(schedule9Values(sched.sredTaxCredit.result, sched.sredTaxCredit.group));
3785
- issues.push(...sched.sredTaxCredit.result.issues);
3786
- }
3787
3011
  if (sched?.lossCarryback) schedulePayloads.push(schedule10Values(sched.lossCarryback));
3788
3012
  if (sched?.reconciliation) schedulePayloads.push(schedule12Values(sched.reconciliation));
3789
3013
  if (sched?.cca) {
@@ -3812,7 +3036,7 @@ function computeAlbertaReturn(input) {
3812
3036
  issues.push(...sched.donations.gifts?.issues ?? []);
3813
3037
  }
3814
3038
  if (sched?.losses) {
3815
- schedulePayloads.push(schedule21Values(sched.losses));
3039
+ schedulePayloads.push(schedule21Values$1(sched.losses));
3816
3040
  issues.push(...sched.losses.limitedPartnershipLosses?.issues ?? []);
3817
3041
  issues.push(...sched.losses.nonCapitalByYearOfOrigin?.issues ?? []);
3818
3042
  issues.push(...sched.losses.otherLossesByYearOfOrigin?.issues ?? []);
@@ -3861,15 +3085,29 @@ const at1Engine = {
3861
3085
  //#endregion
3862
3086
  //#region src/t2/at1/filing/at1-line-items.ts
3863
3087
  /**
3864
- * AT1 line 000090 — balance unpaid (overpayment), exactly as specified:
3865
- *
3866
- * 000090 = 000080 − (000081 + 000082 + 000085 + 000086 + 000087)
3867
- *
3868
- * Signed a negative result is an overpayment, and line 000092 then chooses
3869
- * between a refund and applying it to next year.
3088
+ * AT1 line 000090 — balance unpaid (overpayment), as the PRINTED form strikes
3089
+ * it:
3090
+ *
3091
+ * 000088 = 000129 + 000082 + 000085 + 000086 + 000115 + 000087
3092
+ * 000090 = 000080 000088
3093
+ *
3094
+ * 088 is a printed subtotal with no line code of its own, so only 090 is
3095
+ * filed. Signed — a negative result is an overpayment, and line 000092 then
3096
+ * chooses between a refund and applying it to next year.
3097
+ *
3098
+ * This used to follow §3.2.3.1's own line-090 rule,
3099
+ * `000080 - (000081 + 000082 + 00085 + 000086 + 000087)`, which nets the
3100
+ * ELIMINATED Alberta SR&ED tax credit and omits both the Innovation
3101
+ * Employment Grant and the Film and Television Tax Credit — two credits the
3102
+ * same specification marks mandatory. Every corporation claiming an IEG was
3103
+ * therefore filed with a balance overstated by the whole grant. See
3104
+ * `AT1_BALANCE_CREDIT_LINES` in `../forms/jacket.ts` for the full evidence,
3105
+ * and `albertaBalanceUnpaidPerSpec` below for the figure the specification
3106
+ * would produce — the review layer reports the difference rather than letting
3107
+ * the disagreement pass silently.
3870
3108
  */
3871
3109
  function albertaBalanceUnpaid(d) {
3872
- return d.albertaTaxPayable - ((d.sredTaxCredit ?? 0) + (d.instalmentsPaid ?? 0) + (d.interactiveDigitalMediaTaxCredit ?? 0) + (d.capitalGainsRefund ?? 0) + (d.otherCredits ?? 0));
3110
+ return d.albertaTaxPayable - ((d.innovationEmploymentGrant ?? 0) + (d.instalmentsPaid ?? 0) + (d.interactiveDigitalMediaTaxCredit ?? 0) + (d.capitalGainsRefund ?? 0) + (d.filmAndTelevisionTaxCredit ?? 0) + (d.otherCredits ?? 0));
3873
3111
  }
3874
3112
  /**
3875
3113
  * "Critical Mandatory" fields, named in §3.2.3 of the specification:
@@ -4648,6 +3886,128 @@ function toRsiHeader(data) {
4648
3886
  };
4649
3887
  }
4650
3888
  //#endregion
3889
+ //#region src/t2/at1/filing/at1-transmitter-validation.ts
3890
+ /**
3891
+ * §3.2.1.18 — the characters TRA accepts anywhere on the AT1 RSI.
3892
+ *
3893
+ * Latin letters, digits, space, the listed punctuation, and the accented Latin
3894
+ * set. The accented characters are given in the spec as a literal glyph list
3895
+ * that `pdftotext` cannot round-trip, so they are expressed here as the
3896
+ * Latin-1 supplement range they come from (À-ÿ) rather than transcribed
3897
+ * one by one from mojibake.
3898
+ */
3899
+ const ALLOWABLE = /^[A-Za-z0-9 \-'/&*#!@+=?$%()_;:",.<>~`^{}[\]|\\À-ÿ]*$/;
3900
+ /** Canadian provinces and territories, per the spec's province table. */
3901
+ const CA_PROVINCES = /* @__PURE__ */ new Set([
3902
+ "AB",
3903
+ "BC",
3904
+ "MB",
3905
+ "NB",
3906
+ "NL",
3907
+ "NS",
3908
+ "NT",
3909
+ "NU",
3910
+ "ON",
3911
+ "PE",
3912
+ "QC",
3913
+ "SK",
3914
+ "YT"
3915
+ ]);
3916
+ /** A9A 9A9, with or without the space. */
3917
+ const CA_POSTAL = /^[A-Za-z]\d[A-Za-z][ ]?\d[A-Za-z]\d$/;
3918
+ /** Five digits, or nine as 12345-6789 / 123456789. */
3919
+ const US_ZIP = /^\d{5}(-?\d{4})?$/;
3920
+ /** Deliberately permissive: TRA checks format and length, not deliverability. */
3921
+ const EMAIL = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
3922
+ /**
3923
+ * The dev placeholder certification code. Blocked because TRA validates the
3924
+ * SCC against its own registry (20010), so `AB0000` cannot succeed — unlike
3925
+ * the serial number, where the rule is presence only (20013) and `SR_DEV` is
3926
+ * a legitimate, if unlovely, value. Only rules TRA actually applies are
3927
+ * enforced here; being stricter than TRA would refuse returns TRA accepts.
3928
+ */
3929
+ const PLACEHOLDER_CERT_CODE = "AB0000";
3930
+ function validateAt1Transmitter(info) {
3931
+ const defects = [];
3932
+ const add = (field, traCode, message) => defects.push({
3933
+ field,
3934
+ traCode,
3935
+ message
3936
+ });
3937
+ /** Present, within `max` characters, and drawn from the allowable set. */
3938
+ const text = (value, field, traCode, label, max, required = true) => {
3939
+ const v = (value ?? "").trim();
3940
+ if (v === "") {
3941
+ if (required) add(field, traCode, `${label} must be provided.`);
3942
+ return;
3943
+ }
3944
+ if (v.length > max) add(field, traCode, `${label} must not exceed ${max} characters (is ${v.length}).`);
3945
+ 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.`);
3946
+ };
3947
+ if (!info.softwareCertCode?.trim()) add("softwareCertCode", "20010", "The TRA-issued Software Certification Code must be provided.");
3948
+ 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.`);
3949
+ if (!info.webServiceVersion?.trim()) add("webServiceVersion", "20011", "Web Service Version must be provided.");
3950
+ if (!info.softwareVersion?.trim()) add("softwareVersion", "20012", "Software Version must be provided.");
3951
+ if (!info.serialNumber?.trim()) add("serialNumber", "20013", "Software Serial Number must be provided.");
3952
+ const isThirdParty = info.thirdPartyIndicator === "1";
3953
+ if (info.thirdPartyIndicator !== "1" && info.thirdPartyIndicator !== "2") add("thirdPartyIndicator", "20065", "Third Party Service Provider Indicator must be \"1\" (yes) or \"2\" (no).");
3954
+ text(info.legalName, "legalName", "20070", "Organization Legal Name", 70, isThirdParty);
3955
+ if (isThirdParty && !info.organizationType) add("organizationType", "20080", "Type of Organization must be CORPORATION, PARTNERSHIP or INDIVIDUAL when filing as a third party.");
3956
+ const c = info.contact;
3957
+ text(c?.firstName, "contact.firstName", "20085", "Contact First Name", 35);
3958
+ text(c?.lastName, "contact.lastName", "20090", "Contact Last Name", 35);
3959
+ text(c?.position, "contact.position", "20095", "Position", 40);
3960
+ const phone = (c?.phone ?? "").trim();
3961
+ const phoneDigits = phone.replace(/\D/g, "");
3962
+ if (phone === "") add("contact.phone", "20100", "Phone Number must be provided.");
3963
+ else if (phoneDigits.length < 10 || phoneDigits.length > 15) add("contact.phone", "20100", `Phone Number must be 10 to 15 digits (is ${phoneDigits.length}).`);
3964
+ 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.`);
3965
+ const email = (c?.email ?? "").trim();
3966
+ if (email === "") add("contact.email", "20110", "Email Address must be provided.");
3967
+ else if (email.length > 50) add("contact.email", "20110", `Email Address must not exceed 50 characters (is ${email.length}).`);
3968
+ else if (!EMAIL.test(email)) add("contact.email", "20110", `Email Address "${email}" is not a valid format.`);
3969
+ const a = info.address;
3970
+ if (isThirdParty && !a) add("address", "20115", "A third-party filer must supply a mailing address.");
3971
+ else if (a) {
3972
+ text(a.street, "address.street", "20115", "Address Line 1", 35);
3973
+ if (a.line2?.trim()) {
3974
+ text(a.line2, "address.line2", "20120", "Address Line 2", 35, false);
3975
+ if (a.line2.trim().toUpperCase() === (a.street ?? "").trim().toUpperCase()) add("address.line2", "20120", "Address Line 2 cannot repeat Address Line 1.");
3976
+ }
3977
+ text(a.city, "address.city", "20125", "City", 35);
3978
+ const country = (a.country ?? "").trim().toUpperCase();
3979
+ const province = (a.province ?? "").trim().toUpperCase();
3980
+ const postal = (a.postalCode ?? "").trim();
3981
+ if (country === "") add("address.country", "20140", "Country must be provided.");
3982
+ 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}").`);
3983
+ if (country === "CA" || country === "US") {
3984
+ if (province === "") add("address.province", "20130", `Province must be provided when the country is ${country}.`);
3985
+ else if (country === "CA" && !CA_PROVINCES.has(province)) add("address.province", "20130", `"${a.province}" is not a Canadian province or territory code.`);
3986
+ else if (country === "US" && !/^[A-Z]{2}$/.test(province)) add("address.province", "20130", `"${a.province}" is not a two-letter US state code.`);
3987
+ if (postal === "") add("address.postalCode", "20135", `Postal Code must be provided when the country is ${country}.`);
3988
+ else if (country === "CA" && !CA_POSTAL.test(postal)) add("address.postalCode", "20135", `Postal Code "${postal}" is not in Canadian A9A 9A9 format.`);
3989
+ else if (country === "US" && !US_ZIP.test(postal)) add("address.postalCode", "20135", `Postal Code "${postal}" is not a 5- or 9-digit US ZIP.`);
3990
+ } else if (country !== "") {
3991
+ if (province !== "") add("address.province", "20130", "Province must be blank when the country is not CA or US.");
3992
+ if (postal !== "") add("address.postalCode", "20135", "Postal Code must be blank when the country is not CA or US.");
3993
+ }
3994
+ }
3995
+ return defects;
3996
+ }
3997
+ var At1TransmitterInvalidError = class extends Error {
3998
+ defects;
3999
+ constructor(defects) {
4000
+ 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.");
4001
+ this.name = "At1TransmitterInvalidError";
4002
+ this.defects = defects;
4003
+ }
4004
+ };
4005
+ /** Throw unless every filer-detail rule TRA applies is satisfied. */
4006
+ function assertAt1TransmitterValid(info) {
4007
+ const defects = validateAt1Transmitter(info);
4008
+ if (defects.length > 0) throw new At1TransmitterInvalidError(defects);
4009
+ }
4010
+ //#endregion
4651
4011
  //#region src/t2/schedules/loss-carryback.ts
4652
4012
  var LossCarrybackError = class extends Error {
4653
4013
  constructor(message) {
@@ -5675,33 +5035,33 @@ function computeAlbertaSchedule13(input) {
5675
5035
  }
5676
5036
  //#endregion
5677
5037
  //#region src/t2/at1/schedules/schedule16-sred.ts
5678
- const nn$23 = (v) => Math.max(0, Math.round(v ?? 0));
5038
+ const nn$25 = (v) => Math.max(0, Math.round(v ?? 0));
5679
5039
  /**
5680
5040
  * Line 016004 for federal T661 versions from 2008 onward: lines 429 + 431 + 432.
5681
5041
  * The 2007-and-earlier form used a single line 430, which can be passed to
5682
5042
  * `assistance` directly.
5683
5043
  */
5684
5044
  function assistanceFrom(line429, line431, line432) {
5685
- return nn$23(line429) + nn$23(line431) + nn$23(line432);
5045
+ return nn$25(line429) + nn$25(line431) + nn$25(line432);
5686
5046
  }
5687
5047
  function computeAlbertaSchedule16(input) {
5688
5048
  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);
5049
+ const currentYearExpenditures = nn$25(input.currentYearExpenditures);
5050
+ const assistance = nn$25(input.assistance);
5051
+ const priorYearItcClaimed = nn$25(input.priorYearItcClaimed);
5052
+ const saleOfCapitalAssetsAndOther = nn$25(input.saleOfCapitalAssetsAndOther);
5053
+ const assistanceRepayments = nn$25(input.assistanceRepayments);
5054
+ const openingPoolBalance = nn$25(input.openingPoolBalance);
5055
+ const poolTransferredIn = nn$25(input.poolTransferredIn);
5056
+ const priorYearItcRecaptured = nn$25(input.priorYearItcRecaptured);
5697
5057
  const totalDeductions = assistance + priorYearItcClaimed + saleOfCapitalAssetsAndOther;
5698
5058
  const totalAdditions = assistanceRepayments + openingPoolBalance + poolTransferredIn + priorYearItcRecaptured;
5699
5059
  const subtotal = currentYearExpenditures - totalDeductions + totalAdditions;
5700
5060
  const deductionAvailable = Math.max(0, subtotal);
5701
5061
  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
5062
  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;
5063
+ const openingDiffers = input.federalOpeningPoolBalance !== void 0 && nn$25(input.federalOpeningPoolBalance) !== openingPoolBalance;
5064
+ const claimDiffers = input.federalAmountClaimed !== void 0 && nn$25(input.federalAmountClaimed) !== amountClaimed;
5705
5065
  const formRequired = openingDiffers || claimDiffers;
5706
5066
  const formPermitted = (input.reportsDifferentAlbertaIncome ?? false) || (input.electsDifferentDiscretionaryAmounts ?? false);
5707
5067
  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 +5189,10 @@ const AT1_RESERVE_LINES = Object.freeze({
5829
5189
  closing: "017077"
5830
5190
  }
5831
5191
  });
5832
- const nn$22 = (v) => Math.max(0, Math.round(v ?? 0));
5192
+ const nn$24 = (v) => Math.max(0, Math.round(v ?? 0));
5833
5193
  /** `undefined` falls back to federal; a `0` is a real Alberta override. */
5834
5194
  function pick(alberta, federal) {
5835
- return nn$22(alberta !== void 0 ? alberta : federal);
5195
+ return nn$24(alberta !== void 0 ? alberta : federal);
5836
5196
  }
5837
5197
  function computeAlbertaSchedule17(input) {
5838
5198
  const issues = [];
@@ -5935,7 +5295,7 @@ const AT1_DISPOSITION_CATEGORIES = [
5935
5295
  * Line 018076 then applies the inclusion rate once, to the total.
5936
5296
  */
5937
5297
  const SECTION_34_2_GROSS_UP = 2;
5938
- const nn$21 = (v) => Math.max(0, v ?? 0);
5298
+ const nn$23 = (v) => Math.max(0, v ?? 0);
5939
5299
  const num = (v) => v ?? 0;
5940
5300
  /** Merge one category: an omitted Alberta field takes federal; a `0` overrides. */
5941
5301
  function mergeCategory(federal, alberta) {
@@ -5946,9 +5306,9 @@ function mergeCategory(federal, alberta) {
5946
5306
  const o = f.outlays;
5947
5307
  return {
5948
5308
  totals: {
5949
- proceeds: nn$21(p),
5309
+ proceeds: nn$23(p),
5950
5310
  acb: num(c),
5951
- outlays: nn$21(o)
5311
+ outlays: nn$23(o)
5952
5312
  },
5953
5313
  differs: a.proceeds !== void 0 || a.acb !== void 0
5954
5314
  };
@@ -5970,17 +5330,17 @@ function computeAlbertaSchedule18(input) {
5970
5330
  const gainOf = (c) => categories.find((x) => x.category === c)?.gain ?? 0;
5971
5331
  const personalUseGain = gainOf("personalUse");
5972
5332
  const listedPersonalGain = gainOf("listedPersonal");
5973
- const lppLossesApplied = listedPersonalGain > 0 ? Math.min(nn$21(input.unappliedLppLosses), listedPersonalGain) : 0;
5333
+ const lppLossesApplied = listedPersonalGain > 0 ? Math.min(nn$23(input.unappliedLppLosses), listedPersonalGain) : 0;
5974
5334
  const ordinaryGains = gainOf("shares") + gainOf("realEstate") + gainOf("bonds") + gainOf("otherProperties");
5975
5335
  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);
5336
+ const reserveOpening = nn$23(input.albertaReserveOpening ?? input.federalReserveOpening);
5337
+ const reserveClosing = nn$23(input.albertaReserveClosing ?? input.federalReserveClosing);
5338
+ 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
5339
  const taxableCapitalGain = Math.max(0, Math.round(inclusionRate * netBeforeInclusionRate));
5980
5340
  const abil = (input.abilEntries ?? []).map((e) => ({
5981
5341
  name: e.name,
5982
5342
  kind: e.kind,
5983
- businessInvestmentLoss: nn$21(e.proceeds) - (nn$21(e.acb) + nn$21(e.outlays))
5343
+ businessInvestmentLoss: nn$23(e.proceeds) - (nn$23(e.acb) + nn$23(e.outlays))
5984
5344
  }));
5985
5345
  const totalBil = abil.reduce((s, e) => s + Math.min(0, e.businessInvestmentLoss), 0);
5986
5346
  const allowableBusinessInvestmentLoss = -Math.round(inclusionRate * -totalBil);
@@ -6011,7 +5371,7 @@ function computeAlbertaSchedule18(input) {
6011
5371
  }
6012
5372
  //#endregion
6013
5373
  //#region src/t2/at1/schedules/schedule20-donations.ts
6014
- const nn$20 = (v) => Math.max(0, v ?? 0);
5374
+ const nn$22 = (v) => Math.max(0, v ?? 0);
6015
5375
  /**
6016
5376
  * Alberta figures default to federal, per-field. A `0` entered on the Alberta
6017
5377
  * side is a real override and must not be swallowed by the default, so the
@@ -6036,11 +5396,11 @@ function resolveCarryforward(federal, alberta) {
6036
5396
  return out;
6037
5397
  }
6038
5398
  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);
5399
+ const openingBalance = nn$22(input.openingBalance);
5400
+ const expired = nn$22(input.expired);
5401
+ const transferredIn = nn$22(input.transferredIn);
5402
+ const currentYearGifts = nn$22(input.currentYearGifts);
5403
+ const acquisitionOfControlAdjustment = nn$22(input.acquisitionOfControlAdjustment);
6044
5404
  const availableBeforeClaim = Math.max(0, openingBalance - expired + transferredIn + currentYearGifts - acquisitionOfControlAdjustment);
6045
5405
  const issues = [];
6046
5406
  let ceiling;
@@ -6111,12 +5471,12 @@ function computeSchedule20(input) {
6111
5471
  const AT1_DONATION_INCOME_RATE = .75;
6112
5472
  /** Gains and recapture on gifted capital property add back at 25%. */
6113
5473
  const AT1_DONATION_GAIN_RATE = .25;
6114
- const nn$19 = (v) => Math.max(0, v ?? 0);
5474
+ const nn$21 = (v) => Math.max(0, v ?? 0);
6115
5475
  function computeDonationMaximum(input) {
6116
5476
  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));
5477
+ const lesserOfProceedsAndCost = Math.min(nn$21(input.proceedsNetOfOutlays), nn$21(input.capitalCost));
5478
+ const allowableRecapture = Math.min(nn$21(input.recaptureOnGifts), lesserOfProceedsAndCost);
5479
+ const gainsComponent = Math.round(AT1_DONATION_GAIN_RATE * (nn$21(input.taxableCapitalGainsOnGifts) + nn$21(input.deemedGiftGains) + allowableRecapture));
6120
5480
  return {
6121
5481
  incomeComponent,
6122
5482
  lesserOfProceedsAndCost,
@@ -6209,6 +5569,37 @@ function computeLossSchedule(input) {
6209
5569
  };
6210
5570
  }
6211
5571
  //#endregion
5572
+ //#region src/t2/at1/schedules/schedule21-rife.ts
5573
+ function computeRifeContinuity(input = {}) {
5574
+ const openingBalance = Math.max(0, input.openingBalance ?? 0);
5575
+ const transferredOnWindUp = Math.max(0, input.transferredOnWindUp ?? 0);
5576
+ const acquisitionOfControlAdjustment = Math.max(0, input.acquisitionOfControlAdjustment ?? 0);
5577
+ const currentYearRife = Math.max(0, input.currentYearRife ?? 0);
5578
+ const excessCapacity = Math.max(0, input.excessCapacity ?? 0);
5579
+ const receivedCapacity = Math.max(0, input.receivedCapacity ?? 0);
5580
+ const rifeFromPreviousYears = Math.max(0, openingBalance + transferredOnWindUp - acquisitionOfControlAdjustment);
5581
+ const totalCapacity = excessCapacity + receivedCapacity;
5582
+ const maxDeductible = Math.max(0, Math.min(rifeFromPreviousYears, totalCapacity));
5583
+ const issues = [];
5584
+ const requestedClaim = Math.max(0, input.deductedClaim ?? maxDeductible);
5585
+ if (requestedClaim > maxDeductible) issues.push(`Line 240 (RIFE deducted, ${requestedClaim}) cannot exceed line 350 (${maxDeductible}). Capped at ${maxDeductible}.`);
5586
+ const deducted = Math.min(requestedClaim, maxDeductible);
5587
+ return {
5588
+ openingBalance,
5589
+ transferredOnWindUp,
5590
+ acquisitionOfControlAdjustment,
5591
+ currentYearRife,
5592
+ rifeFromPreviousYears,
5593
+ excessCapacity,
5594
+ receivedCapacity,
5595
+ totalCapacity,
5596
+ maxDeductible,
5597
+ deducted,
5598
+ closingBalance: openingBalance + transferredOnWindUp - acquisitionOfControlAdjustment + currentYearRife - deducted,
5599
+ issues
5600
+ };
5601
+ }
5602
+ //#endregion
6212
5603
  //#region src/t2/at1/schedules/schedule21-year-of-origin.ts
6213
5604
  function sumRows(rows) {
6214
5605
  const sum = (f) => rows.reduce((s, r) => s + f(r), 0);
@@ -6458,35 +5849,270 @@ const T2_CERTIFICATION_FIXTURES = [
6458
5849
  }
6459
5850
  ];
6460
5851
  //#endregion
6461
- //#region src/t2/rates/corporate-rates.ts
5852
+ //#region src/t2/filing/t2-schedule-line-items.ts
6462
5853
  /**
6463
- * Federal corporate-tax rate table — the Part I rate stack, the small-business
6464
- * limit + grind bands, and the refundable (Part IV / AAII) fractions. This is
6465
- * the DATA the engine's pure formulas consume; a host supplies future years or
6466
- * overrides these reference values via the {@link CORP_TAX_RATE_BOOK} seam.
5854
+ * Federal T2 — the per-schedule, per-line breakdown of a computed return.
5855
+ *
5856
+ * Alberta has had this since the AT1 filing path was built
5857
+ * (`at1-schedule-line-items.ts`): every schedule's result turned into a flat
5858
+ * list of `{lineItemId, value}` pairs, persisted with the computed return, and
5859
+ * read back by the paper Form Views so a preparer sees the actual figure
5860
+ * against the actual line. Federal had nothing equivalent. Its computed return
5861
+ * carried only summary fields under symbolic names — `netIncomeForTax`,
5862
+ * `ccaClaimed` — which no form can be keyed by, so every federal paper view
5863
+ * rendered "not available" against every computed line of every schedule.
5864
+ *
5865
+ * ── The rule this file follows, and why it is strict ────────────────────────
5866
+ *
5867
+ * A value is emitted ONLY where the line it belongs on is recorded in code:
5868
+ * carried in the data (Schedule 1's own `Schedule1Line.line`), exported as a
5869
+ * named constant (`SCHEDULE_8_CCA_LINE`), or stated in the result type's own
5870
+ * doc comment. Nothing here is a line number typed from memory or inferred from
5871
+ * a caption that looks close.
5872
+ *
5873
+ * The reason is the failure this repository keeps hitting: a figure filed under
5874
+ * the wrong line is not a missing figure, it is a WRONG return, and it looks
5875
+ * completely correct on screen. Schedule 4's jacket references claimed lines 150
5876
+ * and 250 where the form prints 130 and 225; Schedule 33's own result type said
5877
+ * line 690 where the form has 790. Both were plausible, both were wrong, and
5878
+ * neither was caught by a type.
5879
+ *
5880
+ * So a schedule whose result has no recorded line mapping produces NO entry
5881
+ * rather than a guessed one, and the paper view keeps saying "not available"
5882
+ * for it. That is the honest state, and it is visibly incomplete, which is what
5883
+ * makes it safe to extend one verified line at a time.
5884
+ *
5885
+ * ── Identifier shape ────────────────────────────────────────────────────────
5886
+ *
5887
+ * Six characters: the three-digit CRA line, then a three-digit occurrence.
5888
+ * Alberta uses nine (`SSSFFFOOO`) because a TRA line item id names its schedule
5889
+ * too; a federal line number is already unique across the whole return, so the
5890
+ * schedule is carried once on the envelope instead of repeated on every row.
5891
+ * The trailing occurrence exists for the grid forms, where one line number
5892
+ * repeats down a column — Schedule 8 has one row per capital cost allowance
5893
+ * class, all of them line 217.
5894
+ */
5895
+ /** `LLLOOO` — three-digit CRA line, three-digit occurrence. Occurrence is 1-based. */
5896
+ function t2LineItemId(line, occurrence = 1) {
5897
+ return `${line}${String(occurrence).padStart(3, "0")}`;
5898
+ }
5899
+ /**
5900
+ * Split a federal line item id back into its line and occurrence.
6467
5901
  *
6468
- * Rate stack (ITA Part I):
6469
- * basic rate 38% of taxable income
6470
- * federal abatement 10% of taxable income earned in a province (s.124) → 28%
6471
- * small-business ded. 19% of income eligible for the SBD (CCPC) → 9%
6472
- * − general rate red. 13% of full-rate income (not SBD/AAII/M&P) → 15%
5902
+ * Returns `undefined` for anything that is not six digits, so a caller handed
5903
+ * an Alberta nine-digit id (or a malformed one) drops it rather than reading
5904
+ * the first three characters as a line number and displaying a figure against
5905
+ * a line it does not belong to.
5906
+ */
5907
+ function parseT2LineItemId(lineItemId) {
5908
+ if (!/^\d{6}$/.test(lineItemId)) return void 0;
5909
+ return {
5910
+ line: lineItemId.slice(0, 3),
5911
+ occurrence: Number(lineItemId.slice(3, 6))
5912
+ };
5913
+ }
5914
+ /** Drop entries with no value, so an absent figure stays absent rather than becoming 0. */
5915
+ const present = (values) => values.filter((v) => v !== null);
5916
+ /** One value, or `null` when the figure was not computed. */
5917
+ const at = (line, value, occurrence = 1) => value === void 0 ? null : {
5918
+ lineItemId: t2LineItemId(line, occurrence),
5919
+ value
5920
+ };
5921
+ /**
5922
+ * Schedule 1 — the only federal schedule that needs no line table here.
6473
5923
  *
6474
- * Never mutate a shipped year add a new {@link RateBookEntry} for the new
6475
- * year (in the host book) so prior-year returns stay reproducible.
5924
+ * `Schedule1Line` carries its own `line`, and has since the schedule was built,
5925
+ * precisely because "a reconciling item recorded only as a description with an
5926
+ * amount has nowhere to go on the wire". Reading it back out is the whole job.
5927
+ *
5928
+ * A line may legitimately repeat: the form provides open rows (135, 295, 395,
5929
+ * 495) for items it does not name, and a return can carry several. Those get
5930
+ * successive occurrences rather than being summed, so the paper view can show
5931
+ * each on its own row. A line with no number is skipped — `assertSchedule1Fileable`
5932
+ * is what refuses the return over it, not this.
6476
5933
  */
6477
- const CORP_TAX_2024 = Object.freeze({
6478
- BASIC_RATE: .38,
6479
- FEDERAL_ABATEMENT: .1,
6480
- SBD_RATE: .19,
6481
- GENERAL_RATE_REDUCTION: .13,
6482
- BUSINESS_LIMIT: 5e5,
6483
- TC_GRIND_LOWER: 1e7,
6484
- TC_GRIND_UPPER: 5e7,
6485
- AAII_THRESHOLD: 5e4,
6486
- AAII_REDUCTION_PER_DOLLAR: 5,
6487
- PART_IV_RATE: 115 / 300,
6488
- REFUNDABLE_PART_I_RATE: 92 / 300,
6489
- CAPITAL_GAINS_INCLUSION_RATE: .5,
5934
+ function schedule1Values(r) {
5935
+ const values = [];
5936
+ const seen = /* @__PURE__ */ new Map();
5937
+ for (const l of [...r.additions, ...r.deductions]) {
5938
+ if (!l.line) continue;
5939
+ const occurrence = (seen.get(l.line) ?? 0) + 1;
5940
+ seen.set(l.line, occurrence);
5941
+ values.push({
5942
+ lineItemId: t2LineItemId(l.line, occurrence),
5943
+ value: l.amount
5944
+ });
5945
+ }
5946
+ values.push({
5947
+ lineItemId: t2LineItemId("500"),
5948
+ value: r.totalAdditions
5949
+ });
5950
+ values.push({
5951
+ lineItemId: t2LineItemId("510"),
5952
+ value: r.totalDeductions
5953
+ });
5954
+ return {
5955
+ scheduleId: "T2SCH1",
5956
+ values
5957
+ };
5958
+ }
5959
+ /** Schedule 2 — the donation claim. Only line 210 is a named constant. */
5960
+ function schedule2Values(r) {
5961
+ return {
5962
+ scheduleId: "T2SCH2",
5963
+ values: present([at("210", r.donationsClaimed)])
5964
+ };
5965
+ }
5966
+ /**
5967
+ * Schedule 7 — the adjusted aggregate investment income that grinds the
5968
+ * business limit. Line 745 is exported by the form module; the rest of Part 2's
5969
+ * working lines are not recorded anywhere, so they are not emitted.
5970
+ */
5971
+ function schedule7Values(r) {
5972
+ return {
5973
+ scheduleId: "T2SCH7",
5974
+ values: present([at("745", r.adjustedAggregateInvestmentIncome)])
5975
+ };
5976
+ }
5977
+ /**
5978
+ * Schedule 8 — capital cost allowance, one occurrence per class.
5979
+ *
5980
+ * Only the three lines the form module exports are emitted: recapture (213),
5981
+ * terminal loss (215) and the claim (217). The grid's other twenty columns are
5982
+ * either intermediate arithmetic the form shows without numbering, or columns
5983
+ * whose number this package has not recorded — see `SCHEDULE_8_COLUMNS`.
5984
+ */
5985
+ function schedule8Values(r) {
5986
+ const values = [];
5987
+ r.classes.forEach((c, i) => {
5988
+ const occurrence = i + 1;
5989
+ values.push(...present([
5990
+ at("213", c.recapture, occurrence),
5991
+ at("215", c.terminalLoss, occurrence),
5992
+ at("217", c.ccaClaimed, occurrence)
5993
+ ]));
5994
+ });
5995
+ return {
5996
+ scheduleId: "T2SCH8",
5997
+ values
5998
+ };
5999
+ }
6000
+ /**
6001
+ * Schedule 21 — the two foreign tax credits.
6002
+ *
6003
+ * These land on different jacket lines (632 non-business, 636 business) and the
6004
+ * form module's own doc comment warns that swapping them "is not cosmetic".
6005
+ * Both come from named constants for exactly that reason.
6006
+ */
6007
+ function schedule21Values(r) {
6008
+ return {
6009
+ scheduleId: "T2SCH21",
6010
+ values: present([at("180", r.nonBusinessFtc), at("280", r.businessFtc)])
6011
+ };
6012
+ }
6013
+ /**
6014
+ * Schedule 33 — taxable capital.
6015
+ *
6016
+ * The four figures whose lines the result type states: capital (190), the
6017
+ * investment allowance (490), taxable capital (500) and taxable capital
6018
+ * employed in Canada (790, from the form module's constant — the result type's
6019
+ * comment used to say 690, which is not a line of this form).
6020
+ */
6021
+ function schedule33Values(r) {
6022
+ return {
6023
+ scheduleId: "T2SCH33",
6024
+ values: present([
6025
+ at("190", r.capital),
6026
+ at("490", r.investmentAllowance),
6027
+ at("500", r.taxableCapital),
6028
+ at("790", r.taxableCapitalEmployedInCanada)
6029
+ ])
6030
+ };
6031
+ }
6032
+ /** Schedule 53 — the closing general rate income pool. */
6033
+ function schedule53Values(r) {
6034
+ return {
6035
+ scheduleId: "T2SCH53",
6036
+ values: present([at("590", r.closingGrip)])
6037
+ };
6038
+ }
6039
+ /**
6040
+ * Schedule 55 — Part III.1 tax.
6041
+ *
6042
+ * The result type states "20% of amount B (s.185.1(1)(a)) — line 190 / line
6043
+ * 290". Two lines for one figure because the form splits by corporation type:
6044
+ * Part 1 (line 190) for CCPCs and deposit insurance corporations, Part 2 (line
6045
+ * 290) for everyone else. Nothing in the result says which part applied, so the
6046
+ * base tax is emitted against BOTH and the paper view shows it under whichever
6047
+ * part the reader is looking at, rather than this file picking one and being
6048
+ * wrong for half of all filers.
6049
+ */
6050
+ function schedule55Values(r) {
6051
+ return {
6052
+ scheduleId: "T2SCH55",
6053
+ values: present([at("190", r.baseTax), at("290", r.baseTax)])
6054
+ };
6055
+ }
6056
+ /** The jacket — the three headline figures the form module names. */
6057
+ function jacketValues(r) {
6058
+ return {
6059
+ scheduleId: "T2",
6060
+ values: present([
6061
+ at("300", r.netIncomeForTax),
6062
+ at("360", r.taxableIncome),
6063
+ at("770", r.totalFederalTax)
6064
+ ])
6065
+ };
6066
+ }
6067
+ /**
6068
+ * Every schedule's filed line items for one computed federal return.
6069
+ *
6070
+ * A schedule that was not computed is ABSENT, not present and empty — the same
6071
+ * rule Alberta's assembler follows. An empty schedule on a return says "this
6072
+ * schedule was completed and everything on it is nil", which is a different
6073
+ * statement from "this schedule does not apply", and only one of them is true.
6074
+ */
6075
+ function federalSchedulePayloads(r) {
6076
+ const payloads = [jacketValues(r), schedule1Values(r.schedule1)];
6077
+ if (r.donations) payloads.push(schedule2Values(r.donations));
6078
+ if (r.adjustedAggregateInvestmentIncomeSchedule) payloads.push(schedule7Values(r.adjustedAggregateInvestmentIncomeSchedule));
6079
+ if (r.cca) payloads.push(schedule8Values(r.cca));
6080
+ if (r.foreignTaxCredit) payloads.push(schedule21Values(r.foreignTaxCredit));
6081
+ if (r.taxableCapitalSchedule) payloads.push(schedule33Values(r.taxableCapitalSchedule));
6082
+ if (r.grip) payloads.push(schedule53Values(r.grip));
6083
+ if (r.partIII1) payloads.push(schedule55Values(r.partIII1));
6084
+ return payloads.filter((p) => p.values.length > 0);
6085
+ }
6086
+ //#endregion
6087
+ //#region src/t2/rates/corporate-rates.ts
6088
+ /**
6089
+ * Federal corporate-tax rate table — the Part I rate stack, the small-business
6090
+ * limit + grind bands, and the refundable (Part IV / AAII) fractions. This is
6091
+ * the DATA the engine's pure formulas consume; a host supplies future years or
6092
+ * overrides these reference values via the {@link CORP_TAX_RATE_BOOK} seam.
6093
+ *
6094
+ * Rate stack (ITA Part I):
6095
+ * basic rate 38% of taxable income
6096
+ * − federal abatement 10% of taxable income earned in a province (s.124) → 28%
6097
+ * − small-business ded. 19% of income eligible for the SBD (CCPC) → 9%
6098
+ * − general rate red. 13% of full-rate income (not SBD/AAII/M&P) → 15%
6099
+ *
6100
+ * Never mutate a shipped year — add a new {@link RateBookEntry} for the new
6101
+ * year (in the host book) so prior-year returns stay reproducible.
6102
+ */
6103
+ const CORP_TAX_2024 = Object.freeze({
6104
+ BASIC_RATE: .38,
6105
+ FEDERAL_ABATEMENT: .1,
6106
+ SBD_RATE: .19,
6107
+ GENERAL_RATE_REDUCTION: .13,
6108
+ BUSINESS_LIMIT: 5e5,
6109
+ TC_GRIND_LOWER: 1e7,
6110
+ TC_GRIND_UPPER: 5e7,
6111
+ AAII_THRESHOLD: 5e4,
6112
+ AAII_REDUCTION_PER_DOLLAR: 5,
6113
+ PART_IV_RATE: 115 / 300,
6114
+ REFUNDABLE_PART_I_RATE: 92 / 300,
6115
+ CAPITAL_GAINS_INCLUSION_RATE: .5,
6490
6116
  GRIP_FACTOR: .72,
6491
6117
  SRED_ITC_ENHANCED_RATE: .35,
6492
6118
  SRED_ITC_BASIC_RATE: .15,
@@ -6560,12 +6186,12 @@ function computeSBD(input, rates = CORP_TAX_2024) {
6560
6186
  sbdAmount: Math.round(rates.SBD_RATE * sbdIncome)
6561
6187
  };
6562
6188
  }
6563
- const nn$18 = (v) => v ?? 0;
6189
+ const nn$20 = (v) => v ?? 0;
6564
6190
  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;
6191
+ const amountA = nn$20(input.allowableCapitalLosses) + nn$20(input.netCapitalLossesClaimed);
6192
+ const amountB = Math.max(0, nn$20(input.taxableCapitalGains) - amountA);
6193
+ const amountC = nn$20(input.exemptIncome) + nn$20(input.agriInvestFundReceived) + nn$20(input.taxableDividendsDeductible) + nn$20(input.trustPropertyIncome);
6194
+ const amountD = nn$20(input.incomeFromProperty) - amountC;
6569
6195
  const amountE = amountB + amountD;
6570
6196
  return {
6571
6197
  amountA,
@@ -6573,20 +6199,20 @@ function computeAggregateInvestmentIncome(input) {
6573
6199
  amountC,
6574
6200
  amountD,
6575
6201
  amountE,
6576
- aggregateInvestmentIncome: Math.max(0, amountE - nn$18(input.lossesFromProperty))
6202
+ aggregateInvestmentIncome: Math.max(0, amountE - nn$20(input.lossesFromProperty))
6577
6203
  };
6578
6204
  }
6579
6205
  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;
6206
+ const amountF = Math.max(0, nn$20(input.taxableCapitalGains) - nn$20(input.allowableCapitalLosses));
6207
+ const amountG = nn$20(input.exemptIncome) + nn$20(input.agriInvestFundReceived) + nn$20(input.dividendsFromConnectedCorporations) + nn$20(input.trustPropertyIncome);
6208
+ const amountH = nn$20(input.incomeFromProperty) - amountG;
6583
6209
  const amountI = amountF + amountH;
6584
6210
  return {
6585
6211
  amountF,
6586
6212
  amountG,
6587
6213
  amountH,
6588
6214
  amountI,
6589
- adjustedAggregateInvestmentIncome: Math.max(0, amountI - nn$18(input.lossesFromProperty) + nn$18(input.subsection91_4Deduction))
6215
+ adjustedAggregateInvestmentIncome: Math.max(0, amountI - nn$20(input.lossesFromProperty) + nn$20(input.subsection91_4Deduction))
6590
6216
  };
6591
6217
  }
6592
6218
  //#endregion
@@ -6827,6 +6453,165 @@ function isSchedule5Province(code) {
6827
6453
  return code in PROVINCE_RATES_2024;
6828
6454
  }
6829
6455
  //#endregion
6456
+ //#region src/t2/schedules/eifel-adjusted-taxable-income.ts
6457
+ /**
6458
+ * ITA subsection 18.2(1) — **adjusted taxable income**, the base the EIFEL
6459
+ * ceiling is computed on.
6460
+ *
6461
+ * `eifel-limitation.ts` took this as a required input because deriving it
6462
+ * partially would produce a plausible figure from an incomplete definition. This
6463
+ * derives it, and is explicit about the components it does and does not cover.
6464
+ *
6465
+ * ── What it is ──────────────────────────────────────────────────────────────
6466
+ *
6467
+ * An EBITDA-like measure, built from taxable income by adding back the things the
6468
+ * regime is measuring against and removing the things that would double-count.
6469
+ *
6470
+ * ATI = A + B − C
6471
+ *
6472
+ * A = D − E the income base
6473
+ * B the ADD-BACKS
6474
+ * C the REDUCTIONS
6475
+ *
6476
+ * **The add-backs include the interest and financing expenses themselves.** That
6477
+ * is the point of the measure and the thing to hold on to: the ceiling is a
6478
+ * percentage of income computed *before* the very expenses being limited, so a
6479
+ * corporation cannot shrink its own ceiling by borrowing more.
6480
+ *
6481
+ * ── A — the income base (D − E) ─────────────────────────────────────────────
6482
+ *
6483
+ * **D** is taxable income for the year, determined **without regard to** s.18.2(2)
6484
+ * itself, paragraphs 12(1)(l.2) and 111(1)(a.1), and clause 95(2)(f.11)(ii)(D) —
6485
+ * a non-resident uses taxable income earned in Canada on the same basis. The
6486
+ * circularity is deliberate: the limitation cannot be an input to its own base.
6487
+ *
6488
+ * **E** subtracts the year's non-capital loss on the same basis, any amount
6489
+ * claimed under paragraph 111(1)(a) that did not actually reduce taxable income,
6490
+ * and a controlled-foreign-affiliate component (`T × U ÷ V`).
6491
+ *
6492
+ * ── B — the add-backs ───────────────────────────────────────────────────────
6493
+ *
6494
+ * (a) interest and financing expenses for the year
6495
+ * (b) capital cost allowance and resource deductions — paragraph 20(1)(a),
6496
+ * 59.1(a) and subsections 66(4), 66.1(2)/(3), 66.2(2), 66.21(4), 66.4(2),
6497
+ * 66.7(1)-(5)
6498
+ * (c) terminal losses — subsection 20(16)
6499
+ * (d) the taxpayer's share of a partnership's 20(1)(a) and 20(16) deductions
6500
+ * (e) the portion of a paragraph 111(1)(e) limited-partnership-loss claim
6501
+ * attributable to those amounts
6502
+ *
6503
+ * ── C — the reductions ──────────────────────────────────────────────────────
6504
+ *
6505
+ * (a) interest and financing revenues
6506
+ * (b) recapture — subsection 13(1)
6507
+ * (c) the taxpayer's share of a partnership's 13(1) inclusion
6508
+ * (d) resource inclusions — subsections 59(1), 59(3.2), paragraph 59.1(b)
6509
+ * (e) for a corporation, a grossed-up foreign tax credit amount:
6510
+ * **100/28** of what would be deductible under s.126(1), and
6511
+ * the s.126(2) amounts times the relevant factor
6512
+ *
6513
+ * ── Not modelled ────────────────────────────────────────────────────────────
6514
+ *
6515
+ * The trust variant of C(e), and the later paragraphs of B and C dealing with
6516
+ * foreign affiliate income and exempt interest. Each is available as an explicit
6517
+ * `otherAdditions` / `otherReductions` input rather than silently omitted, so a
6518
+ * preparer with one of those amounts can still arrive at the right figure and the
6519
+ * engine does not pretend the definition is shorter than it is.
6520
+ *
6521
+ * Source: `research/sources/legislation/ITA-section-18.2-EIFEL.txt`.
6522
+ *
6523
+ * Pure, whole dollars.
6524
+ */
6525
+ /** C(e)(i) — s.126(1) amounts are grossed up by 100/28. */
6526
+ const FOREIGN_TAX_CREDIT_GROSS_UP = 100 / 28;
6527
+ const nn$19 = (v) => Math.max(0, Math.round(v ?? 0));
6528
+ function computeAdjustedTaxableIncome(input) {
6529
+ const issues = [];
6530
+ const e = nn$19(input.nonCapitalLossForYear) + nn$19(input.lossClaimNotReducingTaxableIncome) + nn$19(input.foreignAccrualPropertyLossComponent);
6531
+ const incomeBase = Math.round(input.taxableIncome) - e;
6532
+ 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);
6533
+ 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);
6534
+ const adjustedTaxableIncome = incomeBase + totalAdditions - totalReductions;
6535
+ 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.`);
6536
+ 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.");
6537
+ return {
6538
+ incomeBase,
6539
+ totalAdditions,
6540
+ totalReductions,
6541
+ adjustedTaxableIncome,
6542
+ issues
6543
+ };
6544
+ }
6545
+ //#endregion
6546
+ //#region src/t2/schedules/eifel-capacity.ts
6547
+ const nn$18 = (v) => Math.max(0, Math.round(v ?? 0));
6548
+ /**
6549
+ * Part 2O on its own — the total of lines 159 to 162.
6550
+ *
6551
+ * Exported separately because of the order the form imposes: line 159 is the
6552
+ * denial from Part 2L, which cannot be computed until Parts 2G-2J have supplied
6553
+ * `excessReceivedCapacity` and `absorbedCapacity` to Part 2K. A caller running
6554
+ * the whole chain therefore computes capacity, then the limitation, then calls
6555
+ * this — rather than computing capacity twice.
6556
+ */
6557
+ function computeRifeUnderSubsection111_8(input) {
6558
+ return nn$18(input.excessInterestAndFinancingExpenses) + nn$18(input.partnershipIfeAddBack) + nn$18(input.clause95FapiAmountI) + nn$18(input.clause95FapiAmountII);
6559
+ }
6560
+ function computeEifelCapacity(input) {
6561
+ const issues = [];
6562
+ const ati = Math.round(input.adjustedTaxableIncome);
6563
+ const atiFloored = Math.max(0, ati);
6564
+ const ife = nn$18(input.interestAndFinancingExpenses);
6565
+ const ifr = nn$18(input.interestAndFinancingRevenues);
6566
+ const ratio = input.ratioOfPermissibleExpenses;
6567
+ const usedGroupRatio = input.hasGroupRatioElection === true;
6568
+ const receivedCapacity = (input.receivedCapacity ?? []).reduce((s, r) => s + nn$18(r.amount), 0);
6569
+ const permittedAmount = usedGroupRatio ? 0 : Math.round(atiFloored * ratio);
6570
+ const revenueOverExpense = usedGroupRatio ? 0 : Math.max(0, ifr - ife);
6571
+ const negativeAtiAbsolute = usedGroupRatio ? 0 : ati < 0 ? Math.abs(ati) : 0;
6572
+ const negativeAtiOffset = Math.min(revenueOverExpense, negativeAtiAbsolute);
6573
+ const negativeAtiOffsetAtRatio = Math.round(negativeAtiOffset * ratio);
6574
+ const revenueCapacity = usedGroupRatio ? 0 : Math.max(0, ifr - negativeAtiOffsetAtRatio);
6575
+ const totalCapacityBeforeExpenses = permittedAmount + revenueCapacity;
6576
+ const excessCapacityBeforeRife = usedGroupRatio ? 0 : Math.max(0, totalCapacityBeforeExpenses - ife);
6577
+ const rifeFromPreviousYears = nn$18(input.rifeFromPreviousYears);
6578
+ const rifeCapacityAvailable = excessCapacityBeforeRife + receivedCapacity;
6579
+ const rifeDeductible = Math.min(rifeFromPreviousYears, rifeCapacityAvailable);
6580
+ const excessCapacityForYear = Math.max(0, excessCapacityBeforeRife - rifeDeductible);
6581
+ const vintages = input.priorYearExcessCapacity ?? [];
6582
+ 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.`);
6583
+ 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);
6584
+ const cumulativeUnusedExcessCapacityBeforeAbsorption = priorYearUnusedCapacity + excessCapacityForYear;
6585
+ const absorbedShelter = (usedGroupRatio ? nn$18(input.groupRatioAmount) : Math.round(atiFloored * ratio)) + ifr;
6586
+ const absorbedRoom = Math.max(0, ife - absorbedShelter);
6587
+ const absorbedCapacity = Math.min(cumulativeUnusedExcessCapacityBeforeAbsorption, absorbedRoom);
6588
+ const cumulativeUnusedExcessCapacity = Math.max(0, cumulativeUnusedExcessCapacityBeforeAbsorption - absorbedCapacity);
6589
+ const excessReceivedCapacity = Math.max(0, receivedCapacity - rifeDeductible);
6590
+ const rifeForYear = computeRifeUnderSubsection111_8(input);
6591
+ 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.");
6592
+ return {
6593
+ receivedCapacity,
6594
+ permittedAmount,
6595
+ revenueOverExpense,
6596
+ negativeAtiAbsolute,
6597
+ negativeAtiOffset,
6598
+ negativeAtiOffsetAtRatio,
6599
+ revenueCapacity,
6600
+ totalCapacityBeforeExpenses,
6601
+ excessCapacityBeforeRife,
6602
+ excessCapacityForYear,
6603
+ rifeCapacityAvailable,
6604
+ rifeDeductible,
6605
+ priorYearUnusedCapacity,
6606
+ cumulativeUnusedExcessCapacityBeforeAbsorption,
6607
+ cumulativeUnusedExcessCapacity,
6608
+ absorbedCapacity,
6609
+ excessReceivedCapacity,
6610
+ rifeForYear,
6611
+ issues
6612
+ };
6613
+ }
6614
+ //#endregion
6830
6615
  //#region src/t2/schedules/eifel-excluded-entity.ts
6831
6616
  /**
6832
6617
  * EIFEL — excessive interest and financing expenses limitation (s.18.2, 18.21).
@@ -6888,7 +6673,7 @@ function assessEifel(input, thresholds) {
6888
6673
  if (input.domesticExceptionApplies === true) return exclude("domestic");
6889
6674
  const issues = [];
6890
6675
  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.`);
6676
+ 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
6677
  return {
6893
6678
  inForce: true,
6894
6679
  isExcludedEntity: false,
@@ -6898,6 +6683,289 @@ function assessEifel(input, thresholds) {
6898
6683
  };
6899
6684
  }
6900
6685
  //#endregion
6686
+ //#region src/t2/schedules/eifel-ife.ts
6687
+ const nn$17 = (v) => Math.max(0, Math.round(v ?? 0));
6688
+ const sum = (rows, pick) => rows.reduce((s, r) => s + pick(r), 0);
6689
+ function computeExemptIfe(rows) {
6690
+ return {
6691
+ totalExemptIfe: sum(rows, (r) => nn$17(r.ifeIncurred)),
6692
+ incomeFromExemptActivities: sum(rows, (r) => nn$17(r.incomeFromFundedActivities)),
6693
+ lossFromExemptActivities: sum(rows, (r) => nn$17(r.lossFromFundedActivities))
6694
+ };
6695
+ }
6696
+ function computeBorrowings(rows) {
6697
+ return {
6698
+ interestPaidOrPayable: sum(rows, (r) => nn$17(r.interestPaidOrPayable)),
6699
+ fundingCostAmounts: sum(rows, (r) => nn$17(r.fundingCostAmounts)),
6700
+ costReducingAmounts: sum(rows, (r) => nn$17(r.costReducingAmounts))
6701
+ };
6702
+ }
6703
+ function computeLoans(rows) {
6704
+ return {
6705
+ returnAmounts: sum(rows, (r) => nn$17(r.returnAmounts)),
6706
+ returnReducingAmounts: sum(rows, (r) => nn$17(r.returnReducingAmounts))
6707
+ };
6708
+ }
6709
+ function computePartnershipIfe(rows) {
6710
+ const computed = rows.map((r) => ({
6711
+ ...r.partnershipName !== void 0 ? { partnershipName: r.partnershipName } : {},
6712
+ includedAmount: Math.max(0, nn$17(r.shareOfPartnershipIfe) - nn$17(r.portionUnderParagraph12_1_l1) - nn$17(r.portionDeniedBySubsection96_2_1))
6713
+ }));
6714
+ return {
6715
+ rows: computed,
6716
+ totalIncluded: sum(computed, (r) => r.includedAmount)
6717
+ };
6718
+ }
6719
+ function computeCapitalizedIfe(rows) {
6720
+ const issues = [];
6721
+ const computed = rows.map((r) => {
6722
+ const ifeInUcc = Math.max(0, nn$17(r.ifeInOpeningUcc) + Math.round(r.ifeInAcquisitionsAndDispositions ?? 0));
6723
+ const requested = nn$17(r.ifeInCca);
6724
+ 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.`);
6725
+ const ifeInCca = Math.min(requested, ifeInUcc);
6726
+ return {
6727
+ ...r.ccaClass !== void 0 ? { ccaClass: r.ccaClass } : {},
6728
+ ifeInUcc,
6729
+ ifeInCca,
6730
+ closingIfeInUcc: Math.max(0, ifeInUcc - ifeInCca)
6731
+ };
6732
+ });
6733
+ return {
6734
+ rows: computed,
6735
+ totalIfeInTerminalLoss: sum(rows, (r) => nn$17(r.ifeInTerminalLoss)),
6736
+ totalIfeInCca: sum(computed, (r) => r.ifeInCca),
6737
+ issues
6738
+ };
6739
+ }
6740
+ function computeResourceIfe(rows) {
6741
+ const issues = [];
6742
+ const computed = rows.map((r) => {
6743
+ const ifeAvailable = Math.max(0, nn$17(r.ifeInOpeningBalance) + Math.round(r.ifeAddedOrDeducted ?? 0));
6744
+ const requested = nn$17(r.ifeInCurrentYearClaim);
6745
+ if (requested > ifeAvailable) issues.push(`EIFEL: IFE claimed in the ${r.pool} pool (${requested}) cannot exceed the IFE available before the claim (${ifeAvailable}). Capped.`);
6746
+ const ifeClaimed = Math.min(requested, ifeAvailable);
6747
+ return {
6748
+ pool: r.pool,
6749
+ ifeAvailable,
6750
+ ifeClaimed,
6751
+ closing: Math.max(0, ifeAvailable - ifeClaimed)
6752
+ };
6753
+ });
6754
+ return {
6755
+ rows: computed,
6756
+ totalIfeInResourceClaims: sum(computed, (r) => r.ifeClaimed),
6757
+ issues
6758
+ };
6759
+ }
6760
+ function computeInterestAndFinancingExpenses(input) {
6761
+ 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);
6762
+ const variableB = nn$17(input.costReducingAmounts) + nn$17(input.costReducingGain) + nn$17(input.costReducingPartnershipShare);
6763
+ return {
6764
+ variableA,
6765
+ variableB,
6766
+ totalIfe: Math.max(0, variableA - variableB)
6767
+ };
6768
+ }
6769
+ function computeInterestAndFinancingRevenues(input) {
6770
+ 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);
6771
+ 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);
6772
+ return {
6773
+ variableA,
6774
+ variableB,
6775
+ totalIfr: Math.max(0, variableA - variableB)
6776
+ };
6777
+ }
6778
+ function computeLossPortionFromIfe(rows) {
6779
+ const issues = [];
6780
+ const computed = rows.map((r) => {
6781
+ const loss = nn$17(r.nonCapitalLoss);
6782
+ const variableJ = Math.min(loss, nn$17(r.variableJSecondAmount));
6783
+ if (loss === 0) {
6784
+ 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.`);
6785
+ return {
6786
+ ...r.taxYearOfOrigin !== void 0 ? { taxYearOfOrigin: r.taxYearOfOrigin } : {},
6787
+ variableJ,
6788
+ attributableToIfe: 0
6789
+ };
6790
+ }
6791
+ return {
6792
+ ...r.taxYearOfOrigin !== void 0 ? { taxYearOfOrigin: r.taxYearOfOrigin } : {},
6793
+ variableJ,
6794
+ attributableToIfe: Math.round(nn$17(r.amountDeducted) * variableJ / loss)
6795
+ };
6796
+ });
6797
+ return {
6798
+ rows: computed,
6799
+ totalAttributableToIfe: sum(computed, (r) => r.attributableToIfe),
6800
+ issues
6801
+ };
6802
+ }
6803
+ /**
6804
+ * The amount actually denied, and the amount actually added back on Schedule 1
6805
+ * line 251.
6806
+ *
6807
+ * This is NOT simply "the shortfall". Part 2K computes a **proportion** (amount
6808
+ * G) and Part 2L applies it to a base that deliberately excludes two things
6809
+ * already counted elsewhere:
6810
+ *
6811
+ * 141 variable A of IFE
6812
+ * 142 less the partnership share (Part 1E amount A) — denied instead through
6813
+ * the paragraph 12(1)(l.2) add-back in Part 2N
6814
+ * 143 less a CFA's relevant affiliate IFE — denied instead through
6815
+ * clause 95(2)(f.11)(ii)(D) in Part 2M
6816
+ *
6817
+ * With neither of those present the base is variable A and the result equals
6818
+ * the raw shortfall, which is why a simple corporation sees no difference. With
6819
+ * either present, using the shortfall directly double-counts the denial.
6820
+ */
6821
+ function computeExcessIfe(input) {
6822
+ const base = Math.max(0, nn$17(input.variableAOfIfe) - nn$17(input.partnershipShare) - nn$17(input.affiliateRaife));
6823
+ return {
6824
+ base,
6825
+ excessIfe: Math.round(base * Math.max(0, input.deniedProportion))
6826
+ };
6827
+ }
6828
+ /**
6829
+ * Part 2N line 158 — the partnership IFE add-back under paragraph 12(1)(l.2):
6830
+ * the Part 1E total (line 156) at the Part 2K proportion (line 157). Feeds
6831
+ * Schedule 1 **line 252** and Part 2O **line 160**.
6832
+ */
6833
+ function computePartnershipIfeAddBack(partnershipShare, deniedProportion) {
6834
+ return Math.round(nn$17(partnershipShare) * Math.max(0, deniedProportion));
6835
+ }
6836
+ /**
6837
+ * @param deniedProportion Amount G from Part 2K — the proportion of each
6838
+ * expense denied under subsection 18.2(2). This is why Part 2M runs after the
6839
+ * limitation rather than before it.
6840
+ */
6841
+ function computeClause95Amounts(denied, included, deniedProportion) {
6842
+ return {
6843
+ deniedUnderSubclauseI: sum(denied, (r) => Math.round(nn$17(r.variableAForAffiliate) * deniedProportion * (r.specifiedParticipatingPercentage ?? 0))),
6844
+ includedUnderSubclauseII: sum(included, (r) => Math.round(nn$17(r.amountInAffiliateFapi) * (r.specifiedParticipatingPercentage ?? 0)))
6845
+ };
6846
+ }
6847
+ //#endregion
6848
+ //#region src/t2/schedules/eifel-limitation.ts
6849
+ /**
6850
+ * ITA subsection 18.2(2) — the excessive interest and financing expenses
6851
+ * limitation itself.
6852
+ *
6853
+ * `eifel-excluded-entity.ts` decides **whether** the regime applies. This decides
6854
+ * **how much** it denies, which was previously left unbuilt on the grounds that
6855
+ * computing it from an unbuilt definition would be confidently wrong.
6856
+ *
6857
+ * ── The provision ───────────────────────────────────────────────────────────
6858
+ *
6859
+ * s.18.2(2) denies a *proportion* of each interest and financing expense:
6860
+ *
6861
+ * (A − (B + C + D + E)) ÷ F
6862
+ *
6863
+ * A the taxpayer's interest and financing expenses for the year
6864
+ * B the group-ratio amount under s.18.21(2) where that applies, otherwise
6865
+ * **G × H** — the ratio of permissible expenses times adjusted taxable income
6866
+ * C the taxpayer's interest and financing revenues for the year
6867
+ * D received capacity, to the extent it exceeds the amount deductible under
6868
+ * paragraph 111(1)(a.1)
6869
+ * E absorbed capacity
6870
+ * F ordinarily the same figure as A
6871
+ *
6872
+ * Because F is A in the ordinary case, the *amount* denied is simply
6873
+ *
6874
+ * denied = A − (B + C + D + E), floored at nil
6875
+ *
6876
+ * which is the form this module computes, while still reporting the proportion —
6877
+ * the statute denies a fraction of *each* expense, and a preparer allocating the
6878
+ * denial across expense lines needs the fraction rather than the total.
6879
+ *
6880
+ * ── The ratio of permissible expenses ───────────────────────────────────────
6881
+ *
6882
+ * Keyed off when the taxation year **BEGINS**, not when it ends:
6883
+ *
6884
+ * begins on or after 2023-10-01 and before 2024-01-01 → **40%**
6885
+ * begins on or after 2024-01-01 → **30%**
6886
+ *
6887
+ * The 40% band is transitional and narrow — one quarter — and it does **not**
6888
+ * apply when determining cumulative unused excess capacity for a year beginning
6889
+ * on or after 1 January 2024. That carve-out is not modelled; excess-capacity
6890
+ * carry-forward is a separate mechanism this module does not compute.
6891
+ *
6892
+ * ── What this module does NOT compute ───────────────────────────────────────
6893
+ *
6894
+ * **Adjusted taxable income** is an input to THIS module, not a derivation — it
6895
+ * is a build-up from taxable income through a dozen add-backs and reductions,
6896
+ * and deriving it partially here would produce a plausible number from an
6897
+ * incomplete definition. It is therefore **required**, and an absent one denies
6898
+ * nothing while saying so. `eifel-adjusted-taxable-income.ts` derives it
6899
+ * (Schedule 130 Part 2F), and `computeFederalT2` feeds that result in.
6900
+ *
6901
+ * Likewise the received and absorbed capacity amounts, which come from the
6902
+ * excess-capacity regime — `eifel-capacity.ts` computes those (Parts 1A and
6903
+ * 2G-2J), and the engine threads them in as `excessReceivedCapacity` (Part 2K
6904
+ * amount C) and `absorbedCapacity` (Part 2H amount D). The group-ratio election
6905
+ * under s.18.21 remains a preparer assertion.
6906
+ *
6907
+ * Source: `research/sources/legislation/ITA-section-18.2-EIFEL.txt`.
6908
+ *
6909
+ * Pure, whole dollars.
6910
+ */
6911
+ /** The ratio bands, keyed off the taxation year START. */
6912
+ const EIFEL_TRANSITIONAL_RATIO = .4;
6913
+ const EIFEL_STANDARD_RATIO = .3;
6914
+ /** The regime's first day — years beginning before this are outside it. */
6915
+ const EIFEL_FIRST_YEAR_START = "2023-10-01";
6916
+ /** The transitional 40% band ends when years beginning in 2024 start. */
6917
+ const EIFEL_STANDARD_RATIO_FROM = "2024-01-01";
6918
+ const nn$16 = (v) => Math.max(0, Math.round(v ?? 0));
6919
+ function utcDay$1(iso) {
6920
+ return Date.parse(`${iso.slice(0, 10)}T00:00:00Z`);
6921
+ }
6922
+ /**
6923
+ * The ratio of permissible expenses for a year beginning on `taxYearStart`.
6924
+ * Returns 0 for a year beginning before the regime applies at all.
6925
+ */
6926
+ function ratioOfPermissibleExpenses(taxYearStart) {
6927
+ const start = utcDay$1(taxYearStart);
6928
+ if (Number.isNaN(start) || start < utcDay$1("2023-10-01")) return 0;
6929
+ return start < utcDay$1("2024-01-01") ? EIFEL_TRANSITIONAL_RATIO : EIFEL_STANDARD_RATIO;
6930
+ }
6931
+ function computeEifelLimitation(input) {
6932
+ const issues = [];
6933
+ const ife = nn$16(input.interestAndFinancingExpenses);
6934
+ const nil = (ratio) => ({
6935
+ ratioOfPermissibleExpenses: ratio,
6936
+ permittedAmount: 0,
6937
+ usedGroupRatio: false,
6938
+ totalShelter: 0,
6939
+ deniedAmount: 0,
6940
+ deniedProportion: 0,
6941
+ deductibleAmount: ife,
6942
+ issues
6943
+ });
6944
+ const ratio = ratioOfPermissibleExpenses(input.taxYearStart);
6945
+ if (ratio === 0) {
6946
+ issues.push(`EIFEL: the taxation year beginning ${input.taxYearStart} is before the regime applies (${EIFEL_FIRST_YEAR_START}), so nothing is denied.`);
6947
+ return nil(0);
6948
+ }
6949
+ const usedGroupRatio = input.groupRatioAmount !== void 0;
6950
+ if (!usedGroupRatio && input.adjustedTaxableIncome === void 0) {
6951
+ 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.");
6952
+ return nil(ratio);
6953
+ }
6954
+ const permittedAmount = usedGroupRatio ? nn$16(input.groupRatioAmount) : Math.round(ratio * Math.max(0, input.adjustedTaxableIncome ?? 0));
6955
+ const totalShelter = permittedAmount + nn$16(input.interestAndFinancingRevenues) + nn$16(input.excessReceivedCapacity) + nn$16(input.absorbedCapacity);
6956
+ const deniedAmount = Math.max(0, ife - totalShelter);
6957
+ return {
6958
+ ratioOfPermissibleExpenses: ratio,
6959
+ permittedAmount,
6960
+ usedGroupRatio,
6961
+ totalShelter,
6962
+ deniedAmount,
6963
+ deniedProportion: ife > 0 ? deniedAmount / ife : 0,
6964
+ deductibleAmount: ife - deniedAmount,
6965
+ issues
6966
+ };
6967
+ }
6968
+ //#endregion
6901
6969
  //#region src/t2/schedules/part-vi-1-deduction.ts
6902
6970
  const PART_VI_1_DEDUCTION_BANDS = [
6903
6971
  {
@@ -6913,15 +6981,15 @@ const PART_VI_1_DEDUCTION_BANDS = [
6913
6981
  multiple: 3.5
6914
6982
  }
6915
6983
  ];
6916
- function utcDay$1(iso) {
6984
+ function utcDay(iso) {
6917
6985
  return Date.parse(`${iso.slice(0, 10)}T00:00:00Z`);
6918
6986
  }
6919
6987
  /** The multiple in force for a taxation year ending on `taxYearEnd`. */
6920
6988
  function partVI1DeductionMultiple(taxYearEnd, bands = PART_VI_1_DEDUCTION_BANDS) {
6921
- const end = utcDay$1(taxYearEnd);
6989
+ const end = utcDay(taxYearEnd);
6922
6990
  if (Number.isNaN(end)) return 0;
6923
6991
  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;
6992
+ for (const band of [...bands].sort((a, b) => utcDay(a.from) - utcDay(b.from))) if (end >= utcDay(band.from)) multiple = band.multiple;
6925
6993
  return multiple;
6926
6994
  }
6927
6995
  /**
@@ -7080,10 +7148,10 @@ function assertSchedule1Fileable(result) {
7080
7148
  }
7081
7149
  //#endregion
7082
7150
  //#region src/t2/schedules/schedule2-donations.ts
7083
- const nn$17 = (v) => Math.max(0, v ?? 0);
7151
+ const nn$15 = (v) => Math.max(0, v ?? 0);
7084
7152
  function computeSchedule2(input, rates) {
7085
- const openingDonationPool = nn$17(input.openingDonationPool);
7086
- const currentYearDonations = nn$17(input.currentYearDonations);
7153
+ const openingDonationPool = nn$15(input.openingDonationPool);
7154
+ const currentYearDonations = nn$15(input.currentYearDonations);
7087
7155
  const available = openingDonationPool + currentYearDonations;
7088
7156
  const deductionLimit = Math.max(0, Math.round(rates.DONATION_INCOME_LIMIT_RATE * input.netIncomeForTax));
7089
7157
  const donationsClaimed = Math.min(available, deductionLimit);
@@ -7122,25 +7190,25 @@ function computeSchedule2(input, rates) {
7122
7190
  const PART_IV_RATE = 115 / 300;
7123
7191
  /** 30⅔% — the refundable portion of Part I tax on aggregate investment income. */
7124
7192
  const REFUNDABLE_PART_I_RATE = 92 / 300;
7125
- const nn$16 = (v) => Math.max(0, v ?? 0);
7193
+ const nn$14 = (v) => Math.max(0, v ?? 0);
7126
7194
  const DEFAULT_PART4_RATES = {
7127
7195
  PART_IV_RATE,
7128
7196
  REFUNDABLE_PART_I_RATE
7129
7197
  };
7130
7198
  function computePart4Rdtoh(input, rates = DEFAULT_PART4_RATES) {
7131
- const portfolio = nn$16(input.portfolioDividendsReceived);
7132
- const eligible = Math.min(portfolio, nn$16(input.eligiblePortfolioDividends));
7199
+ const portfolio = nn$14(input.portfolioDividendsReceived);
7200
+ const eligible = Math.min(portfolio, nn$14(input.eligiblePortfolioDividends));
7133
7201
  const nonEligible = portfolio - eligible;
7134
- const aaii = nn$16(input.aggregateInvestmentIncome);
7202
+ const aaii = nn$14(input.aggregateInvestmentIncome);
7135
7203
  const partIvOnEligible = Math.round(eligible * rates.PART_IV_RATE);
7136
7204
  const partIvOnNonEligible = Math.round(nonEligible * rates.PART_IV_RATE);
7137
7205
  const partIvTax = partIvOnEligible + partIvOnNonEligible;
7138
7206
  const refundablePartI = Math.round(aaii * rates.REFUNDABLE_PART_I_RATE);
7139
7207
  const erdtohAddition = partIvOnEligible;
7140
7208
  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);
7209
+ const erdtohClosing = nn$14(input.openingErdtoh) + erdtohAddition;
7210
+ const nerdtohClosing = nn$14(input.openingNerdtoh) + nerdtohAddition;
7211
+ const refundClaim = Math.round(nn$14(input.taxableDividendsPaid) * PART_IV_RATE);
7144
7212
  return {
7145
7213
  partIvTax,
7146
7214
  refundablePartI,
@@ -7304,7 +7372,7 @@ const PROVINCE_NAMES = {
7304
7372
  AB: "Alberta",
7305
7373
  QC: "Quebec"
7306
7374
  };
7307
- const nn$15 = (v) => Math.max(0, v ?? 0);
7375
+ const nn$13 = (v) => Math.max(0, v ?? 0);
7308
7376
  function computeProvincialAllocation(input, rates = PROVINCE_RATES_2024) {
7309
7377
  const byProvince = /* @__PURE__ */ new Map();
7310
7378
  for (const pe of input.permanentEstablishments) {
@@ -7313,8 +7381,8 @@ function computeProvincialAllocation(input, rates = PROVINCE_RATES_2024) {
7313
7381
  grossRevenue: 0,
7314
7382
  salariesWages: 0
7315
7383
  };
7316
- cur.grossRevenue += nn$15(pe.grossRevenue);
7317
- cur.salariesWages += nn$15(pe.salariesWages);
7384
+ cur.grossRevenue += nn$13(pe.grossRevenue);
7385
+ cur.salariesWages += nn$13(pe.salariesWages);
7318
7386
  byProvince.set(key, cur);
7319
7387
  }
7320
7388
  const totalRevenue = [...byProvince.values()].reduce((s, p) => s + p.grossRevenue, 0);
@@ -7458,7 +7526,7 @@ function computeSchedule6(dispositions, inclusionRate) {
7458
7526
  *
7459
7527
  * Whole dollars, pure functions, no I/O.
7460
7528
  */
7461
- const nn$14 = (v) => Math.max(0, v ?? 0);
7529
+ const nn$12 = (v) => Math.max(0, v ?? 0);
7462
7530
  const round = (v) => Math.round(v);
7463
7531
  /** CDE/CCOGPE-style short-tax-year proration: full rate at ≥357 days, else rate × days/365. */
7464
7532
  function stepYearFactor(daysInTaxYear) {
@@ -7493,13 +7561,13 @@ function forcedOrCappedClaim(requested, subtotal, issues, label) {
7493
7561
  }
7494
7562
  function computeDepletion(input = {}) {
7495
7563
  const issues = [];
7496
- const edaRegularPool = nn$14(input.edaRegularOpening);
7564
+ const edaRegularPool = nn$12(input.edaRegularOpening);
7497
7565
  const edaRegularClaim = claimUpToCap(input.edaRegularClaim, edaRegularPool, issues, "Schedule 12 EDA regular (115)");
7498
7566
  const edaRegularClosing = edaRegularPool - edaRegularClaim;
7499
- const edaSuccessorPool = nn$14(input.edaSuccessorOpening);
7567
+ const edaSuccessorPool = nn$12(input.edaSuccessorOpening);
7500
7568
  const edaSuccessorClaim = claimUpToCap(input.edaSuccessorClaim, edaSuccessorPool, issues, "Schedule 12 EDA successor (140)");
7501
7569
  const edaSuccessorClosing = edaSuccessorPool - edaSuccessorClaim;
7502
- const cmedbPool = nn$14(input.cmedbOpening);
7570
+ const cmedbPool = nn$12(input.cmedbOpening);
7503
7571
  const cmedbClaim = claimUpToCap(input.cmedbClaim, cmedbPool, issues, "Schedule 12 CMEDB (170)");
7504
7572
  return {
7505
7573
  edaRegularPool,
@@ -7517,10 +7585,10 @@ function computeDepletion(input = {}) {
7517
7585
  }
7518
7586
  function computeCee(input = {}) {
7519
7587
  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);
7588
+ const regularSubtotal = nn$12(input.regularOpening) + nn$12(input.regularCurrentYearExpenses) + nn$12(input.regularOtherAdditions) - nn$12(input.regularGovernmentAssistance) - nn$12(input.regularOtherDeductions);
7521
7589
  const regularClaim = forcedOrCappedClaim(input.regularClaim, regularSubtotal, issues, "Schedule 12 CEE regular (245)");
7522
7590
  const regularClosing = regularSubtotal > 0 ? regularSubtotal - regularClaim : 0;
7523
- const successorSubtotal = nn$14(input.successorOpening) - nn$14(input.successorOtherDeductions);
7591
+ const successorSubtotal = nn$12(input.successorOpening) - nn$12(input.successorOtherDeductions);
7524
7592
  const successorClaim = forcedOrCappedClaim(input.successorClaim, successorSubtotal, issues, "Schedule 12 CEE successor (295)");
7525
7593
  return {
7526
7594
  regularSubtotal,
@@ -7542,15 +7610,15 @@ function computeCde(input = {}, daysInTaxYear, cogpe = {
7542
7610
  successorSubtotal: 0
7543
7611
  }) {
7544
7612
  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));
7613
+ const regularCreditBalance = cogpe.regularSubtotal < 0 ? round(cogpe.regularSubtotal) : nn$12(input.regularCreditBalanceInCogpePool);
7614
+ 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);
7615
+ const rcdePortion = Math.min(nn$12(input.regularCurrentYearExpenses), Math.max(0, regularSubtotal));
7548
7616
  const regularCap = CDE_BASE_RATE * stepYearFactor(daysInTaxYear) * regularSubtotal + CDE_RCDE_BONUS_RATE * stepYearFactor(daysInTaxYear) * rcdePortion;
7549
7617
  const regularClaim = regularSubtotal > 0 ? claimUpToCap(input.regularClaim, regularCap, issues, "Schedule 12 CDE regular (345)") : 0;
7550
7618
  const regularClosing = Math.max(0, regularSubtotal - regularClaim);
7551
7619
  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);
7620
+ const successorCreditBalance = cogpe.successorSubtotal < 0 ? round(cogpe.successorSubtotal) : nn$12(input.successorCreditBalanceInCogpePool);
7621
+ const successorSubtotal = nn$12(input.successorOpening) - successorCreditBalance - nn$12(input.successorOtherDeductions);
7554
7622
  const successorCap = CDE_BASE_RATE * stepYearFactor(daysInTaxYear) * successorSubtotal;
7555
7623
  const successorClaim = successorSubtotal > 0 ? claimUpToCap(input.successorClaim, successorCap, issues, "Schedule 12 CDE successor (395)") : 0;
7556
7624
  return {
@@ -7570,13 +7638,13 @@ const COGPE_BASE_RATE = .1;
7570
7638
  const COGPE_RCOGPE_BONUS_RATE = .05;
7571
7639
  function computeCogpe(input = {}, daysInTaxYear) {
7572
7640
  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));
7641
+ 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);
7642
+ const rcogpePortion = Math.min(nn$12(input.regularCurrentYearExpenses), Math.max(0, regularSubtotal));
7575
7643
  const regularCap = COGPE_BASE_RATE * stepYearFactor(daysInTaxYear) * regularSubtotal + COGPE_RCOGPE_BONUS_RATE * stepYearFactor(daysInTaxYear) * rcogpePortion;
7576
7644
  const regularClaim = regularSubtotal > 0 ? claimUpToCap(input.regularClaim, regularCap, issues, "Schedule 12 COGPE regular (445)") : 0;
7577
7645
  const regularClosing = regularSubtotal > 0 ? regularSubtotal - regularClaim : 0;
7578
7646
  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);
7647
+ const successorSubtotal = nn$12(input.successorOpening) - nn$12(input.successorReceivableOnDisposition) - nn$12(input.successorOtherDeductions);
7580
7648
  const successorCap = COGPE_BASE_RATE * stepYearFactor(daysInTaxYear) * successorSubtotal;
7581
7649
  const successorClaim = successorSubtotal > 0 ? claimUpToCap(input.successorClaim, successorCap, issues, "Schedule 12 COGPE successor (495)") : 0;
7582
7650
  const successorClosing = Math.max(0, successorSubtotal - successorClaim);
@@ -7595,18 +7663,18 @@ function computeCogpe(input = {}, daysInTaxYear) {
7595
7663
  /** Part 7 — Foreign exploration and development expenses (pre-2001 tax years; still a real, if rare, carryforward). */
7596
7664
  function computeForeignExploration(input = {}, daysInTaxYear) {
7597
7665
  const issues = [];
7598
- const regularPool = nn$14(input.regularOpening) - nn$14(input.regularOtherDeductions);
7666
+ const regularPool = nn$12(input.regularOpening) - nn$12(input.regularOtherDeductions);
7599
7667
  let regularClaim = 0;
7600
7668
  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
7669
  else if (regularPool > 0) {
7602
- const cap = Math.max(COGPE_BASE_RATE * stepYearFactor(daysInTaxYear) * regularPool, nn$14(input.regularForeignResourceIncome));
7670
+ const cap = Math.max(COGPE_BASE_RATE * stepYearFactor(daysInTaxYear) * regularPool, nn$12(input.regularForeignResourceIncome));
7603
7671
  regularClaim = claimUpToCap(input.regularClaim, Math.min(regularPool, cap), issues, "Schedule 12 FEDE regular (520)");
7604
7672
  }
7605
7673
  const regularClosing = regularPool - regularClaim;
7606
- const successorPool = nn$14(input.successorOpening) - nn$14(input.successorOtherDeductions);
7674
+ const successorPool = nn$12(input.successorOpening) - nn$12(input.successorOtherDeductions);
7607
7675
  let successorClaim = 0;
7608
7676
  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)");
7677
+ else if (successorPool > 0) successorClaim = claimUpToCap(input.successorClaim, Math.min(successorPool, nn$12(input.successorForeignResourceIncome)), issues, "Schedule 12 FEDE successor (570)");
7610
7678
  const successorClosing = successorPool - successorClaim;
7611
7679
  return {
7612
7680
  regularPool,
@@ -7621,10 +7689,10 @@ function computeForeignExploration(input = {}, daysInTaxYear) {
7621
7689
  /** Part 8 — specified foreign exploration/development, regular OR successor (call once per column; rates are identical). */
7622
7690
  function computeSpecifiedForeignExploration(input = {}, label) {
7623
7691
  const issues = [];
7624
- const pool = nn$14(input.openingBalance) - nn$14(input.otherDeductions);
7692
+ const pool = nn$12(input.openingBalance) - nn$12(input.otherDeductions);
7625
7693
  let claim = 0;
7626
7694
  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);
7695
+ else if (pool > 0) claim = claimUpToCap(input.claim, Math.min(pool, Math.max(nn$12(input.foreignResourceIncome), pool)), issues, label);
7628
7696
  return {
7629
7697
  pool,
7630
7698
  claim,
@@ -7635,12 +7703,12 @@ function computeSpecifiedForeignExploration(input = {}, label) {
7635
7703
  /** Part 9 — cumulative foreign resource expenses, regular OR successor. */
7636
7704
  function computeCumulativeForeignResource(input = {}, daysInTaxYear, label) {
7637
7705
  const issues = [];
7638
- const pool = nn$14(input.openingBalance) + nn$14(input.currentYearExpenses) - nn$14(input.otherDeductions);
7706
+ const pool = nn$12(input.openingBalance) + nn$12(input.currentYearExpenses) - nn$12(input.otherDeductions);
7639
7707
  let claim = 0;
7640
7708
  if (pool < 0) issues.push(`${label}: a country-level pool is negative — include it as income on Schedule 1 manually.`);
7641
7709
  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));
7710
+ const a = Math.max(.1 * stepYearFactor(daysInTaxYear) * pool, Math.min(.3 * stepYearFactor(daysInTaxYear) * pool, nn$12(input.foreignResourceIncome)));
7711
+ const cap = a + Math.min(pool - a, nn$12(input.foreignResourceIncome));
7644
7712
  claim = claimUpToCap(input.claim, Math.min(pool, cap), issues, label);
7645
7713
  }
7646
7714
  return {
@@ -7694,15 +7762,15 @@ function computeSchedule12ResourceDeductions(input) {
7694
7762
  }
7695
7763
  //#endregion
7696
7764
  //#region src/t2/schedules/schedule13-reserves.ts
7697
- const nn$13 = (v) => Math.max(0, Math.round(v ?? 0));
7765
+ const nn$11 = (v) => Math.max(0, Math.round(v ?? 0));
7698
7766
  function computeSchedule13(rows = []) {
7699
7767
  let totalOpening = 0;
7700
7768
  let totalTransfer = 0;
7701
7769
  let totalClosing = 0;
7702
7770
  for (const r of rows) {
7703
- totalOpening += nn$13(r.opening);
7704
- totalTransfer += nn$13(r.transfer);
7705
- totalClosing += nn$13(r.closing);
7771
+ totalOpening += nn$11(r.opening);
7772
+ totalTransfer += nn$11(r.transfer);
7773
+ totalClosing += nn$11(r.closing);
7706
7774
  }
7707
7775
  const schedule1Addition = totalOpening + totalTransfer;
7708
7776
  const schedule1Deduction = totalClosing;
@@ -7717,15 +7785,15 @@ function computeSchedule13(rows = []) {
7717
7785
  }
7718
7786
  //#endregion
7719
7787
  //#region src/t2/schedules/schedule21-foreign-tax-credit.ts
7720
- const nn$12 = (v) => Math.max(0, v ?? 0);
7788
+ const nn$10 = (v) => Math.max(0, v ?? 0);
7721
7789
  function computeSchedule21(input) {
7722
7790
  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);
7791
+ const partITax = nn$10(input.partITax);
7792
+ const fNonBizIncome = nn$10(input.foreignNonBusinessIncome);
7793
+ const fNonBizTax = nn$10(input.foreignNonBusinessTaxPaid);
7794
+ const fBizIncome = nn$10(input.foreignBusinessIncome);
7795
+ const fBizTax = nn$10(input.foreignBusinessTaxPaid);
7796
+ const openingPool = nn$10(input.openingBusinessFtcPool);
7729
7797
  if (taxableIncome <= 0 || partITax <= 0) return {
7730
7798
  nonBusinessFtc: 0,
7731
7799
  businessFtc: 0,
@@ -7795,11 +7863,11 @@ function allocateEvenly(count, totalLimit = DEFAULT_BUSINESS_LIMIT) {
7795
7863
  }
7796
7864
  //#endregion
7797
7865
  //#region src/t2/schedules/schedule27-zetm.ts
7798
- const nn$11 = (v) => Math.max(0, v ?? 0);
7866
+ const nn$9 = (v) => Math.max(0, v ?? 0);
7799
7867
  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);
7868
+ const sbdIncome = nn$9(input.sbdIncome);
7869
+ const generalRateIncome = nn$9(input.generalRateIncome);
7870
+ const zetmIncome = Math.min(nn$9(input.zetmIncome), sbdIncome + generalRateIncome);
7803
7871
  const zetmSbdIncome = Math.min(zetmIncome, sbdIncome);
7804
7872
  const zetmGeneralIncome = Math.min(zetmIncome - zetmSbdIncome, generalRateIncome);
7805
7873
  const sbdDifferential = Math.max(0, input.sbdEffectiveRate - rates.ZETM_SBD_RATE);
@@ -7872,13 +7940,13 @@ function computeZetm(input, rates) {
7872
7940
  */
7873
7941
  /** s.127(27)-(29) — the recapture window. */
7874
7942
  const ITC_RECAPTURE_PERIOD_YEARS = 20;
7875
- const nn$10 = (v) => Math.max(0, Math.round(v ?? 0));
7943
+ const nn$8 = (v) => Math.max(0, Math.round(v ?? 0));
7876
7944
  function computeItcRecapture(items) {
7877
7945
  const issues = [];
7878
7946
  const results = items.map((item) => {
7879
7947
  const label = item.description ? ` (${item.description})` : "";
7880
7948
  const usedFairMarketValue = item.armsLengthProceeds === void 0;
7881
- const dispositionValue = usedFairMarketValue ? nn$10(item.fairMarketValue) : nn$10(item.armsLengthProceeds);
7949
+ const dispositionValue = usedFairMarketValue ? nn$8(item.fairMarketValue) : nn$8(item.armsLengthProceeds);
7882
7950
  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
7951
  const outsideRecapturePeriod = item.yearsSinceCredit !== void 0 && item.yearsSinceCredit > 20;
7884
7952
  const base = {
@@ -7891,12 +7959,12 @@ function computeItcRecapture(items) {
7891
7959
  outsideRecapturePeriod
7892
7960
  };
7893
7961
  if (outsideRecapturePeriod) return base;
7894
- const ownRecapture = Math.min(nn$10(item.itcEarned), Math.round(Math.max(0, item.itcRate) * dispositionValue));
7962
+ const ownRecapture = Math.min(nn$8(item.itcEarned), Math.round(Math.max(0, item.itcRate) * dispositionValue));
7895
7963
  let transferredRecapture = 0;
7896
7964
  if (item.transferred) {
7897
7965
  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));
7966
+ const formula = Math.round(Math.max(0, t.transfereeItcRate) * dispositionValue) - nn$8(t.alreadyRecaptured);
7967
+ transferredRecapture = Math.max(0, Math.min(nn$8(t.transfereeItcEarned), formula));
7900
7968
  }
7901
7969
  return {
7902
7970
  ...base,
@@ -7913,9 +7981,9 @@ function computeItcRecapture(items) {
7913
7981
  }
7914
7982
  //#endregion
7915
7983
  //#region src/t2/schedules/schedule31-sred-itc.ts
7916
- const nn$9 = (v) => Math.max(0, v ?? 0);
7984
+ const nn$7 = (v) => Math.max(0, v ?? 0);
7917
7985
  function computeSchedule31(input, rates) {
7918
- const qualifiedExpenditures = nn$9(input.qualifiedExpenditures);
7986
+ const qualifiedExpenditures = nn$7(input.qualifiedExpenditures);
7919
7987
  const isCcpc = input.isCcpc ?? false;
7920
7988
  const expenditureLimit = input.expenditureLimit ?? rates.SRED_EXPENDITURE_LIMIT;
7921
7989
  const enhancedBase = isCcpc ? Math.min(qualifiedExpenditures, expenditureLimit) : 0;
@@ -7924,8 +7992,8 @@ function computeSchedule31(input, rates) {
7924
7992
  const basicItc = Math.round(rates.SRED_ITC_BASIC_RATE * basicBase);
7925
7993
  const itcEarned = enhancedItc + basicItc;
7926
7994
  const refundableItc = enhancedItc;
7927
- const availableNonRefundable = basicItc + nn$9(input.openingItcPool);
7928
- const itcAppliedAgainstTax = Math.min(availableNonRefundable, nn$9(input.partITaxAvailable));
7995
+ const availableNonRefundable = basicItc + nn$7(input.openingItcPool);
7996
+ const itcAppliedAgainstTax = Math.min(availableNonRefundable, nn$7(input.partITaxAvailable));
7929
7997
  return {
7930
7998
  qualifiedExpenditures,
7931
7999
  expenditureLimit,
@@ -7964,17 +8032,17 @@ function computeSchedule31(input, rates) {
7964
8032
  /** The large-corporation filing / grind threshold (s.181.5, s.125(5.1)). */
7965
8033
  const LARGE_CORPORATION_THRESHOLD = 1e7;
7966
8034
  const n$1 = (v) => Math.round(v ?? 0);
7967
- const nn$8 = (v) => Math.max(0, Math.round(v ?? 0));
8035
+ const nn$6 = (v) => Math.max(0, Math.round(v ?? 0));
7968
8036
  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);
8037
+ 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);
8038
+ const deductions = nn$6(input.deferredTaxDebit) + nn$6(input.deficitInEquity) + nn$6(input.patronageDeducted) + nn$6(input.deferredForexLosses);
7971
8039
  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);
8040
+ 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
8041
  const taxableCapital = Math.max(0, capital - investmentAllowance);
7974
8042
  let ratio = 1;
7975
8043
  if (input.taxableIncomeEarnedInCanada !== void 0 && input.taxableIncome !== void 0) {
7976
8044
  const denom = input.taxableIncome > 0 ? input.taxableIncome : 1e3;
7977
- ratio = Math.max(0, Math.min(1, nn$8(input.taxableIncomeEarnedInCanada) / denom));
8045
+ ratio = Math.max(0, Math.min(1, nn$6(input.taxableIncomeEarnedInCanada) / denom));
7978
8046
  }
7979
8047
  const taxableCapitalEmployedInCanada = Math.round(taxableCapital * ratio);
7980
8048
  return {
@@ -7987,18 +8055,18 @@ function computeTaxableCapital(input = {}) {
7987
8055
  }
7988
8056
  //#endregion
7989
8057
  //#region src/t2/schedules/schedule43-part6-1.ts
7990
- const nn$7 = (v) => Math.max(0, v ?? 0);
8058
+ const nn$5 = (v) => Math.max(0, v ?? 0);
7991
8059
  function computeSchedule43(input, rates) {
7992
- const shortTerm = nn$7(input.shortTermPreferredDividends);
7993
- const other = nn$7(input.otherPreferredDividends);
8060
+ const shortTerm = nn$5(input.shortTermPreferredDividends);
8061
+ const other = nn$5(input.otherPreferredDividends);
7994
8062
  const issues = [];
7995
8063
  let dividendAllowance;
7996
8064
  if (input.isAssociated === true) if (input.allocatedAllowance == null) {
7997
8065
  dividendAllowance = 0;
7998
8066
  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);
8067
+ } else dividendAllowance = Math.min(nn$5(input.allocatedAllowance), rates.DIVIDEND_ALLOWANCE);
8000
8068
  else dividendAllowance = rates.DIVIDEND_ALLOWANCE;
8001
- const priorExcess = Math.max(0, nn$7(input.priorYearPreferredDividends) - rates.ALLOWANCE_GRIND_THRESHOLD);
8069
+ const priorExcess = Math.max(0, nn$5(input.priorYearPreferredDividends) - rates.ALLOWANCE_GRIND_THRESHOLD);
8002
8070
  dividendAllowance = Math.max(0, dividendAllowance - priorExcess);
8003
8071
  const shortTermTaxable = Math.max(0, shortTerm - dividendAllowance);
8004
8072
  const allowanceLeft = Math.max(0, dividendAllowance - shortTerm);
@@ -8021,12 +8089,12 @@ function computeSchedule43(input, rates) {
8021
8089
  }
8022
8090
  //#endregion
8023
8091
  //#region src/t2/schedules/schedule53-grip.ts
8024
- const nn$6 = (v) => Math.max(0, v ?? 0);
8092
+ const nn$4 = (v) => Math.max(0, v ?? 0);
8025
8093
  function computeGrip(input, gripFactor = .72) {
8026
- const openingGrip = nn$6(input.openingGrip);
8094
+ const openingGrip = nn$4(input.openingGrip);
8027
8095
  const generalRateAddition = Math.round(gripFactor * Math.max(0, input.generalRateIncome));
8028
- const eligibleDividendsReceived = nn$6(input.eligibleDividendsReceived);
8029
- const eligibleDividendsDesignated = nn$6(input.eligibleDividendsDesignated);
8096
+ const eligibleDividendsReceived = nn$4(input.eligibleDividendsReceived);
8097
+ const eligibleDividendsDesignated = nn$4(input.eligibleDividendsDesignated);
8030
8098
  const gripBeforeDesignation = openingGrip + generalRateAddition + eligibleDividendsReceived;
8031
8099
  const excessiveDesignation = Math.max(0, eligibleDividendsDesignated - gripBeforeDesignation);
8032
8100
  return {
@@ -8128,24 +8196,24 @@ function computeGrip(input, gripFactor = .72) {
8128
8196
  const LRIP_INVESTMENT_INCOME_FACTOR = .8;
8129
8197
  /** Line 160 — the investment corporation deduction enters the pool at four times its value. */
8130
8198
  const LRIP_INVESTMENT_CORPORATION_MULTIPLE = 4;
8131
- const nn$5 = (v) => Math.max(0, Math.round(v ?? 0));
8199
+ const nn$3 = (v) => Math.max(0, Math.round(v ?? 0));
8132
8200
  const sn = (v) => Math.round(v ?? 0);
8133
8201
  function computeSchedule54(input) {
8134
8202
  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);
8203
+ const openingLrip = nn$3(input.openingLrip);
8204
+ const investmentIncomeAddition = Math.round(LRIP_INVESTMENT_INCOME_FACTOR * nn$3(input.priorYearAggregateInvestmentIncome));
8205
+ const investmentCorporationAddition = 4 * nn$3(input.priorYearInvestmentCorporationDeduction);
8138
8206
  const lripBeforeDividends = openingLrip + investmentIncomeAddition + investmentCorporationAddition;
8139
8207
  const ordered = [...input.dividendEvents ?? []].sort((a, b) => a.date.localeCompare(b.date));
8140
8208
  const events = [];
8141
8209
  let designationsSoFar = 0;
8142
8210
  for (const e of ordered) {
8143
- const poolBeforeReductions = lripBeforeDividends + nn$5(e.dividendsReceivableBefore) + sn(e.adjustmentsBefore);
8211
+ const poolBeforeReductions = lripBeforeDividends + nn$3(e.dividendsReceivableBefore) + sn(e.adjustmentsBefore);
8144
8212
  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);
8213
+ const excessiveDesignationsBefore = e.excessiveDesignationsBefore !== void 0 ? nn$3(e.excessiveDesignationsBefore) : derivedPrior;
8214
+ 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.`);
8215
+ const lripAtDate = Math.max(0, poolBeforeReductions - nn$3(e.dividendsPayableBefore) - excessiveDesignationsBefore);
8216
+ const eligibleDividendsPaid = nn$3(e.eligibleDividendsPaid);
8149
8217
  const excessiveDesignation = Math.max(0, Math.min(lripAtDate, eligibleDividendsPaid));
8150
8218
  events.push({
8151
8219
  date: e.date,
@@ -8158,8 +8226,8 @@ function computeSchedule54(input) {
8158
8226
  designationsSoFar += excessiveDesignation;
8159
8227
  }
8160
8228
  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;
8229
+ const poolIncludingReceipts = lripBeforeDividends + nn$3(input.dividendsReceivableInYear) + sn(input.adjustmentsInYear);
8230
+ const totalReductions = nn$3(input.dividendsPayableInYear) + totalExcessiveDesignation;
8163
8231
  const closingLrip = Math.max(0, poolIncludingReceipts - totalReductions);
8164
8232
  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
8233
  return {
@@ -8177,7 +8245,7 @@ function computeSchedule54(input) {
8177
8245
  }
8178
8246
  //#endregion
8179
8247
  //#region src/t2/schedules/schedule55-part3-1.ts
8180
- const nn$4 = (v) => Math.max(0, v ?? 0);
8248
+ const nn$2 = (v) => Math.max(0, v ?? 0);
8181
8249
  /**
8182
8250
  * Compute Part III.1 tax.
8183
8251
  *
@@ -8186,10 +8254,10 @@ const nn$4 = (v) => Math.max(0, v ?? 0);
8186
8254
  */
8187
8255
  function computeSchedule55(input, baseRate = .2, paragraphCRate = .1) {
8188
8256
  const issues = [];
8189
- const excessiveDesignation = nn$4(input.excessiveDesignation);
8257
+ const excessiveDesignation = nn$2(input.excessiveDesignation);
8190
8258
  const arisesUnderParagraphC = input.arisesUnderParagraphC === true;
8191
8259
  const electionAvailable = !arisesUnderParagraphC;
8192
- const claimed = input.electedAmount !== void 0 ? nn$4(input.electedAmount) : input.electsMaximum === true ? excessiveDesignation : 0;
8260
+ const claimed = input.electedAmount !== void 0 ? nn$2(input.electedAmount) : input.electsMaximum === true ? excessiveDesignation : 0;
8193
8261
  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
8262
  let reclassifiedAsOrdinary = electionAvailable ? Math.min(claimed, excessiveDesignation) : 0;
8195
8263
  if (electionAvailable && claimed > excessiveDesignation) {
@@ -8314,6 +8382,24 @@ function computeSchedule101(input) {
8314
8382
  * schedules): AAII refundable tax + RDTOH, Part IV tax, M&P, associated-group
8315
8383
  * allocation, provincial/AT1 tax (computed separately).
8316
8384
  */
8385
+ /**
8386
+ * Every `issues` string the given sub-results raised, in one flat list.
8387
+ *
8388
+ * Deliberately structural rather than a hand-written list of fields: a result
8389
+ * qualifies by HAVING an `issues` array, so a schedule that starts raising them
8390
+ * is surfaced without anyone remembering to come back here. Duplicates are
8391
+ * dropped — two schedules can reach the same conclusion about the same missing
8392
+ * input, and a preparer should be told once.
8393
+ */
8394
+ function collectIssues(results) {
8395
+ const seen = /* @__PURE__ */ new Set();
8396
+ for (const value of Object.values(results)) {
8397
+ const issues = value?.issues;
8398
+ if (!Array.isArray(issues)) continue;
8399
+ for (const issue of issues) if (typeof issue === "string" && issue !== "") seen.add(issue);
8400
+ }
8401
+ return [...seen];
8402
+ }
8317
8403
  /** Date | ISO string | undefined → `YYYY-MM-DD` ('' when absent/invalid). */
8318
8404
  function isoDay(v) {
8319
8405
  if (v instanceof Date) return Number.isNaN(v.getTime()) ? "" : v.toISOString().slice(0, 10);
@@ -8456,76 +8542,266 @@ function computeFederalT2(input) {
8456
8542
  ref: "s.66(4)/66.7(2)"
8457
8543
  });
8458
8544
  }
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 } : {}
8545
+ /**
8546
+ * Schedule 1 → net income → Division C → taxable income → Schedule 33, as a
8547
+ * closure, because EIFEL makes it run **twice**.
8548
+ *
8549
+ * Subsection 18.2(1) defines adjusted taxable income from taxable income
8550
+ * "determined without regard to subsection 18.2(2), paragraphs 12(1)(l.2)
8551
+ * and 111(1)(a.1)" — and those three are exactly the three adjustments the
8552
+ * EIFEL computation produces (Schedule 1 lines 251 and 252, and the jacket
8553
+ * line 336 deduction). So the limitation cannot be an input to the base it
8554
+ * is computed from: the first pass supplies that base, the EIFEL chain runs
8555
+ * on it, and the second pass applies the three adjustments it produced.
8556
+ *
8557
+ * Every step in here is a pure function of its arguments, so running it
8558
+ * twice costs only arithmetic and cannot drift between the passes which
8559
+ * is the reason it is one closure rather than two copies of the sequence.
8560
+ */
8561
+ const runIncomeSequence = (eifelAdjustments) => {
8562
+ const passAdditions = eifelAdjustments ? [...schedule1Additions, ...eifelAdjustments.additions] : schedule1Additions;
8563
+ const schedule1 = computeSchedule1({
8564
+ bookNetIncome: input.bookNetIncome,
8565
+ ...passAdditions.length ? { additions: passAdditions } : {},
8566
+ ...schedule1Deductions.length ? { deductions: schedule1Deductions } : {}
8567
+ });
8568
+ const partVI1 = input.preferredShareDividends && ((input.preferredShareDividends.shortTermPreferredDividends ?? 0) > 0 || (input.preferredShareDividends.otherPreferredDividends ?? 0) > 0) ? computeSchedule43(input.preferredShareDividends, {
8569
+ SHORT_TERM_RATE: rates.PART_VI_1_SHORT_TERM_RATE,
8570
+ ELECTED_RATE: rates.PART_VI_1_ELECTED_RATE,
8571
+ BASE_RATE: rates.PART_VI_1_BASE_RATE,
8572
+ DIVIDEND_ALLOWANCE: rates.PART_VI_1_DIVIDEND_ALLOWANCE,
8573
+ ALLOWANCE_GRIND_THRESHOLD: rates.PART_VI_1_ALLOWANCE_GRIND_THRESHOLD
8574
+ }) : void 0;
8575
+ const partVI1Deduction = partVI1 ? computePartVI1Deduction(partVI1.partVI1Tax, isoDay(input.periodEnd)) : void 0;
8576
+ const donations = input.charitableDonations !== void 0 || input.openingDonationPool !== void 0 ? computeSchedule2({
8577
+ ...input.openingDonationPool !== void 0 ? { openingDonationPool: input.openingDonationPool } : {},
8578
+ ...input.charitableDonations !== void 0 ? { currentYearDonations: input.charitableDonations } : {},
8579
+ netIncomeForTax: schedule1.netIncomeForTax
8580
+ }, rates) : void 0;
8581
+ const culturalEcologicalGiftsClaimed = Math.max(0, input.culturalEcologicalGifts ?? 0);
8582
+ const divisionCDeductions = [
8583
+ ...donations && donations.donationsClaimed > 0 ? [{
8584
+ line: "112",
8585
+ label: "Charitable donations and gifts from Schedule 2",
8586
+ amount: donations.donationsClaimed,
8587
+ ref: "s.110.1"
8588
+ }] : [],
8589
+ ...culturalEcologicalGiftsClaimed > 0 ? [{
8590
+ line: "112",
8591
+ label: "Gifts of certified cultural property and ecologically sensitive land from Schedule 2",
8592
+ amount: culturalEcologicalGiftsClaimed,
8593
+ ref: "s.110.1(1)(b)/(c) not subject to the 75% income limit"
8594
+ }] : [],
8595
+ ...partVI1Deduction && partVI1Deduction.deduction > 0 ? [{
8596
+ line: "325",
8597
+ label: "Part VI.1 tax deduction",
8598
+ amount: partVI1Deduction.deduction,
8599
+ ref: `s.110(1)(k) — ${partVI1Deduction.multiple}× Part VI.1 tax payable`
8600
+ }] : [],
8601
+ ...input.divisionCDeductions ?? [],
8602
+ ...eifelAdjustments?.deductions ?? []
8603
+ ];
8604
+ const taxableIncomeCalc = computeTaxableIncome({
8605
+ netIncomeForTax: schedule1.netIncomeForTax,
8606
+ ...divisionCDeductions.length ? { deductions: divisionCDeductions } : {}
8607
+ });
8608
+ const currentYearNonCapitalLoss = Math.max(0, -schedule1.netIncomeForTax);
8609
+ const lossCarryback = input.lossCarrybacks?.length ? computeLossCarryback({
8610
+ currentYearLoss: currentYearNonCapitalLoss,
8611
+ carrybacks: input.lossCarrybacks
8612
+ }) : void 0;
8613
+ const nonCapitalCarriedBack = lossCarryback ? lossCarryback.totalCarriedBack : input.nonCapitalLossCarriedBack;
8614
+ const losses = computeSchedule4Losses({
8615
+ ...input.openingNonCapitalLoss !== void 0 ? { openingNonCapitalLoss: input.openingNonCapitalLoss } : {},
8616
+ ...input.openingNetCapitalLoss !== void 0 ? { openingNetCapitalLoss: input.openingNetCapitalLoss } : {},
8617
+ netIncomeForTax: schedule1.netIncomeForTax,
8618
+ taxableIncomeBeforeLosses: taxableIncomeCalc.taxableIncome,
8619
+ ...capitalGains ? { taxableCapitalGains: capitalGains.taxableCapitalGain } : input.taxableCapitalGains !== void 0 ? { taxableCapitalGains: input.taxableCapitalGains } : {},
8620
+ ...input.nonCapitalLossToApply !== void 0 ? { nonCapitalLossToApply: input.nonCapitalLossToApply } : {},
8621
+ ...input.netCapitalLossToApply !== void 0 ? { netCapitalLossToApply: input.netCapitalLossToApply } : {},
8622
+ ...nonCapitalCarriedBack !== void 0 ? { nonCapitalCarriedBack } : {},
8623
+ ...input.nonCapitalLossExpired !== void 0 ? { nonCapitalExpired: input.nonCapitalLossExpired } : {},
8624
+ ...input.netCapitalLossExpired !== void 0 ? { netCapitalExpired: input.netCapitalLossExpired } : {},
8625
+ ...capitalGains && capitalGains.currentYearNetCapitalLoss > 0 ? { currentYearNetCapitalLoss: capitalGains.currentYearNetCapitalLoss } : input.currentYearNetCapitalLoss !== void 0 ? { currentYearNetCapitalLoss: input.currentYearNetCapitalLoss } : {}
8626
+ });
8627
+ const taxableIncome = Math.max(0, taxableIncomeCalc.taxableIncome - losses.totalApplied);
8628
+ const associatedAllocation = input.associatedMembers ? computeBusinessLimitAllocation({ members: input.associatedMembers }) : void 0;
8629
+ const taxableCapitalSchedule = input.taxableCapitalDetail ? computeTaxableCapital({
8630
+ ...input.taxableCapitalDetail,
8631
+ ...input.taxableCapitalDetail.taxableIncome === void 0 ? { taxableIncome } : {}
8632
+ }) : void 0;
8633
+ return {
8634
+ schedule1,
8635
+ partVI1,
8636
+ partVI1Deduction,
8637
+ donations,
8638
+ culturalEcologicalGiftsClaimed,
8639
+ divisionCDeductions,
8640
+ taxableIncomeCalc,
8641
+ currentYearNonCapitalLoss,
8642
+ lossCarryback,
8643
+ nonCapitalCarriedBack,
8644
+ losses,
8645
+ taxableIncome,
8646
+ associatedAllocation,
8647
+ taxableCapitalSchedule,
8648
+ grindTaxableCapital: input.taxableCapital ?? taxableCapitalSchedule?.taxableCapitalEmployedInCanada
8649
+ };
8650
+ };
8651
+ const provisional = runIncomeSequence();
8652
+ const eifel = assessEifel({
8653
+ taxYearStart: isoDay(input.periodStart ?? input.period?.start),
8654
+ ...(input.eifel?.isCcpc ?? input.isCcpc) !== void 0 ? { isCcpc: input.eifel?.isCcpc ?? input.isCcpc } : {},
8655
+ ...(() => {
8656
+ const tc = input.eifel?.groupTaxableCapital ?? provisional.taxableCapitalSchedule?.taxableCapitalEmployedInCanada ?? input.taxableCapital;
8657
+ return tc !== void 0 ? { groupTaxableCapital: tc } : {};
8658
+ })(),
8659
+ ...input.eifel?.netInterestAndFinancingExpenses !== void 0 ? { netInterestAndFinancingExpenses: input.eifel.netInterestAndFinancingExpenses } : {},
8660
+ ...input.eifel?.domesticExceptionApplies !== void 0 ? { domesticExceptionApplies: input.eifel.domesticExceptionApplies } : {}
8661
+ }, {
8662
+ SMALL_CCPC_TAXABLE_CAPITAL: rates.EIFEL_SMALL_CCPC_TAXABLE_CAPITAL,
8663
+ DE_MINIMIS_NET_IFE: rates.EIFEL_DE_MINIMIS_NET_IFE
8521
8664
  });
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;
8665
+ const eifelChain = (() => {
8666
+ if (!eifel.requiresLimitation) return null;
8667
+ const e = input.eifel;
8668
+ const taxYearStart = isoDay(input.periodStart ?? input.period?.start);
8669
+ const exemptIfe = computeExemptIfe(e?.exemptIfe ?? []);
8670
+ const borrowings = computeBorrowings(e?.borrowings ?? []);
8671
+ const loans = computeLoans(e?.loans ?? []);
8672
+ const partnership = computePartnershipIfe(e?.partnershipIfe ?? []);
8673
+ const capitalized = computeCapitalizedIfe(e?.capitalizedIfe ?? []);
8674
+ const resourceIfe = computeResourceIfe(e?.resourceIfe ?? []);
8675
+ const lossPortion = computeLossPortionFromIfe(e?.lossPortionFromIfe ?? []);
8676
+ const ife = computeInterestAndFinancingExpenses({
8677
+ ...e?.ifeDetail ?? {},
8678
+ interestOnBorrowings: borrowings.interestPaidOrPayable,
8679
+ ifeInCca: capitalized.totalIfeInCca,
8680
+ ifeInResourceExpenses: resourceIfe.totalIfeInResourceClaims,
8681
+ ifeInTerminalLoss: capitalized.totalIfeInTerminalLoss,
8682
+ fundingCostAmounts: borrowings.fundingCostAmounts,
8683
+ partnershipShare: partnership.totalIncluded,
8684
+ costReducingAmounts: borrowings.costReducingAmounts
8685
+ });
8686
+ const ifr = computeInterestAndFinancingRevenues({
8687
+ ...e?.ifrDetail ?? {},
8688
+ returnAmounts: loans.returnAmounts,
8689
+ returnReducingAmounts: loans.returnReducingAmounts
8690
+ });
8691
+ const eifelIfe = e?.interestAndFinancingExpenses ?? ife.totalIfe;
8692
+ const eifelIfr = e?.interestAndFinancingRevenues ?? ifr.totalIfr;
8693
+ const ati = computeAdjustedTaxableIncome({
8694
+ ...e?.adjustedTaxableIncomeDetail ?? {},
8695
+ taxableIncome: provisional.taxableIncome,
8696
+ nonCapitalLossForYear: provisional.currentYearNonCapitalLoss,
8697
+ lossClaimNotReducingTaxableIncome: Math.max(0, provisional.losses.totalApplied - Math.max(0, provisional.taxableIncomeCalc.taxableIncome)),
8698
+ interestAndFinancingExpenses: eifelIfe,
8699
+ capitalCostAllowance: cca?.totalCca ?? 0,
8700
+ resourceDeductions: resourceDeductions ? resourceDeductions.depletionClaim + resourceDeductions.ceeClaim + resourceDeductions.cdeClaim + resourceDeductions.cogpeClaim + resourceDeductions.foreignClaim : 0,
8701
+ terminalLoss: cca?.totalTerminalLoss ?? 0,
8702
+ partVI1TaxDeduction: provisional.partVI1Deduction?.deduction ?? 0,
8703
+ lossPortionDerivedFromIfe: lossPortion.totalAttributableToIfe,
8704
+ exemptIfeActivityLoss: exemptIfe.lossFromExemptActivities,
8705
+ exemptIfeActivityIncome: exemptIfe.incomeFromExemptActivities,
8706
+ interestAndFinancingRevenues: eifelIfr,
8707
+ recapture: cca?.totalRecapture ?? 0
8708
+ });
8709
+ const resolvedAti = e?.adjustedTaxableIncome ?? ati.adjustedTaxableIncome;
8710
+ const capacityBase = computeEifelCapacity({
8711
+ adjustedTaxableIncome: resolvedAti,
8712
+ interestAndFinancingExpenses: eifelIfe,
8713
+ interestAndFinancingRevenues: eifelIfr,
8714
+ ratioOfPermissibleExpenses: ratioOfPermissibleExpenses(taxYearStart),
8715
+ ...e?.hasGroupRatioElection !== void 0 ? { hasGroupRatioElection: e.hasGroupRatioElection } : {},
8716
+ ...e?.groupRatioAmount !== void 0 ? { groupRatioAmount: e.groupRatioAmount } : {},
8717
+ ...e?.receivedCapacity ? { receivedCapacity: e.receivedCapacity } : {},
8718
+ ...e?.rifeFromPreviousYears !== void 0 ? { rifeFromPreviousYears: e.rifeFromPreviousYears } : {},
8719
+ ...e?.priorYearExcessCapacity ? { priorYearExcessCapacity: e.priorYearExcessCapacity } : {}
8720
+ });
8721
+ const limitation = computeEifelLimitation({
8722
+ interestAndFinancingExpenses: eifelIfe,
8723
+ adjustedTaxableIncome: resolvedAti,
8724
+ interestAndFinancingRevenues: eifelIfr,
8725
+ excessReceivedCapacity: capacityBase.excessReceivedCapacity,
8726
+ absorbedCapacity: capacityBase.absorbedCapacity,
8727
+ ...e?.hasGroupRatioElection && e?.groupRatioAmount !== void 0 ? { groupRatioAmount: e.groupRatioAmount } : {},
8728
+ taxYearStart
8729
+ });
8730
+ const { excessIfe } = computeExcessIfe({
8731
+ variableAOfIfe: e?.interestAndFinancingExpenses ?? ife.variableA,
8732
+ partnershipShare: partnership.totalIncluded,
8733
+ ...e?.ifeDetail?.affiliateRaife !== void 0 ? { affiliateRaife: e.ifeDetail.affiliateRaife } : {},
8734
+ deniedProportion: limitation.deniedProportion
8735
+ });
8736
+ const partnershipIfeAddBack = e?.partnershipIfeAddBack ?? computePartnershipIfeAddBack(partnership.totalIncluded, limitation.deniedProportion);
8737
+ const clause95 = computeClause95Amounts(e?.clause95Denied ?? [], e?.clause95Included ?? [], limitation.deniedProportion);
8738
+ return {
8739
+ ati,
8740
+ limitation,
8741
+ capacity: {
8742
+ ...capacityBase,
8743
+ rifeForYear: computeRifeUnderSubsection111_8({
8744
+ excessInterestAndFinancingExpenses: excessIfe,
8745
+ partnershipIfeAddBack,
8746
+ clause95FapiAmountI: e?.clause95FapiAmountI ?? clause95.deniedUnderSubclauseI,
8747
+ clause95FapiAmountII: e?.clause95FapiAmountII ?? clause95.includedUnderSubclauseII
8748
+ }),
8749
+ issues: [
8750
+ ...capacityBase.issues,
8751
+ ...capitalized.issues,
8752
+ ...resourceIfe.issues,
8753
+ ...lossPortion.issues
8754
+ ]
8755
+ },
8756
+ ife,
8757
+ ifr,
8758
+ excessIfe,
8759
+ partnershipIfeAddBack
8760
+ };
8761
+ })();
8762
+ /**
8763
+ * A return inside the regime that never supplied its GROSS interest and
8764
+ * financing expenses computes a denial of nil — which looks like "nothing was
8765
+ * restricted" and is really "nothing was measured". The group NET figure that
8766
+ * settled the de-minimis test above is not a substitute: it is a different
8767
+ * figure, for a different purpose, at group level.
8768
+ */
8769
+ const eifelWithIssues = eifel.requiresLimitation && !((eifelChain?.ife.totalIfe ?? 0) > 0) ? {
8770
+ ...eifel,
8771
+ 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."]
8772
+ } : eifel;
8773
+ /**
8774
+ * The three adjustments the EIFEL computation produces, on the lines the
8775
+ * forms name for them:
8776
+ *
8777
+ * Schedule 1 line 251 the denial under s.18.2(2) (Part 2L amount B)
8778
+ * Schedule 1 line 252 the 12(1)(l.2) partnership add-back (Part 2N)
8779
+ * jacket line 336 the 111(1)(a.1) RIFE deduction (Part 2J amount B)
8780
+ *
8781
+ * Each is one of the three things adjusted taxable income is defined to
8782
+ * disregard, which is why applying them needs the second pass below rather
8783
+ * than being folded into the first.
8784
+ */
8785
+ const eifelAdjustments = eifelChain ? {
8786
+ additions: [...eifelChain.excessIfe > 0 ? [{
8787
+ line: "251",
8788
+ label: "Excess IFE under subsection 18.2(2) from Schedule 130",
8789
+ amount: eifelChain.excessIfe,
8790
+ ref: "s.18.2(2)"
8791
+ }] : [], ...eifelChain.partnershipIfeAddBack > 0 ? [{
8792
+ line: "252",
8793
+ label: "Partnership IFE add-back under paragraph 12(1)(l.2) from Schedule 130",
8794
+ amount: eifelChain.partnershipIfeAddBack,
8795
+ ref: "s.12(1)(l.2)"
8796
+ }] : []],
8797
+ deductions: eifelChain.capacity.rifeDeductible > 0 ? [{
8798
+ line: "336",
8799
+ label: "Restricted interest and financing expenses from Schedule 4",
8800
+ amount: eifelChain.capacity.rifeDeductible,
8801
+ ref: "s.111(1)(a.1)"
8802
+ }] : []
8803
+ } : void 0;
8804
+ 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
8805
  const adjustedAggregateInvestmentIncomeSchedule = input.adjustedAggregateInvestmentIncomeDetail ? computeAdjustedAggregateInvestmentIncome(input.adjustedAggregateInvestmentIncomeDetail) : void 0;
8530
8806
  const resolvedAaii = input.aaii ?? adjustedAggregateInvestmentIncomeSchedule?.adjustedAggregateInvestmentIncome;
8531
8807
  const aggregateInvestmentIncomeSchedule = input.aggregateInvestmentIncomeDetail ? computeAggregateInvestmentIncome(input.aggregateInvestmentIncomeDetail) : void 0;
@@ -8617,19 +8893,6 @@ function computeFederalT2(input) {
8617
8893
  ...input.provincialAllocationFactor !== void 0 ? { allocationFactor: input.provincialAllocationFactor } : {}
8618
8894
  }, provinceRates) : void 0;
8619
8895
  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
8896
  const internetBusiness = input.internetBusiness ? normalizeSchedule88(input.internetBusiness) : void 0;
8634
8897
  const firstReturn = input.firstReturn ? computeSchedule101(input.firstReturn) : void 0;
8635
8898
  return {
@@ -8657,7 +8920,14 @@ function computeFederalT2(input) {
8657
8920
  ...partIII1 ? { partIII1 } : {},
8658
8921
  ...partVI1 ? { partVI1 } : {},
8659
8922
  ...partVI1Deduction ? { partVI1Deduction } : {},
8660
- eifel,
8923
+ eifel: eifelWithIssues,
8924
+ ...eifelChain ? {
8925
+ eifelAdjustedTaxableIncome: eifelChain.ati,
8926
+ eifelLimitation: eifelChain.limitation,
8927
+ eifelCapacity: eifelChain.capacity,
8928
+ eifelIfe: eifelChain.ife,
8929
+ eifelIfr: eifelChain.ifr
8930
+ } : {},
8661
8931
  ...internetBusiness ? { internetBusiness } : {},
8662
8932
  ...firstReturn ? { firstReturn } : {},
8663
8933
  ...sredItc ? { sredItc } : {},
@@ -8672,7 +8942,37 @@ function computeFederalT2(input) {
8672
8942
  taxableIncome,
8673
8943
  federalTaxPayable: partI.partITaxPayable,
8674
8944
  totalFederalTax,
8675
- totalTax
8945
+ totalTax,
8946
+ issues: collectIssues({
8947
+ eifel: eifelWithIssues,
8948
+ ...eifelChain ? {
8949
+ eifelAdjustedTaxableIncome: eifelChain.ati,
8950
+ eifelLimitation: eifelChain.limitation,
8951
+ eifelCapacity: eifelChain.capacity,
8952
+ eifelIfe: eifelChain.ife,
8953
+ eifelIfr: eifelChain.ifr
8954
+ } : {},
8955
+ ...partVI1 ? { partVI1 } : {},
8956
+ ...class13 ? { class13 } : {},
8957
+ ...class14 ? { class14 } : {},
8958
+ ...class141AdditionalAllowance ? { class141AdditionalAllowance } : {},
8959
+ ...associatedAllocation ? { associatedAllocation } : {},
8960
+ ...sredItc ? { sredItc } : {},
8961
+ ...firstReturn ? { firstReturn } : {}
8962
+ }),
8963
+ schedulePayloads: federalSchedulePayloads({
8964
+ schedule1,
8965
+ netIncomeForTax: schedule1.netIncomeForTax,
8966
+ taxableIncome,
8967
+ totalFederalTax,
8968
+ ...donations ? { donations } : {},
8969
+ ...adjustedAggregateInvestmentIncomeSchedule ? { adjustedAggregateInvestmentIncomeSchedule } : {},
8970
+ ...cca ? { cca } : {},
8971
+ ...foreignTaxCredit ? { foreignTaxCredit } : {},
8972
+ ...taxableCapitalSchedule ? { taxableCapitalSchedule } : {},
8973
+ ...grip ? { grip } : {},
8974
+ ...partIII1 ? { partIII1 } : {}
8975
+ })
8676
8976
  };
8677
8977
  }
8678
8978
  //#endregion
@@ -8910,7 +9210,7 @@ function computeQuebecTax(input, rates = QC_TAX_2024) {
8910
9210
  }
8911
9211
  //#endregion
8912
9212
  //#region src/t2/co17/schedules/quebec-allocation.ts
8913
- const nn$3 = (v) => Math.max(0, v ?? 0);
9213
+ const nn$1 = (v) => Math.max(0, v ?? 0);
8914
9214
  function computeQuebecAllocationFactor(establishments, quebecCode = "QC") {
8915
9215
  let quebecRevenue = 0;
8916
9216
  let totalRevenue = 0;
@@ -8919,8 +9219,8 @@ function computeQuebecAllocationFactor(establishments, quebecCode = "QC") {
8919
9219
  let quebecCount = 0;
8920
9220
  const total = establishments.length;
8921
9221
  for (const pe of establishments) {
8922
- const rev = nn$3(pe.grossRevenue);
8923
- const pay = nn$3(pe.salariesWages);
9222
+ const rev = nn$1(pe.grossRevenue);
9223
+ const pay = nn$1(pe.salariesWages);
8924
9224
  totalRevenue += rev;
8925
9225
  totalSalaries += pay;
8926
9226
  if (pe.province === quebecCode) {
@@ -9408,215 +9708,6 @@ function computeT2Settlement(input) {
9408
9708
  };
9409
9709
  }
9410
9710
  //#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
9711
  //#region src/t2/schedules/schedule27-mp.ts
9621
9712
  /**
9622
9713
  * T2 Schedule 27 — Canadian Manufacturing and Processing Profits Deduction
@@ -9794,4 +9885,4 @@ function computeMpDeduction(input, rates = MP_RATES_2024) {
9794
9885
  };
9795
9886
  }
9796
9887
  //#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 };
9888
+ export { computeSchedule6 as $, resolveRates as $i, resolveCcaRates as $n, computeIegReductionFactor as $r, dividendsDeductibleS112 as $t, LRIP_INVESTMENT_CORPORATION_MULTIPLE as A, schedule12LossDeductions as Ai, AT1_RESERVE_LINES as An, renderRsiHeader as Ar, computeExcessIfe as At, computeZetm as B, schedule2Values$1 as Bi, CLASS_14_1_MINIMUM_DEDUCTION as Bn, assertCriticalFields as Br, assessEifel as Bt, runConformance as C, SINGLE_JURISDICTION_ALBERTA_FACTOR 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, AT1_SCHEDULES_WITH_BUILDERS as Di, SECTION_34_2_GROSS_UP as Dn, formatRsiDate as Dr, computeBorrowings as Dt, computeSchedule101 as E, AT1_SCHEDULES_WITHOUT_BUILDERS as Ei, AT1_DISPOSITION_CATEGORIES as En, formatRsiAmount as Er, ratioOfPermissibleExpenses as Et, LARGE_CORPORATION_THRESHOLD as F, schedule18Values as Fi, computeAlbertaSchedule13 as Fn, At1MandatoryFieldMissingError as Fr, computeLossPortionFromIfe as Ft, computeCde as G, computeDayWeightedGeneralTax as Gi, computeClass13 as Gn, computeAlbertaReturn as Gr, PROVINCE_RATES_2024 as Gt, computeBusinessLimitAllocation as H, computeAlbertaTax as Hi, CLASS_14_1_TRANSITIONAL_RATE as Hn, at1YesNo as Hr, computeRifeUnderSubsection111_8 as Ht, computeTaxableCapital as I, schedule1Values$1 as Ii, UnsupportedCcaClassError as In, At1TaxPayableMismatchError as Ir, computePartnershipIfe as It, computeCumulativeForeignResource as J, resolveAlbertaTaxRates as Ji, computeClass141RecaptureReduction as Jn, computeIegAgreement as Jr, resolveProvinceRates as Jt, computeCee as K, AB_TAX_2024 as Ki, computeClass14 as Kn, allocateIegEvenly as Kr, PROVINCE_RATE_BOOK as Kt, computeSchedule31 as L, schedule20Values as Li, computeCcaClass as Ln, albertaBalanceUnpaid as Lr, computePartnershipIfeAddBack as Lt, computeSchedule54 as M, schedule13Values as Mi, computeAlbertaSchedule17 as Mn, renderAt1NetFile as Mr, computeInterestAndFinancingExpenses as Mt, computeGrip as N, schedule16Values as Ni, assistanceFrom as Nn, AT1_CRITICAL_MANDATORY_FIELDS as Nr, computeInterestAndFinancingRevenues as Nt, normalizeSchedule88 as O, at1LineItemId as Oi, computeAlbertaSchedule18 as On, formatRsiText as Or, computeCapitalizedIfe as Ot, computeSchedule43 as P, schedule17Values as Pi, computeAlbertaSchedule16 as Pn, At1CriticalFieldMissingError as Pr, computeLoans as Pt, computeSpecifiedForeignExploration as Q, latestRateYear as Qi, isDecliningBalanceClass as Qn, computeIegBaseAmount as Qr, computeTaxableIncome as Qt, ITC_RECAPTURE_PERIOD_YEARS as R, schedule21Values$1 as Ri, computeCcaSchedule as Rn, assertAt1MandatoryComplete as Rr, computeResourceIfe as Rt, formatConformanceReport as S, schedule3Values as Si, AT1_DONATION_GAIN_RATE as Sn, RSI_DELIMITER as Sr, EIFEL_STANDARD_RATIO as St, computeFederalT2 as T, computeAt4970 as Ti, computeSchedule20 as Tn, RsiLineItemError as Tr, computeEifelLimitation as Tt, computeSchedule21 as U, computeAlbertaSbd as Ui, MAX_LEASEHOLD_PERIODS as Un, xmlEscape as Ur, FOREIGN_TAX_CREDIT_GROSS_UP as Ut, allocateEvenly as V, schedule4970Values as Vi, CLASS_14_1_RECAPTURE_REDUCTION_RATE as Vn, at1TaxPayableDeductions as Vr, computeEifelCapacity as Vt, computeSchedule13 as W, AB_GENERAL_RATE_BANDS as Wi, MIN_LEASEHOLD_PERIODS as Wn, at1Engine as Wr, computeAdjustedTaxableIncome as Wt, computeForeignExploration as X, extendRateBook as Xi, CCA_DECLINING_BALANCE_RATES_2024 as Xn, IEG_2024 as Xr, dayWeightedRate as Xt, computeDepletion as Y, earliestRateYear as Yi, leaseholdPeriods as Yn, computeIegGroupFigures as Yr, blendProvinceRateTable as Yt, computeSchedule12ResourceDeductions as Z, hasExactRateYear 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, computeCdeRegular as ai, computeAggregateInvestmentIncome as an, albertaDispositionAdjustments as ar, computePart4Rdtoh as at, T2_LINE_META as b, schedule4Values as bi, computeLimitedPartnershipLossRow as bn, toRsiSchedule as br, partVI1DeductionMultiple as bt, computeSmallManufacturerTest as c, computeCeeSuccessor as ci, CORP_TAX_2024 as cn, albertaResourceDeductionDifference as cr, amortizationAddBack as ct, t2Engine as d, computeCmedb as di, federalSchedulePayloads as dn, reconcileAlbertaNetIncome as dr, computeSchedule1 as dt, computeIegEligibleExpenditures as ei, netCapitalLossApplied as en, albertaAbilDifference as er, computeProvincialAllocation as et, renderCo17DraftReturn as f, 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, computeCcogpeSuccessor as ii, computeAdjustedAggregateInvestmentIncome as in, albertaCurrentYearLoss as ir, REFUNDABLE_PART_I_RATE as it, LRIP_INVESTMENT_INCOME_FACTOR as j, schedule12Values as ji, AT1_RESERVE_TOTAL_LINES as jn, renderRsiLineItem as jr, computeExemptIfe as jt, computeSchedule55 as k, schedule10Values as ki, AT1_RESERVE_KINDS as kn, renderAt1Rsi as kr, computeClause95Amounts as kt, computeT2Settlement as l, computeCfreRegular as li, CORP_TAX_RATE_BOOK as ln, albertaTerminalLossDifference as lr, assertSchedule1Fileable as lt, computeQuebecReturn as m, computeFedeRegular as mi, T2_CERTIFICATION_FIXTURES as mn, At1TransmitterInvalidError as mr, incomeTaxProvisionAddBack as mt, MP_GROSS_REVENUE_THRESHOLD as n, computeAlbertaSchedule15 as ni, computeCcpcActiveBusinessTax as nn, albertaCcaDifference as nr, computeSchedule4Losses as nt, computeMpDeduction as o, computeCdeSuccessor as oi, computeBusinessLimit as on, albertaRecaptureDifference as or, computeSchedule2 as ot, co17Engine as p, computeEdaSuccessor as pi, t2LineItemId as pn, computeLossCarryback as pr, findSchedule1LineDefects as pt, computeCogpe as q, AB_TAX_RATE_BOOK as qi, computeClass141AdditionalAllowance as qn, allocateIegExpenditureLimit as qr, isSchedule5Province as qt, MP_RATES_2024 as r, computeCcogpeRegular as ri, computePartITax as rn, albertaCcaScheduleAdjustments as rr, PART_IV_RATE as rt, computePart2MPProfits as s, computeCeeRegular as si, computeSBD as sn, albertaReserveDifference as sr, Schedule1NotFileableError as st, MP_EXCLUDED_ACTIVITIES as t, iegT661SourceLine as ti, nonCapitalLossApplied as tn, albertaCapitalGainDifference as tr, computeSchedule5 as tt, renderT2DraftReturn as u, 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, computeAllocationFactor as wi, computeDonationMaximum as wn, RSI_WORD_GAP as wr, EIFEL_TRANSITIONAL_RATIO as wt, foldT2Lines as x, computeSchedule3 as xi, computeLimitedPartnershipLosses as xn, RSI_COLUMN_GAP as xr, EIFEL_FIRST_YEAR_START as xt, resolveQuebecTaxRates as y, computeSchedule4 as yi, computeLossContinuity as yn, toRsiLineItems as yr, computePartVI1Deduction as yt, computeItcRecapture as z, schedule29Values as zi, computeSchedule8 as zn, assertAt1TaxPayableReconciles as zr, EIFEL_EFFECTIVE_FROM as zt };