前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >12.寻光集后台管理系统-库存信息(后端)

12.寻光集后台管理系统-库存信息(后端)

作者头像
zx钟
发布2022-12-02 16:09:54
5410
发布2022-12-02 16:09:54
举报
文章被收录于专栏:测试游记测试游记

有了产品信息之后,下面来写库存信息部分

每一个库存的入库和出库都需要对应一个产品,所以产品信息是它的外键

库存信息

创建App

代码语言:javascript
复制
python manage.py startapp warehouse

warehouse文件夹移动到backend/apps/warehouse

注册App

backend/LightSeeking/settings.pyINSTALLED_APPS中添加

代码语言:javascript
复制
INSTALLED_APPS = [
    ...
    'users.apps.UsersConfig',
    'product.apps.ProductConfig',
    'warehouse.apps.WarehouseConfig'
]

表结构设计

库存信息包含了

  • 产品信息
  • 单价
  • 生产日期
  • 保质期天数
  • 数量
  • 库存状态
  • 订单号
  • 供应商
  • 备注

产品信息使用外键的方式,并且两个键之间不互相影响

代码语言:javascript
复制
product = models.ForeignKey(Product, verbose_name="产品信息", on_delete=models.DO_NOTHING, help_text="产品信息")

其他都是普通的字段

代码语言:javascript
复制
from django.db import models

from product.models import Product
from utils.models import BaseModel


class Warehouse(BaseModel):
    STOCKSTATUS = (
        (, "入库"),
        (, "出库"),
        (, "报废"),
    )
    product = models.ForeignKey(Product, verbose_name="产品信息", on_delete=models.DO_NOTHING, help_text="产品信息")
    price = models.DecimalField('成本单价', max_digits=, decimal_places=, default=, help_text='成本单价')
    date_of_manufacture = models.DateTimeField("生产日期", help_text="生产日期")
    quality_guarantee = models.IntegerField("保质期天数", help_text="保质期天数")
    num = models.IntegerField("数量", default=, help_text="数量")
    stock_status = models.CharField("库存状态", max_length=, choices=STOCKSTATUS, default=,
                                    help_text='库存状态:1-入库,2-出库,3-报废')
    order_id = models.CharField("订单号", max_length=, null=True, blank=True, default='', help_text='订单号')
    supplier = models.CharField("供应商", max_length=, null=True, blank=True, default='', help_text='供应商')
    desc = models.CharField('备注', max_length=, null=True, blank=True, default='', help_text='备注')

    class Meta:
        db_table = 'tb_warehouse'
        verbose_name = '库存信息'
        verbose_name_plural = verbose_name

    def __str__(self):
        return self.id

数据迁移

代码语言:javascript
复制
python manage.py makemigrations
python manage.py migrate

序列化器

在库存序列化器中需要指定产品来进行新增,查看的时候需要返回全部的产品信息

所以先新建一个包含全部产品的序列化器

backend/apps/product/serializers.py

代码语言:javascript
复制
class ProductAllModelSerializer(serializers.ModelSerializer):
    class Meta:
        model = Product
        fields = '__all__'

添加产品的时候使用的是产品的id,这时候就需要判断一下这个产品是否存在了

编写whether_existed_product_id方法来进行判断

代码语言:javascript
复制
def whether_existed_product_id(value):
    """
    检查产品id是否存在
    :param value:
    :return:
    """
    if value != :
        if not isinstance(value, int):
            raise serializers.ValidationError('所选产品信息有误!')
        elif not Product.objects.filter(is_delete=False, id=value).exists():
            raise serializers.ValidationError('所选产品信息不存在!')

所以库存的序列化器基础版本为

代码语言:javascript
复制
class WarehouseModelSerializer(serializers.ModelSerializer):
    product_id = serializers.IntegerField(
        write_only=True,
        help_text='产品信息ID',
        validators=[validates.whether_existed_product_id]
    )
    product = ProductAllModelSerializer(read_only=True, many=False)

    class Meta:
        model = Warehouse
        exclude = ('is_delete',)
        extra_kwargs = {
            'c_time': {
                'read_only': True
            },
        }
重点

