1
0
forked from erp-dev/erp

feat: stock module

This commit is contained in:
2025-11-04 18:04:27 +08:00
parent 9fde654e2f
commit d88bf367f8
27 changed files with 2238 additions and 561 deletions

104
stock/services.py Normal file
View File

@@ -0,0 +1,104 @@
from . import models
from django.utils import timezone
import logging
logger = logging.getLogger(__name__)
def find_inventory(product_id: int, warehouse_id: int) -> models.Inventory | None:
"""根据产品ID和仓库ID查找库存记录"""
try:
inventory = models.Inventory.objects.get(
product_id=product_id,
warehouse_id=warehouse_id,
)
return inventory
except models.Inventory.DoesNotExist:
return None
def create_stock_snapshot(stock_change_record: models.StockChangeRecord, inventory: models.Inventory) -> models.StockSnapshot:
"""创建库存快照记录"""
if not stock_change_record or stock_change_record.id is None:
raise ValueError("无效的库存变动记录")
delta = stock_change_record.delta
# 必须在库存变动发生后创建快照
snapshot = models.StockSnapshot(
product_id=inventory.product_id,
warehouse_id=inventory.warehouse_id,
delta=delta,
quantity_before=inventory.quantity - delta,
quantity_after=inventory.quantity,
stock_change_record_id=stock_change_record.id,
unit=stock_change_record.unit,
num_of_rolls=stock_change_record.num_of_rolls or 1,
)
snapshot.save()
logger.info(
f'创建库存快照库存ID: {inventory.id}, 数量: {inventory.quantity}, '
f'匹数: {inventory.num_of_rolls}'
)
return snapshot
def make_stock_change_completed(stock_change_record: models.StockChangeRecord) -> bool:
"""处理库存变动完成后的逻辑"""
# TODO: 这里可以添加事务处理以确保数据一致性
if not stock_change_record or stock_change_record.id is None:
# 无效的库存变动记录
return False
if stock_change_record.is_finished:
return True
inventory_record = find_inventory(
product_id=stock_change_record.product_id,
warehouse_id=stock_change_record.warehouse_id,
)
if not inventory_record:
logger.info(
f'库存记录未找到产品ID: {stock_change_record.product_id}, '
f'仓库ID: {stock_change_record.warehouse_id},正在创建新的库存记录。'
)
# 如果没有找到库存记录且为入库,则创建一个新的库存记录
inventory_record = models.Inventory(
product_id=stock_change_record.product_id,
warehouse_id=stock_change_record.warehouse_id,
quantity=stock_change_record.delta,
num_of_rolls=stock_change_record.num_of_rolls or 0,
minimum_quantity=0,
)
logger.info(
f'创建新的库存记录产品ID: {inventory_record.product_id}, '
f'仓库ID: {inventory_record.warehouse_id}, 数量: {inventory_record.quantity},'
f'匹数: {inventory_record.num_of_rolls}'
)
else:
# 更新现有库存记录
inventory_record.quantity += stock_change_record.delta
if stock_change_record.num_of_rolls:
inventory_record.num_of_rolls += stock_change_record.num_of_rolls
logger.info(
f'更新库存记录 {inventory_record.id},新数量: {inventory_record.quantity}, '
f'新匹数: {inventory_record.num_of_rolls}'
)
inventory_record.save()
create_stock_snapshot(stock_change_record, inventory_record)
stock_change_record.is_finished = True
stock_change_record.finished_at = timezone.now()
stock_change_record.save()
logger.info(
f'库存变动记录 {stock_change_record.id} 标记为已完成。'
)
return True