Beispiel #1
0
    def __init__(self):
        self.db = MysqlDB()
        self.cph = CashierPrintHandler()
        self.user_id = None  # 正在结算的用户ID
        self.user_name = None  # 正在结算的用户名
        self.cashier_id = None  # 结算员ID

        self.create_tcp_server()
Beispiel #2
0
    def __init__(self):
        self.db = MysqlDB()
        self.aph = CustomerPrintHandler()
        self.user_id = None
        self.shopping_cart = None

        # 主函数映射方法
        self.start_menu_map = {
            "1": "register",  # 注册
            "2": "login",  # 登录
        }

        # 用户菜单函数映射
        self.customer_menu_map = {
            "1": "get_product_list",  # 查看商品列表
            "2": "add_product",  # 添加商品到购物车
            "3": "remove_product",  # 从购物车中移除商品
            "4": "get_my_shopping_carts",  # 查看我的购物车
            "5": "paying",  # 发起结算
        }
Beispiel #3
0
    def __init__(self):
        self.db = MysqlDB()
        self.aph = AdminPrintHandler()

        # 主函数方法映射
        self.start_menu_map = {
            "1": "register",  # 注册
            "2": "login",  # 登录
        }
        # 管理员菜单函数映射
        self.admin_menu_map = {
            "1": "get_product_list",  # 获取商品信息列表
            "2": "add_product",  # 添加新商品
            "3": "change_product_count",  # 调整商品库存
            "4": "get_order_list",  # 查看订单列表
            "5": "get_order_detail",  # 查看订单详情
            "6": "remove_product",  # 商品下架
            "7": "check_profit",  # 计算收益
            "8": "add_cashier",  # 添加结算员
            "9": "lacked_product_list",  # 缺货库存列表
        }

        # 创建UPD Socket连接
        self.create_udp_socket()
Beispiel #4
0
    def __init__(self):
        self.db = MysqlDB()
        self.aph = CustomerPrintHandler()

        # 主函数映射方法
        self.start_menu_map = {
            "1": "register",  # 注册
            "2": "login",  # 登录
        }

        # 用户菜单函数映射
        self.customer_menu_map = {
            "1": "add_product",  # 添加商品到购物车
            "2": "remove_product",  # 从购物车中移除商品
            "3": "get_my_orders",  # 查看我的购物车
            "4": "paying",  # 发起结算
        }
        # 创建TCP Socket连接
        self.create_tcp_socket()
