mirror of
https://github.com/dyiop/astute.git
synced 2025-04-09 06:40:20 -04:00
added first input validation (phone),
added delete buttons at each detail section
This commit is contained in:
parent
90ce18f698
commit
22d345cfc1
|
@ -0,0 +1,25 @@
|
||||||
|
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { NumberFormatterComponent } from './number-formatter.component';
|
||||||
|
|
||||||
|
describe('NumberFormatterComponent', () => {
|
||||||
|
let component: NumberFormatterComponent;
|
||||||
|
let fixture: ComponentFixture<NumberFormatterComponent>;
|
||||||
|
|
||||||
|
beforeEach(async(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
declarations: [ NumberFormatterComponent ]
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
|
}));
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = TestBed.createComponent(NumberFormatterComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,15 @@
|
||||||
|
import { Component } from '@angular/core';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-number-formatter-cell',
|
||||||
|
template: `
|
||||||
|
<span>{{params.value | currency:'USD'}}</span>
|
||||||
|
`
|
||||||
|
})
|
||||||
|
export class NumberFormatterComponent {
|
||||||
|
params: any;
|
||||||
|
|
||||||
|
agInit(params: any): void {
|
||||||
|
this.params = params;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,25 @@
|
||||||
|
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { PhoneEditorComponent } from './phone-editor.component';
|
||||||
|
|
||||||
|
describe('PhoneEditorComponent', () => {
|
||||||
|
let component: PhoneEditorComponent;
|
||||||
|
let fixture: ComponentFixture<PhoneEditorComponent>;
|
||||||
|
|
||||||
|
beforeEach(async(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
declarations: [ PhoneEditorComponent ]
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
|
}));
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = TestBed.createComponent(PhoneEditorComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,44 @@
|
||||||
|
import {AfterViewInit, Component, ViewChild} from '@angular/core';
|
||||||
|
import {ToastManagerService} from '../../services/toast-manager/toast-service.service';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-phone-editor-cell',
|
||||||
|
template: `
|
||||||
|
<input #i [value]="params.value" [textMask]="{mask: usPhoneMask, guide: false}" (keydown)="onKeyDown($event)"/>
|
||||||
|
`
|
||||||
|
})
|
||||||
|
export class PhoneEditorComponent implements AfterViewInit {
|
||||||
|
@ViewChild('i', {'static': false}) textInput;
|
||||||
|
usPhoneMask = ['(', /[1-9]/, /\d/, /\d/, ')', ' ', /\d/, /\d/, /\d/, '-', /\d/, /\d/, /\d/, /\d/];
|
||||||
|
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.length < 14) {
|
||||||
|
event.stopPropagation();
|
||||||
|
this.notif('Phone number\'s should have 10 digits');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ** toast notification method
|
||||||
|
notif(text: string) {
|
||||||
|
this.toastService.show(text, {classname: 'bg-warning'});
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,25 @@
|
||||||
|
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { PhoneFormatterComponent } from './phone-formatter.component';
|
||||||
|
|
||||||
|
describe('PhoneFormatterComponent', () => {
|
||||||
|
let component: PhoneFormatterComponent;
|
||||||
|
let fixture: ComponentFixture<PhoneFormatterComponent>;
|
||||||
|
|
||||||
|
beforeEach(async(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
declarations: [ PhoneFormatterComponent ]
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
|
}));
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = TestBed.createComponent(PhoneFormatterComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,20 @@
|
||||||
|
import { Component } from '@angular/core';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-phone-formatter-cell',
|
||||||
|
template: `
|
||||||
|
<span>({{firstThree}}) {{secondThree}}-{{lastFour}}</span>
|
||||||
|
`
|
||||||
|
})
|
||||||
|
export class PhoneFormatterComponent {
|
||||||
|
firstThree: string;
|
||||||
|
secondThree: string;
|
||||||
|
lastFour: string;
|
||||||
|
|
||||||
|
agInit(params: any): void {
|
||||||
|
const whole: string = params.value;
|
||||||
|
this.firstThree = whole.substr(0, 3);
|
||||||
|
this.secondThree = whole.substr(3, 3);
|
||||||
|
this.lastFour = whole.substr(6, 4);
|
||||||
|
}
|
||||||
|
}
|
|
@ -7,7 +7,7 @@ import { AstuteClientService } from './services/astute-client-service';
|
||||||
import { AgGridModule } from 'ag-grid-angular';
|
import { AgGridModule } from 'ag-grid-angular';
|
||||||
import { ModalFormComponent } from './modal-form/modal-form.component';
|
import { ModalFormComponent } from './modal-form/modal-form.component';
|
||||||
import { NgbModule } from '@ng-bootstrap/ng-bootstrap';
|
import { NgbModule } from '@ng-bootstrap/ng-bootstrap';
|
||||||
import {HttpClientModule} from '@angular/common/http';
|
import { HttpClientModule } from '@angular/common/http';
|
||||||
import { AppRoutingModule } from './app-routing.module';
|
import { AppRoutingModule } from './app-routing.module';
|
||||||
import { NavBarComponent } from './nav-bar/nav-bar.component';
|
import { NavBarComponent } from './nav-bar/nav-bar.component';
|
||||||
import { SalesOrderComponent } from './sales-order/sales-order.component';
|
import { SalesOrderComponent } from './sales-order/sales-order.component';
|
||||||
|
@ -23,6 +23,9 @@ import { FormsModule } from '@angular/forms';
|
||||||
import { ReactiveFormsModule } from '@angular/forms';
|
import { ReactiveFormsModule } from '@angular/forms';
|
||||||
import { SettingsComponent } from './settings/settings.component';
|
import { SettingsComponent } from './settings/settings.component';
|
||||||
import { ToastsContainerComponent } from './services/toast-manager/toasts-container/toasts-container.component';
|
import { ToastsContainerComponent } from './services/toast-manager/toasts-container/toasts-container.component';
|
||||||
|
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 { ServiceTypeComponent } from './service-type/service-type.component';
|
// import { ServiceTypeComponent } from './service-type/service-type.component';
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
|
@ -39,12 +42,19 @@ import { ToastsContainerComponent } from './services/toast-manager/toasts-contai
|
||||||
LoginComponent,
|
LoginComponent,
|
||||||
InvoicePaymentComponent,
|
InvoicePaymentComponent,
|
||||||
SettingsComponent,
|
SettingsComponent,
|
||||||
ToastsContainerComponent// ,
|
ToastsContainerComponent,
|
||||||
|
NumberFormatterComponent,
|
||||||
|
PhoneFormatterComponent,
|
||||||
|
PhoneEditorComponent// ,
|
||||||
// ServiceTypeComponent
|
// ServiceTypeComponent
|
||||||
],
|
],
|
||||||
imports: [
|
imports: [
|
||||||
BrowserModule,
|
BrowserModule,
|
||||||
AgGridModule.withComponents([]),
|
AgGridModule.withComponents([
|
||||||
|
NumberFormatterComponent,
|
||||||
|
PhoneFormatterComponent,
|
||||||
|
PhoneEditorComponent
|
||||||
|
]),
|
||||||
NgbModule,
|
NgbModule,
|
||||||
HttpClientModule,
|
HttpClientModule,
|
||||||
AppRoutingModule,
|
AppRoutingModule,
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
[enableFilter]="true"
|
[enableFilter]="true"
|
||||||
[rowData]="rowData | async"
|
[rowData]="rowData | async"
|
||||||
[columnDefs]="columnDefs"
|
[columnDefs]="columnDefs"
|
||||||
|
[frameworkComponents]="frameworkComponents"
|
||||||
(cellEditingStopped)="updateRow($event)"
|
(cellEditingStopped)="updateRow($event)"
|
||||||
(gridReady)="onGridReady($event)"
|
(gridReady)="onGridReady($event)"
|
||||||
(rowClicked)="setSelectedRow($event)"
|
(rowClicked)="setSelectedRow($event)"
|
||||||
|
@ -307,6 +308,7 @@
|
||||||
[enableFilter]="true"
|
[enableFilter]="true"
|
||||||
[rowData]="contactsData | async"
|
[rowData]="contactsData | async"
|
||||||
[columnDefs]="contactsColDef"
|
[columnDefs]="contactsColDef"
|
||||||
|
[frameworkComponents]="frameworkComponents"
|
||||||
(cellEditingStopped)="updateContactRow($event)"
|
(cellEditingStopped)="updateContactRow($event)"
|
||||||
(gridReady)="onContactGridReady($event)"
|
(gridReady)="onContactGridReady($event)"
|
||||||
(rowDataChanged)="resizeColumns($event)"
|
(rowDataChanged)="resizeColumns($event)"
|
||||||
|
@ -317,23 +319,20 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="row justify-content-center mt-2">
|
<div class="row justify-content-center mt-2">
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<div class="btn-group w-100">
|
<div class="input-group mb-3 mt-2">
|
||||||
<button class="btn btn-success btn-sm w-100 mt-2 mb-2" type="button"
|
<input type="text" class="form-control input-group-sm" placeholder="Name" #customerContactName>
|
||||||
(click)="createEmptyContact()">
|
<div class="input-group-append w-25">
|
||||||
|
<button class="btn btn-success w-50 input-group-sm" type="button"
|
||||||
|
(click)="createEmptyContact(customerContactName.value); customerContactName.value = '';" [disabled]="!customerContactName.value">
|
||||||
Add
|
Add
|
||||||
</button>
|
</button>
|
||||||
<button class="btn btn-danger btn-sm w-100 mt-2 mb-2" type="button"
|
<button class="btn btn-danger w-50 input-group-sm" type="button"
|
||||||
(click)="deleteContact()">
|
(click)="deleteContact()">
|
||||||
Delete
|
Delete
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!--<div class="col">-->
|
</div>
|
||||||
<!--<button class="btn btn-danger btn-sm w-100 mt-2 mb-2" type="button"-->
|
|
||||||
<!--(click)="deleteContact()">-->
|
|
||||||
<!--Delete-->
|
|
||||||
<!--</button>-->
|
|
||||||
<!--</div>-->
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -341,20 +340,12 @@
|
||||||
<!--<button type="button" class="btn btn-info" (click)="close(contacts)">Exit</button>-->
|
<!--<button type="button" class="btn btn-info" (click)="close(contacts)">Exit</button>-->
|
||||||
<!--</div>-->
|
<!--</div>-->
|
||||||
</div>
|
</div>
|
||||||
<!--<div *ngIf="!selected">-->
|
<div *ngIf="!selected">
|
||||||
<!--<div class="modal-body">-->
|
<div class="modal-body">
|
||||||
<!--Choose a Customer First!-->
|
Choose a Customer First!
|
||||||
<!--</div>-->
|
</div>
|
||||||
<!--<div class="modal-footer">-->
|
<div class="modal-footer">
|
||||||
<!--<button class="btn btn-danger" type="button"-->
|
<button type="button" class="btn btn-info" (click)="close(contacts)">Exit</button>
|
||||||
<!--[disabled]="true">-->
|
</div>
|
||||||
<!--Delete Contact-->
|
</div>
|
||||||
<!--</button>-->
|
|
||||||
<!--<button class="btn btn-primary" type="button"-->
|
|
||||||
<!--[disabled]="true">-->
|
|
||||||
<!--Add Contact-->
|
|
||||||
<!--</button>-->
|
|
||||||
<!--<button type="button" class="btn btn-info" (click)="close(contacts)">Exit</button>-->
|
|
||||||
<!--</div>-->
|
|
||||||
<!--</div>-->
|
|
||||||
</app-modal-form>
|
</app-modal-form>
|
|
@ -1,6 +1,8 @@
|
||||||
import {Component, OnInit} from '@angular/core';
|
import {Component, OnInit} from '@angular/core';
|
||||||
import {AstuteClientService} from '../services/astute-client-service';
|
import {AstuteClientService} from '../services/astute-client-service';
|
||||||
import {ToastManagerService} from '../services/toast-manager/toast-service.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';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-customer',
|
selector: 'app-customer',
|
||||||
|
@ -17,19 +19,23 @@ export class CustomerComponent implements OnInit {
|
||||||
customers;
|
customers;
|
||||||
columnDefs = [
|
columnDefs = [
|
||||||
{headerName: 'ID', field: 'customerId'},
|
{headerName: 'ID', field: 'customerId'},
|
||||||
{headerName: 'Name', field: 'customerName', editable: true},
|
{headerName: 'Name ✎', field: 'customerName', editable: true},
|
||||||
{headerName: 'Bill To', field: 'billToDept', editable: true},
|
{headerName: 'Bill To ✎', field: 'billToDept', editable: true},
|
||||||
{headerName: 'Address 1', field: 'add1', editable: true},
|
{headerName: 'Address 1 ✎', field: 'add1', editable: true},
|
||||||
{headerName: 'Address 2', field: 'add2', editable: true},
|
{headerName: 'Address 2 ✎', field: 'add2', editable: true},
|
||||||
{headerName: 'City', field: 'city', editable: true},
|
{headerName: 'City ✎', field: 'city', editable: true},
|
||||||
{headerName: 'Email', field: 'email', editable: true},
|
{headerName: 'Email ✎', field: 'email', editable: true},
|
||||||
{headerName: 'Fax', field: 'fax', editable: true},
|
{headerName: 'Fax ✎', field: 'fax', editable: true, cellEditor: 'phoneEditorComponent'},
|
||||||
{headerName: 'Phone', field: 'phone', editable: true},
|
{headerName: 'Phone ✎', field: 'phone', editable: true, cellEditor: 'phoneEditorComponent'},
|
||||||
{headerName: 'Ext.', field: 'phExt', editable: true},
|
{headerName: 'Ext. ✎', field: 'phExt', editable: true},
|
||||||
{headerName: 'State', field: 'state', editable: true},
|
{headerName: 'State ✎', field: 'state', editable: true},
|
||||||
{headerName: 'ZIP', field: 'zip', editable: true},
|
{headerName: 'ZIP ✎', field: 'zip', editable: true},
|
||||||
{headerName: 'ZIP-4', field: 'ziplast4', editable: true}
|
{headerName: 'ZIP-4 ✎', field: 'ziplast4', editable: true}
|
||||||
];
|
];
|
||||||
|
frameworkComponents = {
|
||||||
|
phoneFormatterComponent: PhoneFormatterComponent,
|
||||||
|
phoneEditorComponent: PhoneEditorComponent
|
||||||
|
};
|
||||||
rowData: any;
|
rowData: any;
|
||||||
states = [
|
states = [
|
||||||
'AL',
|
'AL',
|
||||||
|
@ -88,15 +94,14 @@ export class CustomerComponent implements OnInit {
|
||||||
|
|
||||||
contactsData: any;
|
contactsData: any;
|
||||||
contactsColDef = [
|
contactsColDef = [
|
||||||
{headerName: 'ID', field: 'contactId', checkboxSelection: true},
|
{headerName: 'Name ✎', field: 'name', editable: true},
|
||||||
{headerName: 'Name', field: 'name', editable: true},
|
{headerName: 'Title ✎', field: 'title', editable: true},
|
||||||
{headerName: 'Title', field: 'title', editable: true},
|
{headerName: 'Email ✎', field: 'email', editable: true},
|
||||||
{headerName: 'Email', field: 'email', editable: true},
|
{headerName: 'Work ✎', field: 'workPhone', editable: true, cellEditor: 'phoneEditorComponent'},
|
||||||
{headerName: 'Work', field: 'workPhone', editable: true},
|
{headerName: 'Phone ✎', field: 'mobile', editable: true, cellEditor: 'phoneEditorComponent'},
|
||||||
{headerName: 'Phone', field: 'mobile', editable: true},
|
{headerName: 'Ext. ✎', field: 'phExt', editable: true},
|
||||||
{headerName: 'Ext.', field: 'phExt', editable: true},
|
{headerName: 'Fax ✎', field: 'fax', editable: true, cellEditor: 'phoneEditorComponent'},
|
||||||
{headerName: 'Fax', field: 'fax', editable: true},
|
{headerName: 'Address ✎', field: 'address', editable: true}
|
||||||
{headerName: 'Address', field: 'address', editable: true}
|
|
||||||
];
|
];
|
||||||
|
|
||||||
// address: "123 Test Drive"
|
// address: "123 Test Drive"
|
||||||
|
@ -211,17 +216,17 @@ export class CustomerComponent implements OnInit {
|
||||||
}
|
}
|
||||||
|
|
||||||
// wrappers for contact service methods (only inline editing)
|
// wrappers for contact service methods (only inline editing)
|
||||||
createEmptyContact() {
|
createEmptyContact(name: string) {
|
||||||
const newContactData = {
|
const newContactData = {
|
||||||
address: '',
|
address: '',
|
||||||
customerId: this.selected.customerId,
|
customerId: this.selected.customerId,
|
||||||
email: '',
|
email: '',
|
||||||
fax: null,
|
fax: '',
|
||||||
mobile: null,
|
mobile: '',
|
||||||
name: '',
|
name: name,
|
||||||
phExt: null,
|
phExt: '',
|
||||||
title: '',
|
title: '',
|
||||||
workPhone: null
|
workPhone: ''
|
||||||
};
|
};
|
||||||
console.log(newContactData);
|
console.log(newContactData);
|
||||||
this.astuteClientService.createCustomerContact(newContactData).then ((data) => {
|
this.astuteClientService.createCustomerContact(newContactData).then ((data) => {
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
[enableFilter]="true"
|
[enableFilter]="true"
|
||||||
[rowData]="source"
|
[rowData]="source"
|
||||||
[columnDefs]="columnDefs"
|
[columnDefs]="columnDefs"
|
||||||
|
[frameworkComponents]="frameworkComponents"
|
||||||
(cellEditingStopped)="updateRow($event)"
|
(cellEditingStopped)="updateRow($event)"
|
||||||
(gridReady)="onGridReady($event)"
|
(gridReady)="onGridReady($event)"
|
||||||
(rowDataChanged)="resizeColumns($event)"
|
(rowDataChanged)="resizeColumns($event)"
|
||||||
|
@ -679,22 +680,33 @@
|
||||||
[enableFilter]="true"
|
[enableFilter]="true"
|
||||||
[rowData]="selectedInDetails | async"
|
[rowData]="selectedInDetails | async"
|
||||||
[columnDefs]="detailColumnDefs"
|
[columnDefs]="detailColumnDefs"
|
||||||
|
[frameworkComponents]="frameworkComponents"
|
||||||
(cellEditingStopped)="updateDetailRow($event)"
|
(cellEditingStopped)="updateDetailRow($event)"
|
||||||
(gridReady)="onDetailGridReady($event)"
|
(gridReady)="onDetailGridReady($event)"
|
||||||
(rowDataChanged)="resizeColumns($event)"
|
(rowDataChanged)="resizeColumns($event)"
|
||||||
rowSelection="single"
|
rowSelection="single"
|
||||||
></ag-grid-angular>
|
></ag-grid-angular>
|
||||||
<div class="input-group mt-2">
|
<div class="input-group mt-2">
|
||||||
<select class="custom-select" #poDetailSelec
|
<select class="custom-select"
|
||||||
[disabled]="!selectedPODetails.length || (chosenInv ? chosenInv.invoiceStatus === 2 || chosenInv.invoiceStatus === 3: false)"
|
[disabled]="!selectedPODetails.length || (chosenInv ? chosenInv.invoiceStatus === 2 || chosenInv.invoiceStatus === 3: false)"
|
||||||
#poDetSelec>
|
#poDetailSelec>
|
||||||
|
<option value="" disabled selected>Choose Sales Order...</option>
|
||||||
<option *ngFor="let po of selectedPODetails" [value]="po.lineItemNo">{{po.serviceDesc}}</option>
|
<option *ngFor="let po of selectedPODetails" [value]="po.lineItemNo">{{po.serviceDesc}}</option>
|
||||||
<option [value]="-1">Out of Pocket Expenses</option>
|
<hr>
|
||||||
|
<option [value]="-1">Invoice Out of Pocket Expenses</option>
|
||||||
</select>
|
</select>
|
||||||
<div class="input-group-append">
|
<div class="input-group-append w-25">
|
||||||
<button class="btn btn-primary btn-sm" type="button" (click)="addEmptyDetail(poDetailSelec.value)"
|
<button class="btn btn-success w-50" type="button"
|
||||||
[disabled]="(chosenInv ? chosenInv.invoiceStatus === 2 || chosenInv.invoiceStatus === 3: false)">Add</button>
|
(click)="addEmptyDetail(poDetailSelec.value); poDetailSelec.selectedIndex = 0"
|
||||||
|
[disabled]="!poDetailSelec.value || (chosenInv ? chosenInv.invoiceStatus === 2 || chosenInv.invoiceStatus === 3: false)">
|
||||||
|
Add
|
||||||
|
</button>
|
||||||
|
<button class="btn btn-danger w-50 input-group-sm" type="button"
|
||||||
|
[disabled]="true">
|
||||||
|
Delete
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
import {Component, OnInit, ViewChild} from '@angular/core';
|
import {Component, OnInit, ViewChild} from '@angular/core';
|
||||||
import {AstuteClientService} from '../services/astute-client-service';
|
import {AstuteClientService} from '../services/astute-client-service';
|
||||||
import {formatCurrency} from "@angular/common";
|
import {formatCurrency} from '@angular/common';
|
||||||
import {PrintInvoiceService} from '../services/print-invoice.service';
|
import {PrintInvoiceService} from '../services/print-invoice.service';
|
||||||
import {ToastManagerService} from "../services/toast-manager/toast-service.service";
|
import {ToastManagerService} from '../services/toast-manager/toast-service.service';
|
||||||
|
import {NumberFormatterComponent} from '../ag-grid-components/number-formatter/number-formatter.component';
|
||||||
|
|
||||||
declare var $: any;
|
declare var $: any;
|
||||||
|
|
||||||
|
@ -49,8 +50,8 @@ export class InvoiceComponent implements OnInit {
|
||||||
{headerName: 'Sales Order Number', field: 'poNum'},
|
{headerName: 'Sales Order Number', field: 'poNum'},
|
||||||
{headerName: 'Change Order Number', field: 'changeOrderNum'},
|
{headerName: 'Change Order Number', field: 'changeOrderNum'},
|
||||||
{headerName: 'Outstanding Balance', field: 'outstandingBalanceString'},
|
{headerName: 'Outstanding Balance', field: 'outstandingBalanceString'},
|
||||||
{headerName: 'Bill Amount', field: 'billAmtString'},
|
{headerName: 'Bill Amount', field: 'billAmt', cellRenderer: 'numberFormatterComponent'},
|
||||||
{headerName: 'Notes', field: 'specialNotes',
|
{headerName: 'Notes ✎', field: 'specialNotes',
|
||||||
editable: (node => node.data.invoiceStatus === 1), cellEditor: 'agLargeTextCellEditor'}
|
editable: (node => node.data.invoiceStatus === 1), cellEditor: 'agLargeTextCellEditor'}
|
||||||
];
|
];
|
||||||
gridOptions = {
|
gridOptions = {
|
||||||
|
@ -60,18 +61,21 @@ export class InvoiceComponent implements OnInit {
|
||||||
'text-warning': (node => node.data.invoiceStatus === 3)
|
'text-warning': (node => node.data.invoiceStatus === 3)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
frameworkComponents = {
|
||||||
|
numberFormatterComponent: NumberFormatterComponent
|
||||||
|
};
|
||||||
detailColumnDefs = [
|
detailColumnDefs = [
|
||||||
{headerName: '#', field: 'lineItemNum'},
|
{headerName: '#', field: 'lineItemNum'},
|
||||||
{headerName: 'PO Detail', field: 'poDetailName'},
|
{headerName: 'PO Detail', field: 'poDetailName'},
|
||||||
{headerName: 'Description', field: 'desc',
|
{headerName: 'Description ✎', field: 'desc',
|
||||||
editable: (_ => (this.chosenInv && this.chosenInv.invoiceStatus === 1)), cellEditor: 'agLargeTextCellEditor'},
|
editable: (_ => (this.chosenInv && this.chosenInv.invoiceStatus === 1)), cellEditor: 'agLargeTextCellEditor'},
|
||||||
{headerName: 'Fee Type', field: 'rateTypeName'},
|
{headerName: 'Fee Type', field: 'rateTypeName'},
|
||||||
{headerName: 'Service Type', field: 'serviceTypeName'},
|
{headerName: 'Service Type', field: 'serviceTypeName'},
|
||||||
{headerName: 'Qty or Hours', field: 'qty',
|
{headerName: 'Qty or Hours ✎', field: 'qty',
|
||||||
editable: (_ => (this.chosenInv && this.chosenInv.invoiceStatus === 1))},
|
editable: (_ => (this.chosenInv && this.chosenInv.invoiceStatus === 1))},
|
||||||
{headerName: '(/Remaining)', field: 'remainingQty'},
|
{headerName: '(/Remaining)', field: 'remainingQty'},
|
||||||
{headerName: 'Fee', field: 'fee',
|
{headerName: 'Fee', field: 'fee',
|
||||||
editable: (_ => (this.chosenInv && this.chosenInv.invoiceStatus === 1))}
|
cellRenderer: 'numberFormatterComponent'}
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
||||||
|
@ -261,7 +265,7 @@ export class InvoiceComponent implements OnInit {
|
||||||
} else {
|
} else {
|
||||||
const temp = this.selectedPODetails[invDetail.poLineItemNum - 1];
|
const temp = this.selectedPODetails[invDetail.poLineItemNum - 1];
|
||||||
if (temp) {
|
if (temp) {
|
||||||
invDetail.poDetailName = this.selectedPODetails[invDetail.poLineItemNum - 1].desc;
|
invDetail.poDetailName = this.selectedPODetails[invDetail.poLineItemNum - 1].serviceDesc;
|
||||||
} else {
|
} else {
|
||||||
invDetail.poDetailName = '';
|
invDetail.poDetailName = '';
|
||||||
}
|
}
|
||||||
|
@ -550,17 +554,32 @@ export class InvoiceComponent implements OnInit {
|
||||||
|
|
||||||
// creates empty line item detail
|
// creates empty line item detail
|
||||||
addEmptyDetail(poLineItemNum) {
|
addEmptyDetail(poLineItemNum) {
|
||||||
const emptyData = {
|
let emptyData;
|
||||||
desc: '',
|
if (poLineItemNum === -1) {
|
||||||
fee: 0,
|
emptyData = {
|
||||||
feeTypeId: 1,
|
desc: this.selectedPODetails[poLineItemNum - 1].serviceDesc,
|
||||||
|
fee: this.selectedPODetails[poLineItemNum - 1].fee,
|
||||||
|
feeTypeId: this.selectedPODetails[poLineItemNum - 1].feeTypeId,
|
||||||
invoiceNum: this.chosenInv.invoiceNumber,
|
invoiceNum: this.chosenInv.invoiceNumber,
|
||||||
// lineItemNum: 1,
|
// lineItemNum: 1,
|
||||||
poLineItemNum: poLineItemNum,
|
poLineItemNum: poLineItemNum,
|
||||||
qty: 1,
|
qty: 1,
|
||||||
remainingQty: 1,
|
remainingQty: this.selectedPODetails[poLineItemNum - 1].remainingQty,
|
||||||
serviceTypeId: 1
|
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,
|
||||||
|
serviceTypeId: this.selectedPODetails[poLineItemNum - 1].serviceTypeId
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
// desc: "Design Somethign"
|
// desc: "Design Somethign"
|
||||||
// fee: 2500
|
// fee: 2500
|
||||||
|
|
|
@ -25,12 +25,13 @@ export class NavBarComponent implements OnInit {
|
||||||
}
|
}
|
||||||
|
|
||||||
logout() {
|
logout() {
|
||||||
|
this.notif('Logging Out...');
|
||||||
this.astuteClientService.logout().then((data) => {
|
this.astuteClientService.logout().then((data) => {
|
||||||
if (data) {
|
if (data) {
|
||||||
this.router.navigate(['/login']);
|
this.router.navigate(['/login']);
|
||||||
this.notif('Logout successful');
|
this.notif('Logout Successful');
|
||||||
} else {
|
} else {
|
||||||
this.notif('Logout unsuccessful');
|
this.notif('Logout Unsuccessful');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
[enableFilter]="true"
|
[enableFilter]="true"
|
||||||
[rowData]="rowData | async"
|
[rowData]="rowData | async"
|
||||||
[columnDefs]="columnDefs"
|
[columnDefs]="columnDefs"
|
||||||
|
[frameworkComponents]="frameworkComponents"
|
||||||
(cellEditingStopped)="updateRow($event)"
|
(cellEditingStopped)="updateRow($event)"
|
||||||
(gridReady)="onGridReady($event)"
|
(gridReady)="onGridReady($event)"
|
||||||
(rowClicked)="setSelectedRow($event)"
|
(rowClicked)="setSelectedRow($event)"
|
||||||
|
@ -415,12 +416,30 @@
|
||||||
[enableFilter]="true"
|
[enableFilter]="true"
|
||||||
[rowData]="selectedPODetail | async"
|
[rowData]="selectedPODetail | async"
|
||||||
[columnDefs]="detailColumnDefs"
|
[columnDefs]="detailColumnDefs"
|
||||||
|
[frameworkComponents]="frameworkComponents"
|
||||||
(cellEditingStopped)="updateDetailRow($event)"
|
(cellEditingStopped)="updateDetailRow($event)"
|
||||||
(gridReady)="onDetailGridReady($event)"
|
(gridReady)="onDetailGridReady($event)"
|
||||||
(rowDataChanged)="resizeColumns($event)"
|
(rowDataChanged)="resizeColumns($event)"
|
||||||
rowSelection="single"
|
rowSelection="single"
|
||||||
></ag-grid-angular>
|
></ag-grid-angular>
|
||||||
<button class="btn btn-primary btn-sm w-100 mt-2" type="button" (click)="addEmptyDetail()" [disabled]="(selected ? selected.isFinal : false)">Add</button>
|
</div>
|
||||||
|
</div>
|
||||||
|
<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>
|
||||||
|
<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 = '';"
|
||||||
|
[disabled]="!poDescription.value || (selected ? selected.isFinal : false)">
|
||||||
|
Add
|
||||||
|
</button>
|
||||||
|
<button class="btn btn-danger w-50 input-group-sm" type="button"
|
||||||
|
[disabled]="true">
|
||||||
|
Delete
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<hr>
|
<hr>
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
import {Component, OnInit, ViewChild} from '@angular/core';
|
import {Component, OnInit, ViewChild} from '@angular/core';
|
||||||
import {AstuteClientService} from '../services/astute-client-service';
|
import {AstuteClientService} from '../services/astute-client-service';
|
||||||
import {formatCurrency} from '@angular/common';
|
import {formatCurrency, formatNumber} from '@angular/common';
|
||||||
import {ToastManagerService} from "../services/toast-manager/toast-service.service";
|
import {ToastManagerService} from '../services/toast-manager/toast-service.service';
|
||||||
|
import {NumberFormatterComponent} from '../ag-grid-components/number-formatter/number-formatter.component';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-sales-order',
|
selector: 'app-sales-order',
|
||||||
|
@ -25,19 +26,20 @@ export class SalesOrderComponent implements OnInit {
|
||||||
// data for SO grid
|
// data for SO grid
|
||||||
rowData: any;
|
rowData: any;
|
||||||
columnDefs = [
|
columnDefs = [
|
||||||
{headerName: 'Project Number', field: 'astuteProjectNumber', editable: (node => !node.data.isFinal)},
|
{headerName: 'Project Number ✎', field: 'astuteProjectNumber', editable: (node => !node.data.isFinal)},
|
||||||
{headerName: 'SO Number', field: 'ponum'},
|
{headerName: 'SO Number', field: 'ponum'},
|
||||||
// {headerName: 'Customer ID', field: 'customerId'},
|
// {headerName: 'Customer ID', field: 'customerId'},
|
||||||
{headerName: 'Customer Name', field: 'customerName'},
|
{headerName: 'Customer Name', field: 'customerName'},
|
||||||
{headerName: 'Contract Number', field: 'contractNum', editable: (node => !node.data.isFinal)},
|
{headerName: 'Contract Number ✎', field: 'contractNum', editable: (node => !node.data.isFinal)},
|
||||||
{headerName: 'SO Title', field: 'title', editable: (node => !node.data.isFinal)},
|
{headerName: 'SO Title ✎', field: 'title', editable: (node => !node.data.isFinal)},
|
||||||
{headerName: 'Contract Amount', field: 'contractAmtString'},
|
{headerName: 'Contract Amount', field: 'contractAmt', cellRenderer: 'numberFormatterComponent'},
|
||||||
// {headerName: 'Contract Amount', field: 'contractAmt'},
|
// {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)},
|
||||||
{headerName: '# of Invoices', field: 'invoiceSequence'},
|
{headerName: '# of Invoices', field: 'invoiceSequence'},
|
||||||
{headerName: 'notes', field: 'notes', editable: (node => !node.data.isFinal), cellEditor: 'agLargeTextCellEditor'}
|
{headerName: 'notes ✎', field: 'notes', editable: (node => !node.data.isFinal), cellEditor: 'agLargeTextCellEditor'}
|
||||||
// {headerName: 'oneInvInDraft', field: 'oneInvInDraft'}
|
// {headerName: 'oneInvInDraft', field: 'oneInvInDraft'}
|
||||||
];
|
];
|
||||||
|
|
||||||
gridOptions = {
|
gridOptions = {
|
||||||
rowClassRules: {
|
rowClassRules: {
|
||||||
'text-danger': function (params) {
|
'text-danger': function (params) {
|
||||||
|
@ -48,19 +50,25 @@ export class SalesOrderComponent implements OnInit {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
frameworkComponents = {
|
||||||
|
numberFormatterComponent: NumberFormatterComponent
|
||||||
|
};
|
||||||
|
|
||||||
selected = null; // the selected SO row
|
selected = null; // the selected SO row
|
||||||
|
|
||||||
// data for SO detail grid
|
// data for SO detail grid
|
||||||
selectedPODetail;
|
selectedPODetail;
|
||||||
detailColumnDefs = [
|
detailColumnDefs = [
|
||||||
{headerName: '#', field: 'lineItemNo'},
|
{headerName: '#', field: 'lineItemNo'},
|
||||||
{headerName: 'Description', field: 'serviceDesc', editable: (_ => (this.selected && !this.selected.isFinal))},
|
{headerName: 'Description ✎', field: 'serviceDesc', editable: (_ => (this.selected && !this.selected.isFinal))},
|
||||||
{headerName: 'Rate Type', field: 'rateTypeName', editable: (_ => (this.selected && !this.selected.isFinal)),
|
{headerName: 'Rate Type ✎', field: 'rateTypeName', editable: (_ => (this.selected && !this.selected.isFinal)),
|
||||||
cellEditor: 'agSelectCellEditor', cellEditorParams: {values: this.rateNames}},
|
cellEditor: 'agSelectCellEditor', cellEditorParams: {values: this.rateNames}},
|
||||||
{headerName: 'Service Type', field: 'serviceTypeName', editable: (_ => (this.selected && !this.selected.isFinal)),
|
{headerName: 'Service Type ✎', field: 'serviceTypeName', editable: (_ => (this.selected && !this.selected.isFinal)),
|
||||||
cellEditor: 'agSelectCellEditor', cellEditorParams: {values: this.serviceNames}},
|
cellEditor: 'agSelectCellEditor', cellEditorParams: {values: this.serviceNames}},
|
||||||
{headerName: 'Qty or Hours', field: 'qty', editable: (_ => (this.selected && !this.selected.isFinal))},
|
{headerName: 'Qty or Hours ✎', field: 'qty', editable: (_ => (this.selected && !this.selected.isFinal))},
|
||||||
{headerName: 'Rate ($)', field: 'fee', editable: (_ => (this.selected && !this.selected.isFinal))}
|
{headerName: 'Rate ($) ✎', field: 'fee', editable: (_ => (this.selected && !this.selected.isFinal)),
|
||||||
|
cellRenderer: 'numberFormatterComponent'}
|
||||||
];
|
];
|
||||||
contractAmount = 0; // used to show total amount
|
contractAmount = 0; // used to show total amount
|
||||||
|
|
||||||
|
@ -243,7 +251,7 @@ export class SalesOrderComponent implements OnInit {
|
||||||
}
|
}
|
||||||
|
|
||||||
// wrappers for SO detail service methods
|
// wrappers for SO detail service methods
|
||||||
addEmptyDetail() {
|
addEmptyDetail(desc: string) {
|
||||||
const emptyData = {
|
const emptyData = {
|
||||||
fee: 0,
|
fee: 0,
|
||||||
feeTypeId: 1,
|
feeTypeId: 1,
|
||||||
|
@ -251,7 +259,7 @@ export class SalesOrderComponent implements OnInit {
|
||||||
poNum: this.selected.poNum,
|
poNum: this.selected.poNum,
|
||||||
qty: 1,
|
qty: 1,
|
||||||
remainingQty: 1,
|
remainingQty: 1,
|
||||||
serviceDesc: '',
|
serviceDesc: desc,
|
||||||
serviceTypeId: 1
|
serviceTypeId: 1
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -273,6 +281,7 @@ export class SalesOrderComponent implements OnInit {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// open and closing modal-form components
|
// open and closing modal-form components
|
||||||
open(ref) {
|
open(ref) {
|
||||||
// this.getSelectedRows();
|
// this.getSelectedRows();
|
||||||
|
@ -315,7 +324,6 @@ export class SalesOrderComponent implements OnInit {
|
||||||
// this.pos = data;
|
// this.pos = data;
|
||||||
data.forEach((row) => {
|
data.forEach((row) => {
|
||||||
row.customerName = this.getCustomerNameFromId(row.customerId);
|
row.customerName = this.getCustomerNameFromId(row.customerId);
|
||||||
row.contractAmtString = formatCurrency(row.contractAmt, 'en-US', '$', 'USD');
|
|
||||||
row.poNum = row.ponum;
|
row.poNum = row.ponum;
|
||||||
});
|
});
|
||||||
this.selected = null;
|
this.selected = null;
|
||||||
|
|
|
@ -398,6 +398,29 @@ export class AstuteClientService {
|
||||||
this.notif(error);
|
this.notif(error);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
// public deletePODetail(customerId) {
|
||||||
|
// console.log('*** In deleteCustomer()');
|
||||||
|
// const url = `${this.customerUrl}/${customerId}/delete${this.sessionString}`;
|
||||||
|
// return this.http.put(url, {})
|
||||||
|
// .toPromise()
|
||||||
|
// .then(response => {
|
||||||
|
// const code = response['code'];
|
||||||
|
// const message = response['message'];
|
||||||
|
// if (code === 9000) {
|
||||||
|
// console.log(response['entity']);
|
||||||
|
// return response['entity'];
|
||||||
|
// } else if (message.includes('login')) {
|
||||||
|
// this.notif('Please login again!');
|
||||||
|
// } else {
|
||||||
|
// this.notif('Delete Customer Failed: ' + message);
|
||||||
|
// }
|
||||||
|
// }, (reason) => {
|
||||||
|
// this.notif('Delete Customer Failed: ' + reason);
|
||||||
|
// })
|
||||||
|
// .catch( error => {
|
||||||
|
// this.notif(error);
|
||||||
|
// });
|
||||||
|
// }
|
||||||
public finalizePO(ponum: string) {
|
public finalizePO(ponum: string) {
|
||||||
console.log('*** In finalizePO()');
|
console.log('*** In finalizePO()');
|
||||||
const url = `${this.POUrl}/${ponum}/finalize${this.sessionString}`;
|
const url = `${this.POUrl}/${ponum}/finalize${this.sessionString}`;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user