收藏网站

Django 商品订单管理软件

2021年1月20日 14:54 Django 3986

用Python开发一个简单的商品订单管理软件,设计思路是:查询出订单商品及条形码,写入数量和单价添加到订单列表待用。软件会根据数量和单价自动计算出总数量和总金额,并换算人民币。

订单管理软件

开发环境

# 开发环境

Python:3.9.0
Django:3.1.3
Mysql:8.0.22
Pycharm:2020.2

准备好开发环境后,创建项目并新建订单管理应用(sale)

数据模型

from django.db import models


class Product(models.Model):
    """商品数据模型"""
    product_name = models.CharField('商品名称',max_length=200)
    product_barcode = models.CharField('条形码',max_length=64)
    product_number = models.CharField('数量',max_length=64)
    product_price = models.DecimalField('单价',max_digits=8,decimal_places=2)

    class Meta:
        verbose_name = '商品'
        verbose_name_plural = '商品管理'

    def __str__(self):
        return self.product_name


class SaleList(models.Model):
    """订单数据模型"""
    sale_code = models.CharField('订单号',max_length=128)
    sale_number = models.CharField('数量',max_length=32)
    sale_price = models.DecimalField('总金额',max_digits=8,decimal_places=2)
    sale_time = models.DateTimeField('订单时间',auto_now_add=True)

    class Meta:
        verbose_name = '订单'
        verbose_name_plural = '商品订单'

    def __str__(self):
        return self.sale_code


class SaleDetail(models.Model):
    """订单详细"""
    detail_code = models.CharField('订单号', max_length=128)
    detail_product = models.CharField('商品', max_length=200)
    detail_number = models.CharField('数量', max_length=64)
    detail_price = models.DecimalField('单价', max_digits=8, decimal_places=2)

    class Meta:
        verbose_name = verbose_name_plural = '订单详细'

    def __str__(self):
        return self.detail_code

路由设置

from django.contrib import admin
from django.urls import path
from sale import views

urlpatterns = [
    path('admin/', admin.site.urls),
    path('',views.sale_list,name='sale'),
    path('search/',views.search_product,name='search'),  # 查找商品
    path('add/',views.sale_buy_list,name='add'),  # 添加订单列表
    path('delete/<int:barcode>',views.delete_product,name='delete'),  # 删除商品
    path('cancle/',views.cancel_order,name='cancel'),  # 清空订单
    path('save/',views.submit_order,name='save'),  # 提交到数据库
]

业务代码

在sale目录下创建一个myclass文件夹,并新建order_id.py(订单号)、order_buy.py(订单功能)、format(人民币大写)三个文件,分别用来实现业务代码。

# myclass目录下的format.py 人民币大写

def get_format(currency):
    currency = round(currency)
    digit = [u'零', u'壹', u'贰', u'叁', u'肆', u'伍', u'陆', u'柒', u'捌', u'玖']
    weight = [u'圆', u'拾', u'佰', u'仟', u'万', u'拾', u'佰', u'仟']
    Z = [(u'零仟', u'零佰', u'零拾', u'零零零', u'零零', u'零万', u'零圆'), (u'零', u'零', u'零', u'零', u'零', u'万', u'圆')]
    num = str(abs(currency))  # 整数转换成字符串
    s = u'负' if currency < 0 else ''
    for i, x in enumerate(num):
        s += digit[int(x)] + weight[len(num) - i - 1]

    for z, v in zip(Z[0], Z[1]):
        s = s.replace(z, v)
    return '人民币' + s + '整'
# myclass 目录下的order_id.py  自动订单号

from datetime import datetime
import random
"""模块说明:根据当前时间随机生成订单号"""


class OrderCode:
    def __init__(self):
        self.odd_number = ''  # 存储生成的订单号,默认为空

        # 自动执行
        self.get_odd_number()

    def get_odd_number(self):
        # 获取当前系统时间
        dt = datetime.now()
        # 格式化时间
        self.odd_number = '%04d%02d%02d%02d%02d%02d' % (dt.year, dt.month, dt.day, dt.hour, dt.minute, dt.second)
        # 生成4位随机数字
        ran_list = random.randint(0, 9999)
        # 合并成订单号
        self.odd_number += '%04d' % ran_list
# myclass 目录下的order_buy.py 订单功能实现

from sale.models import SaleList, SaleDetail
from decimal import Decimal

"""
模块说明:
"""


