Untitled

mail@pastecode.io avatar
unknown
plain_text
7 months ago
26 kB
2
Indexable
Never
from time import sleep
from datetime import datetime

# Print important one line message
def print_message(message):
    length = len(message)

    if length <= 30:
        print("*" * 30)
        print(message)
        print("*" * 30)
    else:
        print("*" * len(message))
        print(message)
        print("*" * len(message))

# User choose for menu
def menu_choice(choice1, choice2, choice3 = "", choice4 = ""):
    print("-" * 30)
    print(f"1. {choice1}")
    print(f"2. {choice2}")
    if choice3 != "":
        print(f"3. {choice3}")
        choice = check_input_range(1, 3)
    elif choice4 != "":
        print(f"4. {choice4}")
        choice = check_input_range(1, 4)
    else:
        choice = check_input_range(1, 2)
    print("-" * 30)


    if choice == 1:
        return choice1
    elif choice == 2:
        return choice2
    elif choice == 3:
        return choice3
    elif choice == 4:
        return choice4

# Limit user input range based on the menu
def check_input_range(lower_limit, upper_limit):
    while True:
        try:
            print("-" * 30)
            input_choice = int(input(">>> "))
            if input_choice < lower_limit or input_choice > upper_limit:
                raise ValueError
        except:
            print_message("Invalid Input! Please Try Again!")
            sleep(1)
        else:
            return input_choice

# Limit customer's message to 300 characters
def check_message_length():
    max_characters = 300
    while True:
        input_message = input("Message for Recipient (Max 300 Characters): ")
        if len(input_message) > max_characters:
            print_message("Your Message Should Not Be Longer Than 300 Characters! Please Try Again!")
            print_message("Your Original Message: " + input_message[:max_characters])
        else:
            break

# Determine the delivery charge based on the week
def weekend_delivery_charge(input_date):
    # input_date = datetime.strptime(date_str, "%Y-%m-%d")
    week = input_date.strftime("%a")

    if week == "Sat" or week == "Sun":
        delivery_charge = 10
        return delivery_charge
    else:
        delivery_charge = 0
        return delivery_charge

# Check the user input date
def is_valid_date():
    today_date_and_time = datetime.today()
    today_date = today_date_and_time.date()
    print_message(f"Today's Date: {today_date}")

    while True:
        input_date = input("Delivery Date (YYYY-MM-DD): ")
        try:
            input_date = datetime.strptime(input_date, '%Y-%m-%d').date()
            if input_date < today_date:
                print("Invalid Date! Please enter a date on or after today.")
                continue
        except ValueError:
            print_message("Invalid Date! Please Try Again!")
            sleep(1)

        else:

            if input_date > today_date:
                same_day_delivery = "No"
                same_day_delivery_charges = 0
                weekend_delivery_charges = weekend_delivery_charge(input_date)
                return same_day_delivery, same_day_delivery_charges, input_date, weekend_delivery_charges

            elif input_date == today_date:
                confirmation = input("Same Day Delivery? (Additional Charge of $35 Applies) (Y/N): ")

                if confirmation.upper() == "Y":
                    same_day_delivery = "Yes"
                    same_day_delivery_charges = 35
                    weekend_delivery_charges = weekend_delivery_charge(input_date)
                    return same_day_delivery, same_day_delivery_charges, input_date, weekend_delivery_charges
                else:
                    continue

# Let the user choose the shipping option
def shipping_option():
    print("Shipping Option: ")
    choice = menu_choice("Store Pick Up", "Delivery")

    if choice == "Store Pick Up":
        delivery_address = "-"
        same_day_delivery = "No"
        same_day_delivery_charges = 0
        delivery_charges = 0
        delivery_date = "-"
        return delivery_date, same_day_delivery, same_day_delivery_charges, delivery_charges, delivery_address

    elif choice == "Delivery":
        delivery_address = input("Delivery Address: ")
        same_day_delivery, same_day_delivery_charges, delivery_date, weekend_delivery_charges = is_valid_date()
        delivery_charges = 35 + weekend_delivery_charges
        return delivery_date, same_day_delivery, same_day_delivery_charges, delivery_charges, delivery_address

# Print the item content from text file
def print_context(mode, attribute_list):
    row_line = "-" * (30 * len(attribute_list))
    for attribute in attribute_list:
        print(get_aligned_string(attribute, 30), end = "")

    if mode == "Header":
        print("\n" + row_line + "\n")
    elif mode == "Content":
        print("\n")

