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
|
||||
|
||||
var Alert = ReactBootstrap.Alert;
|
||||
var Modal = ReactBootstrap.Modal;
|
||||
var Pagination = ReactBootstrap.Pagination;
|
||||
|
||||
@ -127,12 +128,16 @@ const AmountInput = React.createClass({
|
||||
var symbol = "?";
|
||||
if (this.props.security)
|
||||
symbol = this.props.security.Symbol;
|
||||
var bsStyle = "";
|
||||
if (this.props.bsStyle)
|
||||
bsStyle = this.props.bsStyle;
|
||||
|
||||
return (
|
||||
<Input type="text"
|
||||
value={this.state.Amount}
|
||||
onChange={this.onChange}
|
||||
addonBefore={symbol}
|
||||
bsStyle={bsStyle}
|
||||
ref="amount"/>
|
||||
);
|
||||
}
|
||||
@ -142,7 +147,10 @@ const AddEditTransactionModal = React.createClass({
|
||||
_getInitialState: function(props) {
|
||||
// Ensure we can edit this without screwing up other copies of it
|
||||
var t = props.transaction.deepCopy();
|
||||
return {transaction: t};
|
||||
return {
|
||||
errorAlert: [],
|
||||
transaction: t
|
||||
};
|
||||
},
|
||||
getInitialState: function() {
|
||||
return this._getInitialState(this.props);
|
||||
@ -232,6 +240,24 @@ const AddEditTransactionModal = React.createClass({
|
||||
});
|
||||
},
|
||||
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)
|
||||
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 = [];
|
||||
for (var i = 0; i < this.state.transaction.Splits.length; i++) {
|
||||
var self = this;
|
||||
var s = this.state.transaction.Splits[i];
|
||||
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];
|
||||
if (security.SecurityId in imbalancedSecurityMap)
|
||||
amountValidation = "error";
|
||||
} else {
|
||||
accountValidation = "has-error";
|
||||
}
|
||||
|
||||
// Define all closures for calling split-updating functions
|
||||
var deleteSplitFn = (function() {
|
||||
@ -307,12 +345,14 @@ const AddEditTransactionModal = React.createClass({
|
||||
value={s.AccountId}
|
||||
includeRoot={false}
|
||||
onSelect={updateAccountFn}
|
||||
ref={"account-"+i} /></Col>
|
||||
ref={"account-"+i}
|
||||
className={accountValidation}/></Col>
|
||||
<Col xs={2}><AmountInput type="text"
|
||||
value={s.Amount}
|
||||
security={security}
|
||||
onChange={updateAmountFn}
|
||||
ref={"amount-"+i} /></Col>
|
||||
ref={"amount-"+i}
|
||||
bsStyle={amountValidation}/></Col>
|
||||
{deleteSplitButton}
|
||||
</Row>
|
||||
));
|
||||
@ -367,6 +407,7 @@ const AddEditTransactionModal = React.createClass({
|
||||
bsStyle="success">
|
||||
<Glyphicon glyph='plus-sign' /></Button></Col>
|
||||
</Row>
|
||||
<Row>{this.state.errorAlert}</Row>
|
||||
</Grid>
|
||||
</form>
|
||||
</Modal.Body>
|
||||
|
@ -31,6 +31,9 @@ const AccountCombobox = React.createClass({
|
||||
},
|
||||
render: function() {
|
||||
var accounts = getAccountDisplayList(this.props.accounts, this.props.includeRoot, this.props.rootName);
|
||||
var className = "";
|
||||
if (this.props.className)
|
||||
className = this.props.className;
|
||||
return (
|
||||
<Combobox
|
||||
data={accounts}
|
||||
@ -38,7 +41,8 @@ const AccountCombobox = React.createClass({
|
||||
textField='Name'
|
||||
value={this.props.value}
|
||||
onSelect={this.handleAccountChange}
|
||||
ref="account" />
|
||||
ref="account"
|
||||
className={className} />
|
||||
);
|
||||
}
|
||||
});
|
||||
|
@ -323,6 +323,33 @@ Transaction.prototype.deepCopy = function() {
|
||||
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() {
|
||||
this.ErrorId = -1;
|
||||
this.ErrorString = "";
|
||||
|
@ -115,3 +115,22 @@ div.accounttree-root div {
|
||||
.skinny-pagination {
|
||||
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