astute/AstuteClient2/src/app/sales-order/sales-order.component.ts
2019-07-16 23:12:22 -04:00

429 lines
15 KiB
TypeScript

import {Component, OnInit, ViewChild} from '@angular/core';
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',
templateUrl: './sales-order.component.html',
styleUrls: ['./sales-order.component.css']
})
export class SalesOrderComponent implements OnInit {
loggedIn: boolean;
// both of the grid api's
gridApi;
gridColumnApi;
detailGridApi;
detailColumnApi;
// one time fetch meta-data
customers;
serviceTypes;
serviceNames = [];
rateTypes = [];
rateNames = [];
// data for SO grid
rowData: any;
columnDefs = [
{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), 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), cellEditor: 'emptyErrorEditorComponent'},
{headerName: '# of Invoices', field: 'invoiceSequence'},
{headerName: 'notes ✎', field: 'notes', editable: (node => !node.data.isFinal), cellEditor: 'agLargeTextCellEditor'}
// {headerName: 'oneInvInDraft', field: 'oneInvInDraft'}
];
gridOptions = {
rowClassRules: {
'text-danger': function (params) {
return !params.data.isFinal;
},
'text-primary': function (params) {
return params.data.isFinal;
},
}
};
frameworkComponents = {
emptyErrorEditorComponent: EmptyErrorEditorComponent,
numberFormatterComponent: NumberFormatterComponent
};
selected = null; // the selected SO row
// data for SO detail grid
selectedPODetail;
detailColumnDefs = [
{headerName: '#', field: 'lineItemNo'},
{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)),
cellEditor: 'agSelectCellEditor', cellEditorParams: {values: this.serviceNames}},
{headerName: 'Qty or Hours ✎', field: 'qty', 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
constructor(private astuteClientService: AstuteClientService, protected toastService: ToastManagerService) {
}
ngOnInit() {
if (localStorage.getItem('SESSION_ID') && localStorage.getItem('SESSION_USER')) {
this.loggedIn = true;
this.astuteClientService.getServiceTypes().then((d) => {
if (d) {
this.serviceTypes = d;
this.serviceTypes.forEach((type) => {
this.serviceNames.push(type.serviceTypeDesc);
});
// console.log(this.serviceNames);
} else {
this.notif ('Get service types failed');
}
}, reason => {
this.notif('Get service type failed: ' + reason);
});
this.astuteClientService.getRateTypes().then((d) => {
if (d) {
this.rateTypes = d;
this.rateTypes.forEach((type) => {
this.rateNames.push(type.feeTypeDesc);
});
} else {
this.notif ('Get rate types failed');
}
}, reason => {
this.notif('Get rate type failed: ' + reason);
});
this.astuteClientService.getCustomers().then((customers) => {
if (customers) {
this.customers = customers;
} else {
this.notif('Get Customers Failed!');
}
}, (reason) => {
this.notif('Get Customers Failed: ' + reason);
});
this.refreshData();
} else {
this.loggedIn = false;
}
}
// callback for grid selection
setSelectedRow(event) {
if (event) {
this.selected = event.data;
}
this.selectedPODetail = this.astuteClientService.getPODetail(this.selected.ponum).then((data) => {
if (data) {
data.forEach((row) => {
row.poNum = row.ponum;
row.serviceTypeName = this.serviceNames[row.serviceTypeId - 1];
row.rateTypeName = this.rateNames[row.feeTypeId - 1];
});
this.updateContractAmt();
return data;
} else {
this.notif('Get SO detail failed!');
}
}, (reason) => {
this.notif('Get SO detail failed: ' + reason);
});
}
// for inline updating
updateRow(event) {
const eventData = event.data;
// console.log(eventData);
this.astuteClientService.updatePO(eventData.poNum, eventData).then((data) => {
if (!data) {
this.notif('SO updating failed, check input fields');
this.refreshData();
}
}, (reason) => {
this.notif('Update SO failed: ' + reason);
});
// this.refreshData();
}
updateDetailRow(event) {
const eventData = event.data;
// console.log(eventData);
event.data.serviceTypeId = this.getServiceIdFromName(event.data.serviceTypeName);
event.data.feeTypeId = this.getFeeIdFromName(event.data.rateTypeName);
if (event.data.feeTypeId === 1 && event.data.qty > 1) { // fixed fee and qty > 1
this.notif('Cannot have a quantity greater than 1 for fixed fee rate type.');
this.refreshDetailsOfSelected();
} else {
// console.log(event.data.serviceTypeId);
this.astuteClientService.updatePODetail(eventData.poNum, eventData.lineItemNo, eventData).then((data) => {
if (!data) {
this.notif('SO Detail updating failed, check input fields');
this.refreshDetailsOfSelected();
} else {
this.updateContractAmt();
}
}, (reason) => {
this.notif('Update SO Detail failed: ' + reason);
});
// this.refreshData();
}
}
// wrappers for PO service methods
addPo(projNum, ponum, podate, customerid, contractnum, contractamt, title, notes, ref) {
const poData = {
'astuteProjectNumber': projNum,
'poNum': ponum,
'podate': podate,
'customerId': customerid,
'contractNum': contractnum,
'contractAmt': contractamt,
'title': title,
'notes': notes
};
// console.log(poData);
this.astuteClientService.createPO(poData).then((data) => {
if (data) {
this.refreshData();
// this.addPODetail(this.newPODetail);
ref.close();
} else {
this.notif('SO Creation failed, check input fields');
}
}, (reason) => {
this.notif('Add SO failed for ' + reason);
});
}
editPo(projNum, ponum, podate, contractnum, contractamt, title, notes, ref) {
const poData = {
'astuteProjectNumber': projNum,
'poNum': ponum,
'podate': podate,
'contractNum': contractnum,
'contractAmt': contractamt,
'title': title,
'notes': notes,
};
// console.log(poData);
this.astuteClientService.updatePO(ponum, poData).then((data) => {
if (data) {
this.refreshData();
// this.editPODetail(this.selectedPODetail);
ref.close();
} else {
this.notif('SO updating failed, check input fields');
}
}, (reason) => {
this.notif('Update SO failed for ' + reason);
});
}
finalizePO(ponum) {
this.astuteClientService.finalizePO(ponum).then((data) => {
if (data) {
this.refreshData();
this.notif('SO is now final and ready to be used, you can\'t edit it anymore!');
} else {
this.notif('Finalizing SO failed, check input fields');
}
}, reason => {
this.notif('Finalizing SO failed: ' + reason);
});
}
deletePO(ponum) {
if (confirm('Are you sure?')) {
this.astuteClientService.deletePO(ponum).then((data) => {
if (data) {
this.refreshData();
} else {
this.notif('Deleting SO failed, check input fields');
}
}, (reason) => {
this.notif('Deleting SO failed: ' + reason);
});
}
}
// wrappers for SO detail service methods
addEmptyDetail(desc: string) {
const emptyData = {
fee: 0,
feeTypeId: 1,
// lineItemNo: 7,
poNum: this.selected.poNum,
qty: 1,
remainingQty: 1,
serviceDesc: desc,
serviceTypeId: 1
};
// String poNum;
// int lineItemNo;
// String serviceDesc;
// int feeTypeId;
// Double qty;
// Double fee;
// int serviceTypeId;
// Double remainingQuantity;
this.astuteClientService.createPODetail(emptyData).then((data) => {
if (!data) {
this.notif('Creating SO detailed failed!');
}
this.refreshDetailsOfSelected();
}, (reason) => {
this.notif('Creating SO detailed failed: ' + reason);
});
}
// open and closing modal-form components
open(ref) {
// this.getSelectedRows();
ref.open();
if (this.gridColumnApi) {
this.gridColumnApi.autoSizeAllColumns();
}
if (this.detailColumnApi) {
this.detailColumnApi.autoSizeAllColumns();
}
}
close(ref) {
// this.newPODetail = [];
// this.selectedPODetail = [];
ref.close();
}
// refreshing data methods
refreshData() {
// this.astuteClientService.getPOs().then((data) => {
// if (data) {
// // this.pos = data;
// this.rowData = data;
// this.rowData.forEach((row) => {
// row.customerName = this.getCustomerNameFromId(row.customerId);
// row.contractAmtString = formatCurrency(row.contractAmt, 'en-US', '$', 'USD');
// row.poNum = row.ponum;
// });
// this.selected = null;
// this.updateNewContractAmt();
// this.updateEditContractAmt();
// } else {
// this.notif('Get SO\'s Failed!');
// }
// }, (reason) => {
// this.notif('Get SO\'s Failed: ' + reason);
// });
this.rowData = this.astuteClientService.getPOs().then((data) => {
if (data) {
// this.pos = data;
data.forEach((row) => {
row.customerName = this.getCustomerNameFromId(row.customerId);
row.poNum = row.ponum;
});
this.selected = null;
this.contractAmount = 0;
return data;
} else {
this.notif('Get SO\'s Failed!');
}
}, (reason) => {
this.notif('Get SO\'s Failed: ' + reason);
});
}
refreshDetailsOfSelected() {
this.setSelectedRow(null);
}
updateContractAmt() {
this.contractAmount = 0;
if (this.selectedPODetail) {
this.selectedPODetail.then((detail) => {
detail.forEach((d) => {
this.contractAmount += +d.qty * +d.fee;
});
});
}
}
// helper methods
getCurrDate() {
const d = new Date();
return this.formatDate(d);
}
formatDate(d: Date) {
let month = '' + (d.getMonth() + 1),
day = '' + d.getDate(),
year = d.getFullYear();
if (month.length < 2) {
month = '0' + month;
}
if (day.length < 2) {
day = '0' + day;
}
return [year, month, day].join('-');
}
getCustomerNameFromId(customerId) {
let name = '';
this.customers.forEach((customer) => {
if (customer.customerId === customerId) {
name = customer.customerName;
}
});
return name;
}
getServiceIdFromName(name) {
let id = -1;
this.serviceTypes.forEach((type) => {
console.log(type.serviceTypeDesc + ' ' + name);
if (type.serviceTypeDesc === name) {
id = type.serviceTypeId;
}
});
return id;
}
getFeeIdFromName(name: any) {
let id = -1;
this.rateTypes.forEach((type) => {
if (type.feeTypeDesc === name) {
id = type.feeTypeId;
}
});
return id;
}
// ag grid callbacks
onGridReady(evt) {
this.gridApi = evt.api;
this.gridColumnApi = evt.columnApi;
}
onDetailGridReady(evt) {
this.detailGridApi = evt.api;
this.detailColumnApi = evt.columnApi;
}
resizeColumns(evt) {
evt.columnApi.autoSizeAllColumns();
}
// ** toast notification method
notif(text: string) {
this.toastService.show(text, {classname: 'bg-danger text-light'});
}
}