taxtank-core 0.28.70 → 0.28.73
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 +134 -34
- package/bundles/taxtank-core.umd.js.map +1 -1
- package/esm2015/lib/collections/sole/sole-business-losses.collection.js +28 -14
- package/esm2015/lib/forms/sole/sole-invoice.form.js +45 -25
- package/esm2015/lib/models/sole/bas-report.js +19 -1
- package/esm2015/lib/models/sole/sole-business-loss.js +5 -1
- package/esm2015/lib/services/http/sole/sole-invoice/sole-invoice.service.js +12 -1
- package/fesm2015/taxtank-core.js +101 -34
- package/fesm2015/taxtank-core.js.map +1 -1
- package/lib/collections/sole/sole-business-losses.collection.d.ts +7 -1
- package/lib/forms/sole/sole-invoice.form.d.ts +11 -2
- package/lib/models/sole/bas-report.d.ts +6 -0
- package/lib/models/sole/sole-business-loss.d.ts +4 -0
- package/lib/services/http/sole/sole-invoice/sole-invoice.service.d.ts +5 -0
- package/package.json +1 -1
package/fesm2015/taxtank-core.js
CHANGED
|
@@ -2409,6 +2409,10 @@ __decorate([
|
|
|
2409
2409
|
Type(() => SoleBusinessLossOffsetRule)
|
|
2410
2410
|
], SoleBusinessLossOffsetRule.prototype, "parent", void 0);
|
|
2411
2411
|
|
|
2412
|
+
/**
|
|
2413
|
+
* If a sole trader business makes a tax loss in a current year, you can generally carry forward that loss and offset profit in future years.
|
|
2414
|
+
* https://taxtank.atlassian.net/wiki/spaces/TAXTANK/pages/4641357930/Rules+when+a+business+makes+a+loss+Tax+Summary#Offsetting-current-year-business-losses
|
|
2415
|
+
*/
|
|
2412
2416
|
class SoleBusinessLoss extends SoleBusinessLoss$1 {
|
|
2413
2417
|
constructor() {
|
|
2414
2418
|
super(...arguments);
|
|
@@ -4198,6 +4202,24 @@ class BasReport extends BasReport$1 {
|
|
|
4198
4202
|
get taxWithheldTotal() {
|
|
4199
4203
|
return this.taxWithheldSalary + this.taxWithheldNoABN;
|
|
4200
4204
|
}
|
|
4205
|
+
get paygTaxInstalmentOwedToATO() {
|
|
4206
|
+
return this.paygTaxInstalment > 0 ? this.paygTaxInstalment : 0;
|
|
4207
|
+
}
|
|
4208
|
+
get paygTaxInstalmentOwedByATO() {
|
|
4209
|
+
return this.paygTaxInstalment < 0 ? Math.abs(this.paygTaxInstalment) : 0;
|
|
4210
|
+
}
|
|
4211
|
+
get fuelTaxCreditOwedToATO() {
|
|
4212
|
+
return this.fuelTaxCredit < 0 ? this.fuelTaxCredit : 0;
|
|
4213
|
+
}
|
|
4214
|
+
get fuelTaxCreditOwedByATO() {
|
|
4215
|
+
return this.fuelTaxCredit > 0 ? Math.abs(this.fuelTaxCredit) : 0;
|
|
4216
|
+
}
|
|
4217
|
+
get owesToATO() {
|
|
4218
|
+
return this.incomeGST + this.taxWithheldTotal + this.paygTaxInstalmentOwedToATO + this.fuelTaxCreditOwedToATO;
|
|
4219
|
+
}
|
|
4220
|
+
get owedByATO() {
|
|
4221
|
+
return this.expenseGST + this.paygTaxInstalmentOwedByATO + this.fuelTaxCreditOwedByATO;
|
|
4222
|
+
}
|
|
4201
4223
|
/**
|
|
4202
4224
|
* GST payable to the ATO, or refundable from the ATO in case it's negative
|
|
4203
4225
|
*/
|
|
@@ -5991,26 +6013,40 @@ class Dictionary {
|
|
|
5991
6013
|
|
|
5992
6014
|
class SoleBusinessLossesCollection extends Collection {
|
|
5993
6015
|
/**
|
|
5994
|
-
*
|
|
6016
|
+
* Business loss applied in current year, includes previous year losses and current year losses for businesses matching offset rule
|
|
5995
6017
|
*/
|
|
5996
6018
|
calculateBusinessLossApplied(transactions) {
|
|
5997
|
-
|
|
5998
|
-
|
|
6019
|
+
// claim amounts for businesses that can be applied to be reduced by prior year business losses
|
|
6020
|
+
const claimAmountsByBusinessId = this.getClaimAmountsByBusinessId(transactions);
|
|
6021
|
+
return Object.keys(claimAmountsByBusinessId.items).reduce((sum, businessId) => {
|
|
6022
|
+
const loss = this.findBy('business.id', +businessId);
|
|
6023
|
+
const lossOpenBalance = (loss === null || loss === void 0 ? void 0 : loss.openBalance) || 0;
|
|
6024
|
+
// business loss can be applied to business profit or other income types profit in case in offset rule met
|
|
6025
|
+
return sum + (loss.offsetRule ? lossOpenBalance : Math.min(lossOpenBalance, claimAmountsByBusinessId.get(businessId)));
|
|
6026
|
+
}, 0);
|
|
6027
|
+
}
|
|
6028
|
+
/**
|
|
6029
|
+
* Get business claim amounts that can be applied to be reduced by prior year business losses:
|
|
6030
|
+
* businesses with income or businesses with a loss, but which met the non-commercial loss rules
|
|
6031
|
+
* https://www.ato.gov.au/Business/Non-commercial-losses/
|
|
6032
|
+
*/
|
|
6033
|
+
getClaimAmountsByBusinessId(transactions) {
|
|
5999
6034
|
const claimAmountsByBusinessId = new Dictionary([]);
|
|
6000
|
-
|
|
6001
|
-
|
|
6035
|
+
const transactionsByBusinessId = new CollectionDictionary(transactions, 'business.id');
|
|
6036
|
+
transactionsByBusinessId.keys.forEach((businessId) => {
|
|
6037
|
+
var _a;
|
|
6038
|
+
// business loss may not exist if, when creating a business, user didn't add losses for previous years
|
|
6039
|
+
const lossOffsetRule = (_a = this.findBy('business.id', +businessId)) === null || _a === void 0 ? void 0 : _a.offsetRule;
|
|
6040
|
+
const businessClaimAmount = transactionsByBusinessId
|
|
6002
6041
|
.get(businessId)
|
|
6003
6042
|
.getClaimAmountByBusinessId(+businessId);
|
|
6004
|
-
//
|
|
6005
|
-
if (businessClaimAmount
|
|
6006
|
-
|
|
6043
|
+
// no way to apply loss for business without profit if offset rules not met
|
|
6044
|
+
if (businessClaimAmount < 0 && !lossOffsetRule) {
|
|
6045
|
+
return;
|
|
6007
6046
|
}
|
|
6047
|
+
claimAmountsByBusinessId.add(businessId, businessClaimAmount);
|
|
6008
6048
|
});
|
|
6009
|
-
return
|
|
6010
|
-
var _a;
|
|
6011
|
-
const lossOpenBalance = ((_a = this.findBy('business.id', +businessId)) === null || _a === void 0 ? void 0 : _a.openBalance) || 0;
|
|
6012
|
-
return sum + Math.min(lossOpenBalance, claimAmountsByBusinessId.get(businessId));
|
|
6013
|
-
}, 0);
|
|
6049
|
+
return claimAmountsByBusinessId;
|
|
6014
6050
|
}
|
|
6015
6051
|
}
|
|
6016
6052
|
|
|
@@ -10466,6 +10502,16 @@ class SoleInvoiceService extends RestService {
|
|
|
10466
10502
|
sendEmail(invoice) {
|
|
10467
10503
|
return this.http.post(`${this.environment.apiV2}/${this.url}/${invoice.id}/send`, {});
|
|
10468
10504
|
}
|
|
10505
|
+
/**
|
|
10506
|
+
* Return the next number from the last invoice.
|
|
10507
|
+
* Basically needed to create a new invoice to show its number when the invoice has not yet been sent to the backend
|
|
10508
|
+
*/
|
|
10509
|
+
getNewInvoiceNumber() {
|
|
10510
|
+
if (!this.cache) {
|
|
10511
|
+
return 0;
|
|
10512
|
+
}
|
|
10513
|
+
return last(this.cache).number + 1;
|
|
10514
|
+
}
|
|
10469
10515
|
}
|
|
10470
10516
|
SoleInvoiceService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.15", ngImport: i0, type: SoleInvoiceService, deps: null, target: i0.ɵɵFactoryTarget.Injectable });
|
|
10471
10517
|
SoleInvoiceService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "12.2.15", ngImport: i0, type: SoleInvoiceService, providedIn: 'root' });
|
|
@@ -16044,31 +16090,37 @@ class SoleInvoiceItemForm extends AbstractForm {
|
|
|
16044
16090
|
}
|
|
16045
16091
|
}
|
|
16046
16092
|
|
|
16093
|
+
/**
|
|
16094
|
+
* Form is divided into two groups, since the creation of Sole invoice takes place in two steps:
|
|
16095
|
+
* a common invoice data and sole invoice items.
|
|
16096
|
+
*/
|
|
16047
16097
|
class SoleInvoiceForm extends AbstractForm {
|
|
16048
16098
|
constructor(invoice, soleDetailsGST,
|
|
16049
16099
|
// default template to be preselected
|
|
16050
16100
|
defaultTemplate) {
|
|
16051
16101
|
super({
|
|
16052
|
-
|
|
16053
|
-
|
|
16102
|
+
commonData: new FormGroup({
|
|
16103
|
+
dateFrom: new FormControl(invoice.dateFrom || new Date(), Validators.required),
|
|
16104
|
+
dateTo: new FormControl(invoice.dateTo, Validators.required),
|
|
16105
|
+
payer: new FormControl(invoice.payer, Validators.required),
|
|
16106
|
+
taxType: new FormControl(invoice.taxType, Validators.required),
|
|
16107
|
+
bankAccount: new FormControl(invoice.bankAccount, Validators.required),
|
|
16108
|
+
reference: new FormControl(invoice.reference)
|
|
16109
|
+
}),
|
|
16054
16110
|
items: new FormArray((invoice.items || [plainToClass(SoleInvoiceItem, {})]).map((item) => new SoleInvoiceItemForm(item))),
|
|
16055
|
-
payer: new FormControl(invoice.payer, Validators.required),
|
|
16056
|
-
taxType: new FormControl(invoice.taxType, Validators.required),
|
|
16057
|
-
bankAccount: new FormControl(invoice.bankAccount, Validators.required),
|
|
16058
|
-
reference: new FormControl(invoice.reference)
|
|
16059
16111
|
}, invoice);
|
|
16060
16112
|
this.invoice = invoice;
|
|
16061
16113
|
this.soleDetailsGST = soleDetailsGST;
|
|
16062
16114
|
this.defaultTemplate = defaultTemplate;
|
|
16063
16115
|
// we need invoice template only for new invoices
|
|
16064
16116
|
if (!invoice.id) {
|
|
16065
|
-
this.addControl('template', new FormControl(this.defaultTemplate));
|
|
16117
|
+
(this.commonData).addControl('template', new FormControl(this.defaultTemplate));
|
|
16066
16118
|
this.updateTemplateRelatedFields(this.defaultTemplate);
|
|
16067
16119
|
}
|
|
16068
16120
|
// invoice.taxType is always NONE ('No Tax') when soleDetails.isGST === false
|
|
16069
16121
|
if (!this.soleDetailsGST) {
|
|
16070
|
-
this.get('taxType').setValue(SoleInvoiceTaxTypeEnum.NO_TAX);
|
|
16071
|
-
this.get('taxType').disable();
|
|
16122
|
+
this.commonData.get('taxType').setValue(SoleInvoiceTaxTypeEnum.NO_TAX);
|
|
16123
|
+
this.commonData.get('taxType').disable();
|
|
16072
16124
|
// Items isGST is not available when invoice.taxType === NONE ('No Tax')
|
|
16073
16125
|
this.items.controls.forEach((itemForm) => {
|
|
16074
16126
|
this.disableItemGST(itemForm);
|
|
@@ -16088,8 +16140,8 @@ class SoleInvoiceForm extends AbstractForm {
|
|
|
16088
16140
|
this.listenItemChartAccountsChanges(itemForm);
|
|
16089
16141
|
});
|
|
16090
16142
|
}
|
|
16091
|
-
// nothing to listen if template field is not
|
|
16092
|
-
if (this.contains('template')) {
|
|
16143
|
+
// nothing to listen if template field is not exist (edit invoice case)
|
|
16144
|
+
if ((this.commonData).contains('template')) {
|
|
16093
16145
|
this.listenTemplateChanges();
|
|
16094
16146
|
}
|
|
16095
16147
|
}
|
|
@@ -16106,15 +16158,20 @@ class SoleInvoiceForm extends AbstractForm {
|
|
|
16106
16158
|
this.items.removeAt(index);
|
|
16107
16159
|
}
|
|
16108
16160
|
submit(data = {}) {
|
|
16109
|
-
|
|
16110
|
-
|
|
16111
|
-
|
|
16161
|
+
this.submitted = true;
|
|
16162
|
+
this.markAllAsTouched();
|
|
16163
|
+
if (!this.disabled && !this.valid) {
|
|
16164
|
+
return null;
|
|
16165
|
+
}
|
|
16166
|
+
const invoiceInstance = this.currentValue;
|
|
16167
|
+
this.onSubmit.emit(invoiceInstance);
|
|
16168
|
+
return invoiceInstance;
|
|
16112
16169
|
}
|
|
16113
16170
|
/**
|
|
16114
16171
|
* Update default values from selected invoice template
|
|
16115
16172
|
*/
|
|
16116
16173
|
listenTemplateChanges() {
|
|
16117
|
-
this.get('template').valueChanges.subscribe((template) => {
|
|
16174
|
+
this.commonData.get('template').valueChanges.subscribe((template) => {
|
|
16118
16175
|
this.updateTemplateRelatedFields(template);
|
|
16119
16176
|
});
|
|
16120
16177
|
}
|
|
@@ -16122,7 +16179,7 @@ class SoleInvoiceForm extends AbstractForm {
|
|
|
16122
16179
|
* GST is not available for items when invoice.taxType === NONE
|
|
16123
16180
|
*/
|
|
16124
16181
|
listenTaxTypeChanges() {
|
|
16125
|
-
this.get('taxType').valueChanges.subscribe((type) => {
|
|
16182
|
+
this.commonData.get('taxType').valueChanges.subscribe((type) => {
|
|
16126
16183
|
this.items.controls.forEach((itemForm) => {
|
|
16127
16184
|
const chartAccounts = itemForm.get('chartAccounts').value;
|
|
16128
16185
|
// Item GST is available when invoice.taxType !== NONE ('No Tax')
|
|
@@ -16135,18 +16192,18 @@ class SoleInvoiceForm extends AbstractForm {
|
|
|
16135
16192
|
});
|
|
16136
16193
|
}
|
|
16137
16194
|
updateTemplateRelatedFields(template) {
|
|
16138
|
-
this.get('bankAccount').setValue(template.bankAccount);
|
|
16139
|
-
const dateFrom = this.get('dateFrom').value;
|
|
16195
|
+
this.commonData.get('bankAccount').setValue(template.bankAccount);
|
|
16196
|
+
const dateFrom = this.commonData.get('dateFrom').value;
|
|
16140
16197
|
if (dateFrom) {
|
|
16141
|
-
this.get('dateTo').setValue(new Date(dateFrom.getTime() + template.termTime));
|
|
16198
|
+
this.commonData.get('dateTo').setValue(new Date(dateFrom.getTime() + template.termTime));
|
|
16142
16199
|
}
|
|
16143
16200
|
// invoice.taxType is always 'No Tax' when soleDetails.isGST = false and not available for changing
|
|
16144
16201
|
if (this.soleDetailsGST) {
|
|
16145
|
-
this.get('taxType').setValue(template.taxType);
|
|
16202
|
+
this.commonData.get('taxType').setValue(template.taxType);
|
|
16146
16203
|
}
|
|
16147
16204
|
}
|
|
16148
16205
|
/**
|
|
16149
|
-
* GST availability depends
|
|
16206
|
+
* GST availability depends on chart accounts isGST flag
|
|
16150
16207
|
*/
|
|
16151
16208
|
listenItemChartAccountsChanges(itemForm) {
|
|
16152
16209
|
itemForm.get('chartAccounts').valueChanges.subscribe((chartAccounts) => {
|
|
@@ -16170,6 +16227,16 @@ class SoleInvoiceForm extends AbstractForm {
|
|
|
16170
16227
|
itemForm.get('isGST').setValue(true);
|
|
16171
16228
|
itemForm.get('isGST').enable();
|
|
16172
16229
|
}
|
|
16230
|
+
get commonData() {
|
|
16231
|
+
return this.get('commonData');
|
|
16232
|
+
}
|
|
16233
|
+
/**
|
|
16234
|
+
* Rewrite abstract form getter to flat "commonData" field, which is not in the class
|
|
16235
|
+
*/
|
|
16236
|
+
get currentValue() {
|
|
16237
|
+
const formRawValue = this.getRawValue();
|
|
16238
|
+
return plainToClass(SoleInvoice, Object.assign({}, this.model, Object.assign(Object.assign({}, formRawValue.commonData), { items: formRawValue.items })));
|
|
16239
|
+
}
|
|
16173
16240
|
}
|
|
16174
16241
|
|
|
16175
16242
|
class SoleInvoiceTemplateForm extends AbstractForm {
|