大货跟踪程序精简版v1.20200731

程序的作用:
跟踪大货,全程监控excel表中设置的工作安排
程序的缺陷:
1.在跟踪的订单多的情况下,弹框数量会很多,因为用了并发式弹框,需要更进程序的体验
2.黑窗口操作,最用户不友好
3.其他没有发现的bug

注意事项
程序的启动模块为main.py文件
注意导入的文件一定要与程序在同一文件夹下
注意导入的数据一定要符合sainty文件中的模板格式,否则会出错
本脚本程序,暂时只有导入excel文件,查询订单,以及订单追踪功能

当订单多的时候,线程会呈指数增长,该版本解决了该问题

excel_to_sql.py:将excel表导入数据库模块
import os
import time
import pymysql
import xlrd
import prettytable

class DB(object):

    # 读取时间常量
    LOADING_TIME = 3

    def __init__(self, db_name):
        """初始化操作"""
        self.db = DB.mysql_link(db_name)  # 打开数据库连接
        self.cursor = self.db.cursor()  # 使用 cursor() 方法创建一个游标对象 cursor

    @staticmethod
    def mysql_link(de_name):
        """连接数据库"""
        try:
            db = pymysql.connect(host="localhost", user="root",
                                 passwd="root",
                                 db=de_name,
                                 charset='utf8')
            return db
        except:
            print("连接数据库时出错")

    @staticmethod
    def open_excel(excel_file):
        """手动打开excel文件"""
        try:
            # excel_file = input("请输入文件名[xxx]:") + ".xlsx"
            book = xlrd.open_workbook(excel_file)  # 文件名,把文件与py文件放在同一目录下
            return book
        except:
            print("打开excel文件失败")

    def atuo_open_excel(self):
        """自动检索excel文件名"""

        print("正在获取当前目录的excel文件中...")
        time.sleep(DB.LOADING_TIME)

        current_path = os.getcwd()  # 获取当前文件路径
        # 获取指定目录下包含的文件和目录
        dirs = os.listdir(current_path)
        for file in dirs:
            # 判断文件是否是以xlsx或xls结尾
            if file.endswith("xlsx") or file.endswith("xls"):
                book = DB.open_excel(file)
                print("获取excel数据成功")
                return book

    def type_change(self):
        """检测导入的excel数据类型"""
        pass

    def del_sql_table(self):
        """删除数据库表操作"""

        sql = """drop table sainty;"""
        print("重构原数据库表中...")
        time.sleep(DB.LOADING_TIME)
        self.cursor.execute(sql)

    def create_sql_table(self):
        """创建数据库表操作"""

        sql = """create table sainty (
                            id int(100) not null,
                            category_num varchar(40) not null,
                            guest varchar(40) not null,
                            total_quantity int(100) not null,
                            factory_name varchar(40) not null,
                            start_order_date date not null,
                            delivery_date date not null,
                            sailing_date date not null,
                            pp_sample date default null,
                            sealed_sample date default null,
                            reserved_sample date default null,
                            golden_sealed date default null,
                            inspection_time date default null,
                            is_del varchar(1) default 0,
                            primary key(id, category_num)
                            ); """

        print("初始化表格中...")
        time.sleep(DB.LOADING_TIME)  # 减缓插入速度

        self.cursor.execute(sql)

    def store_to(self):
        """存储excel数据进入sql
           把文件与py文件放在同一目录下
        """
        try:
            self.del_sql_table()
            self.create_sql_table()
        except:
            self.create_sql_table()

        # book = DB.open_excel()  # 手动打开excel文件
        book = self.atuo_open_excel()  # 自动打开excel文件
        sheets = book.sheet_names()  # 获取所有sheet表名

        for sheet in sheets:
            sh = book.sheet_by_name(sheet)  # 打开每一张表
            row_num = sh.nrows

            data_list = list()  # 定义列表用来存放数据
            # 第一行是标题名,对应表中的字段名所以应该从第二行开始
            # 计算机以0开始计数,所以值是1
            for i in range(1, row_num):
                # if sh.row_values(i)
                row_data = sh.row_values(i)  # 按行获取excel的值

                value = (row_data[0], row_data[1], row_data[2], row_data[3],
                    row_data[4], row_data[5], row_data[6], row_data[7],
                    row_data[8], row_data[9], row_data[10], row_data[11], row_data[12], row_data[13])

                data_list.append(value)  # 将数据暂存在列表

            # 调用插入操作方法
            self.insert_into(data_list, sheet, row_num)

        # 调用close关闭cursor和connection
        self.close()

    def insert_into(self, data_list, sheet, row_num):
        """插入操作"""
        sql = """INSERT IGNORE INTO sainty (id,category_num,
                            guest,total_quantity,factory_name,start_order_date,delivery_date,
                            sailing_date,pp_sample,sealed_sample,reserved_sample,
                            golden_sealed,inspection_time,is_del) VALUES (%s, %s, %s, %s, %s,
                            %s, %s, %s, %s, %s, %s, %s, %s, %s)"""

        print("插入订单数据中...")
        time.sleep(DB.LOADING_TIME)  # 减缓插入速度
        self.cursor.executemany(sql, data_list)  # 执行sql语句
        self.db.commit()  # 提交
        data_list.clear()  # 清空list
        print("表格: " + sheet + " 已经被插入 " + str(row_num) + " 数据!")

    def query_sql(self, input_num):
        """查询操作"""

        # 创建列表用来存储每行的下单时间,交货期,船期,验货时间 元祖
        date_list = list()

        sql = """select * from sainty where is_del='0'"""

        # 执行sql语句
        self.cursor.execute(sql)

        # 创建表头
        order_sheet = prettytable.PrettyTable(["po号", "品类数", "客人", "总数量", "工厂名",
                                     "下单日", "交期", "船期", "产前样", "签字封样",
                                     "留样", "客人封样", "验货时间", "是否出运"])
        # 获取所有记录
        results = self.cursor.fetchall()
        for row_data in results:
            # 获取每行的每个字段的值
            id = row_data[0]
            category_num = row_data[1]
            guest = row_data[2]
            total_quantity = row_data[3]
            factory_name = row_data[4]
            start_order_date = row_data[5]
            delivery_date = row_data[6]
            sailing_date = row_data[7]
            pp_sample = row_data[8]
            sealed_sample = row_data[9]
            reserved_sample = row_data[10]
            golden_sealed = row_data[11]
            inspection_time = row_data[12]
            is_del = row_data[13]

            # 创建一个元祖用来存储下单时间,交货期,船期,验货时间等时间
            date_value = (pp_sample, sealed_sample, reserved_sample, golden_sealed,
                          start_order_date, delivery_date, sailing_date, inspection_time,
                          id, category_num, factory_name, guest)

            date_list.append(date_value)  # 将时间变量存入列表

            # 如果用户输入时2,则将数据放入prettyTable的表格内
            if input_num == "2":
                order_sheet.add_row([id, category_num, guest, total_quantity,
                          factory_name, start_order_date, delivery_date,
                          sailing_date, pp_sample, sealed_sample, reserved_sample,
                           golden_sealed, inspection_time, is_del])

        # 判断用户输入,如果是查询,则数据的表格被打印
        if input_num == "2":
            print("\n")
            print("=" * 170)
            print("查询数据库")
            print(order_sheet)

            self.close()

        # 返回日期列表
        return date_list


    def update_sql(self):
        """修改操作"""

        print("\n")
        print("=" * 50)
        print("修改数据功能维护中...")

    def del_sql(self):
        """删除操作"""

        print("")
        print("="* 50)
        print("删除已经出运的数据")
        sql = """update sainty set is_del='1' where id=%s"""

        # 创建临时列表用来存储用户输入
        temp_po_list = list()
        while True:
            po_num = input("请输入需要删除的订单PO号[回车退出删除]:")
            if po_num == "":
                break
            else:
                print(po_num, "订单信息将被删除...")
            temp_po_list.append(po_num)

        self.cursor.executemany(sql, temp_po_list)
        self.db.commit()  # 提交
        temp_po_list.clear()  # 清空list
        print("数据已经删除")
        self.close()

    def close(self):
        """关闭资源"""
        self.cursor.close()
        self.db.close()