# Ask and print the order details
def get_customer_details():
    customer_name = input("Customer's Name: ")
    recipient_name = input("Recipient's Name: ")
    message = check_message_length()
    return customer_name, recipient_name, message



# Get item list for summary
def get_item_details(item_line, mode):
    item_str_list = []
    id = "-"
    name = "-"
    price = "-"
    if item_line != None:
        item_str_list = item_line.split(",")
        
    if item_str_list != []:
        id = item_str_list[0]
        name = item_str_list[1]
        price = int(item_str_list[-2])
    else:
        new_item_list = ["Add-On:", "", "", 0]
        return new_item_list

    if mode == "Bloom":
        new_item_list = ["Item:"]
    elif mode == "Add-On":
        new_item_list = ["Add-On:"]

    new_item_list.append(id)
    new_item_list.append(name)
    new_item_list.append(price)

    return new_item_list

# Get delivery list for summary
def get_delivery_and_customer_details(detail, mode, same_day_confirmation = ""):
    if mode == "Date":
        details_list = ["Delivery Date:", detail]
    elif mode == "Same-Day":
        details_list = ["Same Day Delivery:", same_day_confirmation, "", int(detail)]
    elif mode == "Charges":
        details_list = ["Delivery Charges:", "", "", int(detail)]
    elif mode == "Customer Name":
        details_list = ["Customer's name:", detail]
    elif mode == "Recipient Name":
        details_list = ["Recipient's name:", detail]
    elif mode == "Message":
        details_list = ["Message for Recipient:", detail]
    elif mode == "Address":
        details_list = ["Delivery Address:", detail]

    return details_list

def combine_details_list(mode, list1, list2, list3 = "", list4 = ""):
    details_list = []

    if mode == "Item":
        details_list = [list1, list2]
    elif mode == "Delivery":
        details_list = [list1, list2, list3]
    elif mode == "Customer":
        details_list = [list1, list2, list3, list4]

    return details_list

# Get all details list for order summary
def summary_list(available_bloom_line = "", available_addon_line = ""):
    customer_name, recipient_name, message = get_customer_details()
    delivery_date, same_day_confirmation, same_day_delivery_charges, delivery_charges, delivery_address = shipping_option()

    # Get the item details
    bloom_list = get_item_details(available_bloom_line, "Bloom")
    addon_list = get_item_details(available_addon_line, "Add-On")
    item_details = combine_details_list("Item", bloom_list, addon_list)

    # Get the delivery details
    date_list = get_delivery_and_customer_details(delivery_date, "Date")
    same_day_list = get_delivery_and_customer_details(same_day_delivery_charges, "Same-Day", same_day_confirmation)
    charges_list = get_delivery_and_customer_details(delivery_charges, "Charges")
    delivery_details = combine_details_list("Delivery", date_list, same_day_list, charges_list)

    # Get the sum details
    total_calculate = bloom_list[3] + addon_list[3] + same_day_list[3] + charges_list[3]
    total_calculate_str = "$" + str(total_calculate)
    sum_details = [["Total", "", "", total_calculate]]

    # Get the customer details
    customer_name_list = get_delivery_and_customer_details(customer_name, "Customer Name")
    recipient_name_list = get_delivery_and_customer_details(recipient_name, "Recipient Name")
    message_list = get_delivery_and_customer_details(message, "Message")
    address_list = get_delivery_and_customer_details(delivery_address, "Address")
    customer_details = combine_details_list(customer_name_list, recipient_name_list, message_list, address_list)

    return item_details, delivery_details, sum_details, customer_details

# Align center the string
def get_centered_string(string, length):
    left_padding = (length - len(string)) // 2
    right_padding = length - len(string) - left_padding
    centered_string = (" " * left_padding) + string + (" " * right_padding)
    return centered_string

# Align the string
def get_aligned_string(string, length):
    if len(string) >= length:
        return string
    else:
        right_padding = length - len(string)
        aligned_string = string + " " * right_padding
        return aligned_string

# Show the order summary
def show_summary(details, mode):
    if mode == "Item":
        print_message(get_centered_string("Order Summary", 30))
        print_message(get_centered_string("Item Details", 30))
    elif mode == "Delivery":
        print_message(get_centered_string("Delivery Details", 30))
    elif mode == "Sum":
        print_message(get_centered_string("Total Price", 30))
    elif mode == "Customer":
        print_message(get_centered_string("Customer Details", 30))

    for detail in details:
        for attribute in detail:
            print(get_aligned_string(attribute, 20))

    

