開発eurekapuメモ
概要
連結会計アプリの連結精算表ページにおいて、以下の4つのUIコンポーネント改善を実施した。
- 売却パターン図の追加 - PrerequisitesCard.vueに6パターンの売却図を追加
- パターン図のSVGサイズ調整 - viewBox幅拡大で右端ラベルの見切れを修正
- マイナス値表示の「▲」形式対応 - formatNumber関数を改修し7コンポーネントに適用
- 合計仕訳ブロックのスタイル調整 - JournalCategoryTable.vueのタイトル・余白を改善
1. 売却パターン図の追加
背景
連結会計の資本連結では、株式の「追加取得」と「売却」で異なる会計処理が必要になる。既存のPrerequisitesCard.vueには追加取得の5パターンのみが実装されていたため、売却の6パターンを追加した。
パターン定義
追加取得(既存):
// 追加取得の5パターン定義(図表4-1準拠)
const acquisitionPatterns = [
{ num: 1, startPercent: 70, endPercent: 80, label: '①' },
{ num: 2, startPercent: 5, endPercent: 80, label: '②' },
{ num: 3, startPercent: 30, endPercent: 80, label: '③' },
{ num: 4, startPercent: 25, endPercent: 40, label: '④' },
{ num: 5, startPercent: 5, endPercent: 25, label: '⑤' },
]
const acquisitionPatternNames = [
'① 子会社株式を追加取得した場合',
'② 子会社・関連会社以外から子会社とする場合',
'③ 関連会社から子会社とする場合',
'④ 関連会社株式を追加取得した場合',
'⑤ 子会社・関連会社以外から関連会社とする場合',
]
売却(新規追加):
// 売却の6パターン定義(第5章準拠)
const salePatterns = [
{ num: 1, startPercent: 80, endPercent: 70, label: '①' },
{ num: 2, startPercent: 80, endPercent: 30, label: '②' },
{ num: 3, startPercent: 80, endPercent: 10, label: '③' },
{ num: 4, startPercent: 80, endPercent: 0, label: '④' },
{ num: 5, startPercent: 70, endPercent: 30, label: '⑤' },
{ num: 6, startPercent: 80, endPercent: 30, label: '⑥' },
]
const salePatternNames = [
'① 支配関係が継続する場合',
'② 支配を喪失し関連会社になった場合',
'③ 支配を喪失し関連会社にも該当しなくなった場合',
'④ 子会社株式の全部を売却した場合',
'⑤ 一部売却後に一部売却を行い関連会社になった場合',
'⑥ 追加取得後に一部売却を行い関連会社になった場合',
]
売却パターン図のSVG実装
売却パターンでは、追加取得と異なり下向き矢印で持分の減少を表現する。
<!-- 売却パターン: 売却前のバー(上部)&売却後の点線バー -->
<template v-if="patternType === 'sale'">
<!-- 売却後のバー(残存持分) -->
<rect
v-if="p.endPercent > 0"
:x="50 + i * 42"
:y="150 - (p.endPercent / 100) * 136"
width="22"
:height="(p.endPercent / 100) * 136"
:class="prerequisites.acquisitionPattern!.patternNumber === p.num
? 'bar-before-active' : 'bar-before'"
rx="2"
/>
<!-- 売却前の持分(点線枠で示す) -->
<rect
:x="50 + i * 42"
:y="150 - (p.startPercent / 100) * 136"
width="22"
:height="((p.startPercent - p.endPercent) / 100) * 136"
fill="none"
:stroke="prerequisites.acquisitionPattern!.patternNumber === p.num
? '#ef4444' : '#d1d5db'"
stroke-width="1.5"
stroke-dasharray="3 2"
rx="2"
/>
<!-- 下向き矢印(売却による減少) -->
<line
:x1="61 + i * 42"
:y1="150 - (p.startPercent / 100) * 136 + 4"
:x2="61 + i * 42"
:y2="150 - (p.endPercent / 100) * 136 - 5"
:class="prerequisites.acquisitionPattern!.patternNumber === p.num
? 'pattern-arrow-sale-active' : 'pattern-arrow-sale'"
stroke-width="2"
/>
<polygon
:points="`${57 + i * 42},${150 - (p.endPercent / 100) * 136 - 5}
${61 + i * 42},${150 - (p.endPercent / 100) * 136 + 2}
${65 + i * 42},${150 - (p.endPercent / 100) * 136 - 5}`"
:class="prerequisites.acquisitionPattern!.patternNumber === p.num
? 'pattern-arrowhead-sale-active' : 'pattern-arrowhead-sale'"
/>
</template>
パターンタイプの自動判定
データファイルのacquisitionPattern.patternTypeプロパティで追加取得/売却を判定:
const patternType = computed(() =>
props.prerequisites.acquisitionPattern?.patternType ?? 'acquisition'
)
const allPatterns = computed(() =>
patternType.value === 'sale' ? salePatterns : acquisitionPatterns
)
const patternNames = computed(() =>
patternType.value === 'sale' ? salePatternNames : acquisitionPatternNames
)
const patternTitle = computed(() =>
patternType.value === 'sale' ? '子会社株式売却のパターン' : '追加取得のパターン'
)
売却パターン用のCSS
/* 矢印: 非アクティブ(売却) */
.pattern-arrow-sale {
stroke: #d1d5db;
}
.pattern-arrowhead-sale {
fill: #d1d5db;
}
/* 矢印: アクティブ(売却) - 赤色で売却を強調 */
.pattern-arrow-sale-active {
stroke: #ef4444;
}
.pattern-arrowhead-sale-active {
fill: #ef4444;
}
2. パターン図のSVGサイズ調整
問題
パターン図の右端にある「子会社」「関連会社」のラベルが見切れていた。
原因
SVGのviewBox幅が不足していた。
修正内容
<!-- Before -->
<svg viewBox="0 0 300 190" class="diagram-svg pattern-svg">
<!-- After: パターンタイプに応じてviewBox幅を調整 -->
<svg :viewBox="patternType === 'sale' ? '0 0 370 190' : '0 0 340 190'"
class="diagram-svg pattern-svg">
| パターン | 修正前 | 修正後 |
|---|---|---|
| 追加取得 | 300px | 340px |
| 売却 | - | 370px |
売却パターンは6パターンあるため、追加取得(5パターン)より幅が必要。
グリッド線とラベル位置の調整
<!-- グリッド線の終端位置をpatternTypeで調整 -->
<line x1="40" y1="14"
:x2="patternType === 'sale' ? 300 : 270"
y2="14" stroke="#e5e7eb" stroke-width="1" />
<!-- 閾値ラベルの位置も調整 -->
<text :x="patternType === 'sale' ? 308 : 278" y="82"
class="threshold-label threshold-sub">子会社</text>
<text :x="patternType === 'sale' ? 308 : 278" y="120"
class="threshold-label threshold-assoc">関連会社</text>
max-widthの緩和
/* パネル幅いっぱいに広がるよう制限を緩和 */
.pattern-svg {
max-width: 100%;
}
3. マイナス値表示の「▲」形式対応
背景
会計帳票では、マイナス値を「-100」ではなく「▲100」と表示するのが一般的。この形式に対応するため、共通のformatNumber関数を改修した。
formatNumber関数の実装
// apps/web/app/components/consolidated-worksheet/data/types.ts
export const formatNumber = (n: number): string =>
n === 0 ? '-' : n < 0
? `<span class="neg-mark">▲</span>${(-n).toLocaleString('ja-JP')}`
: n.toLocaleString('ja-JP')
設計ポイント
- ゼロ値:
-(ハイフン)で表示 - 負の値:
▲マーク + 絶対値(カンマ区切り) - 正の値: そのままカンマ区切り
- HTMLタグを返す:
v-htmlディレクティブで描画
スタイル定義
.td-amount :deep(.neg-mark) {
font-size: 0.75em;
vertical-align: baseline;
margin-right: 1px;
}
:deep()を使用してスコープ付きCSS内でも.neg-markクラスにスタイルを適用。
更新したコンポーネント(7ファイル)
| コンポーネント | 用途 |
|---|---|
| JournalCategoryTable.vue | 連結修正仕訳の表示 |
| WorksheetTable.vue | 連結精算表の表示 |
| EquityCalcTable.vue | 持分計算表の表示 |
| IndividualFinancialStatements.vue | 個別財務諸表 |
| PLStatementTable.vue | 損益計算書 |
| BSStatementTable.vue | 貸借対照表 |
| consolidation-simulator.vue | 連結シミュレーター |
4. 合計仕訳ブロックのスタイル調整
背景
JournalCategoryTable.vueでは、同一のtargetColumnに複数の仕訳がある場合、自動的に「合計仕訳」を計算して表示する。この合計仕訳ブロックが個別仕訳と見分けがつきにくかったため、スタイルを改善した。
合計仕訳の自動計算ロジック
// targetColumn ごとにエントリをグループ化し、2件以上あるグループの合計を計算
const columnSummaries = computed<Map<string, ColumnSummary>>(() => {
const groups = new Map<string, EntryView[]>()
for (const ev of entries.value) {
const key = ev.entry.targetColumn
const arr = groups.get(key)
if (arr) arr.push(ev)
else groups.set(key, [ev])
}
const result = new Map<string, ColumnSummary>()
for (const [colId, evs] of groups) {
if (evs.length < 2) continue
// 勘定科目ごとに借方・貸方を合算
const accountMap = new Map<string, { debit: number; credit: number }>()
for (const ev of evs) {
for (const line of ev.entry.debit) {
const acc = accountMap.get(line.account) ?? { debit: 0, credit: 0 }
acc.debit += line.amount
accountMap.set(line.account, acc)
}
for (const line of ev.entry.credit) {
const acc = accountMap.get(line.account) ?? { debit: 0, credit: 0 }
acc.credit += line.amount
accountMap.set(line.account, acc)
}
}
// 純額計算: 借方 > 貸方 → 借方側、貸方 > 借方 → 貸方側、差額0 → 省略
const debitLines: SummaryAccountLine[] = []
const creditLines: SummaryAccountLine[] = []
for (const [account, { debit, credit }] of accountMap) {
const net = debit - credit
if (net === 0) continue
if (net > 0) debitLines.push({ account, amount: net })
else creditLines.push({ account, amount: -net })
}
// ... 結果をMapに格納
}
return result
})
スタイル改善のポイント
/* 合計仕訳のタイトル行 */
.summary-title {
padding: 1.5rem 0.5rem 0.5rem 0.5rem; /* 上部に大きな余白 */
font-weight: 700;
font-size: 1.15rem; /* 個別仕訳(0.8rem)より大きく */
color: #1e40af;
background: #fff;
border-top: 3px solid #3b82f6; /* 上部に青い境界線 */
}
/* 合計仕訳のテーブル本体 */
.summary-entry-group {
background: #f8fafc; /* 薄いグレー背景で区別 */
}
/* クリック可能な行のスタイル */
.summary-row-clickable {
cursor: pointer;
}
.summary-row-clickable:hover td {
background: #fef3c7; /* ホバー時に黄色 */
}
インタラクション: 合計仕訳と個別仕訳のリンク
合計仕訳の勘定科目行をクリックすると、その科目を含む個別仕訳がハイライトされる:
const highlightedAccount = ref<{ targetColumn: string; account: string } | null>(null)
const toggleHighlight = (targetColumn: string, account: string) => {
if (highlightedAccount.value?.targetColumn === targetColumn
&& highlightedAccount.value?.account === account) {
highlightedAccount.value = null
} else {
highlightedAccount.value = { targetColumn, account }
}
}
// 個別仕訳の行がハイライト対象かを判定
const isHighlighted = (ev: EntryView, account: string): boolean => {
if (!highlightedAccount.value) return false
return highlightedAccount.value.targetColumn === ev.entry.targetColumn
&& highlightedAccount.value.account === account
}
まとめ
今回の改善により、連結会計アプリのUIが以下の点で向上した:
- 視覚的な明確さ: 売却パターン図で持分変動の方向(下向き矢印)が直感的に理解できる
- 情報の完全性: SVGサイズ調整でラベルの見切れを解消
- 会計帳票の慣習への準拠: マイナス値の「▲」表示で専門家にも違和感のない表示
- UXの改善: 合計仕訳と個別仕訳の関係がインタラクティブに確認可能
変更ファイル一覧
| ファイル | 変更内容 |
|---|---|
PrerequisitesCard.vue | 売却パターン6種追加、SVGサイズ調整 |
data/types.ts | formatNumber関数改修 |
JournalCategoryTable.vue | 合計仕訳スタイル改善 |
| 他6コンポーネント | formatNumber適用 |