class Sale:
    def __init__(self):
        self.order_list = []  # 存储临时商品列表
        self.error_info = ''  # 存储错误信息
        self.total_number = 0  # 存储订单商品总数量
        self.total_money = Decimal(0.0)  # 存储订单总金额

    def add_order_list(self, name, barcode, number, price):
        """订单模块:将查找出来的内容添加到订单列表中"""
        if len(name) and len(barcode) and len(number) and len(price) == 0:
            self.error_info = '商品信息不能为空'
        else:
            temp_dict = {
                'name': name,
                'barcode': barcode,
                'number': number,
                'price': Decimal(price),
                'total': int(number) * Decimal(price),
            }
            self.order_list.append(temp_dict)

    def delete_product_list(self, barcode):
        """订单模块:删除列表中的某个商品"""
        # 先遍历order_list
        for index in range(len(self.order_list)):
            # 判断传递过来的条形码是否在order_list中
            if int(self.order_list[index]['barcode']) == int(barcode):
                self.order_list.pop(index)
            else:
                continue

    def get_total_info(self):
        """订单模块:商品总数和总金额"""
        self.total_number = 0
        self.total_money = Decimal(0.0)
        # 遍历订单列表
        for product in self.order_list:
            self.total_number += int(product['number'])
            self.total_money += product['total']

        # 保留金额的两位小数点
        self.total_money = round(self.total_money)

    def submit_order_list(self, serialnum):
        """订单模块:保存到数据库"""
        if len(self.order_list) != 0:
            try:
                SaleList.objects.create(sale_code=serialnum, sale_number=self.total_number, sale_price=self.total_money)
                # 遍历订单列表,把详细订单数据存储到SaleDetail表中
                for order in self.order_list:
                    SaleDetail.objects.create(detail_code=serialnum, detail_product=order['name'],
                                              detail_number=order['number'],
                                              detail_price=order['price'])
                self.error_info = '订单保存成功'
            except Exception as e:
                self.error_info = '新增订单失败:' + str(e)
        else:
            self.error_info = '商品列表为空'
# sale目录下的views.py 视图函数

from django.shortcuts import render,redirect
from sale.models import Product
from sale.myclass import order_id,order_buy,format  # 引用自定义模块
from django.http import JsonResponse


# 实例化订单模块
sale_buy = order_buy.Sale()
# 实例化自动单号
sale_id = order_id.OrderCode()


def sale_list(request):
    """订单模块:显示订单列表"""
    # 如果为空自动生成订单号
    if len(sale_id.odd_number) == 0:
        sale_id.get_odd_number()
    # 统计商品总数和总金额
    sale_buy.get_total_info()
    # 订单总金额转换人民币大写
    if sale_buy.total_money == 0:
        pub_format = ''
    else:
        pub_format = format.get_format(sale_buy.total_money)

    context = {
        'sale_id':sale_id.odd_number,
        'list':sale_buy.order_list,
        'order_total':sale_buy,
        'error':sale_buy.error_info,
        'pub_format':pub_format,
    }
    return render(request,'index.htm',context)


def search_product(request):
    """订单模块:根据前端传递的条件查找商品"""
    search_text = request.GET.get('search_text')
    search_list = Product.objects.filter(product_name__icontains=search_text).values('id','product_name','product_barcode','product_price','product_number')
    return JsonResponse(list(search_list),safe=False)


def sale_buy_list(request):
    """订单模块:将商品添加到订单列表"""
    product_name_dict = request.POST.get('product_name')
    product_barcode_dict = request.POST.get('product_barcode')
    product_number_dict = request.POST.get('product_number')
    product_price_dict = request.POST.get('product_price')

    sale_buy.add_order_list(product_name_dict,product_barcode_dict,product_number_dict,product_price_dict)
    return redirect('/')


def delete_product(request,barcode):
    """订单模块:删除列表中的某个商品"""
    try:
        sale_buy.delete_product_list(barcode)
        return redirect('/')
    except:
        return redirect('/')


def cancel_order(request):
    """订单模块:取消订单"""
    if len(sale_buy.order_list) != 0:
        sale_id.odd_number = ''  # 清空订单号
        sale_buy.order_list.clear()  # 清空商品列表
        sale_buy.total_number = 0  # 清空商品数量
        sale_buy.total_money = 0.0  # 清空总金额
        return redirect('/')
    else:
        return redirect('/')


def submit_order(request):
    """订单视图:保存到数据库"""
    sale_buy.submit_order_list(sale_id.odd_number)
    sale_id.odd_number = ''  # 清空订单号
    sale_buy.order_list.clear()  # 清空商品列表
    sale_buy.total_number = 0  # 清空商品数量
    sale_buy.total_money = 0.0  # 清空总金额

    return redirect('/')


前端模版

# index.html  前端模版

<!DOCTYPE HTML>
<html>

<head>
    <meta charset="utf-8" />
    <meta name="renderer" content="webkit">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=0, minimal-ui">
    <title>订单管理系统</title>
    <meta name="keywords" content="" />
    <meta name="description" content="" />
    <link rel="stylesheet" type="text/css" href="/images/css/common.css" />
    <script src="/images/js/jquery.min.js"></script>
</head>