# User choose for inventory management
def product_setting_choice():
    print("-" * 30)
    print("1. View / Update Blooms")
    print("2. Add New Bloom")
    print("3. View / Update Add-ons")
    print("4. Add New Add-on")
    print("5. Back to Home Menu")

    choice = check_input_range(1, 5)

    if choice == 1:
        return "View / Update Blooms"
    elif choice == 2:
        return "Add New Bloom"
    elif choice == 3:
        return "View / Update Add-ons"
    elif choice == 4:
        return "Add New Add-on"
    elif choice == 5:
        return "Back to Home Menu"



# Sort blooms by price
def sort_by_price():
    with open("blooms.txt") as file:
        next(file)
        recorded_list = file.readlines()
        loop_count = len(recorded_list)
        sorted_list = []
        cheapest_bloom_line = ""
        cheapest_bloom_price = int(recorded_list[0].split(",")[-2])
        for count in range(0, loop_count):
            for line in recorded_list:
                current_bloom_price = int(line.split(",")[-2])
                if current_bloom_price <= cheapest_bloom_price:
                    cheapest_bloom_price = current_bloom_price
                    cheapest_bloom_line = line
            recorded_list.remove(cheapest_bloom_line)
            sorted_list.append(cheapest_bloom_line)
            if count != loop_count - 1:
                cheapest_bloom_price = int(recorded_list[0].split(",")[-2])
        return sorted_list

# View/Filter bloom/add-on
def view_items(file_path, mode, category = ""):
    with open(file_path, "r") as file:
        first_line = True
        recorded_category = ""
        recorded_status = ""
        sorted_list = []
        for line in file:
            attribute_list = line.strip().split(",")
            row_line = "-" * (30 * len(attribute_list))

            if mode == "Filter":
                recorded_category = line.split(",")[2].strip()

            elif mode == "Sort":
                sorted_list = sort_by_price()

            elif mode == "Available":
                recorded_status = line.split(",")[-1].strip()

            if first_line: # Print Header
                print(row_line)
                print_context("Header", attribute_list)
                first_line = False
            
            else: # Print Content
                if (mode == "Filter" or mode == "Available") and (recorded_category == category or recorded_status == "Available"):
                    print_context("Content", attribute_list)

                elif mode == "View":
                    print_context("Content", attribute_list)

                # elif mode == "Sort":
                #     print_context("Content", attribute_list)

        if mode == "Sort":
            for line in sorted_list:
                attribute_list = line.strip().split(",")
                print_context("Content", attribute_list)
        print(row_line)

# Get a valid bloom/add-on id
def get_valid_item_id(file_path, product, mode = ""):
    with open(file_path, "r") as file:
        while True:
            if mode == "Order": 
                input_item_id = input(f"Enter The {product} ID for Add-On (or 0 to skip): ")
                if input_item_id == "0":
                    return "Skip"
            else:
                input_item_id = input(f"Enter The {product} ID: ")
            for line in file:
                recorded_id = line.split(",")[0].strip()
                if input_item_id == recorded_id:
                    return input_item_id
            file.seek(0)
            print_message("Please Enter A Valid ID!")

# Update bloom/add-on
def update_item(file_path, input_item_id, for_update, position):
    with open(file_path, "r+") as file:
        lines = file.readlines()
        for index, line in enumerate(lines):
            if input_item_id == line.split(",")[0].strip():
                recorded = line.split(",")[position].strip()
                updated_line = line.replace(recorded, for_update)
                lines[index] = updated_line
        file.seek(0)
        for line in lines:
            file.write(line)
        file.truncate()
    print("Update Successfully!")

# View and update bloom/add-on
def view_and_update(file_path, product):
    while True:
        choice = menu_choice("View", "Update", "Back")

        if choice == "View":
            view_items(file_path, "View")

        elif choice == "Update":
            view_items(file_path, "View")
            input_item_id = get_valid_item_id(file_path, product)

            while True:
                choice = menu_choice("Price", "Status", "Back")

                if choice == "Price":
                    update_item(file_path, input_item_id, input("Enter New Price: "), -2)
                elif choice == "Status":
                    update_item(file_path, input_item_id, input("Enter New Status: "), -1)
                elif choice == "Back":
                    break

        elif choice == "Back":
            break

