diff --git a/src/components/Utilities/index.js b/src/components/Utilities/index.js index 2ef6f4a7e7671e4a8cc5d78892e98371cf40ffdb..36eacf7cacc98515f54d400f8f4c3f0aedbe6e5d 100644 --- a/src/components/Utilities/index.js +++ b/src/components/Utilities/index.js @@ -2,7 +2,7 @@ import React, { Component, PropTypes, cloneElement } from 'react'; import buildingDetailPropTypes from '../../containers/Building/propTypes'; import request from '../../utils/request'; -import { getHeaders, billsURL, accountURL } from '../../utils/restServices'; +import { getHeaders, scrapeURL, accountURL } from '../../utils/restServices'; import documentsPropType from '../../containers/Documents/propTypes'; import UtilityAccount from '../UtilityAccount'; @@ -55,7 +55,7 @@ class Utilities extends Component { const data = res.data; if (!res.err && data.utilities) { const allDocumentKeys = data.utilities.reduce((acc, val) => { - acc.push(val.scrape_document_key); + acc.push(val.bill_document_key); acc.push(val.disaggregate_document_key); return acc; }, []); @@ -63,20 +63,22 @@ class Utilities extends Component { this.props.getDocuments([], allDocumentKeys, 'utilityBills'); const allAccounts = data.utilities.map((account) => { const documentKeys = { - scrape: account.scrape_document_key, + scrape: account.bill_document_key, disaggregate: account.disaggregate_document_key, }; - return this.createUtilityComponent({ - building_address: address, - utility: account.type, - account_number: account.account_number, - username: account.login, - password: account.pass, - access_code: account.access_code, - }, + return this.createUtilityComponent( + { + building_address: address, + utility: account.type, + account_number: account.account_number, + username: account.login, + password: account.pass, + access_code: account.access_code, + }, account.id, documentKeys, - this.parseDisaggregateData(account.disaggregated_csv_output), + account.bill_database_output, + this.parseDisaggregateData(account.disaggregated_database_output), ); }); const blankAccount = this.createUtilityComponent(); @@ -90,14 +92,15 @@ class Utilities extends Component { }); } - updateUtilityBill = ( + fetchUtilityBill = ( form, accountId, updateLoadingFetchState, + setBillData, setDisaggregateData, setDocumentURLs ) => { - request(billsURL, { + request(scrapeURL, { method: 'POST', headers: getHeaders(), body: JSON.stringify({ @@ -111,10 +114,13 @@ class Utilities extends Component { this.setState({ error: `Failed to retrieve utility bill. | ${res.err.message}` }); } else { const data = res.data; - const documentURLs = { disaggregate: data.disaggregate_download_url, - scrape: data.scrape_download_url }; + const documentURLs = { + disaggregate: data.disaggregate_download_url, + scrape: data.bill_download_url, + }; setDocumentURLs(documentURLs); - const disaggregateData = this.parseDisaggregateData(data.disaggregate_csv_output); + setBillData(data.bill_database_output); + const disaggregateData = this.parseDisaggregateData(data.disaggregate_database_output); setDisaggregateData(disaggregateData); this.resetErrorMessage(); @@ -123,13 +129,17 @@ class Utilities extends Component { }); } - updateDisaggregateBill = ( + updateBill = ( form, accountId, fileContent, updateLoadingUploadState, - setDisaggregateData) => { - request(`${billsURL}${accountId}`, { + setBillData, + setDisaggregateData, + setDocumentURLs, + dataType, + ) => { + request(`${scrapeURL}${accountId}`, { method: 'PUT', headers: getHeaders(), body: JSON.stringify({ @@ -138,13 +148,26 @@ class Utilities extends Component { building_id: this.props.buildingId, building_address: this.props.building.address, file_content: fileContent, + data_type: dataType, }), }).then((res) => { if (res.err) { this.setState({ error: `Failed to update utility bill. | ${res.err.message}` }); } else { const data = res.data; - const disaggregateData = this.parseDisaggregateData(data.disaggregate_csv_output); + const documentURLs = { + disaggregate: data.disaggregate_download_url, + }; + // If we upload a new disaggregated bill there will be no bill document key + if (data.bill_download_url) { + documentURLs.scrape = data.bill_download_url; + } + setDocumentURLs(documentURLs); + // If we upload disaggregated bill there will be no bill data + if (data.bill_database_output) { + setBillData(data.bill_database_output); + } + const disaggregateData = this.parseDisaggregateData(data.disaggregate_database_output); setDisaggregateData(disaggregateData); this.resetErrorMessage(); } @@ -230,16 +253,19 @@ class Utilities extends Component { } createUtilityComponent = ( - incForm, - accountId = null, - documentKeys = {}, - disaggregateData = []) => { + incForm, + accountId = null, + documentKeys = {}, + billData = [], + disaggregateData = [], + ) => { let accountProps = {}; const { accountsCounter } = this.state; if (incForm !== undefined) { accountProps = { form: incForm, account_id: accountId, + billData, disaggregateData, documentKeys, documentURLs: {}, @@ -257,8 +283,8 @@ class Utilities extends Component { key={accountsCounter} createAccount={this.createAccount} deleteAccount={this.deleteAccountLine} - updateUtilityBill={this.updateUtilityBill} - updateDisaggregateBill={this.updateDisaggregateBill} + fetchUtilityBill={this.fetchUtilityBill} + updateBill={this.updateBill} /> ); } diff --git a/src/components/UtilityAccount/index.js b/src/components/UtilityAccount/index.js index 8a521131b0ccfa78afe62d1b44c4636d6d0bf4e3..ce71dc24712342e91286290f5c863f86ade4de23 100644 --- a/src/components/UtilityAccount/index.js +++ b/src/components/UtilityAccount/index.js @@ -17,6 +17,7 @@ class UtilityAccount extends Component { access_code: this.props.form.access_code, }, account_id: this.props.account_id, + billData: this.props.billData, disaggregateData: this.props.disaggregateData, documentKeys: { scrape: this.props.documentKeys.scrape, @@ -28,7 +29,9 @@ class UtilityAccount extends Component { }, disabled: this.props.disabled, convertingFile: false, - displayChart: false, + displayBillData: false, + displayDisaggregateData: false, + displayDisaggregateChart: false, loadingFetch: false, loadingUpload: false, }; @@ -40,13 +43,22 @@ class UtilityAccount extends Component { } setDocumentURLs = urls => ( - this.setState({ documentURLs: urls }) + this.setState({ + documentURLs: { + ...this.state.documentURLs, + ...urls, + }, + }) ) setDisaggregateData = data => ( this.setState({ disaggregateData: data }) ) + setBillData = data => ( + this.setState({ billData: data }) + ) + updateLoadingFetchState = isLoading => ( this.setState({ loadingFetch: isLoading }) ) @@ -79,15 +91,17 @@ class UtilityAccount extends Component { }); } - handleUpdatingUtilityBill = (event) => { + handleFetchingUtilityBill = (event) => { event.preventDefault(); this.updateLoadingFetchState(true); - this.props.updateUtilityBill( - this.state.form, - this.state.account_id, - this.updateLoadingFetchState, - this.setDisaggregateData, - this.setDocumentURLs); + this.props.fetchUtilityBill( + this.state.form, + this.state.account_id, + this.updateLoadingFetchState, + this.setBillData, + this.setDisaggregateData, + this.setDocumentURLs + ); } handleCreateAccount = (event) => { @@ -101,9 +115,25 @@ class UtilityAccount extends Component { this.props.deleteAccount(this); } - toggleChartDisplay = (event) => { + toggleBillDataDisplay = (event) => { + event.preventDefault(); + this.setState({ + displayBillData: !this.state.displayBillData, + }); + } + + toggleDisaggregateDataDisplay = (event) => { event.preventDefault(); - this.setState({ displayChart: !this.state.displayChart }); + this.setState({ + displayDisaggregateData: !this.state.displayDisaggregateData, + }); + } + + toggleDisaggregateChartDisplay = (event) => { + event.preventDefault(); + this.setState({ + displayDisaggregateChart: !this.state.displayDisaggregateChart, + }); } isAccountNumberLong = () => this.state.form.account_number.length > 15; @@ -114,6 +144,10 @@ class UtilityAccount extends Component { uploadHandler = (event) => { const file = event.target.files[0]; + let dataType = 'bill'; + if (event.target.name === 'Disaggregated Bill') { + dataType = 'disaggregated_bill'; + } if (file) { this.setState({ convertingFile: true }); const fileReader = new FileReader(); @@ -122,12 +156,15 @@ class UtilityAccount extends Component { const base64result = fileReader.result.split(',')[1]; this.updateLoadingUploadState(true); this.setState({ convertingFile: false }); - this.props.updateDisaggregateBill( - this.state.form, - this.state.account_id, - base64result, - this.updateLoadingUploadState, - this.setDisaggregateData, + this.props.updateBill( + this.state.form, + this.state.account_id, + base64result, + this.updateLoadingUploadState, + this.setBillData, + this.setDisaggregateData, + this.setDocumentURLs, + dataType, ); }.bind(this); fileReader.readAsDataURL(file); @@ -137,8 +174,11 @@ class UtilityAccount extends Component { renderAddAccountBtn = () => { let isDisabled = !(this.state.form.account_number); if (this.state.form.utility === 'national_grid_gas') { - isDisabled = !(this.state.form.account_number && this.state.form.access_code) - && !(this.state.form.account_number && this.state.form.username && this.state.form.password); + isDisabled = !( + this.state.form.account_number && this.state.form.access_code + ) && !( + this.state.form.account_number && this.state.form.username && this.state.form.password + ); } isDisabled = isDisabled || this.isAccountNumberLong(); return ( @@ -152,12 +192,12 @@ class UtilityAccount extends Component { ); } - renderUploadButton = () => { + renderUploadButton = (type) => { let disabled = false; let img = (
- Upload Disaggregation + Upload {type}
); if (this.state.convertingFile || this.state.loadingUpload) { @@ -172,16 +212,16 @@ class UtilityAccount extends Component { ); } return ( -
+
-
@@ -193,7 +233,7 @@ class UtilityAccount extends Component { @@ -208,7 +248,7 @@ class UtilityAccount extends Component { ) - renderDisaggregateButtons = () => { + renderBillButtons = () => { const scrapeKey = this.state.documentKeys.scrape; const disaggregateKey = this.state.documentKeys.disaggregate; const scrapeUrl = this.state.documentURLs.scrape; @@ -222,28 +262,6 @@ class UtilityAccount extends Component { if (disaggregateUrl !== undefined && disaggregateUrl !== '') { disaggregateVisibility = 'visible'; } - let chartToggle = ( - ); - if (this.state.displayChart) { - chartDownload = ( - - ); - } - } let scrapeText = 'Download Scraped Bill'; let disaggregateText = 'Download Disaggregated Bill'; if (scrapeVisibility === 'hidden') { @@ -271,6 +289,9 @@ class UtilityAccount extends Component { {scrapeText}
+ {this.renderUploadButton('Bill')} +
+
{disaggregateText} +
+ {this.renderUploadButton('Disaggregated Bill')}
- {this.renderUploadButton()} -

+ + ); + } + + renderChartDownloadButton = () => { + let chartDownload = ( + ); + } + return chartDownload; + } + + renderBillViewButtons = () => { + let billDataToggle = ( + ); + } + let disaggregateDataToggle = ( + ); + chartToggle = ( + + ); + } + + return ( +

+
+ {billDataToggle} +
+
+
+ {disaggregateDataToggle} +
+
+
{chartToggle} - {chartDownload} -

+
); } + renderDisaggregateData = () => { + if (this.state.disaggregateData && this.state.displayDisaggregateData) { + return ( +
+
+
Disaggregation Data
+
+
+ + + + + + + + + + + + + {this.renderDisaggregateLines()} + +
Bill From DateBill To DateHeating UsageCooling UsageOther UsageTotal Usage
+
+
+
+
+ ); + } + return (
); + } + + renderDisaggregateLines = () => { + const lines = this.state.disaggregateData.map( + (val) => { + const totalUsage = ( + val.heating + val.cooling + val.other + ); + const trKey = `disaggregate${val.billFromDate}${val.billToDate}${this.state.account_id}`; + return ( + + {val.billFromDate} + {val.billToDate} + {val.heating.toFixed(2)} + {val.cooling.toFixed(2)} + {val.other.toFixed(2)} + {totalUsage.toFixed(2)} + + ); + } + ); + return lines; + } + renderBillData = () => { + if (this.state.billData && this.state.displayBillData) { + return ( +
+
+
Bill Data
+
+
+ + + + + + + + + + + + + + {this.renderBillLines()} + +
Bill From DateBill To DateUsageDelivery ChargeSupply ChargeTotal ChargeDifference
+
+
+
+
+ ); + } + return (
); + } + + renderBillLines = () => { + const lines = this.state.billData.map( + (val) => { + const diff = ( + val.delivery_charge + val.supply_charge + ) - val.total_charge_bill; + const trKey = `bill${val.bill_from_date}${val.bill_to_date}${this.state.account_id}`; + return ( + + {val.bill_from_date} + {val.bill_to_date} + {val.usage} + {val.delivery_charge} + {val.supply_charge} + {val.total_charge_bill} + {diff.toFixed(2)} + + ); + } + ); + return lines; + } + renderDisaggregateChart = () => { - if (this.state.disaggregateData && this.state.displayChart) { + if (this.state.disaggregateData && this.state.displayDisaggregateChart) { const data = this.state.disaggregateData.map(val => ({ name: val.billFromDate, heating: val.heating, @@ -315,7 +507,7 @@ class UtilityAccount extends Component { ); } - return (
); + return (
); } renderNatGrid = () => { @@ -402,11 +594,27 @@ class UtilityAccount extends Component {
{this.state.disabled ? 'Account Details' : ''}
- {this.state.disabled && this.renderDisaggregateButtons()} + {this.state.disabled && this.renderBillButtons()} +
+
+
+
{this.state.disabled ? 'View Data' : ''}
+
+ {this.state.disabled && this.renderBillViewButtons()} +
+
+
+ {this.renderBillData()} + {this.renderDisaggregateData()} +
+
+
{this.state.displayDisaggregateChart ? 'Disaggregation Chart' : ''}
+ {this.renderChartDownloadButton()} +
+ {this.renderDisaggregateChart()}
- {this.renderDisaggregateChart()}
); @@ -423,15 +631,23 @@ UtilityAccount.propTypes = { password: PropTypes.string, }), account_id: PropTypes.number, + billData: PropTypes.arrayOf( + PropTypes.shape({ + bill_from_date: PropTypes.string, + bill_to_date: PropTypes.string, + usage: PropTypes.number, + delivery_charge: PropTypes.number, + supply_charge: PropTypes.number, + total_charge_bill: PropTypes.number, + }) + ), disaggregateData: PropTypes.arrayOf( PropTypes.shape({ billFromDate: PropTypes.string, billToDate: PropTypes.string, - daysInBill: PropTypes.number, - usage: PropTypes.number, - heatingUsage: PropTypes.number, - coolingUsage: PropTypes.number, - otherUsage: PropTypes.number, + heating: PropTypes.number, + cooling: PropTypes.number, + other: PropTypes.number, }) ), documentKeys: PropTypes.shape({ @@ -445,8 +661,8 @@ UtilityAccount.propTypes = { disabled: PropTypes.bool, createAccount: PropTypes.func, deleteAccount: PropTypes.func, - updateUtilityBill: PropTypes.func, - updateDisaggregateBill: PropTypes.func, + fetchUtilityBill: PropTypes.func, + updateBill: PropTypes.func, }; UtilityAccount.defaultProps = { @@ -460,6 +676,7 @@ UtilityAccount.defaultProps = { }, account_id: null, disaggregateData: [], + billData: [], documentKeys: {}, documentURLs: {}, disabled: false, diff --git a/src/utils/restServices.js b/src/utils/restServices.js index 0a2ae8dec85a0583ef1db935e17b37dc3ad122a6..99f17c20d3c4c1d47399a0b7925c3f956c2bc012 100644 --- a/src/utils/restServices.js +++ b/src/utils/restServices.js @@ -14,6 +14,6 @@ export const buildingsURL = `${buildingService}/building/`; export const turkURL = `${buildingService}/turkhit/`; export const documentURL = `${documentService}/document/`; export const accountURL = `${utilityService}/account/`; -export const billsURL = `${utilityService}/bills/`; +export const scrapeURL = `${utilityService}/scrape/`; export const projectURL = `${projectService}/project/`; export const projectDocumentURL = `${projectService}/project/document/`;