This commit is contained in:
120
shiftflow/services/closing.py
Normal file
120
shiftflow/services/closing.py
Normal file
@@ -0,0 +1,120 @@
|
||||
from django.db import transaction
|
||||
from django.utils import timezone
|
||||
|
||||
from shiftflow.models import (
|
||||
CuttingSession,
|
||||
Item,
|
||||
ProductionReportConsumption,
|
||||
ProductionReportRemnant,
|
||||
ShiftItem,
|
||||
)
|
||||
from shiftflow.services.sessions import close_cutting_session
|
||||
from warehouse.models import StockItem
|
||||
|
||||
|
||||
@transaction.atomic
|
||||
def apply_closing(
|
||||
*,
|
||||
user_id: int,
|
||||
machine_id: int,
|
||||
material_id: int,
|
||||
item_actions: dict[int, dict],
|
||||
consumptions: dict[int, float],
|
||||
remnants: list[dict],
|
||||
) -> None:
|
||||
items = list(
|
||||
Item.objects.select_for_update(of=('self',))
|
||||
.select_related('task', 'task__deal', 'task__material', 'machine')
|
||||
.filter(id__in=list(item_actions.keys()), machine_id=machine_id, status='work', task__material_id=material_id)
|
||||
)
|
||||
if not items:
|
||||
raise RuntimeError('Не найдено пунктов сменки для закрытия.')
|
||||
|
||||
report = CuttingSession.objects.create(
|
||||
operator_id=user_id,
|
||||
machine_id=machine_id,
|
||||
used_stock_item=None,
|
||||
date=timezone.localdate(),
|
||||
is_closed=False,
|
||||
)
|
||||
|
||||
for it in items:
|
||||
spec = item_actions.get(it.id) or {}
|
||||
action = (spec.get('action') or '').strip()
|
||||
fact = int(spec.get('fact') or 0)
|
||||
|
||||
if action not in ['done', 'partial']:
|
||||
continue
|
||||
|
||||
plan = int(it.quantity_plan or 0)
|
||||
if plan <= 0:
|
||||
continue
|
||||
|
||||
if action == 'done':
|
||||
fact = plan
|
||||
else:
|
||||
fact = max(0, min(fact, plan))
|
||||
if fact <= 0:
|
||||
raise RuntimeError('При частичном закрытии факт должен быть больше 0.')
|
||||
|
||||
ShiftItem.objects.create(session=report, task=it.task, quantity_fact=fact)
|
||||
|
||||
for stock_item_id, qty in consumptions.items():
|
||||
if qty <= 0:
|
||||
continue
|
||||
ProductionReportConsumption.objects.create(
|
||||
report=report,
|
||||
stock_item_id=stock_item_id,
|
||||
material_id=None,
|
||||
quantity=float(qty),
|
||||
)
|
||||
|
||||
for r in remnants:
|
||||
qty = float(r.get('quantity') or 0)
|
||||
if qty <= 0:
|
||||
continue
|
||||
ProductionReportRemnant.objects.create(
|
||||
report=report,
|
||||
material_id=material_id,
|
||||
quantity=qty,
|
||||
current_length=r.get('current_length'),
|
||||
current_width=r.get('current_width'),
|
||||
unique_id=None,
|
||||
)
|
||||
|
||||
close_cutting_session(report.id)
|
||||
|
||||
for it in items:
|
||||
spec = item_actions.get(it.id) or {}
|
||||
action = (spec.get('action') or '').strip()
|
||||
fact = int(spec.get('fact') or 0)
|
||||
|
||||
if action not in ['done', 'partial']:
|
||||
continue
|
||||
|
||||
plan = int(it.quantity_plan or 0)
|
||||
if plan <= 0:
|
||||
continue
|
||||
|
||||
if action == 'done':
|
||||
it.quantity_fact = plan
|
||||
it.status = 'done'
|
||||
it.save(update_fields=['quantity_fact', 'status'])
|
||||
continue
|
||||
|
||||
fact = max(0, min(fact, plan))
|
||||
residual = plan - fact
|
||||
it.quantity_fact = fact
|
||||
it.status = 'partial'
|
||||
it.save(update_fields=['quantity_fact', 'status'])
|
||||
|
||||
if residual > 0:
|
||||
Item.objects.create(
|
||||
task=it.task,
|
||||
date=it.date,
|
||||
machine=it.machine,
|
||||
quantity_plan=residual,
|
||||
quantity_fact=0,
|
||||
status='leftover',
|
||||
is_synced_1c=False,
|
||||
)
|
||||
Reference in New Issue
Block a user