@threestarsoftware/tssgrid 0.1.2 → 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -3,6 +3,14 @@
3
3
  TssGrid の各リリースの変更点。日付は JST。形式は [Keep a Changelog](https://keepachangelog.com/ja/1.1.0/) 準拠(ゆるめ)。
4
4
  数値は特記なき限り**自社調べ**(headless Chrome / Windows 11・環境差あり)。
5
5
 
6
+ ## [0.1.3] - 2026-07-17
7
+
8
+ ### 追加
9
+ - **`tss-sum` の行 spec に `after(sum)`=集計後フック**(プラグイン)— `of` で集めた合計に対して**最後に1回だけ**走る(行ごとではない)。**適格請求書の消費税は「一の適格請求書につき税率ごとに1回だけ」端数処理する**のが要件だが、従来の `tss-sum` は `of(row)` を各行に適用して合計するため **`of` の中で丸める=明細行ごと**の形しか書けず、「**集めてから1回丸める**」を宣言で表現する口が無かった(`105円×2行@10%`: 正しくは `端数処理(210×0.10)=¥21` / 行ごとだと `floor(10.5)×2=¥20` で**1円ずれる**)。`when` で税率ごとに行が分かれるので `after` は**その税率の合計**に対して走る(請求書全体で1回ではない)。`after` の結果は後続の `total(vals)` にも渡る=**合計(税込)が丸め後の税額を見る**。`after` を書かない既存 spec は影響を受けない。tssgrid-kintone 側で先行実装・実機運用されていたものを本体へ回収(=フォーク解消)。
10
+
11
+ ### 修正
12
+ - **請求書/見積サンプルの消費税を「税率ごとに1回」の端数処理に修正**(examples)— `examples/invoice.html` は**明細行ごとに丸めた上で「適格請求書=インボイス方式」と説明**しており、**要件を満たさない請求書の作り方を教えていた**(但し書きも「各明細行ごとに算出し」)。上記 `after` で税率ごと1回に修正し、説明と但し書きも訂正。`examples/quote.html`(見積書)も同じ形だったため揃えた(見積自体は適格請求書ではないが、そのまま請求書にした時に数字が食い違うため)。
13
+
6
14
  ## [0.1.2] - 2026-07-17
7
15
 
8
16
  ### 修正
package/README.md CHANGED
@@ -493,15 +493,17 @@ const sum = TssSum.attach(grid, document.getElementById('sumgrid'), {
493
493
  format: v => '¥' + Number(v).toLocaleString('ja-JP'),
494
494
  rows: [
495
495
  { label: '小計(税抜)', of: r => (+r[2]||0)*(+r[3]||0) }, // 全データ行の合計
496
- { label: '消費税(10%)', when: r => r[4]==='10%', of: r => Math.round((+r[2]||0)*(+r[3]||0)*0.10) }, // 条件付き
497
- { label: '消費税(8%)', when: r => r[4]==='8%', of: r => Math.round((+r[2]||0)*(+r[3]||0)*0.08) },
496
+ // 条件付き+集計後フック: of で税抜を集めて、after でその合計に 1 回だけ端数処理
497
+ { label: '消費税(10%)', when: r => r[4]==='10%', of: r => (+r[2]||0)*(+r[3]||0), after: s => Math.round(s*0.10) },
498
+ { label: '消費税(8%)', when: r => r[4]==='8%', of: r => (+r[2]||0)*(+r[3]||0), after: s => Math.round(s*0.08) },
498
499
  { label: '合計(税込)', total: v => v[0]+v[1]+v[2] }, // 既出行から派生
499
500
  ],
500
501
  onCompute: vals => { /* 上部の総額表示など */ },
501
502
  });
502
503
  // sum.refresh() 手動再計算 / sum.detach() フック解除+集計グリッド破棄
503
504
  ```
504
- - 行は **`{label, when?, of}`**(`when` 一致行で `of(row)` を合計=SUMIF)または **`{label, total}`**(既出行の値から派生)。`row` は内部配列(列index)で受ける。
505
+ - 行は **`{label, when?, of, after?}`**(`when` 一致行で `of(row)` を合計=SUMIF)または **`{label, total}`**(既出行の値から派生)。`row` は内部配列(列index)で受ける。
506
+ - **`after(sum)`=集めた合計に対して最後に1回だけ**走る(行ごとではない)。**適格請求書の消費税は「税率ごとに1回だけ」端数処理する**のが要件で、`of` の中で丸めると**明細行ごと**になってしまうため(`105円×2行@10%`: `after`=`端数処理(210×0.10)=¥21` / 行ごと=`floor(10.5)×2=¥20` で**1円ずれる**)。`when` で税率ごとに行が分かれるので、`after` は**その税率の合計**に対して走る(請求書全体で1回ではない)。`after` の結果は後続の `total(vals)` にも渡る=**合計(税込)が丸め後の税額を見る**。
505
507
  - ソースの **`onAfterChange`/`onStructureChange` を自動で包んで再計算**=編集・行追加削除・Undo すべてに追従。集計グリッドは**表示専用**(同一列幅で `金額` 列が揃う)。
506
508
 
507
509
  ### 同梱プラグイン: 残高/累計(running total・縦の連鎖)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@threestarsoftware/tssgrid",
3
- "version": "0.1.2",
3
+ "version": "0.1.3",
4
4
  "description": "軽量・ノービルド・日本語IME堅牢な編集グリッド(vanilla JS / 依存なし / MIT)。Excel ライクな入力画面を <script> タグ1本で。",
5
5
  "license": "MIT",
6
6
  "author": "ThreeStarSoftware (https://www.threestarsoftware.co.jp/)",
@@ -22,8 +22,15 @@
22
22
  * sum.refresh(); // 手動再計算 / sum.detach(); // フック解除+集計グリッド破棄
23
23
  *
24
24
  * 行の定義:
25
- * { label, when?(row)->bool, of(row)->number } … when に一致するデータ行で of(row) を合計(when 省略=全行)
25
+ * { label, when?(row)->bool, of(row)->number, after?(sum)->number }
26
+ * … when に一致するデータ行で of(row) を合計(when 省略=全行)。after は**その合計に対して最後に1回だけ**走る。
26
27
  * { label, total(priorValues[])->number } … それまでの行の値配列から派生(小計+税 など)
28
+ *
29
+ * after が要る理由(of では書けない): **適格請求書の消費税は「税率ごとに1回だけ」端数処理する**のが法要件で、
30
+ * 「行ごとに丸めて合計」ではない。of の中で丸めると行ごとになってしまうため、「集めてから1回丸める」を書く口が要る。
31
+ * { label:'消費税(10%)', when: r => tax(r)==='10%', of: r => amount(r), after: s => Math.round(s*0.10) } // 税率ごと1回(正)
32
+ * { label:'消費税(10%)', when: r => tax(r)==='10%', of: r => Math.round(amount(r)*0.10) } // 行ごと(旧来式)
33
+ * 105円×2行@10% で after あり=¥21 / 行ごと=¥20 と1円ずれる。when で税率ごとに行が分かれるので複数税率でも正しい。
27
34
  * opts: rows(必須) / valueCol(既定=最終列) / sumCol(of 省略時に合計する列) / format / rowHeight(既定28)
28
35
  * / onCompute(vals) / name / TssGrid(モジュール利用時にコンストラクタを注入)
29
36
  * 返り値: { grid, refresh, detach }
@@ -83,6 +90,12 @@
83
90
  v += spec.of ? num(spec.of(row)) : num(row[(opts.sumCol != null) ? opts.sumCol : valueCol]);
84
91
  }
85
92
  }
93
+ // 集計後フック: 集めた合計に対して最後に1回だけ走る(行ごとではない)。
94
+ // 適格請求書の消費税は「税率ごとに1回」端数処理するのが法要件= of の中で丸めると「行ごと」になり
95
+ // 1円ずれる(105円×2行@10%: after=端数処理(210*0.10)=21 / 行ごと=floor(10.5)*2=20)。
96
+ // when で税率ごとに行が分かれているので after はその税率の合計に対して走る(請求書全体で1回ではない)。
97
+ // ここ(vals[i] の直前)なので、後続の total(vals) 行は「丸めた後の税額」を見る=合計が合う。
98
+ if (typeof spec.after === 'function') v = spec.after(v);
86
99
  vals[i] = v;
87
100
  tg.data[i][valueCol] = String(v);
88
101
  }