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