Ввел логику сделок через партии
All checks were successful
Deploy MES Core / deploy (push) Successful in 4m16s
All checks were successful
Deploy MES Core / deploy (push) Successful in 4m16s
This commit is contained in:
@@ -8,7 +8,7 @@ from django.db import models, transaction
|
||||
from django.db.models import Sum
|
||||
from django.db.models.functions import Coalesce
|
||||
|
||||
from manufacturing.models import BOM, ProductEntity
|
||||
from manufacturing.models import BOM, EntityOperation, ProductEntity
|
||||
from shiftflow.models import Deal, DealItem, ProcurementRequirement, ProductionTask
|
||||
from warehouse.models import StockItem
|
||||
|
||||
@@ -16,9 +16,19 @@ logger = logging.getLogger('mes')
|
||||
|
||||
|
||||
class ExplosionValidationError(Exception):
|
||||
def __init__(self, missing_material_ids: list[int]):
|
||||
super().__init__('missing_material')
|
||||
def __init__(
|
||||
self,
|
||||
*,
|
||||
missing_material_ids: list[int] | None = None,
|
||||
missing_route_entity_ids: list[int] | None = None,
|
||||
):
|
||||
self.missing_material_ids = [int(x) for x in (missing_material_ids or [])]
|
||||
self.missing_route_entity_ids = [int(x) for x in (missing_route_entity_ids or [])]
|
||||
|
||||
if self.missing_route_entity_ids:
|
||||
super().__init__('missing_tech_process')
|
||||
else:
|
||||
super().__init__('missing_material')
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
@@ -338,6 +348,8 @@ def explode_deal(
|
||||
def explode_roots_additive(
|
||||
deal_id: int,
|
||||
roots: list[tuple[int, int]],
|
||||
*,
|
||||
delivery_batch_id: int | None = None,
|
||||
) -> ExplosionStats:
|
||||
"""Additive BOM Explosion для запуска в производство по частям.
|
||||
|
||||
@@ -370,13 +382,34 @@ def explode_roots_additive(
|
||||
.filter(id__in=list(required_nodes.keys()))
|
||||
}
|
||||
|
||||
missing = [
|
||||
missing_material = [
|
||||
int(e.id)
|
||||
for e in entities.values()
|
||||
if (getattr(e, 'entity_type', '') == 'part' and not getattr(e, 'planned_material_id', None) and int(required_nodes.get(int(e.id), 0) or 0) > 0)
|
||||
if (
|
||||
(getattr(e, 'entity_type', '') == 'part')
|
||||
and not getattr(e, 'planned_material_id', None)
|
||||
and int(required_nodes.get(int(e.id), 0) or 0) > 0
|
||||
)
|
||||
]
|
||||
if missing:
|
||||
raise ExplosionValidationError(missing)
|
||||
if missing_material:
|
||||
raise ExplosionValidationError(missing_material_ids=missing_material)
|
||||
|
||||
internal_types = {'part', 'assembly', 'product'}
|
||||
internal_ids = [
|
||||
int(e.id)
|
||||
for e in entities.values()
|
||||
if (
|
||||
(getattr(e, 'entity_type', '') or '').strip() in internal_types
|
||||
and int(required_nodes.get(int(e.id), 0) or 0) > 0
|
||||
)
|
||||
]
|
||||
if internal_ids:
|
||||
routed = set(
|
||||
EntityOperation.objects.filter(entity_id__in=internal_ids, seq=1).values_list('entity_id', flat=True)
|
||||
)
|
||||
missing_route = sorted({int(x) for x in internal_ids} - {int(x) for x in routed})
|
||||
if missing_route:
|
||||
raise ExplosionValidationError(missing_route_entity_ids=missing_route)
|
||||
|
||||
tasks_created = 0
|
||||
tasks_updated = 0
|
||||
@@ -408,6 +441,7 @@ def explode_roots_additive(
|
||||
|
||||
pt, created = ProductionTask.objects.get_or_create(
|
||||
deal=deal,
|
||||
delivery_batch_id=(int(delivery_batch_id) if delivery_batch_id else None),
|
||||
entity=entity,
|
||||
defaults=defaults,
|
||||
)
|
||||
@@ -427,8 +461,9 @@ def explode_roots_additive(
|
||||
tasks_updated += 1
|
||||
|
||||
logger.info(
|
||||
'explode_roots_additive: deal_id=%s roots=%s nodes=%s tasks_created=%s tasks_updated=%s skipped_no_material=%s skipped_supply=%s',
|
||||
'explode_roots_additive: deal_id=%s batch_id=%s roots=%s nodes=%s tasks_created=%s tasks_updated=%s skipped_no_material=%s skipped_supply=%s',
|
||||
deal_id,
|
||||
delivery_batch_id,
|
||||
roots,
|
||||
len(required_nodes),
|
||||
tasks_created,
|
||||
@@ -443,6 +478,8 @@ def explode_roots_additive(
|
||||
def rollback_roots_additive(
|
||||
deal_id: int,
|
||||
roots: list[tuple[int, int]],
|
||||
*,
|
||||
delivery_batch_id: int | None = None,
|
||||
) -> ExplosionStats:
|
||||
"""Откат additive BOM Explosion.
|
||||
|
||||
@@ -485,7 +522,11 @@ def rollback_roots_additive(
|
||||
skipped_supply += 1
|
||||
continue
|
||||
|
||||
pt = ProductionTask.objects.filter(deal=deal, entity=entity).first()
|
||||
pt = ProductionTask.objects.filter(
|
||||
deal=deal,
|
||||
delivery_batch_id=(int(delivery_batch_id) if delivery_batch_id else None),
|
||||
entity=entity,
|
||||
).first()
|
||||
if not pt:
|
||||
missing_tasks += 1
|
||||
continue
|
||||
@@ -501,8 +542,9 @@ def rollback_roots_additive(
|
||||
tasks_updated += 1
|
||||
|
||||
logger.info(
|
||||
'rollback_roots_additive: deal_id=%s roots=%s nodes=%s tasks_updated=%s skipped_supply=%s missing_tasks=%s',
|
||||
'rollback_roots_additive: deal_id=%s batch_id=%s roots=%s nodes=%s tasks_updated=%s skipped_supply=%s missing_tasks=%s',
|
||||
deal_id,
|
||||
delivery_batch_id,
|
||||
roots,
|
||||
len(required_nodes),
|
||||
tasks_updated,
|
||||
|
||||
Reference in New Issue
Block a user