forked from erp-dev/erp
feat: retry haobuye sync order
This commit is contained in:
@@ -16,6 +16,7 @@ from shipment.models import (
|
||||
ExternalFinishedProduct,
|
||||
SalesItem,
|
||||
SalesItemChangeRecord,
|
||||
SalesItemRebuildRecord,
|
||||
Shipment,
|
||||
ShipmentDelivery,
|
||||
ShipmentDeliveryStatus,
|
||||
@@ -50,6 +51,25 @@ def ensure_sales_item_can_be_soft_deleted(sales_item: SalesItem) -> None:
|
||||
raise ValueError("已关联出货单的销售品不允许删除")
|
||||
|
||||
|
||||
def _get_printing_job_for_sales_item(*, printing_job_id: int, merchant):
|
||||
from printing.models import PrintingJob
|
||||
|
||||
try:
|
||||
return PrintingJob.objects.select_related("printing_order").get(
|
||||
id=printing_job_id,
|
||||
merchant=merchant,
|
||||
)
|
||||
except PrintingJob.DoesNotExist:
|
||||
raise ValueError(f"生产任务 {printing_job_id} 不存在或不属于当前商户")
|
||||
|
||||
|
||||
def _normalize_sales_item_quantity(quantity: str | Decimal) -> Decimal:
|
||||
try:
|
||||
return Decimal(str(quantity))
|
||||
except (InvalidOperation, ValueError, TypeError) as e:
|
||||
raise ValueError(f"数量 {quantity} 格式无效: {e}")
|
||||
|
||||
|
||||
def _resolve_delivery_shipments(
|
||||
*,
|
||||
shipment_ids: list[int],
|
||||
@@ -302,6 +322,64 @@ def delete_sales_item(
|
||||
return sales_item
|
||||
|
||||
|
||||
@transaction.atomic
|
||||
def rebuild_sales_item(
|
||||
sales_item: SalesItem,
|
||||
*,
|
||||
new_printing_job_id: int,
|
||||
operator,
|
||||
quantity: str | Decimal | None = None,
|
||||
) -> SalesItem:
|
||||
"""
|
||||
软删除旧销售品,并基于新 printing_job 重建一个新销售品。
|
||||
"""
|
||||
ensure_sales_item_can_be_soft_deleted(sales_item)
|
||||
|
||||
merchant = sales_item.merchant
|
||||
printing_job = _get_printing_job_for_sales_item(
|
||||
printing_job_id=new_printing_job_id,
|
||||
merchant=merchant,
|
||||
)
|
||||
|
||||
new_quantity = (
|
||||
_normalize_sales_item_quantity(quantity)
|
||||
if quantity is not None
|
||||
else sales_item.quantity
|
||||
)
|
||||
|
||||
deleted_sales_item = delete_sales_item(sales_item, deleted_by=operator)
|
||||
|
||||
customer_id = sales_item.customer_id
|
||||
if customer_id is None and printing_job.printing_order and printing_job.printing_order.customer:
|
||||
customer_id = printing_job.printing_order.customer_id
|
||||
|
||||
new_sales_item = SalesItem.objects.create(
|
||||
shipment=None,
|
||||
merchant=merchant,
|
||||
name=sales_item.name,
|
||||
quantity=new_quantity,
|
||||
unit=sales_item.unit,
|
||||
created_by=sales_item.created_by,
|
||||
printing_job_id=printing_job.id,
|
||||
customer_id=customer_id,
|
||||
remark=sales_item.remark,
|
||||
position=sales_item.position,
|
||||
)
|
||||
|
||||
SalesItemRebuildRecord.objects.create(
|
||||
old_sales_item=deleted_sales_item,
|
||||
new_sales_item=new_sales_item,
|
||||
operator=operator,
|
||||
rebuilt_at=timezone.now(),
|
||||
old_printing_job_id=deleted_sales_item.printing_job_id,
|
||||
new_printing_job_id=printing_job.id,
|
||||
old_quantity=deleted_sales_item.quantity,
|
||||
new_quantity=new_sales_item.quantity,
|
||||
)
|
||||
|
||||
return new_sales_item
|
||||
|
||||
|
||||
@transaction.atomic
|
||||
def create_shipment_delivery(
|
||||
*,
|
||||
@@ -841,6 +919,7 @@ def create_sales_item(
|
||||
customer_id: int | None = None,
|
||||
remark: str = "",
|
||||
position: str = "",
|
||||
merge_remark: dict | None = None,
|
||||
) -> SalesItem:
|
||||
"""
|
||||
手动创建销售品
|
||||
@@ -861,8 +940,6 @@ def create_sales_item(
|
||||
Raises:
|
||||
ValueError: 如果生产任务不存在或不属于当前商户
|
||||
"""
|
||||
from printing.models import PrintingJob
|
||||
|
||||
# 获取当前用户的商户
|
||||
emp = getattr(created_by, "employee", None)
|
||||
merchant = getattr(emp, "merchant", None) if emp else None
|
||||
@@ -870,19 +947,13 @@ def create_sales_item(
|
||||
raise ValueError("用户未关联商户,无法创建销售品")
|
||||
|
||||
# 验证生产任务存在且属于当前商户
|
||||
try:
|
||||
printing_job = PrintingJob.objects.select_related("printing_order").get(
|
||||
id=printing_job_id,
|
||||
merchant=merchant,
|
||||
)
|
||||
except PrintingJob.DoesNotExist:
|
||||
raise ValueError(f"生产任务 {printing_job_id} 不存在或不属于当前商户")
|
||||
printing_job = _get_printing_job_for_sales_item(
|
||||
printing_job_id=printing_job_id,
|
||||
merchant=merchant,
|
||||
)
|
||||
|
||||
# 转换数量为Decimal
|
||||
try:
|
||||
quantity_decimal = Decimal(str(quantity))
|
||||
except (InvalidOperation, ValueError, TypeError) as e:
|
||||
raise ValueError(f"数量 {quantity} 格式无效: {e}")
|
||||
quantity_decimal = _normalize_sales_item_quantity(quantity)
|
||||
|
||||
# 如果未提供客户ID,尝试从主订单获取
|
||||
if (
|
||||
@@ -904,6 +975,35 @@ def create_sales_item(
|
||||
customer_id=customer_id,
|
||||
remark=remark,
|
||||
position=position,
|
||||
merge_remark=merge_remark,
|
||||
)
|
||||
|
||||
return sales_item
|
||||
|
||||
|
||||
def get_merge_remark_jobs_by_main_job(
|
||||
printing_job_id: int,
|
||||
merchant,
|
||||
) -> list[list[int]]:
|
||||
"""
|
||||
查找指定 printing_job_id 作为 main_job 的所有销售品,返回每条记录的 jobs 列表。
|
||||
|
||||
同一个 printing_job_id 可能出现在多条销售品的 main_job 中,
|
||||
因此返回值是一个二维列表,每个元素对应一条匹配记录的 jobs。
|
||||
|
||||
Args:
|
||||
printing_job_id: 要查询的生产任务ID
|
||||
merchant: 当前商户
|
||||
|
||||
Returns:
|
||||
匹配记录的 jobs 列表集合,无匹配时返回空列表。
|
||||
示例: [[9777, 9776], [9777, 9780]]
|
||||
"""
|
||||
merge_remarks = list(
|
||||
get_active_sales_items_queryset()
|
||||
.filter(merchant=merchant, merge_remark__main_job=printing_job_id)
|
||||
.values_list("merge_remark", flat=True)
|
||||
)
|
||||
if not merge_remarks:
|
||||
return []
|
||||
return [mr.get("jobs", []) for mr in merge_remarks if mr]
|
||||
|
||||
Reference in New Issue
Block a user