use timezone everywhere

This commit is contained in:
Patrick Nagurny
2019-06-27 14:11:05 -04:00
parent ca871a8021
commit b602cb1740
21 changed files with 150 additions and 114 deletions

View File

@@ -590,13 +590,6 @@ export class AccountService {
return this.apiService.deleteAccount(id); return this.apiService.deleteAccount(id);
} }
getPeriodStart(): Date {
let date = new Date();
date.setDate(1);
date.setHours(0, 0, 0, 0);
return date;
}
createDefaultAccounts(tree: AccountTree): Observable<any> { createDefaultAccounts(tree: AccountTree): Observable<any> {
let assetAccount = tree.getAccountByName('Assets', 1); let assetAccount = tree.getAccountByName('Assets', 1);
let equityAccount = tree.getAccountByName('Equity', 1); let equityAccount = tree.getAccountByName('Equity', 1);

View File

@@ -56,7 +56,7 @@
</div> </div>
<div class="row" *ngFor="let recentTx of recentTxs" [routerLink]="'/accounts/'+recentTx.account.id+'/transactions'" [ngClass]="{hidden: recentTx.hidden}"> <div class="row" *ngFor="let recentTx of recentTxs" [routerLink]="'/accounts/'+recentTx.account.id+'/transactions'" [ngClass]="{hidden: recentTx.hidden}">
<div class="col-3 col-md-2 date"> <div class="col-3 col-md-2 date">
{{recentTx.tx.date | date:"M/d"}} {{recentTx.tx.date | datetz:"M/D":org.timezone}}
</div> </div>
<div class="col-5 col-md-6 description"> <div class="col-5 col-md-6 description">
{{recentTx.tx.description}} {{recentTx.tx.description}}

View File

@@ -7,6 +7,7 @@ import { SessionService } from '../core/session.service';
import { Transaction, Split } from '../shared/transaction'; import { Transaction, Split } from '../shared/transaction';
import { Org } from '../shared/org'; import { Org } from '../shared/org';
import { Account, AccountTree } from '../shared/account'; import { Account, AccountTree } from '../shared/account';
import { Util } from '../shared/util';
import { TxListPage } from '../transaction/list'; import { TxListPage } from '../transaction/list';
import { IncomeReport } from '../reports/income'; import { IncomeReport } from '../reports/income';
import { Observable } from 'rxjs/Observable'; import { Observable } from 'rxjs/Observable';
@@ -46,11 +47,12 @@ export class DashboardPage implements OnInit {
ngOnInit() { ngOnInit() {
this.sessionService.setLoading(true); this.sessionService.setLoading(true);
this.log.debug('dashboard init'); this.log.debug('dashboard init');
let periodStart = this.accountService.getPeriodStart();
this.org = this.orgService.getCurrentOrg(); this.org = this.orgService.getCurrentOrg();
this.log.debug('org', this.org); this.log.debug('org', this.org);
let periodStart = Util.getPeriodStart(this.org.timezone);
let tree$ = this.accountService.getAccountTreeWithPeriodBalance(periodStart); let tree$ = this.accountService.getAccountTreeWithPeriodBalance(periodStart);
tree$.do(tree => { tree$.do(tree => {

View File

@@ -13,6 +13,8 @@ import {
import { Util } from '../shared/util'; import { Util } from '../shared/util';
import { PriceService } from '../core/price.service'; import { PriceService } from '../core/price.service';
import { Price } from '../shared/price'; import { Price } from '../shared/price';
import { SessionService } from '../core/session.service';
import { Org } from '../shared/org';
import { Observable } from 'rxjs/Observable'; import { Observable } from 'rxjs/Observable';
@Component({ @Component({
@@ -23,15 +25,18 @@ import { Observable } from 'rxjs/Observable';
export class PriceModal { export class PriceModal {
public form: FormGroup; public form: FormGroup;
public error: AppError; public error: AppError;
public org: Org;
private originalDate: Date; private originalDate: Date;
constructor( constructor(
public activeModal: NgbActiveModal, public activeModal: NgbActiveModal,
private log: Logger, private log: Logger,
private priceService: PriceService, private priceService: PriceService,
private sessionService: SessionService,
private fb: FormBuilder private fb: FormBuilder
) { ) {
let dateString = Util.getLocalDateString(new Date()); this.org = this.sessionService.getOrg();
let dateString = Util.getLocalDateString(new Date(), this.org.timezone);
this.form = fb.group({ this.form = fb.group({
'id': [null], 'id': [null],
@@ -47,7 +52,7 @@ export class PriceModal {
this.form.patchValue({ this.form.patchValue({
id: data.id, id: data.id,
currency: data.currency, currency: data.currency,
date: Util.getLocalDateString(data.date), date: Util.getLocalDateString(data.date, this.org.timezone),
price: data.price price: data.price
}); });
} }
@@ -56,18 +61,11 @@ export class PriceModal {
this.error = null; this.error = null;
let date = this.form.value.id ? this.originalDate : new Date(); let date = this.form.value.id ? this.originalDate : new Date();
let formDate = Util.getDateFromLocalDateString(this.form.value.date); let formDate = Util.getDateFromLocalDateString(this.form.value.date, this.org.timezone);
if(formDate.getTime()) { if(formDate.getTime() && !Util.isSameDay(date, formDate, this.org.timezone)) {
// make the time be at the very end of the day // make the time be at the very end of the day
formDate.setHours(23, 59, 59, 999); Util.setEndOfDay(formDate, this.org.timezone);
}
let sameDay = formDate.getFullYear() === date.getFullYear() &&
formDate.getMonth() === date.getMonth() &&
formDate.getDate() === date.getDate();
if(formDate.getTime() && !sameDay) {
date = formDate; date = formDate;
} }

View File

@@ -17,7 +17,7 @@
<ng-container *ngIf="isExpanded(currency)"> <ng-container *ngIf="isExpanded(currency)">
<div class="row" *ngFor="let price of prices$[currency] | async" depth="2"> <div class="row" *ngFor="let price of prices$[currency] | async" depth="2">
<div class="col-4 date"> <div class="col-4 date">
{{price.date | date:"M/d/y"}} {{price.date | datetz:"M/D/YYYY":org.timezone}}
</div> </div>
<div class="col-4 price"> <div class="col-4 price">
{{price.price * multiplier | currencyFormat:org.precision:org.currency}} {{price.price * multiplier | currencyFormat:org.precision:org.currency}}

View File

@@ -14,7 +14,7 @@
<div class="col-6 inflows"> <div class="col-6 inflows">
<div class="container-fluid"> <div class="container-fluid">
<div *ngFor="let item of inflows" class="row"> <div *ngFor="let item of inflows" class="row">
<div class="col-3">{{item.tx.date | date:"M/d/y"}}</div> <div class="col-3">{{item.tx.date | datetz:"M/D/YYYY":org.timezone}}</div>
<div class="col-4">{{item.tx.description}}</div> <div class="col-4">{{item.tx.description}}</div>
<div class="col-3">{{item.amount | currencyFormat:account.precision:account.currency}}</div> <div class="col-3">{{item.amount | currencyFormat:account.precision:account.currency}}</div>
<div class="col-2"> <div class="col-2">
@@ -26,7 +26,7 @@
<div class="col-6 outflows"> <div class="col-6 outflows">
<div class="container-fluid"> <div class="container-fluid">
<div *ngFor="let item of outflows" class="row"> <div *ngFor="let item of outflows" class="row">
<div class="col-3">{{item.tx.date | date:"M/d/y"}}</div> <div class="col-3">{{item.tx.date | datetz:"M/D/YYYY":org.timezone}}</div>
<div class="col-4">{{item.tx.description}}</div> <div class="col-4">{{item.tx.description}}</div>
<div class="col-3">{{item.amount | currencyFormat:account.precision:account.currency}}</div> <div class="col-3">{{item.amount | currencyFormat:account.precision:account.currency}}</div>
<div class="col-2"> <div class="col-2">

View File

@@ -45,6 +45,7 @@ export class ReconcileModal {
public balance: number; public balance: number;
public reconciled: number; public reconciled: number;
public error: AppError; public error: AppError;
public org: Org;
constructor( constructor(
public activeModal: NgbActiveModal, public activeModal: NgbActiveModal,
@@ -52,7 +53,9 @@ export class ReconcileModal {
private txService: TransactionService, private txService: TransactionService,
private sessionService: SessionService, private sessionService: SessionService,
private fb: FormBuilder private fb: FormBuilder
) {} ) {
this.org = this.sessionService.getOrg();
}
setData(account: Account, rec: Reconciliation) { setData(account: Account, rec: Reconciliation) {
this.account = account; this.account = account;

View File

@@ -53,7 +53,7 @@
<h2>Past Reconciliations</h2> <h2>Past Reconciliations</h2>
<div *ngFor="let rec of pastReconciliations; index as i"> <div *ngFor="let rec of pastReconciliations; index as i">
Period: {{rec.startDate | date:"M/d/y"}} - {{rec.endDate | date:"M/d/y"}}<br> Period: {{rec.startDate | datetz:"M/D/YYYY":org.timezone}} - {{rec.endDate | datetz:"M/D/YYYY":org.timezone}}<br>
Beginning Balance: {{rec.startBalance | currencyFormat:account.precision:account.currency}}<br> Beginning Balance: {{rec.startBalance | currencyFormat:account.precision:account.currency}}<br>
Ending Balance: {{rec.endBalance | currencyFormat:account.precision:account.currency}}<br> Ending Balance: {{rec.endBalance | currencyFormat:account.precision:account.currency}}<br>
<a *ngIf="i === 0" [routerLink]="" (click)="delete()">Delete</a> <a *ngIf="i === 0" [routerLink]="" (click)="delete()">Delete</a>

View File

@@ -14,6 +14,7 @@ import { OrgService } from '../core/org.service';
import { TransactionService } from '../core/transaction.service'; import { TransactionService } from '../core/transaction.service';
import { Account, AccountApi, AccountTree } from '../shared/account'; import { Account, AccountApi, AccountTree } from '../shared/account';
import { Transaction } from '../shared/transaction'; import { Transaction } from '../shared/transaction';
import { Org } from '../shared/org';
import { AppError } from '../shared/error'; import { AppError } from '../shared/error';
import { Util } from '../shared/util'; import { Util } from '../shared/util';
import { NgbModal, ModalDismissReasons } from '@ng-bootstrap/ng-bootstrap'; import { NgbModal, ModalDismissReasons } from '@ng-bootstrap/ng-bootstrap';
@@ -37,6 +38,7 @@ export class ReconcilePage {
public pastReconciliations: Reconciliation[]; public pastReconciliations: Reconciliation[];
public unreconciledTxs: Transaction[]; public unreconciledTxs: Transaction[];
public error: AppError; public error: AppError;
public org: Org;
private accountTree: AccountTree; private accountTree: AccountTree;
@ViewChild('confirmDeleteModal') confirmDeleteModal: ElementRef; @ViewChild('confirmDeleteModal') confirmDeleteModal: ElementRef;
@@ -50,7 +52,7 @@ export class ReconcilePage {
private modalService: NgbModal, private modalService: NgbModal,
private sessionService: SessionService) { private sessionService: SessionService) {
let org = this.orgService.getCurrentOrg(); this.org = this.orgService.getCurrentOrg();
this.accountForm = fb.group({ this.accountForm = fb.group({
'accountId': [null, Validators.required] 'accountId': [null, Validators.required]
}); });
@@ -85,8 +87,8 @@ export class ReconcilePage {
let value = this.newReconcile.getRawValue(); let value = this.newReconcile.getRawValue();
let rec = new Reconciliation(); let rec = new Reconciliation();
rec.startDate = Util.getDateFromLocalDateString(value.startDate); rec.startDate = Util.getDateFromLocalDateString(value.startDate, this.org.timezone);
rec.endDate = Util.getDateFromLocalDateString(value.endDate); rec.endDate = Util.getDateFromLocalDateString(value.endDate, this.org.timezone);
rec.startBalance = Math.round(parseFloat(value.startBalance) * Math.pow(10, this.account.precision)); rec.startBalance = Math.round(parseFloat(value.startBalance) * Math.pow(10, this.account.precision));
rec.endBalance = Math.round(parseFloat(value.endBalance) * Math.pow(10, this.account.precision)); rec.endBalance = Math.round(parseFloat(value.endBalance) * Math.pow(10, this.account.precision));
@@ -104,7 +106,7 @@ export class ReconcilePage {
this.newReconcile.patchValue( this.newReconcile.patchValue(
{ {
startDate: Util.getLocalDateString(rec.endDate), startDate: Util.getLocalDateString(rec.endDate, this.org.timezone),
startBalance: rec.endBalance / Math.pow(10, this.account.precision), startBalance: rec.endBalance / Math.pow(10, this.account.precision),
endBalance: 0, endBalance: 0,
endDate: '' endDate: ''
@@ -201,7 +203,7 @@ export class ReconcilePage {
if(!dates.length) { if(!dates.length) {
if(firstStartDate) { if(firstStartDate) {
this.newReconcile.patchValue({startDate: Util.getLocalDateString(firstStartDate)}); this.newReconcile.patchValue({startDate: Util.getLocalDateString(firstStartDate, this.org.timezone)});
} }
return; return;
} }
@@ -226,7 +228,7 @@ export class ReconcilePage {
this.newReconcile.patchValue( this.newReconcile.patchValue(
{ {
startDate: Util.getLocalDateString(lastRec.endDate), startDate: Util.getLocalDateString(lastRec.endDate, this.org.timezone),
startBalance: lastRec.endBalance / Math.pow(10, this.account.precision) startBalance: lastRec.endBalance / Math.pow(10, this.account.precision)
} }
); );
@@ -270,7 +272,7 @@ export class ReconcilePage {
if(lastRec) { if(lastRec) {
this.newReconcile.patchValue( this.newReconcile.patchValue(
{ {
startDate: Util.getLocalDateString(lastRec.endDate), startDate: Util.getLocalDateString(lastRec.endDate, this.org.timezone),
startBalance: lastRec.endBalance / Math.pow(10, this.account.precision) startBalance: lastRec.endBalance / Math.pow(10, this.account.precision)
} }
); );

View File

@@ -1,4 +1,4 @@
<h1>Balance Sheet<br>{{date | date:"shortDate"}} (<a [routerLink]="" (click)="toggleShowOptionsForm()">options</a>)</h1> <h1>Balance Sheet<br>{{date.getTime() - 1 | datetz:"M/D/YYYY":org.timezone}} (<a [routerLink]="" (click)="toggleShowOptionsForm()">options</a>)</h1>
<div class="section"> <div class="section">
<div *ngIf="showOptionsForm" class="card card-body"> <div *ngIf="showOptionsForm" class="card card-body">

View File

@@ -62,15 +62,16 @@ export class BalanceSheetReport {
} }
} }
this.org = this.orgService.getCurrentOrg();
this.form = fb.group({ this.form = fb.group({
date: [Util.getLocalDateStringExcl(this.date), Validators.required], date: [Util.getLocalDateStringExcl(this.date, this.org.timezone), Validators.required],
priceSource: [this.priceSource, Validators.required] priceSource: [this.priceSource, Validators.required]
}); });
} }
ngOnInit() { ngOnInit() {
this.sessionService.setLoading(true); this.sessionService.setLoading(true);
this.org = this.orgService.getCurrentOrg();
this.amounts = {}; this.amounts = {};
this.assetAccount = null; this.assetAccount = null;
@@ -133,7 +134,7 @@ export class BalanceSheetReport {
this.treeSubscription.unsubscribe(); this.treeSubscription.unsubscribe();
//this.dataService.setLoading(true); //this.dataService.setLoading(true);
this.showOptionsForm = false; this.showOptionsForm = false;
this.date = Util.getDateFromLocalDateStringExcl(this.form.value.date); this.date = Util.getDateFromLocalDateStringExcl(this.form.value.date, this.org.timezone);
this.priceSource = this.form.value.priceSource; this.priceSource = this.form.value.priceSource;
let reportData = this.configService.get('reportData'); let reportData = this.configService.get('reportData');

View File

@@ -1,4 +1,4 @@
<h1>Income Statement<br>{{startDate | date:"shortDate"}} - {{endDate.getTime() - 1 | date:"shortDate"}} (<a [routerLink]="" (click)="toggleShowDateForm()">edit</a>)</h1> <h1>Income Statement<br>{{startDate | datetz:"M/D/YYYY":org.timezone}} - {{endDate.getTime() - 1 | datetz:"M/D/YYYY":org.timezone}} (<a [routerLink]="" (click)="toggleShowDateForm()">edit</a>)</h1>
<div class="section"> <div class="section">
<form *ngIf="showDateForm" [formGroup]="form" (ngSubmit)="onSubmit()"> <form *ngIf="showDateForm" [formGroup]="form" (ngSubmit)="onSubmit()">

View File

@@ -44,10 +44,16 @@ export class IncomeReport {
private orgService: OrgService, private orgService: OrgService,
private configService: ConfigService, private configService: ConfigService,
private sessionService: SessionService) { private sessionService: SessionService) {
}
ngOnInit() {
this.sessionService.setLoading(true);
this.org = this.orgService.getCurrentOrg();
this.startDate = new Date(); this.startDate = new Date();
Util.setFirstOfMonth(this.startDate); Util.setFirstOfMonth(this.startDate, this.org.timezone);
Util.setBeginOfDay(this.startDate); Util.setBeginOfDay(this.startDate, this.org.timezone);
this.endDate = Util.getOneMonthLater(this.startDate); this.endDate = Util.getOneMonthLater(this.startDate, this.org.timezone);
let reportData = this.configService.get('reportData'); let reportData = this.configService.get('reportData');
@@ -62,15 +68,10 @@ export class IncomeReport {
} }
} }
this.form = fb.group({ this.form = this.fb.group({
startDate: [Util.getLocalDateString(this.startDate), Validators.required], startDate: [Util.getLocalDateString(this.startDate, this.org.timezone), Validators.required],
endDate: [Util.getLocalDateStringExcl(this.endDate), Validators.required] endDate: [Util.getLocalDateStringExcl(this.endDate, this.org.timezone), Validators.required]
}); });
}
ngOnInit() {
this.sessionService.setLoading(true);
this.org = this.orgService.getCurrentOrg();
this.treeSubscription = this.accountService.getAccountTreeWithPeriodBalance(this.startDate, this.endDate) this.treeSubscription = this.accountService.getAccountTreeWithPeriodBalance(this.startDate, this.endDate)
.subscribe(tree => { .subscribe(tree => {
@@ -90,8 +91,8 @@ export class IncomeReport {
this.treeSubscription.unsubscribe(); this.treeSubscription.unsubscribe();
//this.dataService.setLoading(true); //this.dataService.setLoading(true);
this.showDateForm = false; this.showDateForm = false;
this.startDate = Util.getDateFromLocalDateString(this.form.value.startDate); this.startDate = Util.getDateFromLocalDateString(this.form.value.startDate, this.org.timezone);
this.endDate = Util.getDateFromLocalDateStringExcl(this.form.value.endDate); this.endDate = Util.getDateFromLocalDateStringExcl(this.form.value.endDate, this.org.timezone);
let reportData = this.configService.get('reportData'); let reportData = this.configService.get('reportData');

View File

@@ -0,0 +1,14 @@
import { Pipe, PipeTransform } from '@angular/core';
//import * as moment from 'moment-timezone/builds/moment-timezone-with-data-2012-2022.min';
import * as moment from 'moment-timezone';
@Pipe({name: 'datetz'})
export class DateTzPipe implements PipeTransform {
constructor() {
}
transform(date: Date, format: string, tz: string): string {
let m = moment(date).tz(tz || moment.tz.guess());
return m.format(format);
}
}

View File

@@ -5,6 +5,7 @@ export class Org {
name: string; name: string;
currency: string; currency: string;
precision: number; precision: number;
timezone: string;
constructor(options: any = {}) { constructor(options: any = {}) {
this.id = options.id; this.id = options.id;
this.inserted = options.inserted ? new Date(options.inserted) : null; this.inserted = options.inserted ? new Date(options.inserted) : null;
@@ -12,5 +13,6 @@ export class Org {
this.name = options.name; this.name = options.name;
this.currency = options.currency; this.currency = options.currency;
this.precision = options.precision && parseInt(options.precision); this.precision = options.precision && parseInt(options.precision);
this.timezone = options.timezone;
} }
} }

View File

@@ -3,11 +3,12 @@ import { DecimalPipe } from '@angular/common';
import { CurrencyFormatPipe } from './currency-format.pipe'; import { CurrencyFormatPipe } from './currency-format.pipe';
import { AccountNamePipe } from './account-name.pipe'; import { AccountNamePipe } from './account-name.pipe';
import { AccountBalancePipe } from './account-balance.pipe'; import { AccountBalancePipe } from './account-balance.pipe';
import { DateTzPipe } from './datetz.pipe';
@NgModule({ @NgModule({
imports: [], imports: [],
declarations: [CurrencyFormatPipe, AccountNamePipe, AccountBalancePipe], declarations: [CurrencyFormatPipe, AccountNamePipe, AccountBalancePipe, DateTzPipe],
exports: [CurrencyFormatPipe, AccountNamePipe, AccountBalancePipe], exports: [CurrencyFormatPipe, AccountNamePipe, AccountBalancePipe, DateTzPipe],
providers: [DecimalPipe, CurrencyFormatPipe] providers: [DecimalPipe, CurrencyFormatPipe]
}) })
export class SharedModule { } export class SharedModule { }

View File

@@ -4,8 +4,8 @@ import * as moment from 'moment-timezone';
const defaultTz = moment.tz.guess(); const defaultTz = moment.tz.guess();
export class Util { export class Util {
static getLocalDateString(input: Date, tz: string = defaultTz) { static getLocalDateString(input: Date, tz: string) {
let m = moment(input).tz(tz); let m = moment(input).tz(tz || defaultTz);
let year = m.format('YYYY'); let year = m.format('YYYY');
let month = m.format('MM'); let month = m.format('MM');
@@ -22,8 +22,8 @@ export class Util {
return year + '-' + month + '-' + date; return year + '-' + month + '-' + date;
} }
static getLocalDateStringExcl(input: Date, tz: string = defaultTz) { static getLocalDateStringExcl(input: Date, tz: string) {
let m = moment(input.getTime() - 1).tz(tz); let m = moment(input.getTime() - 1).tz(tz || defaultTz);
let year = m.format('YYYY'); let year = m.format('YYYY');
let month = m.format('MM'); let month = m.format('MM');
@@ -40,10 +40,10 @@ export class Util {
return year + '-' + month + '-' + date; return year + '-' + month + '-' + date;
} }
static getDateFromLocalDateString(input: string, tz: string = defaultTz) { static getDateFromLocalDateString(input: string, tz: string) {
let parts = input.split('-'); let parts = input.split('-');
let m = moment().tz(tz); let m = moment().tz(tz || defaultTz);
m.hours(0); m.hours(0);
m.minutes(0); m.minutes(0);
m.seconds(0); m.seconds(0);
@@ -55,10 +55,10 @@ export class Util {
return m.toDate(); return m.toDate();
} }
static getDateFromLocalDateStringExcl(input: string, tz: string = defaultTz) { static getDateFromLocalDateStringExcl(input: string, tz: string) {
let parts = input.split('-'); let parts = input.split('-');
let m = moment().tz(tz); let m = moment().tz(tz || defaultTz);
m.hours(0); m.hours(0);
m.minutes(0); m.minutes(0);
m.seconds(0); m.seconds(0);
@@ -70,15 +70,15 @@ export class Util {
return m.toDate(); return m.toDate();
} }
static setFirstOfMonth(input: Date, tz: string = defaultTz) { static setFirstOfMonth(input: Date, tz: string) {
let m = moment(input).tz(tz); let m = moment(input).tz(tz || defaultTz);
m.date(1); m.date(1);
input.setTime(m.valueOf()); input.setTime(m.valueOf());
} }
static setBeginOfDay(input: Date, tz: string = defaultTz) { static setBeginOfDay(input: Date, tz: string) {
let m = moment(input).tz(tz); let m = moment(input).tz(tz || defaultTz);
m.hours(0); m.hours(0);
m.minutes(0); m.minutes(0);
@@ -87,8 +87,8 @@ export class Util {
input.setTime(m.valueOf()); input.setTime(m.valueOf());
} }
static setEndOfDay(input: Date, tz: string = defaultTz) { static setEndOfDay(input: Date, tz: string) {
let m = moment(input).tz(tz); let m = moment(input).tz(tz || defaultTz);
m.hours(23); m.hours(23);
m.minutes(59); m.minutes(59);
@@ -97,21 +97,21 @@ export class Util {
input.setTime(m.valueOf()); input.setTime(m.valueOf());
} }
static getOneMonthLater(input: Date, tz: string = defaultTz): Date { static getOneMonthLater(input: Date, tz: string): Date {
let m = moment(input).tz(tz); let m = moment(input).tz(tz || defaultTz);
m.month(m.month() + 1); m.month(m.month() + 1);
return m.toDate(); return m.toDate();
} }
static computeTransactionDate(formDate: Date, txDate: Date, tz: string = defaultTz): Date { static computeTransactionDate(formDate: Date, txDate: Date, tz: string): Date {
if(!formDate || !formDate.getTime()) { if(!formDate || !formDate.getTime()) {
return txDate; return txDate;
} }
let formMoment = moment(formDate).tz(tz); let formMoment = moment(formDate).tz(tz || defaultTz);
let txMoment = moment(txDate).tz(tz); let txMoment = moment(txDate).tz(tz || defaultTz);
// make the time be at the very end of the day // make the time be at the very end of the day
formMoment.hours(23); formMoment.hours(23);
@@ -123,11 +123,45 @@ export class Util {
formMoment.month() === txMoment.month() && formMoment.month() === txMoment.month() &&
formMoment.date() === txMoment.date(); formMoment.date() === txMoment.date();
if(!sameDay) { if(sameDay) {
return formMoment.toDate(); return txDate;
} }
return txDate; if(formDate < txDate) {
// make time end of day for past dates
formMoment.hours(23);
formMoment.minutes(59);
formMoment.seconds(59);
formMoment.milliseconds(999);
} else {
// make time beginning of day for future dates
formMoment.hours(0);
formMoment.minutes(0);
formMoment.seconds(0);
formMoment.milliseconds(0);
}
return formMoment.toDate();
}
static isSameDay(date1: Date, date2: Date, tz: string) {
let m1 = moment(date1).tz(tz || defaultTz);
let m2 = moment(date2).tz(tz || defaultTz);
return m1.year() === m2.year() &&
m1.month() === m2.month() &&
m1.date() === m2.date();
}
static getPeriodStart(tz: string): Date {
let m = moment().tz(tz || defaultTz);
m.date(1);
m.hours(0);
m.minutes(0);
m.seconds(0);
m.milliseconds(0);
return m.toDate();
} }
static newGuid() { static newGuid() {

View File

@@ -50,7 +50,7 @@ export class AdvancedEdit {
this.org = this.orgService.getCurrentOrg(); this.org = this.orgService.getCurrentOrg();
let dateString = Util.getLocalDateString(item.tx.date); let dateString = Util.getLocalDateString(item.tx.date, this.org.timezone);
this.form = new FormGroup({ this.form = new FormGroup({
date: new FormControl(dateString), date: new FormControl(dateString),
@@ -110,20 +110,9 @@ export class AdvancedEdit {
this.error = null; this.error = null;
let date = this.item.tx.id ? this.item.tx.date : new Date(); let date = this.item.tx.id ? this.item.tx.date : new Date();
let formDate = Util.getDateFromLocalDateString(this.form.value.date); let formDate = Util.getDateFromLocalDateString(this.form.value.date, this.org.timezone);
if(formDate.getTime()) { date = Util.computeTransactionDate(formDate, date, this.org.timezone);
// 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({ let tx = new Transaction({
id: this.item.tx.id, id: this.item.tx.id,

View File

@@ -35,7 +35,7 @@
<form [id]="'form' + item.tx.id + item.activeSplitIndex" [formGroup]="item.form" *ngFor="let item of items; let i = index"> <form [id]="'form' + item.tx.id + item.activeSplitIndex" [formGroup]="item.form" *ngFor="let item of items; let i = index">
<div class="row" (click)="editTransaction(item, $event)" [ngClass]="{odd: !(i % 2), editing: item.editing}"> <div class="row" (click)="editTransaction(item, $event)" [ngClass]="{odd: !(i % 2), editing: item.editing}">
<div class="col custom-3 date"> <div class="col custom-3 date">
<span *ngIf="!item.editing" class="date">{{item.tx.date | date:"M/d/y"}}</span> <span *ngIf="!item.editing" class="date">{{item.tx.date | datetz:"M/D/YYYY":org.timezone}}</span>
<input *ngIf="item.editing" type="date" formControlName="date" placeholder="Date" class="form-control" (keyup.enter)="onEnter(item, $event)"/> <input *ngIf="item.editing" type="date" formControlName="date" placeholder="Date" class="form-control" (keyup.enter)="onEnter(item, $event)"/>
</div> </div>
<div class="col custom-7 description"> <div class="col custom-7 description">

View File

@@ -2,6 +2,7 @@ import { Component, Input, OnInit, ViewChild, ElementRef, AfterViewChecked, Rend
import { Logger } from '../core/logger'; import { Logger } from '../core/logger';
import { ActivatedRoute } from '@angular/router'; import { ActivatedRoute } from '@angular/router';
import { TransactionService } from '../core/transaction.service'; import { TransactionService } from '../core/transaction.service';
import { OrgService } from '../core/org.service';
import { AccountService } from '../core/account.service'; import { AccountService } from '../core/account.service';
import { Account, AccountTree } from '../shared/account'; import { Account, AccountTree } from '../shared/account';
import { Transaction, Split} from '../shared/transaction'; import { Transaction, Split} from '../shared/transaction';
@@ -22,6 +23,7 @@ import 'rxjs/add/operator/mergeMap';
import { AdvancedEdit } from './advancededit'; import { AdvancedEdit } from './advancededit';
import { TxItem } from './txitem'; import { TxItem } from './txitem';
import { Subject } from 'rxjs'; import { Subject } from 'rxjs';
import { Org } from '../shared/org';
@Component({ @Component({
selector: 'app-txlist', selector: 'app-txlist',
@@ -34,6 +36,7 @@ export class TxListPage implements OnInit, AfterViewChecked {
public account: Account; public account: Account;
public items: TxItem[]; public items: TxItem[];
public error: AppError; public error: AppError;
public org: Org;
private accountId: string; private accountId: string;
private accountTree: AccountTree; private accountTree: AccountTree;
private balance: number; private balance: number;
@@ -54,6 +57,7 @@ export class TxListPage implements OnInit, AfterViewChecked {
private log: Logger, private log: Logger,
private route: ActivatedRoute, private route: ActivatedRoute,
private txService: TransactionService, private txService: TransactionService,
private orgService: OrgService,
private accountService: AccountService, private accountService: AccountService,
private fb: FormBuilder, private fb: FormBuilder,
private renderer: Renderer, private renderer: Renderer,
@@ -70,6 +74,9 @@ export class TxListPage implements OnInit, AfterViewChecked {
ngOnInit() { ngOnInit() {
this.accountId = this.route.snapshot.paramMap.get('id'); //+this.route.snapshot.paramMap.get('id'); this.accountId = this.route.snapshot.paramMap.get('id'); //+this.route.snapshot.paramMap.get('id');
this.org = this.orgService.getCurrentOrg();
console.log(this.org);
this.accountService.getAccountTree().subscribe(tree => { this.accountService.getAccountTree().subscribe(tree => {
this.account = tree.accountMap[this.accountId]; this.account = tree.accountMap[this.accountId];
@@ -88,7 +95,7 @@ export class TxListPage implements OnInit, AfterViewChecked {
splits: [] splits: []
}); });
newTx.date.setHours(23, 59, 59, 999); Util.setEndOfDay(newTx.date, this.org.timezone);
newTx.splits.push(new Split({ newTx.splits.push(new Split({
accountId: this.account.id accountId: this.account.id
@@ -403,7 +410,7 @@ export class TxListPage implements OnInit, AfterViewChecked {
item.editing = true; item.editing = true;
let dateString = Util.getLocalDateString(item.tx.date); let dateString = Util.getLocalDateString(item.tx.date, this.org.timezone);
this.log.debug(item); this.log.debug(item);
let debit = this.getDebit(item); let debit = this.getDebit(item);
@@ -622,9 +629,9 @@ export class TxListPage implements OnInit, AfterViewChecked {
} }
let date = item.tx.id ? item.tx.date : new Date(); let date = item.tx.id ? item.tx.date : new Date();
let formDate = Util.getDateFromLocalDateString(item.form.value.date); let formDate = Util.getDateFromLocalDateString(item.form.value.date, this.org.timezone);
date = Util.computeTransactionDate(formDate, date); date = Util.computeTransactionDate(formDate, date, this.org.timezone);
let tx = new Transaction({ let tx = new Transaction({
id: item.tx.id, id: item.tx.id,
@@ -707,7 +714,7 @@ export class TxListPage implements OnInit, AfterViewChecked {
splits: [] splits: []
}); });
newTx.date.setHours(23, 59, 59, 999); Util.setEndOfDay(newTx.date, this.org.timezone);
newTx.splits.push(new Split({ newTx.splits.push(new Split({
accountId: this.account.id accountId: this.account.id
@@ -825,11 +832,11 @@ export class TxListPage implements OnInit, AfterViewChecked {
autocomplete(item: TxItem, tx: Transaction) { autocomplete(item: TxItem, tx: Transaction) {
this.log.debug('chose tx', tx); this.log.debug('chose tx', tx);
let formDate = Util.getDateFromLocalDateString(item.form.value.date); let formDate = Util.getDateFromLocalDateString(item.form.value.date, this.org.timezone);
item.tx = new Transaction( item.tx = new Transaction(
{ {
id: item.tx.id, id: item.tx.id,
date: Util.computeTransactionDate(formDate, new Date()), date: Util.computeTransactionDate(formDate, new Date(), this.org.timezone),
description: tx.description, description: tx.description,
splits: tx.splits splits: tx.splits
} }

View File

@@ -17,6 +17,7 @@ import { Util } from '../shared/util';
import { AppError } from '../shared/error'; import { AppError } from '../shared/error';
import { Transaction, Split } from '../shared/transaction'; import { Transaction, Split } from '../shared/transaction';
import { Logger } from '../core/logger'; import { Logger } from '../core/logger';
import { Org } from '../shared/org';
@Component({ @Component({
selector: 'app-txnew', selector: 'app-txnew',
@@ -45,6 +46,7 @@ export class NewTransactionPage {
public openingBalances: Account; public openingBalances: Account;
public accountTree: AccountTree; public accountTree: AccountTree;
public accountMap: any; public accountMap: any;
public org;
@ViewChild('acc') acc: any; @ViewChild('acc') acc: any;
@ViewChild('amount') amount: ElementRef @ViewChild('amount') amount: ElementRef
@@ -57,12 +59,10 @@ export class NewTransactionPage {
private orgService: OrgService, private orgService: OrgService,
private fb: FormBuilder, private fb: FormBuilder,
private log: Logger) { private log: Logger) {
this.numAccountsShown = 3; this.numAccountsShown = 3;
this.org = this.orgService.getCurrentOrg();
let org = this.orgService.getCurrentOrg(); let dateString = Util.getLocalDateString(new Date(), this.org.timezone);
let dateString = Util.getLocalDateString(new Date());
this.form = this.fb.group({ this.form = this.fb.group({
type: ['', Validators.required], type: ['', Validators.required],
firstAccountPrimary: [null, Validators.required], firstAccountPrimary: [null, Validators.required],
@@ -226,20 +226,9 @@ export class NewTransactionPage {
this.error = null; this.error = null;
let date = new Date(); let date = new Date();
let formDate = Util.getDateFromLocalDateString(this.form.value.date); let formDate = Util.getDateFromLocalDateString(this.form.value.date, this.org.timezone);
if (formDate.getTime()) { date = Util.computeTransactionDate(formDate, date, this.org.timezone);
// 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({ let tx = new Transaction({
id: Util.newGuid(), id: Util.newGuid(),