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

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

作者头像
zx钟
发布于 2022-12-02 08:09:54
发布于 2022-12-02 08:09:54
59200
代码可运行
举报
文章被收录于专栏:测试游记测试游记
运行总次数:0
代码可运行

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

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

库存信息

创建App

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
python manage.py startapp warehouse

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

注册App

backend/LightSeeking/settings.pyINSTALLED_APPS中添加

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
INSTALLED_APPS = [
    ...
    'users.apps.UsersConfig',
    'product.apps.ProductConfig',
    'warehouse.apps.WarehouseConfig'
]

表结构设计

库存信息包含了

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

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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
product = models.ForeignKey(Product, verbose_name="产品信息", on_delete=models.DO_NOTHING, help_text="产品信息")

其他都是普通的字段

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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
代码运行次数:0
运行
AI代码解释
复制
python manage.py makemigrations
python manage.py migrate

序列化器

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

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

backend/apps/product/serializers.py

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class ProductAllModelSerializer(serializers.ModelSerializer):
    class Meta:
        model = Product
        fields = '__all__'

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

编写whether_existed_product_id方法来进行判断

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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
代码运行次数:0
运行
AI代码解释
复制
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
代码运行次数:0
运行
AI代码解释
复制
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
代码运行次数:0
运行
AI代码解释
复制
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
代码运行次数:0
运行
AI代码解释
复制
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
代码运行次数:0
运行
AI代码解释
复制
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
代码运行次数:0
运行
AI代码解释
复制
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
代码运行次数:0
运行
AI代码解释
复制
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
代码运行次数:0
运行
AI代码解释
复制
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
代码运行次数:0
运行
AI代码解释
复制
{
    "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
代码运行次数:0
运行
AI代码解释
复制
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
代码运行次数:0
运行
AI代码解释
复制
{
    "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 删除。

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

评论
登录后参与评论
暂无评论
推荐阅读
新一代基于大数据的管理信息系统(MIS)报表需求开发
2.然后通过将数据在后台(主要使用java)封装成前台需要的格式(一般是json格式),这一步中包含了service,DAO,spring配置以及使用,struts2的配置以及使用,如sql部分过于复杂还需要使用到Mybatis的配置和使用。当然还有业务逻辑方法的代码编写。
MickyInvQ
2020/09/27
1.8K0
新一代基于大数据的管理信息系统(MIS)报表需求开发
源码分析 | Spring定时任务Quartz执行全过程源码解读
在日常开发中经常会用到定时任务,用来;库表扫描发送MQ、T+n账单结算、缓存数据更新、秒杀活动状态变更,等等。因为有了Spring的Schedule极大的方便了我们对这类场景的使用。那么,除了应用你还了解它多少呢;
小傅哥
2020/07/14
1.6K0
纳税服务系统六(信息发布管理模块)【Ueditor、异步信息交互、抽取BaseService、条件查询、分页】
需求分析 我们现在来到了纳税服务系统的信息发布管理模块,首先我们跟着原型图来进行需求分析把: 一些普通的CRUD,值得一做的就是状态之间的切换了。停用和发布切换。 值得注意的是:在信息内容中,它可以带
Java3y
2018/04/02
1.9K0
纳税服务系统六(信息发布管理模块)【Ueditor、异步信息交互、抽取BaseService、条件查询、分页】
Java+Spring 实现任务调度Quartz框架(纯Java实现+Spring实现) 读写Excel
开发工具: Myelicps2014 这里选用Quartz 的1.8.6版本,此版本在项目中应用较多,也较为稳定
Java_慈祥
2024/08/06
1610
Java+Spring 实现任务调度Quartz框架(纯Java实现+Spring实现) 读写Excel
​分布式定时任务框架Quartz
项目中总要写那么几个定时任务来处理一些事情。一些简单的定时任务使用Spring自带的定时任务就能完成。但是如果需要大量的定时任务的话要怎么才能统一管理呢?
乱敲代码
2020/05/21
4.8K0
Spring 集成Quartz
在使用jdk的timer时发现无法在指定的日期进行执行任务。这便引入一个优秀的开源任务调度框架“quartz”。这里使用的是quartz-1.8.6版本。Quart的官网:http://www.quartz-scheduler.org/;spring 3.0版本无法集成quartz 2.x及其后续版本。
HUC思梦
2020/09/03
7830
Spring 集成Quartz
玩转 SSH(七):使用 dubbo + zookeeper 实现服务模块化
一、创建 SSMVCAnnoDemo 项目 点击菜单,选择“File -> New Project” 创建新项目。选择使用 archetype 中的 maven-quickstart 模版创建。 输入
陈树义
2018/04/13
1.2K0
玩转 SSH(七):使用 dubbo + zookeeper 实现服务模块化
Quartz任务调度器
这里加入的是quartz-1.8.6版本。Quart的官网:http://www.quartz-scheduler.org/;项目中的框架的spring是spring 3.0版本无法集成quartz 2.x及其后续版本;所以这里用quartz 1.8.6版本。
intsmaze-刘洋
2018/08/29
1.2K0
Quartz任务调度器
ASP.NET MVC5+EF6+EasyUI 后台管理系统(85)-Quartz 作业调度用法详解二
前言 上一节我们学习了Quartz的基本用法 这一节学习通过XML配置的形式来执行任务 这一节主要认识一些属性,为下一步打基础 代码下载:链接:http://pan.baidu.com/s/1
用户1149182
2018/01/12
6410
ASP.NET MVC5+EF6+EasyUI 后台管理系统(85)-Quartz 作业调度用法详解二
Quartz定时任务框架使用教程详解
Quartz是OpenSymphony开源组织在Job scheduling领域又一个开源项目,完全由Java开发,可以用来执行定时任务,类似于java.util.Timer。但是相较于Timer, Quartz增加了很多功能:
大忽悠爱学习
2021/12/07
2.3K0
Quartz定时任务框架使用教程详解
Spring Boot整合Scheduled定时任务器、整合Quartz定时任务框架
首先说明一下,这里使用的是Springboot2.2.6.RELEASE版本,由于Springboot迭代很快,所以要注意版本问题。
别先生
2020/05/27
1.2K0
Spring Boot整合Scheduled定时任务器、整合Quartz定时任务框架
基于Quartz编写一个可复用的分布式调度任务管理WebUI组件
创业小团队,无论选择任何方案,都优先考虑节省成本。关于分布式定时调度框架,成熟的候选方案有XXL-JOB、Easy Scheduler、Light Task Scheduler和Elastic Job等等,其实这些之前都在生产环境使用过。但是想要搭建高可用的分布式调度平台,这些框架(无论是否去中心化)都需要额外的服务器资源去部署中心调度管理服务实例,甚至有时候还会依赖一些中间件如Zookeeper。回想之前花过一段时间看Quartz的源码去分析它的线程模型,想到了它可以基于MySQL,通过一个不是很推荐的X锁方案(SELECT FOR UPDATE加锁)实现服务集群中单个触发器只有一个节点(加锁成功的那个节点)能够执行,这样子,就能够仅仅依赖于现有的MySQL实例资源实现分布式调度任务管理。一般来说,有关系型数据保存需求的业务应用都会有自己的MySQL实例,这样子就能几乎零成本引入一个分布式调度管理模块。某个加班的周六下午敲定了初步方案之后,花了几个小时把这个轮子造出来了,效果如下:
Throwable
2020/06/23
8510
Spring+Quartz实现定时任务 (二)
在我们进行软件项目开发的过程中,相信大家在很多时候都会遇到如下业务场景:每天、每周或每月生成相应的业务报表;每天统计系统注册人数;定期清理平台长久不登录的用户等等。遇到这种业务场景需要怎样去处理?人为定时去数据库操作来统计?别开玩笑了,这种事情哪用得着人来做,如果像这种任务还需要专人每天都去做统计,那估计很多人就要疯掉了。针对于这种业务情况,采用定时任务是个非常不错的选择。在Java领域中,定时任务的开源工具也非常多,小到一个Timer类,大到Quartz框架。总体来说,个人比较喜欢的还是Quartz,功能
Java学习123
2018/05/16
9520
java 项目日志管理设计方案[通俗易懂]
自定义注解主要包括模块名称、操作内容两个内容,其使用方式为:@LogAnnotation(moduleName = “角色管理”, operate = “新增角色”) 如果需要其他内容,可根据以下源码进行扩展
全栈程序员站长
2022/08/31
1.6K0
quartz使用入门篇【面试+工作】
你曾经需要应用执行一个任务吗?这个任务每天或每周星期二晚上11:30,或许仅仅每个月的最后一天执行。一个自动执行而无须干预的任务在执行过程中如果发生一个严重错误,应用能够知到其执行失败并尝试重新执行吗?你和你的团队是用Java编程吗?如果这些问题中任何一个你回答是,那么你应该使用Quartz调度器。
Java帮帮
2018/07/26
2K0
quartz使用入门篇【面试+工作】
Quartz任务调度快速入门
Quartz对任务调度的领域问题进行了高度的抽象,提出了调度器、任务和触发器这3个核心的概念,并在org.quartz通过接口和类对重要的这些核心概念进行描述:
MonroeCode
2018/01/09
1.4K0
Quartz任务调度快速入门
十分钟用 Python 绘制动态排行图 —— 以 A 股历年市值前十股票排行榜为例
相信大家都曾在 YouTube 和 B 站看到过类似的视频,这种图在国外叫做 Bar Chart Race,配上一段气势磅礴的 BGM,就会营造出一种「浮沉跌宕」的沉浸感,这类型的视频很多都获得了相当可观的播放量。
davidac
2021/07/11
1.3K0
day32_Hibernate学习笔记_04
  缓存(Cache):是计算机领域非常通用的概念。它介于应用程序和永久性数据存储源(如硬盘上的文件或者数据库)之间,其作用是降低应用程序直接读写硬盘(永久性数据存储源)的频率,从而提高应用的运行性能。缓存中的数据是数据存储源中数据的拷贝。缓存的物理介质通常是内存。   缓存:程序 <-- (内存) --> 硬盘
黑泽君
2018/10/11
9940
day32_Hibernate学习笔记_04
深入Quartz,优雅地管理你的定时任务
最近在工作遇到了定时任务场景,因此特地对定时任务相关知识进行了调研,记录在此,后文中使用的代码已经上传到Github: https://github.com/ThinkMugz/springboot-demo-major,需要的伙伴儿自取。
云深i不知处
2022/05/11
4.7K0
深入Quartz,优雅地管理你的定时任务
宿舍管理系统部分代码实现
public class DBHelper { private String dbUrl="jdbc:mysql://localhost:3306/sushe"; private String dbUser="root"; private String dbPassword="123456"; private String jdbcName="com.mysql.jdbc.Driver"; public Connection getConn(){ Connection conn = null; try{ Class.forName(jdbcName); } catch(Exception e){} try{ conn=DriverManager.getConnection(dbUrl,dbUser,dbPassword); } catch(SQLException ex){} return conn; } public static void main(String[] args) { System.out.println(new DBHelper().getConn());
张哥编程
2024/12/22
1050
推荐阅读
相关推荐
新一代基于大数据的管理信息系统(MIS)报表需求开发
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档