if __name__ == '__main__':
    db = DB("sainty")
    db.store_to()

order.py:订单模块

import time
import excel_to_sql

class Order(object):
    """订单类"""

    # 读取时间常量
    LOADING_TIME = 3

    def __init__(self):
        """初始化"""

        print("订单操作程序启动中...")
        time.sleep(Order.LOADING_TIME)
        print("订单操作系统已经启动...")

    @staticmethod
    def menu():
        """界面"""
        print("\n")
        print("功能界面")
        print("=" * 50)
        print("欢迎使用大货跟踪程序V1.20200731")
        print("1.导入EXCEL表文件")
        print("2.查询订单详情(未出运)")
        print("3.修改订单信息")
        print("4.删除订单")
        print("0.退出程序")
        print("=" * 50)

    @staticmethod
    def input_order_data():
        """输入数据"""

        # 创建数据库类
        db = excel_to_sql.DB("sainty")
        # 调用插入方法
        db.store_to()
        print("EXCCEL数据已经导入进数据库")

    @staticmethod
    def retrieve_order_data(input_num):
        """查询操作"""
        # 创建数据库类
        db = excel_to_sql.DB("sainty")
        db.query_sql(input_num)

    @staticmethod
    def exit_order():
        """退出订单操作"""
        print("退出程序中...")
        time.sleep(Order.LOADING_TIME)
        print("订单操作程序已经退出,欢迎再次使用O(∩_∩)O~")
        exit()

    def user_select(self):
        user_input = input("请输入需要操作的功能序号[1 2 3 4 0]:\n")
        if user_input == "1":
            Order.input_order_data()
        elif user_input == "2":
            Order.retrieve_order_data(user_input)
        elif user_input == "3":
            self.update_order_data()
        elif user_input == "4":
            self.del_order_data()
        elif user_input == "0":
            Order.exit_order()
        else:
            print("输入有误,请重新输入")

    def update_order_data(self):
        """修改日期操作"""
        # 创建数据库类
        db = excel_to_sql.DB("sainty")
        db.update_sql()

    def del_order_data(self):
        """删除订单数据(通过isdel实现)"""
        # 创建数据库类
        db = excel_to_sql.DB("sainty")
        db.del_sql()

    def start(self):

        while True:
            Order.menu()  # 菜单界面
            self.user_select()  # 用户输入

