From bf284dc591b4fac0444c5490a1e30b231088d964 Mon Sep 17 00:00:00 2001 From: Aaron Lindsay Date: Wed, 31 May 2017 21:04:01 -0400 Subject: [PATCH] Add OFX fields to backend and UI --- accounts.go | 14 +++ js/components/AccountsTab.js | 196 ++++++++++++++++++++++++++++++++++- js/models.js | 49 +++++++++ static/css/stylesheet.css | 8 ++ 4 files changed, 264 insertions(+), 3 deletions(-) diff --git a/accounts.go b/accounts.go index 847e291..c4e9341 100644 --- a/accounts.go +++ b/accounts.go @@ -81,6 +81,20 @@ type Account struct { // allowing a client to ensure they have a consistent version when paging // through transactions. AccountVersion int64 `json:"Version"` + + // Optional fields specifying how to fetch transactions from a bank via OFX + OFXURL string + OFXORG string + OFXFID string + OFXUser string + OFXBankID string // OFX BankID (BrokerID if AcctType == Investment) + OFXAcctID string + OFXAcctType string // ofxgo.acctType + OFXClientUID string + OFXAppID string + OFXAppVer string + OFXVersion string + OFXNoIndent bool } type AccountList struct { diff --git a/js/components/AccountsTab.js b/js/components/AccountsTab.js index 89f819b..d5544be 100644 --- a/js/components/AccountsTab.js +++ b/js/components/AccountsTab.js @@ -18,12 +18,16 @@ var ListGroupItem = ReactBootstrap.ListGroupItem; var Alert = ReactBootstrap.Alert; var Modal = ReactBootstrap.Modal; var Collapse = ReactBootstrap.Collapse; +var Tabs = ReactBootstrap.Tabs; +var Tab = ReactBootstrap.Tab; +var Panel = ReactBootstrap.Panel; var Combobox = require('react-widgets').Combobox; var models = require('../models'); var Security = models.Security; var Account = models.Account; +var AccountType = models.AccountType; var AccountTypeList = models.AccountTypeList; var AccountCombobox = require('./AccountCombobox'); @@ -36,7 +40,19 @@ const AddEditAccountModal = React.createClass({ security: 1, parentaccountid: -1, type: 1, - name: "" + name: "", + ofxurl: "", + ofxorg: "", + ofxfid: "", + ofxuser: "", + ofxbankid: "", + ofxacctid: "", + ofxaccttype: "CHECKING", + ofxclientuid: "", + ofxappid: "", + ofxappver: "", + ofxversion: "", + ofxnoindent: false, }; if (this.props.editAccount != null) { s.accountid = this.props.editAccount.AccountId; @@ -44,6 +60,18 @@ const AddEditAccountModal = React.createClass({ s.security = this.props.editAccount.SecurityId; s.parentaccountid = this.props.editAccount.ParentAccountId; s.type = this.props.editAccount.Type; + s.ofxurl = this.props.editAccount.OFXURL; + s.ofxorg = this.props.editAccount.OFXORG; + s.ofxfid = this.props.editAccount.OFXFID; + s.ofxuser = this.props.editAccount.OFXUser; + s.ofxbankid = this.props.editAccount.OFXBankID; + s.ofxacctid = this.props.editAccount.OFXAcctID; + s.ofxaccttype = this.props.editAccount.OFXAcctType; + s.ofxclientuid = this.props.editAccount.OFXClientUID; + s.ofxappid = this.props.editAccount.OFXAppID; + s.ofxappver = this.props.editAccount.OFXAppVer; + s.ofxversion = this.props.editAccount.OFXVersion; + s.ofxnoindent = this.props.editAccount.OFXNoIndent; } else if (this.props.initialParentAccount != null) { s.security = this.props.initialParentAccount.SecurityId; s.parentaccountid = this.props.initialParentAccount.AccountId; @@ -58,8 +86,23 @@ const AddEditAccountModal = React.createClass({ handleChange: function() { this.setState({ name: ReactDOM.findDOMNode(this.refs.name).value, + ofxurl: ReactDOM.findDOMNode(this.refs.ofxurl).value, + ofxorg: ReactDOM.findDOMNode(this.refs.ofxorg).value, + ofxfid: ReactDOM.findDOMNode(this.refs.ofxfid).value, + ofxuser: ReactDOM.findDOMNode(this.refs.ofxuser).value, + ofxbankid: ReactDOM.findDOMNode(this.refs.ofxbankid).value, + ofxacctid: ReactDOM.findDOMNode(this.refs.ofxacctid).value, + ofxaccttype: ReactDOM.findDOMNode(this.refs.ofxaccttype).value, + ofxclientuid: ReactDOM.findDOMNode(this.refs.ofxclientuid).value, + ofxappid: ReactDOM.findDOMNode(this.refs.ofxappid).value, + ofxappver: ReactDOM.findDOMNode(this.refs.ofxappver).value, + ofxversion: ReactDOM.findDOMNode(this.refs.ofxversion).value, }); }, + + handleNoIndentClick: function() { + this.setState({ofxnoindent: !this.state.ofxnoindent}); + }, handleSecurityChange: function(security) { if (security.hasOwnProperty('SecurityId')) this.setState({ @@ -85,6 +128,19 @@ const AddEditAccountModal = React.createClass({ a.SecurityId = this.state.security; a.Type = this.state.type; + a.OFXURL = this.state.ofxurl; + a.OFXORG = this.state.ofxorg; + a.OFXFID = this.state.ofxfid; + a.OFXUser = this.state.ofxuser; + a.OFXBankID = this.state.ofxbankid; + a.OFXAcctID = this.state.ofxacctid; + a.OFXAcctType = this.state.ofxaccttype; + a.OFXClientUID = this.state.ofxclientuid; + a.OFXAppID = this.state.ofxappid; + a.OFXAppVer = this.state.ofxappver; + a.OFXVersion = this.state.ofxversion; + a.OFXNoIndent = this.state.ofxNoIndent; + if (this.props.onSubmit != null) this.props.onSubmit(a); }, @@ -97,13 +153,39 @@ const AddEditAccountModal = React.createClass({ var headerText = (this.props.editAccount != null) ? "Edit" : "Create New"; var buttonText = (this.props.editAccount != null) ? "Save Changes" : "Create Account"; var rootName = (this.props.editAccount != null) ? "Top-level Account" : "New Top-level Account"; + var ofxBankIdName = "Broker ID"; + var ofxAcctType = []; + if (this.state.type != AccountType.Investment) { + ofxBankIdName = "Bank ID"; + ofxAcctType = ( + + Account Type + + + + + + + + + + + ); + } return ( {headerText} Account -
+ + + Name @@ -151,7 +233,115 @@ const AddEditAccountModal = React.createClass({ ref="type" /> - + + + +
+ + OFX URL + + + + + + ORG + + + + + + FID + + + + + + Username + + + + + + {ofxBankIdName} + + + + + + Account ID + + + + + {ofxAcctType} + + + Client UID + + + + + + App ID + + + + + + App Version + + + + + + OFX Version + + + + + + + + Don't indent OFX request files + + + + +
+
+
diff --git a/js/models.js b/js/models.js index 8487dd3..62c8a64 100644 --- a/js/models.js +++ b/js/models.js @@ -161,6 +161,19 @@ function Account() { this.ParentAccountId = -1; this.Type = -1; this.Name = ""; + + this.OFXURL = ""; + this.OFXORG = ""; + this.OFXFID = ""; + this.OFXUser = ""; + this.OFXBankID = ""; + this.OFXAcctID = ""; + this.OFXAcctType = ""; + this.OFXClientUID = ""; + this.OFXAppID = ""; + this.OFXAppVer = ""; + this.OFXVersion = ""; + this.OFXNoIndent = false } Account.prototype.toJSON = function() { @@ -171,6 +184,18 @@ Account.prototype.toJSON = function() { json_obj.ParentAccountId = this.ParentAccountId; json_obj.Type = this.Type; json_obj.Name = this.Name; + json_obj.OFXURL = this.OFXURL; + json_obj.OFXORG = this.OFXORG; + json_obj.OFXFID = this.OFXFID; + json_obj.OFXUser = this.OFXUser; + json_obj.OFXBankID = this.OFXBankID; + json_obj.OFXAcctID = this.OFXAcctID; + json_obj.OFXAcctType = this.OFXAcctType; + json_obj.OFXClientUID = this.OFXClientUID; + json_obj.OFXAppID = this.OFXAppID; + json_obj.OFXAppVer = this.OFXAppVer; + json_obj.OFXVersion = this.OFXVersion; + json_obj.OFXNoIndent = this.OFXNoIndent; return JSON.stringify(json_obj); } @@ -189,6 +214,30 @@ Account.prototype.fromJSON = function(json_input) { this.Type = json_obj.Type; if (json_obj.hasOwnProperty("Name")) this.Name = json_obj.Name; + if (json_obj.hasOwnProperty("OFXURL")) + this.OFXURL = json_obj.OFXURL; + if (json_obj.hasOwnProperty("OFXORG")) + this.OFXORG = json_obj.OFXORG; + if (json_obj.hasOwnProperty("OFXFID")) + this.OFXFID = json_obj.OFXFID; + if (json_obj.hasOwnProperty("OFXUser")) + this.OFXUser = json_obj.OFXUser; + if (json_obj.hasOwnProperty("OFXBankID")) + this.OFXBankID = json_obj.OFXBankID; + if (json_obj.hasOwnProperty("OFXAcctID")) + this.OFXAcctID = json_obj.OFXAcctID; + if (json_obj.hasOwnProperty("OFXAcctType")) + this.OFXAcctType = json_obj.OFXAcctType; + if (json_obj.hasOwnProperty("OFXClientUID")) + this.OFXClientUID = json_obj.OFXClientUID; + if (json_obj.hasOwnProperty("OFXAppID")) + this.OFXAppID = json_obj.OFXAppID; + if (json_obj.hasOwnProperty("OFXAppVer")) + this.OFXAppVer = json_obj.OFXAppVer; + if (json_obj.hasOwnProperty("OFXVersion")) + this.OFXVersion = json_obj.OFXVersion; + if (json_obj.hasOwnProperty("OFXNoIndent")) + this.OFXNoIndent = json_obj.OFXNoIndent; } Account.prototype.isAccount = function() { diff --git a/static/css/stylesheet.css b/static/css/stylesheet.css index 9cf2da4..e4f7a30 100644 --- a/static/css/stylesheet.css +++ b/static/css/stylesheet.css @@ -33,6 +33,14 @@ div#content { flex: auto; } +/* Tabs */ +.nav-tabs { + margin-bottom: 15px; +} +#mainNavigationTabs .nav-tabs { + margin-bottom: 0px; +} + /* Style the account tree */ div.accounttree-root-nochildren { position: relative;