✅ 02_ユーザーストーリー.md - 作物マスタの定義を統一 ✅ 03_データ仕様書.md - 作物・品種マスタを更新 ✅ 04_画面設計書.md - 集計サイドバーと編集モーダルのUI ✅ 05_実装優先順位.md - Day 5-6に集計API・品種追加APIを追加 ✅ 06_Gemini向け統合指示書.md - コード例を全面更新
14 KiB
14 KiB
データ仕様書
📊 データ構造の全体像
このシステムで扱うデータは3種類:
- 実圃場データ(吉田農地台帳.ods)- 実際に作業する農地
- 共済マスタ(水稲共済細目用.ods)- 申請書用の区画
- 中山間マスタ(中山間.ods)- 申請書用の区画
紐付けの関係:
- 実圃場 → 共済区画: M対1(複数の実圃場が1つの共済区画に対応)
- 実圃場 → 中山間区画: M対1(複数の実圃場が1つの中山間区画に対応)
erDiagram
実圃場 }o--|| 共済区画 : "紐づく(M:1)"
実圃場 }o--|| 中山間区画 : "紐づく(M:1)"
実圃場 ||--o{ 作付け計画 : "持つ(1:N)"
実圃場 {
int id PK
string 名称
string 住所
float 面積_反
string 地主
int 細目_耕地番号 "共済紐付けキー"
int 細目_分筆番号 "共済紐付けキー"
int 中山間_ID "中山間紐付けキー"
}
共済区画 {
int id PK
string 地名_地番
int 耕地番号
int 分筆番号
float 本地面積_m2
string 漢字地名
}
中山間区画 {
int id PK
int ID
string 大字
string 字
int 地番
int 農地面積_m2
int 交付金額
}
作付け計画 {
int id PK
int 実圃場_id FK
int 年度
string 作物
string 品種
date 播種日
date 収穫日
}
1. 実圃場データ(吉田農地台帳.ods)
ファイル情報
- 行数: 39行(39筆の圃場)
- 列数: 7列
カラム定義
| カラム名 | データ型 | 必須 | 説明 | 例 |
|---|---|---|---|---|
| 名称 | string | ○ | 圃場の名称(自由記述) | "口神 1反2畝" |
| 住所 | string | ○ | 圃場の住所 | "口神ノ川198(笹ヶ谷374-1)" |
| 面積(反) | float | ○ | 面積(単位: 反)※1反=1000m2=10a | 1.20 |
| 地主 | string | ○ | 地主の氏名 | "山崎 出祥" |
| 細目_耕地番号 | int | ○ | 共済マスタとの紐付けキー(1/2) | 2 |
| 細目_分筆番号 | int | ○ | 共済マスタとの紐付けキー(2/2) | 1 |
| 中山間_ID | int | △ | 中山間マスタとの紐付けキー | 50 |
データサンプル
名称 住所 面積(反) 細目_耕地番号 細目_分筆番号 中山間_ID
口神 1反2畝 口神ノ川198(笹ヶ谷374-1) 1.20 2 1 50
口神 北東 口神ノ川198(笹ヶ谷374-1) 0.40 2 2 50
口神 北中 口神ノ川198(笹ヶ谷374-1) 0.43 2 2 50
特記事項
- 中山間_IDは一部NULL: 39筆中2筆が中山間の対象外(
NaN) - 同じ共済区画に複数の実圃場: 例えば共済キー「2-2」には3つの実圃場が紐づく
- 面積単位: DB内部では「反」と「m2」の両方を保持する(変換: 1反=1000m2)
2. 共済マスタ(水稲共済細目用.ods)
ファイル情報
- 行数: 31行(31区画)
- 列数: 5列
カラム定義
| カラム名 | データ型 | 必須 | 説明 | 例 |
|---|---|---|---|---|
| 地名 地番 | string | ○ | 地名と地番(スペース区切り) | "四万十町 ササガタニ 374-1" |
| 耕地番号 | int | ○ | 共済区画の識別子(1/2) | 2 |
| 分筆番号 | int | ○ | 共済区画の識別子(2/2) | 1 |
| 本地面積 (m2) | float | ○ | 申請上の面積(単位: m2) | 25.4 |
| 漢字地名 | string | ○ | 漢字表記の地名 | "四万十町 笹ヶ谷 374-1" |
データサンプル
地名 地番 耕地番号 分筆番号 本地面積(m2) 漢字地名
四万十町 ササガタニ 374-1 2 1 25.4 四万十町 笹ヶ谷 374-1
四万十町 ササガタニ 374-1 2 2 12.0 四万十町 笹ヶ谷 374-1
特記事項
- 面積の不整合は許容: 役場データが古いため、実圃場の合計面積と一致しないことがある
- 例: 共済キー「2-2」の面積は12.0m2だが、実圃場の合計は1.33反=1330m2
- これは「そういうもの」として扱い、システム側で修正しない
- 重複キーなし: (耕地番号, 分筆番号)の組み合わせは一意
3. 中山間マスタ(中山間.ods)
ファイル情報
- 行数: 71行(71区画)
- 列数: 17列(うち使用するのは一部)
カラム定義(主要なもの)
| カラム名 | データ型 | 必須 | 説明 | 例 |
|---|---|---|---|---|
| ID | int | ○ | 中山間区画の識別子 | 50 |
| 大字 | string | ○ | 大字名 | "口神ノ川" |
| 字 | string | ○ | 字名 | "壱町切" |
| 地番 | int | ○ | 地番 | 1694 |
| 農地面積 | int | ○ | 面積(単位: m2) | 2900 |
| 作付け品目 | string | △ | (役場が記入、システムでは上書き) | "ニラ" |
| 交付金額 | int | △ | 交付金額 | 37700 |
データサンプル
ID 大字 字 地番 農地面積 作付け品目 交付金額
50 口神ノ川 笹ヶ谷 374 2698 米 xxxxxx
特記事項
- 使用する列は限定的: システムでは主に「ID」「大字」「字」「地番」「農地面積」を使用
- 作付け品目は上書き: 役場が記入した「作付け品目」は参考情報で、システムで上書きする
- 面積の不整合は許容: 共済マスタと同様、実圃場との差異は受け入れる
4. 作付け計画データ(システム内部)
テーブル定義
| カラム名 | データ型 | 必須 | 説明 |
|---|---|---|---|
| id | int | ○ | 主キー(自動採番) |
| field_id | int | ○ | 実圃場ID(外部キー) |
| year | int | ○ | 年度(2025など) |
| crop | string | ○ | 作物(「米」「トウモロコシ」など) |
| variety | string | △ | 品種(「にこまる」など) |
| planting_date | date | △ | 播種日/定植日(Phase 2) |
| harvest_date | date | △ | 収穫日(Phase 2) |
| notes | text | △ | 備考 |
制約
- ユニーク制約: (field_id, year) - 1つの圃場に対して1年度につき1つの作付け計画のみ
- Phase 2で二毛作対応する場合は、この制約を見直す
5. 作物マスタ
作物リスト
- 米
- トウモロコシ
- エンドウ
- 野菜
- その他
品種の登録方法
すべての作物で統一されたUI:
- プリセット品種から選択
- その場で新しい品種を追加可能
- 作物による操作の違いなし
プリセット品種の例
米
- にこまる
- たちはるか
- たちはるか(特栽)
トウモロコシ
- (ユーザーが追加)
エンドウ
- 久留米豊
野菜
- (ユーザーが追加)
その他
- 完全休耕
- 緑肥(ヘアリーベッチ)
- 緑肥(レンゲ)
- 景観作物(コスモス)
- 景観作物(ヒマワリ)
実装上の注意
- すべての作物で
Varietyテーブルに品種を登録 - 「作付けしない」系を特別扱いしない
- UIは完全に統一
6. データインポート仕様
初期セットアップ時
-
共済マスタのインポート
水稲共済細目用.odsを読み込みOfficialKyosaiFieldテーブルに保存
-
中山間マスタのインポート
中山間.odsを読み込みOfficialChusankanFieldテーブルに保存
-
実圃場データのインポート
吉田農地台帳.odsを読み込みFieldテーブルに保存- 同時に共済・中山間マスタとの紐付けを確立:
細目_耕地番号+細目_分筆番号→OfficialKyosaiField.idを外部キーとして保存中山間_ID→OfficialChusankanField.idを外部キーとして保存
紐付けロジック
# 共済マスタとの紐付け
kyosai_record = OfficialKyosaiField.objects.get(
k_num=row['細目_耕地番号'],
s_num=row['細目_分筆番号']
)
field.kyosai_field_ref = kyosai_record.id
# 中山間マスタとの紐付け
if pd.notna(row['中山間_ID']):
chusankan_record = OfficialChusankanField.objects.get(
c_id=int(row['中山間_ID'])
)
field.chusankan_field_ref = chusankan_record.id
7. 申請書PDF出力ロジック
水稲共済細目書
出力形式:
- A4サイズ、縦向き
- ヘッダー: 「水稲共済細目書(◯◯年度)」
- 表形式(罫線あり)
- フォントサイズ: 10pt
- ページ番号(複数ページの場合)
表の列:
耕地番号 | 分筆番号 | 地名地番 | 漢字地名 | 本地面積(m2) | 作付品目 | 品種 | 備考
1 | 1 | 四万十町... | 四万十町... | 2.2 | 米 |にこまる|
2 | 1 | 四万十町... | 四万十町... | 25.4 | 米 |にこまる|
2 | 2 | 四万十町... | 四万十町... | 12.0 |米,野菜|にこまる,トマト|複数圃場
集計ロジック:
def generate_kyosai_pdf(year):
# 1. データ集約(CSVと同じロジック)
output_rows = []
for kyosai in OfficialKyosaiField.objects.all().order_by('k_num', 's_num'):
fields = Field.objects.filter(kyosai_field_ref=kyosai.id)
plans = Plan.objects.filter(field__in=fields, year=year)
crops = list(set([p.crop.name for p in plans if p.crop]))
varieties = list(set([p.variety.name for p in plans if p.variety]))
row = {
'耕地番号': kyosai.k_num,
'分筆番号': kyosai.s_num,
'地名地番': kyosai.address,
'漢字地名': kyosai.kanji_name,
'本地面積(m2)': kyosai.area,
'作付品目': ','.join(crops) if crops else '未設定',
'品種': ','.join(varieties) if varieties else '',
'備考': f'{len(fields)}筆合算' if len(fields) > 1 else ''
}
output_rows.append(row)
# 2. HTMLテンプレートで表を生成
html = render_to_string('reports/kyosai_template.html', {
'year': year,
'rows': output_rows
})
# 3. HTML → PDF変換
pdf = HTML(string=html).write_pdf()
return pdf
HTMLテンプレート例(reports/kyosai_template.html):
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<style>
@page { size: A4; margin: 2cm; }
body { font-family: "MS Gothic", monospace; font-size: 10pt; }
h1 { text-align: center; font-size: 14pt; margin-bottom: 20px; }
table { width: 100%; border-collapse: collapse; }
th, td { border: 1px solid black; padding: 5px; text-align: center; }
th { background-color: #f0f0f0; }
</style>
</head>
<body>
<h1>水稲共済細目書({{ year }}年度)</h1>
<table>
<thead>
<tr>
<th>耕地番号</th>
<th>分筆番号</th>
<th>地名地番</th>
<th>漢字地名</th>
<th>本地面積(m2)</th>
<th>作付品目</th>
<th>品種</th>
<th>備考</th>
</tr>
</thead>
<tbody>
{% for row in rows %}
<tr>
<td>{{ row.耕地番号 }}</td>
<td>{{ row.分筆番号 }}</td>
<td>{{ row.地名地番 }}</td>
<td>{{ row.漢字地名 }}</td>
<td>{{ row.本地面積(m2) }}</td>
<td>{{ row.作付品目 }}</td>
<td>{{ row.品種 }}</td>
<td>{{ row.備考 }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</body>
</html>
中山間交付金申請
出力形式:
- A4サイズ、縦向き
- ヘッダー: 「中山間地域等直接支払交付金(◯◯年度)」
- 表形式(罫線あり)
表の列:
ID | 大字 | 字 | 地番 | 農地面積(m2) | 作付品目 | 品種 | 備考
50 | 口神ノ川 | 笹ヶ谷 | 374 | 2698 | 米,野菜 | にこまる,トマト | 7筆合算
集計ロジック:
- 水稲共済と同様、中山間マスタをループして実圃場を集約 → HTMLテンプレート → PDF
8. データ移行・メンテナンス
年度更新
- 圃場マスタ: 年度をまたいで共通(更新不要)
- 作付け計画: 年度ごとに独立(前年度コピー機能で複製)
マスタデータの更新
- 共済・中山間マスタ: 役場から新しいファイルをもらった場合、再インポート
- 既存データは上書きせず、差分を確認してマージ
- または、全削除→再インポートの2段階処理
バックアップ
- 全テーブルをCSV/Excelでエクスポート可能にする
- 最低5年分のデータを保持(補助金監査対応)
9. 面積単位の扱い
システム内部では以下のように統一:
| 表示単位 | DB保存 | 変換式 |
|---|---|---|
| 反(たん) | m2 | 1反 = 1000m2 |
| アール(a) | m2 | 1a = 100m2 |
| ヘクタール(ha) | m2 | 1ha = 10000m2 |
実装方針:
- DB内部は全て
m2で保存(整数型) - 表示時にユーザー設定に応じて変換(デフォルトは「反」)
- 入力時は「反」で受け付け、内部で
m2に変換
10. データ整合性チェック
チェック項目
-
紐付けの存在確認
- 実圃場の
細目_耕地番号/細目_分筆番号が共済マスタに存在するか - 実圃場の
中山間_IDが中山間マスタに存在するか
- 実圃場の
-
面積の整合性(参考情報)
- 1つの共済区画に紐づく実圃場の合計面積と、共済マスタの面積を比較
- ⚠️ 不整合があっても警告のみ(修正はしない)
-
作付け未設定の検出
- 指定年度で作付け計画が未設定の圃場をリストアップ
実装
- インポート時にバリデーションを実行
- 管理画面で「データ整合性レポート」を表示