Beispiel #5
0
class CashierHandler:
    def __init__(self):
        self.db = MysqlDB()
        self.cph = CashierPrintHandler()
        self.user_id = None  # 正在结算的用户ID
        self.user_name = None  # 正在结算的用户名
        self.cashier_id = None  # 结算员ID

        self.create_tcp_server()

    def create_tcp_server(self):
        """
        创建TCP服务
        :return:
        """
        self.skfd = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.skfd.bind(CASHIER_SOCKET_SERVER_ADDR)
        self.skfd.listen(3)

    def success_send(self, connfd, msg):
        connfd.send("200 {}".format(msg).encode())

    def fail_send(self, connfd, msg):
        connfd.send("400 {}".format(msg).encode())

    def do_request(self, connfd, request_data):
        request_data = eval(request_data)

        if len(request_data["shopping_cards"]):
            id, pn, name = self.db.get_user_msg_from_id(
                request_data["user_id"])
            self.user_id = id
            self.user_name = name
            print("{}来结算了".format(name))
            self.success_send(connfd, "request successful.")
        else:
            self.fail_send(connfd, "您的购物车为空!")

    def sum_shopping_cards_amount(self, shopping_cards):
        """
        计算购物车中商品总价
        :param shopping_cards:
        :return:
        """
        total_amount = Decimal("0.00")
        for item in shopping_cards:
            total_amount += item["price"] * item["count"]
        return total_amount

    def do_shopping_cards(self, connfd, request_data):
        """
        计算购物车中商品总价,发送回用户端
        :param connfd:socket连接
        :param request_data:用户购物车信息
        :return:
        """
        total_amount = self.sum_shopping_cards_amount(
            eval(request_data)["shopping_cards"])
        self.success_send(connfd, total_amount)

    def sum_shopping_cards_profit(self, shopping_cards):
        total_profit = Decimal("0.00")
        for item in shopping_cards:
            profit = self.db.get_profit_by_product_id(item["product_id"])
            total_profit += profit * item["count"]
        return total_profit

    def commit_record(self, commit_record):
        """
        保存交易记录
        :return:
        """
        total_amount = self.sum_shopping_cards_amount(
            commit_record["success_list"])
        total_profit = self.sum_shopping_cards_profit(
            commit_record["success_list"])
        order_id = self.db.create_order_record(self.user_id, self.cashier_id,
                                               total_amount, total_profit)
        for item in commit_record["success_list"]:
            self.db.create_order_detail(order_id, item["product_id"],
                                        item["count"], item["price"])
        return order_id

    def get_export_ticket_paths(self):
        """
        打印小票文件路径及文件
        :return:
        """
        t = datetime.datetime.now()
        str_t1 = t.strftime("%Y-%m-%d_%H:%M:%S")
        return USER_TICKET_PATH + str_t1 + ".txt"

    def export_ticket(self, order_id, pay_result, total_amount, user_pay_money,
                      money_return):
        """
        打印小票
        :return:
        """
        id, pn, name = self.db.get_user_msg_from_id(self.cashier_id)

        file_path = self.get_export_ticket_paths()
        f = open(file_path, 'w+')
        f.write('                消费单' + '\n')
        f.write("-------------***********-------------" + "\n")
        f.write("结算单号:                  %s" % order_id + "\n")
        for into in pay_result["success_list"]:
            f.write('商品名:{},单价:{}元,个数:{}个\n'.format(into["name"],
                                                    into["price"],
                                                    into['count']))
        f.write("应付:                    %s" % total_amount + '\n'
                "实付:                    %s" % user_pay_money + '\n'
                "找零:                    %s" % money_return + "\n")
        f.write("结算员:{}(ID:{})\n".format(name, id))
        f.write("结算时间:{}".format(
            datetime.datetime.now().strftime('%Y年%m月%d日 %H:%M:%S')))
        f.flush()
        f.close()
        return "小票已保存至:{}".format(file_path)

    def send_to_udp_server(self, data):
        """
        给后台发送信息
        :return:
        """
        skfd = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        skfd.sendto(data.encode(), ADMIN_SOCKET_SERVER_ADDR)
        skfd.close()

    def reduce_product_count(self, product_list):
        """
        扣除库存
        :param product_list: 这里接收用户的一个支付成功的购物车列表,
        遍历里面的商品ID扣除库存(注意判断库存不能为负,否则打印log)
        :return:
        """
        success_list = list()
        fail_list = list()
        for value in product_list['shopping_cards']:
            product_id = value["product_id"]
            product_name = value["name"]
            product_count = value["count"]
            num = self.db.get_product_count(product_id)
            set_count = num - product_count
            if set_count > 0:
                self.db.update_product_count(product_id, set_count)
                success_list.append(value)
            elif set_count == 0:
                self.db.update_product_count(product_id, set_count)
                success_list.append(value)
                data = "ID是%s的%s商品库存不足" % (product_id, product_name)
                self.send_to_udp_server(data)
            else:
                fail_list.append(value)
        return {"success_list": success_list, "fail_list": fail_list}

    def do_paying(self, connfd, request_data):
        """
        处理用户支付
        :param connfd: socket连接
        :param request_data:shopping_cards_msg user_pay_money
        :return:
        """
        shopping_cards_msg, user_pay_money = request_data.split("$$")
        total_amount = self.sum_shopping_cards_amount(
            eval(shopping_cards_msg)["shopping_cards"])
        money_return = Decimal(user_pay_money) - Decimal(
            total_amount)  # 计算找零金额
        if money_return >= 0:
            # 结算、减库存
            pay_result = self.reduce_product_count(eval(shopping_cards_msg))
            if len(pay_result.get("success_list", False)):
                # 创建订单记录
                order_id = self.commit_record(pay_result)
                # 打印小票
                ticket_msg = self.export_ticket(order_id, pay_result,
                                                total_amount, user_pay_money,
                                                money_return)
                self.success_send(connfd, ticket_msg)
                # print("{}结算完成".format(self.user_name))
            else:
                # 结算内容全部失败
                self.fail_send(connfd, "订单库存被抢付,支付失败。")
        else:
            self.fail_send(connfd, "支付金额不足!")

    def main_task(self, connfd, addr):
        while True:
            data = connfd.recv(1024)
            try:
                request_mode, request_data = get_request(data.decode())
            except Exception as info:
                logger.info(info)
                continue

            if request_mode == "REQUEST":
                self.do_request(connfd, request_data)
            elif request_mode == "SHOPPING_CARDS":
                self.do_shopping_cards(connfd, request_data)
            elif request_mode == "PAYING":
                self.do_paying(connfd, request_data)
            else:
                logger.info("结算端接收请求异常, addr:{}, error_mode:{}".format(
                    addr, request_mode))

    def waiting_for_connect(self):
        """
        多线程启动,循环等待用户结算
        :return:
        """
        while True:
            print("等待结算中...")
            connfd, addr = self.skfd.accept()
            t = Thread(target=self.main_task, args=(connfd, addr))
            t.start()

    def login(self):
        """
        结算员登录
        :return:
        """
        pn = user_input("请输入手机号:")
        password = getpass.getpass("请输入密码:")
        status, msg, user_id = self.db.user_login(pn, password, 2)
        print(msg)

        if status:
            # 登录成功
            self.cashier_id = user_id
            self.waiting_for_connect()
        else:
            # 登录失败
            self.start()

    def start(self):
        """
        结算端启动函数
        :return:
        """
        self.login()
