This commit is contained in:
TianyangZhang 2025-11-24 09:18:34 +08:00
commit 54196b2a64
10 changed files with 32 additions and 11 deletions

View File

@ -4,6 +4,7 @@ from jinja2 import Template
from apps.bi.models import Dataset from apps.bi.models import Dataset
import concurrent import concurrent
from apps.utils.sql import execute_raw_sql, format_sqldata from apps.utils.sql import execute_raw_sql, format_sqldata
from apps.utils.tools import MyJSONEncoder
forbidden_keywords = ["UPDATE", "DELETE", "DROP", "TRUNCATE", "INSERT", "CREATE", "ALTER", "GRANT", "REVOKE", "EXEC", "EXECUTE"] forbidden_keywords = ["UPDATE", "DELETE", "DROP", "TRUNCATE", "INSERT", "CREATE", "ALTER", "GRANT", "REVOKE", "EXEC", "EXECUTE"]
@ -25,7 +26,7 @@ def format_json_with_placeholders(json_str, **kwargs):
# 遍历关键字参数,将占位符替换为对应的值 # 遍历关键字参数,将占位符替换为对应的值
for key, value in kwargs.items(): for key, value in kwargs.items():
formatted_json = formatted_json.replace("{" + key + "}", json.dumps(value)) formatted_json = formatted_json.replace("{" + key + "}", json.dumps(value, cls=MyJSONEncoder))
# 格式化后的字符串依然是 JSON 字符串,没有使用 json.loads() # 格式化后的字符串依然是 JSON 字符串,没有使用 json.loads()
return formatted_json return formatted_json

View File

@ -126,7 +126,7 @@ class MIOItemCreateSerializer(CustomModelSerializer):
class Meta: class Meta:
model = MIOItem model = MIOItem
fields = ['mio', 'warehouse', 'material', fields = ['mio', 'warehouse', 'material',
'batch', 'count', 'assemb', 'is_testok', 'mioitemw', 'mb', 'wm', 'unit_price', 'note', "pack_index"] 'batch', 'count', 'assemb', 'is_testok', 'mioitemw', 'mb', 'wm', 'unit_price', 'note', "pack_index", "count_send"]
extra_kwargs = { extra_kwargs = {
'mio': {'required': True}, 'warehouse': {'required': False}, 'mio': {'required': True}, 'warehouse': {'required': False},
'material': {'required': False}, 'batch': {'required': False, "allow_null": True, "allow_blank": True}} 'material': {'required': False}, 'batch': {'required': False, "allow_null": True, "allow_blank": True}}
@ -156,6 +156,8 @@ class MIOItemCreateSerializer(CustomModelSerializer):
batch = validated_data.get("batch", None) batch = validated_data.get("batch", None)
if not batch: if not batch:
batch = "" batch = ""
if batch != '' and len(batch) < 5:
raise ParseError('批次号格式错误')
if material.is_hidden: if material.is_hidden:
raise ParseError('隐式物料不可出入库') raise ParseError('隐式物料不可出入库')
if mio.type in [MIO.MIO_TYPE_RETURN_IN, MIO.MIO_TYPE_BORROW_OUT]: if mio.type in [MIO.MIO_TYPE_RETURN_IN, MIO.MIO_TYPE_BORROW_OUT]:

View File

@ -88,7 +88,7 @@ def do_out(item: MIOItem, is_reverse: bool = False):
defect=defect defect=defect
) )
except (MaterialBatch.DoesNotExist, MaterialBatch.MultipleObjectsReturned) as e: except (MaterialBatch.DoesNotExist, MaterialBatch.MultipleObjectsReturned) as e:
raise ParseError(f"批次错误!{e}") raise ParseError(f"{str(xmaterial)}批次{xbatch}错误!{e}")
mb.count = mb.count - xcount mb.count = mb.count - xcount
if mb.count < 0: if mb.count < 0:
raise ParseError(f"{mb.batch}-{str(mb.material)}-批次库存不足,操作失败") raise ParseError(f"{mb.batch}-{str(mb.material)}-批次库存不足,操作失败")

View File

@ -156,6 +156,8 @@ def daoru_mioitems(path:str, mio:MIO):
pass pass
else: else:
batch = "" batch = ""
if batch != '' and len(batch) < 5:
raise ParseError(f'{ind}行批次号{batch}:格式错误')
count = sheet[f"f{ind}"].value count = sheet[f"f{ind}"].value
warehouse_name = sheet[f"g{ind}"].value warehouse_name = sheet[f"g{ind}"].value
try: try:

View File

@ -482,13 +482,25 @@ class MIOItemwViewSet(CustomModelViewSet):
perms_map = {'get': '*', 'post': 'mio.update', 'put': 'mio.update', 'delete': 'mio.update'} perms_map = {'get': '*', 'post': 'mio.update', 'put': 'mio.update', 'delete': 'mio.update'}
queryset = MIOItemw.objects.all() queryset = MIOItemw.objects.all()
serializer_class = MIOItemwCreateUpdateSerializer serializer_class = MIOItemwCreateUpdateSerializer
filterset_fields = ['mioitem', 'wpr'] filterset_fields = {
'mioitem': ['exact'],
'mioitem__material__type': ['exact'],
"wpr": ['exact'],
"number": ["exact"],
"ftest": ["isnull"],
"mioitem__mio__state": ["exact"]
}
select_related_fields = ["ftest"]
ordering = ["number", "create_time"] ordering = ["number", "create_time"]
ordering_fields = ["number", "create_time"] ordering_fields = ["number", "create_time"]
def filter_queryset(self, queryset): def filter_queryset(self, queryset):
if not self.detail and not self.request.query_params.get('mioitem', None): if not self.detail:
raise ParseError('请指定所属出入库记录明细') if not self.request.query_params.get('mioitem', None):
if "ftest__isnull" in self.request.query_params:
pass
else:
raise ParseError('请指定所属出入库记录明细')
return super().filter_queryset(queryset) return super().filter_queryset(queryset)
def cal_mioitem_count(self, mioitem:MIOItem): def cal_mioitem_count(self, mioitem:MIOItem):