# User choose category
def category_choice(mode):
    print("-" * 30)
    print("1. Romantic")
    print("2. Birthday")
    print("3. Grand Opening")
    print("4. Condolence")
    print("5. Anniversary")

    if mode == "Sales":
        print("6. Go Back")
        choice = check_input_range(1, 6)
    elif mode == "Inventory":
        choice = check_input_range(1, 5)
    
    if choice == 1:
        return "Romantic"
    elif choice == 2:
        return "Birthday"
    elif choice == 3:
        return "Grand Opening"
    elif choice == 4:
        return "Condolence"
    elif choice == 5:
        return "Anniversary"
    elif choice == 6:
        return "Go Back"

# Get the valid price
def get_valid_price(product):
    while True:
        try:
            input_price = int(input(f"Enter The {product} Price: "))
            if input_price < 0:
                raise ValueError
        except:
            print("Invalid Input! Please Try Again!")
        else:
            return input_price

# Get the bloom id prefix
def get_bloom_id_prefix(bloom_category):

    if bloom_category == "Romantic":
        return "R"
    elif bloom_category == "Birthday":
        return "B"
    elif bloom_category == "Grand Opening":
        return "GO"
    elif bloom_category == "Condolence":
        return "C"
    elif bloom_category == "Anniversary":
        return "A"

# Get the largest bloom id
def get_largest_bloom_id(input_prefix):
    with open("blooms.txt", "r") as file:
        matched_bloom_id = []
        recorded_bloom_prefix = ""
        next(file)
        for line in file:
            recorded_bloom_id = line.split(",")[0]
            
            if len(input_prefix) == 1:
                recorded_bloom_prefix = line.split(",")[0].strip()[0]
            elif len(input_prefix) == 2:
                recorded_bloom_prefix = line.split(",")[0].strip()[:2]

            if input_prefix == recorded_bloom_prefix:
                matched_bloom_id.append(recorded_bloom_id)

        largest_bloom_id = max(matched_bloom_id)
        return largest_bloom_id

# Get the largest bloom id's numeric part
def get_numeric_part(item_id):
    get_numeric_part = ""
    if len(item_id) == 4: # Bloom ID
        get_numeric_part = item_id[1:]
    elif len(item_id) == 5: # Bloom ID
        get_numeric_part = item_id[2:]
    elif len(item_id) == 11: # Order ID
        get_numeric_part = item_id[7:]

    return get_numeric_part

def new_item_id(lastest_id, prefix, mode):
    new_item_id = ""
    numeric = int(get_numeric_part(lastest_id))
    new_numeric = numeric + 1

    if mode == "Bloom":
        new_item_id = prefix + "{:03d}".format(new_numeric)
    elif mode == "Order":
        new_item_id = prefix + "{:04d}".format(new_numeric)

    return new_item_id

# Auto generate a new bloom id
def generate_bloom_id(bloom_category):
    input_prefix = get_bloom_id_prefix(bloom_category)
    largest_bloom_id = get_largest_bloom_id(input_prefix)
    return new_item_id(largest_bloom_id, input_prefix, "Bloom")

# Auto generate a new add-on id
def generate_addon_id():
    with open("addons.txt", "r") as file:
        count = 0
        for line in file:
            count += 1
            print(count)
        new_id = "ADD" + "{:03d}".format(count)
        print(new_id)
        return new_id

def generate_order_id():
    prefix = "BBO-23-"
    recorded_order_id = ""
    new_order_id = ""
    with open("order.txt", "r") as file:
        next(file)
        for line in file:
            recorded_order_id = line.split(",")[0].strip()

        if recorded_order_id == "":
            new_order_id = prefix + "0001"
            return new_order_id
        else:
            return new_item_id(recorded_order_id, prefix, "Order")

# Create new line for new item
def new_item_line(product, id, name, price, category = ""):
    if product == "Bloom":
        new_bloom_line = f"{id},{name},{category},{price},Available\n"
        return new_bloom_line

    elif product == "Add-On":
        new_addon_line = f"{id},{name},{price},Available\n"
        return new_addon_line

# Write new line to file
def append_to_file(file_path, new_line):
    with open(file_path, "a") as file:
        file.write(new_line)
    sleep(1)
    print_message("Update Successfully!")

# Get the info and add new item to file
def add_new_item(file_path, product):
    item_name = input(f"Enter the {product} name: ")
    item_price = get_valid_price(product)

    if product == "Bloom":
        bloom_category = category_choice("Inventory")
        bloom_id = generate_bloom_id(bloom_category)
        new_bloom = new_item_line(product, bloom_id, item_name, item_price, bloom_category)
        append_to_file(file_path, new_bloom)

    elif product == "Add-On":
        addon_id = generate_addon_id()
        new_addon = new_item_line(product, addon_id, item_name, item_price)
        append_to_file(file_path, new_addon)