order_clock.py:订单备忘闹钟模块

import time
import datetime
import tkinter
import threading
import excel_to_sql

"""
时钟备忘功能的思路:
    1.从数据库获取数据,下单时间,交货期,船期,验货时间
    2.从系统获取时间
    3.进行时间的判断
        系统时间 - 下单时间 >= 15天---> 弹出事务提醒框:内容显示poxxxx的xxx玩具产前样工厂未寄送
        船期 - 系统时间 <= 20天---> 弹出事务提醒框:内容显示POXXX的XXX玩具寄客人样工厂未寄送
                              ---> 弹出事务提醒框:内容显示POXXX的XXX玩具留样样工厂未寄送
        验货时间 - 系统时间 <= 20天--->弹出事务提醒框:内容显示POXXX的XXX玩具签字样工厂未寄送
            如果验货时间为空,则不弹出
    解决线程过多问题:如果后面订单中品类与包装与之前订单相同,则无需要产前样,封样,留样
"""

class Clock(object):
    """备忘时钟类"""
    # 是否在屏幕打印表格的标记
    INPUT_NUM = "1"
    # 读取时间常量
    LOADING_TIME = 3
    # 刷新监听时间为 【3小时一次】
    FLUSH_TIME = 60 * 60 * 3

    def __init__(self):
        """"""
        self.__init_msg()
        self.excel_to_sql = excel_to_sql.DB("sainty")

    @staticmethod
    def __init_msg():
        """初始化消息"""
        print("备忘时钟功能开启中...")
        time.sleep(Clock.LOADING_TIME)
        print("备忘时钟程序已开启...")

    @staticmethod
    def ring():
        """弹框时候的声音"""
        print("\a")


    @staticmethod
    def msg_box(factory_name, id_number, guest, sample_type, days):
        """消息提示框功能"""
        root = tkinter.Tk()
        # root.wm_attributes('-topmost', 1)  # 窗口始终在前面
        root.title("订单跟踪")  # 标题
        root.geometry('400x200')  # 窗口尺寸
        root.resizable(False, False)  # 固定窗体

        tkinter.Button(root, text="""【%s-%s-%s-%s】工厂还没有寄送
                距离下单日已经过去【%d天】
                """ %
                (factory_name, id_number, guest, sample_type,
                 days), font=50,
                width=400, height=200).pack()
        root.mainloop()

    @staticmethod
    def start_handle_thread(factory_name, id_number, guest, sample_type, days):
        """开启一个监听线程"""
        threading.Thread(target=Clock.msg_box,
                         args=(factory_name, id_number,
                               guest, sample_type, days)).start()

    def get_data(self):
        """获取数据"""
        # 调用excel_to_sql模块的query_sql方法,获取日期列表
        date_time = self.excel_to_sql.query_sql(Clock.INPUT_NUM)
        # 获取系统时间
        sys_date = datetime.date.today()
        return date_time, sys_date

    def handle_time(self):
        """监听时间"""
        while True:
            time.sleep(Clock.LOADING_TIME)  # 开辟多线程间的开启时间间隔,与订单线程错开

            # 调用方法,获取数据
            date_time = self.get_data()[0]
            sys_date = self.get_data()[1]

            # 遍历日期列表获取值
            for time_tple in date_time:
                pp_sample_date = time_tple[0]           # 获取产前样确定时间
                sealed_sample_date = time_tple[1]       # 获取封样时间
                reserved_sample_date = time_tple[2]     # 获取留样时间
                golden_sealed_date = time_tple[3]       # 获取寄客人样时间
                start_order_date_date = time_tple[4]    # 获取下单时间
                delivery_date_date = time_tple[5]       # 获取交期
                sailing_date_date = time_tple[6]        # 获取船期
                inspection_time_date = time_tple[7]     # 获取验货时间
                id_number = time_tple[8]                # po号
                cate = time_tple[9]                     # 玩具品名
                factory_name = time_tple[10]            # 工厂名
                guest = time_tple[11]                   # 客人名



