You've already forked openaccounting-web
mirror of
https://github.com/openaccounting/oa-web.git
synced 2025-12-09 09:01:24 +13:00
initial commit
This commit is contained in:
28
src/app/shared/account-balance.pipe.ts
Normal file
28
src/app/shared/account-balance.pipe.ts
Normal file
@@ -0,0 +1,28 @@
|
||||
import { Pipe, PipeTransform } from '@angular/core';
|
||||
import { CurrencyFormatPipe } from './currency-format.pipe';
|
||||
import { Account } from './account';
|
||||
|
||||
@Pipe({name: 'accountBalance'})
|
||||
export class AccountBalancePipe implements PipeTransform {
|
||||
constructor(private currencyFormatPipe: CurrencyFormatPipe) {
|
||||
}
|
||||
|
||||
transform(account: Account, balanceType = 'price'): string {
|
||||
let sign = account.debitBalance ? 1 : -1;
|
||||
|
||||
let nativeBalance = 0;
|
||||
|
||||
switch(balanceType) {
|
||||
case 'cost':
|
||||
nativeBalance = account.totalNativeBalanceCost;
|
||||
break;
|
||||
case 'price':
|
||||
nativeBalance = account.totalNativeBalancePrice;
|
||||
break;
|
||||
default:
|
||||
throw new Error('Invalid balance type ' + balanceType);
|
||||
}
|
||||
|
||||
return this.currencyFormatPipe.transform(sign * nativeBalance, account.orgPrecision, account.orgCurrency);
|
||||
}
|
||||
}
|
||||
21
src/app/shared/account-name.pipe.ts
Normal file
21
src/app/shared/account-name.pipe.ts
Normal file
@@ -0,0 +1,21 @@
|
||||
import { Pipe, PipeTransform } from '@angular/core';
|
||||
|
||||
@Pipe({name: 'accountName'})
|
||||
export class AccountNamePipe implements PipeTransform {
|
||||
constructor() {
|
||||
}
|
||||
|
||||
transform(name: string, depth: number): string {
|
||||
let parts = name.split(':');
|
||||
|
||||
let accountString = '';
|
||||
|
||||
if(!depth) {
|
||||
depth = 1;
|
||||
}
|
||||
|
||||
parts = parts.slice(depth - 1, parts.length);
|
||||
|
||||
return parts.join(':');
|
||||
}
|
||||
}
|
||||
168
src/app/shared/account.ts
Normal file
168
src/app/shared/account.ts
Normal file
@@ -0,0 +1,168 @@
|
||||
export class AccountApi {
|
||||
id: string;
|
||||
orgId: string;
|
||||
inserted: Date;
|
||||
updated: Date;
|
||||
name: string;
|
||||
parent: string;
|
||||
currency: string;
|
||||
precision: number;
|
||||
debitBalance: boolean;
|
||||
balance: number;
|
||||
nativeBalance: number;
|
||||
readOnly: boolean;
|
||||
recentTxCount: number;
|
||||
price: number;
|
||||
constructor(options: any = {}) {
|
||||
this.id = options.id;
|
||||
this.orgId = options.orgId;
|
||||
this.inserted = options.inserted ? new Date(options.inserted): null;
|
||||
this.updated = options.updated ? new Date(options.updated): null;
|
||||
this.name = options.name;
|
||||
this.parent = options.parent ? options.parent : '';
|
||||
this.currency = options.currency;
|
||||
this.precision = options.precision ? parseInt(options.precision) : 0;
|
||||
this.debitBalance = options.debitBalance;
|
||||
this.balance = options.balance;
|
||||
this.nativeBalance = options.nativeBalance;
|
||||
this.readOnly = options.readOnly;
|
||||
this.recentTxCount = options.recentTxCount ? parseInt(options.recentTxCount) : 0;
|
||||
this.price = options.price;
|
||||
}
|
||||
}
|
||||
|
||||
export class Account {
|
||||
id: string;
|
||||
orgId: string;
|
||||
inserted: Date;
|
||||
updated: Date;
|
||||
name: string;
|
||||
fullName: string;
|
||||
parent: Account;
|
||||
currency: string;
|
||||
precision: number;
|
||||
debitBalance: boolean;
|
||||
balance: number;
|
||||
totalBalance: number;
|
||||
nativeBalanceCost: number;
|
||||
totalNativeBalanceCost: number;
|
||||
nativeBalancePrice: number;
|
||||
totalNativeBalancePrice: number;
|
||||
price: number;
|
||||
orgCurrency: string;
|
||||
orgPrecision: number;
|
||||
readOnly: boolean;
|
||||
depth: number;
|
||||
recentTxCount: number;
|
||||
children: Account[];
|
||||
constructor(options: any = {}) {
|
||||
this.id = options.id;
|
||||
this.orgId = options.orgId;
|
||||
this.inserted = options.inserted ? new Date(options.inserted) : null;
|
||||
this.updated = options.updated ? new Date(options.updated) : null;
|
||||
this.name = options.name;
|
||||
this.fullName = options.fullName;
|
||||
this.parent = options.parent;
|
||||
this.currency = options.currency;
|
||||
this.precision = options.precision ? parseInt(options.precision) : 0;
|
||||
this.debitBalance = options.debitBalance || false;
|
||||
this.balance = options.balance || 0;
|
||||
this.totalBalance = options.totalBalance || 0;
|
||||
this.nativeBalanceCost = options.nativeBalance || 0;
|
||||
this.totalNativeBalanceCost = options.totalNativeBalanceCost || options.totalNativeBalance || 0;
|
||||
this.nativeBalancePrice = options.nativeBalancePrice || 0;
|
||||
this.totalNativeBalancePrice = options.totalNativeBalancePrice || 0;
|
||||
this.price = options.price || 0;
|
||||
this.orgCurrency = options.orgCurrency;
|
||||
this.orgPrecision = options.orgPrecision ? parseInt(options.orgPrecision) : 0;
|
||||
this.readOnly = options.readOnly;
|
||||
this.depth = options.depth;
|
||||
this.recentTxCount = options.recentTxCount || 0;
|
||||
this.children = options.children || [];
|
||||
}
|
||||
}
|
||||
|
||||
export class AccountTree {
|
||||
accountMap: { [accountId: number]: Account; };
|
||||
rootAccount: Account;
|
||||
|
||||
constructor(options: any = {}) {
|
||||
this.accountMap = options.accountMap;
|
||||
this.rootAccount = options.rootAccount;
|
||||
}
|
||||
|
||||
getFlattenedAccounts(node?: Account): Account[] {
|
||||
if(!node) {
|
||||
node = this.rootAccount;
|
||||
}
|
||||
|
||||
let flattened = [];
|
||||
|
||||
for(let account of node.children) {
|
||||
flattened.push(account);
|
||||
flattened = flattened.concat(this.getFlattenedAccounts(account));
|
||||
}
|
||||
|
||||
return flattened;
|
||||
}
|
||||
|
||||
getAccountByName (name: string, depth?: number): Account {
|
||||
for(let id in this.accountMap) {
|
||||
let account = this.accountMap[id];
|
||||
|
||||
if(account.name === name) {
|
||||
if(!depth || account.depth === depth) {
|
||||
return account;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
accountIsChildOf(account: Account, parent: Account) {
|
||||
for(let child of parent.children) {
|
||||
if(child.id === account.id) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if(this.accountIsChildOf(account, child)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
getAccountAtoms(node?: Account): Account[] {
|
||||
if(!node) {
|
||||
node = this.rootAccount;
|
||||
}
|
||||
|
||||
let accounts = [];
|
||||
|
||||
for(let i = 0; i < node.children.length; i++) {
|
||||
let child = node.children[i];
|
||||
if(!child.children.length) {
|
||||
accounts.push(child);
|
||||
} else {
|
||||
accounts = accounts.concat(this.getAccountAtoms(child));
|
||||
}
|
||||
}
|
||||
|
||||
return accounts;
|
||||
}
|
||||
|
||||
getAccountLabel(account: Account, depth: number) {
|
||||
let node = account;
|
||||
|
||||
let accountArray = [account.name];
|
||||
|
||||
while(node.parent.depth >= depth) {
|
||||
node = node.parent;
|
||||
accountArray.unshift(node.name);
|
||||
}
|
||||
|
||||
return accountArray.join(':');
|
||||
}
|
||||
}
|
||||
15
src/app/shared/apikey.ts
Normal file
15
src/app/shared/apikey.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
export class ApiKey {
|
||||
id: string;
|
||||
inserted: Date;
|
||||
updated: Date;
|
||||
userId: string;
|
||||
label: string;
|
||||
|
||||
constructor(options: any = {}) {
|
||||
this.id = options.id;
|
||||
this.inserted = options.inserted ? new Date(options.inserted) : null;
|
||||
this.updated = options.updated ? new Date(options.updated) : null;
|
||||
this.userId = options.userId;
|
||||
this.label = options.label;
|
||||
}
|
||||
}
|
||||
13
src/app/shared/config.ts
Normal file
13
src/app/shared/config.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
export class Config {
|
||||
server: string;
|
||||
email: string;
|
||||
password: string; // switch to session based auth
|
||||
defaultOrg: string;
|
||||
reportData: any;
|
||||
constructor(options: any = {}) {
|
||||
this.server = options.server || 'https://openaccounting.io:8080/api';
|
||||
this.email = options.email;
|
||||
this.password = options.password;
|
||||
this.defaultOrg = options.defaultOrg;
|
||||
}
|
||||
}
|
||||
27
src/app/shared/currency-format.pipe.ts
Normal file
27
src/app/shared/currency-format.pipe.ts
Normal file
@@ -0,0 +1,27 @@
|
||||
import { Pipe, PipeTransform } from '@angular/core';
|
||||
import { DecimalPipe } from '@angular/common';
|
||||
|
||||
@Pipe({name: 'currencyFormat'})
|
||||
export class CurrencyFormatPipe implements PipeTransform {
|
||||
constructor(private decimalPipe: DecimalPipe) {
|
||||
}
|
||||
|
||||
transform(amount: number, precision: number, currency = 'USD'): string {
|
||||
if(amount === null || amount === undefined) {
|
||||
return '';
|
||||
}
|
||||
|
||||
let prefix = amount < 0 ? '-' : '';
|
||||
|
||||
if(currency === 'USD') {
|
||||
prefix += '$';
|
||||
}
|
||||
|
||||
let minDigits = Math.min(2, precision);
|
||||
|
||||
return prefix +
|
||||
this.decimalPipe.transform(
|
||||
Math.abs(amount) / Math.pow(10, precision),
|
||||
'1.' + minDigits + '-' + precision);
|
||||
}
|
||||
}
|
||||
8
src/app/shared/error.ts
Normal file
8
src/app/shared/error.ts
Normal file
@@ -0,0 +1,8 @@
|
||||
export class AppError extends Error {
|
||||
constructor(m: string, public code?: number) {
|
||||
super(m);
|
||||
|
||||
// Set the prototype explicitly.
|
||||
Object.setPrototypeOf(this, AppError.prototype);
|
||||
}
|
||||
}
|
||||
17
src/app/shared/invite.ts
Normal file
17
src/app/shared/invite.ts
Normal file
@@ -0,0 +1,17 @@
|
||||
export class Invite {
|
||||
id: string;
|
||||
orgId: string;
|
||||
inserted: Date;
|
||||
updated: Date;
|
||||
email: string;
|
||||
accepted: boolean;
|
||||
|
||||
constructor(options: any = {}) {
|
||||
this.id = options.id;
|
||||
this.orgId = options.orgId;
|
||||
this.inserted = options.inserted ? new Date(options.inserted) : null;
|
||||
this.updated = options.updated ? new Date(options.updated) : null;
|
||||
this.email = options.email;
|
||||
this.accepted = options.accepted;
|
||||
}
|
||||
}
|
||||
19
src/app/shared/message.ts
Normal file
19
src/app/shared/message.ts
Normal file
@@ -0,0 +1,19 @@
|
||||
export class Message {
|
||||
version: string;
|
||||
sequenceNumber: number;
|
||||
type: string;
|
||||
action: string;
|
||||
data: any;
|
||||
|
||||
constructor(options: any = {}) {
|
||||
this.version = options.version;
|
||||
this.sequenceNumber = options.sequenceNumber;
|
||||
this.type = options.type;
|
||||
this.action = options.action;
|
||||
this.data = options.data;
|
||||
}
|
||||
|
||||
toString(): string {
|
||||
return JSON.stringify(this);
|
||||
}
|
||||
}
|
||||
16
src/app/shared/org.ts
Normal file
16
src/app/shared/org.ts
Normal file
@@ -0,0 +1,16 @@
|
||||
export class Org {
|
||||
id: string;
|
||||
inserted: Date;
|
||||
updated: Date;
|
||||
name: string;
|
||||
currency: string;
|
||||
precision: number;
|
||||
constructor(options: any = {}) {
|
||||
this.id = options.id;
|
||||
this.inserted = options.inserted ? new Date(options.inserted) : null;
|
||||
this.updated = options.updated ? new Date(options.updated) : null;
|
||||
this.name = options.name;
|
||||
this.currency = options.currency;
|
||||
this.precision = options.precision && parseInt(options.precision);
|
||||
}
|
||||
}
|
||||
17
src/app/shared/price.ts
Normal file
17
src/app/shared/price.ts
Normal file
@@ -0,0 +1,17 @@
|
||||
export class Price {
|
||||
id: string;
|
||||
currency: string;
|
||||
date: Date;
|
||||
inserted: Date;
|
||||
updated: Date;
|
||||
price: number;
|
||||
|
||||
constructor(options: any = {}) {
|
||||
this.id = options.id;
|
||||
this.currency = options.currency;
|
||||
this.date = options.date ? new Date(options.date) : null;
|
||||
this.inserted = options.inserted ? new Date(options.inserted) : null;
|
||||
this.updated = options.updated ? new Date(options.updated) : null;
|
||||
this.price = options.price;
|
||||
}
|
||||
}
|
||||
6
src/app/shared/session-options.ts
Normal file
6
src/app/shared/session-options.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
export class SessionOptions {
|
||||
createDefaultAccounts: boolean;
|
||||
constructor(options: any = {}) {
|
||||
this.createDefaultAccounts = options.createDefaultAccounts;
|
||||
}
|
||||
};
|
||||
13
src/app/shared/shared.module.ts
Normal file
13
src/app/shared/shared.module.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { DecimalPipe } from '@angular/common';
|
||||
import { CurrencyFormatPipe } from './currency-format.pipe';
|
||||
import { AccountNamePipe } from './account-name.pipe';
|
||||
import { AccountBalancePipe } from './account-balance.pipe';
|
||||
|
||||
@NgModule({
|
||||
imports: [],
|
||||
declarations: [CurrencyFormatPipe, AccountNamePipe, AccountBalancePipe],
|
||||
exports: [CurrencyFormatPipe, AccountNamePipe, AccountBalancePipe],
|
||||
providers: [DecimalPipe, CurrencyFormatPipe]
|
||||
})
|
||||
export class SharedModule { }
|
||||
49
src/app/shared/transaction.ts
Normal file
49
src/app/shared/transaction.ts
Normal file
@@ -0,0 +1,49 @@
|
||||
export class Transaction {
|
||||
id: string;
|
||||
orgId: string;
|
||||
userId: string;
|
||||
date: Date;
|
||||
inserted: Date;
|
||||
updated: Date;
|
||||
description: string;
|
||||
data: any;
|
||||
deleted: boolean;
|
||||
splits: Split[];
|
||||
constructor(options: any = {}) {
|
||||
this.id = options.id;
|
||||
this.orgId = options.id;
|
||||
this.userId = options.id;
|
||||
this.date = options.date ? new Date(options.date) : null;
|
||||
this.inserted = options.inserted ? new Date(options.inserted) : null;
|
||||
this.updated = options.updated ? new Date(options.updated) : null;
|
||||
this.description = options.description;
|
||||
this.data = options.data;
|
||||
this.deleted = options.deleted;
|
||||
this.splits = options.splits ? options.splits.map(split => new Split(split)) : [];
|
||||
}
|
||||
|
||||
getData(): any {
|
||||
try {
|
||||
return JSON.parse(this.data);
|
||||
} catch(e) {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
setData(data: any) {
|
||||
this.data = JSON.stringify(data);
|
||||
}
|
||||
|
||||
// constructor(init?:Partial<Transaction>) {
|
||||
// Object.assign(this, init);
|
||||
// }
|
||||
}
|
||||
|
||||
export class Split {
|
||||
accountId: string;
|
||||
amount: number;
|
||||
nativeAmount: number;
|
||||
constructor(init?:Partial<Split>) {
|
||||
Object.assign(this, init);
|
||||
}
|
||||
}
|
||||
22
src/app/shared/user.ts
Normal file
22
src/app/shared/user.ts
Normal file
@@ -0,0 +1,22 @@
|
||||
export class User {
|
||||
id: string;
|
||||
inserted: Date;
|
||||
updated: Date;
|
||||
firstName: string;
|
||||
lastName: string;
|
||||
email: string;
|
||||
password: string;
|
||||
agreeToTerms: boolean;
|
||||
emailVerified: boolean;
|
||||
constructor(options: any = {}) {
|
||||
this.id = options.id || this.id;
|
||||
this.inserted = options.inserted ? new Date(options.inserted) : null;
|
||||
this.updated = options.updated ? new Date(options.updated) : null;
|
||||
this.firstName = options.firstName || this.firstName;
|
||||
this.lastName = options.lastName || this.lastName;
|
||||
this.email = options.email || this.email;
|
||||
this.password = options.password || this.password;
|
||||
this.agreeToTerms = options.agreeToTerms || false;
|
||||
this.emailVerified = options.emailVerified || this.emailVerified;
|
||||
}
|
||||
}
|
||||
37
src/app/shared/util.ts
Normal file
37
src/app/shared/util.ts
Normal file
@@ -0,0 +1,37 @@
|
||||
export class Util {
|
||||
static getLocalDateString(input: Date) {
|
||||
let year = input.getFullYear().toString();
|
||||
let month = (input.getMonth() + 1).toString();
|
||||
let date = input.getDate().toString();
|
||||
|
||||
if(month.length < 2) {
|
||||
month = '0' + month;
|
||||
}
|
||||
|
||||
if(date.length < 2) {
|
||||
date = '0' + date;
|
||||
}
|
||||
|
||||
return year + '-' + month + '-' + date;
|
||||
}
|
||||
|
||||
static getDateFromLocalDateString(input: string) {
|
||||
let parts = input.split('-');
|
||||
let date = new Date();
|
||||
date.setHours(0, 0, 0, 0);
|
||||
date.setFullYear(parseInt(parts[0]));
|
||||
date.setMonth(parseInt(parts[1]) - 1);
|
||||
date.setDate(parseInt(parts[2]));
|
||||
|
||||
return date;
|
||||
}
|
||||
|
||||
static newGuid() {
|
||||
let arr = new Uint8Array(16);
|
||||
window.crypto.getRandomValues(arr);
|
||||
|
||||
return Array.prototype.map.call(arr, val => {
|
||||
return ('00' + val.toString(16)).slice(-2);
|
||||
}).join('');
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user