施肥散布実績機能を実装し運搬・作業記録・在庫連携を追加
This commit is contained in:
1
backend/apps/workrecords/__init__.py
Normal file
1
backend/apps/workrecords/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
|
||||
11
backend/apps/workrecords/admin.py
Normal file
11
backend/apps/workrecords/admin.py
Normal file
@@ -0,0 +1,11 @@
|
||||
from django.contrib import admin
|
||||
|
||||
from .models import WorkRecord
|
||||
|
||||
|
||||
@admin.register(WorkRecord)
|
||||
class WorkRecordAdmin(admin.ModelAdmin):
|
||||
list_display = ['work_date', 'work_type', 'title', 'year', 'auto_created']
|
||||
list_filter = ['work_type', 'year', 'auto_created']
|
||||
search_fields = ['title']
|
||||
|
||||
8
backend/apps/workrecords/apps.py
Normal file
8
backend/apps/workrecords/apps.py
Normal file
@@ -0,0 +1,8 @@
|
||||
from django.apps import AppConfig
|
||||
|
||||
|
||||
class WorkrecordsConfig(AppConfig):
|
||||
default_auto_field = 'django.db.models.BigAutoField'
|
||||
name = 'apps.workrecords'
|
||||
verbose_name = '作業記録'
|
||||
|
||||
36
backend/apps/workrecords/migrations/0001_initial.py
Normal file
36
backend/apps/workrecords/migrations/0001_initial.py
Normal file
@@ -0,0 +1,36 @@
|
||||
# Generated by Django 5.0 on 2026-03-17 08:49
|
||||
|
||||
import django.db.models.deletion
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
initial = True
|
||||
|
||||
dependencies = [
|
||||
('fertilizer', '0008_spreadingsession_fertilizationentry_actual_bags_and_more'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='WorkRecord',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('work_date', models.DateField(verbose_name='作業日')),
|
||||
('work_type', models.CharField(choices=[('fertilizer_delivery', '肥料運搬'), ('fertilizer_spreading', '肥料散布')], max_length=40, verbose_name='作業種別')),
|
||||
('title', models.CharField(max_length=200, verbose_name='タイトル')),
|
||||
('year', models.IntegerField(verbose_name='年度')),
|
||||
('auto_created', models.BooleanField(default=True, verbose_name='自動生成')),
|
||||
('created_at', models.DateTimeField(auto_now_add=True)),
|
||||
('updated_at', models.DateTimeField(auto_now=True)),
|
||||
('delivery_trip', models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='work_record', to='fertilizer.deliverytrip', verbose_name='運搬回')),
|
||||
('spreading_session', models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='work_record', to='fertilizer.spreadingsession', verbose_name='散布実績')),
|
||||
],
|
||||
options={
|
||||
'verbose_name': '作業記録',
|
||||
'verbose_name_plural': '作業記録',
|
||||
'ordering': ['-work_date', '-updated_at', '-id'],
|
||||
},
|
||||
),
|
||||
]
|
||||
1
backend/apps/workrecords/migrations/__init__.py
Normal file
1
backend/apps/workrecords/migrations/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
|
||||
44
backend/apps/workrecords/models.py
Normal file
44
backend/apps/workrecords/models.py
Normal file
@@ -0,0 +1,44 @@
|
||||
from django.db import models
|
||||
|
||||
|
||||
class WorkRecord(models.Model):
|
||||
class WorkType(models.TextChoices):
|
||||
FERTILIZER_DELIVERY = 'fertilizer_delivery', '肥料運搬'
|
||||
FERTILIZER_SPREADING = 'fertilizer_spreading', '肥料散布'
|
||||
|
||||
work_date = models.DateField(verbose_name='作業日')
|
||||
work_type = models.CharField(
|
||||
max_length=40,
|
||||
choices=WorkType.choices,
|
||||
verbose_name='作業種別',
|
||||
)
|
||||
title = models.CharField(max_length=200, verbose_name='タイトル')
|
||||
year = models.IntegerField(verbose_name='年度')
|
||||
auto_created = models.BooleanField(default=True, verbose_name='自動生成')
|
||||
delivery_trip = models.OneToOneField(
|
||||
'fertilizer.DeliveryTrip',
|
||||
on_delete=models.CASCADE,
|
||||
null=True,
|
||||
blank=True,
|
||||
related_name='work_record',
|
||||
verbose_name='運搬回',
|
||||
)
|
||||
spreading_session = models.OneToOneField(
|
||||
'fertilizer.SpreadingSession',
|
||||
on_delete=models.CASCADE,
|
||||
null=True,
|
||||
blank=True,
|
||||
related_name='work_record',
|
||||
verbose_name='散布実績',
|
||||
)
|
||||
created_at = models.DateTimeField(auto_now_add=True)
|
||||
updated_at = models.DateTimeField(auto_now=True)
|
||||
|
||||
class Meta:
|
||||
ordering = ['-work_date', '-updated_at', '-id']
|
||||
verbose_name = '作業記録'
|
||||
verbose_name_plural = '作業記録'
|
||||
|
||||
def __str__(self):
|
||||
return f'{self.work_date} {self.get_work_type_display()}'
|
||||
|
||||
38
backend/apps/workrecords/serializers.py
Normal file
38
backend/apps/workrecords/serializers.py
Normal file
@@ -0,0 +1,38 @@
|
||||
from rest_framework import serializers
|
||||
|
||||
from .models import WorkRecord
|
||||
|
||||
|
||||
class WorkRecordSerializer(serializers.ModelSerializer):
|
||||
work_type_display = serializers.CharField(source='get_work_type_display', read_only=True)
|
||||
delivery_plan_id = serializers.SerializerMethodField()
|
||||
delivery_plan_name = serializers.SerializerMethodField()
|
||||
|
||||
class Meta:
|
||||
model = WorkRecord
|
||||
fields = [
|
||||
'id',
|
||||
'work_date',
|
||||
'work_type',
|
||||
'work_type_display',
|
||||
'title',
|
||||
'year',
|
||||
'auto_created',
|
||||
'delivery_trip',
|
||||
'delivery_plan_id',
|
||||
'delivery_plan_name',
|
||||
'spreading_session',
|
||||
'created_at',
|
||||
'updated_at',
|
||||
]
|
||||
|
||||
def get_delivery_plan_id(self, obj):
|
||||
if obj.delivery_trip_id:
|
||||
return obj.delivery_trip.delivery_plan_id
|
||||
return None
|
||||
|
||||
def get_delivery_plan_name(self, obj):
|
||||
if obj.delivery_trip_id:
|
||||
return obj.delivery_trip.delivery_plan.name
|
||||
return None
|
||||
|
||||
33
backend/apps/workrecords/services.py
Normal file
33
backend/apps/workrecords/services.py
Normal file
@@ -0,0 +1,33 @@
|
||||
from .models import WorkRecord
|
||||
|
||||
|
||||
def sync_delivery_work_record(trip):
|
||||
if trip.date is None:
|
||||
WorkRecord.objects.filter(delivery_trip=trip).delete()
|
||||
return
|
||||
|
||||
WorkRecord.objects.update_or_create(
|
||||
delivery_trip=trip,
|
||||
defaults={
|
||||
'work_date': trip.date,
|
||||
'work_type': WorkRecord.WorkType.FERTILIZER_DELIVERY,
|
||||
'title': f'肥料運搬: {trip.delivery_plan.name} {trip.order + 1}回目',
|
||||
'year': trip.delivery_plan.year,
|
||||
'auto_created': True,
|
||||
'spreading_session': None,
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
def sync_spreading_work_record(session):
|
||||
WorkRecord.objects.update_or_create(
|
||||
spreading_session=session,
|
||||
defaults={
|
||||
'work_date': session.date,
|
||||
'work_type': WorkRecord.WorkType.FERTILIZER_SPREADING,
|
||||
'title': f'肥料散布: {session.name.strip() or session.date}',
|
||||
'year': session.year,
|
||||
'auto_created': True,
|
||||
'delivery_trip': None,
|
||||
},
|
||||
)
|
||||
12
backend/apps/workrecords/urls.py
Normal file
12
backend/apps/workrecords/urls.py
Normal file
@@ -0,0 +1,12 @@
|
||||
from django.urls import include, path
|
||||
from rest_framework.routers import DefaultRouter
|
||||
|
||||
from .views import WorkRecordViewSet
|
||||
|
||||
router = DefaultRouter()
|
||||
router.register(r'', WorkRecordViewSet, basename='workrecord')
|
||||
|
||||
urlpatterns = [
|
||||
path('', include(router.urls)),
|
||||
]
|
||||
|
||||
22
backend/apps/workrecords/views.py
Normal file
22
backend/apps/workrecords/views.py
Normal file
@@ -0,0 +1,22 @@
|
||||
from rest_framework import viewsets
|
||||
from rest_framework.permissions import IsAuthenticated
|
||||
|
||||
from .models import WorkRecord
|
||||
from .serializers import WorkRecordSerializer
|
||||
|
||||
|
||||
class WorkRecordViewSet(viewsets.ReadOnlyModelViewSet):
|
||||
serializer_class = WorkRecordSerializer
|
||||
permission_classes = [IsAuthenticated]
|
||||
|
||||
def get_queryset(self):
|
||||
queryset = WorkRecord.objects.select_related(
|
||||
'delivery_trip',
|
||||
'delivery_trip__delivery_plan',
|
||||
'spreading_session',
|
||||
)
|
||||
year = self.request.query_params.get('year')
|
||||
if year:
|
||||
queryset = queryset.filter(year=year)
|
||||
return queryset
|
||||
|
||||
Reference in New Issue
Block a user