2021-12-16 17:54:31 +08:00
|
|
|
from extensions.common.schema import *
|
|
|
|
from extensions.common.base import *
|
2021-11-04 23:49:56 +08:00
|
|
|
from extensions.permissions import *
|
|
|
|
from extensions.exceptions import *
|
|
|
|
from extensions.viewsets import *
|
2021-11-11 23:58:18 +08:00
|
|
|
from apps.purchase.serializers import *
|
|
|
|
from apps.purchase.permissions import *
|
|
|
|
from apps.purchase.filters import *
|
|
|
|
from apps.purchase.schemas import *
|
|
|
|
from apps.purchase.models import *
|
2021-11-12 15:29:38 +08:00
|
|
|
from apps.goods.models import *
|
|
|
|
from apps.flow.models import *
|
2021-11-12 18:28:54 +08:00
|
|
|
from apps.stock_in.models import *
|
2021-11-14 15:23:15 +08:00
|
|
|
from apps.stock_out.models import *
|
2021-11-04 17:35:34 +08:00
|
|
|
|
2021-11-04 23:49:56 +08:00
|
|
|
|
2021-11-11 23:58:18 +08:00
|
|
|
class PurchaseOrderViewSet(BaseViewSet, ListModelMixin, RetrieveModelMixin, CreateModelMixin):
|
|
|
|
"""采购单据"""
|
|
|
|
|
|
|
|
serializer_class = PurchaseOrderSerializer
|
|
|
|
permission_classes = [IsAuthenticated, PurchaseOrderPermission]
|
|
|
|
filterset_class = PurchaseOrderFilter
|
|
|
|
search_fields = ['number', 'supplier__number', 'supplier__name', 'remark']
|
|
|
|
ordering_fields = ['id', 'number', 'total_quantity', 'total_amount', 'create_time']
|
2021-11-12 01:03:17 +08:00
|
|
|
select_related_fields = ['warehouse', 'supplier', 'handler', 'creator']
|
2021-11-13 02:34:05 +08:00
|
|
|
prefetch_related_fields = ['purchase_goods_set', 'purchase_goods_set__goods',
|
|
|
|
'purchase_goods_set__goods__unit',
|
2021-11-14 15:23:15 +08:00
|
|
|
'purchase_accounts', 'purchase_accounts__account']
|
2021-11-11 23:58:18 +08:00
|
|
|
queryset = PurchaseOrder.objects.all()
|
2021-11-04 23:49:56 +08:00
|
|
|
|
2021-11-12 15:29:38 +08:00
|
|
|
@transaction.atomic
|
|
|
|
def perform_create(self, serializer):
|
2021-11-12 18:28:54 +08:00
|
|
|
purchase_order = serializer.save()
|
2021-11-12 15:29:38 +08:00
|
|
|
|
|
|
|
if purchase_order.enable_auto_stock_in:
|
|
|
|
# 同步库存, 流水
|
|
|
|
inventory_flows = []
|
|
|
|
for purchase_goods in purchase_order.purchase_goods_set.all():
|
|
|
|
inventory = Inventory.objects.get(warehouse=purchase_order.warehouse,
|
|
|
|
goods=purchase_goods.goods, team=self.team)
|
|
|
|
quantity_before = inventory.total_quantity
|
|
|
|
quantity_change = purchase_goods.purchase_quantity
|
2021-11-13 02:34:05 +08:00
|
|
|
quantity_after = NP.plus(quantity_before, quantity_change)
|
2021-11-12 15:29:38 +08:00
|
|
|
|
|
|
|
inventory_flows.append(InventoryFlow(
|
|
|
|
warehouse=purchase_order.warehouse, goods=purchase_goods.goods,
|
|
|
|
type=InventoryFlow.Type.PURCHASE, quantity_before=quantity_before,
|
|
|
|
quantity_change=quantity_change, quantity_after=quantity_after,
|
|
|
|
purchase_order=purchase_order, creator=self.user, team=self.team
|
|
|
|
))
|
|
|
|
|
|
|
|
inventory.total_quantity = quantity_after
|
|
|
|
inventory.save(update_fields=['total_quantity'])
|
|
|
|
else:
|
|
|
|
InventoryFlow.objects.bulk_create(inventory_flows)
|
|
|
|
else:
|
|
|
|
# 创建入库单据
|
2021-11-12 18:28:54 +08:00
|
|
|
stock_in_order_number = StockInOrder.get_number(team=self.team)
|
|
|
|
stock_in_order = StockInOrder.objects.create(
|
|
|
|
number=stock_in_order_number, warehouse=purchase_order.warehouse,
|
|
|
|
type=StockInOrder.Type.PURCHASE, purchase_order=purchase_order,
|
2021-11-13 02:34:05 +08:00
|
|
|
total_quantity=purchase_order.total_quantity,
|
|
|
|
remain_quantity=purchase_order.total_quantity,
|
|
|
|
creator=self.user, team=self.team
|
2021-11-12 18:28:54 +08:00
|
|
|
)
|
|
|
|
|
|
|
|
# 创建入库商品
|
|
|
|
stock_in_goods_set = []
|
|
|
|
for purchase_goods in purchase_order.purchase_goods_set.all():
|
|
|
|
stock_in_goods_set.append(StockInGoods(
|
|
|
|
stock_in_order=stock_in_order, goods=purchase_goods.goods,
|
2021-11-16 01:15:03 +08:00
|
|
|
stock_in_quantity=purchase_goods.purchase_quantity,
|
|
|
|
remain_quantity=purchase_goods.purchase_quantity, team=self.team
|
2021-11-12 18:28:54 +08:00
|
|
|
))
|
|
|
|
else:
|
|
|
|
StockInGoods.objects.bulk_create(stock_in_goods_set)
|
2021-11-12 15:29:38 +08:00
|
|
|
|
|
|
|
# 同步欠款
|
|
|
|
supplier = purchase_order.supplier
|
|
|
|
supplier.arrears_amount = NP.plus(supplier.arrears_amount, purchase_order.arrears_amount)
|
|
|
|
supplier.save(update_fields=['arrears_amount'])
|
|
|
|
|
|
|
|
# 同步账户, 流水
|
2021-11-14 15:23:15 +08:00
|
|
|
if purchase_order.payment_amount > 0:
|
2021-11-12 15:29:38 +08:00
|
|
|
finance_flows = []
|
2021-11-14 15:23:15 +08:00
|
|
|
for purchase_account in purchase_order.purchase_accounts.all():
|
|
|
|
account = purchase_account.account
|
2021-11-12 15:29:38 +08:00
|
|
|
amount_before = account.balance_amount
|
2021-11-14 15:23:15 +08:00
|
|
|
amount_change = purchase_account.payment_amount
|
2021-11-12 15:29:38 +08:00
|
|
|
amount_after = NP.minus(amount_before, amount_change)
|
|
|
|
|
|
|
|
finance_flows.append(FinanceFlow(
|
2021-11-14 15:23:15 +08:00
|
|
|
account=account, type=FinanceFlow.Type.PURCHASE, amount_before=amount_before,
|
|
|
|
amount_change=amount_change, amount_after=amount_after, purchase_order=purchase_order,
|
2021-11-12 22:07:49 +08:00
|
|
|
creator=self.user, team=self.team
|
2021-11-12 15:29:38 +08:00
|
|
|
))
|
|
|
|
|
|
|
|
account.balance_amount = amount_after
|
|
|
|
account.save(update_fields=['balance_amount'])
|
|
|
|
else:
|
|
|
|
FinanceFlow.objects.bulk_create(finance_flows)
|
|
|
|
|
2021-11-12 01:03:17 +08:00
|
|
|
@extend_schema(responses={200: NumberResponse})
|
|
|
|
@action(detail=False, methods=['get'])
|
|
|
|
def number(self, request, *args, **kwargs):
|
|
|
|
"""获取编号"""
|
|
|
|
|
|
|
|
number = PurchaseOrder.get_number(self.team)
|
|
|
|
return Response(data={'number': number}, status=status.HTTP_200_OK)
|
|
|
|
|
2021-11-12 15:29:38 +08:00
|
|
|
@transaction.atomic
|
|
|
|
@extend_schema(request=None, responses={200: PurchaseOrderSerializer})
|
|
|
|
@action(detail=True, methods=['post'])
|
|
|
|
def void(self, request, *args, **kwargs):
|
|
|
|
"""作废"""
|
|
|
|
|
2021-11-12 19:17:02 +08:00
|
|
|
purchase_order = self.get_object()
|
|
|
|
if purchase_order.is_void:
|
|
|
|
raise ValidationError(f'采购单据[{purchase_order.number}]已作废, 无法再次作废')
|
|
|
|
|
|
|
|
# 同步采购单据, 采购商品
|
|
|
|
purchase_order.is_void = True
|
|
|
|
purchase_order.save(update_fields=['is_void'])
|
|
|
|
purchase_order.purchase_goods_set.all().update(is_void=True)
|
|
|
|
|
|
|
|
if purchase_order.enable_auto_stock_in:
|
|
|
|
# 同步库存, 流水
|
|
|
|
inventory_flows = []
|
|
|
|
for purchase_goods in purchase_order.purchase_goods_set.all():
|
|
|
|
inventory = Inventory.objects.get(warehouse=purchase_order.warehouse,
|
|
|
|
goods=purchase_goods.goods, team=self.team)
|
|
|
|
quantity_before = inventory.total_quantity
|
|
|
|
quantity_change = purchase_goods.purchase_quantity
|
2021-11-13 02:34:05 +08:00
|
|
|
quantity_after = NP.minus(quantity_before, quantity_change)
|
2021-11-12 19:17:02 +08:00
|
|
|
|
|
|
|
inventory_flows.append(InventoryFlow(
|
|
|
|
warehouse=purchase_order.warehouse, goods=purchase_goods.goods,
|
|
|
|
type=InventoryFlow.Type.VOID_PURCHASE, quantity_before=quantity_before,
|
|
|
|
quantity_change=quantity_change, quantity_after=quantity_after,
|
|
|
|
void_purchase_order=purchase_order, creator=self.user, team=self.team
|
|
|
|
))
|
|
|
|
|
|
|
|
inventory.total_quantity = quantity_after
|
|
|
|
inventory.save(update_fields=['total_quantity'])
|
|
|
|
else:
|
|
|
|
InventoryFlow.objects.bulk_create(inventory_flows)
|
|
|
|
else:
|
|
|
|
# 作废入库单据
|
|
|
|
stock_in_order = purchase_order.stock_in_order
|
|
|
|
if stock_in_order.total_quantity != stock_in_order.remain_quantity:
|
|
|
|
raise ValidationError(f'采购单据[{purchase_order.number}]无法作废, 已存在入库记录')
|
|
|
|
|
|
|
|
stock_in_order.is_void = True
|
|
|
|
stock_in_order.save(update_fields=['is_void'])
|
|
|
|
|
|
|
|
# 作废入库商品
|
|
|
|
stock_in_order.stock_in_goods_set.all().update(is_void=True)
|
|
|
|
|
|
|
|
# 同步欠款
|
|
|
|
supplier = purchase_order.supplier
|
|
|
|
supplier.arrears_amount = NP.minus(supplier.arrears_amount, purchase_order.arrears_amount)
|
|
|
|
supplier.save(update_fields=['arrears_amount'])
|
|
|
|
|
|
|
|
# 同步账户, 流水
|
2021-11-14 15:23:15 +08:00
|
|
|
if purchase_order.payment_amount > 0:
|
|
|
|
# 作废采购结算账户
|
|
|
|
purchase_order.purchase_accounts.all().update(is_void=True)
|
2021-11-12 19:17:02 +08:00
|
|
|
|
|
|
|
finance_flows = []
|
2021-11-14 15:23:15 +08:00
|
|
|
for purchase_account in purchase_order.purchase_accounts.all():
|
|
|
|
account = purchase_account.account
|
2021-11-12 19:17:02 +08:00
|
|
|
amount_before = account.balance_amount
|
2021-11-14 15:23:15 +08:00
|
|
|
amount_change = purchase_account.payment_amount
|
2021-11-12 19:17:02 +08:00
|
|
|
amount_after = NP.plus(amount_before, amount_change)
|
|
|
|
|
|
|
|
finance_flows.append(FinanceFlow(
|
2021-11-14 15:23:15 +08:00
|
|
|
account=account, type=FinanceFlow.Type.VOID_PURCHASE, amount_before=amount_before,
|
2021-11-12 22:07:49 +08:00
|
|
|
amount_change=amount_change, amount_after=amount_after,
|
2021-11-14 15:23:15 +08:00
|
|
|
void_purchase_order=purchase_order, creator=self.user, team=self.team
|
2021-11-12 19:17:02 +08:00
|
|
|
))
|
|
|
|
|
|
|
|
account.balance_amount = amount_after
|
|
|
|
account.save(update_fields=['balance_amount'])
|
|
|
|
else:
|
|
|
|
FinanceFlow.objects.bulk_create(finance_flows)
|
|
|
|
|
|
|
|
serializer = PurchaseOrderSerializer(instance=purchase_order)
|
|
|
|
return Response(data=serializer.data, status=status.HTTP_200_OK)
|
|
|
|
|
2021-11-11 23:58:18 +08:00
|
|
|
|
2021-11-14 15:23:15 +08:00
|
|
|
class PurchaseReturnOrderViewSet(BaseViewSet, ListModelMixin, RetrieveModelMixin, CreateModelMixin):
|
|
|
|
"""采购退货单据"""
|
|
|
|
|
|
|
|
serializer_class = PurchaseReturnOrderSerializer
|
|
|
|
permission_classes = [IsAuthenticated, PurchaseReturnOrderPermission]
|
|
|
|
filterset_class = PurchaseReturnOrderFilter
|
|
|
|
search_fields = ['number', 'purchase_order__number', 'supplier__number', 'supplier__name', 'remark']
|
|
|
|
ordering_fields = ['id', 'number', 'total_quantity', 'total_amount', 'create_time']
|
|
|
|
select_related_fields = ['purchase_order', 'warehouse', 'supplier', 'handler', 'creator']
|
|
|
|
prefetch_related_fields = ['purchase_return_goods_set', 'purchase_return_goods_set__goods',
|
|
|
|
'purchase_return_goods_set__goods__unit',
|
|
|
|
'purchase_return_accounts', 'purchase_return_accounts__account']
|
|
|
|
queryset = PurchaseReturnOrder.objects.all()
|
|
|
|
|
|
|
|
@transaction.atomic
|
|
|
|
def perform_create(self, serializer):
|
|
|
|
purchase_return_order = serializer.save()
|
|
|
|
|
|
|
|
if purchase_return_order.enable_auto_stock_out:
|
|
|
|
# 同步库存, 流水
|
|
|
|
inventory_flows = []
|
|
|
|
for purchase_return_goods in purchase_return_order.purchase_return_goods_set.all():
|
|
|
|
inventory = Inventory.objects.get(warehouse=purchase_return_order.warehouse,
|
|
|
|
goods=purchase_return_goods.goods, team=self.team)
|
|
|
|
quantity_before = inventory.total_quantity
|
|
|
|
quantity_change = purchase_return_goods.return_quantity
|
|
|
|
quantity_after = NP.minus(quantity_before, quantity_change)
|
|
|
|
|
|
|
|
inventory_flows.append(InventoryFlow(
|
|
|
|
warehouse=purchase_return_order.warehouse, goods=purchase_return_goods.goods,
|
|
|
|
type=InventoryFlow.Type.PURCHASE_RETURN, quantity_before=quantity_before,
|
|
|
|
quantity_change=quantity_change, quantity_after=quantity_after,
|
|
|
|
purchase_return_order=purchase_return_order, creator=self.user, team=self.team
|
|
|
|
))
|
|
|
|
|
|
|
|
inventory.total_quantity = quantity_after
|
|
|
|
inventory.save(update_fields=['total_quantity'])
|
|
|
|
else:
|
|
|
|
InventoryFlow.objects.bulk_create(inventory_flows)
|
|
|
|
else:
|
|
|
|
# 创建出库单据
|
|
|
|
stock_out_order_number = StockOutOrder.get_number(team=self.team)
|
|
|
|
stock_out_order = StockOutOrder.objects.create(
|
|
|
|
number=stock_out_order_number, warehouse=purchase_return_order.warehouse,
|
|
|
|
type=StockInOrder.Type.PURCHASE, purchase_return_order=purchase_return_order,
|
|
|
|
total_quantity=purchase_return_order.total_quantity,
|
|
|
|
remain_quantity=purchase_return_order.total_quantity,
|
|
|
|
creator=self.user, team=self.team
|
|
|
|
)
|
|
|
|
|
|
|
|
# 创建出库商品
|
|
|
|
stock_out_goods_set = []
|
|
|
|
for purchase_return_goods in purchase_return_order.purchase_return_goods_set.all():
|
|
|
|
stock_out_goods_set.append(StockOutGoods(
|
|
|
|
stock_out_order=stock_out_order, goods=purchase_return_goods.goods,
|
|
|
|
stock_out_quantity=purchase_return_goods.return_quantity, team=self.team
|
|
|
|
))
|
|
|
|
else:
|
|
|
|
StockOutGoods.objects.bulk_create(stock_out_goods_set)
|
|
|
|
|
|
|
|
# 同步欠款
|
|
|
|
supplier = purchase_return_order.supplier
|
|
|
|
supplier.arrears_amount = NP.minus(supplier.arrears_amount, purchase_return_order.arrears_amount)
|
|
|
|
supplier.save(update_fields=['arrears_amount'])
|
|
|
|
|
|
|
|
# 同步账户, 流水
|
|
|
|
if purchase_return_order.collection_amount > 0:
|
|
|
|
finance_flows = []
|
|
|
|
for purchase_return_account in purchase_return_order.purchase_return_accounts.all():
|
|
|
|
account = purchase_return_account.account
|
|
|
|
amount_before = account.balance_amount
|
2021-11-14 18:10:56 +08:00
|
|
|
amount_change = purchase_return_account.collection_amount
|
2021-11-14 15:23:15 +08:00
|
|
|
amount_after = NP.plus(amount_before, amount_change)
|
|
|
|
|
|
|
|
finance_flows.append(FinanceFlow(
|
|
|
|
account=account, type=FinanceFlow.Type.PURCHASE_RETURN, amount_before=amount_before,
|
|
|
|
amount_change=amount_change, amount_after=amount_after,
|
|
|
|
purchase_return_order=purchase_return_order, creator=self.user, team=self.team
|
|
|
|
))
|
|
|
|
|
|
|
|
account.balance_amount = amount_after
|
|
|
|
account.save(update_fields=['balance_amount'])
|
|
|
|
else:
|
|
|
|
FinanceFlow.objects.bulk_create(finance_flows)
|
|
|
|
|
|
|
|
@extend_schema(responses={200: NumberResponse})
|
|
|
|
@action(detail=False, methods=['get'])
|
|
|
|
def number(self, request, *args, **kwargs):
|
|
|
|
"""获取编号"""
|
|
|
|
|
|
|
|
number = PurchaseReturnOrder.get_number(self.team)
|
|
|
|
return Response(data={'number': number}, status=status.HTTP_200_OK)
|
|
|
|
|
2021-11-14 18:10:56 +08:00
|
|
|
@transaction.atomic
|
|
|
|
@extend_schema(request=None, responses={200: PurchaseReturnOrderSerializer})
|
|
|
|
@action(detail=True, methods=['post'])
|
|
|
|
def void(self, request, *args, **kwargs):
|
|
|
|
"""作废"""
|
|
|
|
|
|
|
|
purchase_return_order = self.get_object()
|
|
|
|
if purchase_return_order.is_void:
|
|
|
|
raise ValidationError(f'采购退货单据[{purchase_return_order.number}]已作废, 无法再次作废')
|
|
|
|
|
|
|
|
# 同步采购退货单据, 采购退货商品
|
|
|
|
purchase_return_order.is_void = True
|
|
|
|
purchase_return_order.save(update_fields=['is_void'])
|
|
|
|
purchase_return_order.purchase_return_goods_set.all().update(is_void=True)
|
|
|
|
|
|
|
|
if purchase_return_order.enable_auto_stock_out:
|
|
|
|
# 同步库存, 流水
|
|
|
|
inventory_flows = []
|
|
|
|
for purchase_return_goods in purchase_return_order.purchase_return_goods_set.all():
|
|
|
|
inventory = Inventory.objects.get(warehouse=purchase_return_order.warehouse,
|
|
|
|
goods=purchase_return_goods.goods, team=self.team)
|
|
|
|
quantity_before = inventory.total_quantity
|
|
|
|
quantity_change = purchase_return_goods.return_quantity
|
|
|
|
quantity_after = NP.plus(quantity_before, quantity_change)
|
|
|
|
|
|
|
|
inventory_flows.append(InventoryFlow(
|
|
|
|
warehouse=purchase_return_order.warehouse, goods=purchase_return_goods.goods,
|
|
|
|
type=InventoryFlow.Type.VOID_PURCHASE_RETURN, quantity_before=quantity_before,
|
|
|
|
quantity_change=quantity_change, quantity_after=quantity_after,
|
|
|
|
void_purchase_return_order=purchase_return_order, creator=self.user, team=self.team
|
|
|
|
))
|
|
|
|
|
|
|
|
inventory.total_quantity = quantity_after
|
|
|
|
inventory.save(update_fields=['total_quantity'])
|
2021-11-14 22:04:16 +08:00
|
|
|
|
|
|
|
# 同步采购商品退货数量
|
|
|
|
if purchase_goods := purchase_return_goods.purchase_goods:
|
|
|
|
purchase_goods.return_quantity = NP.minus(purchase_goods.return_quantity,
|
|
|
|
purchase_return_goods.return_quantity)
|
|
|
|
purchase_goods.save(update_fields=['return_quantity'])
|
2021-11-14 18:10:56 +08:00
|
|
|
else:
|
|
|
|
InventoryFlow.objects.bulk_create(inventory_flows)
|
|
|
|
else:
|
|
|
|
# 作废出库单据
|
|
|
|
stock_out_order = purchase_return_order.stock_out_order
|
|
|
|
if stock_out_order.total_quantity != stock_out_order.remain_quantity:
|
|
|
|
raise ValidationError(f'采购退货单据[{purchase_return_order.number}]无法作废, 已存在出库记录')
|
|
|
|
|
|
|
|
stock_out_order.is_void = True
|
|
|
|
stock_out_order.save(update_fields=['is_void'])
|
|
|
|
|
|
|
|
# 作废出库商品
|
|
|
|
stock_out_order.stock_out_goods_set.all().update(is_void=True)
|
|
|
|
|
|
|
|
# 同步欠款
|
|
|
|
supplier = purchase_return_order.supplier
|
|
|
|
supplier.arrears_amount = NP.plus(supplier.arrears_amount, purchase_return_order.arrears_amount)
|
|
|
|
supplier.save(update_fields=['arrears_amount'])
|
|
|
|
|
|
|
|
if purchase_return_order.collection_amount > 0:
|
|
|
|
# 作废采购退货结算账户
|
|
|
|
purchase_return_order.purchase_return_accounts.all().update(is_void=True)
|
|
|
|
|
|
|
|
# 同步账户, 流水
|
|
|
|
finance_flows = []
|
|
|
|
for purchase_return_account in purchase_return_order.purchase_return_accounts.all():
|
|
|
|
account = purchase_return_account.account
|
|
|
|
amount_before = account.balance_amount
|
|
|
|
amount_change = purchase_return_account.collection_amount
|
|
|
|
amount_after = NP.plus(amount_before, amount_change)
|
|
|
|
|
|
|
|
finance_flows.append(FinanceFlow(
|
|
|
|
account=account, type=FinanceFlow.Type.VOID_PURCHASE_RETURN, amount_before=amount_before,
|
|
|
|
amount_change=amount_change, amount_after=amount_after,
|
|
|
|
void_purchase_return_order=purchase_return_order, creator=self.user, team=self.team
|
|
|
|
))
|
|
|
|
|
|
|
|
account.balance_amount = amount_after
|
|
|
|
account.save(update_fields=['balance_amount'])
|
|
|
|
else:
|
|
|
|
FinanceFlow.objects.bulk_create(finance_flows)
|
|
|
|
|
|
|
|
serializer = PurchaseReturnOrderSerializer(instance=purchase_return_order)
|
|
|
|
return Response(data=serializer.data, status=status.HTTP_200_OK)
|
|
|
|
|
2021-11-14 15:23:15 +08:00
|
|
|
|
2021-11-11 23:58:18 +08:00
|
|
|
__all__ = [
|
2021-11-14 15:23:15 +08:00
|
|
|
'PurchaseOrderViewSet', 'PurchaseReturnOrderViewSet',
|
2021-11-04 23:49:56 +08:00
|
|
|
]
|