diff --git a/CHANGELOG.md b/CHANGELOG.md index 2436dd8..d61a363 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ - Отгрузка: можно добавлять несколько сделок в одну сессию отгрузки, выбирать позиции и подтверждать общий список. - Журнал отгрузки: добавлены фильтр по периоду (по умолчанию 2 недели) и поиск по сделкам (номер/описание/заказчик), убран столбец «Куда». - Списание / Производство: в блоках «Списано» и «Остаток ДО» выводится масса материалов (по размерам и «Масса на ед. учёта»); если масса не задана — показывается прочерк. +- Закрытие: деловой остаток (ДО) может наследовать сделку от списанного сырья (отключается чекбоксом) и доступен к отгрузке как сырьё по сделке. - Реестр заданий: комментарий сменного задания/операции отображается под наименованием. - Паспорта изделий/компонентов: ссылки на PDF/DXF/картинки отображаются иконками и открываются в новой вкладке. - Паспорта изделий/сборок: блок «Состав» перенесён в верхнюю часть страницы, в таблицу состава добавлена колонка «Файлы». diff --git a/shiftflow/services/closing.py b/shiftflow/services/closing.py index c27fa6d..7274b1c 100644 --- a/shiftflow/services/closing.py +++ b/shiftflow/services/closing.py @@ -24,6 +24,7 @@ def apply_closing( item_actions: dict[int, dict], consumptions: dict[int, float], remnants: list[dict], + inherit_deal_for_remnants: bool = False, ) -> None: logger.info('apply_closing:start user=%s machine=%s material=%s items=%s consumptions=%s remnants=%s', user_id, machine_id, material_id, list(item_actions.keys()), list(consumptions.keys()), len(remnants)) @@ -93,7 +94,7 @@ def apply_closing( ) logger.info('apply_closing:close_session id=%s', report.id) - close_cutting_session(report.id) + close_cutting_session(report.id, inherit_deal_for_remnants=bool(inherit_deal_for_remnants)) for it in items: spec = item_actions.get(it.id) or {} @@ -142,6 +143,7 @@ def apply_closing_workitems( item_actions: dict[int, dict], # workitem_id -> {'action': 'done'|'partial', 'fact': int} consumptions: dict[int, float], remnants: list[dict], + inherit_deal_for_remnants: bool = False, ) -> None: logger.info('apply_closing_workitems:start user=%s machine=%s material=%s workitems=%s cons=%s rem=%s', user_id, machine_id, material_id, list(item_actions.keys()), list(consumptions.keys()), len(remnants)) @@ -224,5 +226,5 @@ def apply_closing_workitems( unique_id=None, ) - close_cutting_session(report.id) + close_cutting_session(report.id, inherit_deal_for_remnants=bool(inherit_deal_for_remnants)) logger.info('apply_closing_workitems:done report=%s shift_items=%s', report.id, created_shift) diff --git a/shiftflow/services/sessions.py b/shiftflow/services/sessions.py index c950ec1..68f00ec 100644 --- a/shiftflow/services/sessions.py +++ b/shiftflow/services/sessions.py @@ -17,7 +17,7 @@ logger = logging.getLogger('mes') @transaction.atomic -def close_cutting_session(session_id: int) -> None: +def close_cutting_session(session_id: int, *, inherit_deal_for_remnants: bool = False) -> None: """ Закрытие CuttingSession (транзакция склада). @@ -56,6 +56,8 @@ def close_cutting_session(session_id: int) -> None: raise RuntimeError('Не задан склад цеха для станка (Цех -> Склад цеха).') consumed_material_ids: set[int] = set() + consumed_deal_ids: set[int] = set() + consumed_is_customer_supplied = False consumptions = list( ProductionReportConsumption.objects.select_related('material', 'stock_item', 'stock_item__material', 'stock_item__location') @@ -72,6 +74,11 @@ def close_cutting_session(session_id: int) -> None: si = StockItem.objects.select_for_update(of=('self',)).select_related('material', 'location').get(pk=c.stock_item_id) logger.info('close_cutting_session:consume stock_item=%s qty=%s before=%s', si.id, c.quantity, si.quantity) + if getattr(si, 'deal_id', None): + consumed_deal_ids.add(int(si.deal_id)) + if bool(getattr(si, 'is_customer_supplied', False)): + consumed_is_customer_supplied = True + if not si.material_id: raise RuntimeError('В списании сырья указана позиция склада без material.') @@ -129,6 +136,11 @@ def close_cutting_session(session_id: int) -> None: used = StockItem.objects.select_for_update(of=('self',)).select_related('material', 'location').get(pk=session.used_stock_item_id) logger.info('close_cutting_session:used stock_item=%s before=%s', used.id, used.quantity) + + if getattr(used, 'deal_id', None): + consumed_deal_ids.add(int(used.deal_id)) + if bool(getattr(used, 'is_customer_supplied', False)): + consumed_is_customer_supplied = True if not used.material_id: raise RuntimeError('Взятый материал должен ссылаться на сырьё (material), а не на готовую деталь (entity).') @@ -191,13 +203,19 @@ def close_cutting_session(session_id: int) -> None: ) ProductionReportStockResult.objects.create(report=session, stock_item=created, kind='finished') + remnant_deal_id = None + if inherit_deal_for_remnants and len(consumed_deal_ids) == 1: + remnant_deal_id = int(next(iter(consumed_deal_ids))) + remnants = list(ProductionReportRemnant.objects.filter(report=session).select_related('material')) for r in remnants: created = StockItem.objects.create( material=r.material, + deal_id=remnant_deal_id, location=work_location, quantity=float(r.quantity), is_remnant=True, + is_customer_supplied=bool(consumed_is_customer_supplied), current_length=r.current_length, current_width=r.current_width, unique_id=r.unique_id, diff --git a/shiftflow/services/shipping.py b/shiftflow/services/shipping.py index 5391e00..623822a 100644 --- a/shiftflow/services/shipping.py +++ b/shiftflow/services/shipping.py @@ -140,7 +140,6 @@ def build_shipment_rows( is_archived=False, quantity__gt=0, material_id__isnull=False, - is_customer_supplied=True, ) .exclude(location_id=int(shipping_location_id)) .values('material_id') @@ -264,7 +263,6 @@ def create_shipment_transfers( is_archived=False, quantity__gt=0, material_id=int(mat_id), - is_customer_supplied=True, ).select_related('material', 'location'), float(q), ) diff --git a/shiftflow/templates/shiftflow/closing.html b/shiftflow/templates/shiftflow/closing.html index 2af702a..3c431b6 100644 --- a/shiftflow/templates/shiftflow/closing.html +++ b/shiftflow/templates/shiftflow/closing.html @@ -132,7 +132,13 @@
| + | Сырьё | +Доступно | +К отгрузке | +
|---|---|---|---|
| + | {{ r.material.full_name|default:r.material.name }} Сырьё |
+ {{ r.available|floatformat:"-g" }} | ++ + | +
| Нет сырья к отгрузке | |||