diff --git a/backend/Dockerfile b/backend/Dockerfile
index 2688cba..d8ad4a1 100644
--- a/backend/Dockerfile
+++ b/backend/Dockerfile
@@ -10,6 +10,12 @@ RUN apt-get update && apt-get install -y \
libgdal-dev \
libgeos-dev \
libproj-dev \
+ fonts-noto-cjk \
+ libgirepository1.0-dev \
+ libcairo2 \
+ libpango-1.0-0 \
+ libpangocairo-1.0-0 \
+ gir1.2-pango-1.0 \
&& rm -rf /var/lib/apt/lists/*
ENV CPLUS_INCLUDE_PATH=/usr/include/gdal
diff --git a/backend/apps/reports/templates/reports/chusankan_template.html b/backend/apps/reports/templates/reports/chusankan_template.html
new file mode 100644
index 0000000..8955495
--- /dev/null
+++ b/backend/apps/reports/templates/reports/chusankan_template.html
@@ -0,0 +1,108 @@
+
+
+
+
+ 中山間地域直接支払申请书
+
+
+
+ 中山間地域直接支払申请书 - {{ year }}年度
+
+ {% for item in data %}
+ {{ item.chusankan.c_id }} - {{ item.chusankan.oaza }}{{ item.chusankan.aza }}
+
+
+ 大字:
+ {{ item.chusankan.oaza }}
+
+
+ 字:
+ {{ item.chusankan.aza }}
+
+
+ 地番:
+ {{ item.chusankan.chiban }}
+
+
+ 面積:
+ {{ item.chusankan.area }} ha
+
+
+ 支払金額:
+ {{ item.chusankan.payment_amount|default:"-" }} 円
+
+
+ 関連圃場数:
+ {{ item.field_count }}
+
+
+ 作付面積合計:
+ {{ item.total_area|floatformat:4 }} 反
+
+
+ {% if item.crops %}
+
+
+
+ | 作物 |
+ 品種 |
+
+
+
+ {% for crop in item.crops %}
+
+ | {{ crop.name }} |
+ {{ crop.variety }} |
+
+ {% endfor %}
+
+
+ {% endif %}
+
+ {% endfor %}
+
+
diff --git a/backend/apps/reports/templates/reports/kyosai_template.html b/backend/apps/reports/templates/reports/kyosai_template.html
new file mode 100644
index 0000000..eefb1bd
--- /dev/null
+++ b/backend/apps/reports/templates/reports/kyosai_template.html
@@ -0,0 +1,96 @@
+
+
+
+
+ 水稲共済申请书
+
+
+
+ 水稲共済申请书 - {{ year }}年度
+
+ {% for item in data %}
+ {{ item.kyosai.k_num }} - {{ item.kyosai.kanji_name }}
+
+
+ 住所:
+ {{ item.kyosai.address }}
+
+
+ 面積:
+ {{ item.kyosai.area }} ha
+
+
+ 関連圃場数:
+ {{ item.field_count }}
+
+
+ 作付面積合計:
+ {{ item.total_area|floatformat:4 }} 反
+
+
+ {% if item.crops %}
+
+
+
+ | 作物 |
+ 品種 |
+
+
+
+ {% for crop in item.crops %}
+
+ | {{ crop.name }} |
+ {{ crop.variety }} |
+
+ {% endfor %}
+
+
+ {% endif %}
+
+ {% endfor %}
+
+
diff --git a/backend/apps/reports/urls.py b/backend/apps/reports/urls.py
new file mode 100644
index 0000000..c634742
--- /dev/null
+++ b/backend/apps/reports/urls.py
@@ -0,0 +1,7 @@
+from django.urls import path
+from . import views
+
+urlpatterns = [
+ path('kyosai//', views.generate_kyosai_pdf, name='kyosai_pdf'),
+ path('chusankan//', views.generate_chusankan_pdf, name='chusankan_pdf'),
+]
diff --git a/backend/apps/reports/views.py b/backend/apps/reports/views.py
index 91ea44a..5ef7cbd 100644
--- a/backend/apps/reports/views.py
+++ b/backend/apps/reports/views.py
@@ -1,3 +1,88 @@
from django.shortcuts import render
+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
-# Create your views here.
+
+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 crop_name not in crops:
+ crops[crop_name] = {
+ 'name': crop_name,
+ 'variety': plan.variety.name,
+ '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 crop_name not in crops:
+ crops[crop_name] = {
+ 'name': crop_name,
+ 'variety': plan.variety.name,
+ '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
diff --git a/backend/keinasystem/urls.py b/backend/keinasystem/urls.py
index 0642ccb..59d7616 100644
--- a/backend/keinasystem/urls.py
+++ b/backend/keinasystem/urls.py
@@ -21,4 +21,5 @@ urlpatterns = [
path('admin/', admin.site.urls),
path('api/fields/', include('apps.fields.urls')),
path('api/plans/', include('apps.plans.urls')),
+ path('api/reports/', include('apps.reports.urls')),
]