taxtank-core 0.28.110 → 0.28.112
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/bundles/taxtank-core.umd.js +2026 -2025
- package/bundles/taxtank-core.umd.js.map +1 -1
- package/esm2015/lib/collections/transaction/transaction.collection.js +6 -4
- package/esm2015/lib/forms/transaction/work-income.form.js +14 -18
- package/esm2015/lib/models/transaction/transaction.js +17 -7
- package/esm2015/lib/services/transaction/transaction-calculation.service.js +1 -10
- package/fesm2015/taxtank-core.js +1584 -1586
- package/fesm2015/taxtank-core.js.map +1 -1
- package/lib/collections/transaction/transaction.collection.d.ts +1 -3
- package/lib/forms/transaction/work-income.form.d.ts +5 -9
- package/lib/models/transaction/transaction.d.ts +5 -3
- package/lib/services/transaction/transaction-calculation.service.d.ts +0 -5
- package/package.json +1 -1
package/fesm2015/taxtank-core.js
CHANGED
|
@@ -3531,1945 +3531,1956 @@ __decorate([
|
|
|
3531
3531
|
Type(() => Transaction)
|
|
3532
3532
|
], TransactionAllocation.prototype, "transaction", void 0);
|
|
3533
3533
|
|
|
3534
|
-
class
|
|
3535
|
-
|
|
3536
|
-
|
|
3537
|
-
class DepreciationCapitalProject$1 extends AbstractModel {
|
|
3538
|
-
}
|
|
3539
|
-
|
|
3540
|
-
class DepreciationCapitalProject extends DepreciationCapitalProject$1 {
|
|
3541
|
-
}
|
|
3542
|
-
__decorate([
|
|
3543
|
-
Type(() => Date)
|
|
3544
|
-
], DepreciationCapitalProject.prototype, "effectiveDate", void 0);
|
|
3545
|
-
|
|
3546
|
-
class DepreciationForecast$1 extends AbstractModel {
|
|
3547
|
-
}
|
|
3548
|
-
|
|
3549
|
-
class DepreciationForecast extends DepreciationForecast$1 {
|
|
3550
|
-
get dailyClaimAmount() {
|
|
3551
|
-
return this.claimAmount / this.daysApplied;
|
|
3552
|
-
}
|
|
3553
|
-
get daysApplied() {
|
|
3554
|
-
return moment$1(this.toDate).diff(moment$1(this.fromDate), 'days');
|
|
3555
|
-
}
|
|
3556
|
-
getDaysByMonth(month) {
|
|
3557
|
-
// @TODO find a better place
|
|
3558
|
-
const year = this.financialYear - (month > 5 ? 1 : 0);
|
|
3559
|
-
// forecast date intersect by month
|
|
3560
|
-
const range = new DateRange(this.fromDate, this.toDate).intersect(new DateRange(new Date(year, month, 1), new Date(year, month + 1, 0)));
|
|
3561
|
-
return range ? range.duration('days') + 1 : 0;
|
|
3562
|
-
}
|
|
3563
|
-
get claimOpenBalance() {
|
|
3564
|
-
return this.openBalance * this.claimRate;
|
|
3565
|
-
}
|
|
3566
|
-
get claimCloseBalance() {
|
|
3567
|
-
return this.closeBalance * this.claimRate;
|
|
3568
|
-
}
|
|
3569
|
-
get claimAmount() {
|
|
3570
|
-
return this.amount * this.claimRate;
|
|
3534
|
+
class PropertySaleCollection extends Collection {
|
|
3535
|
+
get grossCGT() {
|
|
3536
|
+
return this.create(this.items.filter((propertySale) => propertySale.grossCGT > 0)).sumBy('grossCGT');
|
|
3571
3537
|
}
|
|
3572
|
-
|
|
3573
|
-
|
|
3538
|
+
/**
|
|
3539
|
+
* Property sales are CGT applicable unless it has "Principle place of residence" exemption type
|
|
3540
|
+
*/
|
|
3541
|
+
getCGTApplicable() {
|
|
3542
|
+
return this.create(this.items.filter((propertySale) => propertySale.isCGTApplicable()));
|
|
3574
3543
|
}
|
|
3575
|
-
|
|
3576
|
-
return this.
|
|
3544
|
+
getByPropertyShareIds(ids) {
|
|
3545
|
+
return this.filterBy('share.id', ids);
|
|
3577
3546
|
}
|
|
3578
3547
|
}
|
|
3579
3548
|
|
|
3580
|
-
|
|
3581
|
-
|
|
3582
|
-
|
|
3583
|
-
|
|
3584
|
-
|
|
3585
|
-
|
|
3586
|
-
|
|
3587
|
-
})(
|
|
3588
|
-
|
|
3589
|
-
var TransactionCategoryEnum;
|
|
3590
|
-
(function (TransactionCategoryEnum) {
|
|
3591
|
-
TransactionCategoryEnum[TransactionCategoryEnum["PROPERTY"] = 0] = "PROPERTY";
|
|
3592
|
-
TransactionCategoryEnum[TransactionCategoryEnum["WORK"] = 1] = "WORK";
|
|
3593
|
-
TransactionCategoryEnum[TransactionCategoryEnum["SOLE"] = 2] = "SOLE";
|
|
3594
|
-
TransactionCategoryEnum[TransactionCategoryEnum["PERSONAL"] = 3] = "PERSONAL";
|
|
3595
|
-
})(TransactionCategoryEnum || (TransactionCategoryEnum = {}));
|
|
3549
|
+
var TaxExemptionMetadataEnum;
|
|
3550
|
+
(function (TaxExemptionMetadataEnum) {
|
|
3551
|
+
// principle place of residence
|
|
3552
|
+
TaxExemptionMetadataEnum[TaxExemptionMetadataEnum["PPR_DAYS"] = 1] = "PPR_DAYS";
|
|
3553
|
+
// market value once it was moved, decimal
|
|
3554
|
+
TaxExemptionMetadataEnum[TaxExemptionMetadataEnum["MARKET_VALUE"] = 2] = "MARKET_VALUE";
|
|
3555
|
+
TaxExemptionMetadataEnum[TaxExemptionMetadataEnum["CLAIM_PERCENT"] = 3] = "CLAIM_PERCENT";
|
|
3556
|
+
})(TaxExemptionMetadataEnum || (TaxExemptionMetadataEnum = {}));
|
|
3596
3557
|
|
|
3597
|
-
|
|
3598
|
-
|
|
3599
|
-
|
|
3600
|
-
|
|
3601
|
-
constructor() {
|
|
3602
|
-
super(...arguments);
|
|
3603
|
-
this.forecasts = [];
|
|
3604
|
-
this.type = DepreciationTypeEnum.PLANT_EQUIPMENT;
|
|
3605
|
-
/**
|
|
3606
|
-
* @TODO remove after ? signs removed from db models
|
|
3607
|
-
*/
|
|
3608
|
-
this.amount = 0;
|
|
3609
|
-
}
|
|
3610
|
-
// Type checking
|
|
3611
|
-
isCapital() {
|
|
3612
|
-
return this.type === DepreciationTypeEnum.CAPITAL_WORKS;
|
|
3613
|
-
}
|
|
3614
|
-
isBorrowingExpense() {
|
|
3615
|
-
return this.type === DepreciationTypeEnum.BORROWING_EXPENSES;
|
|
3616
|
-
}
|
|
3617
|
-
isAsset() {
|
|
3618
|
-
return this.type === DepreciationTypeEnum.PLANT_EQUIPMENT;
|
|
3619
|
-
}
|
|
3620
|
-
// Calculation checking
|
|
3621
|
-
isSBPCalculation() {
|
|
3622
|
-
return this.calculation === DepreciationCalculationEnum.SBP;
|
|
3623
|
-
}
|
|
3624
|
-
isPrimeCost() {
|
|
3625
|
-
return this.calculation === DepreciationCalculationEnum.PRIME_COST;
|
|
3558
|
+
class PropertySaleTaxExemptionMetadataCollection extends Collection {
|
|
3559
|
+
getPPRDays() {
|
|
3560
|
+
var _a, _b;
|
|
3561
|
+
return (_b = (_a = this.getByMetadataId(TaxExemptionMetadataEnum.PPR_DAYS)) === null || _a === void 0 ? void 0 : _a.value) !== null && _b !== void 0 ? _b : 0;
|
|
3626
3562
|
}
|
|
3627
|
-
|
|
3628
|
-
|
|
3563
|
+
getMarketValue() {
|
|
3564
|
+
var _a, _b;
|
|
3565
|
+
return (_b = (_a = this.getByMetadataId(TaxExemptionMetadataEnum.MARKET_VALUE)) === null || _a === void 0 ? void 0 : _a.value) !== null && _b !== void 0 ? _b : 0;
|
|
3629
3566
|
}
|
|
3630
|
-
|
|
3631
|
-
|
|
3632
|
-
return
|
|
3567
|
+
getClaimPercent() {
|
|
3568
|
+
var _a, _b;
|
|
3569
|
+
return (_b = (_a = this.getByMetadataId(TaxExemptionMetadataEnum.CLAIM_PERCENT)) === null || _a === void 0 ? void 0 : _a.value) !== null && _b !== void 0 ? _b : 100;
|
|
3633
3570
|
}
|
|
3634
|
-
|
|
3635
|
-
return this.
|
|
3636
|
-
&& !this.isSBPCalculation()
|
|
3637
|
-
&& this.isDiminishing()
|
|
3638
|
-
&& this.currentYearForecast.closeBalance > Depreciation.WRITTEN_OFF_THRESHOLD
|
|
3639
|
-
&& this.currentYearForecast.closeBalance <= Depreciation.LOW_VALUE_POOL_THRESHOLD;
|
|
3571
|
+
getByMetadataId(id) {
|
|
3572
|
+
return this.items.find((metadata) => metadata.metadata.id === id);
|
|
3640
3573
|
}
|
|
3641
|
-
|
|
3642
|
-
|
|
3574
|
+
}
|
|
3575
|
+
|
|
3576
|
+
class PropertyCollection extends Collection {
|
|
3577
|
+
/**
|
|
3578
|
+
* Get new property collection filtered by category id
|
|
3579
|
+
* @param id id of category for filter
|
|
3580
|
+
*/
|
|
3581
|
+
getByCategoryId(id) {
|
|
3582
|
+
return new PropertyCollection(this.items.filter((property) => property.category.id === id));
|
|
3643
3583
|
}
|
|
3644
|
-
|
|
3645
|
-
|
|
3584
|
+
/**
|
|
3585
|
+
* Get new property collection filtered by active status
|
|
3586
|
+
*/
|
|
3587
|
+
getActiveProperties() {
|
|
3588
|
+
return new PropertyCollection(this.items.filter((property) => property.isActive));
|
|
3646
3589
|
}
|
|
3647
|
-
|
|
3648
|
-
|
|
3649
|
-
if (!this.writeOffManualDate && !this.writeOffDate) {
|
|
3650
|
-
return null;
|
|
3651
|
-
}
|
|
3652
|
-
return (_a = new FinancialYear(this.writeOffManualDate || this.writeOffDate)) === null || _a === void 0 ? void 0 : _a.year;
|
|
3590
|
+
getCreatedProperties() {
|
|
3591
|
+
return new PropertyCollection(this.items.filter((property) => property.isOwn()));
|
|
3653
3592
|
}
|
|
3654
3593
|
/**
|
|
3655
|
-
*
|
|
3594
|
+
* Get new property collection filtered by shared
|
|
3656
3595
|
*/
|
|
3657
|
-
|
|
3658
|
-
|
|
3659
|
-
return ((_a = this.chartAccounts.heading) === null || _a === void 0 ? void 0 : _a.id) === ChartAccountsHeadingVehicleListEnum.DEPRECIATION_VEHICLES;
|
|
3596
|
+
getSharedProperties() {
|
|
3597
|
+
return new PropertyCollection(this.items.filter((property) => !property.isOwn()));
|
|
3660
3598
|
}
|
|
3661
3599
|
/**
|
|
3662
|
-
*
|
|
3600
|
+
* Properties that are taxed and will be included in reports (Tax summary, My tax report, e.t.c.)
|
|
3663
3601
|
*/
|
|
3664
|
-
|
|
3665
|
-
return this.
|
|
3602
|
+
getTaxInclusive() {
|
|
3603
|
+
return this.create(this.items.filter((property) => property.category.isTaxInclusive));
|
|
3604
|
+
}
|
|
3605
|
+
getUnsold() {
|
|
3606
|
+
return this.create(this.items.filter((property) => !property.isSold()));
|
|
3666
3607
|
}
|
|
3667
3608
|
/**
|
|
3668
|
-
*
|
|
3609
|
+
* Get total purchase price for all properties in the collection
|
|
3669
3610
|
*/
|
|
3670
|
-
get
|
|
3671
|
-
return this.
|
|
3672
|
-
return forecast.financialYear === new FinancialYear().year;
|
|
3673
|
-
}) || plainToClass(DepreciationForecast, {
|
|
3674
|
-
financialYear: new FinancialYear().year,
|
|
3675
|
-
openBalance: 0,
|
|
3676
|
-
closeBalance: 0,
|
|
3677
|
-
amount: 0,
|
|
3678
|
-
claimPercent: 0
|
|
3679
|
-
});
|
|
3611
|
+
get purchasePrice() {
|
|
3612
|
+
return this.sumBy('purchasePrice');
|
|
3680
3613
|
}
|
|
3681
|
-
|
|
3682
|
-
return this.
|
|
3683
|
-
return forecast.financialYear === year;
|
|
3684
|
-
});
|
|
3614
|
+
get growthPercent() {
|
|
3615
|
+
return this.sumBy('growthPercent');
|
|
3685
3616
|
}
|
|
3686
|
-
|
|
3687
|
-
|
|
3688
|
-
return ((_a = this.getForecastByYear(year)) === null || _a === void 0 ? void 0 : _a.claimAmount) || 0;
|
|
3617
|
+
get marketValue() {
|
|
3618
|
+
return this.sumBy('marketValue');
|
|
3689
3619
|
}
|
|
3690
|
-
|
|
3691
|
-
|
|
3692
|
-
|
|
3620
|
+
get firstForecastYear() {
|
|
3621
|
+
return this.items.reduce((min, property) => {
|
|
3622
|
+
const current = property.firstForecastYear;
|
|
3623
|
+
return min > current ? current : min;
|
|
3624
|
+
}, new FinancialYear().year);
|
|
3693
3625
|
}
|
|
3694
|
-
|
|
3695
|
-
return this.
|
|
3626
|
+
get marketValueGrowth() {
|
|
3627
|
+
return (this.marketValue - this.purchasePrice) / this.purchasePrice;
|
|
3696
3628
|
}
|
|
3697
3629
|
/**
|
|
3698
|
-
*
|
|
3630
|
+
* list of properties
|
|
3699
3631
|
*/
|
|
3700
|
-
|
|
3701
|
-
|
|
3702
|
-
return plainToClass(Transaction, Object.assign(params, this, {
|
|
3703
|
-
amount: -((_a = this.currentYearForecast) === null || _a === void 0 ? void 0 : _a.amount) || 0,
|
|
3704
|
-
claimAmount: -((_b = this.currentYearForecast) === null || _b === void 0 ? void 0 : _b.claimAmount) || 0,
|
|
3705
|
-
}));
|
|
3632
|
+
getCGTApplicable() {
|
|
3633
|
+
return this.create(this.items.filter((property) => property.isCGTApplicable()));
|
|
3706
3634
|
}
|
|
3707
|
-
|
|
3708
|
-
|
|
3709
|
-
*/
|
|
3710
|
-
get claimAmount() {
|
|
3711
|
-
var _a;
|
|
3712
|
-
return ((_a = this.currentYearForecast) === null || _a === void 0 ? void 0 : _a.claimAmount) || 0;
|
|
3635
|
+
getOwnerOccupiedProperties() {
|
|
3636
|
+
return new PropertyCollection(this.items.filter((property) => property.category.isOwnerOccupied()));
|
|
3713
3637
|
}
|
|
3714
|
-
get
|
|
3715
|
-
|
|
3716
|
-
|
|
3717
|
-
|
|
3718
|
-
}
|
|
3719
|
-
return this.amount;
|
|
3638
|
+
get earliestContractDate() {
|
|
3639
|
+
return this.items.reduce((min, property) => {
|
|
3640
|
+
return min < property.contractDate ? min : property.contractDate;
|
|
3641
|
+
}, new FinancialYear(new Date()).startDate);
|
|
3720
3642
|
}
|
|
3721
|
-
|
|
3722
|
-
|
|
3723
|
-
|
|
3643
|
+
/**
|
|
3644
|
+
* Get list of unique property categories from collection
|
|
3645
|
+
*/
|
|
3646
|
+
getCategories() {
|
|
3647
|
+
return uniqBy(this.items.map((property) => property.category), 'id');
|
|
3724
3648
|
}
|
|
3725
3649
|
/**
|
|
3726
|
-
*
|
|
3650
|
+
* Get property with the highest growth percent
|
|
3727
3651
|
*/
|
|
3728
|
-
|
|
3729
|
-
return
|
|
3730
|
-
|
|
3731
|
-
}
|
|
3732
|
-
Depreciation.WRITTEN_OFF_THRESHOLD = 300;
|
|
3733
|
-
Depreciation.LOW_VALUE_POOL_THRESHOLD = 1000;
|
|
3734
|
-
__decorate([
|
|
3735
|
-
Type(() => Date)
|
|
3736
|
-
], Depreciation.prototype, "purchaseDate", void 0);
|
|
3737
|
-
__decorate([
|
|
3738
|
-
Type(() => Date)
|
|
3739
|
-
], Depreciation.prototype, "date", void 0);
|
|
3740
|
-
__decorate([
|
|
3741
|
-
Type(() => Date)
|
|
3742
|
-
], Depreciation.prototype, "lowValuePoolDate", void 0);
|
|
3743
|
-
__decorate([
|
|
3744
|
-
Type(() => Date)
|
|
3745
|
-
], Depreciation.prototype, "writeOffManualDate", void 0);
|
|
3746
|
-
__decorate([
|
|
3747
|
-
Type(() => Date)
|
|
3748
|
-
], Depreciation.prototype, "writeOffDate", void 0);
|
|
3749
|
-
__decorate([
|
|
3750
|
-
Type(() => DepreciationCapitalProject)
|
|
3751
|
-
], Depreciation.prototype, "depreciationCapitalProject", void 0);
|
|
3752
|
-
__decorate([
|
|
3753
|
-
Type(() => DepreciationForecast),
|
|
3754
|
-
Transform(({ value, obj }) => {
|
|
3755
|
-
// value = array of DepreciationForecast
|
|
3756
|
-
// obj = plain (whole Depreciation object)
|
|
3757
|
-
// Set isLVP flag for each DepreciationForecast
|
|
3758
|
-
// @TODO refactor
|
|
3759
|
-
value.forEach((forecast) => {
|
|
3760
|
-
forecast.isLVP =
|
|
3761
|
-
forecast.closeBalance < 1000 &&
|
|
3762
|
-
obj.calculation === DepreciationCalculationEnum.DIMINISHING &&
|
|
3763
|
-
obj.type === DepreciationTypeEnum.PLANT_EQUIPMENT &&
|
|
3764
|
-
!(obj.amount > Depreciation.WRITTEN_OFF_THRESHOLD && obj.amount < Depreciation.LOW_VALUE_POOL_THRESHOLD) &&
|
|
3765
|
-
!(obj.writeOffDate && new FinancialYear(new Date(obj.writeOffDate)).year === obj.financialYear);
|
|
3766
|
-
});
|
|
3767
|
-
return value;
|
|
3768
|
-
})
|
|
3769
|
-
], Depreciation.prototype, "forecasts", void 0);
|
|
3770
|
-
__decorate([
|
|
3771
|
-
Type(() => ChartAccounts)
|
|
3772
|
-
], Depreciation.prototype, "chartAccounts", void 0);
|
|
3773
|
-
__decorate([
|
|
3774
|
-
Type(() => BankTransaction)
|
|
3775
|
-
], Depreciation.prototype, "bankTransaction", void 0);
|
|
3776
|
-
__decorate([
|
|
3777
|
-
Exclude()
|
|
3778
|
-
], Depreciation.prototype, "amountWithGst", null);
|
|
3779
|
-
__decorate([
|
|
3780
|
-
Exclude()
|
|
3781
|
-
], Depreciation.prototype, "gstClaimAmount", null);
|
|
3782
|
-
|
|
3783
|
-
// @TODO Alex: refactor: move here allocations methods, netAmount = amount, grossAmount calculation, remove unused methods, etc.
|
|
3784
|
-
class Transaction extends Transaction$1 {
|
|
3785
|
-
constructor() {
|
|
3786
|
-
super(...arguments);
|
|
3787
|
-
// list of child transactions (fees)
|
|
3788
|
-
this.transactions = [];
|
|
3789
|
-
this.metadata = [];
|
|
3790
|
-
this.allocations = [];
|
|
3791
|
-
this.tax = 0;
|
|
3792
|
-
this.operation = TransactionOperationEnum.FIND_AND_MATCH;
|
|
3793
|
-
this.claimPercent = 100;
|
|
3794
|
-
this.amount = 0;
|
|
3795
|
-
}
|
|
3796
|
-
isDebit() {
|
|
3797
|
-
return this.type === TransactionTypeEnum.DEBIT;
|
|
3798
|
-
}
|
|
3799
|
-
isCredit() {
|
|
3800
|
-
return this.type === TransactionTypeEnum.CREDIT;
|
|
3652
|
+
getBestPerformanceGrowthProperty() {
|
|
3653
|
+
return this.items.reduce((max, current) => {
|
|
3654
|
+
return max.growthPercent < current.growthPercent ? current : max;
|
|
3655
|
+
}, this.first);
|
|
3801
3656
|
}
|
|
3802
3657
|
/**
|
|
3803
|
-
*
|
|
3658
|
+
* Get property with the lowest tax position
|
|
3804
3659
|
*/
|
|
3805
|
-
|
|
3806
|
-
|
|
3807
|
-
|
|
3808
|
-
|
|
3809
|
-
|
|
3810
|
-
|
|
3660
|
+
getBestPerformanceTaxProperty(transactions, depreciations) {
|
|
3661
|
+
const transactionsByProperty = transactions.groupBy('property.id');
|
|
3662
|
+
const depreciationsByProperty = depreciations.groupBy('property.id');
|
|
3663
|
+
return this.items.reduce((min, current) => {
|
|
3664
|
+
const minTaxPosition = min.getTaxPosition(transactionsByProperty.get(min.id), depreciationsByProperty.get(min.id));
|
|
3665
|
+
const currentTaxPosition = current.getTaxPosition(transactionsByProperty.get(current.id), depreciationsByProperty.get(current.id));
|
|
3666
|
+
return minTaxPosition > currentTaxPosition ? current : min;
|
|
3667
|
+
}, this.first);
|
|
3811
3668
|
}
|
|
3812
3669
|
/**
|
|
3813
|
-
*
|
|
3670
|
+
* Show best performance properties first
|
|
3671
|
+
* https://taxtank.atlassian.net/wiki/spaces/TAXTANK/pages/217677997/Property+Tank+Dashboard
|
|
3814
3672
|
*/
|
|
3815
|
-
|
|
3816
|
-
|
|
3817
|
-
|
|
3818
|
-
|
|
3673
|
+
sortByBestPerformance(transactions, depreciations) {
|
|
3674
|
+
const activeProperties = this.getActiveProperties();
|
|
3675
|
+
// nothing to sort when no active properties
|
|
3676
|
+
if (!activeProperties.length) {
|
|
3677
|
+
return this;
|
|
3819
3678
|
}
|
|
3820
|
-
|
|
3679
|
+
const bestProperties = uniqBy(this.create([
|
|
3680
|
+
activeProperties.getBestPerformanceGrowthProperty(),
|
|
3681
|
+
activeProperties.getBestPerformanceTaxProperty(transactions, depreciations)
|
|
3682
|
+
]).toArray(), 'id');
|
|
3683
|
+
const newItems = this.remove(bestProperties).toArray();
|
|
3684
|
+
newItems.unshift(...bestProperties);
|
|
3685
|
+
return this.create(newItems);
|
|
3821
3686
|
}
|
|
3822
|
-
|
|
3823
|
-
|
|
3687
|
+
}
|
|
3688
|
+
|
|
3689
|
+
class PropertyCategoryMovementCollection extends Collection {
|
|
3690
|
+
/**
|
|
3691
|
+
* @TODO TT-2355 Alex refactor propertyForecast, use separated api (then I can remove property from param)
|
|
3692
|
+
*/
|
|
3693
|
+
getByForecast(property, forecast) {
|
|
3694
|
+
const financialYear = new FinancialYear(forecast.financialYear);
|
|
3695
|
+
return this.filterBy('property.id', property.id).filter((movement) => {
|
|
3696
|
+
return movement.fromDate <= financialYear.endDate && !movement.toDate || movement.toDate >= financialYear.startDate;
|
|
3697
|
+
});
|
|
3824
3698
|
}
|
|
3825
|
-
|
|
3826
|
-
return this.
|
|
3699
|
+
hasCategory(categoryId) {
|
|
3700
|
+
return !!this.findBy('propertyCategory.id', categoryId);
|
|
3827
3701
|
}
|
|
3828
|
-
|
|
3829
|
-
|
|
3830
|
-
|
|
3831
|
-
|
|
3832
|
-
|
|
3833
|
-
|
|
3834
|
-
|
|
3835
|
-
|
|
3836
|
-
|
|
3837
|
-
|
|
3702
|
+
}
|
|
3703
|
+
|
|
3704
|
+
class VehicleClaimCollection extends Collection {
|
|
3705
|
+
/**
|
|
3706
|
+
* Get remaining kilometers limit. Total limit ({@link VehicleClaim.totalKmsLimit}) - claimed kilometers from other vehicle claims
|
|
3707
|
+
*/
|
|
3708
|
+
getKmsLimitForClaim(claim) {
|
|
3709
|
+
let collection = this;
|
|
3710
|
+
if (claim) {
|
|
3711
|
+
collection = collection.removeBy('id', claim.id);
|
|
3838
3712
|
}
|
|
3713
|
+
return VehicleClaim.totalKmsLimit - collection.sumBy('kilometers');
|
|
3839
3714
|
}
|
|
3840
3715
|
/**
|
|
3841
|
-
*
|
|
3716
|
+
* Get remaining work usage limit. Total limit ({@link VehicleClaim.totalWorkUsagePercent}) - claimed percent from other vehicle claims
|
|
3842
3717
|
*/
|
|
3843
|
-
|
|
3844
|
-
|
|
3718
|
+
getWorkUsageLimitForClaim(claim) {
|
|
3719
|
+
let collection = this;
|
|
3720
|
+
if (claim) {
|
|
3721
|
+
collection = collection.removeBy('id', claim.id);
|
|
3722
|
+
}
|
|
3723
|
+
return VehicleClaim.totalWorkUsagePercent - collection.sumBy('workUsage');
|
|
3845
3724
|
}
|
|
3725
|
+
}
|
|
3726
|
+
|
|
3727
|
+
class VehicleLogbookCollection extends Collection {
|
|
3846
3728
|
/**
|
|
3847
|
-
*
|
|
3729
|
+
* Best period may be calculated only when user has logbooks minimum for VehicleLogbook.bestPeriodWeeks
|
|
3730
|
+
* @TODO Vik: Best period: move this and related logic to backend
|
|
3848
3731
|
*/
|
|
3849
|
-
|
|
3850
|
-
|
|
3732
|
+
isBestPeriodExist() {
|
|
3733
|
+
if (this.items.length < 2) {
|
|
3734
|
+
return false;
|
|
3735
|
+
}
|
|
3736
|
+
return VehicleLogbook.bestPeriodDuration < (this.last.date.getTime() - this.first.date.getTime());
|
|
3851
3737
|
}
|
|
3852
3738
|
/**
|
|
3853
|
-
*
|
|
3739
|
+
* Get collection of non-personal logbooks (work-related, sole-related).
|
|
3740
|
+
* @TODO Vik: Best period: move this and related logic to backend
|
|
3854
3741
|
*/
|
|
3855
|
-
|
|
3856
|
-
return this.
|
|
3857
|
-
}
|
|
3858
|
-
get taxFreeComponent() {
|
|
3859
|
-
return this.getMetadataFieldValue(ChartAccountsMetadataListEnum.TAX_FREE_COMPONENT);
|
|
3860
|
-
}
|
|
3861
|
-
get frankingCredit() {
|
|
3862
|
-
return this.getMetadataFieldValue(ChartAccountsMetadataListEnum.FRANKING_CREDIT);
|
|
3863
|
-
}
|
|
3864
|
-
get eligibleForReduction() {
|
|
3865
|
-
return this.getMetadataFieldValue(ChartAccountsMetadataListEnum.ELIGIBLE_FOR_REDUCTION);
|
|
3866
|
-
}
|
|
3867
|
-
get untaxedElement() {
|
|
3868
|
-
return this.getMetadataFieldValue(ChartAccountsMetadataListEnum.UNTAXED_ELEMENT);
|
|
3742
|
+
getClaimableLogbooks() {
|
|
3743
|
+
return this.filterBy('isPersonal', false);
|
|
3869
3744
|
}
|
|
3870
3745
|
/**
|
|
3871
|
-
*
|
|
3872
|
-
*
|
|
3746
|
+
* Get Logbook Period with the biggest work usage percent
|
|
3747
|
+
* Best period duration is defined as VehicleLogbook.bestPeriodWeeks by the ATO
|
|
3748
|
+
* @TODO Vik: Best period: move this and related logic to backend
|
|
3873
3749
|
*/
|
|
3874
|
-
|
|
3875
|
-
|
|
3876
|
-
|
|
3877
|
-
|
|
3878
|
-
|
|
3879
|
-
|
|
3880
|
-
|
|
3881
|
-
|
|
3882
|
-
|
|
3883
|
-
|
|
3884
|
-
|
|
3885
|
-
|
|
3886
|
-
|
|
3887
|
-
|
|
3750
|
+
getBestPeriod() {
|
|
3751
|
+
if (!this.isBestPeriodExist()) {
|
|
3752
|
+
return null;
|
|
3753
|
+
}
|
|
3754
|
+
let bestPeriod;
|
|
3755
|
+
// get list of all logbooks available for best period calculation
|
|
3756
|
+
const claimableLogbooks = this.getClaimableLogbooks().toArray();
|
|
3757
|
+
for (let i = 0; i < claimableLogbooks.length; i++) {
|
|
3758
|
+
// no sense to check next logbooks because we already get the end of the year
|
|
3759
|
+
if (bestPeriod && bestPeriod.isEndOfYear()) {
|
|
3760
|
+
break;
|
|
3761
|
+
}
|
|
3762
|
+
// get date range started from current handling logbook date
|
|
3763
|
+
const dateRange = claimableLogbooks[i].getPeriod();
|
|
3764
|
+
// get all logbooks included in current logbook period
|
|
3765
|
+
const logbooksInRange = this.filterByRange('date', dateRange.start, dateRange.end);
|
|
3766
|
+
const currentPeriod = plainToClass(LogbookPeriod, {
|
|
3767
|
+
from: dateRange.start,
|
|
3768
|
+
to: dateRange.end,
|
|
3769
|
+
kilometers: logbooksInRange.getClaimableLogbooks().kilometers,
|
|
3770
|
+
workUsage: logbooksInRange.getWorkUsage(),
|
|
3771
|
+
logbooks: logbooksInRange
|
|
3772
|
+
});
|
|
3773
|
+
// compare with previous best period and overwrite if needs
|
|
3774
|
+
if (!bestPeriod || currentPeriod.workUsage > bestPeriod.workUsage) {
|
|
3775
|
+
bestPeriod = currentPeriod;
|
|
3776
|
+
}
|
|
3777
|
+
else if (currentPeriod.workUsage === bestPeriod.workUsage) {
|
|
3778
|
+
// if work usage is the same then get period with the biggest work usage for work tank
|
|
3779
|
+
const oldWorkUsage = bestPeriod.logbooks.filterBy('tankType', TankTypeEnum.WORK).getWorkUsage();
|
|
3780
|
+
const currentWorkUsage = currentPeriod.logbooks.filterBy('tankType', TankTypeEnum.WORK).getWorkUsage();
|
|
3781
|
+
if (oldWorkUsage < currentWorkUsage) {
|
|
3782
|
+
bestPeriod = currentPeriod;
|
|
3783
|
+
}
|
|
3784
|
+
}
|
|
3785
|
+
}
|
|
3786
|
+
return bestPeriod;
|
|
3888
3787
|
}
|
|
3889
3788
|
/**
|
|
3890
|
-
*
|
|
3891
|
-
* @param field for which value should be returned
|
|
3892
|
-
* @Todo modify 'metadata' property from array to Collection
|
|
3789
|
+
* Calculate total kilometers traveled
|
|
3893
3790
|
*/
|
|
3894
|
-
|
|
3895
|
-
|
|
3896
|
-
return +((_a = this.metadata.find((transactionMetadata) => {
|
|
3897
|
-
return transactionMetadata.chartAccountsMetadata.id === field;
|
|
3898
|
-
})) === null || _a === void 0 ? void 0 : _a.value) || 0;
|
|
3899
|
-
}
|
|
3900
|
-
isCash() {
|
|
3901
|
-
return this.source === TransactionSourceEnum.CASH;
|
|
3791
|
+
get kilometers() {
|
|
3792
|
+
return this.sumBy('kilometers');
|
|
3902
3793
|
}
|
|
3903
3794
|
/**
|
|
3904
|
-
*
|
|
3795
|
+
* Calculate work usage (percent of business-related kilometers from total kilometers)
|
|
3796
|
+
* @TODO Alex: TT-2089 replace with getter
|
|
3905
3797
|
*/
|
|
3906
|
-
|
|
3907
|
-
|
|
3908
|
-
|
|
3909
|
-
amount: this.amount,
|
|
3910
|
-
chartAccounts: this.chartAccounts,
|
|
3911
|
-
description: this.description,
|
|
3912
|
-
type: DepreciationTypeEnum.PLANT_EQUIPMENT,
|
|
3913
|
-
claimPercent: this.claimPercent,
|
|
3914
|
-
property: this.property,
|
|
3915
|
-
calculation: this.property ? this.property.depreciationCalculation : DepreciationCalculationEnum.PRIME_COST
|
|
3916
|
-
});
|
|
3798
|
+
getWorkUsage() {
|
|
3799
|
+
const workKilometers = this.getClaimableLogbooks().kilometers;
|
|
3800
|
+
return Math.round(workKilometers / this.kilometers * 100);
|
|
3917
3801
|
}
|
|
3918
3802
|
/**
|
|
3919
|
-
*
|
|
3803
|
+
* Get list of logbooks related to passed vehicle claim
|
|
3920
3804
|
*/
|
|
3921
|
-
|
|
3922
|
-
return
|
|
3805
|
+
getByVehicleClaim(vehicleClaim) {
|
|
3806
|
+
return vehicleClaim.isSoleTank()
|
|
3807
|
+
// sole tank may have multiple vehicle claims, so we need to filter by business.id
|
|
3808
|
+
? this.filterBy('business.id', vehicleClaim.business.id)
|
|
3809
|
+
// work tank may have only one vehicle claim, so we need to filter by tank type
|
|
3810
|
+
: this.filterBy('tankType', TankTypeEnum.WORK);
|
|
3923
3811
|
}
|
|
3924
|
-
|
|
3925
|
-
|
|
3812
|
+
}
|
|
3813
|
+
|
|
3814
|
+
/**
|
|
3815
|
+
* List of objects grouped by passed property
|
|
3816
|
+
*/
|
|
3817
|
+
class Dictionary {
|
|
3818
|
+
constructor(items, path = 'id') {
|
|
3819
|
+
this.items = {};
|
|
3820
|
+
if (!items.length) {
|
|
3821
|
+
return;
|
|
3822
|
+
}
|
|
3823
|
+
// Do nothing if provided path was not found in the 1st item
|
|
3824
|
+
if (!hasIn(items[0], path.split('.')[0])) {
|
|
3825
|
+
return;
|
|
3826
|
+
}
|
|
3827
|
+
this.groupItems(items, path);
|
|
3926
3828
|
}
|
|
3927
|
-
|
|
3928
|
-
|
|
3829
|
+
add(key, value) {
|
|
3830
|
+
this.items[key] = value;
|
|
3831
|
+
}
|
|
3832
|
+
get(key) {
|
|
3833
|
+
return this.items[key] !== undefined ? this.items[key] : null;
|
|
3834
|
+
}
|
|
3835
|
+
groupItems(items, path) {
|
|
3836
|
+
items.forEach((item) => {
|
|
3837
|
+
let key = get(item, path);
|
|
3838
|
+
// if object does not have property for grouping it will be grouped as 'other'
|
|
3839
|
+
if (key === undefined) {
|
|
3840
|
+
key = 'other';
|
|
3841
|
+
}
|
|
3842
|
+
this.items[key] = item;
|
|
3843
|
+
});
|
|
3929
3844
|
}
|
|
3845
|
+
}
|
|
3846
|
+
|
|
3847
|
+
class SoleBusinessLossesCollection extends Collection {
|
|
3930
3848
|
/**
|
|
3931
|
-
*
|
|
3849
|
+
* Business loss applied in current year, includes previous year losses and current year losses for businesses matching offset rule
|
|
3932
3850
|
*/
|
|
3933
|
-
|
|
3934
|
-
|
|
3851
|
+
calculateBusinessLossApplied(transactions) {
|
|
3852
|
+
// claim amounts for businesses that can be applied to be reduced by prior year business losses
|
|
3853
|
+
const claimAmountsByBusinessId = this.getClaimAmountsByBusinessId(transactions);
|
|
3854
|
+
return Object.keys(claimAmountsByBusinessId.items).reduce((sum, businessId) => {
|
|
3855
|
+
const loss = this.findBy('business.id', +businessId);
|
|
3856
|
+
const lossOpenBalance = (loss === null || loss === void 0 ? void 0 : loss.openBalance) || 0;
|
|
3857
|
+
// business loss can be applied to business profit or other income types profit in case in offset rule met
|
|
3858
|
+
return sum + ((loss === null || loss === void 0 ? void 0 : loss.offsetRule) ? lossOpenBalance : Math.min(lossOpenBalance, claimAmountsByBusinessId.get(businessId)));
|
|
3859
|
+
}, 0);
|
|
3935
3860
|
}
|
|
3936
3861
|
/**
|
|
3937
|
-
*
|
|
3862
|
+
* Get business claim amounts that can be applied to be reduced by prior year business losses:
|
|
3863
|
+
* businesses with income or businesses with a loss, but which met the non-commercial loss rules
|
|
3864
|
+
* https://www.ato.gov.au/Business/Non-commercial-losses/
|
|
3938
3865
|
*/
|
|
3939
|
-
|
|
3940
|
-
|
|
3941
|
-
|
|
3942
|
-
|
|
3943
|
-
|
|
3944
|
-
|
|
3945
|
-
|
|
3946
|
-
|
|
3947
|
-
|
|
3948
|
-
|
|
3866
|
+
getClaimAmountsByBusinessId(transactions) {
|
|
3867
|
+
const claimAmountsByBusinessId = new Dictionary([]);
|
|
3868
|
+
const transactionsByBusinessId = new CollectionDictionary(transactions, 'business.id');
|
|
3869
|
+
transactionsByBusinessId.keys.forEach((businessId) => {
|
|
3870
|
+
var _a;
|
|
3871
|
+
// business loss may not exist if, when creating a business, user didn't add losses for previous years
|
|
3872
|
+
const lossOffsetRule = (_a = this.findBy('business.id', +businessId)) === null || _a === void 0 ? void 0 : _a.offsetRule;
|
|
3873
|
+
const businessClaimAmount = transactionsByBusinessId
|
|
3874
|
+
.get(businessId)
|
|
3875
|
+
.getClaimAmountByBusinessId(+businessId);
|
|
3876
|
+
// no way to apply loss for business without profit if offset rules not met
|
|
3877
|
+
if (businessClaimAmount < 0 && !lossOffsetRule) {
|
|
3878
|
+
return;
|
|
3879
|
+
}
|
|
3880
|
+
claimAmountsByBusinessId.add(businessId, businessClaimAmount);
|
|
3881
|
+
});
|
|
3882
|
+
return claimAmountsByBusinessId;
|
|
3949
3883
|
}
|
|
3950
3884
|
}
|
|
3951
|
-
__decorate([
|
|
3952
|
-
Type(() => Transaction)
|
|
3953
|
-
], Transaction.prototype, "transactions", void 0);
|
|
3954
|
-
__decorate([
|
|
3955
|
-
Type(() => Property)
|
|
3956
|
-
], Transaction.prototype, "property", void 0);
|
|
3957
|
-
__decorate([
|
|
3958
|
-
Type(() => TransactionReceipt)
|
|
3959
|
-
], Transaction.prototype, "receipt", void 0);
|
|
3960
|
-
__decorate([
|
|
3961
|
-
Type(() => ChartAccounts)
|
|
3962
|
-
], Transaction.prototype, "chartAccounts", void 0);
|
|
3963
|
-
__decorate([
|
|
3964
|
-
Type(() => IncomeSource)
|
|
3965
|
-
], Transaction.prototype, "incomeSource", void 0);
|
|
3966
|
-
__decorate([
|
|
3967
|
-
Type(() => TransactionMetadata)
|
|
3968
|
-
], Transaction.prototype, "metadata", void 0);
|
|
3969
|
-
__decorate([
|
|
3970
|
-
Type(() => Transaction)
|
|
3971
|
-
], Transaction.prototype, "transfer", void 0);
|
|
3972
|
-
__decorate([
|
|
3973
|
-
Type(() => Loan)
|
|
3974
|
-
], Transaction.prototype, "loan", void 0);
|
|
3975
|
-
__decorate([
|
|
3976
|
-
Type(() => Date)
|
|
3977
|
-
], Transaction.prototype, "date", void 0);
|
|
3978
|
-
__decorate([
|
|
3979
|
-
Type(() => TransactionAllocation)
|
|
3980
|
-
], Transaction.prototype, "allocations", void 0);
|
|
3981
3885
|
|
|
3982
|
-
class
|
|
3983
|
-
|
|
3984
|
-
|
|
3985
|
-
this.isGST = false;
|
|
3886
|
+
class SoleInvoiceCollection extends Collection {
|
|
3887
|
+
getOverdue() {
|
|
3888
|
+
return this.filter((invoice) => invoice.isOverdue());
|
|
3986
3889
|
}
|
|
3987
|
-
|
|
3988
|
-
return this.
|
|
3890
|
+
getUnpaid() {
|
|
3891
|
+
return this.filter((invoice) => invoice.isUnpaid());
|
|
3989
3892
|
}
|
|
3990
|
-
|
|
3991
|
-
|
|
3992
|
-
Type(() => SoleInvoice)
|
|
3993
|
-
], SoleInvoiceItem.prototype, "invoice", void 0);
|
|
3994
|
-
__decorate([
|
|
3995
|
-
Type(() => ChartAccounts)
|
|
3996
|
-
], SoleInvoiceItem.prototype, "chartAccounts", void 0);
|
|
3997
|
-
__decorate([
|
|
3998
|
-
Type(() => Transaction)
|
|
3999
|
-
], SoleInvoiceItem.prototype, "transaction", void 0);
|
|
4000
|
-
|
|
4001
|
-
class SoleContact$1 extends AbstractModel {
|
|
4002
|
-
}
|
|
4003
|
-
|
|
4004
|
-
// @TODO Alex/Vik: Create some base class for User and SoleContact with common methods and properties
|
|
4005
|
-
class SoleContact extends SoleContact$1 {
|
|
4006
|
-
get fullName() {
|
|
4007
|
-
return `${this.firstName} ${this.lastName}`;
|
|
3893
|
+
getPaid() {
|
|
3894
|
+
return this.filter((invoice) => invoice.isPaid());
|
|
4008
3895
|
}
|
|
4009
|
-
|
|
4010
|
-
return
|
|
3896
|
+
getPending() {
|
|
3897
|
+
return this.filter((invoice) => invoice.isPending());
|
|
4011
3898
|
}
|
|
4012
|
-
|
|
4013
|
-
|
|
4014
|
-
return '';
|
|
3899
|
+
getTransactionsIds() {
|
|
3900
|
+
return flatten(this.items.map((invoice) => invoice.getTransactionsIds()));
|
|
4015
3901
|
}
|
|
4016
3902
|
}
|
|
4017
|
-
__decorate([
|
|
4018
|
-
Type(() => User)
|
|
4019
|
-
], SoleContact.prototype, "user", void 0);
|
|
4020
|
-
__decorate([
|
|
4021
|
-
Type(() => Phone)
|
|
4022
|
-
], SoleContact.prototype, "phone", void 0);
|
|
4023
|
-
__decorate([
|
|
4024
|
-
Type(() => Address)
|
|
4025
|
-
], SoleContact.prototype, "address", void 0);
|
|
4026
|
-
__decorate([
|
|
4027
|
-
Type(() => SoleInvoice)
|
|
4028
|
-
], SoleContact.prototype, "invoices", void 0);
|
|
4029
3903
|
|
|
4030
|
-
|
|
3904
|
+
/**
|
|
3905
|
+
* Chart serie class: chart data item
|
|
3906
|
+
* @TODO consider rename to ChartSerieData
|
|
3907
|
+
*/
|
|
3908
|
+
class ChartSerie {
|
|
4031
3909
|
}
|
|
4032
3910
|
|
|
4033
|
-
|
|
4034
|
-
|
|
4035
|
-
|
|
4036
|
-
|
|
4037
|
-
|
|
4038
|
-
})(SoleInvoiceTemplateTaxTypeEnum || (SoleInvoiceTemplateTaxTypeEnum = {}));
|
|
4039
|
-
|
|
4040
|
-
class SoleInvoiceTemplate extends SoleInvoiceTemplate$1 {
|
|
4041
|
-
constructor() {
|
|
4042
|
-
super(...arguments);
|
|
4043
|
-
/**
|
|
4044
|
-
* Affects to SoleInvoiceItem.isGST flag availability.
|
|
4045
|
-
* When NONE: isGST is unavailable
|
|
4046
|
-
* When EXCLUSIVE: GST amount added additionaly to invoice total price
|
|
4047
|
-
* When INCLUSIVE: GST amount is already included to invoice total price
|
|
4048
|
-
*/
|
|
4049
|
-
this.taxType = SoleInvoiceTemplateTaxTypeEnum.NO_TAX;
|
|
4050
|
-
}
|
|
4051
|
-
/**
|
|
4052
|
-
* Get term duration in milliseconds
|
|
4053
|
-
*/
|
|
4054
|
-
get termTime() {
|
|
4055
|
-
return this.term * 24 * 3600 * 1000;
|
|
4056
|
-
}
|
|
3911
|
+
/**
|
|
3912
|
+
* Chart data class
|
|
3913
|
+
* @TODO consider rename to ChartSerie
|
|
3914
|
+
*/
|
|
3915
|
+
class ChartData {
|
|
4057
3916
|
}
|
|
4058
3917
|
__decorate([
|
|
4059
|
-
Type(() =>
|
|
4060
|
-
],
|
|
4061
|
-
__decorate([
|
|
4062
|
-
Type(() => BankAccount)
|
|
4063
|
-
], SoleInvoiceTemplate.prototype, "bankAccount", void 0);
|
|
4064
|
-
|
|
4065
|
-
var SoleInvoiceStatusesEnum;
|
|
4066
|
-
(function (SoleInvoiceStatusesEnum) {
|
|
4067
|
-
SoleInvoiceStatusesEnum[SoleInvoiceStatusesEnum["CANCELED"] = 0] = "CANCELED";
|
|
4068
|
-
SoleInvoiceStatusesEnum[SoleInvoiceStatusesEnum["DRAFT"] = 1] = "DRAFT";
|
|
4069
|
-
SoleInvoiceStatusesEnum[SoleInvoiceStatusesEnum["PENDING"] = 2] = "PENDING";
|
|
4070
|
-
SoleInvoiceStatusesEnum[SoleInvoiceStatusesEnum["PAID"] = 3] = "PAID";
|
|
4071
|
-
})(SoleInvoiceStatusesEnum || (SoleInvoiceStatusesEnum = {}));
|
|
4072
|
-
|
|
4073
|
-
var SoleInvoiceTaxTypeEnum;
|
|
4074
|
-
(function (SoleInvoiceTaxTypeEnum) {
|
|
4075
|
-
SoleInvoiceTaxTypeEnum[SoleInvoiceTaxTypeEnum["TAX_EXCLUSIVE"] = 0] = "TAX_EXCLUSIVE";
|
|
4076
|
-
SoleInvoiceTaxTypeEnum[SoleInvoiceTaxTypeEnum["TAX_INCLUSIVE"] = 1] = "TAX_INCLUSIVE";
|
|
4077
|
-
SoleInvoiceTaxTypeEnum[SoleInvoiceTaxTypeEnum["NO_TAX"] = 2] = "NO_TAX";
|
|
4078
|
-
})(SoleInvoiceTaxTypeEnum || (SoleInvoiceTaxTypeEnum = {}));
|
|
3918
|
+
Type(() => ChartSerie)
|
|
3919
|
+
], ChartData.prototype, "data", void 0);
|
|
4079
3920
|
|
|
4080
|
-
|
|
4081
|
-
get gstPrice() {
|
|
4082
|
-
return this.filterBy('isGST', true).sumBy('totalPrice');
|
|
4083
|
-
}
|
|
4084
|
-
}
|
|
3921
|
+
const MONTHS = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec', 'Jan'];
|
|
4085
3922
|
|
|
4086
|
-
|
|
4087
|
-
|
|
4088
|
-
|
|
4089
|
-
|
|
4090
|
-
|
|
4091
|
-
}
|
|
3923
|
+
/**
|
|
3924
|
+
* @TODO extend from TransactionBaseCollection
|
|
3925
|
+
* Collection of transactions
|
|
3926
|
+
*/
|
|
3927
|
+
class TransactionCollection extends ExportableCollection {
|
|
4092
3928
|
/**
|
|
4093
|
-
*
|
|
3929
|
+
* @TODO use TransactionBaseCollection instead
|
|
3930
|
+
* we use depreciations as expense transactions a lot
|
|
4094
3931
|
*/
|
|
4095
|
-
|
|
4096
|
-
|
|
3932
|
+
constructor(transactions = [], depreciations = []) {
|
|
3933
|
+
super([...transactions, ...depreciations.map((depreciation) => depreciation.toTransaction())]);
|
|
4097
3934
|
}
|
|
4098
|
-
|
|
4099
|
-
|
|
4100
|
-
*/
|
|
4101
|
-
get price() {
|
|
4102
|
-
return this.itemsCollection.sumBy('totalPrice');
|
|
3935
|
+
getSoleTransactions() {
|
|
3936
|
+
return this.filter((transaction) => transaction.isSoleTank());
|
|
4103
3937
|
}
|
|
4104
|
-
|
|
4105
|
-
|
|
4106
|
-
|
|
4107
|
-
|
|
4108
|
-
|
|
4109
|
-
return
|
|
4110
|
-
}
|
|
4111
|
-
|
|
3938
|
+
get amount() {
|
|
3939
|
+
return this.sumBy('amount');
|
|
3940
|
+
}
|
|
3941
|
+
getUnallocated(allocations) {
|
|
3942
|
+
return new TransactionCollection(this.items.filter((transaction) => {
|
|
3943
|
+
return !transaction.isAllocated(allocations);
|
|
3944
|
+
}));
|
|
3945
|
+
}
|
|
3946
|
+
getUnallocatedAmount(allocations) {
|
|
3947
|
+
return this.items.reduce((sum, transaction) => {
|
|
3948
|
+
return sum + transaction.getUnallocatedAmount(allocations.filterBy('transaction.id', transaction.id));
|
|
3949
|
+
}, 0);
|
|
4112
3950
|
}
|
|
4113
3951
|
/**
|
|
4114
|
-
*
|
|
3952
|
+
* get date of the last transaction
|
|
4115
3953
|
*/
|
|
4116
|
-
|
|
4117
|
-
|
|
4118
|
-
|
|
4119
|
-
|
|
4120
|
-
return this.
|
|
3954
|
+
getLastTransactionDate() {
|
|
3955
|
+
return new Date(Math.max.apply(Math, this.items.map((transaction) => transaction.date)));
|
|
3956
|
+
}
|
|
3957
|
+
get claimAmount() {
|
|
3958
|
+
return this.items.reduce((sum, transaction) => sum + transaction.claimAmount, 0);
|
|
3959
|
+
}
|
|
3960
|
+
get grossClaimAmount() {
|
|
3961
|
+
return this.items.reduce((sum, transaction) => sum + transaction.grossClaimAmount, 0);
|
|
3962
|
+
}
|
|
3963
|
+
get grossAmount() {
|
|
3964
|
+
return this.items.reduce((sum, transaction) => sum + transaction.grossAmount, 0);
|
|
4121
3965
|
}
|
|
4122
|
-
|
|
4123
|
-
|
|
4124
|
-
*/
|
|
4125
|
-
get GSTAmount() {
|
|
4126
|
-
switch (this.taxType) {
|
|
4127
|
-
case SoleInvoiceTaxTypeEnum.TAX_INCLUSIVE:
|
|
4128
|
-
return this.inclusiveGSTAmount;
|
|
4129
|
-
case SoleInvoiceTaxTypeEnum.TAX_EXCLUSIVE:
|
|
4130
|
-
return this.exclusiveGSTAmount;
|
|
4131
|
-
case SoleInvoiceTaxTypeEnum.NO_TAX:
|
|
4132
|
-
return 0;
|
|
4133
|
-
}
|
|
3966
|
+
getByChartAccountsCategories(categories) {
|
|
3967
|
+
return new TransactionCollection(this.items.filter((transaction) => categories.includes(transaction.chartAccounts.category)));
|
|
4134
3968
|
}
|
|
4135
3969
|
/**
|
|
4136
|
-
*
|
|
3970
|
+
* Get transactions by month
|
|
3971
|
+
* @param monthIndex by which desired month should be taken
|
|
4137
3972
|
*/
|
|
4138
|
-
|
|
4139
|
-
|
|
4140
|
-
return +(gstPrice - (gstPrice / (1 + ChartAccounts.GSTRatio))).toFixed(2);
|
|
3973
|
+
getByMonth(monthIndex) {
|
|
3974
|
+
return new TransactionCollection(this.items.filter((transaction) => transaction.date.getMonth() === monthIndex));
|
|
4141
3975
|
}
|
|
4142
3976
|
/**
|
|
4143
|
-
*
|
|
3977
|
+
* Get collection of transactions metadata
|
|
4144
3978
|
*/
|
|
4145
|
-
|
|
4146
|
-
|
|
3979
|
+
getTransactionsMetadata() {
|
|
3980
|
+
const metadataArray = [];
|
|
3981
|
+
this.items.forEach((transaction) => {
|
|
3982
|
+
metadataArray.push(...transaction.metadata);
|
|
3983
|
+
});
|
|
3984
|
+
return new Collection(metadataArray);
|
|
4147
3985
|
}
|
|
4148
|
-
|
|
4149
|
-
return this.
|
|
3986
|
+
getIncomeTransactions() {
|
|
3987
|
+
return new TransactionCollection(this.items.filter((transaction) => transaction.isIncome()));
|
|
4150
3988
|
}
|
|
4151
|
-
|
|
4152
|
-
return this.
|
|
3989
|
+
getExpenseTransactions() {
|
|
3990
|
+
return new TransactionCollection(this.items.filter((transaction) => transaction.isExpense() && !transaction.isInterest()));
|
|
4153
3991
|
}
|
|
4154
|
-
|
|
4155
|
-
return this.
|
|
3992
|
+
get claimIncome() {
|
|
3993
|
+
return this.getIncomeTransactions().claimAmount;
|
|
4156
3994
|
}
|
|
4157
|
-
|
|
4158
|
-
return this.
|
|
3995
|
+
get claimExpense() {
|
|
3996
|
+
return this.getExpenseTransactions().claimAmount;
|
|
4159
3997
|
}
|
|
4160
|
-
|
|
4161
|
-
return this.
|
|
3998
|
+
getInterestTransactions() {
|
|
3999
|
+
return new TransactionCollection(this.items.filter((transaction) => transaction.isInterest()));
|
|
4162
4000
|
}
|
|
4163
|
-
|
|
4164
|
-
return this.
|
|
4001
|
+
get claimInterest() {
|
|
4002
|
+
return this.getInterestTransactions().claimAmount;
|
|
4165
4003
|
}
|
|
4166
4004
|
/**
|
|
4167
|
-
*
|
|
4005
|
+
* Get collection of transactions and properties filtered by properties ids
|
|
4006
|
+
* @param ids Ids of properties for filter
|
|
4168
4007
|
*/
|
|
4169
|
-
|
|
4170
|
-
return this.
|
|
4008
|
+
getByPropertiesIds(ids) {
|
|
4009
|
+
return new TransactionCollection(this.items.filter((transaction) => {
|
|
4010
|
+
var _a;
|
|
4011
|
+
return ids.includes((_a = transaction.property) === null || _a === void 0 ? void 0 : _a.id);
|
|
4012
|
+
}));
|
|
4171
4013
|
}
|
|
4172
4014
|
/**
|
|
4173
|
-
*
|
|
4174
|
-
*
|
|
4015
|
+
* Get new collection filtered by income source id
|
|
4016
|
+
* @param id id of income source for filter
|
|
4175
4017
|
*/
|
|
4176
|
-
|
|
4177
|
-
return this.
|
|
4018
|
+
getByIncomeSourceId(id) {
|
|
4019
|
+
return new TransactionCollection(this.items.filter((transaction) => { var _a; return ((_a = transaction.incomeSource) === null || _a === void 0 ? void 0 : _a.id) === id; }));
|
|
4178
4020
|
}
|
|
4179
4021
|
/**
|
|
4180
|
-
*
|
|
4181
|
-
*
|
|
4022
|
+
* Get new collection filtered by chart accounts category
|
|
4023
|
+
* @param category Chart accounts category value
|
|
4182
4024
|
*/
|
|
4183
|
-
|
|
4184
|
-
return this.
|
|
4185
|
-
}
|
|
4186
|
-
getNumber() {
|
|
4187
|
-
return String(this.number).padStart(SoleInvoice.NUMBER_LENGTH, '0');
|
|
4188
|
-
}
|
|
4189
|
-
get name() {
|
|
4190
|
-
return `invoice-${this.getNumber()}.pdf`;
|
|
4191
|
-
}
|
|
4192
|
-
getTransactionsIds() {
|
|
4193
|
-
return new Collection(this.items).mapBy('transaction.id');
|
|
4194
|
-
this.items.map((item) => item.transaction.id);
|
|
4195
|
-
}
|
|
4196
|
-
}
|
|
4197
|
-
SoleInvoice.NUMBER_LENGTH = 4;
|
|
4198
|
-
__decorate([
|
|
4199
|
-
Type(() => Date)
|
|
4200
|
-
], SoleInvoice.prototype, "dateFrom", void 0);
|
|
4201
|
-
__decorate([
|
|
4202
|
-
Type(() => Date)
|
|
4203
|
-
], SoleInvoice.prototype, "dateTo", void 0);
|
|
4204
|
-
__decorate([
|
|
4205
|
-
Type(() => User)
|
|
4206
|
-
], SoleInvoice.prototype, "user", void 0);
|
|
4207
|
-
__decorate([
|
|
4208
|
-
Type(() => SoleBusiness)
|
|
4209
|
-
], SoleInvoice.prototype, "business", void 0);
|
|
4210
|
-
__decorate([
|
|
4211
|
-
Type(() => SoleInvoiceItem)
|
|
4212
|
-
], SoleInvoice.prototype, "items", void 0);
|
|
4213
|
-
__decorate([
|
|
4214
|
-
Type(() => SoleContact)
|
|
4215
|
-
], SoleInvoice.prototype, "payer", void 0);
|
|
4216
|
-
__decorate([
|
|
4217
|
-
Type(() => SoleInvoiceTemplate)
|
|
4218
|
-
], SoleInvoice.prototype, "template", void 0);
|
|
4219
|
-
__decorate([
|
|
4220
|
-
Type(() => BankAccount)
|
|
4221
|
-
], SoleInvoice.prototype, "bankAccount", void 0);
|
|
4222
|
-
|
|
4223
|
-
/**
|
|
4224
|
-
* Class contains traveled kilometers and work usage percent in 12 weeks date range
|
|
4225
|
-
* @TODO Vik: Best period: move this and related logic to backend
|
|
4226
|
-
* @TODO Alex: check if we need this class when calculation refactored with backend
|
|
4227
|
-
*/
|
|
4228
|
-
class LogbookPeriod {
|
|
4229
|
-
isEndOfYear() {
|
|
4230
|
-
return this.to === new FinancialYear().endDate;
|
|
4231
|
-
}
|
|
4232
|
-
getWorkUsageByClaim(claim) {
|
|
4233
|
-
const claimKilometers = this.logbooks.getByVehicleClaim(claim).getClaimableLogbooks().kilometers;
|
|
4234
|
-
return Math.round(this.workUsage * (claimKilometers / this.kilometers));
|
|
4025
|
+
getByChartAccountsCategory(category) {
|
|
4026
|
+
return new TransactionCollection(this.items.filter((transaction) => transaction.chartAccounts.category === category));
|
|
4235
4027
|
}
|
|
4236
|
-
|
|
4237
|
-
|
|
4238
|
-
|
|
4239
|
-
|
|
4240
|
-
|
|
4241
|
-
Type(() => Date)
|
|
4242
|
-
], LogbookPeriod.prototype, "to", void 0);
|
|
4243
|
-
|
|
4244
|
-
class Vehicle$1 extends AbstractModel {
|
|
4245
|
-
}
|
|
4246
|
-
|
|
4247
|
-
class VehicleLogbook$1 extends AbstractModel {
|
|
4248
|
-
}
|
|
4249
|
-
|
|
4250
|
-
// problem with DateRange and typescript. See more https://github.com/rotaready/moment-range/issues/263
|
|
4251
|
-
const moment = extendMoment(moment$1);
|
|
4252
|
-
class VehicleLogbook extends VehicleLogbook$1 {
|
|
4253
|
-
get kilometers() {
|
|
4254
|
-
return this.odometerEnd - this.odometerStart;
|
|
4028
|
+
/**
|
|
4029
|
+
* Get new collection of property transactions
|
|
4030
|
+
*/
|
|
4031
|
+
getPropertyTransactions() {
|
|
4032
|
+
return new TransactionCollection(this.items.filter((transaction) => transaction.isPropertyTank()));
|
|
4255
4033
|
}
|
|
4256
|
-
|
|
4257
|
-
return this.
|
|
4034
|
+
getDebitTransactions() {
|
|
4035
|
+
return new TransactionCollection(this.items.filter((transaction) => transaction.isDebit()));
|
|
4258
4036
|
}
|
|
4259
|
-
|
|
4260
|
-
return
|
|
4037
|
+
getCreditTransactions() {
|
|
4038
|
+
return new TransactionCollection(this.items.filter((transaction) => transaction.isCredit()));
|
|
4261
4039
|
}
|
|
4262
|
-
|
|
4263
|
-
return
|
|
4040
|
+
getByAllocations(allocations) {
|
|
4041
|
+
return new TransactionCollection(this.items.filter((transaction) => allocations.hasTransaction(transaction)));
|
|
4264
4042
|
}
|
|
4265
4043
|
/**
|
|
4266
|
-
* Get
|
|
4044
|
+
* Get transactions related to Vehicle category
|
|
4267
4045
|
*/
|
|
4268
|
-
|
|
4269
|
-
return
|
|
4270
|
-
|
|
4271
|
-
}
|
|
4272
|
-
/**
|
|
4273
|
-
* Logbook period duration in milliseconds.
|
|
4274
|
-
* https://taxtank.atlassian.net/wiki/spaces/TAXTANK/pages/211517441/Logbook+Vehicle
|
|
4275
|
-
*/
|
|
4276
|
-
VehicleLogbook.bestPeriodDuration = 12 * 7 * 24 * 3600 * 1000;
|
|
4277
|
-
__decorate([
|
|
4278
|
-
Type(() => Date)
|
|
4279
|
-
], VehicleLogbook.prototype, "date", void 0);
|
|
4280
|
-
__decorate([
|
|
4281
|
-
Type(() => SoleBusiness)
|
|
4282
|
-
], VehicleLogbook.prototype, "business", void 0);
|
|
4283
|
-
|
|
4284
|
-
class Vehicle extends Vehicle$1 {
|
|
4285
|
-
}
|
|
4286
|
-
__decorate([
|
|
4287
|
-
Type(() => VehicleLogbook)
|
|
4288
|
-
], Vehicle.prototype, "logbook", void 0);
|
|
4289
|
-
|
|
4290
|
-
class VehicleClaim$1 extends AbstractModel {
|
|
4291
|
-
}
|
|
4292
|
-
|
|
4293
|
-
class VehicleClaimDetails$1 extends AbstractModel {
|
|
4294
|
-
}
|
|
4295
|
-
|
|
4296
|
-
var VehicleClaimDetailsMethodEnum;
|
|
4297
|
-
(function (VehicleClaimDetailsMethodEnum) {
|
|
4298
|
-
VehicleClaimDetailsMethodEnum[VehicleClaimDetailsMethodEnum["KMS"] = 1] = "KMS";
|
|
4299
|
-
VehicleClaimDetailsMethodEnum[VehicleClaimDetailsMethodEnum["LOGBOOK"] = 2] = "LOGBOOK";
|
|
4300
|
-
})(VehicleClaimDetailsMethodEnum || (VehicleClaimDetailsMethodEnum = {}));
|
|
4301
|
-
|
|
4302
|
-
class VehicleClaimDetails extends VehicleClaimDetails$1 {
|
|
4303
|
-
constructor() {
|
|
4304
|
-
super(...arguments);
|
|
4305
|
-
/**
|
|
4306
|
-
* Init default values for the new instances
|
|
4307
|
-
*/
|
|
4308
|
-
this.isManual = true;
|
|
4309
|
-
this.method = VehicleClaimDetailsMethodEnum.KMS;
|
|
4310
|
-
this.financialYear = new FinancialYear().year;
|
|
4046
|
+
getVehicleTransactions() {
|
|
4047
|
+
return this.create(this.items.filter((transaction) => {
|
|
4048
|
+
return transaction.isVehicleTransaction();
|
|
4049
|
+
}));
|
|
4311
4050
|
}
|
|
4312
|
-
|
|
4313
|
-
|
|
4051
|
+
/**
|
|
4052
|
+
* Get new transaction collection filtered by tank type
|
|
4053
|
+
*/
|
|
4054
|
+
getByTankType(tankType) {
|
|
4055
|
+
return this.create(this.items.filter((transaction) => {
|
|
4056
|
+
switch (tankType) {
|
|
4057
|
+
case TankTypeEnum.PROPERTY:
|
|
4058
|
+
return transaction.isPropertyTank();
|
|
4059
|
+
case TankTypeEnum.WORK:
|
|
4060
|
+
return transaction.isWorkTank();
|
|
4061
|
+
case TankTypeEnum.SOLE:
|
|
4062
|
+
return transaction.isSoleTank();
|
|
4063
|
+
// Transaction may be not related to any tank type (personal)
|
|
4064
|
+
default:
|
|
4065
|
+
return false;
|
|
4066
|
+
}
|
|
4067
|
+
}));
|
|
4314
4068
|
}
|
|
4315
|
-
|
|
4316
|
-
return
|
|
4069
|
+
getExportHeader() {
|
|
4070
|
+
return ['Date', 'Description', 'Debit', 'Credit'];
|
|
4317
4071
|
}
|
|
4318
|
-
|
|
4319
|
-
|
|
4320
|
-
|
|
4321
|
-
|
|
4322
|
-
|
|
4323
|
-
|
|
4324
|
-
|
|
4325
|
-
super(...arguments);
|
|
4326
|
-
this.kilometers = 0;
|
|
4327
|
-
this.workUsage = 0;
|
|
4072
|
+
getExportFooter() {
|
|
4073
|
+
return [
|
|
4074
|
+
plainToClass(ExportCell, { value: 'Total', type: ExportCellTypeEnum.STRING }),
|
|
4075
|
+
plainToClass(ExportCell, { value: '', type: ExportCellTypeEnum.STRING }),
|
|
4076
|
+
plainToClass(ExportCell, { value: this.sumBy('debit'), type: ExportCellTypeEnum.CURRENCY }),
|
|
4077
|
+
plainToClass(ExportCell, { value: this.sumBy('credit'), type: ExportCellTypeEnum.CURRENCY })
|
|
4078
|
+
];
|
|
4328
4079
|
}
|
|
4329
|
-
|
|
4330
|
-
return
|
|
4080
|
+
getExportBody() {
|
|
4081
|
+
return this.items.map((transaction) => {
|
|
4082
|
+
return [
|
|
4083
|
+
plainToClass(ExportCell, { value: transaction.date, type: ExportCellTypeEnum.DATE }),
|
|
4084
|
+
plainToClass(ExportCell, { value: transaction.description, type: ExportCellTypeEnum.STRING }),
|
|
4085
|
+
plainToClass(ExportCell, { value: transaction.debit, type: ExportCellTypeEnum.CURRENCY }),
|
|
4086
|
+
plainToClass(ExportCell, { value: transaction.credit, type: ExportCellTypeEnum.CURRENCY })
|
|
4087
|
+
];
|
|
4088
|
+
});
|
|
4331
4089
|
}
|
|
4332
|
-
|
|
4333
|
-
|
|
4090
|
+
/**
|
|
4091
|
+
* Get list of vehicle transactions filtered by vehicle claim
|
|
4092
|
+
*/
|
|
4093
|
+
getByVehicleClaim(vehicleClaim) {
|
|
4094
|
+
if (!vehicleClaim) {
|
|
4095
|
+
return this.create([]);
|
|
4096
|
+
}
|
|
4097
|
+
return vehicleClaim.isSoleTank()
|
|
4098
|
+
// sole tank may have multiple vehicle claims, so we need to filter by business.id
|
|
4099
|
+
? this.getVehicleTransactions().filterBy('business.id', vehicleClaim.business.id)
|
|
4100
|
+
// work tank may have only one vehicle claim, so we need to filter by tank type
|
|
4101
|
+
: this.getVehicleTransactions().filterBy('tankType', TankTypeEnum.WORK);
|
|
4334
4102
|
}
|
|
4335
|
-
|
|
4336
|
-
|
|
4103
|
+
/**
|
|
4104
|
+
* Get list of vehicle transactions except KMS transactions
|
|
4105
|
+
*/
|
|
4106
|
+
getLogbookTransactions() {
|
|
4107
|
+
return this
|
|
4108
|
+
.getVehicleTransactions()
|
|
4109
|
+
.removeBy('chartAccounts.id', [ChartAccountsListEnum.KLMS_TRAVELLED_FOR_WORK, ChartAccountsListEnum.KLMS_TRAVELLED]);
|
|
4337
4110
|
}
|
|
4338
4111
|
/**
|
|
4339
|
-
*
|
|
4112
|
+
* Build chart data with transactions cash position.
|
|
4113
|
+
* Cash position = Income - Expenses (include depreciations)
|
|
4114
|
+
* Chart data for each month from fin year start till current month
|
|
4340
4115
|
*/
|
|
4341
|
-
|
|
4342
|
-
|
|
4116
|
+
getCashPositionChartData() {
|
|
4117
|
+
const chartData = [
|
|
4118
|
+
plainToClass(ChartData, { name: 'Income', data: [] }),
|
|
4119
|
+
plainToClass(ChartData, { name: 'Expense', data: [] })
|
|
4120
|
+
];
|
|
4121
|
+
new FinancialYear().getPastMonths().forEach((month) => {
|
|
4122
|
+
chartData[0].data.push({
|
|
4123
|
+
label: MONTHS[month],
|
|
4124
|
+
value: this.getIncomeTransactions().getByMonth(month).claimAmount
|
|
4125
|
+
});
|
|
4126
|
+
chartData[1].data.push({
|
|
4127
|
+
label: MONTHS[month],
|
|
4128
|
+
value: Math.abs(this.getExpenseTransactions().getByMonth(month).claimAmount)
|
|
4129
|
+
});
|
|
4130
|
+
});
|
|
4131
|
+
return chartData;
|
|
4343
4132
|
}
|
|
4344
4133
|
/**
|
|
4345
|
-
*
|
|
4346
|
-
* ClaimAmount = WorkUsage * transaction/depreciation amount
|
|
4134
|
+
* user pays GST only from allocated part (or paid) of income
|
|
4347
4135
|
*/
|
|
4348
|
-
|
|
4349
|
-
|
|
4350
|
-
|
|
4351
|
-
.
|
|
4352
|
-
|
|
4353
|
-
|
|
4354
|
-
return Math.abs(transactionsAmount) * this.workUsage / 100;
|
|
4136
|
+
calculateAllocatedClaimAmount(allocations) {
|
|
4137
|
+
let allocatedClaimAmount = 0;
|
|
4138
|
+
this.filterBy('isGST', true).toArray().forEach((transaction) => {
|
|
4139
|
+
allocatedClaimAmount += transaction.getAllocatedClaimAmount(allocations);
|
|
4140
|
+
});
|
|
4141
|
+
return allocatedClaimAmount;
|
|
4355
4142
|
}
|
|
4356
|
-
|
|
4357
|
-
return this.
|
|
4143
|
+
calculateAllocatedGST(allocations) {
|
|
4144
|
+
return this.calculateAllocatedClaimAmount(allocations) * ChartAccounts.GSTRatio;
|
|
4358
4145
|
}
|
|
4359
|
-
|
|
4360
|
-
return
|
|
4361
|
-
? ChartAccountsListEnum.KLMS_TRAVELLED_FOR_WORK
|
|
4362
|
-
: ChartAccountsListEnum.KLMS_TRAVELLED;
|
|
4146
|
+
getAllocatedAmount(allocations) {
|
|
4147
|
+
return allocations.getByTransactionsIds(this.getIds()).sumBy('amount');
|
|
4363
4148
|
}
|
|
4364
4149
|
}
|
|
4365
|
-
/**
|
|
4366
|
-
* limit for kms claim method
|
|
4367
|
-
*/
|
|
4368
|
-
VehicleClaim.totalKmsLimit = 5000;
|
|
4369
|
-
/**
|
|
4370
|
-
* limit for work usage claim method
|
|
4371
|
-
*/
|
|
4372
|
-
VehicleClaim.totalWorkUsagePercent = 100;
|
|
4373
|
-
__decorate([
|
|
4374
|
-
Type(() => VehicleClaimDetails)
|
|
4375
|
-
], VehicleClaim.prototype, "details", void 0);
|
|
4376
|
-
__decorate([
|
|
4377
|
-
Type(() => SoleBusiness)
|
|
4378
|
-
], VehicleClaim.prototype, "business", void 0);
|
|
4379
|
-
|
|
4380
|
-
class SoleBusinessActivity$1 extends AbstractModel {
|
|
4381
|
-
}
|
|
4382
4150
|
|
|
4383
|
-
class
|
|
4384
|
-
|
|
4385
|
-
return
|
|
4151
|
+
class TransactionAllocationCollection extends Collection {
|
|
4152
|
+
get amount() {
|
|
4153
|
+
return this.sumBy('amount');
|
|
4386
4154
|
}
|
|
4387
|
-
|
|
4388
|
-
return this.
|
|
4155
|
+
getByTransactionsIds(ids) {
|
|
4156
|
+
return new TransactionAllocationCollection(this.items.filter((allocation) => ids.includes(allocation.transaction.id)));
|
|
4389
4157
|
}
|
|
4390
|
-
|
|
4391
|
-
|
|
4392
|
-
|
|
4393
|
-
|
|
4394
|
-
|
|
4395
|
-
|
|
4396
|
-
|
|
4397
|
-
|
|
4398
|
-
|
|
4399
|
-
|
|
4400
|
-
|
|
4401
|
-
|
|
4402
|
-
|
|
4403
|
-
|
|
4404
|
-
|
|
4405
|
-
|
|
4406
|
-
|
|
4407
|
-
|
|
4408
|
-
|
|
4409
|
-
|
|
4410
|
-
|
|
4411
|
-
|
|
4412
|
-
|
|
4413
|
-
|
|
4414
|
-
|
|
4415
|
-
|
|
4416
|
-
|
|
4417
|
-
|
|
4418
|
-
], SoleBusiness.prototype, "depreciations", void 0);
|
|
4419
|
-
__decorate([
|
|
4420
|
-
Type(() => SoleBusinessActivity$1)
|
|
4421
|
-
], SoleBusiness.prototype, "activity", void 0);
|
|
4422
|
-
__decorate([
|
|
4423
|
-
Type(() => IncomeSource)
|
|
4424
|
-
], SoleBusiness.prototype, "incomeSource", void 0);
|
|
4425
|
-
|
|
4426
|
-
class SoleBusinessActivity extends SoleBusinessActivity$1 {
|
|
4427
|
-
}
|
|
4428
|
-
|
|
4429
|
-
class SoleDepreciationMethod$1 extends AbstractModel {
|
|
4430
|
-
}
|
|
4431
|
-
|
|
4432
|
-
var SoleDepreciationMethodEnum;
|
|
4433
|
-
(function (SoleDepreciationMethodEnum) {
|
|
4434
|
-
SoleDepreciationMethodEnum[SoleDepreciationMethodEnum["SBP"] = 1] = "SBP";
|
|
4435
|
-
SoleDepreciationMethodEnum[SoleDepreciationMethodEnum["DEPRECIATION"] = 2] = "DEPRECIATION";
|
|
4436
|
-
})(SoleDepreciationMethodEnum || (SoleDepreciationMethodEnum = {}));
|
|
4437
|
-
|
|
4438
|
-
class SoleDepreciationMethod extends SoleDepreciationMethod$1 {
|
|
4439
|
-
isSBP() {
|
|
4440
|
-
return this.method === SoleDepreciationMethodEnum.SBP;
|
|
4158
|
+
getByBankTransactionsIds(ids) {
|
|
4159
|
+
return new TransactionAllocationCollection(this.items.filter((allocation) => ids.includes(allocation.bankTransaction.id)));
|
|
4160
|
+
}
|
|
4161
|
+
/**
|
|
4162
|
+
* Group allocations by bank account via bank transactions collection
|
|
4163
|
+
*/
|
|
4164
|
+
groupByBankAccount(bankTransactions) {
|
|
4165
|
+
// Group bank transactions by bank account id
|
|
4166
|
+
const bankTransactionsByBankAccount = new CollectionDictionary(bankTransactions, 'bankAccount.id');
|
|
4167
|
+
// Create empty dictionary of transaction allocations
|
|
4168
|
+
const allocationsByBankAccount = new CollectionDictionary(new TransactionAllocationCollection([]));
|
|
4169
|
+
// Fill allocations dictionary with bank transactions dictionary keys and allocations related with each bank transaction collection
|
|
4170
|
+
bankTransactionsByBankAccount.keys.forEach((key) => {
|
|
4171
|
+
allocationsByBankAccount.add(key, this.getByBankTransactionsIds(bankTransactionsByBankAccount.get(key).getIds()));
|
|
4172
|
+
});
|
|
4173
|
+
return allocationsByBankAccount;
|
|
4174
|
+
}
|
|
4175
|
+
/**
|
|
4176
|
+
* check if collection includes allocation of passed transaction
|
|
4177
|
+
*/
|
|
4178
|
+
hasTransaction(transaction) {
|
|
4179
|
+
return !!this.items.find((allocation) => allocation.transaction.id === transaction.id);
|
|
4180
|
+
}
|
|
4181
|
+
/**
|
|
4182
|
+
* Check if bank transaction is related with current allocations
|
|
4183
|
+
*/
|
|
4184
|
+
hasBankTransaction(bankTransaction) {
|
|
4185
|
+
return !!this.items.find((allocation) => allocation.bankTransaction.id === bankTransaction.id);
|
|
4441
4186
|
}
|
|
4442
4187
|
}
|
|
4443
4188
|
|
|
4444
|
-
class
|
|
4445
|
-
}
|
|
4446
|
-
|
|
4447
|
-
class SoleDetails extends SoleDetails$1 {
|
|
4189
|
+
class Depreciation$1 extends TransactionBase {
|
|
4448
4190
|
}
|
|
4449
|
-
__decorate([
|
|
4450
|
-
Type(() => User)
|
|
4451
|
-
], SoleDetails.prototype, "user", void 0);
|
|
4452
4191
|
|
|
4453
|
-
class
|
|
4192
|
+
class DepreciationCapitalProject$1 extends AbstractModel {
|
|
4454
4193
|
}
|
|
4455
4194
|
|
|
4456
|
-
class
|
|
4457
|
-
get taxWithheldTotal() {
|
|
4458
|
-
return this.taxWithheldSalary + this.taxWithheldNoABN;
|
|
4459
|
-
}
|
|
4460
|
-
get paygTaxInstalmentOwedToATO() {
|
|
4461
|
-
return this.paygTaxInstalment > 0 ? this.paygTaxInstalment : 0;
|
|
4462
|
-
}
|
|
4463
|
-
get paygTaxInstalmentOwedByATO() {
|
|
4464
|
-
return this.paygTaxInstalment < 0 ? Math.abs(this.paygTaxInstalment) : 0;
|
|
4465
|
-
}
|
|
4466
|
-
get fuelTaxCreditOwedToATO() {
|
|
4467
|
-
return this.fuelTaxCredit < 0 ? this.fuelTaxCredit : 0;
|
|
4468
|
-
}
|
|
4469
|
-
get fuelTaxCreditOwedByATO() {
|
|
4470
|
-
return this.fuelTaxCredit > 0 ? Math.abs(this.fuelTaxCredit) : 0;
|
|
4471
|
-
}
|
|
4472
|
-
get owesToATO() {
|
|
4473
|
-
return this.incomeGST + this.taxWithheldTotal + this.paygTaxInstalmentOwedToATO + this.fuelTaxCreditOwedToATO;
|
|
4474
|
-
}
|
|
4475
|
-
get owedByATO() {
|
|
4476
|
-
return this.expenseGST + this.paygTaxInstalmentOwedByATO + this.fuelTaxCreditOwedByATO;
|
|
4477
|
-
}
|
|
4478
|
-
/**
|
|
4479
|
-
* GST payable to the ATO, or refundable from the ATO in case it's negative
|
|
4480
|
-
*/
|
|
4481
|
-
get gst() {
|
|
4482
|
-
return this.incomeGST + this.expenseGST + this.taxWithheldTotal + this.paygTaxInstalment - this.fuelTaxCredit;
|
|
4483
|
-
}
|
|
4195
|
+
class DepreciationCapitalProject extends DepreciationCapitalProject$1 {
|
|
4484
4196
|
}
|
|
4485
4197
|
__decorate([
|
|
4486
4198
|
Type(() => Date)
|
|
4487
|
-
],
|
|
4488
|
-
__decorate([
|
|
4489
|
-
Type(() => Date)
|
|
4490
|
-
], BasReport.prototype, "dateTo", void 0);
|
|
4199
|
+
], DepreciationCapitalProject.prototype, "effectiveDate", void 0);
|
|
4491
4200
|
|
|
4492
|
-
|
|
4493
|
-
|
|
4494
|
-
*/
|
|
4495
|
-
const USER_ROLES = {
|
|
4496
|
-
ROLE_FIRM_OWNER: [UserRolesEnum.FIRM_OWNER, UserRolesEnum.FIRM_MANAGER, UserRolesEnum.ACCOUNTANT, UserRolesEnum.ADVISOR],
|
|
4497
|
-
ROLE_FIRM_MANAGER: [UserRolesEnum.FIRM_MANAGER, UserRolesEnum.ACCOUNTANT, UserRolesEnum.ADVISOR],
|
|
4498
|
-
ROLE_EMPLOYEE: [UserRolesEnum.ACCOUNTANT, UserRolesEnum.ADVISOR],
|
|
4499
|
-
ROLE_ACCOUNTANT: [UserRolesEnum.ACCOUNTANT],
|
|
4500
|
-
ROLE_ADVISOR: [UserRolesEnum.ADVISOR],
|
|
4501
|
-
ROLE_CLIENT: [UserRolesEnum.CLIENT],
|
|
4502
|
-
ROLE_USER_SUBSCRIPTION: [UserRolesEnum.SUBSCRIPTION],
|
|
4503
|
-
ROLE_USER_WORK: [UserRolesEnum.WORK_TANK],
|
|
4504
|
-
ROLE_USER_PROPERTY: [UserRolesEnum.PROPERTY_TANK],
|
|
4505
|
-
ROLE_USER_SOLE: [UserRolesEnum.SOLE_TANK],
|
|
4506
|
-
};
|
|
4201
|
+
class DepreciationForecast$1 extends AbstractModel {
|
|
4202
|
+
}
|
|
4507
4203
|
|
|
4508
|
-
class
|
|
4509
|
-
get
|
|
4510
|
-
return
|
|
4204
|
+
class DepreciationForecast extends DepreciationForecast$1 {
|
|
4205
|
+
get dailyClaimAmount() {
|
|
4206
|
+
return this.claimAmount / this.daysApplied;
|
|
4511
4207
|
}
|
|
4512
|
-
get
|
|
4513
|
-
return this.
|
|
4208
|
+
get daysApplied() {
|
|
4209
|
+
return moment$1(this.toDate).diff(moment$1(this.fromDate), 'days');
|
|
4514
4210
|
}
|
|
4515
|
-
|
|
4516
|
-
|
|
4211
|
+
getDaysByMonth(month) {
|
|
4212
|
+
// @TODO find a better place
|
|
4213
|
+
const year = this.financialYear - (month > 5 ? 1 : 0);
|
|
4214
|
+
// forecast date intersect by month
|
|
4215
|
+
const range = new DateRange(this.fromDate, this.toDate).intersect(new DateRange(new Date(year, month, 1), new Date(year, month + 1, 0)));
|
|
4216
|
+
return range ? range.duration('days') + 1 : 0;
|
|
4517
4217
|
}
|
|
4518
|
-
|
|
4519
|
-
|
|
4520
|
-
*
|
|
4521
|
-
*/
|
|
4522
|
-
get position() {
|
|
4523
|
-
switch (true) {
|
|
4524
|
-
case this.isFirmOwner():
|
|
4525
|
-
return USER_WORK_POSITION[UserRolesEnum.FIRM_OWNER];
|
|
4526
|
-
case this.isManager():
|
|
4527
|
-
return USER_WORK_POSITION[UserRolesEnum.FIRM_MANAGER];
|
|
4528
|
-
case this.isEmployee():
|
|
4529
|
-
return USER_WORK_POSITION[UserRolesEnum.EMPLOYEE];
|
|
4530
|
-
default:
|
|
4531
|
-
return '';
|
|
4532
|
-
}
|
|
4218
|
+
get claimOpenBalance() {
|
|
4219
|
+
return this.openBalance * this.claimRate;
|
|
4533
4220
|
}
|
|
4534
|
-
|
|
4535
|
-
|
|
4536
|
-
*/
|
|
4537
|
-
hasRoles(roles) {
|
|
4538
|
-
roles = roles instanceof Array ? roles : [roles];
|
|
4539
|
-
if (!roles.length) {
|
|
4540
|
-
return true;
|
|
4541
|
-
}
|
|
4542
|
-
roles = flatten(roles.map((role) => USER_ROLES[role]));
|
|
4543
|
-
return !!intersection(this.roles, roles).length;
|
|
4221
|
+
get claimCloseBalance() {
|
|
4222
|
+
return this.closeBalance * this.claimRate;
|
|
4544
4223
|
}
|
|
4545
|
-
|
|
4546
|
-
return this.
|
|
4224
|
+
get claimAmount() {
|
|
4225
|
+
return this.amount * this.claimRate;
|
|
4547
4226
|
}
|
|
4548
|
-
|
|
4549
|
-
return this.
|
|
4227
|
+
get claimRate() {
|
|
4228
|
+
return this.claimPercent / 100;
|
|
4550
4229
|
}
|
|
4551
|
-
|
|
4552
|
-
return this.
|
|
4230
|
+
getClaimAmountByMonth(month) {
|
|
4231
|
+
return this.getDaysByMonth(month) * this.dailyClaimAmount;
|
|
4553
4232
|
}
|
|
4554
|
-
|
|
4555
|
-
|
|
4233
|
+
}
|
|
4234
|
+
|
|
4235
|
+
/**
|
|
4236
|
+
* Enum with income amount types (Net or Gross)
|
|
4237
|
+
*/
|
|
4238
|
+
var IncomeAmountTypeEnum;
|
|
4239
|
+
(function (IncomeAmountTypeEnum) {
|
|
4240
|
+
IncomeAmountTypeEnum[IncomeAmountTypeEnum["NET"] = 0] = "NET";
|
|
4241
|
+
IncomeAmountTypeEnum[IncomeAmountTypeEnum["GROSS"] = 1] = "GROSS";
|
|
4242
|
+
})(IncomeAmountTypeEnum || (IncomeAmountTypeEnum = {}));
|
|
4243
|
+
|
|
4244
|
+
var TransactionCategoryEnum;
|
|
4245
|
+
(function (TransactionCategoryEnum) {
|
|
4246
|
+
TransactionCategoryEnum[TransactionCategoryEnum["PROPERTY"] = 0] = "PROPERTY";
|
|
4247
|
+
TransactionCategoryEnum[TransactionCategoryEnum["WORK"] = 1] = "WORK";
|
|
4248
|
+
TransactionCategoryEnum[TransactionCategoryEnum["SOLE"] = 2] = "SOLE";
|
|
4249
|
+
TransactionCategoryEnum[TransactionCategoryEnum["PERSONAL"] = 3] = "PERSONAL";
|
|
4250
|
+
})(TransactionCategoryEnum || (TransactionCategoryEnum = {}));
|
|
4251
|
+
|
|
4252
|
+
/**
|
|
4253
|
+
* @TODO Alex: clarify grouping rules and refactor
|
|
4254
|
+
*/
|
|
4255
|
+
class Depreciation extends Depreciation$1 {
|
|
4256
|
+
constructor() {
|
|
4257
|
+
super(...arguments);
|
|
4258
|
+
this.forecasts = [];
|
|
4259
|
+
this.type = DepreciationTypeEnum.PLANT_EQUIPMENT;
|
|
4260
|
+
/**
|
|
4261
|
+
* @TODO remove after ? signs removed from db models
|
|
4262
|
+
*/
|
|
4263
|
+
this.amount = 0;
|
|
4556
4264
|
}
|
|
4557
|
-
|
|
4558
|
-
|
|
4265
|
+
// Type checking
|
|
4266
|
+
isCapital() {
|
|
4267
|
+
return this.type === DepreciationTypeEnum.CAPITAL_WORKS;
|
|
4559
4268
|
}
|
|
4560
|
-
|
|
4561
|
-
return this.
|
|
4269
|
+
isBorrowingExpense() {
|
|
4270
|
+
return this.type === DepreciationTypeEnum.BORROWING_EXPENSES;
|
|
4562
4271
|
}
|
|
4563
|
-
|
|
4564
|
-
return this.
|
|
4272
|
+
isAsset() {
|
|
4273
|
+
return this.type === DepreciationTypeEnum.PLANT_EQUIPMENT;
|
|
4565
4274
|
}
|
|
4566
|
-
|
|
4567
|
-
|
|
4275
|
+
// Calculation checking
|
|
4276
|
+
isSBPCalculation() {
|
|
4277
|
+
return this.calculation === DepreciationCalculationEnum.SBP;
|
|
4568
4278
|
}
|
|
4569
|
-
|
|
4570
|
-
|
|
4571
|
-
*/
|
|
4572
|
-
isFirmOwner() {
|
|
4573
|
-
return this.roles.includes(UserRolesEnum.FIRM_OWNER);
|
|
4279
|
+
isPrimeCost() {
|
|
4280
|
+
return this.calculation === DepreciationCalculationEnum.PRIME_COST;
|
|
4574
4281
|
}
|
|
4575
|
-
|
|
4576
|
-
|
|
4577
|
-
*/
|
|
4578
|
-
isManager() {
|
|
4579
|
-
return this.roles.includes(UserRolesEnum.FIRM_MANAGER) || this.roles.includes(UserRolesEnum.FIRM_OWNER);
|
|
4282
|
+
isDiminishing() {
|
|
4283
|
+
return this.calculation === DepreciationCalculationEnum.DIMINISHING;
|
|
4580
4284
|
}
|
|
4581
|
-
|
|
4582
|
-
|
|
4583
|
-
|
|
4584
|
-
hasPropertyTank() {
|
|
4585
|
-
return this.roles ?
|
|
4586
|
-
this.roles.includes(UserRolesEnum.PROPERTY_TANK) :
|
|
4587
|
-
!!this.getSubscriptionRole(UserRolesEnum.PROPERTY_TANK);
|
|
4285
|
+
// Pool checking
|
|
4286
|
+
isPlantEquipmentPool() {
|
|
4287
|
+
return this.isAsset() && !this.isSBPCalculation() && !this.isWrittenOff() && !this.isLVP();
|
|
4588
4288
|
}
|
|
4589
|
-
|
|
4590
|
-
|
|
4591
|
-
|
|
4592
|
-
|
|
4593
|
-
|
|
4594
|
-
this.
|
|
4595
|
-
|
|
4289
|
+
isLVP() {
|
|
4290
|
+
return this.isAsset()
|
|
4291
|
+
&& !this.isSBPCalculation()
|
|
4292
|
+
&& this.isDiminishing()
|
|
4293
|
+
&& this.currentYearForecast.closeBalance > Depreciation.WRITTEN_OFF_THRESHOLD
|
|
4294
|
+
&& this.currentYearForecast.closeBalance <= Depreciation.LOW_VALUE_POOL_THRESHOLD;
|
|
4295
|
+
}
|
|
4296
|
+
isSBP() {
|
|
4297
|
+
return this.isAsset() && this.isSBPCalculation() && !this.isWrittenOff();
|
|
4298
|
+
}
|
|
4299
|
+
isWrittenOff() {
|
|
4300
|
+
return this.writeOffYear === new FinancialYear().year;
|
|
4301
|
+
}
|
|
4302
|
+
get writeOffYear() {
|
|
4303
|
+
var _a;
|
|
4304
|
+
if (!this.writeOffManualDate && !this.writeOffDate) {
|
|
4305
|
+
return null;
|
|
4306
|
+
}
|
|
4307
|
+
return (_a = new FinancialYear(this.writeOffManualDate || this.writeOffDate)) === null || _a === void 0 ? void 0 : _a.year;
|
|
4596
4308
|
}
|
|
4597
4309
|
/**
|
|
4598
|
-
*
|
|
4599
|
-
* @param roleType by which role should be returned
|
|
4310
|
+
* Check if depreciation chart accounts heading related to vehicles category
|
|
4600
4311
|
*/
|
|
4601
|
-
|
|
4312
|
+
isVehicleDepreciation() {
|
|
4602
4313
|
var _a;
|
|
4603
|
-
|
|
4604
|
-
* Add @TODO for Alex to check if we should use getLastSubscription here
|
|
4605
|
-
*/
|
|
4606
|
-
return (_a = this.activeSubscription) === null || _a === void 0 ? void 0 : _a.items.find((subscriptionItem) => subscriptionItem.price.product.role.includes(roleType));
|
|
4314
|
+
return ((_a = this.chartAccounts.heading) === null || _a === void 0 ? void 0 : _a.id) === ChartAccountsHeadingVehicleListEnum.DEPRECIATION_VEHICLES;
|
|
4607
4315
|
}
|
|
4608
4316
|
/**
|
|
4609
|
-
* Get
|
|
4317
|
+
* Get depreciation purchase date
|
|
4610
4318
|
*/
|
|
4611
|
-
|
|
4612
|
-
return this.
|
|
4319
|
+
getDate() {
|
|
4320
|
+
return this.date;
|
|
4613
4321
|
}
|
|
4614
4322
|
/**
|
|
4615
|
-
*
|
|
4323
|
+
* @TODO Vik: Research a problem with depreciations without current year forecast
|
|
4616
4324
|
*/
|
|
4617
|
-
|
|
4618
|
-
return
|
|
4619
|
-
|
|
4620
|
-
}
|
|
4621
|
-
|
|
4622
|
-
|
|
4623
|
-
|
|
4624
|
-
|
|
4625
|
-
|
|
4626
|
-
|
|
4627
|
-
__decorate([
|
|
4628
|
-
Type(() => EmployeeDetails)
|
|
4629
|
-
], User.prototype, "employeeDetails", void 0);
|
|
4630
|
-
__decorate([
|
|
4631
|
-
Type(() => SoleDetails)
|
|
4632
|
-
], User.prototype, "soleDetails", void 0);
|
|
4633
|
-
__decorate([
|
|
4634
|
-
Type(() => Address)
|
|
4635
|
-
], User.prototype, "address", void 0);
|
|
4636
|
-
__decorate([
|
|
4637
|
-
Type(() => Phone)
|
|
4638
|
-
], User.prototype, "phone", void 0);
|
|
4639
|
-
__decorate([
|
|
4640
|
-
Type(() => Date)
|
|
4641
|
-
], User.prototype, "createdAt", void 0);
|
|
4642
|
-
__decorate([
|
|
4643
|
-
Type(() => User)
|
|
4644
|
-
], User.prototype, "clients", void 0);
|
|
4645
|
-
|
|
4646
|
-
class PropertySubscription extends PropertySubscription$1 {
|
|
4647
|
-
}
|
|
4648
|
-
__decorate([
|
|
4649
|
-
Type(() => Date)
|
|
4650
|
-
], PropertySubscription.prototype, "createdAt", void 0);
|
|
4651
|
-
__decorate([
|
|
4652
|
-
Type(() => User)
|
|
4653
|
-
], PropertySubscription.prototype, "user", void 0);
|
|
4654
|
-
|
|
4655
|
-
class PropertyCategory$1 extends AbstractModel {
|
|
4656
|
-
}
|
|
4657
|
-
|
|
4658
|
-
var PropertyCategoryListEnum;
|
|
4659
|
-
(function (PropertyCategoryListEnum) {
|
|
4660
|
-
PropertyCategoryListEnum[PropertyCategoryListEnum["OWNER_OCCUPIED"] = 3] = "OWNER_OCCUPIED";
|
|
4661
|
-
PropertyCategoryListEnum[PropertyCategoryListEnum["SHARED"] = 4] = "SHARED";
|
|
4662
|
-
PropertyCategoryListEnum[PropertyCategoryListEnum["VACANT_LAND"] = 5] = "VACANT_LAND";
|
|
4663
|
-
})(PropertyCategoryListEnum || (PropertyCategoryListEnum = {}));
|
|
4664
|
-
|
|
4665
|
-
class PropertyCategory extends PropertyCategory$1 {
|
|
4666
|
-
// @Todo check if category is Owner Occupied. If will be needed to check more categories - move the checking to the backend
|
|
4667
|
-
isOwnerOccupied() {
|
|
4668
|
-
return this.id === PropertyCategoryListEnum.OWNER_OCCUPIED;
|
|
4325
|
+
get currentYearForecast() {
|
|
4326
|
+
return this.forecasts.find((forecast) => {
|
|
4327
|
+
return forecast.financialYear === new FinancialYear().year;
|
|
4328
|
+
}) || plainToClass(DepreciationForecast, {
|
|
4329
|
+
financialYear: new FinancialYear().year,
|
|
4330
|
+
openBalance: 0,
|
|
4331
|
+
closeBalance: 0,
|
|
4332
|
+
amount: 0,
|
|
4333
|
+
claimPercent: 0
|
|
4334
|
+
});
|
|
4669
4335
|
}
|
|
4670
|
-
|
|
4671
|
-
return this.
|
|
4336
|
+
getForecastByYear(year) {
|
|
4337
|
+
return this.forecasts.find((forecast) => {
|
|
4338
|
+
return forecast.financialYear === year;
|
|
4339
|
+
});
|
|
4672
4340
|
}
|
|
4673
|
-
|
|
4674
|
-
|
|
4341
|
+
getClaimAmountByYear(year) {
|
|
4342
|
+
var _a;
|
|
4343
|
+
return ((_a = this.getForecastByYear(year)) === null || _a === void 0 ? void 0 : _a.claimAmount) || 0;
|
|
4675
4344
|
}
|
|
4676
|
-
|
|
4677
|
-
|
|
4678
|
-
|
|
4679
|
-
}
|
|
4680
|
-
|
|
4681
|
-
class PropertyDocument$1 extends AbstractModel {
|
|
4682
|
-
getApiUrlPrefix() {
|
|
4683
|
-
return '';
|
|
4345
|
+
getCloseBalanceByYear(year) {
|
|
4346
|
+
var _a;
|
|
4347
|
+
return ((_a = this.getForecastByYear(year)) === null || _a === void 0 ? void 0 : _a.closeBalance) || 0;
|
|
4684
4348
|
}
|
|
4685
|
-
|
|
4686
|
-
return
|
|
4349
|
+
isBuildingAtCost() {
|
|
4350
|
+
return this.chartAccounts.id === ChartAccountsListEnum.BUILDING_AT_COST;
|
|
4687
4351
|
}
|
|
4688
|
-
|
|
4689
|
-
|
|
4690
|
-
|
|
4691
|
-
|
|
4692
|
-
|
|
4693
|
-
|
|
4694
|
-
|
|
4352
|
+
/**
|
|
4353
|
+
* Create a new transaction from current depreciation
|
|
4354
|
+
*/
|
|
4355
|
+
toTransaction(params = {}) {
|
|
4356
|
+
var _a, _b;
|
|
4357
|
+
return plainToClass(Transaction, Object.assign(params, this, {
|
|
4358
|
+
amount: -((_a = this.currentYearForecast) === null || _a === void 0 ? void 0 : _a.amount) || 0,
|
|
4359
|
+
claimAmount: -((_b = this.currentYearForecast) === null || _b === void 0 ? void 0 : _b.claimAmount) || 0,
|
|
4360
|
+
}));
|
|
4695
4361
|
}
|
|
4696
|
-
|
|
4697
|
-
|
|
4362
|
+
/**
|
|
4363
|
+
* @TODO Michael: remove and check everywhere in reports
|
|
4364
|
+
*/
|
|
4365
|
+
get claimAmount() {
|
|
4366
|
+
var _a;
|
|
4367
|
+
return ((_a = this.currentYearForecast) === null || _a === void 0 ? void 0 : _a.claimAmount) || 0;
|
|
4698
4368
|
}
|
|
4699
|
-
|
|
4700
|
-
|
|
4369
|
+
get amountWithGst() {
|
|
4370
|
+
// gst applies only to new assets
|
|
4371
|
+
if (this.isNew()) {
|
|
4372
|
+
return super.amountWithGst;
|
|
4373
|
+
}
|
|
4374
|
+
return this.amount;
|
|
4701
4375
|
}
|
|
4702
|
-
|
|
4703
|
-
|
|
4704
|
-
|
|
4705
|
-
get financialYear() {
|
|
4706
|
-
return new FinancialYear(this.date).year;
|
|
4376
|
+
get gstClaimAmount() {
|
|
4377
|
+
var _a;
|
|
4378
|
+
return this.gstAmount * ((_a = this.currentYearForecast) === null || _a === void 0 ? void 0 : _a.claimRate);
|
|
4707
4379
|
}
|
|
4708
|
-
|
|
4709
|
-
|
|
4380
|
+
/**
|
|
4381
|
+
* assets purchased in the current financial year
|
|
4382
|
+
*/
|
|
4383
|
+
isNew() {
|
|
4384
|
+
return new FinancialYear(this.date).year === new FinancialYear().year;
|
|
4710
4385
|
}
|
|
4711
4386
|
}
|
|
4387
|
+
Depreciation.WRITTEN_OFF_THRESHOLD = 300;
|
|
4388
|
+
Depreciation.LOW_VALUE_POOL_THRESHOLD = 1000;
|
|
4712
4389
|
__decorate([
|
|
4713
4390
|
Type(() => Date)
|
|
4714
|
-
],
|
|
4391
|
+
], Depreciation.prototype, "purchaseDate", void 0);
|
|
4715
4392
|
__decorate([
|
|
4716
|
-
Type(() =>
|
|
4717
|
-
],
|
|
4393
|
+
Type(() => Date)
|
|
4394
|
+
], Depreciation.prototype, "date", void 0);
|
|
4395
|
+
__decorate([
|
|
4396
|
+
Type(() => Date)
|
|
4397
|
+
], Depreciation.prototype, "lowValuePoolDate", void 0);
|
|
4398
|
+
__decorate([
|
|
4399
|
+
Type(() => Date)
|
|
4400
|
+
], Depreciation.prototype, "writeOffManualDate", void 0);
|
|
4401
|
+
__decorate([
|
|
4402
|
+
Type(() => Date)
|
|
4403
|
+
], Depreciation.prototype, "writeOffDate", void 0);
|
|
4404
|
+
__decorate([
|
|
4405
|
+
Type(() => DepreciationCapitalProject)
|
|
4406
|
+
], Depreciation.prototype, "depreciationCapitalProject", void 0);
|
|
4407
|
+
__decorate([
|
|
4408
|
+
Type(() => DepreciationForecast),
|
|
4409
|
+
Transform(({ value, obj }) => {
|
|
4410
|
+
// value = array of DepreciationForecast
|
|
4411
|
+
// obj = plain (whole Depreciation object)
|
|
4412
|
+
// Set isLVP flag for each DepreciationForecast
|
|
4413
|
+
// @TODO refactor
|
|
4414
|
+
value.forEach((forecast) => {
|
|
4415
|
+
forecast.isLVP =
|
|
4416
|
+
forecast.closeBalance < 1000 &&
|
|
4417
|
+
obj.calculation === DepreciationCalculationEnum.DIMINISHING &&
|
|
4418
|
+
obj.type === DepreciationTypeEnum.PLANT_EQUIPMENT &&
|
|
4419
|
+
!(obj.amount > Depreciation.WRITTEN_OFF_THRESHOLD && obj.amount < Depreciation.LOW_VALUE_POOL_THRESHOLD) &&
|
|
4420
|
+
!(obj.writeOffDate && new FinancialYear(new Date(obj.writeOffDate)).year === obj.financialYear);
|
|
4421
|
+
});
|
|
4422
|
+
return value;
|
|
4423
|
+
})
|
|
4424
|
+
], Depreciation.prototype, "forecasts", void 0);
|
|
4425
|
+
__decorate([
|
|
4426
|
+
Type(() => ChartAccounts)
|
|
4427
|
+
], Depreciation.prototype, "chartAccounts", void 0);
|
|
4428
|
+
__decorate([
|
|
4429
|
+
Type(() => BankTransaction)
|
|
4430
|
+
], Depreciation.prototype, "bankTransaction", void 0);
|
|
4718
4431
|
__decorate([
|
|
4719
4432
|
Exclude()
|
|
4720
|
-
],
|
|
4433
|
+
], Depreciation.prototype, "amountWithGst", null);
|
|
4434
|
+
__decorate([
|
|
4435
|
+
Exclude()
|
|
4436
|
+
], Depreciation.prototype, "gstClaimAmount", null);
|
|
4721
4437
|
|
|
4722
|
-
|
|
4438
|
+
/**
|
|
4439
|
+
* used to combine transactions/depreciations
|
|
4440
|
+
*/
|
|
4441
|
+
class TransactionBaseCollection extends Collection {
|
|
4442
|
+
getClaimAmountByBusinessId(businessId) {
|
|
4443
|
+
return +this.filterBy('business.id', businessId).items.map((transaction) => transaction instanceof Depreciation ? -transaction.claimAmount : transaction['claimAmount']).reduce((sum, claimAmount) => sum + claimAmount, 0).toFixed(2);
|
|
4444
|
+
}
|
|
4445
|
+
getSoleTransactions() {
|
|
4446
|
+
return this.filter((transaction) => transaction.isSoleTank());
|
|
4447
|
+
}
|
|
4723
4448
|
}
|
|
4724
4449
|
|
|
4725
|
-
|
|
4450
|
+
// @TODO Alex move here all collections
|
|
4451
|
+
|
|
4452
|
+
// @TODO Alex: refactor: move here allocations methods, netAmount = amount, grossAmount calculation, remove unused methods, etc.
|
|
4453
|
+
class Transaction extends Transaction$1 {
|
|
4726
4454
|
constructor() {
|
|
4727
4455
|
super(...arguments);
|
|
4728
|
-
|
|
4456
|
+
// list of child transactions (fees)
|
|
4457
|
+
this.transactions = [];
|
|
4458
|
+
this.metadata = [];
|
|
4459
|
+
this.allocations = [];
|
|
4460
|
+
this.tax = 0;
|
|
4461
|
+
this.operation = TransactionOperationEnum.FIND_AND_MATCH;
|
|
4462
|
+
this.claimPercent = 100;
|
|
4463
|
+
this.amount = 0;
|
|
4464
|
+
}
|
|
4465
|
+
isDebit() {
|
|
4466
|
+
return this.type === TransactionTypeEnum.DEBIT;
|
|
4467
|
+
}
|
|
4468
|
+
isCredit() {
|
|
4469
|
+
return this.type === TransactionTypeEnum.CREDIT;
|
|
4729
4470
|
}
|
|
4730
4471
|
/**
|
|
4731
|
-
*
|
|
4732
|
-
* Cash Position = Income - Expense - Interest
|
|
4472
|
+
* @TODO move to base collection
|
|
4733
4473
|
*/
|
|
4734
|
-
|
|
4735
|
-
|
|
4474
|
+
isIncome() {
|
|
4475
|
+
// @TODO not used
|
|
4476
|
+
if (!this.chartAccounts) {
|
|
4477
|
+
return this.isCredit();
|
|
4478
|
+
}
|
|
4479
|
+
return CHART_ACCOUNTS_CATEGORIES.income.includes(this.chartAccounts.category);
|
|
4736
4480
|
}
|
|
4737
4481
|
/**
|
|
4738
|
-
*
|
|
4739
|
-
* Tax Position = Income - Expense - Interest - Depreciation
|
|
4482
|
+
* @TODO move to base collection
|
|
4740
4483
|
*/
|
|
4741
|
-
|
|
4742
|
-
|
|
4484
|
+
isExpense() {
|
|
4485
|
+
// @TODO not used
|
|
4486
|
+
if (!this.chartAccounts) {
|
|
4487
|
+
return this.isDebit();
|
|
4488
|
+
}
|
|
4489
|
+
return CHART_ACCOUNTS_CATEGORIES.expense.includes(this.chartAccounts.category);
|
|
4490
|
+
}
|
|
4491
|
+
isPersonal() {
|
|
4492
|
+
return CHART_ACCOUNTS_CATEGORIES.personal.includes(this.chartAccounts.category);
|
|
4493
|
+
}
|
|
4494
|
+
isInterest() {
|
|
4495
|
+
return this.chartAccounts.id === ChartAccountsListEnum.INTEREST_ON_LOAN;
|
|
4496
|
+
}
|
|
4497
|
+
get chartAccountsCategories() {
|
|
4498
|
+
switch (true) {
|
|
4499
|
+
case this.isPersonal():
|
|
4500
|
+
return CHART_ACCOUNTS_CATEGORIES.personal;
|
|
4501
|
+
case this.isPropertyTank():
|
|
4502
|
+
return CHART_ACCOUNTS_CATEGORIES.property;
|
|
4503
|
+
case this.isSoleTank():
|
|
4504
|
+
return CHART_ACCOUNTS_CATEGORIES.sole;
|
|
4505
|
+
default:
|
|
4506
|
+
return CHART_ACCOUNTS_CATEGORIES.work;
|
|
4507
|
+
}
|
|
4743
4508
|
}
|
|
4744
4509
|
/**
|
|
4745
|
-
*
|
|
4746
|
-
* Rental Return = Income / Market Value
|
|
4510
|
+
* Check if transaction has 'Kms travelled for work' chart accounts category
|
|
4747
4511
|
*/
|
|
4748
|
-
get
|
|
4749
|
-
return this.
|
|
4512
|
+
get isKmsChartAccountsCategory() {
|
|
4513
|
+
return this.chartAccounts.id === ChartAccountsListEnum.KLMS_TRAVELLED_FOR_WORK;
|
|
4750
4514
|
}
|
|
4751
4515
|
/**
|
|
4752
|
-
*
|
|
4516
|
+
* Get transaction date
|
|
4753
4517
|
*/
|
|
4754
|
-
|
|
4755
|
-
return this.
|
|
4756
|
-
}
|
|
4757
|
-
}
|
|
4758
|
-
__decorate([
|
|
4759
|
-
Transform(({ value }) => +value)
|
|
4760
|
-
], PropertyForecast.prototype, "income", void 0);
|
|
4761
|
-
__decorate([
|
|
4762
|
-
Transform(({ value }) => -Math.abs(+value))
|
|
4763
|
-
], PropertyForecast.prototype, "expense", void 0);
|
|
4764
|
-
__decorate([
|
|
4765
|
-
Transform(({ value }) => -Math.abs(+value))
|
|
4766
|
-
], PropertyForecast.prototype, "interest", void 0);
|
|
4767
|
-
__decorate([
|
|
4768
|
-
Transform(({ value }) => -Math.abs(+value))
|
|
4769
|
-
], PropertyForecast.prototype, "depreciation", void 0);
|
|
4770
|
-
__decorate([
|
|
4771
|
-
Transform(({ value }) => +value)
|
|
4772
|
-
], PropertyForecast.prototype, "loanBalance", void 0);
|
|
4773
|
-
__decorate([
|
|
4774
|
-
Transform(({ value }) => +value)
|
|
4775
|
-
], PropertyForecast.prototype, "marketValue", void 0);
|
|
4776
|
-
|
|
4777
|
-
class PropertyCategoryMovement$1 extends AbstractModel {
|
|
4778
|
-
}
|
|
4779
|
-
|
|
4780
|
-
class PropertyCategoryMovement extends PropertyCategoryMovement$1 {
|
|
4781
|
-
}
|
|
4782
|
-
__decorate([
|
|
4783
|
-
Type(() => PropertyValuation)
|
|
4784
|
-
], PropertyCategoryMovement.prototype, "valuation", void 0);
|
|
4785
|
-
__decorate([
|
|
4786
|
-
Type(() => PropertyCategory)
|
|
4787
|
-
], PropertyCategoryMovement.prototype, "propertyCategory", void 0);
|
|
4788
|
-
__decorate([
|
|
4789
|
-
Type(() => Date)
|
|
4790
|
-
], PropertyCategoryMovement.prototype, "fromDate", void 0);
|
|
4791
|
-
__decorate([
|
|
4792
|
-
Type(() => Date)
|
|
4793
|
-
], PropertyCategoryMovement.prototype, "toDate", void 0);
|
|
4794
|
-
|
|
4795
|
-
var TaxExemptionEnum;
|
|
4796
|
-
(function (TaxExemptionEnum) {
|
|
4797
|
-
TaxExemptionEnum[TaxExemptionEnum["ONE_YEAR_RULE"] = 1] = "ONE_YEAR_RULE";
|
|
4798
|
-
// principle place of residence
|
|
4799
|
-
TaxExemptionEnum[TaxExemptionEnum["PPR"] = 2] = "PPR";
|
|
4800
|
-
TaxExemptionEnum[TaxExemptionEnum["SIX_YEARS_RULE"] = 3] = "SIX_YEARS_RULE";
|
|
4801
|
-
TaxExemptionEnum[TaxExemptionEnum["INVESTMENT_TO_PPR"] = 4] = "INVESTMENT_TO_PPR";
|
|
4802
|
-
TaxExemptionEnum[TaxExemptionEnum["PPR_TO_INVESTMENT"] = 5] = "PPR_TO_INVESTMENT";
|
|
4803
|
-
TaxExemptionEnum[TaxExemptionEnum["TRANSFER"] = 6] = "TRANSFER";
|
|
4804
|
-
TaxExemptionEnum[TaxExemptionEnum["OTHER"] = 7] = "OTHER";
|
|
4805
|
-
})(TaxExemptionEnum || (TaxExemptionEnum = {}));
|
|
4806
|
-
|
|
4807
|
-
var TaxExemptionMetadataEnum;
|
|
4808
|
-
(function (TaxExemptionMetadataEnum) {
|
|
4809
|
-
// principle place of residence
|
|
4810
|
-
TaxExemptionMetadataEnum[TaxExemptionMetadataEnum["PPR_DAYS"] = 1] = "PPR_DAYS";
|
|
4811
|
-
// market value once it was moved, decimal
|
|
4812
|
-
TaxExemptionMetadataEnum[TaxExemptionMetadataEnum["MARKET_VALUE"] = 2] = "MARKET_VALUE";
|
|
4813
|
-
TaxExemptionMetadataEnum[TaxExemptionMetadataEnum["CLAIM_PERCENT"] = 3] = "CLAIM_PERCENT";
|
|
4814
|
-
})(TaxExemptionMetadataEnum || (TaxExemptionMetadataEnum = {}));
|
|
4815
|
-
|
|
4816
|
-
class PropertySaleTaxExemptionMetadataCollection extends Collection {
|
|
4817
|
-
getPPRDays() {
|
|
4818
|
-
var _a, _b;
|
|
4819
|
-
return (_b = (_a = this.getByMetadataId(TaxExemptionMetadataEnum.PPR_DAYS)) === null || _a === void 0 ? void 0 : _a.value) !== null && _b !== void 0 ? _b : 0;
|
|
4518
|
+
getDate() {
|
|
4519
|
+
return this.date;
|
|
4820
4520
|
}
|
|
4821
|
-
|
|
4822
|
-
|
|
4823
|
-
|
|
4521
|
+
/**
|
|
4522
|
+
* Check if transaction type is vehicle
|
|
4523
|
+
*/
|
|
4524
|
+
isVehicleTransaction() {
|
|
4525
|
+
return this.chartAccounts.isVehicleExpense();
|
|
4824
4526
|
}
|
|
4825
|
-
|
|
4826
|
-
|
|
4827
|
-
return (_b = (_a = this.getByMetadataId(TaxExemptionMetadataEnum.CLAIM_PERCENT)) === null || _a === void 0 ? void 0 : _a.value) !== null && _b !== void 0 ? _b : 100;
|
|
4527
|
+
get taxFreeComponent() {
|
|
4528
|
+
return this.getMetadataFieldValue(ChartAccountsMetadataListEnum.TAX_FREE_COMPONENT);
|
|
4828
4529
|
}
|
|
4829
|
-
|
|
4830
|
-
return this.
|
|
4530
|
+
get frankingCredit() {
|
|
4531
|
+
return this.getMetadataFieldValue(ChartAccountsMetadataListEnum.FRANKING_CREDIT);
|
|
4831
4532
|
}
|
|
4832
|
-
|
|
4833
|
-
|
|
4834
|
-
|
|
4835
|
-
get
|
|
4836
|
-
return this.
|
|
4533
|
+
get eligibleForReduction() {
|
|
4534
|
+
return this.getMetadataFieldValue(ChartAccountsMetadataListEnum.ELIGIBLE_FOR_REDUCTION);
|
|
4535
|
+
}
|
|
4536
|
+
get untaxedElement() {
|
|
4537
|
+
return this.getMetadataFieldValue(ChartAccountsMetadataListEnum.UNTAXED_ELEMENT);
|
|
4837
4538
|
}
|
|
4838
4539
|
/**
|
|
4839
|
-
*
|
|
4540
|
+
* Check if transaction reconcile operation if TRANSFER
|
|
4541
|
+
* @TODO bad usage of get (and all is* methods), getter should sound like a noun
|
|
4840
4542
|
*/
|
|
4841
|
-
|
|
4842
|
-
return this.
|
|
4543
|
+
get isTransfer() {
|
|
4544
|
+
return this.operation === TransactionOperationEnum.TRANSFER;
|
|
4843
4545
|
}
|
|
4844
|
-
|
|
4845
|
-
return this.
|
|
4546
|
+
isFindAndMatch() {
|
|
4547
|
+
return this.operation === TransactionOperationEnum.FIND_AND_MATCH;
|
|
4846
4548
|
}
|
|
4847
|
-
|
|
4848
|
-
|
|
4849
|
-
|
|
4850
|
-
|
|
4851
|
-
|
|
4852
|
-
|
|
4853
|
-
|
|
4854
|
-
|
|
4855
|
-
return new PropertyCollection(this.items.filter((property) => property.category.id === id));
|
|
4549
|
+
isMatchInvoice() {
|
|
4550
|
+
return this.operation === TransactionOperationEnum.MATCH_INVOICE;
|
|
4551
|
+
}
|
|
4552
|
+
get debit() {
|
|
4553
|
+
return this.isDebit() ? Math.abs(this.grossAmount) : 0;
|
|
4554
|
+
}
|
|
4555
|
+
get credit() {
|
|
4556
|
+
return this.isCredit() ? Math.abs(this.grossAmount) : 0;
|
|
4856
4557
|
}
|
|
4857
4558
|
/**
|
|
4858
|
-
* Get
|
|
4559
|
+
* Get value of transaction metadata field
|
|
4560
|
+
* @param field for which value should be returned
|
|
4561
|
+
* @Todo modify 'metadata' property from array to Collection
|
|
4859
4562
|
*/
|
|
4860
|
-
|
|
4861
|
-
|
|
4563
|
+
getMetadataFieldValue(field) {
|
|
4564
|
+
var _a;
|
|
4565
|
+
return +((_a = this.metadata.find((transactionMetadata) => {
|
|
4566
|
+
return transactionMetadata.chartAccountsMetadata.id === field;
|
|
4567
|
+
})) === null || _a === void 0 ? void 0 : _a.value) || 0;
|
|
4862
4568
|
}
|
|
4863
|
-
|
|
4864
|
-
return
|
|
4569
|
+
isCash() {
|
|
4570
|
+
return this.source === TransactionSourceEnum.CASH;
|
|
4865
4571
|
}
|
|
4866
4572
|
/**
|
|
4867
|
-
*
|
|
4573
|
+
* Create Depreciation instance based on Transaction
|
|
4868
4574
|
*/
|
|
4869
|
-
|
|
4870
|
-
return
|
|
4575
|
+
toDepreciation() {
|
|
4576
|
+
return plainToClass(Depreciation, {
|
|
4577
|
+
date: this.date,
|
|
4578
|
+
amount: this.amount,
|
|
4579
|
+
chartAccounts: this.chartAccounts,
|
|
4580
|
+
description: this.description,
|
|
4581
|
+
type: DepreciationTypeEnum.PLANT_EQUIPMENT,
|
|
4582
|
+
claimPercent: this.claimPercent,
|
|
4583
|
+
property: this.property,
|
|
4584
|
+
calculation: this.property ? this.property.depreciationCalculation : DepreciationCalculationEnum.PRIME_COST
|
|
4585
|
+
});
|
|
4871
4586
|
}
|
|
4872
4587
|
/**
|
|
4873
|
-
*
|
|
4588
|
+
* Check if transaction is completely allocated
|
|
4874
4589
|
*/
|
|
4875
|
-
|
|
4876
|
-
return this.
|
|
4590
|
+
isAllocated(allocations) {
|
|
4591
|
+
return this.netAmount === this.getAllocatedAmount(allocations);
|
|
4877
4592
|
}
|
|
4878
|
-
|
|
4879
|
-
return
|
|
4593
|
+
getAllocatedAmount(allocations) {
|
|
4594
|
+
return allocations.filterBy('transaction.id', this.id).sumBy('amount');
|
|
4595
|
+
}
|
|
4596
|
+
getAllocatedClaimAmount(allocations) {
|
|
4597
|
+
return this.getAllocatedAmount(allocations) * this.claimRatio;
|
|
4598
|
+
}
|
|
4599
|
+
getUnallocatedAmount(allocations) {
|
|
4600
|
+
return this.netAmount - this.getAllocatedAmount(allocations);
|
|
4880
4601
|
}
|
|
4881
4602
|
/**
|
|
4882
|
-
*
|
|
4603
|
+
* Total transaction amount including taxes and other additional amounts
|
|
4883
4604
|
*/
|
|
4884
|
-
get
|
|
4885
|
-
|
|
4605
|
+
get grossAmount() {
|
|
4606
|
+
let grossAmount = super.grossAmount + this.tax;
|
|
4607
|
+
if (this.isExpense()) {
|
|
4608
|
+
return grossAmount;
|
|
4609
|
+
}
|
|
4610
|
+
// salary included transactions affect parent transaction amount and as a result grossAmount, skip to avoid double sum
|
|
4611
|
+
grossAmount += new Collection(this.transactions)
|
|
4612
|
+
.filter((t) => { var _a; return !((_a = t.chartAccounts) === null || _a === void 0 ? void 0 : _a.isSalaryIncluded()); })
|
|
4613
|
+
.sumBy('amount');
|
|
4614
|
+
if (this.isWorkTank()) {
|
|
4615
|
+
grossAmount += this.frankingCredit - this.taxFreeComponent - this.eligibleForReduction;
|
|
4616
|
+
}
|
|
4617
|
+
return +(Math.round(grossAmount * 100) / 100).toFixed(2);
|
|
4886
4618
|
}
|
|
4887
|
-
|
|
4888
|
-
|
|
4619
|
+
/**
|
|
4620
|
+
* netAmount matches received payment (bankTransaction amount), includes gst and salary included adjustments
|
|
4621
|
+
* ie user received 1000$ salary including 100$ tips. NetAmount=1000$, amount=900$, tips=100$
|
|
4622
|
+
*/
|
|
4623
|
+
get netAmount() {
|
|
4624
|
+
return new Collection(this.transactions)
|
|
4625
|
+
.filter((t) => { var _a; return (_a = t.chartAccounts) === null || _a === void 0 ? void 0 : _a.isSalaryIncluded(); })
|
|
4626
|
+
.sumBy('amount') + this.amountWithGst;
|
|
4889
4627
|
}
|
|
4890
|
-
|
|
4891
|
-
|
|
4628
|
+
}
|
|
4629
|
+
__decorate([
|
|
4630
|
+
Type(() => Transaction)
|
|
4631
|
+
], Transaction.prototype, "transactions", void 0);
|
|
4632
|
+
__decorate([
|
|
4633
|
+
Type(() => Property)
|
|
4634
|
+
], Transaction.prototype, "property", void 0);
|
|
4635
|
+
__decorate([
|
|
4636
|
+
Type(() => TransactionReceipt)
|
|
4637
|
+
], Transaction.prototype, "receipt", void 0);
|
|
4638
|
+
__decorate([
|
|
4639
|
+
Type(() => ChartAccounts)
|
|
4640
|
+
], Transaction.prototype, "chartAccounts", void 0);
|
|
4641
|
+
__decorate([
|
|
4642
|
+
Type(() => IncomeSource)
|
|
4643
|
+
], Transaction.prototype, "incomeSource", void 0);
|
|
4644
|
+
__decorate([
|
|
4645
|
+
Type(() => TransactionMetadata)
|
|
4646
|
+
], Transaction.prototype, "metadata", void 0);
|
|
4647
|
+
__decorate([
|
|
4648
|
+
Type(() => Transaction)
|
|
4649
|
+
], Transaction.prototype, "transfer", void 0);
|
|
4650
|
+
__decorate([
|
|
4651
|
+
Type(() => Loan)
|
|
4652
|
+
], Transaction.prototype, "loan", void 0);
|
|
4653
|
+
__decorate([
|
|
4654
|
+
Type(() => Date)
|
|
4655
|
+
], Transaction.prototype, "date", void 0);
|
|
4656
|
+
__decorate([
|
|
4657
|
+
Type(() => TransactionAllocation)
|
|
4658
|
+
], Transaction.prototype, "allocations", void 0);
|
|
4659
|
+
|
|
4660
|
+
class SoleInvoiceItem extends SoleInvoiceItem$1 {
|
|
4661
|
+
constructor() {
|
|
4662
|
+
super(...arguments);
|
|
4663
|
+
this.isGST = false;
|
|
4892
4664
|
}
|
|
4893
|
-
get
|
|
4894
|
-
return this.
|
|
4895
|
-
const current = property.firstForecastYear;
|
|
4896
|
-
return min > current ? current : min;
|
|
4897
|
-
}, new FinancialYear().year);
|
|
4665
|
+
get totalPrice() {
|
|
4666
|
+
return this.price * this.quantity;
|
|
4898
4667
|
}
|
|
4899
|
-
|
|
4900
|
-
|
|
4668
|
+
}
|
|
4669
|
+
__decorate([
|
|
4670
|
+
Type(() => SoleInvoice)
|
|
4671
|
+
], SoleInvoiceItem.prototype, "invoice", void 0);
|
|
4672
|
+
__decorate([
|
|
4673
|
+
Type(() => ChartAccounts)
|
|
4674
|
+
], SoleInvoiceItem.prototype, "chartAccounts", void 0);
|
|
4675
|
+
__decorate([
|
|
4676
|
+
Type(() => Transaction)
|
|
4677
|
+
], SoleInvoiceItem.prototype, "transaction", void 0);
|
|
4678
|
+
|
|
4679
|
+
class SoleContact$1 extends AbstractModel {
|
|
4680
|
+
}
|
|
4681
|
+
|
|
4682
|
+
// @TODO Alex/Vik: Create some base class for User and SoleContact with common methods and properties
|
|
4683
|
+
class SoleContact extends SoleContact$1 {
|
|
4684
|
+
get fullName() {
|
|
4685
|
+
return `${this.firstName} ${this.lastName}`;
|
|
4901
4686
|
}
|
|
4902
|
-
|
|
4903
|
-
|
|
4904
|
-
*/
|
|
4905
|
-
getCGTApplicable() {
|
|
4906
|
-
return this.create(this.items.filter((property) => property.isCGTApplicable()));
|
|
4687
|
+
getPhotoPlaceholder() {
|
|
4688
|
+
return `${this.firstName[0].toUpperCase()}${this.lastName[0].toUpperCase()}`;
|
|
4907
4689
|
}
|
|
4908
|
-
|
|
4909
|
-
|
|
4690
|
+
// @TODO Vik: add photo field to SoleContact
|
|
4691
|
+
getPhoto() {
|
|
4692
|
+
return '';
|
|
4910
4693
|
}
|
|
4911
|
-
|
|
4912
|
-
|
|
4913
|
-
|
|
4914
|
-
|
|
4694
|
+
}
|
|
4695
|
+
__decorate([
|
|
4696
|
+
Type(() => User)
|
|
4697
|
+
], SoleContact.prototype, "user", void 0);
|
|
4698
|
+
__decorate([
|
|
4699
|
+
Type(() => Phone)
|
|
4700
|
+
], SoleContact.prototype, "phone", void 0);
|
|
4701
|
+
__decorate([
|
|
4702
|
+
Type(() => Address)
|
|
4703
|
+
], SoleContact.prototype, "address", void 0);
|
|
4704
|
+
__decorate([
|
|
4705
|
+
Type(() => SoleInvoice)
|
|
4706
|
+
], SoleContact.prototype, "invoices", void 0);
|
|
4707
|
+
|
|
4708
|
+
class SoleInvoiceTemplate$1 extends AbstractModel {
|
|
4709
|
+
}
|
|
4710
|
+
|
|
4711
|
+
var SoleInvoiceTemplateTaxTypeEnum;
|
|
4712
|
+
(function (SoleInvoiceTemplateTaxTypeEnum) {
|
|
4713
|
+
SoleInvoiceTemplateTaxTypeEnum[SoleInvoiceTemplateTaxTypeEnum["TAX_EXCLUSIVE"] = 0] = "TAX_EXCLUSIVE";
|
|
4714
|
+
SoleInvoiceTemplateTaxTypeEnum[SoleInvoiceTemplateTaxTypeEnum["TAX_INCLUSIVE"] = 1] = "TAX_INCLUSIVE";
|
|
4715
|
+
SoleInvoiceTemplateTaxTypeEnum[SoleInvoiceTemplateTaxTypeEnum["NO_TAX"] = 2] = "NO_TAX";
|
|
4716
|
+
})(SoleInvoiceTemplateTaxTypeEnum || (SoleInvoiceTemplateTaxTypeEnum = {}));
|
|
4717
|
+
|
|
4718
|
+
class SoleInvoiceTemplate extends SoleInvoiceTemplate$1 {
|
|
4719
|
+
constructor() {
|
|
4720
|
+
super(...arguments);
|
|
4721
|
+
/**
|
|
4722
|
+
* Affects to SoleInvoiceItem.isGST flag availability.
|
|
4723
|
+
* When NONE: isGST is unavailable
|
|
4724
|
+
* When EXCLUSIVE: GST amount added additionaly to invoice total price
|
|
4725
|
+
* When INCLUSIVE: GST amount is already included to invoice total price
|
|
4726
|
+
*/
|
|
4727
|
+
this.taxType = SoleInvoiceTemplateTaxTypeEnum.NO_TAX;
|
|
4915
4728
|
}
|
|
4916
4729
|
/**
|
|
4917
|
-
* Get
|
|
4730
|
+
* Get term duration in milliseconds
|
|
4918
4731
|
*/
|
|
4919
|
-
|
|
4920
|
-
return
|
|
4732
|
+
get termTime() {
|
|
4733
|
+
return this.term * 24 * 3600 * 1000;
|
|
4734
|
+
}
|
|
4735
|
+
}
|
|
4736
|
+
__decorate([
|
|
4737
|
+
Type(() => SoleBusiness)
|
|
4738
|
+
], SoleInvoiceTemplate.prototype, "business", void 0);
|
|
4739
|
+
__decorate([
|
|
4740
|
+
Type(() => BankAccount)
|
|
4741
|
+
], SoleInvoiceTemplate.prototype, "bankAccount", void 0);
|
|
4742
|
+
|
|
4743
|
+
var SoleInvoiceStatusesEnum;
|
|
4744
|
+
(function (SoleInvoiceStatusesEnum) {
|
|
4745
|
+
SoleInvoiceStatusesEnum[SoleInvoiceStatusesEnum["CANCELED"] = 0] = "CANCELED";
|
|
4746
|
+
SoleInvoiceStatusesEnum[SoleInvoiceStatusesEnum["DRAFT"] = 1] = "DRAFT";
|
|
4747
|
+
SoleInvoiceStatusesEnum[SoleInvoiceStatusesEnum["PENDING"] = 2] = "PENDING";
|
|
4748
|
+
SoleInvoiceStatusesEnum[SoleInvoiceStatusesEnum["PAID"] = 3] = "PAID";
|
|
4749
|
+
})(SoleInvoiceStatusesEnum || (SoleInvoiceStatusesEnum = {}));
|
|
4750
|
+
|
|
4751
|
+
var SoleInvoiceTaxTypeEnum;
|
|
4752
|
+
(function (SoleInvoiceTaxTypeEnum) {
|
|
4753
|
+
SoleInvoiceTaxTypeEnum[SoleInvoiceTaxTypeEnum["TAX_EXCLUSIVE"] = 0] = "TAX_EXCLUSIVE";
|
|
4754
|
+
SoleInvoiceTaxTypeEnum[SoleInvoiceTaxTypeEnum["TAX_INCLUSIVE"] = 1] = "TAX_INCLUSIVE";
|
|
4755
|
+
SoleInvoiceTaxTypeEnum[SoleInvoiceTaxTypeEnum["NO_TAX"] = 2] = "NO_TAX";
|
|
4756
|
+
})(SoleInvoiceTaxTypeEnum || (SoleInvoiceTaxTypeEnum = {}));
|
|
4757
|
+
|
|
4758
|
+
class SoleInvoiceItemCollection extends Collection {
|
|
4759
|
+
get gstPrice() {
|
|
4760
|
+
return this.filterBy('isGST', true).sumBy('totalPrice');
|
|
4761
|
+
}
|
|
4762
|
+
}
|
|
4763
|
+
|
|
4764
|
+
class SoleInvoice extends SoleInvoice$1 {
|
|
4765
|
+
constructor() {
|
|
4766
|
+
super(...arguments);
|
|
4767
|
+
this.status = SoleInvoiceStatusesEnum.DRAFT;
|
|
4768
|
+
this.taxType = SoleInvoiceTaxTypeEnum.NO_TAX;
|
|
4921
4769
|
}
|
|
4922
4770
|
/**
|
|
4923
|
-
* Get
|
|
4771
|
+
* Get items array as collection
|
|
4924
4772
|
*/
|
|
4925
|
-
|
|
4926
|
-
return this.items
|
|
4927
|
-
return max.growthPercent < current.growthPercent ? current : max;
|
|
4928
|
-
}, this.first);
|
|
4773
|
+
get itemsCollection() {
|
|
4774
|
+
return new SoleInvoiceItemCollection(this.items);
|
|
4929
4775
|
}
|
|
4930
4776
|
/**
|
|
4931
|
-
*
|
|
4777
|
+
* Total price of all items
|
|
4932
4778
|
*/
|
|
4933
|
-
|
|
4934
|
-
|
|
4935
|
-
const depreciationsByProperty = depreciations.groupBy('property.id');
|
|
4936
|
-
return this.items.reduce((min, current) => {
|
|
4937
|
-
const minTaxPosition = min.getTaxPosition(transactionsByProperty.get(min.id), depreciationsByProperty.get(min.id));
|
|
4938
|
-
const currentTaxPosition = current.getTaxPosition(transactionsByProperty.get(current.id), depreciationsByProperty.get(current.id));
|
|
4939
|
-
return minTaxPosition > currentTaxPosition ? current : min;
|
|
4940
|
-
}, this.first);
|
|
4779
|
+
get price() {
|
|
4780
|
+
return this.itemsCollection.sumBy('totalPrice');
|
|
4941
4781
|
}
|
|
4942
4782
|
/**
|
|
4943
|
-
*
|
|
4944
|
-
* https://taxtank.atlassian.net/wiki/spaces/TAXTANK/pages/217677997/Property+Tank+Dashboard
|
|
4783
|
+
* Total invoice price without GST
|
|
4945
4784
|
*/
|
|
4946
|
-
|
|
4947
|
-
|
|
4948
|
-
|
|
4949
|
-
if (!activeProperties.length) {
|
|
4950
|
-
return this;
|
|
4785
|
+
get netPrice() {
|
|
4786
|
+
if (this.isTaxInclusive()) {
|
|
4787
|
+
return this.price - this.GSTAmount;
|
|
4951
4788
|
}
|
|
4952
|
-
|
|
4953
|
-
activeProperties.getBestPerformanceGrowthProperty(),
|
|
4954
|
-
activeProperties.getBestPerformanceTaxProperty(transactions, depreciations)
|
|
4955
|
-
]).toArray(), 'id');
|
|
4956
|
-
const newItems = this.remove(bestProperties).toArray();
|
|
4957
|
-
newItems.unshift(...bestProperties);
|
|
4958
|
-
return this.create(newItems);
|
|
4789
|
+
return this.price;
|
|
4959
4790
|
}
|
|
4960
|
-
}
|
|
4961
|
-
|
|
4962
|
-
class PropertyCategoryMovementCollection extends Collection {
|
|
4963
4791
|
/**
|
|
4964
|
-
*
|
|
4792
|
+
* Total final price (net + GST)
|
|
4965
4793
|
*/
|
|
4966
|
-
|
|
4967
|
-
|
|
4968
|
-
|
|
4969
|
-
|
|
4970
|
-
|
|
4971
|
-
}
|
|
4972
|
-
hasCategory(categoryId) {
|
|
4973
|
-
return !!this.findBy('propertyCategory.id', categoryId);
|
|
4794
|
+
get grossPrice() {
|
|
4795
|
+
if (this.isTaxExclusive()) {
|
|
4796
|
+
return this.price + this.GSTAmount;
|
|
4797
|
+
}
|
|
4798
|
+
return this.price;
|
|
4974
4799
|
}
|
|
4975
|
-
}
|
|
4976
|
-
|
|
4977
|
-
class VehicleClaimCollection extends Collection {
|
|
4978
4800
|
/**
|
|
4979
|
-
*
|
|
4801
|
+
* Total GST amount
|
|
4980
4802
|
*/
|
|
4981
|
-
|
|
4982
|
-
|
|
4983
|
-
|
|
4984
|
-
|
|
4803
|
+
get GSTAmount() {
|
|
4804
|
+
switch (this.taxType) {
|
|
4805
|
+
case SoleInvoiceTaxTypeEnum.TAX_INCLUSIVE:
|
|
4806
|
+
return this.inclusiveGSTAmount;
|
|
4807
|
+
case SoleInvoiceTaxTypeEnum.TAX_EXCLUSIVE:
|
|
4808
|
+
return this.exclusiveGSTAmount;
|
|
4809
|
+
case SoleInvoiceTaxTypeEnum.NO_TAX:
|
|
4810
|
+
return 0;
|
|
4985
4811
|
}
|
|
4986
|
-
return VehicleClaim.totalKmsLimit - collection.sumBy('kilometers');
|
|
4987
4812
|
}
|
|
4988
4813
|
/**
|
|
4989
|
-
*
|
|
4814
|
+
* When tax inclusive, GST amount is included to total price
|
|
4990
4815
|
*/
|
|
4991
|
-
|
|
4992
|
-
|
|
4993
|
-
|
|
4994
|
-
collection = collection.removeBy('id', claim.id);
|
|
4995
|
-
}
|
|
4996
|
-
return VehicleClaim.totalWorkUsagePercent - collection.sumBy('workUsage');
|
|
4816
|
+
get inclusiveGSTAmount() {
|
|
4817
|
+
const gstPrice = this.itemsCollection.gstPrice;
|
|
4818
|
+
return +(gstPrice - (gstPrice / (1 + ChartAccounts.GSTRatio))).toFixed(2);
|
|
4997
4819
|
}
|
|
4998
|
-
}
|
|
4999
|
-
|
|
5000
|
-
class VehicleLogbookCollection extends Collection {
|
|
5001
4820
|
/**
|
|
5002
|
-
*
|
|
5003
|
-
* @TODO Vik: Best period: move this and related logic to backend
|
|
4821
|
+
* When tax exclusive, GST amount should be added additionally to total price
|
|
5004
4822
|
*/
|
|
5005
|
-
|
|
5006
|
-
|
|
5007
|
-
|
|
5008
|
-
|
|
5009
|
-
return
|
|
4823
|
+
get exclusiveGSTAmount() {
|
|
4824
|
+
return +(this.itemsCollection.gstPrice * ChartAccounts.GSTRatio).toFixed(2);
|
|
4825
|
+
}
|
|
4826
|
+
isDraft() {
|
|
4827
|
+
return this.status === SoleInvoiceStatusesEnum.DRAFT;
|
|
4828
|
+
}
|
|
4829
|
+
isCancelled() {
|
|
4830
|
+
return this.status === SoleInvoiceStatusesEnum.CANCELED;
|
|
4831
|
+
}
|
|
4832
|
+
isPending() {
|
|
4833
|
+
return this.status === SoleInvoiceStatusesEnum.PENDING;
|
|
4834
|
+
}
|
|
4835
|
+
isPaid() {
|
|
4836
|
+
return this.status === SoleInvoiceStatusesEnum.PAID;
|
|
4837
|
+
}
|
|
4838
|
+
isOverdue() {
|
|
4839
|
+
return this.isPending() && this.dateTo < new Date();
|
|
4840
|
+
}
|
|
4841
|
+
isUnpaid() {
|
|
4842
|
+
return this.isPending() && this.dateTo >= new Date();
|
|
5010
4843
|
}
|
|
5011
4844
|
/**
|
|
5012
|
-
*
|
|
5013
|
-
* @TODO Vik: Best period: move this and related logic to backend
|
|
4845
|
+
* GST is not available for invoices without taxes
|
|
5014
4846
|
*/
|
|
5015
|
-
|
|
5016
|
-
return this.
|
|
4847
|
+
isNoTax() {
|
|
4848
|
+
return this.taxType === SoleInvoiceTaxTypeEnum.NO_TAX;
|
|
5017
4849
|
}
|
|
5018
4850
|
/**
|
|
5019
|
-
*
|
|
5020
|
-
*
|
|
5021
|
-
* @TODO Vik: Best period: move this and related logic to backend
|
|
4851
|
+
* GST amount is not included in items prices for invoices with tax exclusive,
|
|
4852
|
+
* we should add GST amount additionaly to subtotal price to get total price
|
|
5022
4853
|
*/
|
|
5023
|
-
|
|
5024
|
-
|
|
5025
|
-
return null;
|
|
5026
|
-
}
|
|
5027
|
-
let bestPeriod;
|
|
5028
|
-
// get list of all logbooks available for best period calculation
|
|
5029
|
-
const claimableLogbooks = this.getClaimableLogbooks().toArray();
|
|
5030
|
-
for (let i = 0; i < claimableLogbooks.length; i++) {
|
|
5031
|
-
// no sense to check next logbooks because we already get the end of the year
|
|
5032
|
-
if (bestPeriod && bestPeriod.isEndOfYear()) {
|
|
5033
|
-
break;
|
|
5034
|
-
}
|
|
5035
|
-
// get date range started from current handling logbook date
|
|
5036
|
-
const dateRange = claimableLogbooks[i].getPeriod();
|
|
5037
|
-
// get all logbooks included in current logbook period
|
|
5038
|
-
const logbooksInRange = this.filterByRange('date', dateRange.start, dateRange.end);
|
|
5039
|
-
const currentPeriod = plainToClass(LogbookPeriod, {
|
|
5040
|
-
from: dateRange.start,
|
|
5041
|
-
to: dateRange.end,
|
|
5042
|
-
kilometers: logbooksInRange.getClaimableLogbooks().kilometers,
|
|
5043
|
-
workUsage: logbooksInRange.getWorkUsage(),
|
|
5044
|
-
logbooks: logbooksInRange
|
|
5045
|
-
});
|
|
5046
|
-
// compare with previous best period and overwrite if needs
|
|
5047
|
-
if (!bestPeriod || currentPeriod.workUsage > bestPeriod.workUsage) {
|
|
5048
|
-
bestPeriod = currentPeriod;
|
|
5049
|
-
}
|
|
5050
|
-
else if (currentPeriod.workUsage === bestPeriod.workUsage) {
|
|
5051
|
-
// if work usage is the same then get period with the biggest work usage for work tank
|
|
5052
|
-
const oldWorkUsage = bestPeriod.logbooks.filterBy('tankType', TankTypeEnum.WORK).getWorkUsage();
|
|
5053
|
-
const currentWorkUsage = currentPeriod.logbooks.filterBy('tankType', TankTypeEnum.WORK).getWorkUsage();
|
|
5054
|
-
if (oldWorkUsage < currentWorkUsage) {
|
|
5055
|
-
bestPeriod = currentPeriod;
|
|
5056
|
-
}
|
|
5057
|
-
}
|
|
5058
|
-
}
|
|
5059
|
-
return bestPeriod;
|
|
4854
|
+
isTaxExclusive() {
|
|
4855
|
+
return this.taxType === SoleInvoiceTaxTypeEnum.TAX_EXCLUSIVE;
|
|
5060
4856
|
}
|
|
5061
4857
|
/**
|
|
5062
|
-
*
|
|
4858
|
+
* GST amount already included in items prices for invoices with tax inclusive,
|
|
4859
|
+
* we should subtract GST amount from total price to get subtotal price
|
|
5063
4860
|
*/
|
|
4861
|
+
isTaxInclusive() {
|
|
4862
|
+
return this.taxType === SoleInvoiceTaxTypeEnum.TAX_INCLUSIVE;
|
|
4863
|
+
}
|
|
4864
|
+
getNumber() {
|
|
4865
|
+
return String(this.number).padStart(SoleInvoice.NUMBER_LENGTH, '0');
|
|
4866
|
+
}
|
|
4867
|
+
get name() {
|
|
4868
|
+
return `invoice-${this.getNumber()}.pdf`;
|
|
4869
|
+
}
|
|
4870
|
+
getTransactionsIds() {
|
|
4871
|
+
return new Collection(this.items).mapBy('transaction.id');
|
|
4872
|
+
this.items.map((item) => item.transaction.id);
|
|
4873
|
+
}
|
|
4874
|
+
}
|
|
4875
|
+
SoleInvoice.NUMBER_LENGTH = 4;
|
|
4876
|
+
__decorate([
|
|
4877
|
+
Type(() => Date)
|
|
4878
|
+
], SoleInvoice.prototype, "dateFrom", void 0);
|
|
4879
|
+
__decorate([
|
|
4880
|
+
Type(() => Date)
|
|
4881
|
+
], SoleInvoice.prototype, "dateTo", void 0);
|
|
4882
|
+
__decorate([
|
|
4883
|
+
Type(() => User)
|
|
4884
|
+
], SoleInvoice.prototype, "user", void 0);
|
|
4885
|
+
__decorate([
|
|
4886
|
+
Type(() => SoleBusiness)
|
|
4887
|
+
], SoleInvoice.prototype, "business", void 0);
|
|
4888
|
+
__decorate([
|
|
4889
|
+
Type(() => SoleInvoiceItem)
|
|
4890
|
+
], SoleInvoice.prototype, "items", void 0);
|
|
4891
|
+
__decorate([
|
|
4892
|
+
Type(() => SoleContact)
|
|
4893
|
+
], SoleInvoice.prototype, "payer", void 0);
|
|
4894
|
+
__decorate([
|
|
4895
|
+
Type(() => SoleInvoiceTemplate)
|
|
4896
|
+
], SoleInvoice.prototype, "template", void 0);
|
|
4897
|
+
__decorate([
|
|
4898
|
+
Type(() => BankAccount)
|
|
4899
|
+
], SoleInvoice.prototype, "bankAccount", void 0);
|
|
4900
|
+
|
|
4901
|
+
/**
|
|
4902
|
+
* Class contains traveled kilometers and work usage percent in 12 weeks date range
|
|
4903
|
+
* @TODO Vik: Best period: move this and related logic to backend
|
|
4904
|
+
* @TODO Alex: check if we need this class when calculation refactored with backend
|
|
4905
|
+
*/
|
|
4906
|
+
class LogbookPeriod {
|
|
4907
|
+
isEndOfYear() {
|
|
4908
|
+
return this.to === new FinancialYear().endDate;
|
|
4909
|
+
}
|
|
4910
|
+
getWorkUsageByClaim(claim) {
|
|
4911
|
+
const claimKilometers = this.logbooks.getByVehicleClaim(claim).getClaimableLogbooks().kilometers;
|
|
4912
|
+
return Math.round(this.workUsage * (claimKilometers / this.kilometers));
|
|
4913
|
+
}
|
|
4914
|
+
}
|
|
4915
|
+
__decorate([
|
|
4916
|
+
Type(() => Date)
|
|
4917
|
+
], LogbookPeriod.prototype, "from", void 0);
|
|
4918
|
+
__decorate([
|
|
4919
|
+
Type(() => Date)
|
|
4920
|
+
], LogbookPeriod.prototype, "to", void 0);
|
|
4921
|
+
|
|
4922
|
+
class Vehicle$1 extends AbstractModel {
|
|
4923
|
+
}
|
|
4924
|
+
|
|
4925
|
+
class VehicleLogbook$1 extends AbstractModel {
|
|
4926
|
+
}
|
|
4927
|
+
|
|
4928
|
+
// problem with DateRange and typescript. See more https://github.com/rotaready/moment-range/issues/263
|
|
4929
|
+
const moment = extendMoment(moment$1);
|
|
4930
|
+
class VehicleLogbook extends VehicleLogbook$1 {
|
|
5064
4931
|
get kilometers() {
|
|
5065
|
-
return this.
|
|
4932
|
+
return this.odometerEnd - this.odometerStart;
|
|
4933
|
+
}
|
|
4934
|
+
get tankType() {
|
|
4935
|
+
return this.isSoleTank() ? TankTypeEnum.SOLE : TankTypeEnum.WORK;
|
|
4936
|
+
}
|
|
4937
|
+
isWorkTank() {
|
|
4938
|
+
return !this.business;
|
|
5066
4939
|
}
|
|
5067
|
-
|
|
5068
|
-
|
|
5069
|
-
* @TODO Alex: TT-2089 replace with getter
|
|
5070
|
-
*/
|
|
5071
|
-
getWorkUsage() {
|
|
5072
|
-
const workKilometers = this.getClaimableLogbooks().kilometers;
|
|
5073
|
-
return Math.round(workKilometers / this.kilometers * 100);
|
|
4940
|
+
isSoleTank() {
|
|
4941
|
+
return !!this.business;
|
|
5074
4942
|
}
|
|
5075
4943
|
/**
|
|
5076
|
-
* Get
|
|
4944
|
+
* Get logbook period date range from logbook date and weeksInPeriod duration
|
|
5077
4945
|
*/
|
|
5078
|
-
|
|
5079
|
-
return
|
|
5080
|
-
// sole tank may have multiple vehicle claims, so we need to filter by business.id
|
|
5081
|
-
? this.filterBy('business.id', vehicleClaim.business.id)
|
|
5082
|
-
// work tank may have only one vehicle claim, so we need to filter by tank type
|
|
5083
|
-
: this.filterBy('tankType', TankTypeEnum.WORK);
|
|
4946
|
+
getPeriod() {
|
|
4947
|
+
return moment.rangeFromInterval('milliseconds', VehicleLogbook.bestPeriodDuration, this.date);
|
|
5084
4948
|
}
|
|
5085
4949
|
}
|
|
5086
|
-
|
|
5087
4950
|
/**
|
|
5088
|
-
*
|
|
4951
|
+
* Logbook period duration in milliseconds.
|
|
4952
|
+
* https://taxtank.atlassian.net/wiki/spaces/TAXTANK/pages/211517441/Logbook+Vehicle
|
|
5089
4953
|
*/
|
|
5090
|
-
|
|
5091
|
-
|
|
5092
|
-
|
|
5093
|
-
|
|
5094
|
-
|
|
5095
|
-
|
|
5096
|
-
|
|
5097
|
-
|
|
5098
|
-
|
|
5099
|
-
|
|
5100
|
-
|
|
5101
|
-
|
|
5102
|
-
|
|
5103
|
-
|
|
4954
|
+
VehicleLogbook.bestPeriodDuration = 12 * 7 * 24 * 3600 * 1000;
|
|
4955
|
+
__decorate([
|
|
4956
|
+
Type(() => Date)
|
|
4957
|
+
], VehicleLogbook.prototype, "date", void 0);
|
|
4958
|
+
__decorate([
|
|
4959
|
+
Type(() => SoleBusiness)
|
|
4960
|
+
], VehicleLogbook.prototype, "business", void 0);
|
|
4961
|
+
|
|
4962
|
+
class Vehicle extends Vehicle$1 {
|
|
4963
|
+
}
|
|
4964
|
+
__decorate([
|
|
4965
|
+
Type(() => VehicleLogbook)
|
|
4966
|
+
], Vehicle.prototype, "logbook", void 0);
|
|
4967
|
+
|
|
4968
|
+
class VehicleClaim$1 extends AbstractModel {
|
|
4969
|
+
}
|
|
4970
|
+
|
|
4971
|
+
class VehicleClaimDetails$1 extends AbstractModel {
|
|
4972
|
+
}
|
|
4973
|
+
|
|
4974
|
+
var VehicleClaimDetailsMethodEnum;
|
|
4975
|
+
(function (VehicleClaimDetailsMethodEnum) {
|
|
4976
|
+
VehicleClaimDetailsMethodEnum[VehicleClaimDetailsMethodEnum["KMS"] = 1] = "KMS";
|
|
4977
|
+
VehicleClaimDetailsMethodEnum[VehicleClaimDetailsMethodEnum["LOGBOOK"] = 2] = "LOGBOOK";
|
|
4978
|
+
})(VehicleClaimDetailsMethodEnum || (VehicleClaimDetailsMethodEnum = {}));
|
|
4979
|
+
|
|
4980
|
+
class VehicleClaimDetails extends VehicleClaimDetails$1 {
|
|
4981
|
+
constructor() {
|
|
4982
|
+
super(...arguments);
|
|
4983
|
+
/**
|
|
4984
|
+
* Init default values for the new instances
|
|
4985
|
+
*/
|
|
4986
|
+
this.isManual = true;
|
|
4987
|
+
this.method = VehicleClaimDetailsMethodEnum.KMS;
|
|
4988
|
+
this.financialYear = new FinancialYear().year;
|
|
5104
4989
|
}
|
|
5105
|
-
|
|
5106
|
-
return this.
|
|
4990
|
+
isLogbookMethod() {
|
|
4991
|
+
return this.method === VehicleClaimDetailsMethodEnum.LOGBOOK;
|
|
5107
4992
|
}
|
|
5108
|
-
|
|
5109
|
-
|
|
5110
|
-
let key = get(item, path);
|
|
5111
|
-
// if object does not have property for grouping it will be grouped as 'other'
|
|
5112
|
-
if (key === undefined) {
|
|
5113
|
-
key = 'other';
|
|
5114
|
-
}
|
|
5115
|
-
this.items[key] = item;
|
|
5116
|
-
});
|
|
4993
|
+
isKmsMethod() {
|
|
4994
|
+
return this.method === VehicleClaimDetailsMethodEnum.KMS;
|
|
5117
4995
|
}
|
|
5118
4996
|
}
|
|
4997
|
+
__decorate([
|
|
4998
|
+
Type(() => User)
|
|
4999
|
+
], VehicleClaimDetails.prototype, "user", void 0);
|
|
5119
5000
|
|
|
5120
|
-
class
|
|
5001
|
+
class VehicleClaim extends VehicleClaim$1 {
|
|
5002
|
+
constructor() {
|
|
5003
|
+
super(...arguments);
|
|
5004
|
+
this.kilometers = 0;
|
|
5005
|
+
this.workUsage = 0;
|
|
5006
|
+
}
|
|
5007
|
+
isWorkTank() {
|
|
5008
|
+
return !this.business;
|
|
5009
|
+
}
|
|
5010
|
+
isSoleTank() {
|
|
5011
|
+
return !!this.business;
|
|
5012
|
+
}
|
|
5013
|
+
get tankType() {
|
|
5014
|
+
return this.isSoleTank() ? TankTypeEnum.SOLE : TankTypeEnum.WORK;
|
|
5015
|
+
}
|
|
5121
5016
|
/**
|
|
5122
|
-
*
|
|
5017
|
+
* Claim amount for KMs method. Exists only for KMs method.
|
|
5123
5018
|
*/
|
|
5124
|
-
|
|
5125
|
-
|
|
5126
|
-
const claimAmountsByBusinessId = this.getClaimAmountsByBusinessId(transactions);
|
|
5127
|
-
return Object.keys(claimAmountsByBusinessId.items).reduce((sum, businessId) => {
|
|
5128
|
-
const loss = this.findBy('business.id', +businessId);
|
|
5129
|
-
const lossOpenBalance = (loss === null || loss === void 0 ? void 0 : loss.openBalance) || 0;
|
|
5130
|
-
// business loss can be applied to business profit or other income types profit in case in offset rule met
|
|
5131
|
-
return sum + ((loss === null || loss === void 0 ? void 0 : loss.offsetRule) ? lossOpenBalance : Math.min(lossOpenBalance, claimAmountsByBusinessId.get(businessId)));
|
|
5132
|
-
}, 0);
|
|
5019
|
+
getKMSClaimAmount(vehicleClaimRate) {
|
|
5020
|
+
return +(this.kilometers * vehicleClaimRate).toFixed(2);
|
|
5133
5021
|
}
|
|
5134
5022
|
/**
|
|
5135
|
-
* Get
|
|
5136
|
-
*
|
|
5137
|
-
* https://www.ato.gov.au/Business/Non-commercial-losses/
|
|
5023
|
+
* Get logbook claim amount. Exists only for logbook method.
|
|
5024
|
+
* ClaimAmount = WorkUsage * transaction/depreciation amount
|
|
5138
5025
|
*/
|
|
5139
|
-
|
|
5140
|
-
const
|
|
5141
|
-
|
|
5142
|
-
|
|
5143
|
-
|
|
5144
|
-
|
|
5145
|
-
|
|
5146
|
-
const businessClaimAmount = transactionsByBusinessId
|
|
5147
|
-
.get(businessId)
|
|
5148
|
-
.getClaimAmountByBusinessId(+businessId);
|
|
5149
|
-
// no way to apply loss for business without profit if offset rules not met
|
|
5150
|
-
if (businessClaimAmount < 0 && !lossOffsetRule) {
|
|
5151
|
-
return;
|
|
5152
|
-
}
|
|
5153
|
-
claimAmountsByBusinessId.add(businessId, businessClaimAmount);
|
|
5154
|
-
});
|
|
5155
|
-
return claimAmountsByBusinessId;
|
|
5156
|
-
}
|
|
5157
|
-
}
|
|
5158
|
-
|
|
5159
|
-
class SoleInvoiceCollection extends Collection {
|
|
5160
|
-
getOverdue() {
|
|
5161
|
-
return this.filter((invoice) => invoice.isOverdue());
|
|
5162
|
-
}
|
|
5163
|
-
getUnpaid() {
|
|
5164
|
-
return this.filter((invoice) => invoice.isUnpaid());
|
|
5165
|
-
}
|
|
5166
|
-
getPaid() {
|
|
5167
|
-
return this.filter((invoice) => invoice.isPaid());
|
|
5026
|
+
getLogbookClaimAmount(transactions) {
|
|
5027
|
+
const transactionsAmount = transactions
|
|
5028
|
+
.getByVehicleClaim(this)
|
|
5029
|
+
.getLogbookTransactions()
|
|
5030
|
+
.sumBy('amount');
|
|
5031
|
+
// Math.abs because amount will be negative (because we sum expenses), but we don't want negative percent value
|
|
5032
|
+
return Math.abs(transactionsAmount) * this.workUsage / 100;
|
|
5168
5033
|
}
|
|
5169
|
-
|
|
5170
|
-
return this.
|
|
5034
|
+
getAverageWeeklyKMS() {
|
|
5035
|
+
return this.kilometers / FinancialYear.weeksInYear;
|
|
5171
5036
|
}
|
|
5172
|
-
|
|
5173
|
-
return
|
|
5037
|
+
static getKMSChartAccountsIdByTankType(tankType) {
|
|
5038
|
+
return tankType === TankTypeEnum.WORK
|
|
5039
|
+
? ChartAccountsListEnum.KLMS_TRAVELLED_FOR_WORK
|
|
5040
|
+
: ChartAccountsListEnum.KLMS_TRAVELLED;
|
|
5174
5041
|
}
|
|
5175
5042
|
}
|
|
5176
|
-
|
|
5177
5043
|
/**
|
|
5178
|
-
*
|
|
5179
|
-
* @TODO consider rename to ChartSerieData
|
|
5044
|
+
* limit for kms claim method
|
|
5180
5045
|
*/
|
|
5181
|
-
|
|
5046
|
+
VehicleClaim.totalKmsLimit = 5000;
|
|
5047
|
+
/**
|
|
5048
|
+
* limit for work usage claim method
|
|
5049
|
+
*/
|
|
5050
|
+
VehicleClaim.totalWorkUsagePercent = 100;
|
|
5051
|
+
__decorate([
|
|
5052
|
+
Type(() => VehicleClaimDetails)
|
|
5053
|
+
], VehicleClaim.prototype, "details", void 0);
|
|
5054
|
+
__decorate([
|
|
5055
|
+
Type(() => SoleBusiness)
|
|
5056
|
+
], VehicleClaim.prototype, "business", void 0);
|
|
5057
|
+
|
|
5058
|
+
class SoleBusinessActivity$1 extends AbstractModel {
|
|
5182
5059
|
}
|
|
5183
5060
|
|
|
5061
|
+
class SoleBusiness extends SoleBusiness$1 {
|
|
5062
|
+
getPhotoPlaceholder() {
|
|
5063
|
+
return `${this.name[0]}${this.name[1]}`;
|
|
5064
|
+
}
|
|
5065
|
+
getPhoto() {
|
|
5066
|
+
return this.logo;
|
|
5067
|
+
}
|
|
5068
|
+
}
|
|
5184
5069
|
/**
|
|
5185
|
-
*
|
|
5186
|
-
* @TODO consider rename to ChartSerie
|
|
5070
|
+
* Maximum number of businesses that a person can have, according to the ATO
|
|
5187
5071
|
*/
|
|
5188
|
-
|
|
5072
|
+
SoleBusiness.businessesLimit = 6;
|
|
5073
|
+
__decorate([
|
|
5074
|
+
Type(() => User)
|
|
5075
|
+
], SoleBusiness.prototype, "user", void 0);
|
|
5076
|
+
__decorate([
|
|
5077
|
+
Type(() => SoleBusinessAllocation)
|
|
5078
|
+
], SoleBusiness.prototype, "allocations", void 0);
|
|
5079
|
+
__decorate([
|
|
5080
|
+
Type(() => SoleBusinessLoss)
|
|
5081
|
+
], SoleBusiness.prototype, "losses", void 0);
|
|
5082
|
+
__decorate([
|
|
5083
|
+
Type(() => SoleInvoice)
|
|
5084
|
+
], SoleBusiness.prototype, "invoices", void 0);
|
|
5085
|
+
__decorate([
|
|
5086
|
+
Type(() => SoleInvoiceTemplate)
|
|
5087
|
+
], SoleBusiness.prototype, "invoiceTemplates", void 0);
|
|
5088
|
+
__decorate([
|
|
5089
|
+
Type(() => VehicleClaim)
|
|
5090
|
+
], SoleBusiness.prototype, "vehicleClaims", void 0);
|
|
5091
|
+
__decorate([
|
|
5092
|
+
Type(() => Transaction)
|
|
5093
|
+
], SoleBusiness.prototype, "transactions", void 0);
|
|
5094
|
+
__decorate([
|
|
5095
|
+
Type(() => Depreciation)
|
|
5096
|
+
], SoleBusiness.prototype, "depreciations", void 0);
|
|
5097
|
+
__decorate([
|
|
5098
|
+
Type(() => SoleBusinessActivity$1)
|
|
5099
|
+
], SoleBusiness.prototype, "activity", void 0);
|
|
5100
|
+
__decorate([
|
|
5101
|
+
Type(() => IncomeSource)
|
|
5102
|
+
], SoleBusiness.prototype, "incomeSource", void 0);
|
|
5103
|
+
|
|
5104
|
+
class SoleBusinessActivity extends SoleBusinessActivity$1 {
|
|
5105
|
+
}
|
|
5106
|
+
|
|
5107
|
+
class SoleDepreciationMethod$1 extends AbstractModel {
|
|
5108
|
+
}
|
|
5109
|
+
|
|
5110
|
+
var SoleDepreciationMethodEnum;
|
|
5111
|
+
(function (SoleDepreciationMethodEnum) {
|
|
5112
|
+
SoleDepreciationMethodEnum[SoleDepreciationMethodEnum["SBP"] = 1] = "SBP";
|
|
5113
|
+
SoleDepreciationMethodEnum[SoleDepreciationMethodEnum["DEPRECIATION"] = 2] = "DEPRECIATION";
|
|
5114
|
+
})(SoleDepreciationMethodEnum || (SoleDepreciationMethodEnum = {}));
|
|
5115
|
+
|
|
5116
|
+
class SoleDepreciationMethod extends SoleDepreciationMethod$1 {
|
|
5117
|
+
isSBP() {
|
|
5118
|
+
return this.method === SoleDepreciationMethodEnum.SBP;
|
|
5119
|
+
}
|
|
5120
|
+
}
|
|
5121
|
+
|
|
5122
|
+
class SoleDetails$1 extends AbstractModel {
|
|
5123
|
+
}
|
|
5124
|
+
|
|
5125
|
+
class SoleDetails extends SoleDetails$1 {
|
|
5189
5126
|
}
|
|
5190
5127
|
__decorate([
|
|
5191
|
-
Type(() =>
|
|
5192
|
-
],
|
|
5128
|
+
Type(() => User)
|
|
5129
|
+
], SoleDetails.prototype, "user", void 0);
|
|
5193
5130
|
|
|
5194
|
-
|
|
5131
|
+
class BasReport$1 extends AbstractModel {
|
|
5132
|
+
}
|
|
5195
5133
|
|
|
5196
|
-
|
|
5197
|
-
|
|
5198
|
-
|
|
5199
|
-
*/
|
|
5200
|
-
class TransactionCollection extends ExportableCollection {
|
|
5201
|
-
/**
|
|
5202
|
-
* @TODO use TransactionBaseCollection instead
|
|
5203
|
-
* we use depreciations as expense transactions a lot
|
|
5204
|
-
*/
|
|
5205
|
-
constructor(transactions = [], depreciations = []) {
|
|
5206
|
-
super([...transactions, ...depreciations.map((depreciation) => depreciation.toTransaction())]);
|
|
5134
|
+
class BasReport extends BasReport$1 {
|
|
5135
|
+
get taxWithheldTotal() {
|
|
5136
|
+
return this.taxWithheldSalary + this.taxWithheldNoABN;
|
|
5207
5137
|
}
|
|
5208
|
-
|
|
5209
|
-
return this.
|
|
5138
|
+
get paygTaxInstalmentOwedToATO() {
|
|
5139
|
+
return this.paygTaxInstalment > 0 ? this.paygTaxInstalment : 0;
|
|
5210
5140
|
}
|
|
5211
|
-
get
|
|
5212
|
-
return this.
|
|
5141
|
+
get paygTaxInstalmentOwedByATO() {
|
|
5142
|
+
return this.paygTaxInstalment < 0 ? Math.abs(this.paygTaxInstalment) : 0;
|
|
5213
5143
|
}
|
|
5214
|
-
|
|
5215
|
-
|
|
5216
|
-
|
|
5217
|
-
|
|
5218
|
-
return this.
|
|
5219
|
-
|
|
5220
|
-
|
|
5144
|
+
get fuelTaxCreditOwedToATO() {
|
|
5145
|
+
return this.fuelTaxCredit < 0 ? this.fuelTaxCredit : 0;
|
|
5146
|
+
}
|
|
5147
|
+
get fuelTaxCreditOwedByATO() {
|
|
5148
|
+
return this.fuelTaxCredit > 0 ? Math.abs(this.fuelTaxCredit) : 0;
|
|
5149
|
+
}
|
|
5150
|
+
get owesToATO() {
|
|
5151
|
+
return this.incomeGST + this.taxWithheldTotal + this.paygTaxInstalmentOwedToATO + this.fuelTaxCreditOwedToATO;
|
|
5152
|
+
}
|
|
5153
|
+
get owedByATO() {
|
|
5154
|
+
return this.expenseGST + this.paygTaxInstalmentOwedByATO + this.fuelTaxCreditOwedByATO;
|
|
5221
5155
|
}
|
|
5222
5156
|
/**
|
|
5223
|
-
*
|
|
5157
|
+
* GST payable to the ATO, or refundable from the ATO in case it's negative
|
|
5224
5158
|
*/
|
|
5225
|
-
|
|
5226
|
-
return
|
|
5227
|
-
}
|
|
5228
|
-
get claimAmount() {
|
|
5229
|
-
return this.items.reduce((sum, transaction) => sum + transaction.claimAmount, 0);
|
|
5159
|
+
get gst() {
|
|
5160
|
+
return this.incomeGST + this.expenseGST + this.taxWithheldTotal + this.paygTaxInstalment - this.fuelTaxCredit;
|
|
5230
5161
|
}
|
|
5231
|
-
|
|
5232
|
-
|
|
5162
|
+
}
|
|
5163
|
+
__decorate([
|
|
5164
|
+
Type(() => Date)
|
|
5165
|
+
], BasReport.prototype, "dateFrom", void 0);
|
|
5166
|
+
__decorate([
|
|
5167
|
+
Type(() => Date)
|
|
5168
|
+
], BasReport.prototype, "dateTo", void 0);
|
|
5169
|
+
|
|
5170
|
+
/**
|
|
5171
|
+
* role hierarchy
|
|
5172
|
+
*/
|
|
5173
|
+
const USER_ROLES = {
|
|
5174
|
+
ROLE_FIRM_OWNER: [UserRolesEnum.FIRM_OWNER, UserRolesEnum.FIRM_MANAGER, UserRolesEnum.ACCOUNTANT, UserRolesEnum.ADVISOR],
|
|
5175
|
+
ROLE_FIRM_MANAGER: [UserRolesEnum.FIRM_MANAGER, UserRolesEnum.ACCOUNTANT, UserRolesEnum.ADVISOR],
|
|
5176
|
+
ROLE_EMPLOYEE: [UserRolesEnum.ACCOUNTANT, UserRolesEnum.ADVISOR],
|
|
5177
|
+
ROLE_ACCOUNTANT: [UserRolesEnum.ACCOUNTANT],
|
|
5178
|
+
ROLE_ADVISOR: [UserRolesEnum.ADVISOR],
|
|
5179
|
+
ROLE_CLIENT: [UserRolesEnum.CLIENT],
|
|
5180
|
+
ROLE_USER_SUBSCRIPTION: [UserRolesEnum.SUBSCRIPTION],
|
|
5181
|
+
ROLE_USER_WORK: [UserRolesEnum.WORK_TANK],
|
|
5182
|
+
ROLE_USER_PROPERTY: [UserRolesEnum.PROPERTY_TANK],
|
|
5183
|
+
ROLE_USER_SOLE: [UserRolesEnum.SOLE_TANK],
|
|
5184
|
+
};
|
|
5185
|
+
|
|
5186
|
+
class User extends User$1 {
|
|
5187
|
+
get fullName() {
|
|
5188
|
+
return `${this.firstName} ${this.lastName}`;
|
|
5233
5189
|
}
|
|
5234
|
-
get
|
|
5235
|
-
return this.
|
|
5190
|
+
get activeSubscription() {
|
|
5191
|
+
return this.subscriptions.find((ss) => ss.isActive);
|
|
5236
5192
|
}
|
|
5237
|
-
|
|
5238
|
-
return
|
|
5193
|
+
get lastSubscription() {
|
|
5194
|
+
return this.subscriptions[this.subscriptions.length - 1];
|
|
5239
5195
|
}
|
|
5240
5196
|
/**
|
|
5241
|
-
*
|
|
5242
|
-
*
|
|
5197
|
+
* @TODO refactor
|
|
5198
|
+
*
|
|
5243
5199
|
*/
|
|
5244
|
-
|
|
5245
|
-
|
|
5200
|
+
get position() {
|
|
5201
|
+
switch (true) {
|
|
5202
|
+
case this.isFirmOwner():
|
|
5203
|
+
return USER_WORK_POSITION[UserRolesEnum.FIRM_OWNER];
|
|
5204
|
+
case this.isManager():
|
|
5205
|
+
return USER_WORK_POSITION[UserRolesEnum.FIRM_MANAGER];
|
|
5206
|
+
case this.isEmployee():
|
|
5207
|
+
return USER_WORK_POSITION[UserRolesEnum.EMPLOYEE];
|
|
5208
|
+
default:
|
|
5209
|
+
return '';
|
|
5210
|
+
}
|
|
5246
5211
|
}
|
|
5247
5212
|
/**
|
|
5248
|
-
*
|
|
5213
|
+
* search roles including hierarchy
|
|
5249
5214
|
*/
|
|
5250
|
-
|
|
5251
|
-
|
|
5252
|
-
|
|
5253
|
-
|
|
5254
|
-
}
|
|
5255
|
-
|
|
5215
|
+
hasRoles(roles) {
|
|
5216
|
+
roles = roles instanceof Array ? roles : [roles];
|
|
5217
|
+
if (!roles.length) {
|
|
5218
|
+
return true;
|
|
5219
|
+
}
|
|
5220
|
+
roles = flatten(roles.map((role) => USER_ROLES[role]));
|
|
5221
|
+
return !!intersection(this.roles, roles).length;
|
|
5256
5222
|
}
|
|
5257
|
-
|
|
5258
|
-
return
|
|
5223
|
+
isOnboarding() {
|
|
5224
|
+
return this.status === UserStatusEnum.ON_BOARDING;
|
|
5259
5225
|
}
|
|
5260
|
-
|
|
5261
|
-
return
|
|
5226
|
+
hasSubscription() {
|
|
5227
|
+
return this.roles.includes(UserRolesEnum.SUBSCRIPTION);
|
|
5262
5228
|
}
|
|
5263
|
-
|
|
5264
|
-
return this.
|
|
5229
|
+
isLoggedIn() {
|
|
5230
|
+
return this.id === +localStorage.getItem('userId');
|
|
5265
5231
|
}
|
|
5266
|
-
|
|
5267
|
-
return this.
|
|
5232
|
+
isClient() {
|
|
5233
|
+
return this.roles.includes(UserRolesEnum.CLIENT);
|
|
5268
5234
|
}
|
|
5269
|
-
|
|
5270
|
-
return
|
|
5235
|
+
isEmployee() {
|
|
5236
|
+
return this.isAccountant() || this.isAdvisor();
|
|
5271
5237
|
}
|
|
5272
|
-
|
|
5273
|
-
return this.
|
|
5238
|
+
isAccountant() {
|
|
5239
|
+
return this.roles.includes(UserRolesEnum.ACCOUNTANT);
|
|
5274
5240
|
}
|
|
5275
|
-
|
|
5276
|
-
|
|
5277
|
-
* @param ids Ids of properties for filter
|
|
5278
|
-
*/
|
|
5279
|
-
getByPropertiesIds(ids) {
|
|
5280
|
-
return new TransactionCollection(this.items.filter((transaction) => {
|
|
5281
|
-
var _a;
|
|
5282
|
-
return ids.includes((_a = transaction.property) === null || _a === void 0 ? void 0 : _a.id);
|
|
5283
|
-
}));
|
|
5241
|
+
isAdvisor() {
|
|
5242
|
+
return this.roles.includes(UserRolesEnum.ADVISOR);
|
|
5284
5243
|
}
|
|
5285
|
-
|
|
5286
|
-
|
|
5287
|
-
* @param id id of income source for filter
|
|
5288
|
-
*/
|
|
5289
|
-
getByIncomeSourceId(id) {
|
|
5290
|
-
return new TransactionCollection(this.items.filter((transaction) => { var _a; return ((_a = transaction.incomeSource) === null || _a === void 0 ? void 0 : _a.id) === id; }));
|
|
5244
|
+
isImpersonator() {
|
|
5245
|
+
return this.roles.includes(UserRolesEnum.SWITCH_USER);
|
|
5291
5246
|
}
|
|
5292
5247
|
/**
|
|
5293
|
-
*
|
|
5294
|
-
* @param category Chart accounts category value
|
|
5248
|
+
* Check if current user is firm owner
|
|
5295
5249
|
*/
|
|
5296
|
-
|
|
5297
|
-
return
|
|
5250
|
+
isFirmOwner() {
|
|
5251
|
+
return this.roles.includes(UserRolesEnum.FIRM_OWNER);
|
|
5298
5252
|
}
|
|
5299
5253
|
/**
|
|
5300
|
-
*
|
|
5254
|
+
* Check if current user is firm manager
|
|
5301
5255
|
*/
|
|
5302
|
-
|
|
5303
|
-
return
|
|
5304
|
-
}
|
|
5305
|
-
getDebitTransactions() {
|
|
5306
|
-
return new TransactionCollection(this.items.filter((transaction) => transaction.isDebit()));
|
|
5307
|
-
}
|
|
5308
|
-
getCreditTransactions() {
|
|
5309
|
-
return new TransactionCollection(this.items.filter((transaction) => transaction.isCredit()));
|
|
5310
|
-
}
|
|
5311
|
-
getByAllocations(allocations) {
|
|
5312
|
-
return new TransactionCollection(this.items.filter((transaction) => allocations.hasTransaction(transaction)));
|
|
5256
|
+
isManager() {
|
|
5257
|
+
return this.roles.includes(UserRolesEnum.FIRM_MANAGER) || this.roles.includes(UserRolesEnum.FIRM_OWNER);
|
|
5313
5258
|
}
|
|
5314
5259
|
/**
|
|
5315
|
-
*
|
|
5260
|
+
* check if user has property tank access
|
|
5316
5261
|
*/
|
|
5317
|
-
|
|
5318
|
-
return this.
|
|
5319
|
-
|
|
5320
|
-
|
|
5262
|
+
hasPropertyTank() {
|
|
5263
|
+
return this.roles ?
|
|
5264
|
+
this.roles.includes(UserRolesEnum.PROPERTY_TANK) :
|
|
5265
|
+
!!this.getSubscriptionRole(UserRolesEnum.PROPERTY_TANK);
|
|
5321
5266
|
}
|
|
5322
5267
|
/**
|
|
5323
|
-
*
|
|
5268
|
+
* check if user has property tank access
|
|
5324
5269
|
*/
|
|
5325
|
-
|
|
5326
|
-
return this.
|
|
5327
|
-
|
|
5328
|
-
|
|
5329
|
-
return transaction.isPropertyTank();
|
|
5330
|
-
case TankTypeEnum.WORK:
|
|
5331
|
-
return transaction.isWorkTank();
|
|
5332
|
-
case TankTypeEnum.SOLE:
|
|
5333
|
-
return transaction.isSoleTank();
|
|
5334
|
-
// Transaction may be not related to any tank type (personal)
|
|
5335
|
-
default:
|
|
5336
|
-
return false;
|
|
5337
|
-
}
|
|
5338
|
-
}));
|
|
5339
|
-
}
|
|
5340
|
-
getExportHeader() {
|
|
5341
|
-
return ['Date', 'Description', 'Debit', 'Credit'];
|
|
5342
|
-
}
|
|
5343
|
-
getExportFooter() {
|
|
5344
|
-
return [
|
|
5345
|
-
plainToClass(ExportCell, { value: 'Total', type: ExportCellTypeEnum.STRING }),
|
|
5346
|
-
plainToClass(ExportCell, { value: '', type: ExportCellTypeEnum.STRING }),
|
|
5347
|
-
plainToClass(ExportCell, { value: this.sumBy('debit'), type: ExportCellTypeEnum.CURRENCY }),
|
|
5348
|
-
plainToClass(ExportCell, { value: this.sumBy('credit'), type: ExportCellTypeEnum.CURRENCY })
|
|
5349
|
-
];
|
|
5350
|
-
}
|
|
5351
|
-
getExportBody() {
|
|
5352
|
-
return this.items.map((transaction) => {
|
|
5353
|
-
return [
|
|
5354
|
-
plainToClass(ExportCell, { value: transaction.date, type: ExportCellTypeEnum.DATE }),
|
|
5355
|
-
plainToClass(ExportCell, { value: transaction.description, type: ExportCellTypeEnum.STRING }),
|
|
5356
|
-
plainToClass(ExportCell, { value: transaction.debit, type: ExportCellTypeEnum.CURRENCY }),
|
|
5357
|
-
plainToClass(ExportCell, { value: transaction.credit, type: ExportCellTypeEnum.CURRENCY })
|
|
5358
|
-
];
|
|
5359
|
-
});
|
|
5270
|
+
hasWorkTank() {
|
|
5271
|
+
return this.roles ?
|
|
5272
|
+
this.roles.includes(UserRolesEnum.WORK_TANK) :
|
|
5273
|
+
!!this.getSubscriptionRole(UserRolesEnum.WORK_TANK);
|
|
5360
5274
|
}
|
|
5361
5275
|
/**
|
|
5362
|
-
* Get
|
|
5276
|
+
* Get user subscription role by provided role type
|
|
5277
|
+
* @param roleType by which role should be returned
|
|
5363
5278
|
*/
|
|
5364
|
-
|
|
5365
|
-
|
|
5366
|
-
|
|
5367
|
-
|
|
5368
|
-
|
|
5369
|
-
|
|
5370
|
-
? this.getVehicleTransactions().filterBy('business.id', vehicleClaim.business.id)
|
|
5371
|
-
// work tank may have only one vehicle claim, so we need to filter by tank type
|
|
5372
|
-
: this.getVehicleTransactions().filterBy('tankType', TankTypeEnum.WORK);
|
|
5279
|
+
getSubscriptionRole(roleType) {
|
|
5280
|
+
var _a;
|
|
5281
|
+
/**
|
|
5282
|
+
* Add @TODO for Alex to check if we should use getLastSubscription here
|
|
5283
|
+
*/
|
|
5284
|
+
return (_a = this.activeSubscription) === null || _a === void 0 ? void 0 : _a.items.find((subscriptionItem) => subscriptionItem.price.product.role.includes(roleType));
|
|
5373
5285
|
}
|
|
5374
5286
|
/**
|
|
5375
|
-
* Get
|
|
5287
|
+
* Get user's photo link
|
|
5376
5288
|
*/
|
|
5377
|
-
|
|
5378
|
-
return this
|
|
5379
|
-
.getVehicleTransactions()
|
|
5380
|
-
.removeBy('chartAccounts.id', [ChartAccountsListEnum.KLMS_TRAVELLED_FOR_WORK, ChartAccountsListEnum.KLMS_TRAVELLED]);
|
|
5289
|
+
getPhoto() {
|
|
5290
|
+
return this.photo;
|
|
5381
5291
|
}
|
|
5382
5292
|
/**
|
|
5383
|
-
*
|
|
5384
|
-
* Cash position = Income - Expenses (include depreciations)
|
|
5385
|
-
* Chart data for each month from fin year start till current month
|
|
5293
|
+
* get user's initials
|
|
5386
5294
|
*/
|
|
5387
|
-
|
|
5388
|
-
|
|
5389
|
-
plainToClass(ChartData, { name: 'Income', data: [] }),
|
|
5390
|
-
plainToClass(ChartData, { name: 'Expense', data: [] })
|
|
5391
|
-
];
|
|
5392
|
-
new FinancialYear().getPastMonths().forEach((month) => {
|
|
5393
|
-
chartData[0].data.push({
|
|
5394
|
-
label: MONTHS[month],
|
|
5395
|
-
value: this.getIncomeTransactions().getByMonth(month).claimAmount
|
|
5396
|
-
});
|
|
5397
|
-
chartData[1].data.push({
|
|
5398
|
-
label: MONTHS[month],
|
|
5399
|
-
value: Math.abs(this.getExpenseTransactions().getByMonth(month).claimAmount)
|
|
5400
|
-
});
|
|
5401
|
-
});
|
|
5402
|
-
return chartData;
|
|
5295
|
+
getPhotoPlaceholder() {
|
|
5296
|
+
return `${this.firstName[0].toUpperCase()}${this.lastName[0].toUpperCase()}`;
|
|
5403
5297
|
}
|
|
5404
|
-
|
|
5405
|
-
|
|
5406
|
-
|
|
5407
|
-
|
|
5408
|
-
|
|
5409
|
-
|
|
5410
|
-
|
|
5411
|
-
|
|
5412
|
-
|
|
5298
|
+
}
|
|
5299
|
+
__decorate([
|
|
5300
|
+
Type(() => ServiceSubscription)
|
|
5301
|
+
], User.prototype, "subscriptions", void 0);
|
|
5302
|
+
__decorate([
|
|
5303
|
+
Type(() => ClientDetails)
|
|
5304
|
+
], User.prototype, "clientDetails", void 0);
|
|
5305
|
+
__decorate([
|
|
5306
|
+
Type(() => EmployeeDetails)
|
|
5307
|
+
], User.prototype, "employeeDetails", void 0);
|
|
5308
|
+
__decorate([
|
|
5309
|
+
Type(() => SoleDetails)
|
|
5310
|
+
], User.prototype, "soleDetails", void 0);
|
|
5311
|
+
__decorate([
|
|
5312
|
+
Type(() => Address)
|
|
5313
|
+
], User.prototype, "address", void 0);
|
|
5314
|
+
__decorate([
|
|
5315
|
+
Type(() => Phone)
|
|
5316
|
+
], User.prototype, "phone", void 0);
|
|
5317
|
+
__decorate([
|
|
5318
|
+
Type(() => Date)
|
|
5319
|
+
], User.prototype, "createdAt", void 0);
|
|
5320
|
+
__decorate([
|
|
5321
|
+
Type(() => User)
|
|
5322
|
+
], User.prototype, "clients", void 0);
|
|
5323
|
+
|
|
5324
|
+
class PropertySubscription extends PropertySubscription$1 {
|
|
5325
|
+
}
|
|
5326
|
+
__decorate([
|
|
5327
|
+
Type(() => Date)
|
|
5328
|
+
], PropertySubscription.prototype, "createdAt", void 0);
|
|
5329
|
+
__decorate([
|
|
5330
|
+
Type(() => User)
|
|
5331
|
+
], PropertySubscription.prototype, "user", void 0);
|
|
5332
|
+
|
|
5333
|
+
class PropertyCategory$1 extends AbstractModel {
|
|
5334
|
+
}
|
|
5335
|
+
|
|
5336
|
+
var PropertyCategoryListEnum;
|
|
5337
|
+
(function (PropertyCategoryListEnum) {
|
|
5338
|
+
PropertyCategoryListEnum[PropertyCategoryListEnum["OWNER_OCCUPIED"] = 3] = "OWNER_OCCUPIED";
|
|
5339
|
+
PropertyCategoryListEnum[PropertyCategoryListEnum["SHARED"] = 4] = "SHARED";
|
|
5340
|
+
PropertyCategoryListEnum[PropertyCategoryListEnum["VACANT_LAND"] = 5] = "VACANT_LAND";
|
|
5341
|
+
})(PropertyCategoryListEnum || (PropertyCategoryListEnum = {}));
|
|
5342
|
+
|
|
5343
|
+
class PropertyCategory extends PropertyCategory$1 {
|
|
5344
|
+
// @Todo check if category is Owner Occupied. If will be needed to check more categories - move the checking to the backend
|
|
5345
|
+
isOwnerOccupied() {
|
|
5346
|
+
return this.id === PropertyCategoryListEnum.OWNER_OCCUPIED;
|
|
5413
5347
|
}
|
|
5414
|
-
|
|
5415
|
-
return this.
|
|
5348
|
+
isVacantLand() {
|
|
5349
|
+
return this.id === PropertyCategoryListEnum.VACANT_LAND;
|
|
5416
5350
|
}
|
|
5417
|
-
|
|
5418
|
-
return
|
|
5351
|
+
isShared() {
|
|
5352
|
+
return this.id === PropertyCategoryListEnum.SHARED;
|
|
5419
5353
|
}
|
|
5420
5354
|
}
|
|
5421
5355
|
|
|
5422
|
-
class
|
|
5423
|
-
|
|
5424
|
-
|
|
5356
|
+
class PropertyValuation$1 extends AbstractModel {
|
|
5357
|
+
}
|
|
5358
|
+
|
|
5359
|
+
class PropertyDocument$1 extends AbstractModel {
|
|
5360
|
+
getApiUrlPrefix() {
|
|
5361
|
+
return '';
|
|
5425
5362
|
}
|
|
5426
|
-
|
|
5427
|
-
return
|
|
5363
|
+
getEntity() {
|
|
5364
|
+
return undefined;
|
|
5428
5365
|
}
|
|
5429
|
-
|
|
5430
|
-
|
|
5366
|
+
}
|
|
5367
|
+
|
|
5368
|
+
class PropertyDocument extends PropertyDocument$1 {
|
|
5369
|
+
constructor() {
|
|
5370
|
+
super(...arguments);
|
|
5371
|
+
this.type = AssetTypeEnum.DOCUMENT;
|
|
5372
|
+
this.entityType = AssetEntityTypeEnum.PROPERTIES;
|
|
5373
|
+
}
|
|
5374
|
+
getApiUrlPrefix() {
|
|
5375
|
+
return '';
|
|
5376
|
+
}
|
|
5377
|
+
getEntity() {
|
|
5378
|
+
return this.property;
|
|
5379
|
+
}
|
|
5380
|
+
}
|
|
5381
|
+
|
|
5382
|
+
class PropertyValuation extends PropertyValuation$1 {
|
|
5383
|
+
get financialYear() {
|
|
5384
|
+
return new FinancialYear(this.date).year;
|
|
5385
|
+
}
|
|
5386
|
+
isCurrentYear() {
|
|
5387
|
+
return this.financialYear === new FinancialYear(new Date()).year;
|
|
5388
|
+
}
|
|
5389
|
+
}
|
|
5390
|
+
__decorate([
|
|
5391
|
+
Type(() => Date)
|
|
5392
|
+
], PropertyValuation.prototype, "date", void 0);
|
|
5393
|
+
__decorate([
|
|
5394
|
+
Type(() => PropertyDocument)
|
|
5395
|
+
], PropertyValuation.prototype, "document", void 0);
|
|
5396
|
+
__decorate([
|
|
5397
|
+
Exclude()
|
|
5398
|
+
], PropertyValuation.prototype, "documentFile", void 0);
|
|
5399
|
+
|
|
5400
|
+
class PropertyForecast$1 extends AbstractModel {
|
|
5401
|
+
}
|
|
5402
|
+
|
|
5403
|
+
class PropertyForecast extends PropertyForecast$1 {
|
|
5404
|
+
constructor() {
|
|
5405
|
+
super(...arguments);
|
|
5406
|
+
this.financialYear = new FinancialYear(new Date()).year;
|
|
5431
5407
|
}
|
|
5432
5408
|
/**
|
|
5433
|
-
*
|
|
5409
|
+
* Get cash position
|
|
5410
|
+
* Cash Position = Income - Expense - Interest
|
|
5434
5411
|
*/
|
|
5435
|
-
|
|
5436
|
-
|
|
5437
|
-
const bankTransactionsByBankAccount = new CollectionDictionary(bankTransactions, 'bankAccount.id');
|
|
5438
|
-
// Create empty dictionary of transaction allocations
|
|
5439
|
-
const allocationsByBankAccount = new CollectionDictionary(new TransactionAllocationCollection([]));
|
|
5440
|
-
// Fill allocations dictionary with bank transactions dictionary keys and allocations related with each bank transaction collection
|
|
5441
|
-
bankTransactionsByBankAccount.keys.forEach((key) => {
|
|
5442
|
-
allocationsByBankAccount.add(key, this.getByBankTransactionsIds(bankTransactionsByBankAccount.get(key).getIds()));
|
|
5443
|
-
});
|
|
5444
|
-
return allocationsByBankAccount;
|
|
5412
|
+
get cashPosition() {
|
|
5413
|
+
return this.income + this.expense + this.interest;
|
|
5445
5414
|
}
|
|
5446
5415
|
/**
|
|
5447
|
-
*
|
|
5416
|
+
* Get tax position
|
|
5417
|
+
* Tax Position = Income - Expense - Interest - Depreciation
|
|
5448
5418
|
*/
|
|
5449
|
-
|
|
5450
|
-
return
|
|
5419
|
+
get taxPosition() {
|
|
5420
|
+
return this.cashPosition + this.depreciation;
|
|
5451
5421
|
}
|
|
5452
5422
|
/**
|
|
5453
|
-
*
|
|
5423
|
+
* Get rental return percent
|
|
5424
|
+
* Rental Return = Income / Market Value
|
|
5454
5425
|
*/
|
|
5455
|
-
|
|
5456
|
-
return
|
|
5426
|
+
get rentalReturn() {
|
|
5427
|
+
return this.income / this.marketValue;
|
|
5428
|
+
}
|
|
5429
|
+
/**
|
|
5430
|
+
* Check if forecast is for real current fin year (not selected in the sidebar)
|
|
5431
|
+
*/
|
|
5432
|
+
isCurrentYear() {
|
|
5433
|
+
return this.financialYear === new FinancialYear(new Date()).year;
|
|
5457
5434
|
}
|
|
5458
5435
|
}
|
|
5436
|
+
__decorate([
|
|
5437
|
+
Transform(({ value }) => +value)
|
|
5438
|
+
], PropertyForecast.prototype, "income", void 0);
|
|
5439
|
+
__decorate([
|
|
5440
|
+
Transform(({ value }) => -Math.abs(+value))
|
|
5441
|
+
], PropertyForecast.prototype, "expense", void 0);
|
|
5442
|
+
__decorate([
|
|
5443
|
+
Transform(({ value }) => -Math.abs(+value))
|
|
5444
|
+
], PropertyForecast.prototype, "interest", void 0);
|
|
5445
|
+
__decorate([
|
|
5446
|
+
Transform(({ value }) => -Math.abs(+value))
|
|
5447
|
+
], PropertyForecast.prototype, "depreciation", void 0);
|
|
5448
|
+
__decorate([
|
|
5449
|
+
Transform(({ value }) => +value)
|
|
5450
|
+
], PropertyForecast.prototype, "loanBalance", void 0);
|
|
5451
|
+
__decorate([
|
|
5452
|
+
Transform(({ value }) => +value)
|
|
5453
|
+
], PropertyForecast.prototype, "marketValue", void 0);
|
|
5454
|
+
|
|
5455
|
+
class PropertyCategoryMovement$1 extends AbstractModel {
|
|
5456
|
+
}
|
|
5459
5457
|
|
|
5460
|
-
|
|
5461
|
-
* used to combine transactions/depreciations
|
|
5462
|
-
*/
|
|
5463
|
-
class TransactionBaseCollection extends Collection {
|
|
5464
|
-
getClaimAmountByBusinessId(businessId) {
|
|
5465
|
-
return +this.filterBy('business.id', businessId).items.map((transaction) => transaction instanceof Depreciation ? -transaction.claimAmount : transaction['claimAmount']).reduce((sum, claimAmount) => sum + claimAmount, 0).toFixed(2);
|
|
5466
|
-
}
|
|
5467
|
-
getSoleTransactions() {
|
|
5468
|
-
return this.filter((transaction) => transaction.isSoleTank());
|
|
5469
|
-
}
|
|
5458
|
+
class PropertyCategoryMovement extends PropertyCategoryMovement$1 {
|
|
5470
5459
|
}
|
|
5460
|
+
__decorate([
|
|
5461
|
+
Type(() => PropertyValuation)
|
|
5462
|
+
], PropertyCategoryMovement.prototype, "valuation", void 0);
|
|
5463
|
+
__decorate([
|
|
5464
|
+
Type(() => PropertyCategory)
|
|
5465
|
+
], PropertyCategoryMovement.prototype, "propertyCategory", void 0);
|
|
5466
|
+
__decorate([
|
|
5467
|
+
Type(() => Date)
|
|
5468
|
+
], PropertyCategoryMovement.prototype, "fromDate", void 0);
|
|
5469
|
+
__decorate([
|
|
5470
|
+
Type(() => Date)
|
|
5471
|
+
], PropertyCategoryMovement.prototype, "toDate", void 0);
|
|
5471
5472
|
|
|
5472
|
-
|
|
5473
|
+
var TaxExemptionEnum;
|
|
5474
|
+
(function (TaxExemptionEnum) {
|
|
5475
|
+
TaxExemptionEnum[TaxExemptionEnum["ONE_YEAR_RULE"] = 1] = "ONE_YEAR_RULE";
|
|
5476
|
+
// principle place of residence
|
|
5477
|
+
TaxExemptionEnum[TaxExemptionEnum["PPR"] = 2] = "PPR";
|
|
5478
|
+
TaxExemptionEnum[TaxExemptionEnum["SIX_YEARS_RULE"] = 3] = "SIX_YEARS_RULE";
|
|
5479
|
+
TaxExemptionEnum[TaxExemptionEnum["INVESTMENT_TO_PPR"] = 4] = "INVESTMENT_TO_PPR";
|
|
5480
|
+
TaxExemptionEnum[TaxExemptionEnum["PPR_TO_INVESTMENT"] = 5] = "PPR_TO_INVESTMENT";
|
|
5481
|
+
TaxExemptionEnum[TaxExemptionEnum["TRANSFER"] = 6] = "TRANSFER";
|
|
5482
|
+
TaxExemptionEnum[TaxExemptionEnum["OTHER"] = 7] = "OTHER";
|
|
5483
|
+
})(TaxExemptionEnum || (TaxExemptionEnum = {}));
|
|
5473
5484
|
|
|
5474
5485
|
/**
|
|
5475
5486
|
* propertySale docs - https://taxtank.atlassian.net/wiki/spaces/TAXTANK/pages/4209508353/Property+Sold+button
|
|
@@ -15397,15 +15408,6 @@ class TransactionCalculationService {
|
|
|
15397
15408
|
return transaction.isAllocated(allocations);
|
|
15398
15409
|
}));
|
|
15399
15410
|
}
|
|
15400
|
-
/**
|
|
15401
|
-
* Get collection of unallocated transactions
|
|
15402
|
-
* @TODO Alex: consider to move to collection
|
|
15403
|
-
*/
|
|
15404
|
-
getUnallocatedTransactions(transactions, allocations) {
|
|
15405
|
-
return new TransactionCollection(transactions.items.filter((transaction) => {
|
|
15406
|
-
return !transaction.isAllocated(allocations);
|
|
15407
|
-
}));
|
|
15408
|
-
}
|
|
15409
15411
|
getUnallocatedInvoices(invoices, allocations) {
|
|
15410
15412
|
return invoices.filter((invoice) => {
|
|
15411
15413
|
const invoiceAllocatedAmount = allocations.filterBy('transaction.id', invoice.getTransactionsIds()).sumBy('amount');
|
|
@@ -17948,13 +17950,15 @@ class WorkIncomeForm extends TransactionForm {
|
|
|
17948
17950
|
}, Validators.required),
|
|
17949
17951
|
incomeSource: new FormControl(transaction.incomeSource, [Validators.required, autocompleteValidator()]),
|
|
17950
17952
|
});
|
|
17951
|
-
//
|
|
17953
|
+
// @TODO we use amount field as netAmount to avoid extra watcher for amount recalculation
|
|
17952
17954
|
if (transaction.id) {
|
|
17953
|
-
this.get('amount').setValue(
|
|
17955
|
+
this.get('amount').setValue(transaction.netAmount);
|
|
17954
17956
|
}
|
|
17957
|
+
// forbid to edit some fields for allocated transaction
|
|
17955
17958
|
if (allocations.length) {
|
|
17956
17959
|
this.get('chartAccounts').disable();
|
|
17957
17960
|
}
|
|
17961
|
+
// adjustments allowed only for salary
|
|
17958
17962
|
if (!((_a = transaction.chartAccounts) === null || _a === void 0 ? void 0 : _a.isSalary())) {
|
|
17959
17963
|
this.get('transactions').disable();
|
|
17960
17964
|
}
|
|
@@ -18013,25 +18017,19 @@ class WorkIncomeForm extends TransactionForm {
|
|
|
18013
18017
|
});
|
|
18014
18018
|
}
|
|
18015
18019
|
/**
|
|
18016
|
-
*
|
|
18017
|
-
* @param includeAdjustments reduce result by adjustments included in salary if false or increase amount with included salary adjustments to match received payment if true,
|
|
18018
|
-
* salary/wage comes to bankAccount together with related chartAccounts like tips (kind of salary, but reported in different tax summary section),
|
|
18020
|
+
* salary comes to bankAccount together with related transactions like tips (kind of salary, but reported in different tax summary section),
|
|
18019
18021
|
* adjustments used to clarify received payment by separating it into multiple transactions,
|
|
18020
|
-
*
|
|
18021
|
-
*
|
|
18022
|
-
*
|
|
18023
|
-
|
|
18024
|
-
|
|
18025
|
-
|
|
18026
|
-
|
|
18027
|
-
|
|
18028
|
-
return transaction.amount;
|
|
18029
|
-
}
|
|
18030
|
-
const includedTransactions = new Collection(transaction.transactions).filter((t) => t.chartAccounts.isSalaryIncluded());
|
|
18031
|
-
return transaction.amount + includedTransactions.sumBy('amount') * (includeAdjustments ? 1 : -1);
|
|
18022
|
+
* netAmount always match received payment and includes related adjustments
|
|
18023
|
+
* amount calculated as netAmount - salary included adjustments
|
|
18024
|
+
* ie bankTransaction=1000$ with 900$ salary and 100$ tips will create 2 transactions with 900$ and 100$
|
|
18025
|
+
*/
|
|
18026
|
+
getAmount() {
|
|
18027
|
+
return this.get('amount').value - new Collection(this.currentValue.transactions)
|
|
18028
|
+
.filter((t) => { var _a; return (_a = t.chartAccounts) === null || _a === void 0 ? void 0 : _a.isSalaryIncluded(); })
|
|
18029
|
+
.sumBy('amount');
|
|
18032
18030
|
}
|
|
18033
18031
|
submit(data = {}) {
|
|
18034
|
-
return super.submit(Object.assign(data, { amount: this.getAmount(
|
|
18032
|
+
return super.submit(Object.assign(data, { amount: this.getAmount() }));
|
|
18035
18033
|
}
|
|
18036
18034
|
}
|
|
18037
18035
|
|