03_データ仕様書.md — 全面書き直し(M:N関係、中山間17列モデル、面積単位、PDF出力仕様) 04_画面設計書.md — 全面書き直し(Navbar追加、圃場管理/新規作成画面追加、インライン編集方式、PDF帳票フォーマット仕様 E-1) 01_プロダクトビジョン.md — CSV→PDF、M:1→M:N 05_実装優先順位.md — CSV→PDF、Django 5.0→5.2、モーダル→インライン、init_crops削除 00_Gemini向け統合指示書.md — CSV→PDF、Django 5.2、M:N関係、中山間17列モデル、init_crops削除、IsAuthenticated CLAUDE.md — 既知の課題一覧、次タスク優先順追加、中山間モデル拡張、差異レポートリンク コード修正(4件) D-1: reports/views.py — plan.crop / plan.variety の null チェック追加 D-2: init_crops.py を削除 D-3: settings.py — LANGUAGE_CODE/TIME_ZONE の二重定義を解消 D-4: settings.py — AllowAny → IsAuthenticated に変更 次のタスクは CLAUDE.md の優先順リストに従うと A-8(圃場詳細に共済/中山間情報表示)です。続けますか?
88 lines
2.8 KiB
Python
88 lines
2.8 KiB
Python
from django.template.loader import render_to_string
|
|
from django.http import HttpResponse
|
|
from weasyprint import HTML
|
|
from apps.fields.models import OfficialKyosaiField, OfficialChusankanField, Field
|
|
from apps.plans.models import Plan
|
|
|
|
|
|
def generate_kyosai_pdf(request, year):
|
|
kyosai_fields = OfficialKyosaiField.objects.all()
|
|
|
|
data = []
|
|
for kyosai in kyosai_fields:
|
|
related_fields = kyosai.fields.all()
|
|
plans = Plan.objects.filter(field__in=related_fields, year=year)
|
|
|
|
crops = {}
|
|
total_area = 0
|
|
for plan in plans:
|
|
crop_name = plan.crop.name if plan.crop else '未設定'
|
|
if crop_name not in crops:
|
|
crops[crop_name] = {
|
|
'name': crop_name,
|
|
'variety': plan.variety.name if plan.variety else '',
|
|
'count': 0
|
|
}
|
|
crops[crop_name]['count'] += 1
|
|
total_area += float(plan.field.area_tan)
|
|
|
|
data.append({
|
|
'kyosai': kyosai,
|
|
'fields': related_fields,
|
|
'crops': list(crops.values()),
|
|
'total_area': total_area,
|
|
'field_count': related_fields.count()
|
|
})
|
|
|
|
html_string = render_to_string('reports/kyosai_template.html', {
|
|
'year': year,
|
|
'data': data
|
|
})
|
|
|
|
pdf = HTML(string=html_string).write_pdf()
|
|
|
|
response = HttpResponse(pdf, content_type='application/pdf')
|
|
response['Content-Disposition'] = f'attachment; filename="kyosai_{year}.pdf"'
|
|
return response
|
|
|
|
|
|
def generate_chusankan_pdf(request, year):
|
|
chusankan_fields = OfficialChusankanField.objects.all()
|
|
|
|
data = []
|
|
for chusankan in chusankan_fields:
|
|
related_fields = chusankan.fields.all()
|
|
plans = Plan.objects.filter(field__in=related_fields, year=year)
|
|
|
|
crops = {}
|
|
total_area = 0
|
|
for plan in plans:
|
|
crop_name = plan.crop.name if plan.crop else '未設定'
|
|
if crop_name not in crops:
|
|
crops[crop_name] = {
|
|
'name': crop_name,
|
|
'variety': plan.variety.name if plan.variety else '',
|
|
'count': 0
|
|
}
|
|
crops[crop_name]['count'] += 1
|
|
total_area += float(plan.field.area_tan)
|
|
|
|
data.append({
|
|
'chusankan': chusankan,
|
|
'fields': related_fields,
|
|
'crops': list(crops.values()),
|
|
'total_area': total_area,
|
|
'field_count': related_fields.count()
|
|
})
|
|
|
|
html_string = render_to_string('reports/chusankan_template.html', {
|
|
'year': year,
|
|
'data': data
|
|
})
|
|
|
|
pdf = HTML(string=html_string).write_pdf()
|
|
|
|
response = HttpResponse(pdf, content_type='application/pdf')
|
|
response['Content-Disposition'] = f'attachment; filename="chusankan_{year}.pdf"'
|
|
return response
|