mirror of
https://github.com/aclindsa/moneygo.git
synced 2024-12-26 15:42:27 -05:00
Add validation of transactions in UI
This commit is contained in:
parent
6708edb00c
commit
fcea2d380b
@ -1,5 +1,6 @@
|
|||||||
// Import all the objects we want to use from ReactBootstrap
|
// Import all the objects we want to use from ReactBootstrap
|
||||||
|
|
||||||
|
var Alert = ReactBootstrap.Alert;
|
||||||
var Modal = ReactBootstrap.Modal;
|
var Modal = ReactBootstrap.Modal;
|
||||||
var Pagination = ReactBootstrap.Pagination;
|
var Pagination = ReactBootstrap.Pagination;
|
||||||
|
|
||||||
@ -127,12 +128,16 @@ const AmountInput = React.createClass({
|
|||||||
var symbol = "?";
|
var symbol = "?";
|
||||||
if (this.props.security)
|
if (this.props.security)
|
||||||
symbol = this.props.security.Symbol;
|
symbol = this.props.security.Symbol;
|
||||||
|
var bsStyle = "";
|
||||||
|
if (this.props.bsStyle)
|
||||||
|
bsStyle = this.props.bsStyle;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Input type="text"
|
<Input type="text"
|
||||||
value={this.state.Amount}
|
value={this.state.Amount}
|
||||||
onChange={this.onChange}
|
onChange={this.onChange}
|
||||||
addonBefore={symbol}
|
addonBefore={symbol}
|
||||||
|
bsStyle={bsStyle}
|
||||||
ref="amount"/>
|
ref="amount"/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -142,7 +147,10 @@ const AddEditTransactionModal = React.createClass({
|
|||||||
_getInitialState: function(props) {
|
_getInitialState: function(props) {
|
||||||
// Ensure we can edit this without screwing up other copies of it
|
// Ensure we can edit this without screwing up other copies of it
|
||||||
var t = props.transaction.deepCopy();
|
var t = props.transaction.deepCopy();
|
||||||
return {transaction: t};
|
return {
|
||||||
|
errorAlert: [],
|
||||||
|
transaction: t
|
||||||
|
};
|
||||||
},
|
},
|
||||||
getInitialState: function() {
|
getInitialState: function() {
|
||||||
return this._getInitialState(this.props);
|
return this._getInitialState(this.props);
|
||||||
@ -232,6 +240,24 @@ const AddEditTransactionModal = React.createClass({
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
handleSubmit: function() {
|
handleSubmit: function() {
|
||||||
|
var errorString = ""
|
||||||
|
var imbalancedSecurityList = this.state.transaction.imbalancedSplitSecurities(this.props.account_map);
|
||||||
|
if (imbalancedSecurityList.length > 0)
|
||||||
|
errorString = "Transaction must balance"
|
||||||
|
for (var i = 0; i < this.state.transaction.Splits.length; i++) {
|
||||||
|
var s = this.state.transaction.Splits[i];
|
||||||
|
if (!(s.AccountId in this.props.account_map)) {
|
||||||
|
errorString = "All accounts must be valid"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (errorString.length > 0) {
|
||||||
|
this.setState({
|
||||||
|
errorAlert: (<Alert className='saving-transaction-alert' bsStyle='danger'><strong>Error Saving Transaction:</strong> {errorString}</Alert>)
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (this.props.onSubmit != null)
|
if (this.props.onSubmit != null)
|
||||||
this.props.onSubmit(this.state.transaction);
|
this.props.onSubmit(this.state.transaction);
|
||||||
},
|
},
|
||||||
@ -250,13 +276,25 @@ const AddEditTransactionModal = React.createClass({
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var imbalancedSecurityList = this.state.transaction.imbalancedSplitSecurities(this.props.account_map);
|
||||||
|
var imbalancedSecurityMap = {};
|
||||||
|
for (i = 0; i < imbalancedSecurityList.length; i++)
|
||||||
|
imbalancedSecurityMap[imbalancedSecurityList[i]] = i;
|
||||||
|
|
||||||
splits = [];
|
splits = [];
|
||||||
for (var i = 0; i < this.state.transaction.Splits.length; i++) {
|
for (var i = 0; i < this.state.transaction.Splits.length; i++) {
|
||||||
var self = this;
|
var self = this;
|
||||||
var s = this.state.transaction.Splits[i];
|
var s = this.state.transaction.Splits[i];
|
||||||
var security = null;
|
var security = null;
|
||||||
if (this.props.account_map[s.AccountId])
|
var amountValidation = "";
|
||||||
|
var accountValidation = "";
|
||||||
|
if (s.AccountId in this.props.account_map) {
|
||||||
security = this.props.security_map[this.props.account_map[s.AccountId].SecurityId];
|
security = this.props.security_map[this.props.account_map[s.AccountId].SecurityId];
|
||||||
|
if (security.SecurityId in imbalancedSecurityMap)
|
||||||
|
amountValidation = "error";
|
||||||
|
} else {
|
||||||
|
accountValidation = "has-error";
|
||||||
|
}
|
||||||
|
|
||||||
// Define all closures for calling split-updating functions
|
// Define all closures for calling split-updating functions
|
||||||
var deleteSplitFn = (function() {
|
var deleteSplitFn = (function() {
|
||||||
@ -307,12 +345,14 @@ const AddEditTransactionModal = React.createClass({
|
|||||||
value={s.AccountId}
|
value={s.AccountId}
|
||||||
includeRoot={false}
|
includeRoot={false}
|
||||||
onSelect={updateAccountFn}
|
onSelect={updateAccountFn}
|
||||||
ref={"account-"+i} /></Col>
|
ref={"account-"+i}
|
||||||
|
className={accountValidation}/></Col>
|
||||||
<Col xs={2}><AmountInput type="text"
|
<Col xs={2}><AmountInput type="text"
|
||||||
value={s.Amount}
|
value={s.Amount}
|
||||||
security={security}
|
security={security}
|
||||||
onChange={updateAmountFn}
|
onChange={updateAmountFn}
|
||||||
ref={"amount-"+i} /></Col>
|
ref={"amount-"+i}
|
||||||
|
bsStyle={amountValidation}/></Col>
|
||||||
{deleteSplitButton}
|
{deleteSplitButton}
|
||||||
</Row>
|
</Row>
|
||||||
));
|
));
|
||||||
@ -367,6 +407,7 @@ const AddEditTransactionModal = React.createClass({
|
|||||||
bsStyle="success">
|
bsStyle="success">
|
||||||
<Glyphicon glyph='plus-sign' /></Button></Col>
|
<Glyphicon glyph='plus-sign' /></Button></Col>
|
||||||
</Row>
|
</Row>
|
||||||
|
<Row>{this.state.errorAlert}</Row>
|
||||||
</Grid>
|
</Grid>
|
||||||
</form>
|
</form>
|
||||||
</Modal.Body>
|
</Modal.Body>
|
||||||
|
@ -31,6 +31,9 @@ const AccountCombobox = React.createClass({
|
|||||||
},
|
},
|
||||||
render: function() {
|
render: function() {
|
||||||
var accounts = getAccountDisplayList(this.props.accounts, this.props.includeRoot, this.props.rootName);
|
var accounts = getAccountDisplayList(this.props.accounts, this.props.includeRoot, this.props.rootName);
|
||||||
|
var className = "";
|
||||||
|
if (this.props.className)
|
||||||
|
className = this.props.className;
|
||||||
return (
|
return (
|
||||||
<Combobox
|
<Combobox
|
||||||
data={accounts}
|
data={accounts}
|
||||||
@ -38,7 +41,8 @@ const AccountCombobox = React.createClass({
|
|||||||
textField='Name'
|
textField='Name'
|
||||||
value={this.props.value}
|
value={this.props.value}
|
||||||
onSelect={this.handleAccountChange}
|
onSelect={this.handleAccountChange}
|
||||||
ref="account" />
|
ref="account"
|
||||||
|
className={className} />
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -323,6 +323,33 @@ Transaction.prototype.deepCopy = function() {
|
|||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Transaction.prototype.imbalancedSplitSecurities = function(account_map) {
|
||||||
|
// Return a list of SecurityIDs for those securities that aren't balanced
|
||||||
|
// in this transaction's splits. If a split's AccountId is invalid, that
|
||||||
|
// split is ignored, so those must be checked elsewhere
|
||||||
|
var splitBalances = {};
|
||||||
|
const emptySplit = new Split();
|
||||||
|
for (var i = 0; i < this.Splits.length; i++) {
|
||||||
|
split = this.Splits[i];
|
||||||
|
if (split.AccountId == emptySplit.AccountId) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
var securityId = account_map[split.AccountId].SecurityId;
|
||||||
|
if (securityId in splitBalances) {
|
||||||
|
splitBalances[securityId] = split.Amount.plus(splitBalances[securityId]);
|
||||||
|
} else {
|
||||||
|
splitBalances[securityId] = split.Amount.plus(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var imbalancedIDs = [];
|
||||||
|
for (var id in splitBalances) {
|
||||||
|
if (!splitBalances[id].eq(0)) {
|
||||||
|
imbalancedIDs.push(id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return imbalancedIDs;
|
||||||
|
}
|
||||||
|
|
||||||
function Error() {
|
function Error() {
|
||||||
this.ErrorId = -1;
|
this.ErrorId = -1;
|
||||||
this.ErrorString = "";
|
this.ErrorString = "";
|
||||||
|
@ -115,3 +115,22 @@ div.accounttree-root div {
|
|||||||
.skinny-pagination {
|
.skinny-pagination {
|
||||||
margin: 0px;
|
margin: 0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Make Combobox support .has-error class */
|
||||||
|
.has-error.rw-widget {
|
||||||
|
border-color: #843534;
|
||||||
|
}
|
||||||
|
.has-error.rw-widget.rw-state-focus {
|
||||||
|
border-color: #843534;
|
||||||
|
box-shadow: 0px 1px 1px rgba(0, 0, 0, 0.075) inset, 0px 0px 6px #CE8483;
|
||||||
|
}
|
||||||
|
.has-error.rw-widget > .rw-select {
|
||||||
|
border-left: 1px solid #843534;
|
||||||
|
color: #A94442;
|
||||||
|
background-color: #F2DEDE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Fix Alert Spacing inside */
|
||||||
|
.alert.saving-transaction-alert {
|
||||||
|
margin: 20px 0 0 0;
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user