View File

@ -15,7 +15,7 @@ def send_sms(phone: str, template_code: int, template_param: dict):
from aliyunsdkcore.request import CommonRequest from aliyunsdkcore.request import CommonRequest
config = get_sysconfig() config = get_sysconfig()
if config.get("sms", {}).get('enabled', False) is False: if config.get("sms", {}).get('enabled', False) is False:
return False, {} raise ParseError("短信发送功能未开启")
try: try:
client = AcsClient(config['sms']['xn_key'], client = AcsClient(config['sms']['xn_key'],
config['sms']['xn_secret'], 'default') config['sms']['xn_secret'], 'default')

View File

@ -149,6 +149,7 @@ class TicketDetailSerializer(CustomModelSerializer):
state_ = StateSimpleSerializer(source='state', read_only=True) state_ = StateSimpleSerializer(source='state', read_only=True)
ticket_data_ = serializers.SerializerMethodField() ticket_data_ = serializers.SerializerMethodField()
participant_ = serializers.SerializerMethodField() participant_ = serializers.SerializerMethodField()
create_by_name = serializers.CharField(source='create_by.name', read_only=True)
class Meta: class Meta:
model = Ticket model = Ticket

View File

@ -8,7 +8,7 @@ def main(wprId, mgroup:Mgroup):
wpr = Wpr.objects.get(id=wprId) wpr = Wpr.objects.get(id=wprId)
data = {} data = {}
mgroup_name = mgroup.name mgroup_name = mgroup.name
mlogbw = Mlogbw.objects.filter(wpr=wpr, mlogb__mlog__submit_time__isnull=False).order_by("-update_time").first() mlogbw = Mlogbw.objects.filter(wpr=wpr, mlogb__mlog__mgroup=mgroup, mlogb__mlog__submit_time__isnull=False).order_by("-update_time").first()
if mlogbw: if mlogbw:
data[f"{mgroup_name}_批次号"] = mlogbw.mlogb.batch data[f"{mgroup_name}_批次号"] = mlogbw.mlogb.batch
data[f"{mgroup_name}_日期"] = mlogbw.mlogb.mlog.handle_date.strftime("%Y-%m-%d") data[f"{mgroup_name}_日期"] = mlogbw.mlogb.mlog.handle_date.strftime("%Y-%m-%d")

View File

@ -857,7 +857,9 @@ def handover_submit(handover:Handover, user: User, now: Union[datetime.datetime,
else: else:
raise ParseError("不支持非工段报废") raise ParseError("不支持非工段报废")
elif handover.type == Handover.H_CHANGE: elif handover.type == Handover.H_CHANGE:
if handover.recive_mgroup: if handover.new_wm:
wm_to = handover.new_wm
elif handover.recive_mgroup:
wm_to, _ = WMaterial.objects.get_or_create( wm_to, _ = WMaterial.objects.get_or_create(
batch=batch, batch=batch,
material=handover.material_changed, material=handover.material_changed,

View File

@ -7,6 +7,7 @@ from apps.wpm.serializers import BatchMgroupSerializer
from apps.wpm.models import WMaterial, Mlogb from apps.wpm.models import WMaterial, Mlogb
from django.db.models import Q, Sum, F, ExpressionWrapper from django.db.models import Q, Sum, F, ExpressionWrapper
from collections import defaultdict from collections import defaultdict
from apps.mtm.models import Material
@ -26,12 +27,12 @@ class BatchWorkView(APIView):
mgroup:Mgroup = Mgroup.objects.get(name=vdata['mgroup_name']) mgroup:Mgroup = Mgroup.objects.get(name=vdata['mgroup_name'])
except Exception: except Exception:
raise ParseError(f"获取工段信息失败-{vdata['mgroup_name']}") raise ParseError(f"获取工段信息失败-{vdata['mgroup_name']}")
matoutIds = mgroup.process.get_canout_mat_ids() matinIds = mgroup.process.get_canin_mat_ids()
# 待加工的批次 # 待加工的批次
wm_qs = WMaterial.objects.filter(mgroup=mgroup, count__gt=0) wm_qs = WMaterial.objects.filter(mgroup=mgroup, count__gt=0)
wm_todo_qs = wm_qs.filter(state=WMaterial.WM_OK).exclude(material__id__in=matoutIds)|wm_qs.filter(state=WMaterial.WM_REPAIR) wm_todo_qs = wm_qs.filter(material__id__in=matinIds).exclude(state=WMaterial.WM_REPAIRED)|wm_qs.filter(state=WMaterial.WM_REPAIR, mgroup=mgroup)
wm_v = wm_todo_qs.order_by("batch").values("count", "batch", wmid=F("id")) wm_v = wm_todo_qs.order_by("batch").values("count", "batch", wmid=F("id"))
# 对应的操作子日志投入 # 对应的操作子日志投入