Beispiel #6
0
class AdminHandler:
    # TODO 设置类变量有问题,暂时没有解决方案
    __admin_user_tag = False

    def __init__(self):
        self.db = MysqlDB()
        self.aph = AdminPrintHandler()

        # 主函数方法映射
        self.start_menu_map = {
            "1": "register",  # 注册
            "2": "login",  # 登录
        }
        # 管理员菜单函数映射
        self.admin_menu_map = {
            "1": "get_product_list",  # 获取商品信息列表
            "2": "add_product",  # 添加新商品
            "3": "change_product_count",  # 调整商品库存
            "4": "get_order_list",  # 查看订单列表
            "5": "get_order_detail",  # 查看订单详情
            "6": "remove_product",  # 商品下架
            "7": "check_profit",  # 计算收益
            "8": "add_cashier",  # 添加结算员
            "9": "lacked_product_list",  # 缺货库存列表
        }

        # 创建UPD Socket连接
        self.create_udp_socket()
        # self.__admin_user_tag = False

    def create_udp_socket(self):
        """
        创建UDP socket连接
        :return:
        """
        self.skfd = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        self.skfd.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        self.skfd.bind(ADMIN_SOCKET_SERVER_ADDR)

    def check_pn(self, pn, role):
        if not self.db.user_register_cheker(pn, role):
            self.aph.exist_pn()
            self.start()

        if not match_pn(pn):
            self.aph.error_pn()
            self.start()

    def register(self):
        """
        用户注册
        :return:
        """
        pn = input("请输入手机号:")
        self.check_pn(pn, 1)
        name = input("请输入姓名:")
        # password = getpass.getpass("请输入密码:")
        password1 = input("请输入密码:")
        password2 = input("请再输入一次密码:")
        if password1 != password2:
            self.aph.password_compare_error()
            self.start()

        status, msg = self.db.user_register(name, password1, pn, role=1)
        print(msg)

    def login(self):
        """
        用户登录
        :return:
        """
        pn = input("请输入手机号:")
        # password = getpass.getpass("请输入密码:")
        password = input("请输入密码:")
        status, msg = self.db.user_login(pn, password)
        print(msg)

        if status:
            # 登录成功
            __admin_user_tag = True
            self.admin_menu_handler()
        else:
            # 登录失败
            self.start()

    def check_product_desc(self, desc):
        """
        获取新添商品描述
        :return:
        """
        if not desc:
            desc = "暂无商品描述"
        return desc

    def product_id_str(self, name):
        """
        获取商品ID
        :param name: 商品名称
        :return: 商品ID:数字
        """
        num = 0
        for i in str(name):
            num += ord(i)
        return num

    def price_compare(self, source_price, price):
        """
        比较商品进价,售价大小
        :param source_price: 商品进价
        :param price: 商品售价
        :return: True 或者 False
        """
        return source_price < price

    def get_name(self):
        """
        判断新添商品名称是否重复
        :return: 新添商品名称
        """
        while True:
            name = input("请输入新添商品名称:")
            if not self.db.check_product_name(name):
                print("商品名称重复")
                continue
            else:
                return name

    def get_price(self):
        """
        录入新添商品进价,售价
        :return: 商品进价,售价
        """
        while True:
            source_price = get_number_input("请输入新添商品进价:", is_float=True)
            price = get_number_input("请输入新添商品售价:", is_float=True)
            if not self.price_compare(source_price, price):
                print("售价有误")
                continue
            else:
                return source_price, price

    def add_product(self):
        """
        添加新商品
        :return:商品信息(名称,描述,进价,售价,数量,ID)
        """
        name = self.get_name()
        source_price, price = self.get_price()
        count = get_number_input("请输入数量:")
        description = self.check_product_desc(input("请输入新添商品描述:"))
        product_id = self.product_id_str(name)
        print(
            self.db.add_db_product(
                (name, description, source_price, price, count, product_id)))

    def get_product_list(self):
        """
        获取商品列表(管理员)
        :return:
        """
        data = self.db.get_product_list_db(is_admin=True)
        for product in data:
            self.aph.product_detail_for_admin(product)

    def change_product_count(self):
        """
        修改库存
        :return:
        """
        while True:
            product_id = get_number_input("请输入更改库存的商品的ID(输入q退出):")
            if product_id == "q":
                break
            if self.db.judge_product_id(product_id):
                change_count = get_number_input("调整商品库存为:")
                self.db.change_product_count_db(product_id, change_count)
            else:
                continue

    # @is_admin(__admin_user_tag)
    def add_cashier(self):
        """
        添加结算员
        :return:
        """
        pn = input("请输入结算员手机号:")
        self.check_pn(pn, 2)
        name = input("请输入结算员姓名:")
        # password = getpass.getpass("请输入密码:")
        password = input("请输入结算员密码:")
        status, msg = self.db.user_register(name, password, pn, role=2)
        print(msg)

    def lacked_product_list(self):
        pass

    def remove_product(self):
        product_id = input("请输入下架商品的ID:")
        print(self.db.remove_db_product(product_id))

    def format_datetime(self, input_date):
        formater = r"^[1-9]\d{0,3}-(1[0-2]|0?[1-9])-(3[01]|[12]\d|0?[1-9])$"
        return re.match(formater, input_date)

    def affirm_time(self):
        """
        匹配返回用户输入的时间段
        :return:
        """
        while True:
            order_begin = input("请输入要查询订单的开始时间:")
            order_end = input("请输入要查询订单的结束时间:")
            if self.format_datetime(order_begin) and self.format_datetime(
                    order_end):
                return order_begin, order_end
            else:
                print("输入有误 !格式:'2019-10-10'!")
                continue

    def get_order_list(self):
        """
        获取订单列表
        :return:
        """
        order_begin, order_end = self.affirm_time()
        data = self.db.get_order_list_db(order_begin, order_end)

        for order in data:
            user_id, profit, order_id, cashier_id, amount, create_time = order
            # 补充订单中用户和结算员的详细信息
            order_info = (
                self.db.get_user_msg_from_id(user_id),  # 根据ID补充用户信息
                profit,
                order_id,
                self.db.get_user_msg_from_id(cashier_id),  # 根据ID补充结算员ID
                amount,
                create_time,
            )

            self.aph.get_order_list(order_info)

    def check_profit(self):
        """
        计算收益(刘梓威)
        """
        order_begin, order_end = self.affirm_time()
        data = self.db.get_order_list_db(order_begin, order_end)
        profit = Decimal(0.00)
        for product in data:
            profit += product[1]

        result = "%s到%s的收益为%s元" % (order_begin, order_end, profit)
        print(result)

    def get_order_detail(self):
        """
        获取订单详情
        :return:
        """
        order_id = get_number_input("请输入订单ID:")
        data = self.db.get_order_details_db(order_id)
        for order_detail in data:
            self.aph.get_order_detail(order_detail)

    def admin_menu_handler(self):
        """
        登录成功后主菜单
        :return:
        """
        while True:
            # TODO 注销退出
            self.aph.admin_menu()
            user_input = input(">>")
            point_func = self.admin_menu_map.get(user_input)
            if not point_func:
                self.aph.error_input()
            else:
                eval(change_point_func(point_func))

    def wating_for_socket_msg(self):
        """
        UDP等待接收消息
        :return:
        """
        while True:
            data, addr = self.skfd.recvfrom(1024)
            print("您有新的消息!来自{},消息内容:{}".format(addr, data.decode()))
            # request_mode, content = self.get_request(data)
            # print(request_mode)

    def start(self):
        """
        启动函数
        :return:
        """
        while True:
            self.aph.main_menu()
            user_input = input(">>")
            point_func = self.start_menu_map.get(user_input, False)
            if not point_func:
                self.aph.error_input()
            else:
                eval(change_point_func(point_func))
