写完了领料功能

master
laoxiao 1 year ago
parent eb7daca9aa
commit 5062f48c88

@ -77,3 +77,72 @@ class PaymentItemModel(BaseModel):
verbose_name = '付款单中的 付款项目表'
verbose_name_plural = verbose_name
ordering = ['id']
# 收款类型
receipt_choices = (
('1', '销售定金'),
('2', '销售出库货款'),
('3', '客户还款的收款'),
('4', '其他收款')
)
# 收款单的模型类
class ReceiptModel(BaseModel):
pay_date = models.DateTimeField('收款日期')
number_code = models.CharField('单据编号,不让用户填写', max_length=28)
discount_money = models.DecimalField('优惠金额(收款优惠),最多精确到小数点后两位', max_digits=10, default=0, decimal_places=2,
blank=True, null=True)
receipt_money = models.DecimalField('合计 收款金额最多精确到小数点后两位', max_digits=10, decimal_places=2, default=0)
this_money = models.DecimalField('实际 收款金额最多精确到小数点后两位', max_digits=10, decimal_places=2, default=0)
remark = models.CharField('备注', max_length=512, blank=True, null=True)
currency = models.CharField('货币种类', max_length=20, null=True, choices=currency_choices, default='CNY')
receipt_category = models.CharField('收款类型', max_length=2, null=True, choices=receipt_choices, default='1')
status = models.CharField('状态,0:未审核,1:已审核', max_length=1, default='0')
account = models.ForeignKey('basic_info.SettlementAccountModel', null=True, blank=True, on_delete=models.SET_NULL,
verbose_name='结算账户,审核之后不能改')
operator_user = models.ForeignKey('erp_system.UserModel', related_name='operator2_pay_list', null=True,
blank=True, on_delete=models.SET_NULL,
verbose_name='财务操作人员,不能修改')
# 增加一个冗余字段
operator_user_name = models.CharField('财务人员的真实姓名', max_length=20, null=True, blank=True)
check_user = models.ForeignKey('erp_system.UserModel', related_name='operator4_pay_list', null=True, blank=True, on_delete=models.SET_NULL,
verbose_name='审核人员,不能修改')
# 增加一个冗余字段
check_user_name = models.CharField('审核人员的真实姓名', max_length=20, null=True, blank=True)
customer = models.ForeignKey('basic_info.CustomerModel', null=True, blank=True, on_delete=models.SET_NULL,
verbose_name='客户,审核之后不能改')
# 增加一个冗余字段
customer_name = models.CharField('客户名称', max_length=30, null=True, blank=True)
sale = models.ForeignKey('sale_info.SaleModel', null=True, blank=True, on_delete=models.SET_NULL,
verbose_name='销售订单,审核之后不能改')
attachment_list = models.CharField('附件的id列表字段的值为: 1,2,3,4', max_length=20, null=True, blank=True)
class Meta:
db_table = 't_receipt'
verbose_name = '收款单表'
verbose_name_plural = verbose_name
ordering = ['id']
# 收款单中 收款项目的模型类
class ReceiptItemModel(BaseModel):
# 冗余字段
storage_code = models.CharField('销售出库单编号,不让用户填写', max_length=28)
deliver_storage = models.ForeignKey('warehouse_info.SaleDeliverModel', related_name='pay_item_list', null=True, blank=True,
on_delete=models.SET_NULL, verbose_name='采购入库单')
receipt = models.ForeignKey('ReceiptModel', null=True, blank=True, related_name='item_list', on_delete=models.SET_NULL,
verbose_name='收款单,不能改')
should_money = models.DecimalField('应该 收款金额(就是采购入库单中需要支收的金额),最多精确到小数点后两位', max_digits=10, decimal_places=2, default=0)
this_money = models.DecimalField('本次 收款金额,最多精确到小数点后两位', max_digits=10, decimal_places=2, default=0)
remark = models.CharField('备注', max_length=512, blank=True, null=True)
class Meta:
db_table = 't_receipt_item'
verbose_name = '收款单中的 收款项目表'
verbose_name_plural = verbose_name
ordering = ['id']