# Get the list of available bloom
def get_available_item(file_path, product):
    available_item_line = []
    while True:

        if product == "Bloom":
            input_item_id = get_valid_item_id("blooms.txt", "Bloom")
        elif product == "Add-On":
            input_item_id = get_valid_item_id("addons.txt", "Add-On", "Order")
            if input_item_id == "Skip":
                break

        with open(file_path, "r") as file:
            next(file)

            for line in file:
                recorded_item_id = line.split(",")[0].strip()
                status = line.split(",")[-1].strip()

                if input_item_id == recorded_item_id and status == "Available":
                    available_item_line = line.strip()
                    sleep(0.5)
                    
                    if product == "Bloom":
                        print_message("Order Successfully!")
                    elif product == "Add-On":
                        print_message("Item Added Successfully!")
                    return available_item_line
                
                elif input_item_id == recorded_item_id and status == "Unavailable":
                    file.seek(0)
                    sleep(0.5)
                    print_message(f"Sorry, The {product} is Currently Unavailable!")
                    break



# Main Program for Inventory Management
print_message("Beautiful Blooms Shop 🌺")

while True:

    choice = menu_choice("Inventory Management", "Sales Management", "Exit")

    if choice == "Inventory Management":
        
        while True:

            choice = product_setting_choice()

            if choice == "View / Update Blooms":
                view_and_update("blooms.txt", "Bloom")

            elif choice == "Add New Bloom":
                add_new_item("blooms.txt", "Bloom")

            elif choice == "View / Update Add-ons":
                view_and_update("addons.txt", "Add-On")

            elif choice == "Add New Add-on":
                add_new_item("addons.txt", "Add-On")

            elif choice == "Back to Home Menu":
                break
    
    elif choice == "Sales Management":
        
        while True:

            choice = menu_choice("Create Order", "View / Update Order", "Back to Home Menu")

            if choice == "Create Order":
                view_items("blooms.txt", "View")

                while True:
                    choice = menu_choice("Filter Bloom by Category", "Sort Bloom by Price", "Order Bloom", "Go Back")

                    if choice == "Filter Bloom by Category":

                        while True:
                            choice = category_choice("Sales")

                            if choice == "Romantic":
                                view_items("blooms.txt", "Filter", "Romantic")
                            elif choice == "Birthday":
                                view_items("blooms.txt", "Filter", "Birthday")
                            elif choice == "Grand Opening":
                                view_items("blooms.txt", "Filter", "Grand Opening")
                            elif choice == "Condolence":
                                view_items("blooms.txt", "Filter", "Condolence")
                            elif choice == "Anniversary":
                                view_items("blooms.txt", "Filter", "Anniversary")
                            elif choice == "Go Back":
                                break

                            choice = menu_choice("Order Bloom", "Back to Filter Category", "Back to Main Menu")

                            if choice == "Order Bloom":
                                None
                            elif choice == "Back to Filter Category":
                                continue
                            elif choice == "Back to Main Menu":
                                break

                    elif choice == "Sort Bloom by Price":
                        view_items("blooms.txt", "Sort")

                        choice = menu_choice("Order Bloom", "Back to Main Menu")

                        if choice == "Order Bloom":
                            None
                        elif choice == "Back to Main Menu":
                            continue

                    elif choice == "Order Bloom":
                        view_items("blooms.txt", "View")
                        available_bloom_line = get_available_item("blooms.txt", "Bloom")
                        view_items("addons.txt", "Available")
                        available_addon_line = get_available_item("addons.txt", "Add-On")
                        summary_list(available_bloom_line, available_addon_line)

                        while True:
                            item_details, delivery_details, sum_details, customer_details = summary_list()
                            order_summary = show_summary(item_details, "Item")
                            order_summary = show_summary(delivery_details, "Delivery")
                            order_summary = show_summary(sum_details, "Sum")
                            order_summary = show_summary(customer_details, "Customer")

                            choice = menu_choice("Confirm", "Edit Info", "Cancel")

                            if choice == "Confirm":
                                print_message("Not Done Yet!")
                            elif choice == "Edit Info":
                                continue
                            elif choice == "Cancel":
                                break
                        break


                    elif choice == "Go Back":
                        break

            elif choice == "View / Update Order":
                None

            elif choice == "Back to Home Menu":
                break
    
    elif choice == "Exit":
        print_message("Bye!")
        break