销售记录接口
This commit is contained in:
parent
58d1ccc9bf
commit
c2b38f3f1e
|
@ -1,9 +1,17 @@
|
|||
from django_filters import rest_framework as filters
|
||||
|
||||
from apps.mtm.models import Material
|
||||
from .models import MaterialBatch
|
||||
from .models import IProduct, MaterialBatch
|
||||
class MbFilterSet(filters.FilterSet):
|
||||
material = filters.ModelMultipleChoiceFilter(field_name="material", queryset=Material.objects.all())
|
||||
class Meta:
|
||||
model = MaterialBatch
|
||||
fields = ['material', 'warehouse']
|
||||
fields = ['material', 'warehouse']
|
||||
|
||||
|
||||
class IProductFilterSet(filters.FilterSet):
|
||||
|
||||
order = filters.NumberFilter(field_name="wproduct__subproduction_plan__production_plan__order")
|
||||
class Meta:
|
||||
model = IProduct
|
||||
fields = ['material', 'warehouse', 'batch', 'order']
|
|
@ -0,0 +1,18 @@
|
|||
# Generated by Django 3.2.9 on 2021-12-06 01:58
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('inm', '0019_auto_20211201_1011'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='iproduct',
|
||||
name='is_saled',
|
||||
field=models.BooleanField(default=False, verbose_name='是否售出'),
|
||||
),
|
||||
]
|
|
@ -102,5 +102,6 @@ class IProduct(BaseModel):
|
|||
warehouse = models.ForeignKey(WareHouse, on_delete=models.CASCADE, verbose_name='所在仓库')
|
||||
batch = models.CharField('所属批次号', max_length=100, default='')
|
||||
wproduct = models.ForeignKey('wpm.wproduct', on_delete=models.CASCADE, verbose_name='关联的动态产品', db_constraint=False, null=True, blank=True)
|
||||
is_saled = models.BooleanField('是否售出', default=False)
|
||||
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@ from rest_framework import serializers
|
|||
|
||||
from apps.inm.models import FIFO, FIFOItem, FIFOItemProduct, IProduct, MaterialBatch, WareHouse,Inventory
|
||||
from apps.qm.models import TestRecord, TestRecordItem
|
||||
from apps.sam.serializers import OrderSimpleSerializer
|
||||
|
||||
from apps.system.serializers import UserSimpleSerializer
|
||||
from apps.mtm.serializers import MaterialSimpleSerializer
|
||||
|
@ -40,10 +41,18 @@ class MaterialBatchSerializer(serializers. ModelSerializer):
|
|||
class IProductListSerializer(serializers.ModelSerializer):
|
||||
material_= MaterialSimpleSerializer(source='material', read_only=True)
|
||||
warehouse_ = WareHouseSimpleSerializer(source='warehouse', read_only=True)
|
||||
order_ = serializers.SerializerMethodField()
|
||||
class Meta:
|
||||
model = IProduct
|
||||
fields = '__all__'
|
||||
|
||||
def get_order_(self, obj):
|
||||
if obj.wproduct:
|
||||
order = obj.wproduct.subproduction_plan.production_plan.order
|
||||
if order:
|
||||
return OrderSimpleSerializer(instance=order).data
|
||||
return None
|
||||
|
||||
|
||||
class FIFOListSerializer(serializers.ModelSerializer):
|
||||
auditor_ = UserSimpleSerializer(source='auditor', read_only=True)
|
||||
|
|
|
@ -3,7 +3,7 @@ from rest_framework import serializers
|
|||
from rest_framework.exceptions import APIException
|
||||
from rest_framework.mixins import DestroyModelMixin, ListModelMixin, RetrieveModelMixin
|
||||
from rest_framework.viewsets import GenericViewSet, ModelViewSet
|
||||
from apps.inm.filters import MbFilterSet
|
||||
from apps.inm.filters import IProductFilterSet, MbFilterSet
|
||||
|
||||
from apps.inm.models import FIFO, FIFOItem, IProduct, MaterialBatch, WareHouse,Inventory
|
||||
from apps.inm.serializers import FIFOItemSerializer, FIFOInPurSerializer, FIFOListSerializer, IProductListSerializer, InmTestRecordCreateSerializer, MaterialBatchQuerySerializer, MaterialBatchSerializer, WareHouseSerializer, WareHouseCreateUpdateSerializer,InventorySerializer
|
||||
|
@ -167,9 +167,9 @@ class IProductViewSet(ListModelMixin, GenericViewSet):
|
|||
半成品库存表
|
||||
"""
|
||||
perms_map = {'*': '*'}
|
||||
queryset = IProduct.objects.select_related('material', 'warehouse').all()
|
||||
queryset = IProduct.objects.select_related('material', 'warehouse', 'wproduct__subproduction_plan__production_plan__order').filter(is_saled=False)
|
||||
serializer_class = IProductListSerializer
|
||||
filterset_fields = ['material', 'warehouse', 'batch']
|
||||
filterset_class = IProductFilterSet
|
||||
search_fields = []
|
||||
ordering_fields = ['create_time']
|
||||
ordering = ['-create_time']
|
|
@ -0,0 +1,28 @@
|
|||
# Generated by Django 3.2.9 on 2021-12-03 07:01
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('sam', '0004_order_planed_count'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='order',
|
||||
name='delivered_count',
|
||||
field=models.PositiveIntegerField(default=0, verbose_name='交货数量'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='order',
|
||||
name='count',
|
||||
field=models.PositiveIntegerField(default=0, verbose_name='所需数量'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='order',
|
||||
name='planed_count',
|
||||
field=models.PositiveIntegerField(default=0, verbose_name='已排数量'),
|
||||
),
|
||||
]
|
|
@ -0,0 +1,65 @@
|
|||
# Generated by Django 3.2.9 on 2021-12-06 01:58
|
||||
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
import django.utils.timezone
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
('inm', '0020_iproduct_is_saled'),
|
||||
('mtm', '0041_alter_material_type'),
|
||||
('sam', '0005_auto_20211203_1501'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='order',
|
||||
name='delivered_count',
|
||||
field=models.PositiveIntegerField(default=0, verbose_name='已交货数量'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='order',
|
||||
name='number',
|
||||
field=models.CharField(max_length=100, unique=True, verbose_name='订单编号'),
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Sale',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('create_time', models.DateTimeField(default=django.utils.timezone.now, help_text='创建时间', verbose_name='创建时间')),
|
||||
('update_time', models.DateTimeField(auto_now=True, help_text='修改时间', verbose_name='修改时间')),
|
||||
('is_deleted', models.BooleanField(default=False, help_text='删除标记', verbose_name='删除标记')),
|
||||
('count', models.PositiveIntegerField(default=0, verbose_name='交货数量')),
|
||||
('is_audited', models.BooleanField(default=False, verbose_name='是否审核')),
|
||||
('create_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='sale_create_by', to=settings.AUTH_USER_MODEL, verbose_name='创建人')),
|
||||
('customer', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='sam.customer', verbose_name='客户')),
|
||||
('order', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='sam.order', verbose_name='关联订单')),
|
||||
('product', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='mtm.material', verbose_name='所需产品')),
|
||||
('update_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='sale_update_by', to=settings.AUTH_USER_MODEL, verbose_name='最后编辑人')),
|
||||
],
|
||||
options={
|
||||
'abstract': False,
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='SaleProduct',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('create_time', models.DateTimeField(default=django.utils.timezone.now, help_text='创建时间', verbose_name='创建时间')),
|
||||
('update_time', models.DateTimeField(auto_now=True, help_text='修改时间', verbose_name='修改时间')),
|
||||
('is_deleted', models.BooleanField(default=False, help_text='删除标记', verbose_name='删除标记')),
|
||||
('number', models.CharField(max_length=50, unique=True, verbose_name='物品编号')),
|
||||
('is_mtested', models.BooleanField(default=False, verbose_name='是否军检')),
|
||||
('is_mtestok', models.BooleanField(default=True, verbose_name='是否军检合格')),
|
||||
('iproduct', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='sale_iproduct', to='inm.iproduct', verbose_name='关联库存产品')),
|
||||
('sale', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='sam.sale', verbose_name='关联销售记录')),
|
||||
],
|
||||
options={
|
||||
'unique_together': {('sale', 'iproduct')},
|
||||
},
|
||||
),
|
||||
]
|
|
@ -1,4 +1,4 @@
|
|||
from apps.system.models import CommonAModel
|
||||
from apps.system.models import CommonADModel, CommonAModel
|
||||
from django.db import models
|
||||
from django.contrib.auth.models import AbstractUser
|
||||
from django.db.models.base import Model
|
||||
|
@ -58,16 +58,47 @@ class Order(CommonAModel):
|
|||
"""
|
||||
订单信息
|
||||
"""
|
||||
number = models.CharField('订单编号', max_length=100)
|
||||
number = models.CharField('订单编号', max_length=100, unique=True)
|
||||
customer = models.ForeignKey(Customer, verbose_name='客户', on_delete=models.CASCADE)
|
||||
contract = models.ForeignKey(Contract, verbose_name='所属合同', null=True, blank=True, on_delete=models.SET_NULL)
|
||||
product = models.ForeignKey(Material, verbose_name='所需产品', on_delete=models.CASCADE)
|
||||
count = models.IntegerField('所需数量', default=0)
|
||||
planed_count = models.IntegerField('已排数量', default=0)
|
||||
count = models.PositiveIntegerField('所需数量', default=0)
|
||||
planed_count = models.PositiveIntegerField('已排数量', default=0)
|
||||
delivered_count = models.PositiveIntegerField('已交货数量', default=0)
|
||||
delivery_date = models.DateField('交货日期')
|
||||
class Meta:
|
||||
verbose_name = '订单信息'
|
||||
verbose_name_plural = verbose_name
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
return self.name
|
||||
|
||||
|
||||
class Sale(CommonADModel):
|
||||
"""
|
||||
销售记录
|
||||
"""
|
||||
customer = models.ForeignKey(Customer, verbose_name='客户', on_delete=models.CASCADE)
|
||||
order = models.ForeignKey(Order, verbose_name='关联订单', on_delete=models.CASCADE, null=True, blank=True)
|
||||
product = models.ForeignKey(Material, verbose_name='所需产品', on_delete=models.CASCADE)
|
||||
count = models.PositiveIntegerField('交货数量', default=0)
|
||||
is_audited = models.BooleanField('是否审核', default=False)
|
||||
|
||||
|
||||
class SaleProduct(BaseModel):
|
||||
"""
|
||||
具体产品
|
||||
"""
|
||||
sale = models.ForeignKey(Sale, verbose_name='关联销售记录', on_delete=models.CASCADE)
|
||||
number = models.CharField('物品编号', unique=True, max_length=50)
|
||||
iproduct = models.ForeignKey('inm.iproduct', verbose_name='关联库存产品', on_delete=models.CASCADE, related_name='sale_iproduct')
|
||||
is_mtested = models.BooleanField('是否军检', default=False)
|
||||
is_mtestok = models.BooleanField('是否军检合格', default=True)
|
||||
|
||||
class Meta:
|
||||
unique_together = (
|
||||
('sale','iproduct'), # 联合唯一
|
||||
)
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
from rest_framework import serializers
|
||||
|
||||
from .models import Contract, Customer, Order
|
||||
from apps.inm.models import IProduct
|
||||
|
||||
from .models import Contract, Customer, Order, Sale, SaleProduct
|
||||
|
||||
from apps.mtm.serializers import MaterialSimpleSerializer
|
||||
|
||||
|
@ -54,3 +56,38 @@ class OrderSimpleSerializer(serializers.ModelSerializer):
|
|||
class Meta:
|
||||
model = Order
|
||||
fields = '__all__'
|
||||
|
||||
class SaleCreateSerializer(serializers.ModelSerializer):
|
||||
iproducts = serializers.PrimaryKeyRelatedField(queryset=IProduct.objects.all(), many=True)
|
||||
class Meta:
|
||||
model = Sale
|
||||
fields = ['customer', 'order', 'product', 'iproducts']
|
||||
|
||||
def validate(self, attrs):
|
||||
order = attrs.get('order', None)
|
||||
if order:
|
||||
if order.customer:
|
||||
attrs['customer'] = order.customer
|
||||
attrs['product'] = order.product
|
||||
return super().validate(attrs)
|
||||
|
||||
def create(self, validated_data):
|
||||
iproducts = validated_data.pop('iproducts')
|
||||
sale = Sale.objects.create(**validated_data)
|
||||
i_l = []
|
||||
for i in iproducts:
|
||||
i_d ={}
|
||||
i_d['sale'] = sale
|
||||
i_d['number'] = i.number
|
||||
i_d['iproduct'] = i
|
||||
i_l.append(SaleProduct(**i_d))
|
||||
SaleProduct.objects.bulk_create(i_l)
|
||||
return sale
|
||||
|
||||
class SaleListSerializer(serializers.ModelSerializer):
|
||||
customer_ = CustomerSimpleSerializer(source='customer', read_only=True)
|
||||
order_ = OrderSimpleSerializer(source='order', read_only=True)
|
||||
product_ = MaterialSimpleSerializer(source='product', read_only=True)
|
||||
class Meta:
|
||||
model = Sale
|
||||
fields = '__all__'
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
from django.db.models import base
|
||||
from rest_framework import urlpatterns
|
||||
from apps.sam.views import CustomerViewSet,ContractViewSet,OrderViewSet
|
||||
from apps.sam.views import CustomerViewSet,ContractViewSet,OrderViewSet, SaleViewSet
|
||||
from django.urls import path, include
|
||||
from rest_framework.routers import DefaultRouter
|
||||
|
||||
|
@ -8,6 +8,7 @@ router = DefaultRouter()
|
|||
router.register('customer', CustomerViewSet, basename='customer')
|
||||
router.register('contract', ContractViewSet, basename='contract')
|
||||
router.register('order', OrderViewSet, basename='order')
|
||||
router.register('sale', SaleViewSet, basename='sale')
|
||||
|
||||
urlpatterns = [
|
||||
path('', include(router.urls)),
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
from apps.sam.serializers import ContractCreateUpdateSerializer, ContractSerializer, CustomerCreateUpdateSerializer, CustomerSerializer, OrderCreateUpdateSerializer, OrderSerializer
|
||||
from apps.sam.models import Contract, Customer, Order
|
||||
from rest_framework.viewsets import ModelViewSet
|
||||
from rest_framework.mixins import CreateModelMixin, ListModelMixin, RetrieveModelMixin
|
||||
from apps.sam.serializers import ContractCreateUpdateSerializer, ContractSerializer, CustomerCreateUpdateSerializer, CustomerSerializer, OrderCreateUpdateSerializer, OrderSerializer, SaleCreateSerializer, SaleListSerializer
|
||||
from apps.sam.models import Contract, Customer, Order, Sale
|
||||
from rest_framework.viewsets import GenericViewSet, ModelViewSet
|
||||
from apps.system.mixins import CreateUpdateCustomMixin
|
||||
from django.shortcuts import render
|
||||
from rest_framework.decorators import action
|
||||
|
@ -57,7 +58,7 @@ class OrderViewSet(CreateUpdateCustomMixin, ModelViewSet):
|
|||
def get_serializer_class(self):
|
||||
if self.action in ['create', 'update']:
|
||||
return OrderCreateUpdateSerializer
|
||||
return OrderSerializer
|
||||
return super().get_serializer_class()
|
||||
|
||||
@action(methods=['get'], detail=False, perms_map={'get':'*'})
|
||||
def toplan(self, request, pk=None):
|
||||
|
@ -67,4 +68,24 @@ class OrderViewSet(CreateUpdateCustomMixin, ModelViewSet):
|
|||
serializer = self.get_serializer(page, many=True)
|
||||
return self.get_paginated_response(serializer.data)
|
||||
serializer = self.get_serializer(queryset, many=True)
|
||||
return Response(serializer.data)
|
||||
return Response(serializer.data)
|
||||
|
||||
|
||||
class SaleViewSet(CreateUpdateCustomMixin, ListModelMixin, RetrieveModelMixin, CreateModelMixin, GenericViewSet):
|
||||
"""
|
||||
销售记录
|
||||
"""
|
||||
perms_map = {'*': '*'}
|
||||
queryset = Sale.objects.select_related('customer', 'order', 'product').all()
|
||||
serializer_class = SaleListSerializer
|
||||
search_fields = ['customer__name', 'order__number']
|
||||
filterset_fields = ['product', 'order', 'customer']
|
||||
ordering_fields = ['create_time']
|
||||
ordering = ['-create_time']
|
||||
|
||||
def get_serializer_class(self):
|
||||
if self.action == 'create':
|
||||
return SaleCreateSerializer
|
||||
elif self.action == 'retrieve':
|
||||
return SaleListSerializer
|
||||
return super().get_serializer_class()
|
|
@ -0,0 +1,23 @@
|
|||
# Generated by Django 3.2.9 on 2021-12-03 07:01
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('wf', '0016_auto_20211024_2349'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='customfield',
|
||||
name='field_type',
|
||||
field=models.CharField(choices=[('string', '字符串'), ('int', '整型'), ('float', '浮点'), ('boolean', '布尔'), ('date', '日期'), ('datetime', '日期时间'), ('radio', '单选'), ('checkbox', '多选'), ('select', '单选下拉'), ('selects', '多选下拉'), ('textarea', '文本域'), ('selectuser', '单选用户'), ('selectusers', '多选用户'), ('file', '附件'), ('draw', '绘图')], help_text='5.字符串,10.整形,15.浮点型,20.布尔,25.日期,30.日期时间,35.单选框,40.多选框,45.下拉列表,50.多选下拉列表,55.文本域,60.用户名, 70.多选的用户名, 80.附件(只保存路径,多个使用逗号隔开)', max_length=50, verbose_name='类型'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='ticket',
|
||||
name='ticket_data',
|
||||
field=models.JSONField(default=dict, help_text='工单自定义字段内容', verbose_name='工单数据'),
|
||||
),
|
||||
]
|
|
@ -152,7 +152,8 @@ class CustomField(CommonAModel):
|
|||
('textarea', '文本域'),
|
||||
('selectuser', '单选用户'),
|
||||
('selectusers', '多选用户'),
|
||||
('file', '附件')
|
||||
('file', '附件'),
|
||||
('draw', '绘图')
|
||||
)
|
||||
workflow = models.ForeignKey(Workflow, on_delete=models.CASCADE, verbose_name='所属工作流')
|
||||
field_type = models.CharField('类型', max_length=50, choices=field_type_choices, help_text='5.字符串,10.整形,15.浮点型,20.布尔,25.日期,30.日期时间,35.单选框,40.多选框,45.下拉列表,50.多选下拉列表,55.文本域,60.用户名, 70.多选的用户名, 80.附件(只保存路径,多个使用逗号隔开)')
|
||||
|
@ -201,7 +202,7 @@ class Ticket(CommonBModel):
|
|||
state = models.ForeignKey(State, on_delete=models.CASCADE, verbose_name='当前状态', related_name='ticket_state')
|
||||
parent = models.ForeignKey('self', null=True, blank=True, on_delete=models.CASCADE, verbose_name='父工单')
|
||||
parent_state = models.ForeignKey(State, null=True, blank=True, on_delete=models.CASCADE, verbose_name='父工单状态', related_name='ticket_parent_state')
|
||||
ticket_data = models.JSONField('工单数据', default=dict, help_text='工单所有字段内容')
|
||||
ticket_data = models.JSONField('工单数据', default=dict, help_text='工单自定义字段内容')
|
||||
in_add_node = models.BooleanField('加签状态中', default=False, help_text='是否处于加签状态下')
|
||||
add_node_man = models.ForeignKey(User, verbose_name='加签人', on_delete=models.SET_NULL, null=True, blank=True, help_text='加签操作的人,工单当前处理人处理完成后会回到该处理人,当处于加签状态下才有效')
|
||||
|
||||
|
@ -211,16 +212,17 @@ class Ticket(CommonBModel):
|
|||
multi_all_person = models.JSONField('全部处理的结果', default=dict, blank=True, help_text='需要当前状态处理人全部处理时实际的处理结果,json格式')
|
||||
|
||||
|
||||
class TicketData():
|
||||
"""
|
||||
工单数据,自定义字段值
|
||||
"""
|
||||
form_field = models.ForeignKey(CustomField, verbose_name='关联字段', on_delete=models.SET_NULL, db_constraint=False, null=True, blank=True)
|
||||
field_name = models.CharField('字段名', max_length=50)
|
||||
field_key = models.CharField('字段标识', max_length=50)
|
||||
field_type = models.CharField('字段类型', choices=CustomField.field_type_choices, max_length=50)
|
||||
field_value = models.JSONField('录入值', default=dict, blank=True)
|
||||
sort = models.IntegerField('排序号', default=1)
|
||||
# class TicketCustomField(BaseModel):
|
||||
# """
|
||||
# 工单数据,自定义字段值
|
||||
# """
|
||||
# ticket = models.ForeignKey(Ticket, verbose_name='关联工单', on_delete=models.CASCADE)
|
||||
# form_field = models.ForeignKey(CustomField, verbose_name='关联字段', on_delete=models.SET_NULL, db_constraint=False, null=True, blank=True)
|
||||
# field_name = models.CharField('字段名', max_length=50)
|
||||
# field_key = models.CharField('字段标识', max_length=50)
|
||||
# field_type = models.CharField('字段类型', choices=CustomField.field_type_choices, max_length=50)
|
||||
# field_value = models.JSONField('录入值', default=dict, blank=True)
|
||||
# sort = models.IntegerField('排序号', default=1)
|
||||
|
||||
class TicketFlow(BaseModel):
|
||||
"""
|
||||
|
|
Loading…
Reference in New Issue