下面是序列化器中的一个神奇的操作,也就是它可以逐行处理返回的数据,根据逻辑给每行添加需要的数据

在这个序列化器中需要顺便计算一下产品的保质期相关数据

新加两个字段剩余天数保质期日期

剩余天数 = 保质期天数 - (当前日期 - 生产日期)

保质期日期 = 生产日期+剩余天数

代码语言:javascript
复制
remaining = serializers.SerializerMethodField(label="剩余天数", read_only=True, help_text="剩余天数")
remaining_day = serializers.SerializerMethodField(label="保质期日期", read_only=True, help_text="保质期日期")

使用serializers.SerializerMethodField可以在WarehouseModelSerializer类中编写get_xxx方法来计算这个值

代码语言:javascript
复制
def get_remaining(self, warehouse):
    """
    剩余天数 = 保质期天数 - (当前日期 - 生产日期)
    :param warehouse:
    :return:
    """
    return warehouse.quality_guarantee - (
            warehouse.date_of_manufacture - datetime.datetime.now(tz=pytz.UTC)
    ).days

def get_remaining_day(self, warehouse):
    """
    保质期日期 = 生产日期+剩余天数
    """
    return warehouse.date_of_manufacture + datetime.timedelta(days=warehouse.quality_guarantee)

同理再根据需求添加几个字段

  • 总库存
  • 出库
  • 入库
  • 已经出库时间
  • 已经入库时间
代码语言:javascript
复制
total = serializers.SerializerMethodField(label="总库存", read_only=True, help_text="一个产品的总库存")
warehouse1 = serializers.SerializerMethodField(label="出库", read_only=True, help_text="一个产品的总出库")
warehouse2 = serializers.SerializerMethodField(label="入库", read_only=True, help_text="一个产品的总入库")
warehouse1_time = serializers.SerializerMethodField(label="已经出库时间", read_only=True, help_text="出库距离当前的时间")
warehouse2_time = serializers.SerializerMethodField(label="已经入库时间", read_only=True, help_text="入库距离当前的时间")

实现字段的计算

代码语言:javascript
复制
def get_total(self, warehouse):
    total = self.get_warehouse1(warehouse) - self.get_warehouse2(warehouse)
    return total

def get_warehouse1(self, warehouse):
    product_id = warehouse.product_id
    warehouse_info = Warehouse.objects.filter(stock_status=).values("product").annotate(total=Sum("num")).all()
    total = warehouse_info.filter(product_id=product_id) and \
            warehouse_info.filter(product_id=product_id).get()["total"] or 
    return total

def get_warehouse2(self, warehouse):
    product_id = warehouse.product_id
    warehouse_info = Warehouse.objects.filter(stock_status=).values("product").annotate(total=Sum("num")).all()
    total = warehouse_info.filter(product_id=product_id) and \
            warehouse_info.filter(product_id=product_id).get()["total"] or 
    return total

def get_warehouse1_time(self, warehouse):
    warehouse2_time = warehouse.c_time - datetime.datetime.now(datetime.timezone(datetime.timedelta(hours=+)))
    return warehouse2_time.days

def get_warehouse2_time(self, warehouse):
    warehouse2_time = datetime.datetime.now(datetime.timezone(datetime.timedelta(hours=+))) - warehouse.c_time
    return warehouse2_time.days

视图

代码语言:javascript
复制
from rest_framework.viewsets import ModelViewSet

from utils.pagination import TenItemPerPagePagination
from warehouse.models import Warehouse
from warehouse.serializers import WarehouseModelSerializer


class WarehouseViewSet(ModelViewSet):
    queryset = Warehouse.objects.filter(is_delete=False).order_by("-c_time")
    serializer_class = WarehouseModelSerializer
    pagination_class = TenItemPerPagePagination
    ordering_fields = ['c_time']

    def perform_destroy(self, instance):
        instance.is_delete = True
        instance.save()  # 逻辑删除

路由

backend/apps/warehouse/urls.py

代码语言:javascript
复制
from django.urls import path, include
from rest_framework.routers import DefaultRouter
from . import views

router = DefaultRouter()
router.register("warehouse", views.WarehouseViewSet)

urlpatterns = [
    path('', include(router.urls))
]