##################################################################################################################

                try:
                    pp_sample_date_day = pp_sample_date.day

                except:
                    pp_sample_date = ""
                # 判断时间并监听
                # 系统时间 - 下单时间 >= 15天---> 弹出事务提醒框:内容显示poxxxx的xxx玩具[产前样]工厂未寄送
                if pp_sample_date == "":
                    if (sys_date - start_order_date_date).days >= 15:
                        # print("【%s-%s-%s产前样】工厂还没有寄送" % (factory_name, id_number, guest))
                        # print("距离下单日已经过去【%d天】" % (sys_date - start_order_date_date).days)
                        # print("-" * 50)

                        # 调用线程监听数据方法,做到同时弹出事务框
                        Clock.start_handle_thread(factory_name, id_number, guest, "产前样",
                                                  (sys_date - start_order_date_date).days)

##################################################################################################################

                try:
                    golden_sealed_date_day = golden_sealed_date.day
                    sealed_sample_date_day = sealed_sample_date.day
                except:
                    golden_sealed_date = ""
                    sealed_sample_date = ""
                # 船期 - 系统时间 <= 20天---> 弹出事务提醒框:内容显示POXXX的XXX玩具[寄客人样]工厂未寄送
                #                       ---> 弹出事务提醒框:内容显示POXXX的XXX玩具[留样]工厂未寄送
                if golden_sealed_date == "" or sealed_sample_date == "":
                    if 0 < (sailing_date_date - sys_date).days <= 20:
                        # print("【%s-%s-%s寄客人样与留样】工厂还没有寄送" % (factory_name, id_number, guest))
                        # print("距离下单日已经过去【%d天】" % (sailing_date_date - sys_date).days)
                        # print("-" * 50)

                        # 调用线程监听数据方法,做到同时弹出事务框
                        Clock.start_handle_thread(factory_name, id_number, guest, "寄客人样/留样",
                                                  (sailing_date_date - sys_date).days)

##################################################################################################################

                #  验货时间 - 系统时间 <= 20天--->弹出事务提醒框:内容显示POXXX的XXX玩具签字样工厂未寄送
                #      如果验货时间为空,则不弹出
                try:
                    if 0 < (inspection_time_date - sys_date).days <= 25:
                        # print("【%s-%s-%s签字样】工厂还没有寄送" % (factory_name, id_number, guest))
                        # print("距离下单日已经过去【%d天】" % (sailing_date_date - sys_date).days)
                        # print("-" * 50)

                        # 调用线程监听数据方法,做到同时弹出事务框
                        Clock.start_handle_thread(factory_name, id_number, guest, "签字封样",
                                                  (sailing_date_date - sys_date).days)
                except:
                    pass
            time.sleep(Clock.FLUSH_TIME)  # 每3小时刷新一次数据

##################################################################################################################

    def start(self):
        """开始程序"""
        try:
            self.handle_time()
        except:
            print("程序出错")

main.py:主模块

import order
import order_clock
import threading



"""
Order类负责:
    订单数据的CRUD
Clock类负责:
    订单事件的监听
Main类负责:
    整体框架的控制
"""

class Main(object):
    def __init__(self):

        # 调用权限方法
        Main.access()

        # 创建对象
        self.__create_object()

    @staticmethod
    def access():
        # 输入权限
        username = input("请输入用户名:")
        password = input("请输入密码:")
        if username == "root" and password == "123456":
            print("登录成功!欢迎您  %s" % username)
        else:
            raise Exception("用户名或密码错误!")

    def __create_object(self):
        """"""
        self.order_clock = order_clock.Clock()
        self.order = order.Order()

    def thread_order(self):
        # 订单信息功能
        t_order = threading.Thread(target=self.order.start, args=())
        # self.order.start()
        t_order.start()

    def thread_order_clock(self):
        # 闹钟备忘功能
        t_order_clock = threading.Thread(target=self.order_clock.start, args=())
        # self.order_clock.start()
        t_order_clock.start()

    def run_program(self):
        """整体框架"""
        self.thread_order()
        self.thread_order_clock()


if __name__ == "__main__":
    try:
        main = Main()
        main.run_program()
    except Exception as ret:
        print("错误:", ret)

声明:技术有限,请大佬不要见怪!谢谢!有不足之处请各位朋友指出!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值