Beispiel #7
0
class CustomerHandler:
    def __init__(self):
        self.db = MysqlDB()
        self.aph = CustomerPrintHandler()
        self.user_id = None
        self.shopping_cart = None

        # 主函数映射方法
        self.start_menu_map = {
            "1": "register",  # 注册
            "2": "login",  # 登录
        }

        # 用户菜单函数映射
        self.customer_menu_map = {
            "1": "get_product_list",  # 查看商品列表
            "2": "add_product",  # 添加商品到购物车
            "3": "remove_product",  # 从购物车中移除商品
            "4": "get_my_shopping_carts",  # 查看我的购物车
            "5": "paying",  # 发起结算
        }

    def create_tcp_socket(self):
        try:
            self.skfd = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            self.skfd.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
            self.skfd.connect(CASHIER_SOCKET_SERVER_ADDR)
        except Exception as error:
            self.aph.connect_to_cashier_error()
            logger.error("创建与结算端的TCP连接失败,msg:%s" % error)

    def check_pn(self, pn, role):
        if not self.db.user_register_cheker(pn, role):
            self.aph.exist_pn()
            self.start()

        if not match_pn(pn):
            self.aph.error_pn()
            self.start()

    def register(self):
        """
        用户注册
        :return:
        """
        pn = user_input("请输入手机号:")
        self.check_pn(pn, 0)
        name = user_input("请输入姓名:")
        # password = getpass.getpass("请输入密码:")
        password1 = user_input("请输入密码:")
        password2 = user_input("请再输入一次密码:")
        if password1 != password2:
            self.aph.password_compare_error()
            self.start()

        status, msg = self.db.user_register(name, password1, pn)
        print(msg)

    def login(self):
        """
        用户端 用户登录
        :return:
        """
        pn = user_input("请输入手机号:")
        password = getpass.getpass("请输入密码:")
        status, msg, user_id = self.db.user_login(pn, password, 0)
        print(msg)
        if status:
            # 登录成功
            self.user_id = user_id  # 记录用户ID
            self.shopping_cart = ShoppingCart(user_id=user_id)  # 实例化购物车
            while True:
                self.aph.customer_memu()
                user_input_msg = user_input(">>")
                point_func = self.customer_menu_map.get(user_input_msg)
                if not point_func:
                    self.aph.error_input()
                else:
                    eval(change_point_func(point_func))

    def get_add_product_input(self):
        """
        获取用户添加到购物车的输入商品
        :return:
        """
        while True:
            product_id = get_number_input("请输入购买的商品ID:")
            result = self.db.get_product_msg(product_id)
            if not result:
                print("您输入的商品ID有误!")
                continue
            else:
                product_id, name, description, source_price, price, count = result
                user_input_count = get_number_input("请输入购买的商品个数:")
                if int(count) < user_input_count:
                    print("商品库存不足!")
                    continue
                else:
                    return product_id, name, price, user_input_count

    def add_product(self):
        """
        添加商品到购物车
        :return:
        """
        product_id, name, price, user_input_count = self.get_add_product_input(
        )
        self.shopping_cart.add_product(
            Product(
                product_id=product_id,
                name=name,
                price=price,
                count=user_input_count,
            ))

    def remove_product(self):
        """
        从购物车中移除商品
        :return:
        """
        product_id = get_number_input("请输入需要移除的商品ID:")
        status, msg = self.shopping_cart.remove_product(product_id)
        print(msg)

    def transform_shopping_cards(self):
        return {
            "user_id":
            self.user_id,
            "shopping_cards":
            [product.__dict__ for product in self.shopping_cart.product_list]
        }

    def send_shopping_cards(self):
        request_data = "SHOPPING_CARDS {}".format(
            self.transform_shopping_cards())
        self.skfd.send(request_data.encode())

    def paying(self):
        """
        发起结算
        :return:
        """
        self.create_tcp_socket()
        request_data = "REQUEST {}".format(self.transform_shopping_cards())
        self.skfd.send(request_data.encode())
        status_code, msg = get_request(self.skfd.recv(1024).decode())

        if status_code == "200":
            self.send_shopping_cards()
            status_code, msg = get_request(self.skfd.recv(1024).decode())

            if status_code == "200":
                total_price = Decimal(
                    get_number_input("请输入付款金额:", is_float=True))
                if total_price < Decimal(msg):
                    print("金额不足")
                else:
                    request_data = "PAYING {}$${}".format(
                        self.transform_shopping_cards(), total_price)
                    self.skfd.send(request_data.encode())
                    status_code, msg = get_request(
                        self.skfd.recv(1024).decode())
                    print(msg)
                    # 清空购物车
                    self.shopping_cart.reset_product_list()
            else:
                self.aph.paying_error(msg)
        else:
            self.aph.paying_error(msg)

    def get_my_shopping_carts(self):
        """
        获取我的购物车商品列表
        :return:
        """
        self.aph.my_shop_cards(self.shopping_cart.product_list)

    def get_product_list(self):
        """
        获取商品信息列表
        :return:
        """
        for item in self.db.get_product_list_db():
            self.aph.product_list(item)

    def start(self):
        """
        客户端启动函数
        :return:
        """
        while True:
            self.aph.main_menu()
            user_input_msg = user_input(">>")
            point_func = self.start_menu_map.get(user_input_msg, False)
            if not point_func:
                self.aph.error_input()
            else:
                eval(change_point_func(point_func))