mirror of
https://github.com/odoo/documentation.git
synced 2026-03-26 13:59:55 +07:00
[ADD] Inventory: add stock valuation cheat sheet
An adaptation of the venerable business memento from 8.0 to the new inventory valuation mechanics of Odoo 19.0 by scavenging and cobbling together of the scripts `entries.js` and `coa-valuation.js`. The shared data is kept in a separate file. Additionally, we remove the old inventory valuation documentation. Task ID: 5107300 closes odoo/documentation#14906 Signed-off-by: Felicia Kuan (feku) <feku@odoo.com>
This commit is contained in:
committed by
“Dallas”
parent
c97a8e6bad
commit
912dde6d26
@@ -106,13 +106,6 @@ label:hover,
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
.values-table tr > * {
|
||||
text-align: right;
|
||||
}
|
||||
.values-table tr > :first-child {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
/* 3-column (thing, debit, credit) tables */
|
||||
/* 2nd and 3rd th & td of each row right-aligned and 1/4th width */
|
||||
.d-c-table tr > :nth-child(2),
|
||||
@@ -139,21 +132,7 @@ label:hover,
|
||||
background-color: #eee !important;
|
||||
color: #7A436B !important;
|
||||
}
|
||||
|
||||
.chart-of-accounts .highlight-op,
|
||||
.valuation-chart .highlight-op {
|
||||
background-color: #030035;
|
||||
border-bottom: 1px solid #000000 !important;
|
||||
}
|
||||
|
||||
.chart-of-accounts .highlight-op,
|
||||
.valuation-chart-continental .highlight-op {
|
||||
background-color: #030035;
|
||||
border-bottom: 1px solid #000000 !important;
|
||||
}
|
||||
|
||||
.chart-of-accounts .highlight-op,
|
||||
.valuation-chart-anglo-saxon .highlight-op {
|
||||
.chart-of-accounts .highlight-op {
|
||||
background-color: #030035;
|
||||
border-bottom: 1px solid #000000 !important;
|
||||
}
|
||||
@@ -217,17 +196,3 @@ blockquote.highlights, blockquote.highlights p{
|
||||
margin-bottom: 1rem;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
/*
|
||||
lists of alternatives
|
||||
*/
|
||||
.alternatives-controls label {
|
||||
display: block;
|
||||
}
|
||||
dl.alternatives > dt,
|
||||
dl.alternatives > dd {
|
||||
display: none;
|
||||
}
|
||||
dl.alternatives > dd {
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
128
static/css/valuation.css
Normal file
128
static/css/valuation.css
Normal file
@@ -0,0 +1,128 @@
|
||||
/* Used in valuation cheat_sheet.rst */
|
||||
|
||||
/* Prevent titles from wrapping upwards */
|
||||
h3 { clear: both !important; }
|
||||
|
||||
.full-width { width: 100% !important; }
|
||||
|
||||
.accounting-entries, .journal-entries, .values-table {
|
||||
border: 1px solid #d5d5d5;
|
||||
background-color: #f8f8f8;
|
||||
margin: 0px auto;
|
||||
}
|
||||
|
||||
/* Costing methods table - see misc.js */
|
||||
.alternatives-controls {
|
||||
padding-bottom: 24px;
|
||||
label {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
dl.alternatives > dt {
|
||||
display: none;
|
||||
}
|
||||
dl.alternatives > dd {
|
||||
display: none;
|
||||
margin-left: 0;
|
||||
}
|
||||
.values-table {
|
||||
text-align: right;
|
||||
tr > th:first-of-type {
|
||||
text-align: left;
|
||||
}
|
||||
}
|
||||
|
||||
/* Accounting methods table - see valuation-accounting.js */
|
||||
.accounting-entries {
|
||||
th, td {
|
||||
padding-top: 0px !important;
|
||||
padding-bottom: 0px !important;
|
||||
}
|
||||
thead th, tr > td {
|
||||
padding-left: 48px;
|
||||
}
|
||||
tbody th {
|
||||
font-weight: normal;
|
||||
}
|
||||
.parent-line { background-color: #fafafa; }
|
||||
.child-line { background-color: #f0f0f0; }
|
||||
}
|
||||
.entries-listing {
|
||||
padding: .5rem;
|
||||
}
|
||||
#accounting-entries-controls label,
|
||||
#journaling-entries-controls label {
|
||||
display: block;
|
||||
}
|
||||
|
||||
/* Highlighting of selected options - see misc.js */
|
||||
label:hover, .highlighter-list li:hover {
|
||||
background-color: hsl(0, 0%, 94%);
|
||||
cursor: pointer;
|
||||
}
|
||||
.related {
|
||||
background-color: hsl(317deg 16% 90%) !important;
|
||||
border: 1px solid #000000 !important;
|
||||
transition: .3s;
|
||||
}
|
||||
.secondary {
|
||||
background-color: hsl(180deg 67% 94%) !important;
|
||||
transition: .3s;
|
||||
}
|
||||
.highlight-op {
|
||||
background-color: hsl(317deg 16% 90%) !important;
|
||||
transition: .3s;
|
||||
}
|
||||
.highlighter-target {
|
||||
th {
|
||||
font-weight: 400;
|
||||
}
|
||||
.related {
|
||||
/*background-color: #eee !important;*/
|
||||
color: #7A436B !important;
|
||||
}
|
||||
.secondary {
|
||||
background-color: #eee !important;
|
||||
color: #7A436B !important;
|
||||
}
|
||||
}
|
||||
|
||||
/* Static tables */
|
||||
.feature-table, .config-table {
|
||||
table {
|
||||
/* width: unset; */
|
||||
margin: auto;
|
||||
white-space: nowrap;
|
||||
text-align: center;
|
||||
}
|
||||
tbody td:first-child {
|
||||
text-align: left;
|
||||
}
|
||||
}
|
||||
.config-table {
|
||||
font-size: 90%;
|
||||
}
|
||||
|
||||
.accounting-app-paragraph:hover ~ .feature-table tr > td:first-child:has(+ td .good),
|
||||
.inventory-app-paragraph:hover ~ .feature-table tr > td:first-child:has(+ td + td .good)
|
||||
{ font-weight: bold; }
|
||||
|
||||
.feature-table {
|
||||
td { width: 32px; }
|
||||
td:has(.good) { background-color: #d9ead3 !important; }
|
||||
td:has(.meh) { background-color: #fce5cd !important; }
|
||||
td:has(.bad) { background-color: #f4cccc !important; }
|
||||
}
|
||||
.config-table {
|
||||
th, td {
|
||||
padding-top: 0px !important;
|
||||
padding-bottom: 0px !important;
|
||||
}
|
||||
td:has(.washed) { color: var(--bs-gray); }
|
||||
}
|
||||
|
||||
.yellow, td:has(.yellow), th:has(.yellow) { background-color: #fff2cc !important; }
|
||||
.green, td:has(.green), th:has(.green) { background-color: #d9ead3 !important; }
|
||||
.blue, td:has(.blue), th:has(.blue) { background-color: #cfe2f3 !important; }
|
||||
.darkblue, td:has(.darkblue), th:has(.darkblue) { background-color: #6d9eeb !important; }
|
||||
.purple, td:has(.purple), th:has(.purple) { background-color: #d9d2e9 !important; }
|
||||
@@ -1,6 +1,6 @@
|
||||
/* global Immutable, React */
|
||||
(function () {
|
||||
// NOTE: used by cheat_sheet.rst
|
||||
// NOTE: used by accounting cheat_sheet.rst
|
||||
'use strict';
|
||||
|
||||
function highlight(primary, secondary) {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/* global Immutable, React */
|
||||
/* global createAtom */
|
||||
(function () {
|
||||
// NOTE: used by cheat_sheet.rst
|
||||
// NOTE: used by accounting cheat_sheet.rst
|
||||
'use strict';
|
||||
|
||||
var data = createAtom();
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
/* global createAtom, findAncestor */
|
||||
(function () {
|
||||
'use strict';
|
||||
// NOTE: cheat_sheet.rst
|
||||
// NOTE: used by accounting cheat_sheet.rst
|
||||
|
||||
var data = createAtom();
|
||||
data.addWatch('chart', function (k, m, prev, next) {
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
});
|
||||
|
||||
function highlight() {
|
||||
// NOTE: used by double-entry.rst
|
||||
// NOTE: used by valuation cheat_sheet.rst
|
||||
$('.highlighter-list').each(function () {
|
||||
var $this = $(this),
|
||||
$target = $($this.data('target'));
|
||||
@@ -34,7 +34,7 @@
|
||||
* - automatically select first control on startup
|
||||
*/
|
||||
function alternatives() {
|
||||
// NOTE: used by double-entry.rst & valuation_methods pages
|
||||
// NOTE: used by valuation cheat_sheet.rst
|
||||
$('dl.alternatives').each(function (index) {
|
||||
var $list = $(this),
|
||||
$contents = $list.children('dd');
|
||||
@@ -51,7 +51,18 @@
|
||||
|
||||
label.appendChild(input);
|
||||
label.appendChild(document.createTextNode(' '));
|
||||
label.appendChild(document.createTextNode(this.textContent));
|
||||
|
||||
// Hack to bold the definition since we have to strip rST formatting
|
||||
const [headText, tailText] = this.textContent.split(':', 2);
|
||||
if (tailText) {
|
||||
const bold = document.createElement('b'),
|
||||
defined = document.createTextNode(`${headText}:`);
|
||||
bold.appendChild(defined);
|
||||
label.appendChild(bold);
|
||||
}
|
||||
|
||||
label.appendChild(document.createTextNode(tailText || headText));
|
||||
label.normalize();
|
||||
|
||||
return label;
|
||||
}))
|
||||
@@ -65,9 +76,10 @@
|
||||
})
|
||||
.find('input:first').click();
|
||||
});
|
||||
$('.alternatives-note').insertAfter($('.alternatives-controls'));
|
||||
}
|
||||
function checks_handling() {
|
||||
// NOTE: used by cheat_sheet.rst
|
||||
// NOTE: used by accounting cheat_sheet.rst
|
||||
var $section = $('.checks-handling');
|
||||
if (!$section.length) { return; }
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
(function () {
|
||||
// NOTE: cheat_sheet.rst
|
||||
// NOTE: used by accounting cheat_sheet.rst
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
var $rec = $('#reconciliation .reconciliation-example');
|
||||
if (!$rec.length) { return; }
|
||||
|
||||
262
static/js/valuation-accounting.js
Normal file
262
static/js/valuation-accounting.js
Normal file
@@ -0,0 +1,262 @@
|
||||
/* global Immutable, React */
|
||||
/* global createAtom */
|
||||
/* global VALUATION_{STANDARDS,METHODS,JOURNALS,ENTRIES,REVIEWS} */
|
||||
(function () {
|
||||
'use strict';
|
||||
// NOTE: used by valuation cheat_sheet.rst
|
||||
|
||||
const selectedMode = createAtom(['continental', 'periodic']);
|
||||
const selectedOps = createAtom();
|
||||
|
||||
function watch (next) {
|
||||
React.render(
|
||||
React.createElement(Controls, { p: next }),
|
||||
document.getElementById('accounting-entries-controls'));
|
||||
React.render(
|
||||
React.createElement(Chart, { p: next }),
|
||||
document.querySelector('.accounting-entries'));
|
||||
}
|
||||
|
||||
selectedOps.addWatch('chart', (k, m, prev, next) => watch(next));
|
||||
selectedMode.addWatch('chart', (k, m, prev, next) => watch(selectedOps.deref()));
|
||||
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
const chart = document.querySelector('.accounting-entries');
|
||||
if (!chart) { return; }
|
||||
|
||||
const controls = document.createElement('div');
|
||||
controls.setAttribute('id', 'accounting-entries-controls');
|
||||
chart.parentNode.insertBefore(controls, chart);
|
||||
|
||||
selectedOps.reset(Immutable.Map({
|
||||
// last-selected operation
|
||||
active: null,
|
||||
// set of all currently enabled operations
|
||||
operations: Immutable.OrderedSet()
|
||||
}));
|
||||
});
|
||||
|
||||
function toKey(s, postfix) {
|
||||
if (postfix) {
|
||||
s += ' ' + postfix;
|
||||
}
|
||||
return s.replace(/[^0-9a-z ]/gi, '').toLowerCase().split(/\s+/).join('-');
|
||||
}
|
||||
|
||||
const Controls = React.createClass({
|
||||
render: function () {
|
||||
const state = this.props.p;
|
||||
return React.DOM.div(
|
||||
null,
|
||||
React.DOM.b(null, "Choose a standard:"),
|
||||
VALUATION_STANDARDS.map(function (item, index) {
|
||||
return React.DOM.label(
|
||||
{ key: index },
|
||||
React.DOM.input({
|
||||
type: 'radio',
|
||||
checked: item.get('name') === selectedMode.deref()[0],
|
||||
onChange: function (e) {
|
||||
const newValue = item.get('name');
|
||||
selectedMode.reset([newValue, newValue === 'continental' ? 'periodic' : 'perpetual']);
|
||||
}
|
||||
}),
|
||||
' ',
|
||||
item.get('text')
|
||||
);
|
||||
}),
|
||||
React.DOM.br(),
|
||||
React.DOM.b(null, "Choose an accounting method:"),
|
||||
VALUATION_METHODS.map(function (item, index) {
|
||||
return React.DOM.label(
|
||||
{ key: index },
|
||||
React.DOM.input({
|
||||
type: 'radio',
|
||||
checked: item.get('name') === selectedMode.deref()[1],
|
||||
onChange: e => selectedMode.swap(vals => [vals[0], item.get('name')]),
|
||||
}),
|
||||
' ',
|
||||
item.get('text')
|
||||
);
|
||||
}),
|
||||
React.DOM.br(),
|
||||
React.DOM.b(null, "Activate operations to see the impact:"),
|
||||
VALUATION_ENTRIES.map(function (item, key) {
|
||||
return React.DOM.label(
|
||||
{
|
||||
key: key,
|
||||
style: { display: 'block' },
|
||||
className: (key === state.get('active') ? 'highlight-op' : void 0)
|
||||
},
|
||||
React.DOM.input({
|
||||
type: 'checkbox',
|
||||
checked: state.get('operations').contains(key),
|
||||
onChange: function (e) {
|
||||
if (e.target.checked) {
|
||||
selectedOps.swap(d => d.set('active', key)
|
||||
.update('operations', ops => ops.add(key)));
|
||||
} else {
|
||||
selectedOps.swap(d => d.set('active', null)
|
||||
.update('operations', ops => ops.remove(key)));
|
||||
}
|
||||
}
|
||||
}),
|
||||
' ',
|
||||
item.get('title')
|
||||
);
|
||||
}),
|
||||
React.DOM.br(),
|
||||
"Closing",
|
||||
VALUATION_REVIEWS.map(function (item, key) {
|
||||
// We bold the text if any of the operations in this review is
|
||||
// relevant to the currently selected operations.
|
||||
const boldable = item.getIn([...selectedMode.deref(), 'operations'])
|
||||
.some(function (op) {
|
||||
if (!op.has('entries') && !op.has('except'))
|
||||
return true;
|
||||
const opset = state.get('operations').toSet();
|
||||
if (opset.isSuperset(op.get('entries', []))
|
||||
&& opset.intersect(op.get('except', [])).isEmpty())
|
||||
return true;
|
||||
});
|
||||
return React.DOM.label(
|
||||
{
|
||||
key: key,
|
||||
style: { display: 'block' },
|
||||
className: (key === state.get('active') ? 'highlight-op' : void 0)
|
||||
},
|
||||
React.DOM.input({
|
||||
type: 'checkbox',
|
||||
checked: state.get('operations').contains(key),
|
||||
onChange: function (e) {
|
||||
if (e.target.checked) {
|
||||
selectedOps.swap(d => d.set('active', key)
|
||||
.update('operations', ops => ops.add(key)));
|
||||
} else {
|
||||
selectedOps.swap(d => d.set('active', null)
|
||||
.update('operations', ops => ops.remove(key)));
|
||||
}
|
||||
}
|
||||
}),
|
||||
' ',
|
||||
boldable ? React.DOM.b(null, item.get('title')) : item.get('title'),
|
||||
);
|
||||
}),
|
||||
React.DOM.br(),
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
const Chart = React.createClass({
|
||||
render: function () {
|
||||
// Only used for highlighting cells.
|
||||
const lastop = Immutable.Map(
|
||||
this.props.p.get('active')
|
||||
? (VALUATION_ENTRIES.concat(VALUATION_REVIEWS)
|
||||
.getIn([this.props.p.get('active'), ...selectedMode.deref(), 'operations'], Immutable.List()))
|
||||
.map(op => [VALUATION_JOURNALS.getIn([selectedMode.deref()[0], ...op.get('account'), 'code']),
|
||||
op.has('credit') ? 'credit' : 'debit'])
|
||||
: Immutable.Map());
|
||||
return React.DOM.div(
|
||||
null,
|
||||
React.DOM.table(
|
||||
{ className: 'table table-condensed' },
|
||||
React.DOM.thead(
|
||||
null,
|
||||
React.DOM.tr(
|
||||
null,
|
||||
React.DOM.th(),
|
||||
React.DOM.th({ className: 'text-right' }, "Debit"),
|
||||
React.DOM.th({ className: 'text-right' }, "Credit"),
|
||||
React.DOM.th({ className: 'text-right' }, "Balance"))
|
||||
),
|
||||
React.DOM.tbody(
|
||||
null,
|
||||
this.accounts().map(function (data) {
|
||||
// Don't highlight the cell if it's going to be empty.
|
||||
const highlight = lastop.get(data.get('code')),
|
||||
debit = format(data.get('debit')),
|
||||
credit = format(data.get('credit'));
|
||||
return React.DOM.tr(
|
||||
{
|
||||
key: data.get('code'),
|
||||
className: data.get('level') ? 'parent-line' : 'child-line',
|
||||
},
|
||||
React.DOM.th(
|
||||
null,
|
||||
data.get('level') ? '\u2001 ' : '',
|
||||
data.get('code') || '', ' ', data.get('title')
|
||||
),
|
||||
React.DOM.td(
|
||||
{ className: React.addons.classSet({
|
||||
'text-right': true,
|
||||
'highlight-op': debit ? highlight === 'debit' : void 0 }) },
|
||||
debit),
|
||||
React.DOM.td(
|
||||
{ className: React.addons.classSet({
|
||||
'text-right': true,
|
||||
'highlight-op': credit ? highlight === 'credit' : void 0 }) },
|
||||
credit),
|
||||
React.DOM.td(
|
||||
{ className: 'text-right' },
|
||||
((data.get('debit') || data.get('credit'))
|
||||
? format(data.get('debit') - data.get('credit'), 0)
|
||||
: ''),
|
||||
)
|
||||
);
|
||||
})
|
||||
)
|
||||
)
|
||||
);
|
||||
},
|
||||
accounts: function() {
|
||||
const currentOperations = this.props.p.get('operations');
|
||||
if (!currentOperations)
|
||||
return null;
|
||||
const totals = VALUATION_ENTRIES.concat(VALUATION_REVIEWS)
|
||||
.filter((val, key) => currentOperations.includes(key))
|
||||
.valueSeq()
|
||||
.flatMap(entry => entry.getIn([...selectedMode.deref(), 'operations']))
|
||||
.reduce(function (acc, op) {
|
||||
// `entries' and `except' fields are explained in valuation-data.js (quod vide)
|
||||
if (op.has('entries') || op.has('except')) {
|
||||
const opset = currentOperations.toSet();
|
||||
if (!(opset.isSuperset(op.get('entries', []))
|
||||
&& opset.intersect(op.get('except', [])).isEmpty())) {
|
||||
return acc;
|
||||
}
|
||||
}
|
||||
const code = VALUATION_JOURNALS.getIn([selectedMode.deref()[0], ...op.get('account'), 'code']);
|
||||
return acc
|
||||
.updateIn([code, 'debit'],
|
||||
d => (d || 0) + op.get('debit', 0))
|
||||
.updateIn([code, 'credit'],
|
||||
c => (c || 0) + op.get('credit', 0));
|
||||
}, Immutable.Map());
|
||||
return accounts.get(selectedMode.deref()[0]).map(account =>
|
||||
account.merge(account.get('accounts')
|
||||
.map(code => totals.get(code, NULL))
|
||||
.reduce((acc, it) => acc.mergeWith((a, b) => a + b, it, NULL))));
|
||||
}
|
||||
});
|
||||
|
||||
const NULL = Immutable.Map({ debit: 0, credit: 0 });
|
||||
const accounts = VALUATION_JOURNALS.map(method => method.toList().flatMap(function (cat) {
|
||||
return Immutable.Seq.of(cat.set('level', 0)).concat(cat.filter(function (v, k) {
|
||||
return k.toUpperCase() === k;
|
||||
}).toIndexedSeq().map(function (acc) { return acc.set('level', 1) }));
|
||||
}).map(function (account) { // add accounts: Seq<AccountCode> to each account
|
||||
return account.set(
|
||||
'accounts',
|
||||
Immutable.Seq.of(account.get('code')).concat(
|
||||
account.toIndexedSeq().map(function (val) {
|
||||
return Immutable.Map.isMap(val) && val.get('code');
|
||||
}).filter(function (val) { return !!val; })
|
||||
)
|
||||
);
|
||||
}));
|
||||
function format(val, def) {
|
||||
if (!val) { return def === undefined ? '' : def; }
|
||||
if (val % 1 === 0) { return val; }
|
||||
return val.toFixed(2);
|
||||
}
|
||||
})();
|
||||
1343
static/js/valuation-data.js
Normal file
1343
static/js/valuation-data.js
Normal file
File diff suppressed because it is too large
Load Diff
176
static/js/valuation-journal.js
Normal file
176
static/js/valuation-journal.js
Normal file
@@ -0,0 +1,176 @@
|
||||
/* global Immutable, React */
|
||||
/* global createAtom, findAncestor */
|
||||
/* global VALUATION_{STANDARDS,METHODS,JOURNALS,ENTRIES,REVIEWS} */
|
||||
(function () {
|
||||
'use strict';
|
||||
// NOTE: used by valuation cheat_sheet.rst
|
||||
|
||||
const selectedMode = createAtom()
|
||||
const selectedOp = createAtom();
|
||||
|
||||
const entries = VALUATION_ENTRIES.concat(VALUATION_REVIEWS);
|
||||
|
||||
function watch (next) {
|
||||
React.render(
|
||||
React.createElement(Controls, { entryKey: next }),
|
||||
document.getElementById('journaling-entries-controls'));
|
||||
React.render(
|
||||
React.createElement(FormatEntry, { entryKey: next }),
|
||||
document.querySelector('.journal-entries'));
|
||||
}
|
||||
|
||||
selectedOp.addWatch('chart', (k, m, prev, next) => watch([next, ...selectedMode.deref()]));
|
||||
selectedMode.addWatch('chart', (k, m, prev, next) => watch([selectedOp.deref(), ...next]));
|
||||
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
const entriesSection = findAncestor(document.querySelector('.journal-entries'), 'section');
|
||||
if (!entriesSection) { return; }
|
||||
|
||||
const controls = document.createElement('div');
|
||||
controls.setAttribute('id', 'journaling-entries-controls');
|
||||
entriesSection.insertBefore(controls, entriesSection.lastElementChild);
|
||||
|
||||
selectedMode.reset(['continental', 'periodic']);
|
||||
selectedOp.reset('initial_inventory');
|
||||
});
|
||||
|
||||
const Controls = React.createClass({
|
||||
render: function () {
|
||||
const key = this.props.entryKey;
|
||||
return React.DOM.div(
|
||||
null,
|
||||
React.DOM.b(null, "Choose a standard:"),
|
||||
VALUATION_STANDARDS.map(function (item, index) {
|
||||
return React.DOM.label(
|
||||
{ key: index },
|
||||
React.DOM.input({
|
||||
type: 'radio',
|
||||
checked: item.get('name') === key[1],
|
||||
onChange: function (e) {
|
||||
const newValue = item.get('name');
|
||||
selectedMode.reset([newValue, newValue === 'continental' ? 'periodic' : 'perpetual']);
|
||||
}
|
||||
}),
|
||||
' ',
|
||||
item.get('text')
|
||||
);
|
||||
}),
|
||||
React.DOM.br(),
|
||||
React.DOM.b(null, "Choose an accounting method:"),
|
||||
VALUATION_METHODS.map(function (item, index) {
|
||||
return React.DOM.label(
|
||||
{ key: index },
|
||||
React.DOM.input({
|
||||
type: 'radio',
|
||||
checked: item.get('name') === key[2],
|
||||
onChange: e => selectedMode.swap(vals => [vals[0], item.get('name')]),
|
||||
}),
|
||||
' ',
|
||||
item.get('text')
|
||||
);
|
||||
}),
|
||||
React.DOM.br(),
|
||||
React.DOM.b(null, "Activate operations to see the impact:"),
|
||||
VALUATION_ENTRIES.map(function (item, index) {
|
||||
return React.DOM.label(
|
||||
{ key: index },
|
||||
React.DOM.input({
|
||||
type: 'radio',
|
||||
checked: index === key[0],
|
||||
onChange: e => selectedOp.reset(index),
|
||||
}),
|
||||
' ',
|
||||
item.get('title')
|
||||
);
|
||||
}),
|
||||
React.DOM.br(),
|
||||
"Closing",
|
||||
VALUATION_REVIEWS.map(function (item, index) {
|
||||
return React.DOM.label(
|
||||
{ key: index },
|
||||
React.DOM.input({
|
||||
type: 'radio',
|
||||
checked: index === key[0],
|
||||
onChange: e => selectedOp.reset(index),
|
||||
}),
|
||||
' ',
|
||||
item.get('title')
|
||||
);
|
||||
}),
|
||||
React.DOM.br(),
|
||||
);
|
||||
}
|
||||
});
|
||||
const FormatEntry = React.createClass({
|
||||
render: function () {
|
||||
const entry = entries.getIn(this.props.entryKey);
|
||||
return React.DOM.div(
|
||||
null,
|
||||
React.DOM.table(
|
||||
{ className: 'table table-sm d-c-table' },
|
||||
React.DOM.thead(
|
||||
null,
|
||||
React.DOM.tr(
|
||||
null,
|
||||
React.DOM.th(),
|
||||
React.DOM.th(null, "Debit"),
|
||||
React.DOM.th(null, "Credit"),
|
||||
)
|
||||
),
|
||||
React.DOM.tbody(
|
||||
null,
|
||||
// Use `journal_operations' if it's a review. See `valuation-data.js'.
|
||||
entry && entry.get('journal_operations', entry.get('operations', [])).map(this.renderRow)
|
||||
)
|
||||
),
|
||||
React.createElement(Listing, {
|
||||
heading: "Explanation",
|
||||
items: entry && entry.get('explanation'),
|
||||
}),
|
||||
React.createElement(Listing, {
|
||||
heading: "Configuration",
|
||||
items: entry && entry.get('configuration'),
|
||||
})
|
||||
);
|
||||
},
|
||||
renderRow: function (entry, index) {
|
||||
const standard = this.props.entryKey[1];
|
||||
if (!entry) {
|
||||
return React.DOM.tr(
|
||||
{ key: 'spacer-' + index },
|
||||
React.DOM.td({ colSpan: 3 }, "\u00A0")
|
||||
);
|
||||
}
|
||||
const journalEntry = VALUATION_JOURNALS.getIn([standard, ...entry.get('account')]);
|
||||
const title = journalEntry.get('title');
|
||||
// Don't display 0 for 'General Balance for Inventory Initial Value'
|
||||
const code = journalEntry.get('code') || '';
|
||||
return React.DOM.tr(
|
||||
{ key: index },
|
||||
React.DOM.td(null, `${code} ${title}`),
|
||||
React.DOM.td(null, entry.get('debit')),
|
||||
React.DOM.td(null, entry.get('credit'))
|
||||
);
|
||||
}
|
||||
});
|
||||
const Listing = React.createClass({
|
||||
render: function () {
|
||||
if (!this.props.items || this.props.items.isEmpty()) {
|
||||
return React.DOM.div();
|
||||
}
|
||||
const items = this.props.items;
|
||||
const idx = items.indexOf(null);
|
||||
if (idx !== -1) {
|
||||
// console.log(items.slice(idx + 1).deref());
|
||||
items = items.take(idx);
|
||||
}
|
||||
return React.DOM.div(
|
||||
{ className: 'entries-listing' },
|
||||
React.DOM.h4(null, this.props.heading, ':'),
|
||||
items.map(function (item, index) {
|
||||
return React.DOM.p({ key: index }, item);
|
||||
})
|
||||
);
|
||||
}
|
||||
});
|
||||
}());
|
||||
Reference in New Issue
Block a user