@ -0,0 +1,74 @@
from django.db import transaction
from django.db.models import Sum
from rest_framework import serializers
from rest_framework.exceptions import ValidationError
from financial_info.models import ReceiptModel, ReceiptItemModel
class ReceiptItemSerializer(serializers.ModelSerializer):
"""
收款单中 收款项目 的序列化器
"""
# 查询当前销售 出库单中已经 收金额
already_receipt = serializers.SerializerMethodField(read_only=True, help_text='已经收款的金额')
class Meta:
model = ReceiptItemModel
fields = '__all__'
def get_already_receipt(self, obj: ReceiptItemModel):
"""
查询当前 销售出库单中已经 收的货款金额
:param obj: ReceiptItemModel
:return: 0获取其他的数值
"""
if obj.deliver_storage:
sum_dict = ReceiptItemModel.objects.filter(deliver_storage_id=obj.deliver_storage.id)\
.exclude(receipt__status='0')\
.aggregate(sum=Sum('this_money'))
if sum_dict:
return sum_dict['sum'] if sum_dict['sum'] else 0
return 0
return 0
class ReceiptSerializer(serializers.ModelSerializer):
"""
收款单序列化器
"""
item_list = ReceiptItemSerializer(many=True, required=False)
class Meta:
model = ReceiptModel
fields = '__all__'
def create(self, validated_data):
if 'item_list' not in validated_data:
return super(ReceiptSerializer, self).create(validated_data)
item_list = validated_data.pop('item_list')
with transaction.atomic():
receipt = ReceiptModel.objects.create(**validated_data)
for item in item_list:
# 插入收款项目
ReceiptItemModel.objects.create(receipt=receipt, **item)
return receipt
# 必须重写update
def update(self, instance, validated_data):
if instance.status != '0':
raise ValidationError("收款单已经生效,不能修改!")
with transaction.atomic():
if 'item_list' in validated_data:
item_list = validated_data.pop('item_list')
old_list = instance.item_list.all()
if old_list.exists():
# 然后把旧数据删除因为在validated_data拿不到货品库存数据的ID
instance.item_list.all().delete()
for item in item_list: # 重新插入采购项 数据
ReceiptItemModel.objects.create(receipt=instance, **item)
result = super(ReceiptSerializer, self).update(instance=instance, validated_data=validated_data)
return result

