diff --git a/hb_client/src/api/wpm.js b/hb_client/src/api/wpm.js
index 5f6d562..0c16a1c 100644
--- a/hb_client/src/api/wpm.js
+++ b/hb_client/src/api/wpm.js
@@ -298,11 +298,11 @@ export function testInit(data) {
}
//不合格半成品报废
-export function scrap(id) {
+export function scrap(id,data) {
return request({
url: `/wpm/wproduct/${id}/scrap/`,
method: 'post',
-
+ data
})
}
diff --git a/hb_client/src/views/wpm/need.vue b/hb_client/src/views/wpm/need.vue
index 9c3bd3c..6eda955 100644
--- a/hb_client/src/views/wpm/need.vue
+++ b/hb_client/src/views/wpm/need.vue
@@ -43,6 +43,11 @@
@click="checkRecord(scope,'1')"
>检验记录
+ 报废
+
@@ -53,6 +58,32 @@
:limit.sync="listQuery.page_size"
@pagination="getList"
/>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -594,6 +625,7 @@
data() {
return {
testitem: defaultetestitem,
+ formbcp:{},
form: {remark: "", warehouse: ""},
wproductList: {
count: 0,
@@ -659,6 +691,12 @@
label: "不合格",
},
],
+ scrapreason: [
+ { lable: "气泡", value: 10 },
+ { lable: "破点", value: 20 },
+ { lable: "划伤", value: 30 },
+ { lable: "其他", value: 40 },
+ ],
recordList: [],
options: [],
listLoading: true,
@@ -674,6 +712,7 @@
page: 0,
},
recordVisible:false,
+ dialogFormVisiblebcp:false,
innerIndex:null,
origintest:null,
mutipID: [],
@@ -716,6 +755,25 @@
this.listLoading = false;
});
},
+ //待检半成品报废
+ handleScrapbcp(scope){
+ this.dialogFormVisiblebcp=true;
+ this.bcpbf=scope.row.id;
+
+ },
+ //确定报废半成品
+ scrapesubmit(){
+
+ console.log(this.formbcp);
+ scrap(this.bcpbf,this.formbcp).then((response) => {
+ if (response.data) {
+ this.$message.success("该半成品已报废!");
+ this.dialogFormVisiblebcp=false;
+ this.getList();
+ }
+
+ });
+ },
//复检半成品列表
getList2() {
this.listQuery2.act_state = 6;
diff --git a/hb_client/src/views/wpm/operation.vue b/hb_client/src/views/wpm/operation.vue
index b627aff..684e367 100644
--- a/hb_client/src/views/wpm/operation.vue
+++ b/hb_client/src/views/wpm/operation.vue
@@ -128,7 +128,7 @@ export default {
watch: {},
created() {
this.id = this.$route.params.id;
- this. getProcessList()
+ this.getProcessList()
},
methods: {
@@ -147,19 +147,23 @@ handleoperation(scope)
});
},
+getList(){
+ getoperationList(this.listQuery).then((response) => {
+ if (response.data) {
+ this.operationList = response.data;
+ }
+
+ });
+},
//选项卡切换
handleClick(tab) {
this.process = tab.name;
this.listQuery.step__process = tab.name;
- this.steps = [];
- getoperationList(this.listQuery).then((response) => {
- if (response.data) {
- this.operationList = response.data;
- }
- this.listLoading = false;
- });
+ this.getList();
+
},
+
//操作记录删除
handleDelete(scope) {
this.$confirm("确认该操作删除?", "警告", {
diff --git a/hb_client/src/views/wpm/worktask.vue b/hb_client/src/views/wpm/worktask.vue
index 22ed361..d6438a9 100644
--- a/hb_client/src/views/wpm/worktask.vue
+++ b/hb_client/src/views/wpm/worktask.vue
@@ -18,20 +18,22 @@
@current-change="handleCurrentChange"
>
-
-
+
+
+ {{ scope.row.number }}
+
+
{{
- scope.row.number
+ scope.row.product_.name
}}
-
- {{ scope.row.product_.name }}
-
-
- {{ scope.row.product_.specification }}
-
-
- {{
+
+ {{
+ scope.row.product_.specification
+ }}
+
+
+ {{
scope.row.main_product_.name
}}
@@ -66,10 +68,8 @@
-
- {{
- state_[scope.row.state]
- }}
+ {{ state_[scope.row.state] }}
@@ -77,12 +77,10 @@
已领料
-
+
{{
- scope.row.main_count
- }}/{{ scope.row.main_count_real }}/{{
+ >{{ scope.row.main_count }}/{{ scope.row.main_count_real }}/{{
scope.row.main_count_ok
}}
@@ -90,13 +88,19 @@
- 领料
- 继续领料
- 领半成品
@@ -111,12 +115,11 @@
/>
-
半成品
- 显示全部
+ 报废
+
-
- {{ scope.row.subproduction_plan_.number}}
+
+ {{
+ scope.row.subproduction_plan_.number
+ }}
@@ -162,12 +175,11 @@
scope.row.step_.name
}}
-
+
{{
- actstate_[scope.row.act_state]
+ actstate_[scope.row.act_state]
}}
-
{{
@@ -175,7 +187,11 @@
}}
+
+
+
+
@@ -191,7 +207,7 @@
max-height="300"
>
-
+
{{
scope.row.subproduction_plan_.number
}}
@@ -218,48 +234,74 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 领半成品
+
+
+
+
+
- >
-
-
- 领半成品
-
-
-
-
-
-
-
-
-
-
+
-
+
-
+
{{ scope.row.number }}
-
-
+
{{ scope.row.material_.name }}
-
-
- {{ scope.row.subproduction_plan }}
+
+
+ {{
+ scope.row.subproduction_plan
+ }}
-
+
{{ scope.row.remark }}
-
-
-
-
-
+
+
-
-
+
生产所需领料表
-
+
@@ -330,17 +379,25 @@
>
-
-
+
-
+
-
+
-
-
- 选择半成品
-
-
+
+
+ 选择半成品
+
+
-
-
+
-
+
{{ scope.row.number }}
@@ -393,21 +452,21 @@
{{ scope.row.batch }}
-
+
{{ scope.row.material_.name }}
-
-
- {{ scope.row.warehouse_.name }}
-
-
+
+ {{
+ scope.row.warehouse_.name
+ }}
+
-
-
+
+
消耗物料表
-
- 产出物料表
- 确认
+
\ No newline at end of file
diff --git a/hb_server/apps/wf/models.py b/hb_server/apps/wf/models.py
index 0aebb03..94c9c44 100644
--- a/hb_server/apps/wf/models.py
+++ b/hb_server/apps/wf/models.py
@@ -19,7 +19,7 @@ class Workflow(CommonAModel):
view_permission_check = models.BooleanField('查看权限校验', default=True, help_text='开启后,只允许工单的关联人(创建人、曾经的处理人)有权限查看工单')
limit_expression = models.JSONField('限制表达式', default=dict, blank=True, help_text='限制周期({"period":24} 24小时), 限制次数({"count":1}在限制周期内只允许提交1次), 限制级别({"level":1} 针对(1单个用户 2全局)限制周期限制次数,默认特定用户);允许特定人员提交({"allow_persons":"zhangsan,lisi"}只允许张三提交工单,{"allow_depts":"1,2"}只允许部门id为1和2的用户提交工单,{"allow_roles":"1,2"}只允许角色id为1和2的用户提交工单)')
display_form_str = models.JSONField('展现表单字段', default=list, blank=True, help_text='默认"[]",用于用户只有对应工单查看权限时显示哪些字段,field_key的list的json,如["days","sn"],内置特殊字段participant_info.participant_name:当前处理人信息(部门名称、角色名称),state.state_name:当前状态的状态名,workflow.workflow_name:工作流名称')
- title_template = models.CharField('标题模板', max_length=50, default='你有一个待办工单:{title}', null=True, blank=True, help_text='工单字段的值可以作为参数写到模板中,格式如:你有一个待办工单:{title}')
+ title_template = models.CharField('标题模板', max_length=50, default='{title}', null=True, blank=True, help_text='工单字段的值可以作为参数写到模板中,格式如:你有一个待办工单:{title}')
content_template = models.CharField('内容模板', max_length=1000, default='标题:{title}, 创建时间:{create_time}', null=True, blank=True, help_text='工单字段的值可以作为参数写到模板中,格式如:标题:{title}, 创建时间:{create_time}')
class State(CommonAModel):
diff --git a/hb_server/apps/wf/scripts.py b/hb_server/apps/wf/scripts.py
index 3ce706f..cbb7560 100644
--- a/hb_server/apps/wf/scripts.py
+++ b/hb_server/apps/wf/scripts.py
@@ -4,7 +4,9 @@ from apps.wpm.models import WProduct
class GetParticipants:
-
+ """
+ 获取处理人脚本
+ """
all_funcs = [
{'func':'get_create_by', 'name':'获取工单创建人'}
]
@@ -20,8 +22,11 @@ class GetParticipants:
return participant
class HandleScripts:
+ """
+ 任务处理脚本
+ """
all_funcs = [
- {'func': 'handle_wproduct', 'name':'处理不合格品'}
+ {'func': 'handle_something', 'name':'处理一些工作'}
]
@@ -42,32 +47,11 @@ class HandleScripts:
return ticket
@classmethod
- def handle_wproduct(cls, ticket:Ticket):
- """处理不合格品"""
- # 任务处理
+ def handle_something(cls, ticket:Ticket):
+ """处理一些工作"""
+ # 任务处理代码区
- ticket_data = ticket.ticket_data
- wt = ticket.wt_ticket
- wp = wt.wproduct
- if 'shenli2' in ticket_data and ticket_data['shenli2']:
- wt.decision = ticket_data['shenli2']
- if ticket_data['shenli2'] in ['返工', '返修']:
- pass
- elif ticket_data['shenli2'] in ['让步接收']:
- wp.act_state = WProduct.WPR_ACT_STATE_OK
- elif 'shenli1' in ticket_data and ticket_data['shenli1']:
- wp.decision = ticket_data['shenli1']
- if ticket_data['shenli1'] in ['返工', '返修']:
- pass
- elif ticket_data['shenli1'] in ['让步接收']:
- wp.act_state = WProduct.WPR_ACT_STATE_OK
- wt.save()
- wp.save()
# 调用自动流转
- ticket = cls.to_next(ticket=ticket, by_task=True, script_str= 'handle_wproduct')
- if ticket.act_state == Ticket.TICKET_ACT_STATE_FINISH:
- # 如果工单完成
- wp.ticket = None
- wp.save()
+ ticket = cls.to_next(ticket=ticket, by_task=True, script_str= 'handle_something')
diff --git a/hb_server/apps/wf/serializers.py b/hb_server/apps/wf/serializers.py
index e7987ec..de756fe 100644
--- a/hb_server/apps/wf/serializers.py
+++ b/hb_server/apps/wf/serializers.py
@@ -51,6 +51,7 @@ class TicketSimpleSerializer(serializers.ModelSerializer):
class TicketCreateSerializer(serializers.ModelSerializer):
transition = serializers.PrimaryKeyRelatedField(queryset=Transition.objects.all(), write_only=True)
+ title = serializers.CharField(allow_blank=True, required=False)
class Meta:
model=Ticket
fields=['title','workflow', 'ticket_data', 'transition']
diff --git a/hb_server/apps/wf/services.py b/hb_server/apps/wf/services.py
index beb9724..5d486c1 100644
--- a/hb_server/apps/wf/services.py
+++ b/hb_server/apps/wf/services.py
@@ -273,7 +273,7 @@ class WfService(object):
# 校验表单必填项目
if transition.field_require_check or not created:
for key, value in ticket.state.state_fields.items():
- if value == State.STATE_FIELD_REQUIRED:
+ if int(value) == State.STATE_FIELD_REQUIRED:
if key not in new_ticket_data or not new_ticket_data[key]:
raise APIException('字段{}必填'.format(key))
diff --git a/hb_server/apps/wf/views.py b/hb_server/apps/wf/views.py
index 7dfa9c2..2f9b092 100644
--- a/hb_server/apps/wf/views.py
+++ b/hb_server/apps/wf/views.py
@@ -64,7 +64,7 @@ class WorkflowViewSet(CreateUpdateModelAMixin, ModelViewSet):
工作流下的自定义字段
"""
wf = self.get_object()
- serializer = self.serializer_class(instance=CustomField.objects.filter(workflow=wf), many=True)
+ serializer = self.serializer_class(instance=CustomField.objects.filter(workflow=wf, is_deleted=False).order_by('sort'), many=True)
return Response(serializer.data)
@action(methods=['get'], detail=True, perms_map={'get':'workflow_init'})
@@ -132,10 +132,10 @@ class TicketViewSet(OptimizationMixin, CreateUpdateCustomMixin, CreateModelMixin
return TicketDetailSerializer
return super().get_serializer_class()
- def get_queryset(self):
- if self.action=='list' and (not self.request.query_params.get('category', None)):
+ def filter_queryset(self, queryset):
+ if not self.request.query_params.get('category', None):
raise APIException('请指定查询分类')
- return super().get_queryset()
+ return super().filter_queryset(queryset)
@transaction.atomic
def create(self, request, *args, **kwargs):
@@ -154,11 +154,11 @@ class TicketViewSet(OptimizationMixin, CreateUpdateCustomMixin, CreateModelMixin
# 校验必填项
if transition.field_require_check:
for key, value in start_state.state_fields.items():
- if value == State.STATE_FIELD_REQUIRED:
+ if int(value) == State.STATE_FIELD_REQUIRED:
if key not in ticket_data and not ticket_data[key]:
raise APIException('字段{}必填'.format(key))
save_ticket_data[key] = ticket_data[key]
- elif value == State.STATE_FIELD_OPTIONAL:
+ elif int(value) == State.STATE_FIELD_OPTIONAL:
save_ticket_data[key] = ticket_data[key]
ticket = serializer.save(state=start_state,
@@ -205,7 +205,7 @@ class TicketViewSet(OptimizationMixin, CreateUpdateCustomMixin, CreateModelMixin
vdata = serializer.validated_data
new_ticket_data = ticket.ticket_data
new_ticket_data.update(**vdata['ticket_data'])
-
+
ticket = WfService.handle_ticket(ticket=ticket, transition=vdata['transition'],
new_ticket_data=new_ticket_data, handler=request.user, suggestion=vdata['suggestion'])
return Response(TicketSerializer(instance=ticket).data)
diff --git a/hb_server/apps/wpm/apps.py b/hb_server/apps/wpm/apps.py
index 7c2337e..3f5a5ef 100644
--- a/hb_server/apps/wpm/apps.py
+++ b/hb_server/apps/wpm/apps.py
@@ -4,4 +4,8 @@ class WpmConfig(AppConfig):
name = 'apps.wpm'
verbose_name = '车间生产'
+ def ready(self):
+ # 加载信号
+ import apps.wpm.signals
+
diff --git a/hb_server/apps/wpm/migrations/0037_wproduct_scrap_reason.py b/hb_server/apps/wpm/migrations/0037_wproduct_scrap_reason.py
new file mode 100644
index 0000000..a87bc0c
--- /dev/null
+++ b/hb_server/apps/wpm/migrations/0037_wproduct_scrap_reason.py
@@ -0,0 +1,18 @@
+# Generated by Django 3.2.9 on 2021-12-21 08:19
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('wpm', '0036_auto_20211221_0923'),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name='wproduct',
+ name='scrap_reason',
+ field=models.IntegerField(blank=True, choices=[(10, '气泡'), (20, '破点'), (30, '划伤'), (40, '其他')], null=True, verbose_name='报废原因'),
+ ),
+ ]
diff --git a/hb_server/apps/wpm/models.py b/hb_server/apps/wpm/models.py
index 2b4b897..169e295 100644
--- a/hb_server/apps/wpm/models.py
+++ b/hb_server/apps/wpm/models.py
@@ -94,6 +94,7 @@ class WprouctTicket(CommonAModel):
material = models.ForeignKey(Material, verbose_name='所在物料状态', on_delete=models.CASCADE)
step = models.ForeignKey(Step, verbose_name='所在步骤', on_delete=models.CASCADE)
subproduction_plan = models.ForeignKey(SubProductionPlan, verbose_name='所在子生产计划', on_delete=models.CASCADE)
+
ticket = models.ForeignKey('wf.ticket', verbose_name='关联工单', on_delete=models.CASCADE, related_name='wt_ticket')
decision = models.CharField('最终决定', null=True, blank=True, max_length=100)
diff --git a/hb_server/apps/wpm/signals.py b/hb_server/apps/wpm/signals.py
new file mode 100644
index 0000000..2c816a2
--- /dev/null
+++ b/hb_server/apps/wpm/signals.py
@@ -0,0 +1,60 @@
+from django.db.models.signals import post_save
+from apps.qm.models import TestRecord
+from apps.wf.models import Ticket
+from django.dispatch import receiver
+
+from apps.wpm.models import WProduct, WprouctTicket
+
+
+@receiver(post_save, sender=Ticket)
+def handleTicket(sender, instance, created, **kwargs):
+ if instance.workflow.name == '不合格品审理单':
+ if created:
+ ticket_data = instance.ticket_data
+ """
+ 创建关联信息表
+ """
+ obj = WprouctTicket()
+ wproduct = WProduct.objects.get(id=ticket_data['wproduct'])
+ obj.wproduct = wproduct
+ obj.number = wproduct.number
+ obj.material = wproduct.material
+ obj.step = wproduct.step
+ obj.subproduction_plan = wproduct.subproduction_plan
+ obj.ticket = instance
+
+ test_record = TestRecord.objects.filter(wproduct=wproduct, is_deleted=False, is_testok=False).order_by('-id').first()
+ obj.save()
+
+ # 工单绑定半成品
+ wproduct.ticket = instance
+ wproduct.save()
+
+ # 检验员
+ if not ticket_data.get('tester', None):
+ ticket_data['tester'] = test_record.create_by.id
+ instance.ticket_data = ticket_data
+ instance.save()
+
+ elif instance.act_state == Ticket.TICKET_ACT_STATE_FINISH:
+ """
+ 执行操作决定
+ """
+ ticket_data = instance.ticket_data
+ wt = instance.wt_ticket
+ wp = wt.wproduct
+ if 'decision_1' in ticket_data and ticket_data['decision_1']:
+ wt.decision = ticket_data['decision_1']
+ if ticket_data['decision_1'] in ['返工', '返修']:
+ pass
+ elif ticket_data['decision_1'] in ['让步接收']:
+ wp.act_state = WProduct.WPR_ACT_STATE_OK
+ elif 'decision_2' in ticket_data and ticket_data['decision_2']:
+ wp.decision = ticket_data['decision_2']
+ if ticket_data['decision_2'] in ['返工', '返修']:
+ pass
+ elif ticket_data['decision_2'] in ['让步接收']:
+ wp.act_state = WProduct.WPR_ACT_STATE_OK
+ wt.save()
+ wp.save()
+
\ No newline at end of file
diff --git a/hb_server/apps/wpm/views.py b/hb_server/apps/wpm/views.py
index 4d62249..34556f6 100644
--- a/hb_server/apps/wpm/views.py
+++ b/hb_server/apps/wpm/views.py
@@ -339,10 +339,11 @@ class WProductViewSet(ListModelMixin, GenericViewSet):
"""
obj = self.get_object()
serializer = ScrapSerializer(data=request.data)
+ serializer.is_valid(raise_exception=True)
vdata = serializer.validated_data
if obj.act_state == WProduct.WPR_ACT_STATE_NOTOK:
pass
- elif obj.step.process == 1: # 如果是冷加工可直接报废
+ elif obj.step.process.id == 1: # 如果是冷加工可直接报废
if vdata.get('scrap_reason', None):
obj.scrap_reason = vdata['scrap_reason']
else:
@@ -363,21 +364,29 @@ class WProductViewSet(ListModelMixin, GenericViewSet):
# return WorkflowSimpleSerializer(instance=wfs, many=True).data
@action(methods=['get'], detail=True, perms_map={'get':'*'})
- def bhg_wf(self, request, pk=None):
+ def wf_bhg(self, request, pk=None):
"""
发起不合格审理单
"""
obj = self.get_object()
if obj.act_state != WProduct.WPR_ACT_STATE_NOTOK:
raise exceptions.APIException('非检验不合格产品不可发起不合格审理')
- ret = {
- 'sys_wproduct':obj.id,
- 'sys_name':obj.material.name,
- 'sys_specification':obj.material.specification,
- 'sys_finder':request.user.id,
- 'sys_process':obj.step.process.id,
- }
- return Response(ret)
+ workflow = Workflow.objects.filter(name='不合格品审理单', is_deleted=False).first()
+ if workflow:
+ exist_data = {
+ 'wproduct':obj.id,
+ 'wproduct_name':obj.material.name,
+ 'wproduct_specification':obj.material.specification,
+ 'finder':request.user.id,
+ 'find_process':obj.step.process.id,
+ }
+ ret = {'workflow':workflow.id}
+ ret['exist_data'] = exist_data
+ return Response(ret)
+ else:
+ raise exceptions.APIException('未找到对应审批流程')
+
+
diff --git a/hb_server/utils/view.py b/hb_server/utils/view.py
index dff8293..e7b3ca5 100644
--- a/hb_server/utils/view.py
+++ b/hb_server/utils/view.py
@@ -50,7 +50,7 @@ class GenSignature(APIView):
cv2.imwrite(path,image)
return Response(request.data, status=status.HTTP_200_OK)
-
+import time
class UpdateDevelop(APIView):
"""
更新开发服务器
@@ -66,7 +66,9 @@ class UpdateDevelop(APIView):
# 奇怪的处理
os.chdir('/home/hberp/hb_server/vuedist')
os.popen('cp index.html indexbak')
+ time.sleep(1000)
os.popen('rm -rf index.html')
+ time.sleep(1000)
os.popen('mv -f indexbak index.html')
# 打包前端
# os.chdir('/home/hberp/hb_client')