1
0
mirror of https://github.com/aclindsa/moneygo.git synced 2024-10-31 16:00:05 -04:00

Add OFX fields to backend and UI

This commit is contained in:
Aaron Lindsay 2017-05-31 21:04:01 -04:00
parent 618ce0554b
commit bf284dc591
4 changed files with 264 additions and 3 deletions

View File

@ -81,6 +81,20 @@ type Account struct {
// allowing a client to ensure they have a consistent version when paging // allowing a client to ensure they have a consistent version when paging
// through transactions. // through transactions.
AccountVersion int64 `json:"Version"` 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 { type AccountList struct {

View File

@ -18,12 +18,16 @@ var ListGroupItem = ReactBootstrap.ListGroupItem;
var Alert = ReactBootstrap.Alert; var Alert = ReactBootstrap.Alert;
var Modal = ReactBootstrap.Modal; var Modal = ReactBootstrap.Modal;
var Collapse = ReactBootstrap.Collapse; var Collapse = ReactBootstrap.Collapse;
var Tabs = ReactBootstrap.Tabs;
var Tab = ReactBootstrap.Tab;
var Panel = ReactBootstrap.Panel;
var Combobox = require('react-widgets').Combobox; var Combobox = require('react-widgets').Combobox;
var models = require('../models'); var models = require('../models');
var Security = models.Security; var Security = models.Security;
var Account = models.Account; var Account = models.Account;
var AccountType = models.AccountType;
var AccountTypeList = models.AccountTypeList; var AccountTypeList = models.AccountTypeList;
var AccountCombobox = require('./AccountCombobox'); var AccountCombobox = require('./AccountCombobox');
@ -36,7 +40,19 @@ const AddEditAccountModal = React.createClass({
security: 1, security: 1,
parentaccountid: -1, parentaccountid: -1,
type: 1, type: 1,
name: "" name: "",
ofxurl: "",
ofxorg: "",
ofxfid: "",
ofxuser: "",
ofxbankid: "",
ofxacctid: "",
ofxaccttype: "CHECKING",
ofxclientuid: "",
ofxappid: "",
ofxappver: "",
ofxversion: "",
ofxnoindent: false,
}; };
if (this.props.editAccount != null) { if (this.props.editAccount != null) {
s.accountid = this.props.editAccount.AccountId; s.accountid = this.props.editAccount.AccountId;
@ -44,6 +60,18 @@ const AddEditAccountModal = React.createClass({
s.security = this.props.editAccount.SecurityId; s.security = this.props.editAccount.SecurityId;
s.parentaccountid = this.props.editAccount.ParentAccountId; s.parentaccountid = this.props.editAccount.ParentAccountId;
s.type = this.props.editAccount.Type; 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) { } else if (this.props.initialParentAccount != null) {
s.security = this.props.initialParentAccount.SecurityId; s.security = this.props.initialParentAccount.SecurityId;
s.parentaccountid = this.props.initialParentAccount.AccountId; s.parentaccountid = this.props.initialParentAccount.AccountId;
@ -58,8 +86,23 @@ const AddEditAccountModal = React.createClass({
handleChange: function() { handleChange: function() {
this.setState({ this.setState({
name: ReactDOM.findDOMNode(this.refs.name).value, 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) { handleSecurityChange: function(security) {
if (security.hasOwnProperty('SecurityId')) if (security.hasOwnProperty('SecurityId'))
this.setState({ this.setState({
@ -85,6 +128,19 @@ const AddEditAccountModal = React.createClass({
a.SecurityId = this.state.security; a.SecurityId = this.state.security;
a.Type = this.state.type; 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) if (this.props.onSubmit != null)
this.props.onSubmit(a); this.props.onSubmit(a);
}, },
@ -97,13 +153,39 @@ const AddEditAccountModal = React.createClass({
var headerText = (this.props.editAccount != null) ? "Edit" : "Create New"; var headerText = (this.props.editAccount != null) ? "Edit" : "Create New";
var buttonText = (this.props.editAccount != null) ? "Save Changes" : "Create Account"; var buttonText = (this.props.editAccount != null) ? "Save Changes" : "Create Account";
var rootName = (this.props.editAccount != null) ? "Top-level Account" : "New Top-level 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 = (
<FormGroup>
<Col componentClass={ControlLabel} xs={2}>Account Type</Col>
<Col xs={10}>
<FormControl
componentClass="select"
placeholder="select"
value={this.state.ofxaccttype}
onChange={this.handleChange}
ref="ofxaccttype">
<option value="CHECKING">Checking</option>
<option value="SAVINGS">Savings</option>
<option value="MONEYMRKT">Money Market</option>
<option value="CREDITLINE">Credit Line</option>
<option value="CD">CD</option>
</FormControl>
</Col>
</FormGroup>
);
}
return ( return (
<Modal show={this.props.show} onHide={this.handleCancel}> <Modal show={this.props.show} onHide={this.handleCancel}>
<Modal.Header closeButton> <Modal.Header closeButton>
<Modal.Title>{headerText} Account</Modal.Title> <Modal.Title>{headerText} Account</Modal.Title>
</Modal.Header> </Modal.Header>
<Modal.Body> <Modal.Body>
<Form horizontal onSubmit={this.handleSubmit}> <Tabs defaultActiveKey={1} id="editAccountTabs">
<Tab eventKey={1} title="General">
<Form horizontal onSubmit={this.handleSubmit}>
<FormGroup> <FormGroup>
<Col componentClass={ControlLabel} xs={2}>Name</Col> <Col componentClass={ControlLabel} xs={2}>Name</Col>
<Col xs={10}> <Col xs={10}>
@ -151,7 +233,115 @@ const AddEditAccountModal = React.createClass({
ref="type" /> ref="type" />
</Col> </Col>
</FormGroup> </FormGroup>
</Form> </Form>
</Tab>
<Tab eventKey={2} title="Sync (OFX)">
<Form horizontal onSubmit={this.handleSubmit}>
<FormGroup>
<Col componentClass={ControlLabel} xs={2}>OFX URL</Col>
<Col xs={10}>
<FormControl type="text"
value={this.state.ofxurl}
onChange={this.handleChange}
ref="ofxurl"/>
</Col>
</FormGroup>
<FormGroup>
<Col componentClass={ControlLabel} xs={2}>ORG</Col>
<Col xs={10}>
<FormControl type="text"
value={this.state.ofxorg}
onChange={this.handleChange}
ref="ofxorg"/>
</Col>
</FormGroup>
<FormGroup>
<Col componentClass={ControlLabel} xs={2}>FID</Col>
<Col xs={10}>
<FormControl type="text"
value={this.state.ofxfid}
onChange={this.handleChange}
ref="ofxfid"/>
</Col>
</FormGroup>
<FormGroup>
<Col componentClass={ControlLabel} xs={2}>Username</Col>
<Col xs={10}>
<FormControl type="text"
value={this.state.ofxuser}
onChange={this.handleChange}
ref="ofxuser"/>
</Col>
</FormGroup>
<FormGroup>
<Col componentClass={ControlLabel} xs={2}>{ofxBankIdName}</Col>
<Col xs={10}>
<FormControl type="text"
value={this.state.ofxbankid}
onChange={this.handleChange}
ref="ofxbankid"/>
</Col>
</FormGroup>
<FormGroup>
<Col componentClass={ControlLabel} xs={2}>Account ID</Col>
<Col xs={10}>
<FormControl type="text"
value={this.state.ofxacctid}
onChange={this.handleChange}
ref="ofxacctid"/>
</Col>
</FormGroup>
{ofxAcctType}
<Panel collapsible header="Advanced Settings">
<FormGroup>
<Col componentClass={ControlLabel} xs={2}>Client UID</Col>
<Col xs={10}>
<FormControl type="text"
value={this.state.ofxclientuid}
onChange={this.handleChange}
ref="ofxclientuid"/>
</Col>
</FormGroup>
<FormGroup>
<Col componentClass={ControlLabel} xs={2}>App ID</Col>
<Col xs={10}>
<FormControl type="text"
value={this.state.ofxappid}
onChange={this.handleChange}
ref="ofxappid"/>
</Col>
</FormGroup>
<FormGroup>
<Col componentClass={ControlLabel} xs={2}>App Version</Col>
<Col xs={10}>
<FormControl type="text"
value={this.state.ofxappver}
onChange={this.handleChange}
ref="ofxappver"/>
</Col>
</FormGroup>
<FormGroup>
<Col componentClass={ControlLabel} xs={2}>OFX Version</Col>
<Col xs={10}>
<FormControl type="text"
value={this.state.ofxversion}
onChange={this.handleChange}
ref="ofxversion"/>
</Col>
</FormGroup>
<FormGroup>
<Col xsOffset={2} xs={10}>
<Checkbox
checked={this.state.ofxnoindent ? "checked" : ""}
onClick={this.handleNoIndentClick}>
Don't indent OFX request files
</Checkbox>
</Col>
</FormGroup>
</Panel>
</Form>
</Tab>
</Tabs>
</Modal.Body> </Modal.Body>
<Modal.Footer> <Modal.Footer>
<ButtonGroup className="pull-right"> <ButtonGroup className="pull-right">

View File

@ -161,6 +161,19 @@ function Account() {
this.ParentAccountId = -1; this.ParentAccountId = -1;
this.Type = -1; this.Type = -1;
this.Name = ""; 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() { Account.prototype.toJSON = function() {
@ -171,6 +184,18 @@ Account.prototype.toJSON = function() {
json_obj.ParentAccountId = this.ParentAccountId; json_obj.ParentAccountId = this.ParentAccountId;
json_obj.Type = this.Type; json_obj.Type = this.Type;
json_obj.Name = this.Name; 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); return JSON.stringify(json_obj);
} }
@ -189,6 +214,30 @@ Account.prototype.fromJSON = function(json_input) {
this.Type = json_obj.Type; this.Type = json_obj.Type;
if (json_obj.hasOwnProperty("Name")) if (json_obj.hasOwnProperty("Name"))
this.Name = json_obj.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() { Account.prototype.isAccount = function() {

View File

@ -33,6 +33,14 @@ div#content {
flex: auto; flex: auto;
} }
/* Tabs */
.nav-tabs {
margin-bottom: 15px;
}
#mainNavigationTabs .nav-tabs {
margin-bottom: 0px;
}
/* Style the account tree */ /* Style the account tree */
div.accounttree-root-nochildren { div.accounttree-root-nochildren {
position: relative; position: relative;