@ -16,7 +16,7 @@ Including another URLconf
from django.contrib import admin
from django.urls import path, re_path
from rest_framework.routers import DefaultRouter
from .views import payment_views
from .views import payment_views, receipt_views
from rest_framework_jwt.views import obtain_jwt_token
@ -28,5 +28,6 @@ urlpatterns = [
router = DefaultRouter()
router.register('payment', payment_views.PaymentViewSet)
router.register('receipt', receipt_views.ReceiptViewSet)
urlpatterns += router.urls

@ -0,0 +1,197 @@
from django.db import transaction
from django.db.models import Q, F, Sum
from drf_yasg import openapi
from drf_yasg.utils import swagger_auto_schema
from rest_framework import viewsets, status
from rest_framework.decorators import action
from rest_framework.response import Response
from ERP_5.utils.base_views import MultipleDestroyMixin, MultipleAuditMixin
from ERP_5.utils.paginations import GlobalPagination
from basic_info.models import SettlementAccountModel, CustomerModel
from erp_system.models import UserModel
from financial_info.models import ReceiptModel, ReceiptItemModel
from financial_info.serializer.receipt_serializer import ReceiptSerializer
from warehouse_info.models import SaleDeliverModel
class ReceiptViewSet(viewsets.ModelViewSet, MultipleDestroyMixin, MultipleAuditMixin):
"""
create:
收款单--新增,注意其中images_list="1,2,3,4";里面是附件的ID
收款单新增, status: 201(成功), return: 新增收款单信息
destroy:
收款单--删除
收款单删除, status: 204(成功), return: None
multiple_delete:
收款单--批量删除,必传参数ids=[1,2,3,4...]
收款单批量删除, status: 204(成功), return: None
update:
收款单--修改,注意其中images_list="1,2,3,4";里面是附件的ID
收款单修改, status: 200(成功), return: 修改后的收款单信息
list:
收款单--该接口可以弃用
收款单列表信息, status: 200(成功), return: 收款单信息列表
retrieve:
查询某一个收款单
查询指定ID的收款单, status: 200(成功), return: 用户收款单
"""
queryset = ReceiptModel.objects.all()
serializer_class = ReceiptSerializer
pagination_class = GlobalPagination
def get_queryset(self):
if self.action == 'find': # 过滤查询
# 获取请求参数(在json中)
number_code = self.request.data.get('number_code', None)
check_user = self.request.data.get('check_user', 0)
start_date = self.request.data.get('start_date', None)
end_date = self.request.data.get('start_date', None)
customer = self.request.data.get('customer', 0)
operator_user = self.request.data.get('operator_user', 0)
status = self.request.data.get('status', None)
account = self.request.data.get('account', 0)
sale_number_code = self.request.data.get('sale_number_code', None)
query = Q()
if check_user:
query.add(Q(check_user__id=check_user), 'AND')
if account:
query.add(Q(account__id=account), 'AND')
if sale_number_code:
query.add(Q(sale__number_code__contains=sale_number_code), 'AND')
if start_date:
query.add(Q(pay_date__gt=start_date), 'AND')
if end_date:
query.add(Q(pay_date__lt=end_date), 'AND')
if customer:
query.add(Q(customer__id=customer), 'AND')
if number_code:
query.add(Q(number_code__contains=number_code), 'AND')
if operator_user:
query.add(Q(operator_user__id=operator_user), 'AND')
if status:
query.add(Q(status=status), 'AND')
return ReceiptModel.objects.filter(query).distinct().all()
else:
return ReceiptModel.objects.all()
params = openapi.Schema(type=openapi.TYPE_OBJECT, properties={
'start_date': openapi.Schema(type=openapi.TYPE_STRING, description="起始日期2020-10-01"),
'number_code': openapi.Schema(type=openapi.TYPE_STRING, description="收款单编号(序列号)"),
'end_date': openapi.Schema(type=openapi.TYPE_STRING, description="结束日期2020-10-01"),
'status': openapi.Schema(type=openapi.TYPE_STRING, description="状态0或者1"),
'customer': openapi.Schema(type=openapi.TYPE_INTEGER, description="客户的ID"),
'operator_user': openapi.Schema(type=openapi.TYPE_INTEGER, description="财务人员的ID"),
'check_user': openapi.Schema(type=openapi.TYPE_INTEGER, description="审核人员的ID"),
'account': openapi.Schema(type=openapi.TYPE_INTEGER, description="结算账户的ID"),
'sale_number_code': openapi.Schema(type=openapi.TYPE_STRING, description="销售订单编号关键字"),
})
# 分页参数必须是query_param(看源码)
page_param = openapi.Parameter(name='page', in_=openapi.IN_QUERY, description="页号", type=openapi.TYPE_INTEGER)
size_param = openapi.Parameter(name='size', in_=openapi.IN_QUERY, description="每页显示数量",
type=openapi.TYPE_INTEGER)
@swagger_auto_schema(method='POST', request_body=params, manual_parameters=[page_param, size_param],
operation_description="收款单的搜索过滤")
@action(methods=['POST'], detail=False)
def find(self, request, *args, **kwargs):
return super(ReceiptViewSet, self).list(request=request, *args, **kwargs)
"""
自定义的 批量审核的 视图函数
"""
body_param = openapi.Schema(type=openapi.TYPE_OBJECT, required=['ids', 'user_id'], properties={
'ids': openapi.Schema(type=openapi.TYPE_ARRAY, items=openapi.Schema(type=openapi.TYPE_INTEGER),
description="选择哪些需要批量的ID主键列表"),
'user_id': openapi.Schema(type=openapi.TYPE_INTEGER, description="审核人的用户ID"),
})
@swagger_auto_schema(method='put', request_body=body_param, operation_description="批量审核")
@action(methods=['put'], detail=False)
@transaction.atomic # 自动 数据库事务
def multiple_audit(self, request, *args, **kwargs):
audit_ids = request.data.get('ids')
user_id = request.data.get('user_id') # 用户ID
is_audit = request.data.get('is_audit', '1') # 审核1
# 为了减少代码量,参数的验证就不写了
queryset = self.get_queryset().filter(id__in=audit_ids).all()
check_user = UserModel.objects.get(id=int(user_id))
for receipt in queryset: # 期中receipt是收款单
# 判断1关联的销售 单状态是否为“未审核”
if receipt.sale and receipt.sale.status == '0':
return Response(data={'detail': '销售订单未审核,不能收款'}, status=status.HTTP_400_BAD_REQUEST)
# 判断2 收款单的状态是否为:“已审核”
if receipt.status == '1':
return Response(data={'detail': '收款单已经审核,不需要再次审核'}, status=status.HTTP_400_BAD_REQUEST)
# 处理关联业务逻辑
# 业务一: 销售定金收款
if receipt.receipt_category == '1' and receipt.sale and not receipt.item_list.exists():
receipt.sale.status = '5' # 已收 销售定金
receipt.sale.save()
# 业务二: 客户还款 的收款
if receipt.receipt_category == '3' and not receipt.item_list.exists():
CustomerModel.objects.filter(id=receipt.customer.id).update(
current_receivable=F('current_receivable') - receipt.this_money)
# 业务三: 出库货款 的收入
if receipt.receipt_category == '2' and receipt.sale:
if receipt.item_list.exists(): # 这种判断不回从数据库中返回数据
for item in receipt.item_list.all(): # 期中item是收款项目
# 判断4 出库单必须是已经审核状态
if item.deliver_storage and item.deliver_storage.status != '1':
return Response(data={'detail': '出库单未审核或者已经收款,不能收款'},
status=status.HTTP_400_BAD_REQUEST)
# 业务三——第1种情况 对应的出库单,是否应该:收款完成 ,首先需要查询该出库单的已经收款金额之和
sum_dict = ReceiptItemModel.objects \
.filter(deliver_storage_id=item.deliver_storage.id, receipt__status='1') \
.aggregate(sum=Sum('this_money'))
in_sum = sum_dict['sum'] if sum_dict['sum'] else 0
if item.should_money == (in_sum + item.this_money):
item.deliver_storage.status = '2' # 把出库单的状态修改为:收款完成
item.deliver_storage.save()
# 业务三——第2种情况 对应的销售单状态是否要改为:销售完成
# 销售完成的条件: 1、该销售单必须是全部出库状态2、该销售单中 所有的出库单状态也都必须是:收款完成
sale = item.receipt.sale
if sale.status == '3':
# 查询 该销售单中 所有出库单状态不是:'收款完成' 的有多少个?
number = SaleDeliverModel.objects \
.filter(sale_id=sale.id) \
.exclude(status='2').count()
if number == 0: # 则 所有的出库单状态都为:收款完成
sale.status = '4' # 修改销售单状态为: 销售完成
sale.save()
else:
return Response(data={'detail': '没有选择收款项目,支收货款的时候必须选择'},
status=status.HTTP_400_BAD_REQUEST)
# 至此: 三种业务都完成
# 业务四: 修改 结算账户的余额
SettlementAccountModel.objects.filter(id=receipt.account.id) \
.update(balance=F('balance') + receipt.this_money)
# 至此: 四种业务都完成,开始修改收款单的状态以及审核信息
# 审核
self.get_queryset().filter(id__in=audit_ids) \
.update(
status='1',
check_user_name=check_user.real_name,
check_user_id=check_user.id)
return Response(status=status.HTTP_200_OK)

@ -0,0 +1,44 @@
from rest_framework import serializers
from ERP_5.utils.get_inventory import get_inventory_by_goods
from goods_info.models import GoodsModel
from production_info.models import BomProcessModel, BomMaterialModel
class ProcessSerializer(serializers.ModelSerializer):
"""
生产工序的 序列化器
"""
class Meta:
model = BomProcessModel
fields = '__all__'
class MaterialSerializer(serializers.ModelSerializer):
"""
生产物料的 序列化器
"""
cur_inventory = serializers.SerializerMethodField(read_only=True, help_text='在仓库中库存')
class Meta:
model = BomMaterialModel
fields = '__all__'
def get_cur_inventory(self, obj: BomMaterialModel): # 当前的obj为BomMaterialModel
result = get_inventory_by_goods(obj.goods.id)
return result if result else 0
class GoodsBomSerializer(serializers.ModelSerializer):
"""
某一个货品的BOM表数据 序列化器
"""
# 当前商品BOM表中所有的 生产工序列表
process_list = ProcessSerializer(many=True, read_only=True)
# 当前商品BOM表中所有的 生产物料列表
material_list = MaterialSerializer(many=True, read_only=True)
class Meta:
model = GoodsModel
fields = ['number_code', 'name', 'material_list', 'process_list']

@ -0,0 +1,153 @@
from django.db import transaction
from django.db.models import F
from django.utils import timezone
from rest_framework import serializers
from rest_framework.exceptions import ValidationError
from ERP_5.utils.cont import NumberPrefix
from ERP_5.utils.generate_code import generate_code
from ERP_5.utils.get_inventory import get_inventory_by_goods
from basic_info.models import WarehouseModel
from goods_info.models import GoodsModel, GoodsInventoryModel
from production_info.models import ProductProcessModel, ProductMaterialModel, ProductTaskModel
from warehouse_info.models import SaleDeliverModel, SaleDeliverItemModel
class ProductProcessSerializer(serializers.ModelSerializer):
"""
生产计划中的生产工序 序列化器
"""
class Meta:
model = ProductProcessModel
fields = '__all__'
class ProductMaterialSerializer(serializers.ModelSerializer):
"""
生产计划中的生产物料 序列化器
"""
cur_inventory = serializers.SerializerMethodField(read_only=True, help_text='在仓库中库存')
class Meta:
model = ProductMaterialModel
fields = '__all__'
def get_cur_inventory(self, obj: ProductMaterialModel): # 当前的obj为ProductMaterialModel
result = get_inventory_by_goods(obj.goods.id)
return result if result else 0
class ProductTaskSerializer(serializers.ModelSerializer):
"""
生产任务的 序列化器
"""
# 当前生产任务中所有的: 生产工序列表
process_list = ProductProcessSerializer(many=True)
# 当前生产任务中所有的: 生产物料列表
material_list = ProductMaterialSerializer(many=True)
class Meta:
model = ProductTaskModel
fields = '__all__'
def create(self, validated_data):
process_list = validated_data.pop('process_list')
material_list = validated_data.pop('material_list')
with transaction.atomic():
pt = ProductTaskModel.objects.create(**validated_data)
for item in process_list:
ProductProcessModel.objects.create(product_task=pt, **item)
for item in material_list:
ProductMaterialModel.objects.create(product_task=pt, **item)
return pt
def update(self, instance, validated_data):
if instance.status != '0':
raise ValidationError("生产任务已经生效,不能修改!")
process_list = validated_data.pop('process_list')
material_list = validated_data.pop('material_list')
old_list1 = instance.process_list
old_list2 = instance.material_list
with transaction.atomic():
if old_list1.exists():
# 然后把旧数据删除因为在validated_data拿不到货品库存数据的ID
instance.process_list.all().delete()
if old_list2.exists():
# 然后把旧数据删除因为在validated_data拿不到货品库存数据的ID
instance.material_list.all().delete()
for item in process_list:
ProductProcessModel.objects.create(product_task=instance, **item)
for item in material_list:
ProductMaterialModel.objects.create(product_task=instance, **item)
result = super(ProductTaskSerializer, self).update(instance=instance, validated_data=validated_data)
return result
class GetMaterialSerializer(serializers.Serializer):
"""
领料的序列化器
"""
def update(self, instance, validated_data):
pass
def create(self, validated_data):
# 需要完成4件事情
with transaction.atomic():
# 1、插入出库单
deliver = SaleDeliverModel.objects.create(invoices_date=timezone.now(),
number_code=generate_code(NumberPrefix['deliver'].value),
last_amount=validated_data['money'],
number_count=validated_data['count'],
product_task_id=validated_data['pt_id'],
status='1',
is_other='1')
# 2、插入出库项目
goods = GoodsModel.objects.get(pk=validated_data['good_id'])
wh = WarehouseModel.objects.get(pk=validated_data['warehouse_id'])
psi = SaleDeliverItemModel()
psi.goods_id = goods.id
psi.specification = goods.specification
psi.model_number = goods.model_number
psi.number_code = goods.number_code
psi.color = goods.color
psi.category = goods.category
psi.category_name = goods.category.name
psi.units = goods.units
psi.units_name = goods.units.basic_name
psi.name = goods.name
psi.sale_count = validated_data['count']
psi.sale_price = validated_data['price']
psi.sale_money = validated_data['money']
psi.warehouse_name = wh.name
psi.warehouse_id = wh.id
psi.sale_deliver_id = deliver.id
psi.save()
# 3、 修改库存数量
GoodsInventoryModel.objects \
.filter(goods_id=goods.id, warehouse_id=wh.id) \
.update(cur_inventory=F('cur_inventory') - psi.sale_count)
# 4、 修改生产物料中领料数量
ProductMaterialModel.objects.filter(id=validated_data['material_id']) \
.update(get_count=F('get_count') + psi.sale_count)
return deliver
goods_number_code = serializers.CharField(help_text='物料的条码或者编号', required=False)
warehouse_name = serializers.CharField(help_text='领取仓库的名字')
warehouse_id = serializers.IntegerField(help_text='领取仓库的主键')
good_id = serializers.IntegerField(help_text='领取的货品主键')
count = serializers.DecimalField(help_text='领取数量,最多精确到小数点后两位', max_digits=10, decimal_places=2, default=0)
price = serializers.DecimalField(help_text='领取的成本单价,最多精确到小数点后两位', max_digits=10, decimal_places=2, default=0)
money = serializers.DecimalField(help_text='领取的成本总价,最多精确到小数点后两位', max_digits=10, decimal_places=2, default=0)
material_id = serializers.IntegerField(help_text='所属生产物料的主键')
pt_id = serializers.IntegerField(help_text='所属生产任务的主键')

@ -0,0 +1,35 @@
"""ERP_5 URL Configuration
The `urlpatterns` list routes URLs to views. For more information please see:
https://docs.djangoproject.com/en/3.2/topics/http/urls/
Examples:
Function views
1. Add an import: from my_app import views
2. Add a URL to urlpatterns: path('', views.home, name='home')
Class-based views
1. Add an import: from other_app.views import Home
2. Add a URL to urlpatterns: path('', Home.as_view(), name='home')
Including another URLconf
1. Import the include() function: from django.urls import include, path
2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
"""
from django.contrib import admin
from django.urls import path, re_path
from rest_framework.routers import DefaultRouter
from .views import bom_views, product_task_views
from rest_framework_jwt.views import obtain_jwt_token
urlpatterns = [
# path('admin/', admin.site.urls),
]
router = DefaultRouter()
router.register('bom_material', bom_views.MaterialViewSets)
router.register('bom_process', bom_views.ProcessViewSets)
router.register('bom', bom_views.GoodsBomViewSet)
router.register('products', product_task_views.ProductTaskViewSets)
urlpatterns += router.urls

@ -0,0 +1,84 @@
from rest_framework import mixins, viewsets
from ERP_5.utils.base_views import MultipleDestroyMixin
from goods_info.models import GoodsModel
from production_info.models import BomMaterialModel, BomProcessModel
from production_info.serializer.bom_serializer import MaterialSerializer, ProcessSerializer, GoodsBomSerializer
class MaterialViewSets(mixins.CreateModelMixin, mixins.UpdateModelMixin, mixins.DestroyModelMixin,
mixins.RetrieveModelMixin, viewsets.GenericViewSet, MultipleDestroyMixin):
"""
create:
生产物料--新增,
生产物料新增, status: 201(成功), return: 新增生产物料信息
destroy:
生产物料--删除
生产物料删除, status: 204(成功), return: None
multiple_delete:
生产物料--批量删除,必传参数ids=[1,2,3,4...]
生产物料批量删除, status: 204(成功), return: None
update:
生产物料--修改,
生产物料修改, status: 200(成功), return: 修改后的生产物料信息
retrieve:
查询某一个生产物料
查询指定ID的生产物料, status: 200(成功), return: 生产物料
"""
queryset = BomMaterialModel.objects.all()
serializer_class = MaterialSerializer
class ProcessViewSets(mixins.CreateModelMixin, mixins.RetrieveModelMixin, mixins.UpdateModelMixin,
mixins.DestroyModelMixin, viewsets.GenericViewSet, MultipleDestroyMixin):
"""
create:
生产工序--新增,
生产工序新增, status: 201(成功), return: 新增生产工序信息
destroy:
生产工序--删除
生产工序删除, status: 204(成功), return: None
multiple_delete:
生产工序--批量删除,必传参数ids=[1,2,3,4...]
生产工序批量删除, status: 204(成功), return: None
update:
生产工序--修改,
生产工序修改, status: 200(成功), return: 修改后的生产物料信息
retrieve:
查询某一个生产工序
查询指定ID的生产工序, status: 200(成功), return: 生产工序
"""
queryset = BomProcessModel.objects.all()
serializer_class = ProcessSerializer
class GoodsBomViewSet(mixins.RetrieveModelMixin, viewsets.GenericViewSet):
"""
retrieve:
查询某一个货品的BOM表数据包括BOM表中物料清单和工序清单
包括BOM中的物料清单和生产工序列表, status: 200(成功), return: BOM表
"""
serializer_class = GoodsBomSerializer
queryset = GoodsModel.objects.all()

@ -0,0 +1,110 @@
from django.db.models import Q
from drf_yasg import openapi
from drf_yasg.utils import swagger_auto_schema
from rest_framework import viewsets
from rest_framework.decorators import action
from rest_framework.response import Response
from ERP_5.utils.base_views import MultipleDestroyMixin, MultipleAuditMixin
from ERP_5.utils.paginations import GlobalPagination
from production_info.models import ProductTaskModel
from production_info.serializer.product_task_serializer import ProductTaskSerializer, GetMaterialSerializer
class ProductTaskViewSets(viewsets.ModelViewSet, MultipleDestroyMixin, MultipleAuditMixin):
"""
create:
生产任务--新增,注意如果有BOM表则直接读取BOM如果没有需要自己添加生产物料和工序
生产任务新增, status: 201(成功), return: 新增生产任务信息
destroy:
生产任务--删除
生产任务删除, status: 204(成功), return: None
multiple_delete:
生产任务--批量删除,必传参数ids=[1,2,3,4...]
生产任务批量删除, status: 204(成功), return: None
update:
生产任务--修改,注意其中images_list="1,2,3,4";里面是附件的ID
生产任务修改, status: 200(成功), return: 修改后的生产任务信息
partial_update:
生产任务--局部修改,可以传参任意属性的值服务器会修改指定的属性值
生产任务局部修改, status: 200(成功), return: 修改后的生产任务信息
list:
生产任务--该接口可以弃用
生产任务列表信息, status: 200(成功), return: 生产任务信息列表
retrieve:
查询某一个生产任务
查询指定ID的生产任务, status: 200(成功), return: 用户生产任务
"""
queryset = ProductTaskModel.objects.all()
serializer_class = ProductTaskSerializer
pagination_class = GlobalPagination
def get_queryset(self):
if self.action == 'find': # 过滤查询
# 获取请求参数(在json中)
number_code = self.request.data.get('number_code', None)
keyword = self.request.data.get('keyword', None)
start_date = self.request.data.get('start_date', None)
end_date = self.request.data.get('start_date', None)
query = Q()
if keyword:
child_query = Q()
child_query.add(Q(name__contains=keyword), 'OR')
child_query.add(Q(specification=keyword), 'OR')
query.add(child_query, 'AND')
if start_date:
query.add(Q(invoices_date__gt=start_date), 'AND')
if end_date:
query.add(Q(invoices_date__lt=end_date), 'AND')
if number_code:
query.add(Q(number_code__contains=number_code), 'AND')
return ProductTaskModel.objects.filter(query).distinct().all()
else:
return ProductTaskModel.objects.all()
params = openapi.Schema(type=openapi.TYPE_OBJECT, properties={
'keyword': openapi.Schema(type=openapi.TYPE_STRING, description="名称的关键字或者型号"),
'start_date': openapi.Schema(type=openapi.TYPE_STRING, description="起始日期2020-10-01"),
'number_code': openapi.Schema(type=openapi.TYPE_STRING, description="编号(序列号)"),
'end_date': openapi.Schema(type=openapi.TYPE_STRING, description="结束日期2020-10-01")
})
# 分页参数必须是query_param(看源码)
page_param = openapi.Parameter(name='page', in_=openapi.IN_QUERY, description="页号", type=openapi.TYPE_INTEGER)
size_param = openapi.Parameter(name='size', in_=openapi.IN_QUERY, description="每页显示数量",
type=openapi.TYPE_INTEGER)
@swagger_auto_schema(method='POST', request_body=params, manual_parameters=[page_param, size_param],
operation_description="生产任务的搜索过滤")
@action(methods=['POST'], detail=False)
def find(self, request, *args, **kwargs):
return super(ProductTaskViewSets, self).list(request=request, *args, **kwargs)
@swagger_auto_schema(method='POST', request_body=GetMaterialSerializer,
operation_description="生产任务中领取物料")
@action(methods=['POST'], detail=False)
def get_material(self, request, *args, **kwargs):
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
result = serializer.save()
return Response({'msg': 'ok'})
def get_serializer_class(self):
if self.action == 'get_material':
return GetMaterialSerializer
else:
return ProductTaskSerializer

@ -144,6 +144,10 @@ class SaleDeliverModel(BaseModel):
is_other = models.CharField('是否是其他出库,0:销售出库,1:其他出库', max_length=1, default='0')
product_task = models.ForeignKey('production_info.ProductTaskModel', null=True, blank=True,
on_delete=models.SET_NULL,
verbose_name='所属的生产任务')
class Meta:
db_table = 't_sale_deliver'
verbose_name = '出库单表'

@ -1,8 +1,10 @@
from django.db import transaction
from django.db.models import Sum
from rest_framework import serializers
from rest_framework.exceptions import ValidationError
from ERP_5.utils.get_inventory import get_inventory_by_goods
from financial_info.models import ReceiptItemModel
from warehouse_info.models import SaleDeliverItemModel, SaleDeliverModel
@ -30,10 +32,28 @@ class DeliverySerializer(serializers.ModelSerializer):
# 出库单列表中需要展示:商品信息。
goods_info = serializers.SerializerMethodField(read_only=True, label='列表中展示的商品信息')
# 查询当前销售 出库单中已经 收金额
already_receipt = serializers.SerializerMethodField(read_only=True, help_text='已经收款的金额')
class Meta:
model = SaleDeliverModel
fields = '__all__'
def get_already_receipt(self, obj: SaleDeliverModel):
"""
查询当前 销售出库单中已经 收的货款金额
:param obj: SaleDeliverModel
:return: 0获取其他的数值
"""
sum_dict = ReceiptItemModel.objects.filter(deliver_storage_id=obj.id)\
.exclude(receipt__status='0')\
.aggregate(sum=Sum('this_money'))
if sum_dict:
return sum_dict['sum'] if sum_dict['sum'] else 0
return 0
def get_goods_info(self, obj):
"""
商品信息是由 商品1名称 商品1规格 , 商品2名称 商品2规格 ....

@ -48,6 +48,7 @@ INSTALLED_APPS = [
'warehouse_info',
'financial_info',
'sale_info',
'production_info',
# 'django.contrib.staticfiles', # required for serving swagger ui's css/js files
'drf_yasg',

@ -42,6 +42,7 @@ urlpatterns = [
path('api/', include('warehouse_info.urls')),
path('api/', include('financial_info.urls')),
path('api/', include('sale_info.urls')),
path('api/', include('production_info.urls')),
re_path(r'^api/generate_code/$', GenerateCode.as_view()),
# 媒体资源文件的访问路由

@ -15,3 +15,7 @@ class NumberPrefix(Enum): # 定义编号的前缀
cat = 'CAT'
# 商品信息编号的前缀
goo = 'GOO'
# 出库单编号的前缀
deliver = 'OUT'
# 入库单编号的前缀
storage = 'INS'

Loading…
Cancel
Save