78 lines
3.0 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

from collections.abc import Mapping
from django.db import IntegrityError, transaction
from django.utils import timezone
from procurement.constants import EquipmentStatus, ProcurementStatus
from procurement.models import Equipment, ProcurementItem
class EquipmentCreationError(Exception):
"""Expected business-rule failure while creating equipment from an item."""
class ProcurementItemUnavailable(EquipmentCreationError):
"""The procurement item disappeared before the command acquired its lock."""
@transaction.atomic
def create_equipment_from_procurement_item(
*,
item_id: int,
attributes: Mapping[str, object],
) -> Equipment:
"""Create and link equipment as one concurrency-safe transaction."""
try:
item = (
ProcurementItem.objects.select_for_update()
.select_related("request", "equipment")
.get(pk=item_id)
)
except ProcurementItem.DoesNotExist as exc:
raise ProcurementItemUnavailable("Позиция закупки не найдена.") from exc
if item.request.status != ProcurementStatus.COMPLETED:
raise EquipmentCreationError(
"Оборудование можно создать только из завершённой заявки."
)
if item.equipment_id is not None:
raise EquipmentCreationError("Оборудование для этой позиции уже создано.")
purchase_cost = item.actual_unit_price or item.estimated_unit_price
if purchase_cost is None:
raise EquipmentCreationError(
"Для создания оборудования укажите фактическую или ориентировочную "
"цену позиции."
)
inventory_number = str(attributes["inventory_number"])
if Equipment.objects.filter(inventory_number=inventory_number).exists():
raise EquipmentCreationError(
f'Инвентарный номер "{inventory_number}" уже используется.'
)
try:
equipment = Equipment.objects.create(
name=item.name,
inventory_number=inventory_number,
serial_number=attributes.get("serial_number", ""),
category=attributes["category"],
department=attributes["department"],
status=EquipmentStatus.AVAILABLE,
responsible_person=attributes.get("responsible_person"),
location=attributes.get("location", ""),
purchase_date=timezone.localdate(),
warranty_until=attributes.get("warranty_until"),
purchase_cost=purchase_cost,
notes=item.description,
)
except IntegrityError as exc:
raise EquipmentCreationError(
"Не удалось создать оборудование: проверьте уникальность "
"инвентарного номера."
) from exc
item.equipment = equipment
item.save(update_fields=["equipment"])
return equipment