i cant even keep track anymore

This commit is contained in:
Akash Shah 2019-07-16 23:12:22 -04:00
parent 12748b8035
commit 6f54177cad
19 changed files with 1849 additions and 1548 deletions

View File

@ -0,0 +1,25 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { EmptyErrorEditorComponent } from './empty-error-editor.component';
describe('EmptyErrorEditorComponent', () => {
let component: EmptyErrorEditorComponent;
let fixture: ComponentFixture<EmptyErrorEditorComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ EmptyErrorEditorComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(EmptyErrorEditorComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -0,0 +1,46 @@
import {AfterViewInit, Component, ViewChild} from '@angular/core';
import {ToastManagerService} from '../../services/toast-manager/toast-service.service';
@Component({
selector: 'app-empty-error-editor',
template: `
<input #i class="w-100" [value]="params.value" (keydown)="onKeyDown($event)"/>
`
})
export class EmptyErrorEditorComponent implements AfterViewInit {
@ViewChild('i', {'static': false}) textInput;
params;
constructor(protected toastService: ToastManagerService) { }
ngAfterViewInit() {
setTimeout(() => {
this.textInput.nativeElement.focus();
});
}
agInit(params: any): void {
this.params = params;
}
getValue() {
return this.textInput.nativeElement.value;
}
onKeyDown(event) {
if (event.keyCode === 9 || event.keyCode === 13) {
if (!this.textInput.nativeElement.value) {
event.stopPropagation();
this.notif('Value should not be empty');
setTimeout(() => {
this.textInput.nativeElement.focus();
});
}
}
}
// ** toast notification method
notif(text: string) {
this.toastService.show(text, {classname: 'bg-warning'});
}
}

View File

@ -0,0 +1,25 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { NumericEditorComponent } from './numeric-editor.component';
describe('NumericEditorComponent', () => {
let component: NumericEditorComponent;
let fixture: ComponentFixture<NumericEditorComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ NumericEditorComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(NumericEditorComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -0,0 +1,51 @@
import {AfterViewInit, Component, ViewChild} from '@angular/core';
import {ToastManagerService} from '../../services/toast-manager/toast-service.service';
@Component({
selector: 'app-numeric-editor',
template: `
<input #i type="number" class="w-100" [value]="params.value" (keydown)="onKeyDown($event)"/>
`
})
export class NumericEditorComponent implements AfterViewInit {
@ViewChild('i', {'static': false}) numberInput;
params;
canBeEmpty: boolean;
constructor(protected toastService: ToastManagerService) { }
ngAfterViewInit() {
setTimeout(() => {
this.numberInput.nativeElement.focus();
});
}
agInit(params: any): void {
this.params = params;
this.canBeEmpty = params.canBeEmpty;
}
getValue() {
return this.numberInput.nativeElement.value;
}
onKeyDown(event) {
if (this.canBeEmpty) {
if (event.keyCode === 9 || event.keyCode === 13) {
if (!this.numberInput.nativeElement.value) {
event.stopPropagation();
this.notif('Value should not be empty');
setTimeout(() => {
this.numberInput.nativeElement.focus();
});
}
}
}
}
// ** toast notification method
notif(text: string) {
this.toastService.show(text, {classname: 'bg-warning'});
}
}

View File

@ -4,7 +4,7 @@ import {ToastManagerService} from '../../services/toast-manager/toast-service.se
@Component({
selector: 'app-phone-editor-cell',
template: `
<input #i [value]="params.value" [textMask]="{mask: usPhoneMask, guide: false}" (keydown)="onKeyDown($event)"/>
<input #i class="w-100" [value]="params.value" [textMask]="{mask: usPhoneMask, guide: false}" (keydown)="onKeyDown($event)"/>
`
})
export class PhoneEditorComponent implements AfterViewInit {

View File

@ -26,6 +26,8 @@ import { ToastsContainerComponent } from './services/toast-manager/toasts-contai
import { NumberFormatterComponent } from './ag-grid-components/number-formatter/number-formatter.component';
import { PhoneFormatterComponent } from './ag-grid-components/phone-formatter/phone-formatter.component';
import { PhoneEditorComponent } from './ag-grid-components/phone-editor/phone-editor.component';
import { EmptyErrorEditorComponent } from './ag-grid-components/empty-error-editor/empty-error-editor.component';
import { NumericEditorComponent } from './ag-grid-components/numeric-editor/numeric-editor.component';
// import { ServiceTypeComponent } from './service-type/service-type.component';
@NgModule({
@ -45,7 +47,9 @@ import { PhoneEditorComponent } from './ag-grid-components/phone-editor/phone-ed
ToastsContainerComponent,
NumberFormatterComponent,
PhoneFormatterComponent,
PhoneEditorComponent// ,
PhoneEditorComponent,
EmptyErrorEditorComponent,
NumericEditorComponent// ,
// ServiceTypeComponent
],
imports: [
@ -53,7 +57,9 @@ import { PhoneEditorComponent } from './ag-grid-components/phone-editor/phone-ed
AgGridModule.withComponents([
NumberFormatterComponent,
PhoneFormatterComponent,
PhoneEditorComponent
PhoneEditorComponent,
EmptyErrorEditorComponent,
NumericEditorComponent
]),
NgbModule,
HttpClientModule,

View File

@ -9,3 +9,11 @@
::-ms-input-placeholder { /* Microsoft Edge */
color: lightblue;
}
.disabled {
position: absolute;
width: 100%;
height: 100%;
z-index: 10;
background-color: rgba(0,0,0,0.5) !important;
}

View File

@ -1,7 +1,8 @@
<app-nav-bar [customerActive]="true"></app-nav-bar>
<h1 align="center">Customers</h1>
<div *ngIf="loggedIn">
<h1 align="center">Customers</h1>
<div class="container-fluid">
<div class="container-fluid">
<div class="row">
<div class="col-12">
<ag-grid-angular
@ -32,10 +33,10 @@
</div>
</div>
</div>
</div>
</div>
<!--MODAL: new customer-->
<app-modal-form [title]="'New Customer'" #new>
<!--MODAL: new customer-->
<app-modal-form [title]="'New Customer'" #new>
<div class="modal-body">
<table class="table table-borderless table-sm">
<tbody>
@ -161,10 +162,10 @@
</button>
<button type="button" class="btn btn-danger" (click)="close(new)">Cancel</button>
</div>
</app-modal-form>
</app-modal-form>
<!--MODAL: edit customer-->
<app-modal-form [title]="'Editing'" #edit>
<!--MODAL: edit customer-->
<app-modal-form [title]="'Editing'" #edit>
<div *ngIf="selected">
<div class="modal-body">
<table class="table table-borderless table-sm">
@ -292,10 +293,10 @@
<button type="button" class="btn btn-danger" (click)="close(edit)">Cancel</button>
</div>
</div>
</app-modal-form>
</app-modal-form>
<!--MODAL: customer contacts-->
<app-modal-form [title]="'Customer Contacts'" #contacts>
<!--MODAL: customer contacts-->
<app-modal-form [title]="'Customer Contacts'" #contacts>
<div *ngIf="selected">
<div class="container-fluid">
<div class="row">
@ -348,4 +349,22 @@
<button type="button" class="btn btn-info" (click)="close(contacts)">Exit</button>
</div>
</div>
</app-modal-form>
</app-modal-form>
</div>
<div *ngIf="!loggedIn">
<div class="container mt-5">
<div class="row">
<div class="col-12">
<div class="jumbotron">
<h1 class="display-4">Please Log In First!</h1>
<p class="lead">Once you do, you will be able to create new customers and edit existing ones to your hearts content!</p>
<p class="lead">
<a class="btn btn-success btn-lg" href="#" role="button">Log In</a>
</p>
</div>
</div>
</div>
</div>
</div>

View File

@ -3,6 +3,8 @@ import {AstuteClientService} from '../services/astute-client-service';
import {ToastManagerService} from '../services/toast-manager/toast-service.service';
import {PhoneFormatterComponent} from '../ag-grid-components/phone-formatter/phone-formatter.component';
import {PhoneEditorComponent} from '../ag-grid-components/phone-editor/phone-editor.component';
import {EmptyErrorEditorComponent} from '../ag-grid-components/empty-error-editor/empty-error-editor.component';
import {NumericEditorComponent} from "../ag-grid-components/numeric-editor/numeric-editor.component";
@Component({
selector: 'app-customer',
@ -11,6 +13,7 @@ import {PhoneEditorComponent} from '../ag-grid-components/phone-editor/phone-edi
})
export class CustomerComponent implements OnInit {
// @ViewChild('agGrid') agGrid;
loggedIn: boolean;
gridApi;
gridColumnApi;
contactGridApi;
@ -19,22 +22,24 @@ export class CustomerComponent implements OnInit {
customers;
columnDefs = [
{headerName: 'ID', field: 'customerId'},
{headerName: 'Name ✎', field: 'customerName', editable: true},
{headerName: 'Bill To ✎', field: 'billToDept', editable: true},
{headerName: 'Address 1 ✎', field: 'add1', editable: true},
{headerName: 'Address 2 ✎', field: 'add2', editable: true},
{headerName: 'City ✎', field: 'city', editable: true},
{headerName: 'Email ✎', field: 'email', editable: true},
{headerName: 'Name ✎', field: 'customerName', editable: true, cellEditor: 'emptyErrorEditorComponent'},
{headerName: 'Bill To ✎', field: 'billToDept', editable: true, cellEditor: 'emptyErrorEditorComponent'},
{headerName: 'Email ✎', field: 'email', editable: true, cellEditor: 'emptyErrorEditorComponent'},
{headerName: 'Fax ✎', field: 'fax', editable: true, cellEditor: 'phoneEditorComponent'},
{headerName: 'Phone ✎', field: 'phone', editable: true, cellEditor: 'phoneEditorComponent'},
{headerName: 'Ext. ✎', field: 'phExt', editable: true},
{headerName: 'State ✎', field: 'state', editable: true},
{headerName: 'ZIP ✎', field: 'zip', editable: true},
{headerName: 'ZIP-4 ✎', field: 'ziplast4', editable: true}
{headerName: 'Ext. ✎', field: 'phExt', editable: true, cellEditor: 'numericEditorComponent'},
{headerName: 'Address 1 ✎', field: 'add1', editable: true, cellEditor: 'emptyErrorEditorComponent'},
{headerName: 'Address 2 ✎', field: 'add2', editable: true, cellEditor: 'emptyErrorEditorComponent'},
{headerName: 'City ✎', field: 'city', editable: true, cellEditor: 'emptyErrorEditorComponent'},
{headerName: 'State ✎', field: 'state', editable: true, cellEditor: 'emptyErrorEditorComponent'},
{headerName: 'ZIP ✎', field: 'zip', editable: true, cellEditor: 'emptyErrorEditorComponent'},
{headerName: 'ZIP-4 ✎', field: 'ziplast4', editable: true, cellEditor: 'numericEditorComponent'}
];
frameworkComponents = {
phoneFormatterComponent: PhoneFormatterComponent,
phoneEditorComponent: PhoneEditorComponent
phoneEditorComponent: PhoneEditorComponent,
emptyErrorEditorComponent: EmptyErrorEditorComponent,
numericEditorComponent: NumericEditorComponent
};
rowData: any;
states = [
@ -94,7 +99,7 @@ export class CustomerComponent implements OnInit {
contactsData: any;
contactsColDef = [
{headerName: 'Name ✎', field: 'name', editable: true},
{headerName: 'Name ✎', field: 'name', editable: true, cellEditor: 'emptyErrorEditorComponent'},
{headerName: 'Title ✎', field: 'title', editable: true},
{headerName: 'Email ✎', field: 'email', editable: true},
{headerName: 'Work ✎', field: 'workPhone', editable: true, cellEditor: 'phoneEditorComponent'},
@ -119,7 +124,12 @@ export class CustomerComponent implements OnInit {
}
ngOnInit() {
if (localStorage.getItem('SESSION_ID') && localStorage.getItem('SESSION_USER')) {
this.loggedIn = true;
this.refreshData();
} else {
this.loggedIn = false;
}
}
// callback for grid selection

View File

@ -1,6 +1,8 @@
<app-nav-bar [invoicePaymentActive]="true"></app-nav-bar>
<h1 align="center">Invoice Payments</h1>
<div class="container-fluid">
<div *ngIf="loggedIn">
<h1 align="center">Invoice Payments</h1>
<div class="container-fluid">
<div class="row">
<div class="col-12">
<ag-grid-angular
@ -23,10 +25,10 @@
<button class="btn btn-info" style="width: 100%" (click)="open(edit)">Edit Invoice payment</button>
</div>
</div>
</div>
</div>
<!--MODAL: new Invoice Payment-->
<app-modal-form [title]="'New Invoice Payment'" #new>
<!--MODAL: new Invoice Payment-->
<app-modal-form [title]="'New Invoice Payment'" #new>
<form>
<div class="modal-body">
<table class="table table-borderless table-sm">
@ -111,10 +113,10 @@
<button type="reset" class="btn btn-danger" (click)="close(new)">Cancel</button>
</div>
</form>
</app-modal-form>
</app-modal-form>
<!--MODAL: edit invoice payment-->
<app-modal-form [title]="'Editing'" #edit>
<!--MODAL: edit invoice payment-->
<app-modal-form [title]="'Editing'" #edit>
<div *ngIf="selected">
<div class="modal-body">
<table class="table table-borderless table-sm">
@ -203,4 +205,21 @@
<button type="button" class="btn btn-danger" (click)="close(edit)">Cancel</button>
</div>
</div>
</app-modal-form>
</app-modal-form>
</div>
<div *ngIf="!loggedIn">
<div class="container mt-5">
<div class="row">
<div class="col-12">
<div class="jumbotron">
<h1 class="display-4">Please Log In First!</h1>
<p class="lead">Once you do, you will be able to log payments to your hearts content!</p>
<p class="lead">
<a class="btn btn-success btn-lg" href="#" role="button">Log In</a>
</p>
</div>
</div>
</div>
</div>
</div>

View File

@ -10,6 +10,8 @@ import {ToastManagerService} from "../services/toast-manager/toast-service.servi
})
export class InvoicePaymentComponent implements OnInit {
@ViewChild('agGrid', {'static': false}) agGrid;
loggedIn: boolean;
selected = null;
chosenInv: any = 0;
chosenPaymentType: any = 0;
@ -25,14 +27,17 @@ export class InvoicePaymentComponent implements OnInit {
{headerName: 'Payment Type', field: 'paymentType'},
{headerName: 'Check / ACH #', field: 'checkNo'},
{headerName: 'Transaction #', field: 'transactionNo'}
];
constructor(protected astuteClientService: AstuteClientService, protected toastService: ToastManagerService) {
}
ngOnInit() {
if (localStorage.getItem('SESSION_ID') && localStorage.getItem('SESSION_USER')) {
this.loggedIn = true;
this.refreshData();
} else {
this.loggedIn = false;
}
}
invoiceDropdownChange(index) {

View File

@ -1,6 +1,8 @@
<app-nav-bar [invoiceActive]="true"></app-nav-bar>
<h1 align="center">Invoices</h1>
<div class="container-fluid">
<div *ngIf="loggedIn">
<h1 align="center">Invoices</h1>
<div class="container-fluid">
<!--Table-->
<div class="row">
<div class="col-12">
@ -59,8 +61,8 @@
</div>
</div>
<!--MODAL: edit Invoice-->
<app-modal-form [title]="'Edit Invoice'" #edit>
<!--MODAL: edit Invoice-->
<app-modal-form [title]="'Edit Invoice'" #edit>
<!--General-->
<div class="modal-body" *ngIf="chosenInv">
<p class="h4 text-right">General</p>
@ -394,10 +396,10 @@
<button type="button" class="btn btn-danger" (click)="close(edit)">Cancel</button>
</p>
</div>
</app-modal-form>
</app-modal-form>
<!--MODAL: new invoice-->
<app-modal-form [title]="'New Invoice'" #new>
<!--MODAL: new invoice-->
<app-modal-form [title]="'New Invoice'" #new>
<!--<form>-->
<!--General-->
<div class="modal-body">
@ -664,10 +666,10 @@
<button type="reset" class="btn btn-danger" (click)="close(new)">Cancel</button>
</div>
<!--</form>-->
</app-modal-form>
</app-modal-form>
<!--MODAL: invoice details-->
<app-modal-form [title]="'Invoice Details of ' + (chosenInv ? chosenInv.invoiceNumber: '')" #details>
<!--MODAL: invoice details-->
<app-modal-form [title]="'Invoice Details of ' + (chosenInv ? chosenInv.invoiceNumber: '')" #details>
<div class="modal-body">
<div class="container-fluid">
<div class="row">
@ -722,4 +724,21 @@
<!--<div class="modal-footer">-->
<!--<button class="btn btn-outline-danger" (click)="close(details)">Exit</button>-->
<!--</div>-->
</app-modal-form>
</app-modal-form>
</div>
<div *ngIf="!loggedIn">
<div class="container mt-5">
<div class="row">
<div class="col-12">
<div class="jumbotron">
<h1 class="display-4">Please Log In First!</h1>
<p class="lead">Once you do, you will be able to create new invoices and edit existing ones to your hearts content!</p>
<p class="lead">
<a class="btn btn-success btn-lg" href="#" role="button">Log In</a>
</p>
</div>
</div>
</div>
</div>
</div>

View File

@ -13,6 +13,8 @@ declare var $: any;
styleUrls: ['./invoice.component.css']
})
export class InvoiceComponent implements OnInit {
loggedIn: boolean;
gridApi;
gridColumnApi;
detailGridApi;
@ -49,7 +51,7 @@ export class InvoiceComponent implements OnInit {
{headerName: 'Date', field: 'invoiceDate'},
{headerName: 'Sales Order Number', field: 'poNum'},
{headerName: 'Change Order Number', field: 'changeOrderNum'},
{headerName: 'Outstanding Balance', field: 'outstandingBalanceString'},
{headerName: 'Outstanding Balance', field: 'outstandingBalance', cellRenderer: 'numberFormatterComponent'},
{headerName: 'Bill Amount', field: 'billAmt', cellRenderer: 'numberFormatterComponent'},
{headerName: 'Notes ✎', field: 'specialNotes',
editable: (node => node.data.invoiceStatus === 1), cellEditor: 'agLargeTextCellEditor'}
@ -67,15 +69,17 @@ export class InvoiceComponent implements OnInit {
detailColumnDefs = [
{headerName: '#', field: 'lineItemNum'},
{headerName: 'PO Detail', field: 'poDetailName'},
{headerName: 'Description ✎', field: 'desc',
{headerName: 'Description ✎*', field: 'desc',
editable: (_ => (this.chosenInv && this.chosenInv.invoiceStatus === 1)), cellEditor: 'agLargeTextCellEditor'},
{headerName: 'Fee Type', field: 'rateTypeName'},
{headerName: 'Fee Type *', field: 'rateTypeName',
editable: (node => (node.data.poLineItemNum === -1 && this.chosenInv && this.chosenInv.invoiceStatus === 1)),
cellEditor: 'agSelectCellEditor', cellEditorParams: {values: this.rateNames}},
{headerName: 'Service Type', field: 'serviceTypeName'},
{headerName: 'Qty or Hours ✎', field: 'qty',
{headerName: 'Qty or Hours ✎*', field: 'qty',
editable: (_ => (this.chosenInv && this.chosenInv.invoiceStatus === 1))},
{headerName: '(/Remaining)', field: 'remainingQty'},
{headerName: 'Fee', field: 'fee',
cellRenderer: 'numberFormatterComponent'}
{headerName: 'Remaining Qty', field: 'remainingQty'},
{headerName: 'Fee *', field: 'fee',
editable: (node => (node.data.poLineItemNum === -1 && this.chosenInv && this.chosenInv.invoiceStatus === 1)), cellRenderer: 'numberFormatterComponent'}
];
@ -124,6 +128,8 @@ export class InvoiceComponent implements OnInit {
}
ngOnInit() {
if (localStorage.getItem('SESSION_ID') && localStorage.getItem('SESSION_USER')) {
this.loggedIn = true;
this.astuteClientService.getServiceTypes().then((d) => {
if (d) {
this.serviceTypes = d;
@ -157,6 +163,14 @@ export class InvoiceComponent implements OnInit {
}, (reason) => {
this.notif('Get Customers Failed: ' + reason);
});
this.refreshPOs();
this.refreshData();
} else {
this.loggedIn = false;
}
}
refreshPOs() {
this.astuteClientService.getPOs().then((data) => {
if (data) {
this.pos = data;
@ -164,6 +178,7 @@ export class InvoiceComponent implements OnInit {
this.astuteClientService.getPODetail(po.ponum).then((details) => {
if (details) {
details.forEach((detail) => {
detail.tempRemainingQty = detail.remainingQty;
this.allPODetails.push(detail);
});
// console.log(this.allPODetails);
@ -181,18 +196,12 @@ export class InvoiceComponent implements OnInit {
}, (reason) => {
this.notif('Get SOs Failed: ' + reason);
});
this.refreshData();
}
refreshData() {
this.astuteClientService.getInvoices().then((data) => {
if (data) {
this.source = data;
// console.log(data);
this.source.forEach((row) => {
row.billAmtString = formatCurrency(row.billAmt, 'en-US', '$', 'USD');
row.outstandingBalanceString = formatCurrency(row.outstandingBalance, 'en-US', '$', 'USD');
});
} else {
this.notif('Get Invoices failed!');
}
@ -221,15 +230,16 @@ export class InvoiceComponent implements OnInit {
// this.refreshData();
}
updateDetailRow(event) {
const eventData = event.data;
// console.log(eventData);
event.data.feeTypeId = this.getFeeIdFromName(event.data.rateTypeName);
const eventData = event.data;
this.astuteClientService.updateInvoiceDetail(eventData.invoiceNum, eventData.lineItemNum, eventData).then((data) => {
if (!data) {
this.refreshDetailsOfSelected();
this.notif('Detail Updating Failed, Check Input Fields');
} else {
this.updateSelectedBillAmt();
}
this.refreshDetailsOfSelected();
}, (reason) => {
this.notif('Update Detail failed: ' + reason);
});
@ -251,18 +261,21 @@ export class InvoiceComponent implements OnInit {
this.selectedInDetails = this.astuteClientService.getInvoiceDetail(this.chosenInv.invoiceNumber).then((data) => {
if (data) {
data.forEach((invDetail) => {
const tempPo = this.selectedPODetails.filter((po) => {
return po.lineItemNo === invDetail.poLineItemNum;
})[0];
if (tempPo) {
invDetail.remainingQty = tempPo.remainingQty;
}
invDetail.serviceTypeName = this.serviceNames[invDetail.serviceTypeId - 1];
invDetail.rateTypeName = this.rateNames[invDetail.feeTypeId - 1];
if (invDetail.poLineItemNum === -1) {
invDetail.remainingQty = '-';
invDetail.poDetailName = 'Out of Pocket Expenses';
} else {
if (this.chosenInv.invoiceStatus === 1) {
invDetail.remainingQty = invDetail.draftRemainingQty;
} else {
const tempPo = this.selectedPODetails[invDetail.poLineItemNum - 1];
if (tempPo) {
invDetail.remainingQty = tempPo.remainingQty;
} else {
invDetail.remainingQty = '';
}
}
const temp = this.selectedPODetails[invDetail.poLineItemNum - 1];
if (temp) {
invDetail.poDetailName = this.selectedPODetails[invDetail.poLineItemNum - 1].serviceDesc;
@ -270,6 +283,9 @@ export class InvoiceComponent implements OnInit {
invDetail.poDetailName = '';
}
}
invDetail.serviceTypeName = this.serviceNames[invDetail.serviceTypeId - 1];
invDetail.rateTypeName = this.rateNames[invDetail.feeTypeId - 1];
});
this.updateSelectedBillAmt();
return data;
@ -339,7 +355,19 @@ export class InvoiceComponent implements OnInit {
});
}
}
// updateSelectedDetailRemainingQty(poLineItemNum: number) {
// this.selectedInDetails.then((data) => {
// if (data) {
// let newRemainingQty = this.selectedPODetails[poLineItemNum - 1].remainingQty;
// data.forEach(invDetail => {
// if (invDetail.poLineItemNum.toString() === poLineItemNum.toString()) {
// newRemainingQty = newRemainingQty - invDetail.qty;
// }
// });
// this.selectedPODetails[poLineItemNum - 1].tempRemainingQty = newRemainingQty;
// }
// });
// }
printInvoice() {
this.printService.printPDF (this.chosenInv.invoiceNumber);
@ -555,7 +583,19 @@ export class InvoiceComponent implements OnInit {
// creates empty line item detail
addEmptyDetail(poLineItemNum) {
let emptyData;
if (poLineItemNum === -1) {
if (poLineItemNum === '-1') {
emptyData = {
desc: 'Out of Pocket Expenses',
fee: 0,
feeTypeId: 1,
invoiceNum: this.chosenInv.invoiceNumber,
// lineItemNum: 1,
poLineItemNum: poLineItemNum,
qty: 0,
// remainingQty: 1,
serviceTypeId: 6
};
} else {
emptyData = {
desc: this.selectedPODetails[poLineItemNum - 1].serviceDesc,
fee: this.selectedPODetails[poLineItemNum - 1].fee,
@ -563,20 +603,8 @@ export class InvoiceComponent implements OnInit {
invoiceNum: this.chosenInv.invoiceNumber,
// lineItemNum: 1,
poLineItemNum: poLineItemNum,
qty: 1,
remainingQty: this.selectedPODetails[poLineItemNum - 1].remainingQty,
serviceTypeId: this.selectedPODetails[poLineItemNum - 1].serviceTypeId
};
} else {
emptyData = {
desc: 'Out of Pocket Expenses',
fee: this.selectedPODetails[poLineItemNum - 1].fee,
feeTypeId: this.selectedPODetails[poLineItemNum - 1].feeTypeId,
invoiceNum: this.chosenInv.invoiceNumber,
// lineItemNum: 1,
poLineItemNum: poLineItemNum,
qty: 1,
remainingQty: this.selectedPODetails[poLineItemNum - 1].remainingQty,
qty: 0,
// remainingQty: this.selectedPODetails[poLineItemNum - 1].remainingQty,
serviceTypeId: this.selectedPODetails[poLineItemNum - 1].serviceTypeId
};
}
@ -709,5 +737,4 @@ export class InvoiceComponent implements OnInit {
notif(text: string) {
this.toastService.show(text, {classname: 'bg-danger text-light'});
}
}

View File

@ -8,11 +8,15 @@
</div>
<label for="username" class="sr-only">Username</label>
<input class="form-control" type="text" id="username" name="username" ngModel placeholder="Username">
<input class="form-control"
type="text"
id="username"
name="username"
ngModel
placeholder="Username">
<label for="password" class="sr-only">Password</label>
<input
class="form-control"
<input class="form-control"
type="password"
id="password"
name="password"

View File

@ -30,7 +30,7 @@ export class LoginComponent implements OnInit {
} else {
this.notif('login failed, checked credentials');
}
})
});
}
// ** toast notification method

View File

@ -21,10 +21,11 @@
<span class="nav-item">
<ul class="navbar-nav mr-auto">
<li class="nav-item">
<a class="nav-link" [ngClass]="settingsActive ? 'active' : ''"routerLink="/settings" routerLinkActive="active">Settings</a>
<a *ngIf="loggedIn" class="nav-link" [ngClass]="settingsActive ? 'active' : ''"routerLink="/settings" routerLinkActive="active">Settings</a>
</li>
<li class="nav-item">
<button class="btn" style="color: red" (click)="logout()">Logout</button>
<button *ngIf="loggedIn" class="btn" style="color: red" (click)="logout()">Logout</button>
<a *ngIf="!loggedIn" class="btn" style="color: lawngreen" href="#" role="button">Log In</a>
</li>
</ul>
</span>

View File

@ -17,11 +17,17 @@ export class NavBarComponent implements OnInit {
// @Input() logoffActive: boolean;
@Input() settingsActive: boolean;
loggedIn: boolean;
constructor(private astuteClientService: AstuteClientService, private router: Router, private toastService: ToastManagerService) {
}
ngOnInit() {
if (localStorage.getItem('SESSION_ID') && localStorage.getItem('SESSION_USER')) {
this.loggedIn = true;
} else {
this.loggedIn = false;
}
}
logout() {

View File

@ -1,6 +1,8 @@
<app-nav-bar [salesOrderActive]="true"></app-nav-bar>
<h1 align="center">Sales Orders</h1>
<div class="container-fluid">
<div *ngIf="loggedIn">
<h1 align="center">Sales Orders</h1>
<div class="container-fluid">
<div class="row">
<div class="col-12">
<ag-grid-angular
@ -44,10 +46,10 @@
<!--<button class="btn btn-danger" style="width: 100%" (click)="deletePO(selected.ponum)" [disabled]="!selected?true:selected.final === 0">Delete</button>-->
<!--</div>-->
</div>
</div>
</div>
<!--MODAL: new po-->
<app-modal-form [title]="'New Sales Order'" #new>
<!--MODAL: new po-->
<app-modal-form [title]="'New Sales Order'" #new>
<div class="modal-body">
<p class="h4 text-right">General</p>
<hr>
@ -184,10 +186,10 @@
</button>
<button class="btn btn-outline-danger" (click)="close(new)">Cancel</button>
</div>
</app-modal-form>
</app-modal-form>
<!--MODAL: edit po-->
<app-modal-form [title]="'Edit Sales Order'" #edit>
<!--MODAL: edit po-->
<app-modal-form [title]="'Edit Sales Order'" #edit>
<div *ngIf="selected">
<div class="modal-body">
<p class="h4 text-right">General</p>
@ -400,10 +402,10 @@
<button class="btn btn-outline-danger" (click)="close(edit)">Cancel</button>
</div>
</div>
</app-modal-form>
</app-modal-form>
<!--MODAL: po details-->
<app-modal-form [title]="'Details of ' + (selected ? selected.ponum: '')" #editDetails>
<!--MODAL: po details-->
<app-modal-form [title]="'Details of ' + (selected ? selected.ponum: '')" #editDetails>
<div class="modal-body">
<div class="container-fluid">
<div class="row">
@ -427,7 +429,8 @@
<div class="row justify-content-center mt-2">
<div class="col">
<div class="input-group mb-3 mt-2">
<input type="text" class="form-control input-group-sm" placeholder="Descrpition" #poDescription>
<input type="text" class="form-control input-group-sm" placeholder="Descrpition"
[disabled]="selected ? selected.isFinal : false" #poDescription>
<div class="input-group-append w-25">
<button class="btn btn-success w-50 input-group-sm" type="button"
(click)="addEmptyDetail(poDescription.value); poDescription.value = '';"
@ -450,4 +453,21 @@
</div>
</div>
</div>
</app-modal-form>
</app-modal-form>
</div>
<div *ngIf="!loggedIn">
<div class="container mt-5">
<div class="row">
<div class="col-12">
<div class="jumbotron">
<h1 class="display-4">Please Log In First!</h1>
<p class="lead">Once you do, you will be able to create new sales orders and edit existing ones to your hearts content!</p>
<p class="lead">
<a class="btn btn-success btn-lg" href="#" role="button">Log In</a>
</p>
</div>
</div>
</div>
</div>
</div>

View File

@ -3,6 +3,7 @@ import {AstuteClientService} from '../services/astute-client-service';
import {formatCurrency, formatNumber} from '@angular/common';
import {ToastManagerService} from '../services/toast-manager/toast-service.service';
import {NumberFormatterComponent} from '../ag-grid-components/number-formatter/number-formatter.component';
import {EmptyErrorEditorComponent} from "../ag-grid-components/empty-error-editor/empty-error-editor.component";
@Component({
selector: 'app-sales-order',
@ -10,6 +11,8 @@ import {NumberFormatterComponent} from '../ag-grid-components/number-formatter/n
styleUrls: ['./sales-order.component.css']
})
export class SalesOrderComponent implements OnInit {
loggedIn: boolean;
// both of the grid api's
gridApi;
gridColumnApi;
@ -26,15 +29,15 @@ export class SalesOrderComponent implements OnInit {
// data for SO grid
rowData: any;
columnDefs = [
{headerName: 'Project Number ✎', field: 'astuteProjectNumber', editable: (node => !node.data.isFinal)},
{headerName: 'Project Number ✎', field: 'astuteProjectNumber', editable: (node => !node.data.isFinal), cellEditor: 'emptyErrorEditorComponent'},
{headerName: 'SO Number', field: 'ponum'},
// {headerName: 'Customer ID', field: 'customerId'},
{headerName: 'Customer Name', field: 'customerName'},
{headerName: 'Contract Number ✎', field: 'contractNum', editable: (node => !node.data.isFinal)},
{headerName: 'SO Title ✎', field: 'title', editable: (node => !node.data.isFinal)},
{headerName: 'Contract Number ✎', field: 'contractNum', editable: (node => !node.data.isFinal), cellEditor: 'emptyErrorEditorComponent'},
{headerName: 'SO Title ✎', field: 'title', editable: (node => !node.data.isFinal), cellEditor: 'emptyErrorEditorComponent'},
{headerName: 'Contract Amount', field: 'contractAmt', cellRenderer: 'numberFormatterComponent'},
// {headerName: 'Contract Amount', field: 'contractAmt'},
{headerName: 'SO Date ✎', field: 'podate', editable: (node => !node.data.isFinal)},
{headerName: 'SO Date ✎', field: 'podate', editable: (node => !node.data.isFinal), cellEditor: 'emptyErrorEditorComponent'},
{headerName: '# of Invoices', field: 'invoiceSequence'},
{headerName: 'notes ✎', field: 'notes', editable: (node => !node.data.isFinal), cellEditor: 'agLargeTextCellEditor'}
// {headerName: 'oneInvInDraft', field: 'oneInvInDraft'}
@ -52,6 +55,7 @@ export class SalesOrderComponent implements OnInit {
};
frameworkComponents = {
emptyErrorEditorComponent: EmptyErrorEditorComponent,
numberFormatterComponent: NumberFormatterComponent
};
@ -61,7 +65,8 @@ export class SalesOrderComponent implements OnInit {
selectedPODetail;
detailColumnDefs = [
{headerName: '#', field: 'lineItemNo'},
{headerName: 'Description ✎', field: 'serviceDesc', editable: (_ => (this.selected && !this.selected.isFinal))},
{headerName: 'Description ✎', field: 'serviceDesc', editable: (_ => (this.selected && !this.selected.isFinal)),
cellEditor: 'emptyErrorEditorComponent'},
{headerName: 'Rate Type ✎', field: 'rateTypeName', editable: (_ => (this.selected && !this.selected.isFinal)),
cellEditor: 'agSelectCellEditor', cellEditorParams: {values: this.rateNames}},
{headerName: 'Service Type ✎', field: 'serviceTypeName', editable: (_ => (this.selected && !this.selected.isFinal)),
@ -76,6 +81,8 @@ export class SalesOrderComponent implements OnInit {
}
ngOnInit() {
if (localStorage.getItem('SESSION_ID') && localStorage.getItem('SESSION_USER')) {
this.loggedIn = true;
this.astuteClientService.getServiceTypes().then((d) => {
if (d) {
this.serviceTypes = d;
@ -111,6 +118,9 @@ export class SalesOrderComponent implements OnInit {
this.notif('Get Customers Failed: ' + reason);
});
this.refreshData();
} else {
this.loggedIn = false;
}
}
// callback for grid selection