@classytic/ca-tax 0.0.1 → 0.0.2

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
@@ -431,15 +431,93 @@ function schedule18Values(result) {
431
431
  values
432
432
  };
433
433
  }
434
- function schedule29Values(result) {
434
+ /**
435
+ * Field ids read off the live, TRA-certified form
436
+ * (`research/sources/tra-forms/pdf/AT1SCH29-*.pdf`, Rev. 2026-06):
437
+ *
438
+ * Page 1/2 — the grant itself:
439
+ * 110 8% of the capped expenditures
440
+ * 112 12% of the increment above base — the non-associated path. Filed
441
+ * INSTEAD of 125, never alongside it.
442
+ * 125 12% of the associated path's allocated allowed amount — filed
443
+ * instead of 112 when `result.enhancedRateBasis === 'associated'`.
444
+ * 126 taxable capital the line-128 factor was computed from
445
+ * 128 the taxable-capital reduction factor, 0 to 1
446
+ * 130 (110 + 112-or-125) × 128 — the credit before recapture
447
+ * 132 recapture, only where the caller supplied one
448
+ * 134 NET IEG — the figure AT1 page 2, line 129 carries forward
449
+ *
450
+ * Page 3 — the Agreement Among Associated Corporations, filed only when the
451
+ * group agreed one (`agreement`, from `computeIegAgreement` in
452
+ * `schedule29-ieg-group.ts`); omitted entirely for a non-associated claim:
453
+ * 200/202/204/206/208 the longest-year member's CAN, that member's own
454
+ * tax year begin/end, days in that year, and the resulting $4M-pool
455
+ * maximum for the group
456
+ * Per member, occurrence incrementing in the order given (claimant first):
457
+ * 220 Federal Business Number, 230 Alberta CAN, 235 current taxation
458
+ * year end, 240 allocated expenditure limit, 245 current-year
459
+ * expenditures, 250 prior year 1, 260 prior year 2, 265 taxable capital
460
+ * (prior year), 267 individual maximum allowed amount, 268 allocated
461
+ * allowed amount. The form has NO line for the member's NAME — 220 is
462
+ * the Federal Business Number, confirmed by re-rendering page 3 of the
463
+ * live form (a prior version of this function filed `name` at 220,
464
+ * which put free text in a box the form defines as a 9-10 digit account
465
+ * number; `name` is not transmitted at all, matching the form).
466
+ * 270/275/280/290/300 Σ 240/245/250/260/265 across every member
467
+ * 310 the group Allowed Amount — 275 − (280 + 290) / 2
468
+ * 320 Σ 268
469
+ * 325 the claiming corporation's own 268 — this is what feeds line 125
470
+ * above (`associatedAllowedAmount` in `computeIeg`'s input)
471
+ *
472
+ * 128 is a RATIO, not a dollar figure — formatted to 6 decimal places, the
473
+ * same precision `schedule2.ts`'s Reg 402 allocation factor uses. That
474
+ * precision is this codebase's own convention, not something confirmed
475
+ * against TRA's certification validator for THIS field; verify before relying
476
+ * on it for a corporation whose taxable capital sits inside the $10M–$50M
477
+ * band. See `schedule29-ieg.ts` for why 128 exists and the one unresolved
478
+ * discrepancy in how 130 is meant to be computed.
479
+ */
480
+ function schedule29Values(result, agreement) {
435
481
  const values = [];
436
- const put = (fieldId, value) => values.push({
437
- lineItemId: at1LineItemId("029", fieldId),
482
+ const put = (fieldId, value, occurrence = 1) => values.push({
483
+ lineItemId: at1LineItemId("029", fieldId, occurrence),
438
484
  value
439
485
  });
440
486
  put("110", result.creditAtBaseRate);
441
- put("112", result.creditAtEnhancedRate);
442
- put("128", result.incrementalExpenditures);
487
+ put(result.enhancedRateBasis === "associated" ? "125" : "112", result.creditAtEnhancedRate);
488
+ put("126", result.taxableCapital);
489
+ put("128", result.reductionFactor.toFixed(6));
490
+ put("130", result.grossIeg);
491
+ if (result.recapture > 0) put("132", result.recapture);
492
+ put("134", result.ieg);
493
+ if (agreement) {
494
+ put("200", agreement.longestYearCan);
495
+ put("202", agreement.longestYearBegin);
496
+ put("204", agreement.longestYearEnd);
497
+ put("206", agreement.daysInLongestYear);
498
+ put("208", agreement.maximumExpenditureLimit);
499
+ agreement.members.forEach((m, i) => {
500
+ const n = i + 1;
501
+ if (m.federalBusinessNumber !== void 0) put("220", m.federalBusinessNumber, n);
502
+ if (m.albertaCan !== void 0) put("230", m.albertaCan, n);
503
+ if (m.currentTaxationYearEnd !== void 0) put("235", m.currentTaxationYearEnd, n);
504
+ put("240", m.allocatedExpenditureLimit, n);
505
+ put("245", m.currentYearExpenditures, n);
506
+ put("250", m.priorYear1, n);
507
+ put("260", m.priorYear2, n);
508
+ put("265", m.taxableCapitalPriorYear, n);
509
+ put("267", m.individualMaximumAllowedAmount, n);
510
+ put("268", m.allocatedAllowedAmount, n);
511
+ });
512
+ put("270", agreement.totalAllocatedLimit);
513
+ put("275", agreement.totalCurrentYearExpenditures);
514
+ put("280", agreement.totalPriorYear1);
515
+ put("290", agreement.totalPriorYear2);
516
+ put("300", agreement.totalTaxableCapitalPriorYear);
517
+ put("310", agreement.groupAllowedAmount);
518
+ put("320", agreement.totalAllocatedAllowedAmount);
519
+ put("325", agreement.claimantAllocatedAllowedAmount);
520
+ }
443
521
  return {
444
522
  scheduleId: "029",
445
523
  values
@@ -769,35 +847,83 @@ function computeAllocationFactor(input) {
769
847
  * AT1 Schedule 29 — Alberta Innovation Employment Grant (IEG). AT1 line 129.
770
848
  *
771
849
  * A refundable grant on eligible R&D (SR&ED) carried out in Alberta:
772
- * - 8% base rate on eligible expenditures up to the base level of spending
773
- * - 20% enhanced rate on the INCREMENT above the base level
774
- * (equivalently: 8% on everything + an extra 12% on the increment)
775
- * base level = average of the prior two years' eligible Alberta expenditures
776
- * (associated group aggregated — pass all members' figures)
777
- *
778
- * Eligible expenditures are capped at a $4,000,000 annual limit, reduced on a
779
- * straight-line taxable-capital grind ($10M $50M), shared across an associated
780
- * group. Pure, integer whole dollars.
781
- *
782
- * NOT modelled here (a later associated-group layer): allocation of the shared
783
- * $4M limit across associated corporations (Test Case 3's A/B/C/D grind). This
784
- * computes one corporation's grant given its eligible expenditures, its (group)
785
- * base amount, and its allocated expenditure limit.
850
+ * - line 110: 8% of the CAPPED eligible expenditures (the full amount, not
851
+ * just the portion below base)
852
+ * - line 112 (non-associated): 12% of the increment ABOVE the base level of
853
+ * spending — base level = average of the prior two years'
854
+ * eligible Alberta expenditures (associated group aggregated —
855
+ * pass all members' figures)
856
+ * - line 125 (associated, via a filed agreement): 12% of the LESSER of the
857
+ * expenditure limit and the agreement's allocated allowed
858
+ * amount see `computeIegAgreement` in `schedule29-ieg-group.ts`.
859
+ * A genuinely different formula, not a variant of 112's — it does
860
+ * not reference actual spending at all once the agreement exists.
861
+ *
862
+ * Eligible expenditures are capped at a $4,000,000 annual limit (shared across an
863
+ * associated group; NOT reduced by taxable capital — see below). Pure, integer
864
+ * whole dollars.
865
+ *
866
+ * ── The taxable-capital grind applies to the CREDIT, not the limit ──────────
867
+ *
868
+ * A prior version of this module reduced the $4,000,000 expenditure limit itself
869
+ * on a straight-line taxable-capital grind ($10M → $50M) — modelled on the
870
+ * federal SBD grind's shape, but wrong for this form. Rendering the live,
871
+ * TRA-certified Schedule 29 (`research/sources/tra-forms/pdf/AT1SCH29-*.pdf`,
872
+ * Rev. 2026-06 — cross-checked against AuraTax's live rendering of the same
873
+ * schedule, `research/validation/auratax/2026-08-25-at1-schedule1-royalty/`)
874
+ * shows the grind lives at **line 128**, a REDUCTION FACTOR from 0 to 1:
875
+ *
876
+ * line 128 = (($40,000,000 − (line 126 − $10,000,000)) / $40,000,000)
877
+ * (enter 1 if taxable capital ≤ $10,000,000)
878
+ * line 130 = (line 110 + (line 112 or line 125)) × line 128
879
+ *
880
+ * i.e. the credit is computed in FULL against the unreduced $4M limit, and ONLY
881
+ * THEN scaled by the taxable-capital factor — not the limit ground down first
882
+ * and the credit computed against the smaller number. The two are NOT
883
+ * equivalent except at the band's endpoints (TC ≤ $10M ⇒ both give the full
884
+ * credit; TC ≥ $50M ⇒ both give nil).
885
+ *
886
+ * ── One thing not yet resolved, and worth raising with TRA directly ─────────
887
+ *
888
+ * The AT1 jacket's OWN business-rule table (`research/sources/tra-spec/
889
+ * AT1-Chapter3-2025.2-full.txt`, version 2025.2 / August 2025 — ten months
890
+ * OLDER than the Schedule 29 PDF above) states jacket line 129 as
891
+ * `(029110 + 029112 X 029128) minus 029132` — multiplying ONLY line 112 by the
892
+ * factor, not the sum of 110 and 112. That contradicts Schedule 29's own
893
+ * printed caption, which the certified oracle (AuraTax) also renders as
894
+ * "sum then multiply". This module follows the newer, doubly-corroborated
895
+ * Schedule 29 form. Confirm with TRA before relying on this for an associated
896
+ * corporation with taxable capital between $10M and $50M — the disagreement
897
+ * changes the filed dollar figure.
898
+ *
899
+ * ── The formal Agreement (line 125) ──────────────────────────────────────────
900
+ *
901
+ * TRA's Test Case 3 (four associated corporations, `research/sources/
902
+ * tra-test-cases/Alberta Test Case 3 - Fall 2025.txt`) is the associated path:
903
+ * pass `associatedAllowedAmount` (line 325 of `computeIegAgreement`'s result)
904
+ * and this function uses line 125's formula instead of line 112's. Day-of-year
905
+ * proration of the $4M pool for a short or long taxation year (lines 104/108/
906
+ * 206/208) is modelled in `computeIegAgreement`, not here — this function
907
+ * takes the already-allocated `expenditureLimit` as an input.
786
908
  */
787
909
  const IEG_2024 = Object.freeze({
788
910
  BASE_RATE: .08,
789
- ENHANCED_RATE: .2,
911
+ ENHANCED_RATE: .12,
790
912
  MAX_EXPENDITURE: 4e6,
791
913
  TC_GRIND_LOWER: 1e7,
792
914
  TC_GRIND_UPPER: 5e7,
793
915
  PRIOR_YEARS: 2
794
916
  });
795
- /** The eligible-expenditure limit ($4M) reduced by the taxable-capital grind. */
796
- function computeIegExpenditureLimit(taxableCapital, sharedLimit = IEG_2024.MAX_EXPENDITURE) {
797
- const { TC_GRIND_LOWER, TC_GRIND_UPPER } = IEG_2024;
798
- const tcInBand = Math.max(0, Math.min(Math.max(0, taxableCapital), TC_GRIND_UPPER) - TC_GRIND_LOWER);
799
- const reduction = Math.round(sharedLimit * tcInBand / (TC_GRIND_UPPER - TC_GRIND_LOWER));
800
- return Math.max(0, sharedLimit - reduction);
917
+ /**
918
+ * The line-128 reduction factor: 1 at or below $10M taxable capital, straight-
919
+ * line down to 0 at $50M. Multiplies the COMBINED base + enhanced credit at
920
+ * line 130 it does not touch the $4,000,000 expenditure limit.
921
+ */
922
+ function computeIegReductionFactor(taxableCapital, lower = IEG_2024.TC_GRIND_LOWER, upper = IEG_2024.TC_GRIND_UPPER) {
923
+ const tc = Math.max(0, taxableCapital);
924
+ if (tc <= lower) return 1;
925
+ const band = upper - lower;
926
+ return Math.max(0, Math.min(1, (band - (tc - lower)) / band));
801
927
  }
802
928
  /**
803
929
  * Base level of spending = average of the prior years' eligible Alberta
@@ -813,16 +939,26 @@ function computeIeg(input) {
813
939
  const limit = input.expenditureLimit ?? IEG_2024.MAX_EXPENDITURE;
814
940
  const cappedExpenditures = Math.max(0, Math.min(input.eligibleExpenditures, limit));
815
941
  const incrementalExpenditures = Math.max(0, cappedExpenditures - input.baseAmount);
816
- const baseRatePortion = cappedExpenditures - incrementalExpenditures;
817
- const creditAtBaseRate = Math.round(IEG_2024.BASE_RATE * baseRatePortion);
818
- const creditAtEnhancedRate = Math.round(IEG_2024.ENHANCED_RATE * incrementalExpenditures);
942
+ const creditAtBaseRate = Math.round(IEG_2024.BASE_RATE * cappedExpenditures);
943
+ const enhancedRateBasis = input.associatedAllowedAmount !== void 0 ? "associated" : "non-associated";
944
+ const creditAtEnhancedRate = enhancedRateBasis === "associated" ? Math.round(IEG_2024.ENHANCED_RATE * Math.min(limit, Math.max(0, input.associatedAllowedAmount ?? 0))) : Math.round(IEG_2024.ENHANCED_RATE * incrementalExpenditures);
945
+ const taxableCapital = Math.max(0, input.taxableCapital ?? 0);
946
+ const reductionFactor = computeIegReductionFactor(taxableCapital);
947
+ const grossIeg = Math.round((creditAtBaseRate + creditAtEnhancedRate) * reductionFactor);
948
+ const recapture = Math.max(0, Math.round(input.recapture ?? 0));
949
+ const ieg = Math.max(0, grossIeg - recapture);
819
950
  return {
820
951
  cappedExpenditures,
821
952
  baseAmount: input.baseAmount,
822
953
  incrementalExpenditures,
823
954
  creditAtBaseRate,
824
955
  creditAtEnhancedRate,
825
- ieg: creditAtBaseRate + creditAtEnhancedRate
956
+ enhancedRateBasis,
957
+ taxableCapital,
958
+ reductionFactor,
959
+ grossIeg,
960
+ recapture,
961
+ ieg
826
962
  };
827
963
  }
828
964
  //#endregion
@@ -831,20 +967,27 @@ function computeIeg(input) {
831
967
  * AT1 Schedule 29 — the ASSOCIATED-GROUP layer for the Innovation Employment
832
968
  * Grant.
833
969
  *
834
- * `computeIeg` grants one corporation its IEG given three figures: its own
835
- * eligible Alberta expenditures, its base level of spending, and its allocated
836
- * expenditure limit. Two of those three are **group** figures, and this module
837
- * derives them.
970
+ * `computeIeg` grants one corporation its IEG given its own eligible Alberta
971
+ * expenditures, its base level of spending, its allocated expenditure limit, and
972
+ * the group's taxable capital. The base level of spending is a **group** figure,
973
+ * and this module derives it (along with the group's total taxable capital, for
974
+ * the line-128 reduction factor `computeIeg` applies).
838
975
  *
839
976
  * ── Why a group layer is not optional ───────────────────────────────────────
840
977
  *
841
- * A single corporation with $10M of taxable capital sees no grind at all and gets
842
- * the whole $4,000,000 limit. The same corporation in a group whose members total
843
- * $20M sees the limit ground to $3,000,000. Computing a member in isolation
844
- * therefore **overstates the limit**, and a group that also has prior-year
845
- * spending elsewhere gets an **understated base**, which overstates the 20%
846
- * increment. Both errors run in the taxpayer's favour, which is the direction that
847
- * fails an audit.
978
+ * A group that has prior-year spending elsewhere gets an **understated base**
979
+ * when a member is computed alone, which overstates the 12% increment. And the
980
+ * taxable-capital reduction factor (line 128, see `schedule29-ieg.ts`) is driven
981
+ * by the WHOLE group's taxable capital, not one member's — a member with $10M of
982
+ * its own taxable capital sees no grind in isolation, but the group's combined
983
+ * capital may put it well into the $10M–$50M band. Both errors run in the
984
+ * taxpayer's favour, which is the direction that fails an audit.
985
+ *
986
+ * The $4,000,000 expenditure limit itself is NOT reduced here — see
987
+ * `schedule29-ieg.ts` for why the taxable-capital grind lives at line 128, not
988
+ * the limit. `groupExpenditureLimit` below is the flat $4M shared pool, prorated
989
+ * for a short or long taxation year by the caller if needed (day-of-year
990
+ * proration is not modelled).
848
991
  *
849
992
  * ── Which year's figures ────────────────────────────────────────────────────
850
993
  *
@@ -897,7 +1040,7 @@ function computeIegGroupFigures(members, priorYears = IEG_2024.PRIOR_YEARS) {
897
1040
  const totalPriorYearExpenditures = detail.reduce((s, m) => s + m.priorYearTotal, 0);
898
1041
  return {
899
1042
  groupTaxableCapital,
900
- groupExpenditureLimit: computeIegExpenditureLimit(groupTaxableCapital),
1043
+ groupExpenditureLimit: IEG_2024.MAX_EXPENDITURE,
901
1044
  totalPriorYearExpenditures,
902
1045
  groupBaseAmount: priorYears > 0 ? Math.round(totalPriorYearExpenditures / priorYears) : 0,
903
1046
  members: detail,
@@ -952,6 +1095,70 @@ function allocateIegEvenly(groupExpenditureLimit, names) {
952
1095
  allocated: i === 0 ? each + remainder : each
953
1096
  })));
954
1097
  }
1098
+ function computeAgreementMember(m) {
1099
+ const allocatedExpenditureLimit = nn$23(m.allocatedExpenditureLimit);
1100
+ const currentYearExpenditures = nn$23(m.currentYearExpenditures);
1101
+ const priorYear1 = nn$23(m.priorYear1);
1102
+ const priorYear2 = nn$23(m.priorYear2);
1103
+ const base = Math.round((priorYear1 + priorYear2) / 2);
1104
+ const individualMaximumAllowedAmount = Math.max(0, currentYearExpenditures - base);
1105
+ const days = Math.max(0, Math.min(m.daysInTaxYear ?? 365, 366));
1106
+ const dayProratedLimit = Math.round(4e6 * (days / 365));
1107
+ const dayProratedComponent = Math.max(0, Math.min(dayProratedLimit, currentYearExpenditures) - base);
1108
+ const allocatedAllowedAmount = Math.min(allocatedExpenditureLimit, individualMaximumAllowedAmount, dayProratedComponent);
1109
+ return {
1110
+ name: m.name,
1111
+ ...m.federalBusinessNumber !== void 0 ? { federalBusinessNumber: m.federalBusinessNumber } : {},
1112
+ ...m.albertaCan !== void 0 ? { albertaCan: m.albertaCan } : {},
1113
+ ...m.currentTaxationYearEnd !== void 0 ? { currentTaxationYearEnd: m.currentTaxationYearEnd } : {},
1114
+ allocatedExpenditureLimit,
1115
+ currentYearExpenditures,
1116
+ priorYear1,
1117
+ priorYear2,
1118
+ taxableCapitalPriorYear: nn$23(m.taxableCapitalPriorYear),
1119
+ individualMaximumAllowedAmount,
1120
+ allocatedAllowedAmount
1121
+ };
1122
+ }
1123
+ /**
1124
+ * The formal Agreement Among Associated Corporations. The FIRST entry in
1125
+ * `input.members` must be the claiming corporation — its own line 268 becomes
1126
+ * line 325, which is what actually reaches `computeIeg`.
1127
+ */
1128
+ function computeIegAgreement(input) {
1129
+ const issues = [];
1130
+ if (input.members.length === 0) issues.push("Alberta Schedule 29 Agreement: no members were supplied. The claiming corporation must appear as the first row even in a two-corporation group.");
1131
+ const days = Math.max(0, Math.min(input.daysInLongestYear, 366));
1132
+ const maximumExpenditureLimit = Math.round(4e6 * (days / 365));
1133
+ const members = input.members.map(computeAgreementMember);
1134
+ const sum = (get) => members.reduce((s, m) => s + get(m), 0);
1135
+ const totalAllocatedLimit = sum((m) => m.allocatedExpenditureLimit);
1136
+ const totalCurrentYearExpenditures = sum((m) => m.currentYearExpenditures);
1137
+ const totalPriorYear1 = sum((m) => m.priorYear1);
1138
+ const totalPriorYear2 = sum((m) => m.priorYear2);
1139
+ const totalTaxableCapitalPriorYear = sum((m) => m.taxableCapitalPriorYear);
1140
+ const totalAllocatedAllowedAmount = sum((m) => m.allocatedAllowedAmount);
1141
+ const groupAllowedAmount = Math.round(totalCurrentYearExpenditures - (totalPriorYear1 + totalPriorYear2) / 2);
1142
+ if (totalAllocatedLimit > maximumExpenditureLimit) issues.push(`Alberta Schedule 29 Agreement: the group allocated ${totalAllocatedLimit} of a maximum expenditure limit of ${maximumExpenditureLimit} (line 270 exceeds line 208). The group must agree a valid split.`);
1143
+ if (totalAllocatedAllowedAmount > groupAllowedAmount) issues.push(`Alberta Schedule 29 Agreement: the group's allocated allowed amounts total ${totalAllocatedAllowedAmount}, exceeding the group Allowed Amount of ${groupAllowedAmount} (line 320 exceeds line 310). The group must agree a valid split.`);
1144
+ return {
1145
+ longestYearCan: input.longestYearCan,
1146
+ longestYearBegin: input.longestYearBegin,
1147
+ longestYearEnd: input.longestYearEnd,
1148
+ daysInLongestYear: days,
1149
+ maximumExpenditureLimit,
1150
+ members,
1151
+ totalAllocatedLimit,
1152
+ totalCurrentYearExpenditures,
1153
+ totalPriorYear1,
1154
+ totalPriorYear2,
1155
+ totalTaxableCapitalPriorYear,
1156
+ groupAllowedAmount,
1157
+ totalAllocatedAllowedAmount,
1158
+ claimantAllocatedAllowedAmount: members[0]?.allocatedAllowedAmount ?? 0,
1159
+ issues
1160
+ };
1161
+ }
955
1162
  //#endregion
956
1163
  //#region src/t2/at1/engine/alberta-return.ts
957
1164
  /**
@@ -982,6 +1189,7 @@ function computeAlbertaReturn(input) {
982
1189
  }, rates);
983
1190
  const issues = [];
984
1191
  let iegGroup;
1192
+ let iegAgreement;
985
1193
  let ieg;
986
1194
  if (input.ieg) if (input.ieg.group.length === 0) issues.push("AT1 Schedule 29: no associated-group members were supplied, so no grant was claimed. Pass the claimant itself even when it has no associated corporations — an empty group would otherwise imply no taxable-capital grind and a nil base, producing the maximum possible grant on absent data.");
987
1195
  else {
@@ -992,10 +1200,17 @@ function computeAlbertaReturn(input) {
992
1200
  allocated: input.ieg.allocatedLimit ?? iegGroup.groupExpenditureLimit
993
1201
  }]);
994
1202
  issues.push(...allocation.issues);
1203
+ if (input.ieg.agreement) {
1204
+ iegAgreement = computeIegAgreement(input.ieg.agreement);
1205
+ issues.push(...iegAgreement.issues);
1206
+ }
995
1207
  ieg = computeIeg({
996
1208
  eligibleExpenditures: input.ieg.eligibleExpenditures,
997
1209
  baseAmount: iegGroup.groupBaseAmount,
998
- expenditureLimit: allocation.allocations[0]?.allocated ?? 0
1210
+ expenditureLimit: allocation.allocations[0]?.allocated ?? 0,
1211
+ taxableCapital: iegGroup.groupTaxableCapital,
1212
+ ...input.ieg.recapture !== void 0 ? { recapture: input.ieg.recapture } : {},
1213
+ ...iegAgreement ? { associatedAllowedAmount: iegAgreement.claimantAllocatedAllowedAmount } : {}
999
1214
  });
1000
1215
  }
1001
1216
  const schedulePayloads = [];
@@ -1010,13 +1225,14 @@ function computeAlbertaReturn(input) {
1010
1225
  if (sched?.dispositions) schedulePayloads.push(schedule18Values(sched.dispositions));
1011
1226
  if (sched?.donations) schedulePayloads.push(schedule20Values(sched.donations));
1012
1227
  if (sched?.losses) schedulePayloads.push(schedule21Values(sched.losses));
1013
- if (ieg) schedulePayloads.push(schedule29Values(ieg));
1228
+ if (ieg) schedulePayloads.push(schedule29Values(ieg, iegAgreement));
1014
1229
  return {
1015
1230
  allocationFactor,
1016
1231
  albertaTax,
1017
1232
  albertaTaxPayable: albertaTax.albertaTaxPayable,
1018
1233
  schedulePayloads,
1019
1234
  ...iegGroup ? { iegGroup } : {},
1235
+ ...iegAgreement ? { iegAgreement } : {},
1020
1236
  ...ieg ? { ieg } : {},
1021
1237
  innovationEmploymentGrant: ieg?.ieg ?? 0,
1022
1238
  issues
@@ -6173,4 +6389,4 @@ function computeMpDeduction(input, rates = MP_RATES_2024) {
6173
6389
  };
6174
6390
  }
6175
6391
  //#endregion
6176
- export { computeProvincialAllocation as $, at1TaxPayableDeductions as $n, CEC_DEDUCTION_RATE as $t, runConformance as A, reconcileAlbertaNetIncome as An, AB_GENERAL_RATE_BANDS as Ar, computeCcpcActiveBusinessTax as At, computeGrip as B, formatRsiText as Bn, AT1_DONATION_GAIN_RATE as Bt, computeQuebecTax as C, albertaCcaScheduleAdjustments as Cn, schedule1Values as Cr, blendProvinceRateTable as Ct, T2_LINE_META as D, albertaReserveDifference as Dn, schedule2Values as Dr, dividendsDeductibleS112 as Dt, resolveQuebecTaxRates as E, albertaRecaptureDifference as En, schedule29Values as Er, computeTaxableIncome as Et, normalizeSchedule88 as F, RSI_NEGATIVE_PREFIX as Fn, earliestRateYear as Fr, CORP_TAX_RATE_BOOK as Ft, ITC_RECAPTURE_PERIOD_YEARS as G, AT1_CRITICAL_MANDATORY_FIELDS as Gn, SECTION_34_2_GROSS_UP as Gt, LARGE_CORPORATION_THRESHOLD as H, renderRsiHeader as Hn, computeDonationMaximum as Ht, computeSchedule55 as I, RSI_WORD_GAP as In, extendRateBook as Ir, resolveCorpTaxRates as It, allocateEvenly as J, At1TaxPayableMismatchError as Jn, AT1_RESERVE_LINES as Jt, computeItcRecapture as K, At1CriticalFieldMissingError as Kn, computeAlbertaSchedule18 as Kt, LRIP_INVESTMENT_CORPORATION_MULTIPLE as L, RsiLineItemError as Ln, hasExactRateYear as Lr, T2_CERTIFICATION_FIXTURES as Lt, computeFederalT2 as M, computeLossCarryback as Mn, AB_TAX_2024 as Mr, computeBusinessLimit as Mt, computeSchedule101 as N, RSI_COLUMN_GAP as Nn, AB_TAX_RATE_BOOK as Nr, computeSBD as Nt, foldT2Lines as O, albertaTerminalLossDifference as On, computeAlbertaTax as Or, netCapitalLossApplied as Ot, SCHEDULE_88_MAX_URLS as P, RSI_DELIMITER as Pn, resolveAlbertaTaxRates as Pr, CORP_TAX_2024 as Pt, computeSchedule6 as Q, assertCriticalFields as Qn, computeAlbertaSchedule16 as Qt, LRIP_INVESTMENT_INCOME_FACTOR as R, formatRsiAmount as Rn, latestRateYear as Rr, computeLossSchedule as Rt, computeQuebecAllocationFactor as S, albertaCcaDifference as Sn, schedule18Values as Sr, resolveProvinceRates as St, QC_TAX_RATE_BOOK as T, albertaDispositionAdjustments as Tn, schedule21Values as Tr, charitableDonationsDeduction as Tt, computeTaxableCapital as U, renderRsiLineItem as Un, computeSchedule20 as Ut, computeSchedule43 as V, renderAt1Rsi as Vn, AT1_DONATION_INCOME_RATE as Vt, computeSchedule31 as W, renderAt1NetFile as Wn, AT1_DISPOSITION_CATEGORIES as Wt, computeSchedule21 as X, assertAt1MandatoryComplete as Xn, computeAlbertaSchedule17 as Xt, computeBusinessLimitAllocation as Y, albertaBalanceUnpaid as Yn, AT1_RESERVE_TOTAL_LINES as Yt, computeSchedule13 as Z, assertAt1TaxPayableReconciles as Zn, assistanceFrom as Zt, renderT2DraftReturn as _, CCA_RATE_BOOK as _n, schedule12LossDeductions as _r, EIFEL_EFFECTIVE_FROM as _t, PART_VI_1_DEDUCTION_BANDS as a, computeCcaClass as an, allocateIegExpenditureLimit as ar, computeSchedule2 as at, co17Engine as b, albertaAbilDifference as bn, schedule16Values as br, PROVINCE_RATE_BOOK as bt, EIFEL_FIRST_YEAR_START as c, CLASS_14_1_MINIMUM_DEDUCTION as cn, computeIeg as cr, assertSchedule1Fileable as ct, EIFEL_TRANSITIONAL_RATIO as d, MIN_LEASEHOLD_PERIODS as dn, SINGLE_JURISDICTION_ALBERTA_FACTOR as dr, deferredIncomeTaxProvisionAddBack as dt, CEC_INCLUSION_RATE as en, at1YesNo as er, computeSchedule5 as et, computeEifelLimitation as f, computeClass13 as fn, computeAllocationFactor as fr, findSchedule1LineDefects as ft, computeT2Settlement as g, CCA_DECLINING_BALANCE_RATES_2024 as gn, schedule10Values as gr, terminalLossDeduction as gt, computeAdjustedTaxableIncome as h, leaseholdPeriods as hn, at1LineItemId as hr, recaptureAddBack as ht, computeMpDeduction as i, UnsupportedCcaClassError as in, allocateIegEvenly as ir, computePart4Rdtoh as it, runConformanceSuite as j, LossCarrybackError as jn, computeDayWeightedGeneralTax as jr, computePartITax as jt, formatConformanceReport as k, computeSchedule12 as kn, computeAlbertaSbd as kr, nonCapitalLossApplied as kt, EIFEL_STANDARD_RATIO as l, CLASS_14_1_TRANSITIONAL_RATE as ln, computeIegBaseAmount as lr, ccaDeduction as lt, FOREIGN_TAX_CREDIT_GROSS_UP as m, computeClass141AdditionalAllowance as mn, AT1_SCHEDULES_WITH_BUILDERS as mr, mealsAndEntertainmentAddBack as mt, MP_GROSS_REVENUE_THRESHOLD as n, computeAlbertaSchedule14 as nn, at1Engine as nr, PART_IV_RATE as nt, computePartVI1Deduction as o, computeCcaSchedule as on, computeIegGroupFigures as or, Schedule1NotFileableError as ot, ratioOfPermissibleExpenses as p, computeClass14 as pn, AT1_SCHEDULES_WITHOUT_BUILDERS as pr, incomeTaxProvisionAddBack as pt, computeZetm as q, At1MandatoryFieldMissingError as qn, AT1_RESERVE_KINDS as qt, MP_RATES_2024 as r, computeAlbertaSchedule13 as rn, computeAlbertaReturn as rr, REFUNDABLE_PART_I_RATE as rt, partVI1DeductionMultiple as s, computeSchedule8 as sn, IEG_2024 as sr, amortizationAddBack as st, MP_EXCLUDED_ACTIVITIES as t, cecScheduleAppliesToTaxYear as tn, xmlEscape as tr, computeSchedule4Losses as tt, EIFEL_STANDARD_RATIO_FROM as u, MAX_LEASEHOLD_PERIODS as un, computeIegExpenditureLimit as ur, computeSchedule1 as ut, t2Engine as v, isDecliningBalanceClass as vn, schedule12Values as vr, assessEifel as vt, QC_TAX_2024 as w, albertaCurrentYearLoss as wn, schedule20Values as wr, dayWeightedRate as wt, computeQuebecReturn as x, albertaCapitalGainDifference as xn, schedule17Values as xr, isSchedule5Province as xt, renderCo17DraftReturn as y, resolveCcaRates as yn, schedule13Values as yr, PROVINCE_RATES_2024 as yt, computeSchedule54 as z, formatRsiDate as zn, resolveRates as zr, computeLossContinuity as zt };
6392
+ export { computeProvincialAllocation as $, at1TaxPayableDeductions as $n, CEC_DEDUCTION_RATE as $t, runConformance as A, reconcileAlbertaNetIncome as An, computeAlbertaSbd as Ar, computeCcpcActiveBusinessTax as At, computeGrip as B, formatRsiText as Bn, resolveRates as Br, AT1_DONATION_GAIN_RATE as Bt, computeQuebecTax as C, albertaCcaScheduleAdjustments as Cn, schedule18Values as Cr, blendProvinceRateTable as Ct, T2_LINE_META as D, albertaReserveDifference as Dn, schedule29Values as Dr, dividendsDeductibleS112 as Dt, resolveQuebecTaxRates as E, albertaRecaptureDifference as En, schedule21Values as Er, computeTaxableIncome as Et, normalizeSchedule88 as F, RSI_NEGATIVE_PREFIX as Fn, resolveAlbertaTaxRates as Fr, CORP_TAX_RATE_BOOK as Ft, ITC_RECAPTURE_PERIOD_YEARS as G, AT1_CRITICAL_MANDATORY_FIELDS as Gn, SECTION_34_2_GROSS_UP as Gt, LARGE_CORPORATION_THRESHOLD as H, renderRsiHeader as Hn, computeDonationMaximum as Ht, computeSchedule55 as I, RSI_WORD_GAP as In, earliestRateYear as Ir, resolveCorpTaxRates as It, allocateEvenly as J, At1TaxPayableMismatchError as Jn, AT1_RESERVE_LINES as Jt, computeItcRecapture as K, At1CriticalFieldMissingError as Kn, computeAlbertaSchedule18 as Kt, LRIP_INVESTMENT_CORPORATION_MULTIPLE as L, RsiLineItemError as Ln, extendRateBook as Lr, T2_CERTIFICATION_FIXTURES as Lt, computeFederalT2 as M, computeLossCarryback as Mn, computeDayWeightedGeneralTax as Mr, computeBusinessLimit as Mt, computeSchedule101 as N, RSI_COLUMN_GAP as Nn, AB_TAX_2024 as Nr, computeSBD as Nt, foldT2Lines as O, albertaTerminalLossDifference as On, schedule2Values as Or, netCapitalLossApplied as Ot, SCHEDULE_88_MAX_URLS as P, RSI_DELIMITER as Pn, AB_TAX_RATE_BOOK as Pr, CORP_TAX_2024 as Pt, computeSchedule6 as Q, assertCriticalFields as Qn, computeAlbertaSchedule16 as Qt, LRIP_INVESTMENT_INCOME_FACTOR as R, formatRsiAmount as Rn, hasExactRateYear as Rr, computeLossSchedule as Rt, computeQuebecAllocationFactor as S, albertaCcaDifference as Sn, schedule17Values as Sr, resolveProvinceRates as St, QC_TAX_RATE_BOOK as T, albertaDispositionAdjustments as Tn, schedule20Values as Tr, charitableDonationsDeduction as Tt, computeTaxableCapital as U, renderRsiLineItem as Un, computeSchedule20 as Ut, computeSchedule43 as V, renderAt1Rsi as Vn, AT1_DONATION_INCOME_RATE as Vt, computeSchedule31 as W, renderAt1NetFile as Wn, AT1_DISPOSITION_CATEGORIES as Wt, computeSchedule21 as X, assertAt1MandatoryComplete as Xn, computeAlbertaSchedule17 as Xt, computeBusinessLimitAllocation as Y, albertaBalanceUnpaid as Yn, AT1_RESERVE_TOTAL_LINES as Yt, computeSchedule13 as Z, assertAt1TaxPayableReconciles as Zn, assistanceFrom as Zt, renderT2DraftReturn as _, CCA_RATE_BOOK as _n, schedule10Values as _r, EIFEL_EFFECTIVE_FROM as _t, PART_VI_1_DEDUCTION_BANDS as a, computeCcaClass as an, allocateIegExpenditureLimit as ar, computeSchedule2 as at, co17Engine as b, albertaAbilDifference as bn, schedule13Values as br, PROVINCE_RATE_BOOK as bt, EIFEL_FIRST_YEAR_START as c, CLASS_14_1_MINIMUM_DEDUCTION as cn, IEG_2024 as cr, assertSchedule1Fileable as ct, EIFEL_TRANSITIONAL_RATIO as d, MIN_LEASEHOLD_PERIODS as dn, computeIegReductionFactor as dr, deferredIncomeTaxProvisionAddBack as dt, CEC_INCLUSION_RATE as en, at1YesNo as er, computeSchedule5 as et, computeEifelLimitation as f, computeClass13 as fn, SINGLE_JURISDICTION_ALBERTA_FACTOR as fr, findSchedule1LineDefects as ft, computeT2Settlement as g, CCA_DECLINING_BALANCE_RATES_2024 as gn, at1LineItemId as gr, terminalLossDeduction as gt, computeAdjustedTaxableIncome as h, leaseholdPeriods as hn, AT1_SCHEDULES_WITH_BUILDERS as hr, recaptureAddBack as ht, computeMpDeduction as i, UnsupportedCcaClassError as in, allocateIegEvenly as ir, computePart4Rdtoh as it, runConformanceSuite as j, LossCarrybackError as jn, AB_GENERAL_RATE_BANDS as jr, computePartITax as jt, formatConformanceReport as k, computeSchedule12 as kn, computeAlbertaTax as kr, nonCapitalLossApplied as kt, EIFEL_STANDARD_RATIO as l, CLASS_14_1_TRANSITIONAL_RATE as ln, computeIeg as lr, ccaDeduction as lt, FOREIGN_TAX_CREDIT_GROSS_UP as m, computeClass141AdditionalAllowance as mn, AT1_SCHEDULES_WITHOUT_BUILDERS as mr, mealsAndEntertainmentAddBack as mt, MP_GROSS_REVENUE_THRESHOLD as n, computeAlbertaSchedule14 as nn, at1Engine as nr, PART_IV_RATE as nt, computePartVI1Deduction as o, computeCcaSchedule as on, computeIegAgreement as or, Schedule1NotFileableError as ot, ratioOfPermissibleExpenses as p, computeClass14 as pn, computeAllocationFactor as pr, incomeTaxProvisionAddBack as pt, computeZetm as q, At1MandatoryFieldMissingError as qn, AT1_RESERVE_KINDS as qt, MP_RATES_2024 as r, computeAlbertaSchedule13 as rn, computeAlbertaReturn as rr, REFUNDABLE_PART_I_RATE as rt, partVI1DeductionMultiple as s, computeSchedule8 as sn, computeIegGroupFigures as sr, amortizationAddBack as st, MP_EXCLUDED_ACTIVITIES as t, cecScheduleAppliesToTaxYear as tn, xmlEscape as tr, computeSchedule4Losses as tt, EIFEL_STANDARD_RATIO_FROM as u, MAX_LEASEHOLD_PERIODS as un, computeIegBaseAmount as ur, computeSchedule1 as ut, t2Engine as v, isDecliningBalanceClass as vn, schedule12LossDeductions as vr, assessEifel as vt, QC_TAX_2024 as w, albertaCurrentYearLoss as wn, schedule1Values as wr, dayWeightedRate as wt, computeQuebecReturn as x, albertaCapitalGainDifference as xn, schedule16Values as xr, isSchedule5Province as xt, renderCo17DraftReturn as y, resolveCcaRates as yn, schedule12Values as yr, PROVINCE_RATES_2024 as yt, computeSchedule54 as z, formatRsiDate as zn, latestRateYear as zr, computeLossContinuity as zt };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@classytic/ca-tax",
3
- "version": "0.0.1",
3
+ "version": "0.0.2",
4
4
  "description": "Canadian corporate tax engine for @classytic/tax-core — federal T2, Alberta AT1 and Québec CO-17 with form definitions traced to the published forms, plus GST/HST/PST/QST with dated provincial regimes.",
5
5
  "type": "module",
6
6
  "license": "MIT",