import pandas as pd from django.db import models as django_models from django.http import JsonResponse from django.views.decorators.csrf import csrf_exempt from django.views.decorators.http import require_http_methods from rest_framework import viewsets, permissions, filters from rest_framework.decorators import action from .models import OfficialKyosaiField, OfficialChusankanField, Field from .serializers import FieldSerializer class FieldViewSet(viewsets.ModelViewSet): queryset = Field.objects.all().order_by( django_models.functions.Coalesce('group_name', django_models.Value('')), 'display_order', 'id' ) serializer_class = FieldSerializer permission_classes = [permissions.IsAuthenticated] filter_backends = [filters.OrderingFilter] ordering_fields = ['group_name', 'display_order', 'id', 'area_tan'] @csrf_exempt @require_http_methods(["POST"]) def import_kyosai_master(request): if 'file' not in request.FILES: return JsonResponse({'error': 'No file uploaded'}, status=400) ods_file = request.FILES['file'] try: df = pd.read_excel(ods_file, engine='odf') df.columns = df.columns.str.strip() created_count = 0 updated_count = 0 for _, row in df.iterrows(): k_num = str(row.get('耕地番号', '')).strip() if pd.notna(row.get('耕地番号')) else '' s_num = str(row.get('分筆番号', '')).strip() if pd.notna(row.get('分筆番号')) else '' if not k_num: continue defaults = { 'address': str(row.get('地名 地番', '')).strip() if pd.notna(row.get('地名 地番')) else '', 'kanji_name': str(row.get('漢字地名', '')).strip() if pd.notna(row.get('漢字地名')) else '', 'area': int(float(row.get('本地面積(m2)', 0))) if pd.notna(row.get('本地面積(m2)')) else 0, } obj, created = OfficialKyosaiField.objects.update_or_create( k_num=k_num, s_num=s_num, defaults=defaults ) if created: created_count += 1 else: updated_count += 1 return JsonResponse({ 'success': True, 'created': created_count, 'updated': updated_count, 'message': f'共済マスタ: {created_count}件作成, {updated_count}件更新' }) except Exception as e: return JsonResponse({'error': str(e)}, status=500) @csrf_exempt @require_http_methods(["POST"]) def import_yoshida_fields(request): if 'file' not in request.FILES: return JsonResponse({'error': 'No file uploaded'}, status=400) ods_file = request.FILES['file'] try: df = pd.read_excel(ods_file, engine='odf') df.columns = df.columns.str.strip() created_count = 0 updated_count = 0 def clean_int_str(val): if pd.isna(val): return None s = str(val).strip() if not s: return None if s.endswith('.0'): s = s[:-2] return s for _, row in df.iterrows(): name = str(row.get('名称', '')).strip() if pd.notna(row.get('名称')) else '' if not name: continue raw_kyosai_k = clean_int_str(row.get('細目_耕地番号')) raw_kyosai_s = clean_int_str(row.get('細目_分筆番号')) raw_chusankan_str = clean_int_str(row.get('中山間_ID')) raw_chusankan_ids = [] if raw_chusankan_str: raw_chusankan_ids = [cid.strip() for cid in raw_chusankan_str.split(',') if cid.strip()] area_tan = float(row.get('面積(反)', 0)) if pd.notna(row.get('面積(反)')) else 0 area_m2 = int(area_tan * 1000) if area_tan else 0 defaults = { 'address': str(row.get('住所', '')).strip() if pd.notna(row.get('住所')) else '', 'area_tan': area_tan, 'area_m2': area_m2, 'owner_name': str(row.get('地主', '')).strip() if pd.notna(row.get('地主')) else '', 'raw_kyosai_k_num': raw_kyosai_k, 'raw_kyosai_s_num': raw_kyosai_s, 'raw_chusankan_id': raw_chusankan_str, } field, created = Field.objects.update_or_create( name=name, defaults=defaults ) if created: created_count += 1 else: updated_count += 1 if raw_kyosai_k and raw_kyosai_s: try: kyosai_record = OfficialKyosaiField.objects.get(k_num=raw_kyosai_k, s_num=raw_kyosai_s) field.kyosai_fields.add(kyosai_record) except OfficialKyosaiField.DoesNotExist: pass except OfficialKyosaiField.MultipleObjectsReturned: pass for cid in raw_chusankan_ids: if not cid: continue try: chusankan_record = OfficialChusankanField.objects.get(c_id=cid) field.chusankan_fields.add(chusankan_record) except OfficialChusankanField.DoesNotExist: pass return JsonResponse({ 'success': True, 'created': created_count, 'updated': updated_count, 'message': f'実圃場: {created_count}件作成, {updated_count}件更新' }) except Exception as e: return JsonResponse({'error': str(e)}, status=500) @csrf_exempt @require_http_methods(["POST"]) def import_chusankan_master(request): if 'file' not in request.FILES: return JsonResponse({'error': 'No file uploaded'}, status=400) ods_file = request.FILES['file'] try: df = pd.read_excel(ods_file, engine='odf') df.columns = df.columns.str.strip() created_count = 0 updated_count = 0 for _, row in df.iterrows(): raw_id = row.get('ID') c_id = str(raw_id).strip() if pd.notna(raw_id) else '' if not c_id: continue if not any(char.isdigit() for char in c_id): continue try: payment_amount_val = row.get('交付金額') if pd.notna(payment_amount_val): payment_amount = int(payment_amount_val) else: payment_amount = None except (ValueError, TypeError): payment_amount = None defaults = { 'oaza': str(row.get('大字', '')).strip() if pd.notna(row.get('大字')) else '', 'aza': str(row.get('字', '')).strip() if pd.notna(row.get('字')) else '', 'chiban': str(row.get('地番', '')).strip() if pd.notna(row.get('地番')) else '', 'area': int(float(row.get('農地面積', 0))) if pd.notna(row.get('農地面積')) else 0, 'payment_amount': payment_amount, } obj, created = OfficialChusankanField.objects.update_or_create( c_id=c_id, defaults=defaults ) if created: created_count += 1 else: updated_count += 1 return JsonResponse({ 'success': True, 'created': created_count, 'updated': updated_count, 'message': f'中山間マスタ: {created_count}件作成, {updated_count}件更新' }) except Exception as e: return JsonResponse({'error': str(e)}, status=500)