(function () { 'use strict'; function item(it) { if (it.credit && it.debit) { throw new Error("A journal item can't have both credit and debit, got " + JSON.stringify(it)); } return React.DOM.tr( {key: it.label.toLowerCase().split(' ').concat( ['debit', it.debit, 'credit', it.credit] ).join('-') }, React.DOM.td(null, (it.credit ? '\u2001' : '') + it.label), React.DOM.td(null, it.debit), React.DOM.td(null, it.credit) ); } function spacer(key) { return React.DOM.tr({key: 'spacer-' + key}, React.DOM.td({colSpan: 3}, "\u00A0")); } var ClotureTable = React.createClass({ getInitialState: function () { return { revenues: { cash: 800, receivable: 200, }, expenses: { cash: 100, payable: 500, }, // don't ignore/break invalid values dividends: "0.5", }; }, income: function () { return ( (this.state.revenues.cash + this.state.revenues.receivable) - (this.state.expenses.cash + this.state.expenses.payable) ); }, render: function () { return React.DOM.div( null, this.controls(), React.DOM.table( {className: 'table'}, this.makeHeader(), React.DOM.tbody( null, this.revenues(this.state.revenues), spacer('table-1'), this.expenses(this.state.expenses), spacer('table-2'), this.closure({ dividends: this.state.dividends, income: this.income(), }) ) ) ); }, makeHeader: function () { return React.DOM.thead( null, React.DOM.tr( null, React.DOM.th(), React.DOM.th(null, "Debit"), React.DOM.th(null, "Credit") ) ); }, controls: function () { var _this = this; return [ React.DOM.fieldset( {key: 'income'}, React.DOM.legend(null, "Income"), React.DOM.label( null, "Cash ", React.DOM.input({ type: 'number', step: 1, value: this.state.revenues.cash, onChange: function (e) { var val = e.target.value; _this.setState({ revenues: { cash: val ? parseInt(val, 10) : 0, receivable: _this.state.revenues.receivable } }); } }) ), ' ', React.DOM.label( null, " Accounts Receivable ", React.DOM.input({ type: 'number', step: 1, value: this.state.revenues.receivable, onChange: function (e) { var val = e.target.value; _this.setState({ revenues: { cash: _this.state.revenues.cash, receivable: val ? parseInt(val, 10) : 0, } }) } }) ) ), React.DOM.fieldset( {key: 'expenses'}, React.DOM.legend(null, "Expenses"), React.DOM.label( null, "Cash ", React.DOM.input({ type: 'number', step: 1, value: this.state.expenses.cash, onChange: function (e) { var val = e.target.value; _this.setState({ expenses: { cash: val ? parseInt(val, 10): 0, payable: _this.state.expenses.payable } }) } }) ), ' ', React.DOM.label( null, " Accounts Payable ", React.DOM.input({ type: 'number', step: 1, value: this.state.expenses.payable, onChange: function (e) { var val = e.target.value; _this.setState({ expenses: { cash: _this.state.expenses.cash, payable: val ? parseInt(val, 10) : 0 } }) } }) ) ), React.DOM.fieldset( {key: 'dividends'}, React.DOM.legend(null, "Dividends"), React.DOM.label( null, "Ratio (from retained earnings) ", React.DOM.input({ type: 'range', min: 0, max: 1, step: 0.01, value: this.state.dividends, style: { display: 'inline-block' }, onChange: function (e) { _this.setState({dividends: e.target.value}); } }) ) ) ]; }, // components must return a single root which isn't practical here closure: function (props) { var result, income = Math.abs(props.income), dividends = 0; if (props.income > 0) { // credit retained earnings from income, then credit dividends // from retained var dividends = parseInt(income * Math.max(0, Math.min(1, parseFloat(props.dividends)))); result = [ item({label: "Income Summary", debit: income}), item({label: "Retained Earnings", credit: income}), ]; } else { // debit retained earnings, no dividends result = [ item({label: "Retained Earnings", debit: income}), item({label: "Income Summary", credit: income}), ]; } if (dividends) { result = result.concat([ spacer('closure'), item({label: "Retained Earnings", debit: dividends}), item({label: "Dividends Payable", credit: dividends}) ]); } return result; }, revenues: function (props) { var total = props.cash + props.receivable; return [ item({label: "Cash", debit: props.cash}), item({label: "Accounts Receivable", debit: props.receivable}), item({label: "Revenue", credit: total}), React.DOM.tr({key: 'revenue-notes'}, React.DOM.td( {colSpan: 3}, "\u2001\u2001Consolidation of revenues")), spacer('revenues'), item({label: "Revenue", debit: total}), item({label: "Income Summary", credit: total}) ]; }, expenses: function (props) { var total = props.cash + props.payable; return [ item({label: "Expenses", debit: total}), item({label: "Cash", credit: props.cash}), item({label: "Accounts Payable", credit: props.payable}), React.DOM.tr( {key: 'expenses-note'}, React.DOM.td( {colSpan: 3}, "\u2001\u2001Consolidation of expenses" ) ), spacer('expenses'), item({label: "Income Summary", debit: total}), item({label: "Expenses", credit: total}) ]; } }); document.addEventListener('DOMContentLoaded', function () { React.render( React.createElement(ClotureTable), document.querySelector('.fiscal-year-closing')); }); })();