<body>
    <header>
        <img src="/images/logo.png">
        <a href="">退出登陆</a>
        <a href="">修改密码</a>
    </header>
    <main>
        <div class="add_order_list">
            <form action="{% url 'add' %}" method="post">
                {% csrf_token %}
                <input type="text" placeholder="请选择商品" autocomplete="off" onclick="pop_box()" id="product_name" name="product_name">
                <input type="text" placeholder="条形码" id="product_barcode" name="product_barcode">
                <input type="text" placeholder="数量" id="product_number" name="product_number">
                <input type="text" placeholder="单价" name="product_price">
                <button type="submit">添加</button>
            </form>
        </div>
        <div class="order_list">
            <table id="order_list">
                <thead>
                    <tr>
                        <th>编号</th>
                        <th>商品</th>
                        <th>条形码</th>
                        <th>数量</th>
                        <th>单价</th>
                        <th>金额</th>
                        <th>操作</th>
                    </tr>
                </thead>
                <tbody>
            {% for list in list %}
            <tr>
                <td>{{ forloop.counter }}</td>
                <td>{{ list.name }}</td>
                <td>{{ list.barcode }}</td>
                <td>{{ list.number }}</td>
                <td>{{ list.price }}</td>
                <td>{{ list.total }}</td>
                <td>
                    <a href="{% url 'delete' list.barcode %}">删除</a>
                </td>
            </tr>
            {% endfor %}
                </tbody>
            </table>
        </div>
        <div class="order_info">
            <p>
                <span>订单号:<font>{{ sale_id }}</font></span>
                <span>总数量:<font>{{ order_total.total_number }}</font></span>
                <span>总金额:<font>{{ order_total.total_money }}</font></span>
                <span>大写:<font>{{ pub_format }}</font></span>
            </p>
            <div class="submit">
                <a href="{% url 'save' %}" class="btn_save">提交</a>
                <a href="{% url 'cancel' %}" class="btn_cancel">清空</a>
            </div>
        </div>
        <div id="search_bg"></div>
        <div id="search_box">
            <div class="title">
                <span>产品搜索</span>
                <i onclick="close_box()">x</i>
            </div>
            <div class="search_input">
                <input type="text" placeholder="请输入商品名称" id="search_text">
                <button type="button" onclick="query_product()">查询</button>
            </div>
            <table id="search_product">
                <thead>
                    <tr>
                        <th>编号</th>
                        <th>商品名称</th>
                        <th>条形码</th>
                        <th>库存</th>
                        <th>单价</th>
                    </tr>
                </thead>
                <tbody></tbody>
            </table>
        </div>
        <div class="error">

            <p>{{ error }}</p>

        </div>
    </main>
    <script>
        // 弹出层-搜索产品
        function pop_box() {
            var popbox = document.getElementById('search_box');
            var popbg = document.getElementById('search_bg');
            popbox.style.display = 'block';
            popbg.style.display = 'block';
        }
        // 关闭弹出层
        function close_box() {
            var popbox = document.getElementById('search_box');
            var popbg = document.getElementById('search_bg');
            popbox.style.display = 'none';
            popbg.style.display = 'none';
        }
                // 双击表格获得数据
        function get_product() {
                $("#search_product > tbody > tr").click(function () {
                    var product = $(this).find("td:nth-child(2)").text();
                    var barcode = $(this).find("td:nth-child(3)").text();
                    $("#product_name").val(product);
                    $("#product_barcode").val(barcode);
                    close_box();
                    var number = document.getElementById("product_number");
                    number.focus();
                })
        }
    </script>
<script>
        // ajax查询商品
        function LoadTable(data){
            var new_tbody = $("#search_product").find("tbody");
            new_tbody.empty();
            for (var i in data){
                // 新建行
                var new_tr = $("<tr onclick='get_product()'></tr>");
                // 新建节点
                var new_td1 = $("<td>" + i + "</td>");
                var new_td2 = $("<td>" + data[i].product_name + "</td>");
                var new_td3 = $("<td>" + data[i].product_barcode + "</td>");
                var new_td4 = $("<td>" + data[i].product_number + "</td>");
                var new_td5 = $("<td>" + data[i].product_price + "</td>");

                // 添加数据
                new_tr.append(new_td1);
                new_tr.append(new_td2);
                new_tr.append(new_td3);
                new_tr.append(new_td4);
                new_tr.append(new_td5);
                new_tbody.append(new_tr);
            }
        }
        function query_product(){
            $.ajax({
                url:'/search/',
                type:'get',
                dataType:'json',
                data:{
                    'search_text':$("#search_text").val(),

                },
                error:function (){
                    alert('商品信息错误')
                },
                success:function (data){
                    LoadTable(data);
                },
            });
        }
        // 回车搜索
        $('#search_text').bind('keydown',function (event){
            var event = window.event || arguments.callee.caller.arguments[0];
            if (event.keyCode == 13){
                query_product();
            }
        })
    </script>
</body>
</html>

 

热点推荐

扫码添加微信