from apps.inm.models import MIO, MIOItem, MaterialBatch, MaterialBatchA, MIOItemA, WareHouse from rest_framework.exceptions import ValidationError, ParseError from django.db.models.aggregates import Sum from django.db.models import F from apps.wpm.services import do_out, do_in from apps.mtm.models import Material, Process from apps.utils.tools import ranstr class InmService: @classmethod def update_inm(cls, instance: MIO, is_reverse: bool = False): """ 更新库存, 支持反向操作 """ if instance.type in [MIO.MIO_TYPE_PUR_IN, MIO.MIO_TYPE_DO_IN, MIO.MIO_TYPE_OTHER_IN]: # 采购入库, 生产入库, 其他入库 in_or_out = 1 if is_reverse: in_or_out = -1 cls.update_mb(instance, in_or_out) if instance.type == MIO.MIO_TYPE_PUR_IN: # 需要更新订单 from apps.pum.services import PumService PumService.mio_purin(instance, is_reverse) elif instance.type == MIO.MIO_TYPE_DO_IN: if is_reverse: do_out(instance) else: do_in(instance) elif instance.type in [MIO.MIO_TYPE_DO_OUT, MIO.MIO_TYPE_SALE_OUT, MIO.MIO_TYPE_OTHER_OUT]: # 生产领料 销售出库 in_or_out = -1 if is_reverse: in_or_out = 1 cls.update_mb(instance, in_or_out) if instance.type == MIO.MIO_TYPE_SALE_OUT: from apps.sam.services import SamService SamService.mio_saleout(instance, is_reverse) elif instance.type == MIO.MIO_TYPE_DO_OUT: if is_reverse: do_in(instance) else: do_out(instance) @classmethod def update_mb(cls, instance: MIO, in_or_out: int = 1): """ 更新物料批次 in = 1 out = -1 """ belong_dept = instance.belong_dept mioitems = MIOItem.objects.filter(mio=instance) if not mioitems.exists(): raise ParseError('未填写物料明细') for i in MIOItem.objects.filter(mio=instance): material = i.material warehouse = i.warehouse mb, is_created = MaterialBatch.objects.get_or_create(material=material, warehouse=warehouse, batch=i.batch, defaults={'material': material, 'warehouse': warehouse, 'count': 0, 'batch': i.batch}) if in_or_out == 1: mb.count = mb.count + i.count # if mb.expiration_date is None: # mb.expiration_date = i.expiration_date if instance.type == MIO.MIO_TYPE_DO_IN: # 生产入库需要记录production_dept字段 if mb.production_dept is None or mb.production_dept == belong_dept: mb.production_dept = belong_dept else: raise ParseError('同种物料不同生产车间应该有不同批次号!') mb.save() mias = MIOItemA.objects.filter(mioitem=i) if mias.exists(): # 组合件入库 if not is_created: raise ParseError('该批次组合件已存在') for mia in mias: MaterialBatchA.objects.create( mb=mb, material=mia.material, batch=mia.batch) elif in_or_out == -1: mb.count = mb.count - i.count if mb.count < 0: raise ParseError('批次库存不足,操作失败') elif mb.count == 0: mb.delete() else: mb.save() else: raise ParseError('不支持的操作') material_count = MaterialBatch.objects.filter( material=material).aggregate(total=Sum('count'))['total'] if material_count is None: material_count = 0 Material.objects.filter(id=material.id).update( count=material_count) def daoru_mb(path: str): """ 导入物料批次(如没有物料自动创建) """ objs1 = Material.objects.filter(specification__contains=' ') for i in objs1: i.specification = i.specification.replace(' ', '') i.save() objs2 = Material.objects.filter(specification__contains='×') for i in objs2: i.specification = i.specification.replace('×', '*') i.save() objs3 = (Material.objects.filter( specification__contains='优级') | Material.objects.filter(specification__contains='一级')).exclude(specification__contains='|') for i in objs3: i.specification = i.specification.replace( '优级', '|优级').replace('一级', '|一级') i.save() type_dict = {'主要原料': 30, '半成品': 20, '成品': 10, '辅助材料': 40, '加工工具': 50, '辅助工装': 60, '办公用品': 70} from apps.utils.snowflake import idWorker from openpyxl import load_workbook wb = load_workbook(path) process_l = Process.objects.all() process_d = {p.name: p for p in process_l} warehouse_l = WareHouse.objects.all() warehouse_d = {w.name: w for w in warehouse_l} for sheet in wb.worksheets: i = 3 while sheet[f'a{i}'].value: try: type = type_dict[sheet[f'a{i}'].value.replace(' ', '')] name = sheet[f'b{i}'].value.replace(' ', '') specification = sheet[f'c{i}'].value.replace( ' ', '') + '|' + sheet[f'd{i}'].value.replace(' ', '') model = sheet[f'e{i}'].value.replace(' ', '') process = process_d[sheet[f'f{i}'].value.replace(' ', '')] batch = sheet[f'g{i}'].value.replace(' ', '') count = int(sheet[f'h{i}'].value) warehouse = warehouse_d[sheet[f'i{i}'].value.replace(' ', '')] except KeyError as e: raise ParseError(f'第{i}行数据有误:{str(e)}') material, _ = Material.objects.get_or_create( type=type, name=name, specification=specification, model=model, process=process, defaults={ 'type': type, 'name': name, 'specification': specification, 'model': model, 'process': process, 'number': ranstr(6), 'id': idWorker.get_id() }) mb, is_created = MaterialBatch.objects.get_or_create( material=material, batch=batch, warehouse=warehouse, defaults={ 'material': material, 'batch': batch, 'warehouse': warehouse, 'count': count, 'id': idWorker.get_id() }) # if not is_created: # mb.count += count # mb.save() print(f'第{i}行数据导入成功') i = i + 1