diff --git a/hb_client/.env.development b/hb_client/.env.development index ef83e12..003a43c 100644 --- a/hb_client/.env.development +++ b/hb_client/.env.development @@ -2,8 +2,8 @@ ENV = 'development' # base api -VUE_APP_BASE_API = 'http://127.0.0.1:8000/api' -#VUE_APP_BASE_API = 'http://47.95.0.242:2222/api' +#VUE_APP_BASE_API = 'http://127.0.0.1:8000/api' +VUE_APP_BASE_API = 'http://47.95.0.242:2222/api' # vue-cli uses the VUE_CLI_BABEL_TRANSPILE_MODULES environment variable, diff --git a/hb_client/src/api/inm.js b/hb_client/src/api/inm.js index 3258078..354861a 100644 --- a/hb_client/src/api/inm.js +++ b/hb_client/src/api/inm.js @@ -28,3 +28,32 @@ export function deleteWarehouse(id, data) { data }) } +//物料 +export function getInventoryList(query) { + return request({ + url: '/inm/inventory/', + method: 'get', + params: query + }) +} +export function createInventory(data) { + return request({ + url: '/inm/inventory/', + method: 'post', + data + }) +} +export function updateInventory(id, data) { + return request({ + url: `/inm/inventory/${id}/`, + method: 'put', + data + }) +} +export function deleteInventory(id, data) { + return request({ + url: `/inm/inventory/${id}/`, + method: 'delete', + data + }) +} diff --git a/hb_client/src/router/index.js b/hb_client/src/router/index.js index 064cec7..48d89d0 100644 --- a/hb_client/src/router/index.js +++ b/hb_client/src/router/index.js @@ -93,6 +93,14 @@ export const asyncRoutes = [ name: 'material', component: () => import('@/views/mtm/material'), meta: { title: '物料清单', icon: 'example', perms: ['vendor_manage'] } + } + , + { + path: 'material/:id', + name: 'MaterialDO', + component: () => import('@/views/mtm/materialdo.vue'), + meta: { title: '绑定检查表', perms: ['vendor_manage'] }, + hidden: true }, { path: 'process', @@ -225,12 +233,26 @@ export const asyncRoutes = [ name: 'warehouse', component: () => import('@/views/inm/warehouse'), meta: { title: '仓库', icon: 'example', perms: ['index_manage'] } + } + , + { + path: 'warehouse', + name: 'warehouse', + component: () => import('@/views/inm/warehouse'), + meta: { title: '物料库存', icon: 'example', perms: ['index_manage'] } }, { path: 'warehouse', name: 'warehouse', component: () => import('@/views/inm/warehouse'), - meta: { title: '仓库', icon: 'example', perms: ['index_manage'] } + meta: { title: '半成品库存', icon: 'example', perms: ['index_manage'] } + } + , + { + path: 'warehouse', + name: 'warehouse', + component: () => import('@/views/inm/warehouse'), + meta: { title: '成品库存', icon: 'example', perms: ['index_manage'] } } ] }, @@ -253,7 +275,7 @@ export const asyncRoutes = [ path: 'vendor', name: 'vendor', component: () => import('@/views/procurement/vendor'), - meta: { title: '供应商', icon: 'example', perms: ['vendor_manage'] } + meta: { title: '采购订单', icon: 'example', perms: ['vendor_manage'] } } ] }, diff --git a/hb_client/src/views/em/detection.vue b/hb_client/src/views/em/detection.vue index e46d5f6..89d54b0 100644 --- a/hb_client/src/views/em/detection.vue +++ b/hb_client/src/views/em/detection.vue @@ -79,6 +79,16 @@ + + + @@ -248,7 +258,7 @@ - + + + + diff --git a/hb_client/src/views/em/record.vue b/hb_client/src/views/em/record.vue index a862578..0db948c 100644 --- a/hb_client/src/views/em/record.vue +++ b/hb_client/src/views/em/record.vue @@ -198,6 +198,7 @@ export default { page: 1, page_size: 20, }, + equipmentoptions:[], state_:{ 0:'合格', 1:'准用', diff --git a/hb_client/src/views/mtm/material.vue b/hb_client/src/views/mtm/material.vue index f56d69b..3f5cc05 100644 --- a/hb_client/src/views/mtm/material.vue +++ b/hb_client/src/views/mtm/material.vue @@ -74,7 +74,11 @@ width="220px" > + + diff --git a/hb_client/src/views/mtm/step.vue b/hb_client/src/views/mtm/step.vue index 48f3c4d..3d7f00e 100644 --- a/hb_client/src/views/mtm/step.vue +++ b/hb_client/src/views/mtm/step.vue @@ -545,6 +545,7 @@ } this.getList(); }, + //新增工序 handleCreateStep() { this.step = Object.assign({}, defaultstep); this.dialogTypes = "new"; @@ -620,7 +621,7 @@ recordformLists() { this.listQueryrecordform.step=this.stepid; - + this.listQueryrecordform.type=1; getrecordformList(this.listQueryrecordform).then((response) => { if (response.data) { this.recordformList = response.data; @@ -640,6 +641,7 @@ }); }, + //新增记录表 handleCreate() { this.recordform = Object.assign({}, defaultrecordform); this.dialogType = "new"; @@ -648,6 +650,7 @@ this.$refs["Forms"].clearValidate(); }); }, + //新增字段 handlefieldCreate() { this.field_choice = ['']; diff --git a/hb_client/src/views/procurement/vendor.vue b/hb_client/src/views/procurement/vendor.vue index 9f1892e..71c5579 100644 --- a/hb_client/src/views/procurement/vendor.vue +++ b/hb_client/src/views/procurement/vendor.vue @@ -54,6 +54,9 @@ + + + @@ -114,7 +117,9 @@ - + + + + + + + @@ -51,6 +60,32 @@ /> + + + + + + + + + + @@ -168,6 +203,10 @@ export default { { value: "男", label: "男" }, { value: "女", label: "女" } ], + jobstateOptions:[ + { value: 1, label: "在职" }, + { value: 2, label: "离职" } + ], rules: { ID_number: [ diff --git a/hb_daq/default.aproj b/hb_daq/default.aproj index c3e936d..0aec0ec 100644 --- a/hb_daq/default.aproj +++ b/hb_daq/default.aproj @@ -1,5 +1,5 @@  - + diff --git a/hb_daq/main.aardio b/hb_daq/main.aardio index fe3c075..98024af 100644 --- a/hb_daq/main.aardio +++ b/hb_daq/main.aardio @@ -160,7 +160,7 @@ http.beginRequest( mainForm.serverUrl.text + "/api/em/daq/", "POST" ); var res = web.json.parse(html) if(res['code']==200){ import fsys - var theDir = fsys.createDir(mainForm.backupPath.text+"\"+number, false) + var theDir = fsys.createDir(mainForm.backupPath.text+"\\"+number, false) fsys.move(fullpath, theDir) //移动到备份文件库 mainForm.listbox.add("采集成功!") }else{ @@ -196,7 +196,7 @@ mainForm.listview.onnotify = function(id,code,ptr){ mainForm.add.oncommand = function(id,event){ -var frmChild = mainForm.loadForm("\dlg\add.aardio"); +var frmChild = mainForm.loadForm("\\dlg\\add.aardio"); frmChild.doModal(); } diff --git a/hb_server/apps/em/serializers.py b/hb_server/apps/em/serializers.py index a200114..55d0674 100644 --- a/hb_server/apps/em/serializers.py +++ b/hb_server/apps/em/serializers.py @@ -1,3 +1,4 @@ +from apps.mtm.models import Step from rest_framework import serializers from rest_framework.serializers import ModelSerializer @@ -8,6 +9,7 @@ from apps.system.serializers import OrganizationSimpleSerializer, UserSimpleSeri class EquipmentSerializer(ModelSerializer): belong_dept_ = OrganizationSimpleSerializer(source='belong_dept', read_only=True) keeper_ = UserSimpleSerializer(source='keeper', read_only=True) + step_ = serializers.SerializerMethodField() class Meta: model = Equipment fields = '__all__' @@ -18,6 +20,9 @@ class EquipmentSerializer(ModelSerializer): queryset = queryset.select_related('belong_dept','keeper') return queryset + def get_step_(self, obj): + return Step.objects.filter(equipments=obj).values('id', 'name', 'number') + class EquipmentSimpleSerializer(ModelSerializer): class Meta: model = Equipment diff --git a/hb_server/apps/hrm/migrations/0002_auto_20210924_1127.py b/hb_server/apps/hrm/migrations/0002_auto_20210924_1127.py new file mode 100644 index 0000000..89485c7 --- /dev/null +++ b/hb_server/apps/hrm/migrations/0002_auto_20210924_1127.py @@ -0,0 +1,35 @@ +# Generated by Django 3.2.6 on 2021-09-24 03:27 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('system', '0003_auto_20210812_0909'), + ('hrm', '0001_initial'), + ] + + operations = [ + migrations.AddField( + model_name='employee', + name='academic', + field=models.CharField(blank=True, max_length=50, null=True, verbose_name='学历'), + ), + migrations.AddField( + model_name='employee', + name='birthdate', + field=models.DateField(blank=True, null=True, verbose_name='出生年月'), + ), + migrations.AddField( + model_name='employee', + name='job', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='system.position', verbose_name='岗位'), + ), + migrations.AddField( + model_name='employee', + name='jobstate', + field=models.IntegerField(choices=[(1, '在职'), (2, '离职')], default=1, verbose_name='在职状态'), + ), + ] diff --git a/hb_server/apps/hrm/models.py b/hb_server/apps/hrm/models.py index adb8b44..c448e64 100644 --- a/hb_server/apps/hrm/models.py +++ b/hb_server/apps/hrm/models.py @@ -3,22 +3,31 @@ from django.contrib.auth.models import AbstractUser from django.db.models.base import Model import django.utils.timezone as timezone from django.db.models.query import QuerySet -from apps.system.models import CommonAModel, CommonBModel, Organization, User, Dict, File +from apps.system.models import CommonAModel, CommonBModel, Organization, User, Dict, File,Position from utils.model import SoftModel, BaseModel from simple_history.models import HistoricalRecords + class Employee(CommonAModel): """ 员工信息 """ + jobstate_choices = ( + (1, '在职'), + (2, '离职'), + ) user = models.OneToOneField(User, on_delete=models.CASCADE, related_name='employee_user') number = models.CharField('人员编号', max_length=50,null=True, blank=True, unique=True) photo = models.CharField('证件照', max_length=1000, null=True, blank=True) ID_number = models.CharField('身份证号', max_length=100, null=True, blank=True) gender = models.CharField('性别', max_length=10, default='男') signature = models.CharField('签名图片', max_length=200, null=True, blank=True) + birthdate = models.DateField('出生年月', null=True, blank=True) + academic = models.CharField('学历', max_length=50, null=True, blank=True) + jobstate = models.IntegerField('在职状态', choices=jobstate_choices, default=1) + job = models.ForeignKey(Position, null=True, blank=True, on_delete=models.SET_NULL, verbose_name='岗位') class Meta: verbose_name = '员工补充信息' verbose_name_plural = verbose_name diff --git a/hb_server/apps/inm/migrations/0003_auto_20210928_1702.py b/hb_server/apps/inm/migrations/0003_auto_20210928_1702.py new file mode 100644 index 0000000..b6a77da --- /dev/null +++ b/hb_server/apps/inm/migrations/0003_auto_20210928_1702.py @@ -0,0 +1,41 @@ +# Generated by Django 3.2.6 on 2021-09-28 09:02 + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import django.utils.timezone + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('inm', '0002_fifo_inventory'), + ] + + operations = [ + migrations.AlterField( + model_name='inventory', + name='count', + field=models.IntegerField(default=0, verbose_name='仓库物料存量'), + ), + migrations.CreateModel( + name='Materials', + fields=[ + ('id', models.BigAutoField(auto_created=True, 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='删除标记')), + ('count', models.IntegerField(default=0, verbose_name='存量')), + ('batch', models.CharField(blank=True, max_length=100, null=True, verbose_name='批次')), + ('effective', models.DateField(blank=True, null=True, verbose_name='有效期')), + ('create_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='materials_create_by', to=settings.AUTH_USER_MODEL, verbose_name='创建人')), + ('inventory', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='inm.inventory', verbose_name='仓库物料')), + ('update_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='materials_update_by', to=settings.AUTH_USER_MODEL, verbose_name='最后编辑人')), + ], + options={ + 'verbose_name': '库存表', + 'verbose_name_plural': '库存表', + }, + ), + ] diff --git a/hb_server/apps/inm/migrations/0004_auto_20210929_0842.py b/hb_server/apps/inm/migrations/0004_auto_20210929_0842.py new file mode 100644 index 0000000..aefebcb --- /dev/null +++ b/hb_server/apps/inm/migrations/0004_auto_20210929_0842.py @@ -0,0 +1,45 @@ +# Generated by Django 3.2.6 on 2021-09-29 00:42 + +from django.db import migrations, models +import django.db.models.deletion +import django.utils.timezone + + +class Migration(migrations.Migration): + + dependencies = [ + ('mtm', '0018_material_count'), + ('inm', '0003_auto_20210928_1702'), + ] + + operations = [ + migrations.CreateModel( + name='MaterialBatch', + fields=[ + ('id', models.BigAutoField(auto_created=True, 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='删除标记')), + ('count', models.IntegerField(default=0, verbose_name='存量')), + ('batch', models.CharField(blank=True, max_length=100, null=True, 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={ + 'verbose_name': '库存表', + 'verbose_name_plural': '库存表', + }, + ), + migrations.RemoveField( + model_name='inventory', + name='create_by', + ), + migrations.RemoveField( + model_name='inventory', + name='update_by', + ), + migrations.DeleteModel( + name='Materials', + ), + ] diff --git a/hb_server/apps/inm/models.py b/hb_server/apps/inm/models.py index fa3fc91..52a7ddc 100644 --- a/hb_server/apps/inm/models.py +++ b/hb_server/apps/inm/models.py @@ -23,18 +23,29 @@ class WareHouse(CommonAModel): def __str__(self): return self.name -class Inventory(CommonAModel): +class Inventory(BaseModel): """ - 库存表 + 库存物料 """ material = models.ForeignKey(Material, on_delete=models.CASCADE, verbose_name='物料信息') - count = models.IntegerField('数量', default=0) + count = models.IntegerField('仓库物料存量', default=0) warehouse = models.ForeignKey(WareHouse, on_delete=models.CASCADE, verbose_name='所在仓库') class Meta: verbose_name = '库存表' verbose_name_plural = verbose_name - +class MaterialBatch(BaseModel): + """ + 物料批次 + """ + material = models.ForeignKey(Material, on_delete=models.CASCADE, verbose_name='物料信息') + warehouse = models.ForeignKey(WareHouse, on_delete=models.CASCADE, verbose_name='所在仓库') + count = models.IntegerField('存量', default=0) + batch = models.CharField('批次号', max_length=100, null=True, blank=True) + expiration_date = models.DateField('有效期', null=True, blank=True) + class Meta: + verbose_name = '库存表' + verbose_name_plural = verbose_name class FIFO(CommonAModel): """ diff --git a/hb_server/apps/inm/serializers.py b/hb_server/apps/inm/serializers.py index 06607f1..808f470 100644 --- a/hb_server/apps/inm/serializers.py +++ b/hb_server/apps/inm/serializers.py @@ -1,8 +1,9 @@ from rest_framework import serializers -from apps.inm.models import WareHouse +from apps.inm.models import WareHouse,Inventory from apps.system.serializers import UserSimpleSerializer +from apps.mtm.serializers import MaterialSimpleSerializer class WareHouseSerializer(serializers. ModelSerializer): create_by_=UserSimpleSerializer('create_by', read_only=True) @@ -13,4 +14,21 @@ class WareHouseSerializer(serializers. ModelSerializer): class WareHouseCreateUpdateSerializer(serializers.ModelSerializer): class Meta: model = WareHouse - fields = ['name', 'number', 'place'] \ No newline at end of file + fields = ['name', 'number', 'place'] + +class WareHouseSimpleSerializer(serializers.ModelSerializer): + class Meta: + model = WareHouse + fields = ['name', 'number', 'place'] + +class InventorySerializer(serializers. ModelSerializer): + material_= MaterialSimpleSerializer(source='material', read_only=True) + warehouse_ = WareHouseSimpleSerializer(source='material', read_only=True) + class Meta: + model = Inventory + fields = '__all__' + +class InventoryCreateUpdateSerializer(serializers.ModelSerializer): + class Meta: + model = Inventory + fields = ['material', 'count', 'warehouse'] diff --git a/hb_server/apps/inm/urls.py b/hb_server/apps/inm/urls.py index 4faa6f3..d680958 100644 --- a/hb_server/apps/inm/urls.py +++ b/hb_server/apps/inm/urls.py @@ -1,11 +1,12 @@ from django.db.models import base from rest_framework import urlpatterns -from apps.inm.views import WarehouseViewSet +from apps.inm.views import WarehouseViewSet,InventoryViewSet from django.urls import path, include from rest_framework.routers import DefaultRouter router = DefaultRouter() router.register('warehouse', WarehouseViewSet, basename='warehouse') +router.register('inventory', InventoryViewSet, basename='inventory') urlpatterns = [ path('', include(router.urls)), ] diff --git a/hb_server/apps/inm/views.py b/hb_server/apps/inm/views.py index 62ae7ac..4c3b8c4 100644 --- a/hb_server/apps/inm/views.py +++ b/hb_server/apps/inm/views.py @@ -1,8 +1,8 @@ from django.shortcuts import render from rest_framework.viewsets import ModelViewSet -from apps.inm.models import WareHouse -from apps.inm.serializers import WareHouseSerializer, WareHouseCreateUpdateSerializer +from apps.inm.models import WareHouse,Inventory +from apps.inm.serializers import WareHouseSerializer, WareHouseCreateUpdateSerializer,InventorySerializer,InventoryCreateUpdateSerializer from apps.system.mixins import CreateUpdateModelAMixin, OptimizationMixin @@ -23,3 +23,18 @@ class WarehouseViewSet(CreateUpdateModelAMixin, ModelViewSet): if self.action in ['create', 'update']: return WareHouseCreateUpdateSerializer return WareHouseSerializer +class InventoryViewSet(CreateUpdateModelAMixin, ModelViewSet): + """ + 物料基本信息-增删改查 + """ + perms_map = {'*': '*'} + queryset = Inventory.objects.select_related('create_by').all() + serializer_class = InventorySerializer + filterset_fields = [] + ordering_fields = ['create_time'] + ordering = ['-create_time'] + + def get_serializer_class(self): + if self.action in ['create', 'update']: + return InventoryCreateUpdateSerializer + return InventorySerializer diff --git a/hb_server/apps/mtm/migrations/0017_auto_20210928_1355.py b/hb_server/apps/mtm/migrations/0017_auto_20210928_1355.py new file mode 100644 index 0000000..4c07d85 --- /dev/null +++ b/hb_server/apps/mtm/migrations/0017_auto_20210928_1355.py @@ -0,0 +1,34 @@ +# Generated by Django 3.2.6 on 2021-09-28 05:55 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('mtm', '0016_auto_20210917_0900'), + ] + + operations = [ + migrations.AddField( + model_name='recordform', + name='material', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='mtm.material', verbose_name='关联物料'), + ), + migrations.AlterField( + model_name='material', + name='processes', + field=models.JSONField(blank=True, default=list, null=True, verbose_name='工艺流程'), + ), + migrations.AlterField( + model_name='recordform', + name='step', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='mtm.step', verbose_name='关联子工序'), + ), + migrations.AlterField( + model_name='recordform', + name='type', + field=models.IntegerField(choices=[(1, '生产记录'), (2, '检验记录')], default=1, verbose_name='表格类型'), + ), + ] diff --git a/hb_server/apps/mtm/migrations/0018_material_count.py b/hb_server/apps/mtm/migrations/0018_material_count.py new file mode 100644 index 0000000..9089240 --- /dev/null +++ b/hb_server/apps/mtm/migrations/0018_material_count.py @@ -0,0 +1,18 @@ +# Generated by Django 3.2.6 on 2021-09-28 09:02 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('mtm', '0017_auto_20210928_1355'), + ] + + operations = [ + migrations.AddField( + model_name='material', + name='count', + field=models.IntegerField(default=0, verbose_name='物料总数'), + ), + ] diff --git a/hb_server/apps/mtm/models.py b/hb_server/apps/mtm/models.py index e3f77ed..6fca06f 100644 --- a/hb_server/apps/mtm/models.py +++ b/hb_server/apps/mtm/models.py @@ -29,9 +29,9 @@ class Material(CommonAModel): specification = models.CharField('型号', max_length=100, null=True, blank=True) type = models.CharField('物料类型', choices= type_choices, max_length=20, default=1) sort_str = models.CharField('排序字符', max_length=100, null=True, blank=True) - processes = models.JSONField('工艺流程', default=list, blank=True) + processes = models.JSONField('工艺流程', default=list, blank=True, null=True) unit = models.CharField('基准计量单位', choices=unit_choices, default='块', max_length=10) - + count = models.IntegerField('物料总数', default=0) class Meta: verbose_name = '物料表' verbose_name_plural = verbose_name @@ -80,11 +80,12 @@ class RecordForm(CommonAModel): """ type_choices=( (1, '生产记录'), + (2, '检验记录') ) name = models.CharField('表格名称', max_length=100, unique=True) type = models.IntegerField('表格类型', choices=type_choices, default=1) - step = models.ForeignKey(Step, verbose_name='关联子工序', on_delete=models.CASCADE) - + step = models.ForeignKey(Step, verbose_name='关联子工序', on_delete=models.CASCADE, null=True, blank=True) + material = models.ForeignKey(Material, verbose_name='关联物料', on_delete=models.CASCADE, null=True, blank=True) class Meta: verbose_name = '记录表格' verbose_name_plural = verbose_name @@ -194,3 +195,4 @@ class TechDoc(CommonAModel): class Meta: verbose_name = '技术文件' verbose_name_plural = verbose_name + \ No newline at end of file diff --git a/hb_server/apps/mtm/serializers.py b/hb_server/apps/mtm/serializers.py index 004d3d3..6a1dd98 100644 --- a/hb_server/apps/mtm/serializers.py +++ b/hb_server/apps/mtm/serializers.py @@ -1,6 +1,6 @@ -from apps.em.serializers import EquipmentSerializer, EquipmentSimpleSerializer +from apps.em.serializers import EquipmentSimpleSerializer from rest_framework import serializers -from rest_framework.exceptions import ValidationError +from rest_framework.exceptions import ParseError, ValidationError from .models import InputMaterial, Material, OutputMaterial, Process, ProductProcess, RecordForm, RecordFormField, Step, TechDoc, UsedStep from apps.system.serializers import FileSimpleSerializer, OrganizationSimpleSerializer @@ -140,6 +140,7 @@ class UsedStepListSerializer(serializers.ModelSerializer): class RecordFormSerializer(serializers.ModelSerializer): step_ = StepSimpleSerializer(source='step', read_only=True) + material_ = MaterialSimpleSerializer(source='material', read_only=True) """ 记录表格序列化 """ @@ -150,13 +151,13 @@ class RecordFormSerializer(serializers.ModelSerializer): @staticmethod def setup_eager_loading(queryset): """ Perform necessary eager loading of data. """ - queryset = queryset.select_related('step') + queryset = queryset.select_related('step', 'material') return queryset class RecordFormCreateSerializer(serializers.ModelSerializer): class Meta: model = RecordForm - fields = ['name', 'type', 'step'] + fields = ['name', 'type', 'step', 'material'] class RecordFormUpdateSerializer(serializers.ModelSerializer): class Meta: diff --git a/hb_server/apps/mtm/views.py b/hb_server/apps/mtm/views.py index 317575c..974bdba 100644 --- a/hb_server/apps/mtm/views.py +++ b/hb_server/apps/mtm/views.py @@ -147,7 +147,7 @@ class RecordFormViewSet(OptimizationMixin, CreateUpdateModelAMixin, ModelViewSet """ perms_map = {'*':'*'} queryset = RecordForm.objects.all() - filterset_fields = ['step', 'type'] + filterset_fields = ['step', 'type', 'material'] search_fields = ['name'] def get_serializer_class(self): diff --git a/hb_server/apps/pum/migrations/0002_vendor_material.py b/hb_server/apps/pum/migrations/0002_vendor_material.py new file mode 100644 index 0000000..3bc35b3 --- /dev/null +++ b/hb_server/apps/pum/migrations/0002_vendor_material.py @@ -0,0 +1,18 @@ +# Generated by Django 3.2.6 on 2021-09-24 06:25 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('pum', '0001_initial'), + ] + + operations = [ + migrations.AddField( + model_name='vendor', + name='material', + field=models.CharField(blank=True, max_length=200, null=True, verbose_name='供应的物料'), + ), + ] diff --git a/hb_server/apps/pum/models.py b/hb_server/apps/pum/models.py index bf5d5a7..a705f8a 100644 --- a/hb_server/apps/pum/models.py +++ b/hb_server/apps/pum/models.py @@ -18,6 +18,7 @@ class Vendor(CommonAModel): contact_phone = models.CharField('联系电话', max_length=11, unique=True) address = models.CharField('地址', max_length=200, null=True, blank=True) description = models.CharField('描述', max_length=200, blank=True, null=True) + material = models.CharField('供应的物料', max_length=200, blank=True, null=True) class Meta: verbose_name = '供应商信息' verbose_name_plural = verbose_name diff --git a/hb_server/apps/wf/migrations/0010_alter_ticketflow_transition.py b/hb_server/apps/wf/migrations/0010_alter_ticketflow_transition.py new file mode 100644 index 0000000..82a9ce8 --- /dev/null +++ b/hb_server/apps/wf/migrations/0010_alter_ticketflow_transition.py @@ -0,0 +1,19 @@ +# Generated by Django 3.2.6 on 2021-09-29 00:42 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('wf', '0009_ticketflow_participant_type'), + ] + + operations = [ + migrations.AlterField( + model_name='ticketflow', + name='transition', + field=models.ForeignKey(blank=True, help_text='与worklow.Transition关联, 为0时表示认为干预的操作', null=True, on_delete=django.db.models.deletion.CASCADE, to='wf.transition', verbose_name='流转id'), + ), + ] diff --git a/hb_server/apps/wf/models.py b/hb_server/apps/wf/models.py index 740928c..c4cfc29 100644 --- a/hb_server/apps/wf/models.py +++ b/hb_server/apps/wf/models.py @@ -169,7 +169,7 @@ class TicketFlow(BaseModel): 工单流转日志 """ ticket = models.ForeignKey(Ticket, on_delete=models.CASCADE, verbose_name='关联工单') - transition = models.ForeignKey(Transition, verbose_name='流转id', help_text='与worklow.Transition关联, 为0时表示认为干预的操作', on_delete=models.CASCADE) + transition = models.ForeignKey(Transition, verbose_name='流转id', help_text='与worklow.Transition关联, 为0时表示认为干预的操作', on_delete=models.CASCADE, null=True, blank=True) suggestion = models.CharField('处理意见', max_length=10000, default='', blank=True) participant_type = models.IntegerField('处理人类型', default=0, help_text='0.无处理人,1.个人,2.多人', choices=State.type2_choices) participant = models.ForeignKey(User, verbose_name='处理人', on_delete=models.SET_NULL, null=True, blank=True) diff --git a/hb_server/apps/wf/serializers.py b/hb_server/apps/wf/serializers.py index cddfaff..e674c31 100644 --- a/hb_server/apps/wf/serializers.py +++ b/hb_server/apps/wf/serializers.py @@ -23,7 +23,7 @@ class WorkflowSimpleSerializer(serializers.ModelSerializer): class StateSimpleSerializer(serializers.ModelSerializer): class Meta: model = State - fields = ['id', 'name'] + fields = ['id', 'name', 'type'] class TransitionSerializer(serializers.ModelSerializer): source_state_ = StateSimpleSerializer(source='source_state', read_only=True) diff --git a/hb_server/apps/wf/services.py b/hb_server/apps/wf/services.py index cd691d9..bee8799 100644 --- a/hb_server/apps/wf/services.py +++ b/hb_server/apps/wf/services.py @@ -168,8 +168,13 @@ class WfService(object): if user.id not in participant: return dict(permission=False, msg="非当前处理人") current_participant_count = len(participant) - if current_participant_count >1 and state.distribute_type == State.STATE_DISTRIBUTE_TYPE_ACTIVE: - return dict(permission=False, msg="需要先接单再处理") + if current_participant_count == 1: + if [user.id] != participant: + return dict(permission=False, msg="非当前处理人") + elif current_participant_count >1 and state.distribute_type == State.STATE_DISTRIBUTE_TYPE_ACTIVE: + if user.id not in participant: + return dict(permission=False, msg="非当前处理人") + return dict(permission=False, msg="需要先接单再处理", need_accept=True) if ticket.in_add_node: return dict(permission=False, msg="工单当前处于加签中,请加签完成后操作") return dict(permission=True, msg="") diff --git a/hb_server/apps/wf/views.py b/hb_server/apps/wf/views.py index 3740fec..9df0518 100644 --- a/hb_server/apps/wf/views.py +++ b/hb_server/apps/wf/views.py @@ -247,6 +247,25 @@ class TicketViewSet(OptimizationMixin, CreateUpdateCustomMixin, CreateModelMixin transitions = WfService.get_ticket_transitions(ticket) return Response(TransitionSerializer(instance=transitions, many=True).data) + @action(methods=['post'], detail=True, perms_map={'post':'*'}) + def accpet(self, request, pk=None): + """ + 接单,当工单当前处理人实际为多个人时(角色、部门、多人都有可能, 注意角色和部门有可能实际只有一人) + """ + ticket = self.get_object() + result = WfService.ticket_handle_permission_check(ticket, request.user) + if result.get('need_accept', False): + ticket.participant_type = State.PARTICIPANT_TYPE_PERSONAL + ticket.participant = request.user.id + ticket.save() + # 接单日志 + # 更新工单流转记录 + TicketFlow.objects.create(ticket=ticket, state=ticket.state, ticket_data=WfService.get_ticket_all_field_value(ticket), + suggestion='接单处理', participant_type=State.PARTICIPANT_TYPE_PERSONAL, + participant=request.user, transition=None) + return Response() + else: + raise APIException('无需接单') class TicketFlowViewSet(ListModelMixin, RetrieveModelMixin, GenericViewSet): """