diff --git a/static/modules/finance.js b/static/modules/finance.js
index ce556c2..4b8a3d0 100644
--- a/static/modules/finance.js
+++ b/static/modules/finance.js
@@ -1,7 +1,7 @@
// finance.js — 经营管理(财务)模块
const moneyInt = (v) => `${Math.round(Number(v || 0)).toLocaleString("zh-CN")}`;
-const moneyWan = (v) => `${(Number(v || 0) / 10000).toFixed(1)} 万`;
+const moneyWan = (v) => `${(Number(v || 0) / 10000).toFixed(0)} 万`;
function renderFinance() {
const pfs = state.data.projectFinances || [];
@@ -285,8 +285,8 @@ function renderFinance() {
{ key: '_expand', label: '' },
{ key: 'client_name', label: '客户' }, { key: 'customer_name', label: '项目名称' }, { key: 'sign_amount', label: '签约金额' },
{ key: 'rev', label: '已确收' }, { key: 'gross', label: '毛利' }, { key: 'gross_rate', label: '毛利率' },
- { key: 'payment', label: '回款' }, { key: 'pending', label: '待回款' }, { key: 'pay_rate', label: '回款率' },
- { key: 'cost', label: '成本' }, { key: 'paid', label: '支出' }, { key: 'paid_rate', label: '付款率' },
+ { key: 'payment', label: '回款' }, { key: 'pending', label: '应收' }, { key: 'pay_rate', label: '回款率' },
+ { key: 'cost', label: '成本' }, { key: 'paid', label: '支出' }, { key: 'payable', label: '应付' }, { key: 'paid_rate', label: '付款率' },
{ key: 'cashflow', label: '现金流' },
];
const UNSIGNED_COLS = [
@@ -302,25 +302,25 @@ function renderFinance() {
const netAsset = receivable - payable;
const m = moneyWan;
const rows_data = [
- ['签约金额', m(signTotal), '合同签约总额'],
- ['确收金额', m(sumRev), '已确认收入'],
- ['毛利', m(sumGross), '确收毛利'],
- ['应收', m(receivable), '确收−回款'],
- ['应付', m(payable), '成本−支出'],
- ['现金流', m(cashflow), '回款−支出'],
- ['项目净资产', m(netAsset), '应收−应付'],
+ ['签约金额', m(signTotal), '∑签约金额'],
+ ['确收金额', m(sumRev), '∑确收金额'],
+ ['毛利', m(sumGross), '∑毛利'],
+ ['应收', m(receivable), '确收 − 回款'],
+ ['应付', m(payable), '成本 − 支出'],
+ ['现金流', m(cashflow), '回款 − 支出'],
+ ['往来余额', m(netAsset), '应收 − 应付'],
];
const fs = '
' + rows_data.map(r =>
'
').join('') + '
';
const thead = isUnsigned ? buildThead(UNSIGNED_COLS, 'uns') : buildThead(SIGNED_COLS, 'sig');
- const theadCols = isUnsigned ? 6 : 14;
+ const theadCols = isUnsigned ? 6 : 15;
const tbody = rows.length ? `${rows.join("")}` : `| ${emptyText} |
`;
const subtitle = isUnsigned
? '合同 → 毛利 → 成本 → 项目利润'
: '合同 → 确收 → 毛利 → 成本 → 项目利润 → 回款 → 支出 → 现金流';
return `${isUnsigned ? '' : `${card(`
${finHeaderBase}
${finAddBtn}
`, "py-2 px-4")}
`}` +
- card(fs +
- `项目财务明细
${subtitle}
`, "p-4");
+ card(fs, "px-4 py-2") +
+ card(`项目财务明细
${subtitle}
`, "p-4");
};
const fmtNoUnit = (v) => v ? `${Number(v||0).toLocaleString('zh-CN')}` : '—';
@@ -331,6 +331,9 @@ function renderFinance() {
const payRCls = payRVal === null ? '' : payRVal < 30 ? 'text-red-600' : payRVal < 80 ? 'text-amber-600' : 'text-green-600';
const payR = payRVal !== null ? '' + payRVal + '%' : '—';
const paidR = cost && paid ? Math.round(paid / cost * 100) + '%' : '—';
+ const payable = cost - paid;
+ const payableCls = payable > 0 ? 'text-rose-600' : payable < 0 ? 'text-green-600' : 'text-slate-400';
+ const payableVal = payable ? (payable > 0 ? '+' : '') + money(payable) : '—';
const grossR = rev && gross ? Math.round(gross / rev * 100) + '%' : '—';
const cf = cashflow ? money(cashflow) : '—';
const cfCls = cashflow >= 0 ? 'text-green-600' : 'text-red-600';
@@ -359,7 +362,7 @@ function renderFinance() {
var bCf = bPay - ePaid;
return ' | | ' + m + ' | ' + (bRev ? money(bRev) : '—') + ' | ' + (bGross ? money(bGross) : '—') + ' | | ' + (bPay ? money(bPay) : '—') + ' | | ' + (eCost ? money(eCost) : '—') + ' | ' + (ePaid ? money(ePaid) : '—') + ' | | ' + (bCf ? money(bCf) : '—') + ' | ' + (bRev - bPay ? money(bRev - bPay) : '—') + ' |
';
}).join('');
- return ` | ${esc(pf.client_name || "")} | ${esc(pf.customer_name)} | ${money(pf.sign_amount)} | ${fmtNoUnit(rev)} | ${fmtNoUnit(gross)} | ${grossR} | ${fmtNoUnit(payment)} | ${pendingVal} | ${payR} | ${fmtNoUnit(cost)} | ${fmtNoUnit(paid)} | ${paidR} | ${cf} |
| | 月份 | 确收 | 毛利 | | 回款 | | 成本 | 支出 | | 现金流 | 待回款 | ${detailRows}
|
`;
+ return ` | ${esc(pf.client_name || "")} | ${esc(pf.customer_name)} | ${money(pf.sign_amount)} | ${fmtNoUnit(rev)} | ${fmtNoUnit(gross)} | ${grossR} | ${fmtNoUnit(payment)} | ${pendingVal} | ${payR} | ${fmtNoUnit(cost)} | ${fmtNoUnit(paid)} | ${payableVal} | ${paidR} | ${cf} |
| | 月份 | 确收 | 毛利 | | 回款 | | 成本 | 支出 | | 现金流 | 应收 | ${detailRows}
|
`;
};
// 待签约简版行
const tdRowUnsigned = (pf, cost, gross) => {
diff --git a/static/modules/plan.js b/static/modules/plan.js
index f4f470e..06a94b1 100644
--- a/static/modules/plan.js
+++ b/static/modules/plan.js
@@ -295,7 +295,7 @@ function renderPlan() {
{ key: 'gross', label: '毛利' },
{ key: 'gross_rate', label: '毛利率' },
{ key: 'payment', label: '回款' },
- { key: 'pending', label: '待回款' },
+ { key: 'pending', label: '应收' },
{ key: 'pay_rate', label: '回款率' },
{ key: 'cost', label: '当期成本' },
{ key: 'paid', label: '当期流出' },
@@ -320,25 +320,25 @@ function renderPlan() {
const netAsset = receivable - payable;
const m = moneyWan;
const rows_data = [
- ['签约金额', m(signTotal), '合同签约总额'],
- ['确收金额', m(sumRev), '已确认收入'],
- ['毛利', m(sumGross), '确收毛利'],
- ['应收', m(receivable), '确收−回款'],
- ['应付', m(payable), '成本−支出'],
- ['现金流', m(cashflow), '回款−支出'],
- ['项目净资产', m(netAsset), '应收−应付'],
+ ['签约金额', m(signTotal), '∑签约金额'],
+ ['确收金额', m(sumRev), '∑确收金额'],
+ ['毛利', m(sumGross), '∑毛利'],
+ ['应收', m(receivable), '确收 − 回款'],
+ ['应付', m(payable), '成本 − 支出'],
+ ['现金流', m(cashflow), '回款 − 支出'],
+ ['往来余额', m(netAsset), '应收 − 应付'],
];
const fs = '' + rows_data.map(r =>
'
').join('') + '
';
const thead = isUnsigned ? buildThead(UNSIGNED_COLS, 'uns') : buildThead(SIGNED_COLS, 'sig');
- const theadCols = isUnsigned ? 9 : 14;
+ const theadCols = isUnsigned ? 9 : 15;
const tbody = rows.length ? `${rows.join("")}` : `| ${emptyText} |
`;
const subtitle = isUnsigned
? '合同 → 毛利 → 成本 → 项目利润'
: '合同 → 确收 → 毛利 → 成本 → 项目利润 → 回款 → 支出 → 现金流';
return `${isUnsigned ? '' : `${card(`
${finHeaderBase}
${finAddBtn}
`, "py-2 px-4")}
`}` +
- card(fs +
- `项目财务明细
${subtitle}
`, "p-4");
+ card(fs, "px-4 py-2") +
+ card(`项目财务明细
${subtitle}
`, "p-4");
};
const fmtNoUnit = (v) => v ? `${Number(v||0).toLocaleString('zh-CN')}` : '—';
@@ -390,7 +390,7 @@ function renderPlan() {
var bCf = bPay - ePaid;
return ' | ' + m + ' | ' + (bRev ? money(bRev) : '—') + ' | ' + (bGross ? money(bGross) : '—') + ' | | ' + (bPay ? money(bPay) : '—') + ' | | ' + (eCost ? money(eCost) : '—') + ' | ' + (ePaid ? money(ePaid) : '—') + ' | | ' + (bCf ? money(bCf) : '—') + ' | ' + (bRev - bPay ? money(bRev - bPay) : '—') + ' |
';
}).join('');
- return ` | ${esc(pf.client_name || "")} | ${esc(pf.customer_name)} | ${planInlineSelect('weight', pf.id, 'weight', pf.weight || '20%', ['20%','40%','60%','80%','100%'])} | ${planInlineSelect('ptype', pf.id, 'project_type', pf.project_type || '待签约', ['待签约','已签约'])} | ${money(pf.sign_amount)} | ${fmtNoUnit(rev)} | ${fmtNoUnit(gross)} | ${grossR} | ${fmtNoUnit(payment)} | ${pendingVal} | ${payR} | ${fmtNoUnit(cost)} | ${fmtNoUnit(paid)} | ${cf} |
| 月份 | 确收 | 毛利 | | 回款 | | 当期成本 | 当期流出 | | 现金流 | 待回款 | ${detailRows}
|
`;
+ return ` | ${esc(pf.client_name || "")} | ${esc(pf.customer_name)} | ${planInlineSelect('weight', pf.id, 'weight', pf.weight || '20%', ['20%','40%','60%','80%','100%'])} | ${planInlineSelect('ptype', pf.id, 'project_type', pf.project_type || '待签约', ['待签约','已签约'])} | ${money(pf.sign_amount)} | ${fmtNoUnit(rev)} | ${fmtNoUnit(gross)} | ${grossR} | ${fmtNoUnit(payment)} | ${pendingVal} | ${payR} | ${fmtNoUnit(cost)} | ${fmtNoUnit(paid)} | ${cf} |
| 月份 | 确收 | 毛利 | | 回款 | | 当期成本 | 当期流出 | | 现金流 | 应收 | ${detailRows}
|
`;
};
// 待签约简版行
const tdRowUnsigned = (pf, cost, gross) => {
diff --git a/templates/index.html b/templates/index.html
index 9d4db26..b035713 100644
--- a/templates/index.html
+++ b/templates/index.html
@@ -84,7 +84,7 @@
-
OPC Manager v1.2.0.34
+
OPC Manager v1.2.0.35