Feature: Lazy loading
Lazy loaded everything TODO: The cash flow module when clicking on sub-links, it reloads the whole page, it needs to be diagnosed and fixed, this problem also exists in the other modules TODO: Rename folders and modules such as account to accounts to match the url
This commit is contained in:
9
overlord/src/app/core/account-type.ts
Normal file
9
overlord/src/app/core/account-type.ts
Normal file
@ -0,0 +1,9 @@
|
||||
export class AccountType {
|
||||
id: number;
|
||||
name: string;
|
||||
balanceSheet: boolean;
|
||||
debit: boolean;
|
||||
cashFlowClassification: string;
|
||||
order: number;
|
||||
showInList: boolean;
|
||||
}
|
||||
15
overlord/src/app/core/account.service.spec.ts
Normal file
15
overlord/src/app/core/account.service.spec.ts
Normal file
@ -0,0 +1,15 @@
|
||||
import {inject, TestBed} from '@angular/core/testing';
|
||||
|
||||
import {AccountService} from './account.service';
|
||||
|
||||
describe('AccountService', () => {
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({
|
||||
providers: [AccountService]
|
||||
});
|
||||
});
|
||||
|
||||
it('should be created', inject([AccountService], (service: AccountService) => {
|
||||
expect(service).toBeTruthy();
|
||||
}));
|
||||
});
|
||||
97
overlord/src/app/core/account.service.ts
Normal file
97
overlord/src/app/core/account.service.ts
Normal file
@ -0,0 +1,97 @@
|
||||
import {Injectable} from '@angular/core';
|
||||
import {Observable} from 'rxjs/internal/Observable';
|
||||
import {catchError} from 'rxjs/operators';
|
||||
import {HttpClient, HttpHeaders, HttpParams} from '@angular/common/http';
|
||||
import {Account} from './account';
|
||||
import {ErrorLoggerService} from './error-logger.service';
|
||||
|
||||
const httpOptions = {
|
||||
headers: new HttpHeaders({'Content-Type': 'application/json'})
|
||||
};
|
||||
|
||||
const url = '/api/accounts';
|
||||
const serviceName = 'AccountService';
|
||||
|
||||
@Injectable({providedIn: 'root'})
|
||||
export class AccountService {
|
||||
|
||||
constructor(private http: HttpClient, private log: ErrorLoggerService) {
|
||||
}
|
||||
|
||||
get(id: string): Observable<Account> {
|
||||
const getUrl: string = (id === null) ? `${url}/new` : `${url}/${id}`;
|
||||
return <Observable<Account>>this.http.get<Account>(getUrl)
|
||||
.pipe(
|
||||
catchError(this.log.handleError(serviceName, `get id=${id}`))
|
||||
);
|
||||
}
|
||||
|
||||
list(): Observable<Account[]> {
|
||||
const options = {params: new HttpParams().set('l', '')};
|
||||
return <Observable<Account[]>>this.http.get<Account[]>(url, options)
|
||||
.pipe(
|
||||
catchError(this.log.handleError(serviceName, 'list'))
|
||||
);
|
||||
}
|
||||
|
||||
paymentAutocomplete(term: string): Observable<Account[]> {
|
||||
const options = {params: new HttpParams().set('q', term).set('t', '1')};
|
||||
return <Observable<Account[]>>this.http.get<Account[]>(url, options)
|
||||
.pipe(
|
||||
catchError(this.log.handleError(serviceName, 'list'))
|
||||
);
|
||||
}
|
||||
|
||||
receiptAutocomplete(term: string): Observable<Account[]> {
|
||||
const options = {params: new HttpParams().set('q', term).set('t', '1')};
|
||||
return <Observable<Account[]>>this.http.get<Account[]>(url, options)
|
||||
.pipe(
|
||||
catchError(this.log.handleError(serviceName, 'list'))
|
||||
);
|
||||
}
|
||||
|
||||
save(account: Account): Observable<Account> {
|
||||
return <Observable<Account>>this.http.post<Account>(`${url}/new`, account, httpOptions)
|
||||
.pipe(
|
||||
catchError(this.log.handleError(serviceName, 'save'))
|
||||
);
|
||||
}
|
||||
|
||||
update(account: Account): Observable<Account> {
|
||||
return <Observable<Account>>this.http.put<Account>(`${url}/${account.id}`, account, httpOptions)
|
||||
.pipe(
|
||||
catchError(this.log.handleError(serviceName, 'update'))
|
||||
);
|
||||
}
|
||||
|
||||
saveOrUpdate(account: Account): Observable<Account> {
|
||||
if (!account.id) {
|
||||
return this.save(account);
|
||||
} else {
|
||||
return this.update(account);
|
||||
}
|
||||
}
|
||||
|
||||
delete(id: string): Observable<Account> {
|
||||
return <Observable<Account>>this.http.delete<Account>(`${url}/${id}`, httpOptions)
|
||||
.pipe(
|
||||
catchError(this.log.handleError(serviceName, 'delete'))
|
||||
);
|
||||
}
|
||||
|
||||
autocomplete(term: string): Observable<Account[]> {
|
||||
const options = {params: new HttpParams().set('q', term)};
|
||||
return <Observable<Account[]>>this.http.get<Account[]>(url, options)
|
||||
.pipe(
|
||||
catchError(this.log.handleError(serviceName, 'autocomplete'))
|
||||
);
|
||||
}
|
||||
|
||||
balance(id: string, date: string): Observable<any> {
|
||||
const options = {params: new HttpParams().set('b', 'true').set('d', date)};
|
||||
return <Observable<any>>this.http.get<any>(`${url}/${id}`, options)
|
||||
.pipe(
|
||||
catchError(this.log.handleError(serviceName, 'balance'))
|
||||
);
|
||||
}
|
||||
}
|
||||
18
overlord/src/app/core/account.ts
Normal file
18
overlord/src/app/core/account.ts
Normal file
@ -0,0 +1,18 @@
|
||||
import {AccountType} from './account-type';
|
||||
import {CostCentre} from './cost-centre';
|
||||
|
||||
export class Account {
|
||||
id: string;
|
||||
code: number;
|
||||
name: string;
|
||||
type: AccountType;
|
||||
isActive: boolean;
|
||||
isReconcilable: boolean;
|
||||
isStarred: boolean;
|
||||
isFixture: boolean;
|
||||
costCentre: CostCentre;
|
||||
|
||||
public constructor(init?: Partial<Account>) {
|
||||
Object.assign(this, init);
|
||||
}
|
||||
}
|
||||
24
overlord/src/app/core/batch.service.ts
Normal file
24
overlord/src/app/core/batch.service.ts
Normal file
@ -0,0 +1,24 @@
|
||||
import {Injectable} from '@angular/core';
|
||||
import {Observable} from 'rxjs/internal/Observable';
|
||||
import {catchError} from 'rxjs/operators';
|
||||
import {HttpClient, HttpParams} from '@angular/common/http';
|
||||
import {Batch} from './voucher';
|
||||
import {ErrorLoggerService} from './error-logger.service';
|
||||
|
||||
const url = '/api/batch';
|
||||
const serviceName = 'BatchService';
|
||||
|
||||
@Injectable({providedIn: 'root'})
|
||||
export class BatchService {
|
||||
|
||||
constructor(private http: HttpClient, private log: ErrorLoggerService) {
|
||||
}
|
||||
|
||||
autocomplete(date: string, term: string): Observable<Batch[]> {
|
||||
const options = {params: new HttpParams().set('t', term).set('d', date)};
|
||||
return <Observable<Batch[]>>this.http.get<Batch[]>(url, options)
|
||||
.pipe(
|
||||
catchError(this.log.handleError(serviceName, 'autocomplete'))
|
||||
);
|
||||
}
|
||||
}
|
||||
5
overlord/src/app/core/cost-centre.ts
Normal file
5
overlord/src/app/core/cost-centre.ts
Normal file
@ -0,0 +1,5 @@
|
||||
export class CostCentre {
|
||||
id: string;
|
||||
name: string;
|
||||
isFixture: boolean;
|
||||
}
|
||||
@ -1,61 +1,61 @@
|
||||
<mat-toolbar class="fixed-to-top">
|
||||
<span><a routerLink="/">HnG / TGB</a></span>
|
||||
<mat-menu #voucherMenu="matMenu">
|
||||
<a mat-menu-item routerLink="/Journal">Journal</a>
|
||||
<a mat-menu-item routerLink="/Purchase">Purchase</a>
|
||||
<a mat-menu-item routerLink="/Return">Purchase Return</a>
|
||||
<a mat-menu-item routerLink="/Payment">Payment</a>
|
||||
<a mat-menu-item routerLink="/Receipt">Receipt</a>
|
||||
<a mat-menu-item routerLink="/Issue">Issue</a>
|
||||
<a mat-menu-item routerLink="/journal">Journal</a>
|
||||
<a mat-menu-item routerLink="/purchase">Purchase</a>
|
||||
<a mat-menu-item routerLink="/return">Purchase Return</a>
|
||||
<a mat-menu-item routerLink="/payment">Payment</a>
|
||||
<a mat-menu-item routerLink="/receipt">Receipt</a>
|
||||
<a mat-menu-item routerLink="/issue">Issue</a>
|
||||
</mat-menu>
|
||||
<button mat-button [matMenuTriggerFor]="voucherMenu">
|
||||
Voucher Entry
|
||||
</button>
|
||||
|
||||
<mat-menu #reportMenu="matMenu">
|
||||
<a mat-menu-item routerLink="/Ledger">Display Ledger</a>
|
||||
<a mat-menu-item href="/Reconcile">Ledger Reconcilliation</a>
|
||||
<a mat-menu-item routerLink="/CashFlow">Cash Flow</a>
|
||||
<a mat-menu-item routerLink="/Daybook">Day Book</a>
|
||||
<a mat-menu-item routerLink="/TrialBalance">Trial Balance</a>
|
||||
<a mat-menu-item routerLink="/ProfitLoss">Profit and Loss</a>
|
||||
<a mat-menu-item routerLink="/BalanceSheet">Balance Sheet</a>
|
||||
<a mat-menu-item routerLink="/NetTransactions">Net Transactions</a>
|
||||
<a mat-menu-item routerLink="/Unposted">UnPosted Entries</a>
|
||||
<a mat-menu-item routerLink="/ledger">Display Ledger</a>
|
||||
<a mat-menu-item href="/reconcile">Ledger Reconcilliation</a>
|
||||
<a mat-menu-item routerLink="/cash-flow">Cash Flow</a>
|
||||
<a mat-menu-item routerLink="/daybook">Day Book</a>
|
||||
<a mat-menu-item routerLink="/trial-balance">Trial Balance</a>
|
||||
<a mat-menu-item routerLink="/profit-loss">Profit and Loss</a>
|
||||
<a mat-menu-item routerLink="/balance-sheet">Balance Sheet</a>
|
||||
<a mat-menu-item routerLink="/net-transactions">Net Transactions</a>
|
||||
<a mat-menu-item routerLink="/unposted">UnPosted Entries</a>
|
||||
</mat-menu>
|
||||
<button mat-button [matMenuTriggerFor]="reportMenu">
|
||||
Reports
|
||||
</button>
|
||||
|
||||
<mat-menu #productReportMenu="matMenu">
|
||||
<a mat-menu-item routerLink="/ProductLedger">Product Ledger</a>
|
||||
<a mat-menu-item routerLink="/RawMaterialCost">Raw Material Cost</a>
|
||||
<a mat-menu-item routerLink="/PurchaseEntries">Purchase Entries</a>
|
||||
<a mat-menu-item routerLink="/Purchases">Purchases</a>
|
||||
<a mat-menu-item routerLink="/ClosingStock">Closing Stock</a>
|
||||
<a mat-menu-item routerLink="/StockMovement">Stock Movement</a>
|
||||
<a mat-menu-item routerLink="/product-ledger">Product Ledger</a>
|
||||
<a mat-menu-item routerLink="/raw-material-cost">Raw Material Cost</a>
|
||||
<a mat-menu-item routerLink="/purchase-entries">Purchase Entries</a>
|
||||
<a mat-menu-item routerLink="/purchases">Purchases</a>
|
||||
<a mat-menu-item routerLink="/closing-stock">Closing Stock</a>
|
||||
<a mat-menu-item routerLink="/stock-movement">Stock Movement</a>
|
||||
</mat-menu>
|
||||
<button mat-button [matMenuTriggerFor]="productReportMenu">
|
||||
Product Reports
|
||||
</button>
|
||||
|
||||
<mat-menu #employeeMenu="matMenu">
|
||||
<a mat-menu-item routerLink="/Employees">Employees</a>
|
||||
<a mat-menu-item routerLink="/Attendance">Attendance</a>
|
||||
<a mat-menu-item routerLink="/EmployeeAttendance">Employee Attendance</a>
|
||||
<a mat-menu-item routerLink="/EmployeeFunctions">Employee Functions</a>
|
||||
<a mat-menu-item routerLink="/EmployeeBenefits">Employee Benefits (Esi / Pf)</a>
|
||||
<a mat-menu-item routerLink="/Incentive">Incentive</a>
|
||||
<a mat-menu-item routerLink="/employees">Employees</a>
|
||||
<a mat-menu-item routerLink="/attendance">Attendance</a>
|
||||
<a mat-menu-item routerLink="/employee-attendance">Employee Attendance</a>
|
||||
<a mat-menu-item routerLink="/employee-functions">Employee Functions</a>
|
||||
<a mat-menu-item routerLink="/employee-benefits">Employee Benefits (Esi / Pf)</a>
|
||||
<a mat-menu-item routerLink="/incentive">Incentive</a>
|
||||
</mat-menu>
|
||||
<button mat-button [matMenuTriggerFor]="employeeMenu">
|
||||
Employees
|
||||
</button>
|
||||
|
||||
<mat-menu #masterMenu="matMenu">
|
||||
<a mat-menu-item routerLink="/Accounts">Accounts</a>
|
||||
<a mat-menu-item routerLink="/CostCentres">Cost Centres</a>
|
||||
<a mat-menu-item routerLink="/Products">Products</a>
|
||||
<a mat-menu-item routerLink="/ProductGroups">Product Groups</a>
|
||||
<a mat-menu-item routerLink="/accounts">Accounts</a>
|
||||
<a mat-menu-item routerLink="/cost-centres">Cost Centres</a>
|
||||
<a mat-menu-item routerLink="/products">Products</a>
|
||||
<a mat-menu-item routerLink="/product-groups">Product Groups</a>
|
||||
</mat-menu>
|
||||
<button mat-button [matMenuTriggerFor]="masterMenu">
|
||||
Masters
|
||||
@ -65,11 +65,11 @@
|
||||
|
||||
<mat-menu #userMenu="matMenu">
|
||||
<a mat-menu-item routerLink="/logout">Logout {{nameObject | async}}</a>
|
||||
<a mat-menu-item routerLink="/User/{{nameObject | async}}">Change Password</a>
|
||||
<a mat-menu-item routerLink="/Users">Users</a>
|
||||
<a mat-menu-item routerLink="/Groups">Groups</a>
|
||||
<a mat-menu-item routerLink="/Clients">Clients</a>
|
||||
<a mat-menu-item routerLink="/Settings">Settings</a>
|
||||
<a mat-menu-item routerLink="/users/{{nameObject | async}}">Change Password</a>
|
||||
<a mat-menu-item routerLink="/users">Users</a>
|
||||
<a mat-menu-item routerLink="/groups">Groups</a>
|
||||
<a mat-menu-item routerLink="/clients">Clients</a>
|
||||
<a mat-menu-item routerLink="/settings">Settings</a>
|
||||
</mat-menu>
|
||||
<button mat-button [matMenuTriggerFor]="userMenu" *ngIf="nameObject | async as name">
|
||||
<mat-icon>account_box</mat-icon>
|
||||
|
||||
5
overlord/src/app/core/product-group.ts
Normal file
5
overlord/src/app/core/product-group.ts
Normal file
@ -0,0 +1,5 @@
|
||||
export class ProductGroup {
|
||||
id: string;
|
||||
name: string;
|
||||
isFixture: boolean;
|
||||
}
|
||||
20
overlord/src/app/core/product.ts
Normal file
20
overlord/src/app/core/product.ts
Normal file
@ -0,0 +1,20 @@
|
||||
import {Account} from './account';
|
||||
import {ProductGroup} from './product-group';
|
||||
|
||||
export class Product {
|
||||
id: string;
|
||||
code: number;
|
||||
name: string;
|
||||
units: string;
|
||||
fraction: number;
|
||||
fractionUnits: string;
|
||||
productYield: number;
|
||||
price: number;
|
||||
salePrice: number;
|
||||
isActive: boolean;
|
||||
isFixture: boolean;
|
||||
isPurchased: boolean;
|
||||
isSold: boolean;
|
||||
productGroup: ProductGroup;
|
||||
account: Account;
|
||||
}
|
||||
19
overlord/src/app/core/user.ts
Normal file
19
overlord/src/app/core/user.ts
Normal file
@ -0,0 +1,19 @@
|
||||
export class User {
|
||||
id: string;
|
||||
name: string;
|
||||
password: string;
|
||||
lockedOut: boolean;
|
||||
groups: UserGroup[];
|
||||
perms: string[];
|
||||
isAuthenticated: boolean;
|
||||
|
||||
public constructor(init?: Partial<User>) {
|
||||
Object.assign(this, init);
|
||||
}
|
||||
}
|
||||
|
||||
export class UserGroup {
|
||||
id: string;
|
||||
name: string;
|
||||
enabled: boolean;
|
||||
}
|
||||
15
overlord/src/app/core/voucher.service.spec.ts
Normal file
15
overlord/src/app/core/voucher.service.spec.ts
Normal file
@ -0,0 +1,15 @@
|
||||
import {inject, TestBed} from '@angular/core/testing';
|
||||
|
||||
import {VoucherService} from './voucher.service';
|
||||
|
||||
describe('VoucherService', () => {
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({
|
||||
providers: [VoucherService]
|
||||
});
|
||||
});
|
||||
|
||||
it('should be created', inject([VoucherService], (service: VoucherService) => {
|
||||
expect(service).toBeTruthy();
|
||||
}));
|
||||
});
|
||||
97
overlord/src/app/core/voucher.service.ts
Normal file
97
overlord/src/app/core/voucher.service.ts
Normal file
@ -0,0 +1,97 @@
|
||||
import {Injectable} from '@angular/core';
|
||||
import {catchError} from 'rxjs/operators';
|
||||
import {Observable} from 'rxjs/internal/Observable';
|
||||
import {HttpClient, HttpHeaders, HttpParams} from '@angular/common/http';
|
||||
import {ErrorLoggerService} from './error-logger.service';
|
||||
import {Voucher} from './voucher';
|
||||
|
||||
const httpOptions = {
|
||||
headers: new HttpHeaders({'Content-Type': 'application/json'})
|
||||
};
|
||||
|
||||
const url = '/api/voucher';
|
||||
const serviceName = 'VoucherService';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class VoucherService {
|
||||
|
||||
constructor(private http: HttpClient, private log: ErrorLoggerService) {
|
||||
}
|
||||
|
||||
get(id: string): Observable<Voucher> {
|
||||
const options = {params: new HttpParams()};
|
||||
return <Observable<Voucher>>this.http.get<Voucher>(`${url}/${id}`, options)
|
||||
.pipe(
|
||||
catchError(this.log.handleError(serviceName, 'list'))
|
||||
);
|
||||
}
|
||||
|
||||
getOfType(type: string, account?: string): Observable<Voucher> {
|
||||
const options = {params: new HttpParams().set('t', type)};
|
||||
if (account !== undefined && account !== null) {
|
||||
options.params = options.params.set('a', account);
|
||||
}
|
||||
return <Observable<Voucher>>this.http.get<Voucher>(url, options)
|
||||
.pipe(
|
||||
catchError(this.log.handleError(serviceName, 'list'))
|
||||
);
|
||||
}
|
||||
|
||||
getIncentive(date: string): Observable<Voucher> {
|
||||
const options = {params: new HttpParams().set('t', 'Service Charge').set('d', date)};
|
||||
return <Observable<Voucher>>this.http.get<Voucher>(url, options)
|
||||
.pipe(
|
||||
catchError(this.log.handleError(serviceName, 'list'))
|
||||
);
|
||||
}
|
||||
|
||||
post(id: string): Observable<Voucher> {
|
||||
const options = {params: new HttpParams().set('p', '')};
|
||||
return <Observable<Voucher>>this.http.post<Voucher>(`${url}/${id}`, {}, options)
|
||||
.pipe(
|
||||
catchError(this.log.handleError(serviceName, 'list'))
|
||||
);
|
||||
}
|
||||
|
||||
delete(id: string): Observable<Voucher> {
|
||||
return <Observable<Voucher>>this.http.delete<Voucher>(`${url}/${id}`, httpOptions)
|
||||
.pipe(
|
||||
catchError(this.log.handleError(serviceName, 'delete'))
|
||||
);
|
||||
}
|
||||
|
||||
save(voucher: Voucher): Observable<Voucher> {
|
||||
const options = {
|
||||
params: new HttpParams().set('t', voucher.type)
|
||||
};
|
||||
const fd = new FormData();
|
||||
voucher.files.filter(x => !x.id).forEach((file, index) => {
|
||||
fd.append('f' + index, this.dataURLtoBlob(file.resized));
|
||||
fd.append('t' + index, this.dataURLtoBlob(file.thumbnail));
|
||||
});
|
||||
voucher.files = voucher.files.filter(x => x.id);
|
||||
fd.append('model', JSON.stringify(voucher));
|
||||
const saveUrl: string = (voucher.id === undefined || voucher.id === null) ? url : `${url}/${voucher.id}`;
|
||||
return <Observable<Voucher>>this.http.post<Voucher>(saveUrl, fd, options)
|
||||
.pipe(
|
||||
catchError(this.log.handleError(serviceName, 'list'))
|
||||
);
|
||||
}
|
||||
|
||||
dataURLtoBlob(dataURL) {
|
||||
const re = /^data:([\w/\-\.]+);\w+,(.*)$/;
|
||||
const m = dataURL.match(re);
|
||||
const mimeString = m[1];
|
||||
const byteString = atob(m[2]);
|
||||
const ab = new ArrayBuffer(byteString.length);
|
||||
const dw = new DataView(ab);
|
||||
let i;
|
||||
|
||||
for (i = 0; i < byteString.length; i++) {
|
||||
dw.setUint8(i, byteString.charCodeAt(i));
|
||||
}
|
||||
return new Blob([ab], {type: mimeString});
|
||||
}
|
||||
}
|
||||
83
overlord/src/app/core/voucher.ts
Normal file
83
overlord/src/app/core/voucher.ts
Normal file
@ -0,0 +1,83 @@
|
||||
import {Account} from './account';
|
||||
import {User} from './user';
|
||||
import {CostCentre} from './cost-centre';
|
||||
import {Product} from './product';
|
||||
|
||||
export class Voucher {
|
||||
id: string;
|
||||
date: string;
|
||||
type: string;
|
||||
posted: boolean;
|
||||
narration: string;
|
||||
incentive?: number;
|
||||
journals: Journal[];
|
||||
inventories: Inventory[];
|
||||
employeeBenefits: EmployeeBenefit[];
|
||||
incentives: Incentive[];
|
||||
files: DbFile[];
|
||||
creationDate: string;
|
||||
lastEditDate: string;
|
||||
user: User;
|
||||
isStarred: boolean;
|
||||
poster: string;
|
||||
reconcileDate: string;
|
||||
}
|
||||
|
||||
export class Journal {
|
||||
id: string;
|
||||
debit: number;
|
||||
amount: number;
|
||||
account: Account;
|
||||
costCentre: CostCentre;
|
||||
|
||||
public constructor(init?: Partial<Journal>) {
|
||||
Object.assign(this, init);
|
||||
}
|
||||
}
|
||||
|
||||
export class EmployeeBenefit {
|
||||
grossSalary: number;
|
||||
daysWorked: number;
|
||||
esiEmployee: number;
|
||||
pfEmployee: number;
|
||||
esiEmployer: number;
|
||||
pfEmployer: number;
|
||||
journal: Journal; // Should be employee as we need designation
|
||||
}
|
||||
|
||||
export class Incentive {
|
||||
id: string;
|
||||
name: string;
|
||||
designation: string;
|
||||
department: string;
|
||||
daysWorked: number;
|
||||
points: number;
|
||||
|
||||
}
|
||||
|
||||
export class Inventory {
|
||||
id: string;
|
||||
quantity: number;
|
||||
rate: number;
|
||||
tax: number;
|
||||
discount: number;
|
||||
amount: number;
|
||||
product: Product;
|
||||
batch: Batch;
|
||||
}
|
||||
|
||||
export class Batch {
|
||||
id: string;
|
||||
name: string;
|
||||
quantityRemaining: number;
|
||||
tax: number;
|
||||
discount: number;
|
||||
rate: number;
|
||||
product: Product;
|
||||
}
|
||||
|
||||
export class DbFile {
|
||||
id: string;
|
||||
resized: string;
|
||||
thumbnail: string;
|
||||
}
|
||||
Reference in New Issue
Block a user