@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/CHANGELOG.md +62 -0
- package/dist/forms.mjs +313 -18
- package/dist/index.d.mts +3 -3
- package/dist/index.mjs +2 -2
- package/dist/index3.d.mts +380 -94
- package/dist/index4.d.mts +2 -2
- package/dist/t2/index.d.mts +2 -2
- package/dist/t2/index.mjs +2 -2
- package/dist/t2.mjs +261 -45
- package/package.json +1 -1
package/dist/t2.mjs
CHANGED
|
@@ -431,15 +431,93 @@ function schedule18Values(result) {
|
|
|
431
431
|
values
|
|
432
432
|
};
|
|
433
433
|
}
|
|
434
|
-
|
|
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("
|
|
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%
|
|
773
|
-
*
|
|
774
|
-
*
|
|
775
|
-
*
|
|
776
|
-
*
|
|
777
|
-
*
|
|
778
|
-
*
|
|
779
|
-
*
|
|
780
|
-
*
|
|
781
|
-
*
|
|
782
|
-
*
|
|
783
|
-
*
|
|
784
|
-
*
|
|
785
|
-
*
|
|
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: .
|
|
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
|
-
/**
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
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
|
|
817
|
-
const
|
|
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
|
-
|
|
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
|
|
835
|
-
*
|
|
836
|
-
*
|
|
837
|
-
* derives
|
|
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
|
|
842
|
-
*
|
|
843
|
-
*
|
|
844
|
-
*
|
|
845
|
-
*
|
|
846
|
-
*
|
|
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:
|
|
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,
|
|
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.
|
|
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",
|