backend/LightSeeking/urls.py

代码语言:javascript
复制
urlpatterns = [
    ...
    path('', include('warehouse.urls')),
]

代码

本次代码修改见:

https://gitee.com/zx660644/light-seeking/commit/2a5f9e4a26ff56e7cef5e6d4bdaf0adc63bb37b0

测试

先添加一个产品信息

访问http://127.0.0.1:8000/product/

填入产品信息后点击POST

再访问http://127.0.0.1:8000/warehouse/

添加一个库存信息

查看结果

代码语言:javascript
复制
{
    "id": ,
    "product": {
        "id": ,
        "c_time": "2022-09-02T12:14:32.356282+08:00",
        "u_time": "2022-09-02T12:14:32.356417+08:00",
        "is_delete": false,
        "product_id": "0001",
        "category": "饮料",
        "brand": "可口可乐",
        "name": "可乐",
        "price": "3.00",
        "sample_png": "",
        "desc": "无"
    },
    "remaining": ,
    "remaining_day": "2023-09-01T12:15:00+08:00",
    "total": ,
    "warehouse1": ,
    "warehouse2": ,
    "warehouse1_time": -1,
    "warehouse2_time": ,
    "c_time": "2022-09-02T12:15:46.366239+08:00",
    "u_time": "2022-09-02T12:15:46.366352+08:00",
    "price": "2.50",
    "date_of_manufacture": "2022-09-01T12:15:00+08:00",
    "quality_guarantee": ,
    "num": ,
    "stock_status": ,
    "order_id": "",
    "supplier": "测试供应商",
    "desc": ""
}

其中product字段包含了我们入库的产品信息

另外之前序列化器中添加的几个字段也出现了

bug修复

不过从这里看出来,之前写了个bug,之前把日期计算写反了

代码语言:javascript
复制
def get_remaining(self, warehouse):
    """
    剩余天数 = 保质期天数 - (当前日期 - 生产日期)
    :param warehouse:
    :return:
    """
    return warehouse.quality_guarantee - (
            datetime.datetime.now(tz=pytz.UTC) - warehouse.date_of_manufacture
    ).days

再次刷新后查看 remaining变为了364

代码语言:javascript
复制
{
    "data": {
        "page": ,
        "pageSize": ,
        "rows": [
            {
                "id": ,
                "product": {
                    "id": ,
                    "c_time": "2022-09-02T12:14:32.356282+08:00",
                    "u_time": "2022-09-02T12:14:32.356417+08:00",
                    "is_delete": false,
                    "product_id": "0001",
                    "category": "饮料",
                    "brand": "可口可乐",
                    "name": "可乐",
                    "price": "3.00",
                    "sample_png": "",
                    "desc": "无"
                },
                "remaining": ,
                "remaining_day": "2023-09-01T04:15:00Z",
                "total": ,
                "warehouse1": ,
                "warehouse2": ,
                "warehouse1_time": -1,
                "warehouse2_time": ,
                "c_time": "2022-09-02T12:15:46.366239+08:00",
                "u_time": "2022-09-02T12:15:46.366352+08:00",
                "price": "2.50",
                "date_of_manufacture": "2022-09-01T12:15:00+08:00",
                "quality_guarantee": ,
                "num": ,
                "stock_status": ,
                "order_id": "",
                "supplier": "测试供应商",
                "desc": ""
            }
        ],
        "total": 
    },
    "message": "",
    "code": ,
    "next": null,
    "previous": null
}
本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2022-09-02,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 测试游记 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 库存信息
    • 创建App
      • 注册App
        • 表结构设计
          • 数据迁移
            • 序列化器
              • 重点
            • 视图
              • 路由
              • 代码
              • 测试
                • bug修复
                相关产品与服务
                文件存储
                文件存储(Cloud File Storage,CFS)为您提供安全可靠、可扩展的共享文件存储服务。文件存储可与腾讯云服务器、容器服务、批量计算等服务搭配使用,为多个计算节点提供容量和性能可弹性扩展的高性能共享存储。腾讯云文件存储的管理界面简单、易使用,可实现对现有应用的无缝集成;按实际用量付费,为您节约成本,简化 IT 运维工作。
                领券
                问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档