You've already forked openaccounting-web
mirror of
https://github.com/openaccounting/oa-web.git
synced 2025-12-09 09:01:24 +13:00
got new transaction working
This commit is contained in:
@@ -1,28 +1,10 @@
|
||||
<h1>New Transaction</h1>
|
||||
|
||||
<div class="section">
|
||||
<form [formGroup]="form" (ngSubmit)="onSubmit()">
|
||||
<form [formGroup]="form" (ngSubmit)="onSubmit()" *ngIf="accountTree">
|
||||
<ngb-accordion #acc="ngbAccordion" activeIds="toggle-1">
|
||||
<ngb-panel id="toggle-1" [title]="getToggle1Title()">
|
||||
<ng-template ngbPanelContent>
|
||||
<!-- <input type="radio" class="btn btn-outline-primary mr-2" id="type-expense" value="Expense">
|
||||
<input type="radio" class="btn btn-outline-primary mr-2" id="type-income" value="Income">
|
||||
<input type="radio" class="btn btn-outline-primary mr-2" id="type-ob" value="Opening Balance">
|
||||
<input type="radio" class="btn btn-outline-primary mr-2" id="type-other" value="Other"> -->
|
||||
<div>
|
||||
<!-- <button type="button" class="btn mr-2" (click)="setType('expense')" [ngClass]="{'btn-outline-primary': type !== 'expense', 'btn-primary': type === 'expense'}">
|
||||
Expense
|
||||
</button>
|
||||
<button type="button" class="btn mr-2" (click)="setType('income')" [ngClass]="{'btn-outline-primary': type !== 'income', 'btn-primary': type === 'income'}">
|
||||
Income
|
||||
</button>
|
||||
<button type="button" class="btn mr-2" (click)="setType('openingBalance')" [ngClass]="{'btn-outline-primary': type !== 'openingBalance', 'btn-primary': type === 'openingBalance'}">
|
||||
Opening Balance
|
||||
</button>
|
||||
<button type="button" class="btn mr-2" (click)="setType('other')" [ngClass]="{'btn-outline-primary': type !== 'other', 'btn-primary': type === 'other'}">
|
||||
Other
|
||||
</button> -->
|
||||
|
||||
<div class="btn-group-toggle" ngbRadioGroup name="radioBasic" formControlName="type">
|
||||
<label ngbButtonLabel class="btn-primary mr-2">
|
||||
<input ngbButton type="radio" value="expense"> Expense
|
||||
@@ -30,14 +12,13 @@
|
||||
<label ngbButtonLabel class="btn-primary mr-2">
|
||||
<input ngbButton type="radio" value="income"> Income
|
||||
</label>
|
||||
<label ngbButtonLabel class="btn-primary mr-2">
|
||||
<label ngbButtonLabel class="btn-primary mr-2" *ngIf="openingBalances">
|
||||
<input ngbButton type="radio" value="openingBalance"> Opening Balance
|
||||
</label>
|
||||
<label ngbButtonLabel class="btn-primary mr-2">
|
||||
<input ngbButton type="radio" value="other"> Other
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div id="firstAccountPrimary" *ngIf="form.value?.type === 'expense'" class="mt-3">
|
||||
<div class="btn-group-toggle" ngbRadioGroup name="radioBasic2" formControlName="firstAccountPrimary">
|
||||
<label *ngFor="let account of expenseAccounts" ngbButtonLabel class="btn-primary mr-2">
|
||||
@@ -78,9 +59,21 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="firstAccountPrimary" *ngIf="form.value?.type === 'openingBalance'" class="mt-3">
|
||||
<div id="firstAccountSelect" class="mt-3">
|
||||
<div class="form-group">
|
||||
<label for="firstAccountSecondary" class="col-sm-3 col-form-label">Choose Account</label>
|
||||
<select class="form-control" id="account" formControlName="firstAccountSecondary">
|
||||
<option *ngFor="let account of paymentAccountsAll" [value]="account.id">
|
||||
{{account.label | slice:0:30}}
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</ng-template>
|
||||
</ngb-panel>
|
||||
<ngb-panel id="toggle-2" [title]="getTitle()">
|
||||
<ngb-panel id="toggle-2" [title]="getToggle2Title()" *ngIf="form.value?.type !== 'openingBalance'">
|
||||
<ng-template ngbPanelContent>
|
||||
<div id="secondAccountPrimary" *ngIf="form.value?.type === 'expense'" class="mt-3">
|
||||
<div class="btn-group-toggle" ngbRadioGroup name="secondAccountPrimary" formControlName="secondAccountPrimary">
|
||||
@@ -122,22 +115,12 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="secondAccountSelect" *ngIf="form.value?.type === 'openingBalance'" class="mt-3">
|
||||
<div class="form-group">
|
||||
<label for="secondAccountSecondary" class="col-sm-3 col-form-label">Choose Account</label>
|
||||
<select class="form-control" id="account" formControlName="secondAccountSecondary">
|
||||
<option *ngFor="let account of paymentAccountsAll" [value]="account.id">
|
||||
{{account.label | slice:0:30}}
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</ng-template>
|
||||
</ngb-panel>
|
||||
<ngb-panel id="toggle-3" title="Amount">
|
||||
<ng-template ngbPanelContent>
|
||||
<div class="form-group">
|
||||
<input type="number" class="form-control" id="amount" formControlName="amount">
|
||||
<input #amount type="number" class="form-control" id="amount" formControlName="amount">
|
||||
</div>
|
||||
</ng-template>
|
||||
</ngb-panel>
|
||||
@@ -157,17 +140,47 @@
|
||||
</ngb-panel>
|
||||
<ngb-panel id="toggle-6" title="Advanced">
|
||||
<ng-template ngbPanelContent>
|
||||
Anim pariatur cliche reprehenderit, enim eiusmod high life accusamus terry richardson ad squid. 3 wolf moon
|
||||
officia
|
||||
aute, non cupidatat skateboard dolor brunch. Food truck quinoa nesciunt laborum eiusmod. Brunch 3 wolf moon
|
||||
tempor,
|
||||
sunt aliqua put a bird on it squid single-origin coffee nulla assumenda shoreditch et. Nihil anim keffiyeh
|
||||
helvetica,
|
||||
craft beer labore wes anderson cred nesciunt sapiente ea proident. Ad vegan excepteur butcher vice lomo.
|
||||
Leggings
|
||||
occaecat craft beer farm-to-table, raw denim aesthetic synth nesciunt you probably haven't heard of them
|
||||
accusamus
|
||||
labore sustainable VHS.
|
||||
<div class="container-fluid" formArrayName="splits">
|
||||
<div class="row">
|
||||
<div class="col-8">
|
||||
<h3>Account</h3>
|
||||
</div>
|
||||
<div class="col-2">
|
||||
<h3>Debit</h3>
|
||||
</div>
|
||||
<div class="col-2">
|
||||
<h3>Credit</h3>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row" *ngFor="let split of form.get('splits').controls; let i=index" [formGroup]="split">
|
||||
<div class="col-8">
|
||||
<div class="form-group">
|
||||
<select class="form-control" id="account" formControlName="accountId">
|
||||
<option *ngFor="let account of selectAccounts" [value]="account.id">
|
||||
{{account.fullName | slice:0:50}}
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-2">
|
||||
<div class="form-group">
|
||||
<input type="number" class="form-control" formControlName="debit" [ngClass]="{'positive': accountMap[split.value.accountId]?.debitBalance, 'negative': !accountMap[split.value.accountId]?.debitBalance}"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-2">
|
||||
<div class="form-group">
|
||||
<input type="number" class="form-control" formControlName="credit" [ngClass]="{'positive': !accountMap[split.value.accountId]?.debitBalance, 'negative': accountMap[split.value.accountId]?.debitBalance}"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-8">
|
||||
<p>
|
||||
<a (click)="addSplit()">Add Split</a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</ng-template>
|
||||
</ngb-panel>
|
||||
</ngb-accordion>
|
||||
|
||||
@@ -13,4 +13,7 @@
|
||||
color: $blue;
|
||||
}
|
||||
}
|
||||
h3 {
|
||||
font-size: 1rem;
|
||||
}
|
||||
}
|
||||
@@ -1,18 +1,22 @@
|
||||
import { Component, ViewEncapsulation, ViewChild } from '@angular/core';
|
||||
import { Component, ViewEncapsulation, ViewChild, ElementRef } from '@angular/core';
|
||||
import { Router } from '@angular/router';
|
||||
import {
|
||||
FormGroup,
|
||||
FormControl,
|
||||
Validators,
|
||||
FormBuilder,
|
||||
FormArray,
|
||||
AbstractControl,
|
||||
ValidationErrors
|
||||
} from '@angular/forms';
|
||||
import { AccountService } from '../core/account.service';
|
||||
import { TransactionService } from '../core/transaction.service';
|
||||
import { OrgService } from '../core/org.service';
|
||||
import { Account, AccountApi, AccountTree } from '../shared/account';
|
||||
import { Util } from '../shared/util';
|
||||
import { AppError } from '../shared/error';
|
||||
import { Transaction, Split } from '../shared/transaction';
|
||||
import { Logger } from '../core/logger';
|
||||
|
||||
@Component({
|
||||
selector: 'app-txnew',
|
||||
@@ -38,109 +42,240 @@ export class NewTransactionPage {
|
||||
public incomeAccountsAll: any[] = [];
|
||||
public paymentAccountsAll: any[] = [];
|
||||
public assetAccountsAll: any[] = [];
|
||||
public openingBalances: Account;
|
||||
private accountTree: AccountTree;
|
||||
public accountMap: any;
|
||||
@ViewChild('acc') acc: any;
|
||||
@ViewChild('amount') amount: ElementRef
|
||||
|
||||
// TODO This code needs to be cleaned up
|
||||
|
||||
constructor(
|
||||
private router: Router,
|
||||
private accountService: AccountService,
|
||||
private txService: TransactionService,
|
||||
private orgService: OrgService,
|
||||
private fb: FormBuilder) {
|
||||
private fb: FormBuilder,
|
||||
private log: Logger) {
|
||||
|
||||
this.numAccountsShown = 3;
|
||||
|
||||
let org = this.orgService.getCurrentOrg();
|
||||
|
||||
let dateString = Util.getLocalDateString(new Date());
|
||||
this.form = fb.group({
|
||||
'type': ['', Validators.required],
|
||||
'firstAccountPrimary': [null, Validators.required],
|
||||
'firstAccountSecondary': [null],
|
||||
'secondAccountPrimary': [null, Validators.required],
|
||||
'secondAccountSecondary': [null],
|
||||
'amount': [null, Validators.required],
|
||||
'description': [''],
|
||||
'date': [dateString, Validators.required]
|
||||
this.form = this.fb.group({
|
||||
type: ['', Validators.required],
|
||||
firstAccountPrimary: [null, Validators.required],
|
||||
firstAccountSecondary: [null],
|
||||
secondAccountPrimary: [null, Validators.required],
|
||||
secondAccountSecondary: [null],
|
||||
amount: [null, Validators.required],
|
||||
description: [''],
|
||||
date: [dateString, Validators.required],
|
||||
splits: fb.array([]),
|
||||
});
|
||||
|
||||
this.accountService.getAccountTree().subscribe(tree => {
|
||||
this.addSplit();
|
||||
this.addSplit();
|
||||
|
||||
this.accountService.getAccountTree().take(1).subscribe(tree => {
|
||||
this.accountTree = tree;
|
||||
this.accountMap = tree.accountMap;
|
||||
this.selectAccounts = tree.getFlattenedAccounts().filter(account => {
|
||||
let isAsset = account.fullName.match(/^Assets/);
|
||||
let isLiability = account.fullName.match(/^Liabilities/);
|
||||
return !account.children.length && (isAsset || isLiability);
|
||||
return !account.children.length;
|
||||
});
|
||||
|
||||
this.getExpenseAccounts();
|
||||
this.getIncomeAccounts();
|
||||
this.getPaymentAccounts();
|
||||
this.getAssetAccounts();
|
||||
|
||||
this.openingBalances = tree.getAccountByName('Opening Balances', 2);
|
||||
});
|
||||
|
||||
this.form.get('type').valueChanges.subscribe(val => {
|
||||
if(val === 'openingBalance') {
|
||||
this.acc.collapse('toggle-1');
|
||||
this.acc.expand('toggle-2');
|
||||
this.form.patchValue({description: 'Opening Balance'});
|
||||
}
|
||||
})
|
||||
|
||||
this.form.get('firstAccountPrimary').valueChanges.subscribe(val => {
|
||||
if(val === 'other') {
|
||||
if (val === 'other') {
|
||||
return;
|
||||
}
|
||||
|
||||
this.acc.collapse('toggle-1');
|
||||
this.acc.expand('toggle-2');
|
||||
|
||||
let splits = this.form.get('splits') as FormArray;
|
||||
|
||||
if (splits.length > 0) {
|
||||
splits.at(0).patchValue({
|
||||
accountId: val
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
this.form.get('firstAccountSecondary').valueChanges.subscribe(val => {
|
||||
if (this.form.value.type === 'openingBalance') {
|
||||
this.acc.collapse('toggle-1');
|
||||
this.acc.expand('toggle-3');
|
||||
this.acc.expand('toggle-4');
|
||||
this.form.patchValue({
|
||||
description: 'Opening Balance',
|
||||
firstAccountPrimary: 'other',
|
||||
secondAccountPrimary: this.openingBalances.id
|
||||
});
|
||||
this.focusAmount();
|
||||
let splits = this.form.get('splits') as FormArray;
|
||||
|
||||
if (splits.length > 1) {
|
||||
let firstAccount = this.getFirstAccount();
|
||||
let secondAccount = this.openingBalances;
|
||||
splits.at(0).patchValue({
|
||||
accountId: firstAccount.id
|
||||
});
|
||||
splits.at(1).patchValue({
|
||||
accountId: secondAccount.id
|
||||
});
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
this.acc.collapse('toggle-1');
|
||||
this.acc.expand('toggle-2');
|
||||
|
||||
let splits = this.form.get('splits') as FormArray;
|
||||
|
||||
if (splits.length > 0) {
|
||||
let account = this.getFirstAccount();
|
||||
splits.at(0).patchValue({
|
||||
accountId: account.id
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
this.form.get('secondAccountPrimary').valueChanges.subscribe(val => {
|
||||
if(val === 'other') {
|
||||
if (val === 'other') {
|
||||
return;
|
||||
}
|
||||
|
||||
this.acc.collapse('toggle-2');
|
||||
this.acc.expand('toggle-3');
|
||||
this.acc.expand('toggle-4');
|
||||
this.focusAmount();
|
||||
|
||||
let splits = this.form.get('splits') as FormArray;
|
||||
|
||||
if (splits.length > 1) {
|
||||
splits.at(1).patchValue({
|
||||
accountId: val
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
this.form.get('secondAccountSecondary').valueChanges.subscribe(val => {
|
||||
this.acc.collapse('toggle-2');
|
||||
this.acc.expand('toggle-3');
|
||||
this.acc.expand('toggle-4');
|
||||
this.focusAmount();
|
||||
|
||||
let splits = this.form.get('splits') as FormArray;
|
||||
|
||||
if (splits.length > 1) {
|
||||
splits.at(1).patchValue({
|
||||
accountId: val
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
this.form.get('amount').valueChanges.subscribe(amount => {
|
||||
let type = this.form.get('type').value;
|
||||
let splits = this.form.get('splits') as FormArray;
|
||||
|
||||
if (type === 'expense') {
|
||||
splits.at(0).patchValue({
|
||||
debit: amount
|
||||
});
|
||||
splits.at(1).patchValue({
|
||||
credit: amount
|
||||
});
|
||||
} else if (type === 'income') {
|
||||
splits.at(0).patchValue({
|
||||
credit: amount
|
||||
});
|
||||
splits.at(1).patchValue({
|
||||
debit: amount
|
||||
});
|
||||
} else if (type === 'openingBalance') {
|
||||
let firstAccount = this.getFirstAccount();
|
||||
|
||||
if (firstAccount.debitBalance) {
|
||||
splits.at(0).patchValue({
|
||||
debit: amount
|
||||
});
|
||||
splits.at(1).patchValue({
|
||||
credit: amount
|
||||
});
|
||||
} else {
|
||||
splits.at(0).patchValue({
|
||||
credit: amount
|
||||
});
|
||||
splits.at(1).patchValue({
|
||||
debit: amount
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
onSubmit() {
|
||||
let account = new AccountApi(this.form.value);
|
||||
account.id = Util.newGuid();
|
||||
let parentAccount = this.accountTree.accountMap[account.parent];
|
||||
this.error = null;
|
||||
|
||||
if(!parentAccount) {
|
||||
this.error = new AppError('Invalid parent account');
|
||||
let date = new Date();
|
||||
let formDate = Util.getDateFromLocalDateString(this.form.value.date);
|
||||
|
||||
if (formDate.getTime()) {
|
||||
// make the time be at the very end of the day
|
||||
formDate.setHours(23, 59, 59, 999);
|
||||
}
|
||||
|
||||
let sameDay = formDate.getFullYear() === date.getFullYear() &&
|
||||
formDate.getMonth() === date.getMonth() &&
|
||||
formDate.getDate() === date.getDate();
|
||||
|
||||
if (formDate.getTime() && !sameDay) {
|
||||
date = formDate;
|
||||
}
|
||||
|
||||
let tx = new Transaction({
|
||||
id: Util.newGuid(),
|
||||
description: this.form.value.description,
|
||||
date: date,
|
||||
splits: []
|
||||
});
|
||||
|
||||
for (let i = 0; i < this.form.value.splits.length; i++) {
|
||||
let split = this.form.value.splits[i];
|
||||
let account = this.accountTree.accountMap[split.accountId];
|
||||
|
||||
if (!account) {
|
||||
this.error = new AppError('Invalid account');
|
||||
return;
|
||||
}
|
||||
|
||||
let org = this.orgService.getCurrentOrg();
|
||||
account.orgId = org.id;
|
||||
account.debitBalance = parentAccount.debitBalance;
|
||||
account.currency = account.currency || parentAccount.currency;
|
||||
account.precision = account.precision !== null ? account.precision : parentAccount.precision;
|
||||
let amount = split.debit ? parseFloat(split.debit) : -parseFloat(split.credit);
|
||||
amount = Math.round(amount * Math.pow(10, account.precision));
|
||||
|
||||
this.accountService.newAccount(account)
|
||||
.subscribe(
|
||||
account => {
|
||||
this.router.navigate(['/accounts']);
|
||||
},
|
||||
err => {
|
||||
this.error = err;
|
||||
tx.splits.push(new Split({
|
||||
accountId: split.accountId,
|
||||
amount: amount,
|
||||
nativeAmount: amount
|
||||
}));
|
||||
}
|
||||
);
|
||||
|
||||
this.log.debug(tx);
|
||||
|
||||
this.txService.newTransaction(tx)
|
||||
.subscribe(tx => {
|
||||
this.router.navigate(['/dashboard']);
|
||||
}, error => {
|
||||
this.error = error;
|
||||
});
|
||||
}
|
||||
|
||||
getExpenseAccounts() {
|
||||
@@ -199,7 +334,7 @@ export class NewTransactionPage {
|
||||
id: account.id,
|
||||
name: account.name,
|
||||
label: this.accountTree.getAccountLabel(account, depth),
|
||||
hidden: i < this.numAccountsShown ? false: true
|
||||
hidden: i < this.numAccountsShown ? false : true
|
||||
}
|
||||
});
|
||||
|
||||
@@ -210,19 +345,19 @@ export class NewTransactionPage {
|
||||
let aAlpha = a.label.charCodeAt(0) >= 65 && a.label.charCodeAt(0) <= 122;
|
||||
let bAlpha = b.label.charCodeAt(0) >= 65 && b.label.charCodeAt(0) <= 122;
|
||||
|
||||
if(!aAlpha && bAlpha) {
|
||||
if (!aAlpha && bAlpha) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(aAlpha && !bAlpha) {
|
||||
if (aAlpha && !bAlpha) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(a.label > b.label) {
|
||||
if (a.label > b.label) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(a.label < b.label) {
|
||||
if (a.label < b.label) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -240,9 +375,9 @@ export class NewTransactionPage {
|
||||
|
||||
let type = this.form.value.type;
|
||||
|
||||
if(type) {
|
||||
if (type) {
|
||||
str += type.charAt(0).toUpperCase() + type.substr(1);
|
||||
if(account) {
|
||||
if (account) {
|
||||
str += ' (' + account.name + ')';
|
||||
}
|
||||
}
|
||||
@@ -250,12 +385,12 @@ export class NewTransactionPage {
|
||||
return str;
|
||||
}
|
||||
|
||||
getTitle() {
|
||||
getToggle2Title() {
|
||||
let account = this.getSecondAccount();
|
||||
|
||||
if(this.form.value.type === 'income') {
|
||||
if (this.form.value.type === 'income') {
|
||||
return 'Where was the money sent? ' + (account ? account.name : '');
|
||||
} else if(this.form.value.type === 'openingBalance') {
|
||||
} else if (this.form.value.type === 'openingBalance') {
|
||||
return 'What account? ' + (account ? account.name : '');
|
||||
}
|
||||
|
||||
@@ -263,30 +398,119 @@ export class NewTransactionPage {
|
||||
}
|
||||
|
||||
getFirstAccount() {
|
||||
if(!this.accountTree) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if(this.form.value.firstAccountPrimary && this.form.value.firstAccountPrimary !== 'other') {
|
||||
if (this.form.value.firstAccountPrimary && this.form.value.firstAccountPrimary !== 'other') {
|
||||
return this.accountTree.accountMap[this.form.value.firstAccountPrimary];
|
||||
}
|
||||
|
||||
return this.accountTree.accountMap[this.form.value.firstAccountSecondary];
|
||||
}
|
||||
|
||||
getSecondAccount() {
|
||||
if(!this.accountTree) {
|
||||
return null;
|
||||
getFirstAccountAmount() {
|
||||
let account = this.getFirstAccount();
|
||||
|
||||
switch (this.form.value.type) {
|
||||
case 'expense':
|
||||
return this.form.value.amount * Math.pow(10, account.precision);
|
||||
case 'income':
|
||||
return -this.form.value.amount * Math.pow(10, account.precision);
|
||||
case 'openingBalance':
|
||||
return this.form.value.amount * Math.pow(10, account.precision)
|
||||
* (account.debitBalance ? 1 : -1);
|
||||
}
|
||||
}
|
||||
|
||||
if(this.form.value.secondAccountPrimary && this.form.value.secondAccountPrimary !== 'other') {
|
||||
getSecondAccount() {
|
||||
if (this.form.value.secondAccountPrimary && this.form.value.secondAccountPrimary !== 'other') {
|
||||
return this.accountTree.accountMap[this.form.value.secondAccountPrimary];
|
||||
}
|
||||
|
||||
return this.accountTree.accountMap[this.form.value.secondAccountSecondary];
|
||||
}
|
||||
|
||||
getSecondAccountAmount() {
|
||||
let firstAccount = this.getFirstAccount();
|
||||
let secondAccount = this.getSecondAccount();
|
||||
|
||||
switch (this.form.value.type) {
|
||||
case 'expense':
|
||||
return -this.form.value.amount * Math.pow(10, secondAccount.precision);
|
||||
case 'income':
|
||||
return this.form.value.amount * Math.pow(10, secondAccount.precision);
|
||||
case 'openingBalance':
|
||||
return this.form.value.amount * Math.pow(10, secondAccount.precision)
|
||||
* (firstAccount.debitBalance ? -1 : 1);
|
||||
}
|
||||
}
|
||||
|
||||
addSplit() {
|
||||
let splits = this.form.get('splits') as FormArray;
|
||||
|
||||
let control = new FormGroup({
|
||||
accountId: new FormControl(),
|
||||
debit: new FormControl(),
|
||||
credit: new FormControl()
|
||||
}, { updateOn: 'blur' });
|
||||
|
||||
control.valueChanges.subscribe(val => {
|
||||
this.fillEmptySplit();
|
||||
});
|
||||
splits.push(control);
|
||||
|
||||
this.fillEmptySplit();
|
||||
}
|
||||
|
||||
fillEmptySplit() {
|
||||
// Total up splits and fill in any empty split with the leftover value
|
||||
let splits = this.form.get('splits') as FormArray;
|
||||
let amount = 0;
|
||||
let emptySplit: AbstractControl;
|
||||
for (let i = 0; i < splits.length; i++) {
|
||||
let split = splits.at(i);
|
||||
amount += parseFloat(split.get('debit').value) || 0;
|
||||
amount -= parseFloat(split.get('credit').value) || 0;
|
||||
|
||||
if (!split.get('debit').value && !split.get('credit').value) {
|
||||
emptySplit = split;
|
||||
}
|
||||
}
|
||||
|
||||
if (emptySplit) {
|
||||
let precision = 2;
|
||||
|
||||
let accountId = emptySplit.get('accountId').value;
|
||||
let account = null;
|
||||
|
||||
if (this.accountTree && accountId) {
|
||||
account = this.accountTree.accountMap[emptySplit.get('accountId').value];
|
||||
}
|
||||
|
||||
if (account) {
|
||||
precision = account.precision;
|
||||
}
|
||||
|
||||
amount = this.round(-amount, precision);
|
||||
|
||||
if (amount) {
|
||||
emptySplit.patchValue({
|
||||
debit: amount >= 0 ? amount : '',
|
||||
credit: amount < 0 ? -amount : ''
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
round(amount, precision) {
|
||||
return Math.round(amount * Math.pow(10, precision)) / Math.pow(10, precision);
|
||||
}
|
||||
|
||||
focusAmount() {
|
||||
// TODO Not sure how to get rid of this hack
|
||||
setTimeout(() => {
|
||||
if (this.amount) {
|
||||
this.amount.nativeElement.focus();
|
||||
}
|
||||
}, 1);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -87,3 +87,11 @@ a:hover {
|
||||
padding: 0 0.5rem;
|
||||
}
|
||||
}
|
||||
|
||||
.positive {
|
||||
color: $positive;
|
||||
}
|
||||
|
||||
.negative {
|
||||
color: $negative;
|
||||
}
|
||||
Reference in New Issue
Block a user