From d52a47839d91b3d5ec09c962d7a04855ba41ea2f Mon Sep 17 00:00:00 2001 From: caoqianming Date: Fri, 8 Sep 2023 15:16:22 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0=E5=BA=93=E5=AD=98?= =?UTF-8?q?=E6=A8=A1=E5=9D=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/inm/__init__.py | 0 apps/inm/admin.py | 3 ++ apps/inm/apps.py | 6 ++++ apps/inm/migrations/0001_initial.py | 55 +++++++++++++++++++++++++++++ apps/inm/migrations/__init__.py | 0 apps/inm/models.py | 25 +++++++++++++ apps/inm/serializers.py | 20 +++++++++++ apps/inm/tests.py | 3 ++ apps/inm/urls.py | 13 +++++++ apps/inm/views.py | 39 ++++++++++++++++++++ ruff.toml | 4 ++- server/settings.py | 3 +- server/urls.py | 1 + 13 files changed, 170 insertions(+), 2 deletions(-) create mode 100644 apps/inm/__init__.py create mode 100644 apps/inm/admin.py create mode 100644 apps/inm/apps.py create mode 100644 apps/inm/migrations/0001_initial.py create mode 100644 apps/inm/migrations/__init__.py create mode 100644 apps/inm/models.py create mode 100644 apps/inm/serializers.py create mode 100644 apps/inm/tests.py create mode 100644 apps/inm/urls.py create mode 100644 apps/inm/views.py diff --git a/apps/inm/__init__.py b/apps/inm/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/apps/inm/admin.py b/apps/inm/admin.py new file mode 100644 index 00000000..8c38f3f3 --- /dev/null +++ b/apps/inm/admin.py @@ -0,0 +1,3 @@ +from django.contrib import admin + +# Register your models here. diff --git a/apps/inm/apps.py b/apps/inm/apps.py new file mode 100644 index 00000000..5d2067a9 --- /dev/null +++ b/apps/inm/apps.py @@ -0,0 +1,6 @@ +from django.apps import AppConfig + + +class InmConfig(AppConfig): + default_auto_field = 'django.db.models.BigAutoField' + name = 'apps.inm' diff --git a/apps/inm/migrations/0001_initial.py b/apps/inm/migrations/0001_initial.py new file mode 100644 index 00000000..9ede079d --- /dev/null +++ b/apps/inm/migrations/0001_initial.py @@ -0,0 +1,55 @@ +# Generated by Django 3.2.12 on 2023-09-08 07:06 + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import django.utils.timezone + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ('system', '0002_myschedule'), + ('mtm', '0008_mgroup_is_runing'), + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ] + + operations = [ + migrations.CreateModel( + name='WareHouse', + fields=[ + ('id', models.CharField(editable=False, help_text='主键ID', max_length=20, primary_key=True, serialize=False, verbose_name='主键ID')), + ('create_time', models.DateTimeField(default=django.utils.timezone.now, help_text='创建时间', verbose_name='创建时间')), + ('update_time', models.DateTimeField(auto_now=True, help_text='修改时间', verbose_name='修改时间')), + ('is_deleted', models.BooleanField(default=False, help_text='删除标记', verbose_name='删除标记')), + ('number', models.CharField(max_length=20, verbose_name='仓库编号')), + ('name', models.CharField(max_length=20, verbose_name='仓库名称')), + ('place', models.CharField(max_length=50, verbose_name='具体地点')), + ('belong_dept', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='warehouse_belong_dept', to='system.dept', verbose_name='所属部门')), + ('create_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='warehouse_create_by', to=settings.AUTH_USER_MODEL, verbose_name='创建人')), + ('update_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='warehouse_update_by', to=settings.AUTH_USER_MODEL, verbose_name='最后编辑人')), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='MaterialBatch', + fields=[ + ('id', models.CharField(editable=False, help_text='主键ID', max_length=20, primary_key=True, serialize=False, verbose_name='主键ID')), + ('create_time', models.DateTimeField(default=django.utils.timezone.now, help_text='创建时间', verbose_name='创建时间')), + ('update_time', models.DateTimeField(auto_now=True, help_text='修改时间', verbose_name='修改时间')), + ('is_deleted', models.BooleanField(default=False, help_text='删除标记', verbose_name='删除标记')), + ('batch', models.CharField(max_length=100, verbose_name='批次号')), + ('count', models.PositiveIntegerField(default=0, verbose_name='存量')), + ('expiration_date', models.DateField(blank=True, null=True, verbose_name='有效期')), + ('material', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='mtm.material', verbose_name='物料')), + ('warehouse', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='inm.warehouse', verbose_name='所在仓库')), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/apps/inm/migrations/__init__.py b/apps/inm/migrations/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/apps/inm/models.py b/apps/inm/models.py new file mode 100644 index 00000000..e611d264 --- /dev/null +++ b/apps/inm/models.py @@ -0,0 +1,25 @@ +from django.db import models +from apps.utils.models import BaseModel, CommonBModel +from apps.mtm.models import Material +# Create your models here. + +class WareHouse(CommonBModel): + """ + 仓库信息 + """ + number = models.CharField('仓库编号', max_length=20) + name = models.CharField('仓库名称', max_length=20) + place = models.CharField('具体地点', max_length=50) + + +class MaterialBatch(BaseModel): + """ + 物料批次 + """ + batch = models.CharField('批次号', max_length=100) + material = models.ForeignKey( + Material, on_delete=models.CASCADE, verbose_name='物料') + warehouse = models.ForeignKey( + WareHouse, on_delete=models.CASCADE, verbose_name='所在仓库') + count = models.PositiveIntegerField('存量', default=0) + expiration_date = models.DateField('有效期', null=True, blank=True) diff --git a/apps/inm/serializers.py b/apps/inm/serializers.py new file mode 100644 index 00000000..3938fb16 --- /dev/null +++ b/apps/inm/serializers.py @@ -0,0 +1,20 @@ +from rest_framework import serializers +from apps.utils.serializers import CustomModelSerializer +from apps.inm.models import WareHouse, MaterialBatch +from apps.utils.constants import EXCLUDE_FIELDS_DEPT, EXCLUDE_FIELDS_BASE + + +class WareHourseSerializer(CustomModelSerializer): + class Meta: + model = WareHouse + fields = '__all__' + read_only_fields = EXCLUDE_FIELDS_DEPT + + +class MaterialBatchSerializer(CustomModelSerializer): + warehouse_name = serializers.CharField(source='warehouse.name', read_only=True) + material_name = serializers.CharField(source='material.name', read_only=True) + class Meta: + model = MaterialBatch + fields = '__all__' + read_only_fields = EXCLUDE_FIELDS_BASE \ No newline at end of file diff --git a/apps/inm/tests.py b/apps/inm/tests.py new file mode 100644 index 00000000..7ce503c2 --- /dev/null +++ b/apps/inm/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/apps/inm/urls.py b/apps/inm/urls.py new file mode 100644 index 00000000..d2daaf55 --- /dev/null +++ b/apps/inm/urls.py @@ -0,0 +1,13 @@ +from django.urls import path, include +from rest_framework.routers import DefaultRouter +from apps.inm.views import (WarehouseVIewSet, MaterialBatchViewSet) + +API_BASE_URL = 'api/inm/' +HTML_BASE_URL = 'inm/' + +router = DefaultRouter() +router.register('warehouse', WarehouseVIewSet, basename='warehouse') +router.register('materialbatch', MaterialBatchViewSet, basename='materialbatch') +urlpatterns = [ + path(API_BASE_URL, include(router.urls)), +] \ No newline at end of file diff --git a/apps/inm/views.py b/apps/inm/views.py new file mode 100644 index 00000000..06c9453b --- /dev/null +++ b/apps/inm/views.py @@ -0,0 +1,39 @@ +from django.shortcuts import render +from rest_framework.mixins import ListModelMixin +from rest_framework.exceptions import ParseError + +from apps.inm.models import WareHouse, MaterialBatch +from apps.inm.serializers import MaterialBatchSerializer, WareHourseSerializer +from apps.utils.viewsets import CustomGenericViewSet, CustomModelViewSet + + +# Create your views here. +class WarehouseVIewSet(CustomModelViewSet): + """ + list: 仓库信息 + + 仓库信息 + """ + queryset = WareHouse.objects.all() + serializer_class = WareHourseSerializer + search_fields = ['name', 'number', 'place'] + ordering = ['create_time'] + + def perform_destroy(self, instance): + if MaterialBatch.objects.filter(warehouse=instance).exclude(count=0).exists(): + raise ParseError('该仓库存在物料') + instance.delete() + + +class MaterialBatchViewSet(ListModelMixin, CustomGenericViewSet): + """ + list: 物料批次 + + 物料批次 + """ + perms_map = {'get': '*'} + queryset = MaterialBatch.objects.all() + serializer_class = MaterialBatchSerializer + select_related_fields = ['warehouse', 'material'] + filterset_fields = ['warehouse', 'material'] + \ No newline at end of file diff --git a/ruff.toml b/ruff.toml index 6faf5485..f53c52bf 100644 --- a/ruff.toml +++ b/ruff.toml @@ -1,2 +1,4 @@ [tool.ruff] -line-length = 120 \ No newline at end of file +line-length = 120 +ignore-init-module-imports = true +fix = true \ No newline at end of file diff --git a/server/settings.py b/server/settings.py index b2e602ff..63c0cab1 100755 --- a/server/settings.py +++ b/server/settings.py @@ -104,7 +104,8 @@ INSTALLED_APPS = [ 'apps.wpm', 'apps.qm', 'apps.enm', - 'apps.fim' + 'apps.fim', + 'apps.inm' ] MIDDLEWARE = [ diff --git a/server/urls.py b/server/urls.py index c26af812..b283d558 100755 --- a/server/urls.py +++ b/server/urls.py @@ -61,6 +61,7 @@ urlpatterns = [ path('', include('apps.qm.urls')), path('', include('apps.enm.urls')), path('', include('apps.fim.urls')), + path('', include('apps.inm.urls')),