0% found this document useful (0 votes)
13 views96 pages

Nirdesh Subedi

Python Coursework Islington College

Uploaded by

NIRDESH SUBEDI
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
13 views96 pages

Nirdesh Subedi

Python Coursework Islington College

Uploaded by

NIRDESH SUBEDI
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 96

CS4051NI\CC4059NI Fundamental of Computing

60% Individual Coursework

2023-24 Summer

Student Name: Nirdesh Subedi

London Met ID: 23056546

College ID: NP01AI4S240012

Assignment Due Date: Sunday, August 18, 2024

Assignment Submission Date: Sunday, August 18, 2024

I confirm that I understand my coursework needs to be submitted online via MySecondTeacher under the
relevant module page before the deadline in order for my assignment to be accepted and marked. I am
fully aware that late submissions will be treated as non-submission and a marks of zero will be awarded.
Table of Content
1. Introduction ___________________________________________________________________ 1
1.1. Introduction to the project ___________________________________________________ 1
1.2. Tools used for completion of the project ___________________________________________ 2
1.2.1. IDLE _________________________________________________________________________________ 2
1.2.2. draw.io ______________________________________________________________________________ 2
1.2.3. Microsoft Word _______________________________________________________________________ 3

1.3. Aims and Objectives _____________________________________________________________ 4


2. Discussion and Analysis_______________________________________________________ 5
2.1. Algorithm ________________________________________________________________________ 5
2.2. Flowchart ________________________________________________________________________ 7
2.3. Pseudocode ____________________________________________________________________ 11
2.3.1. Pseudocode for main.py: ____________________________________________________________ 11
2.3.2. Pseudocode for operations.py _______________________________________________________ 14
2.3.3. Pseudocode for read.py _____________________________________________________________ 26
2.3.4. Pseudo for write.py__________________________________________________________________ 27

2.4. Data Structure __________________________________________________________________ 28


2.4.1. List _________________________________________________________________________________ 28
2.4.2. Dictionary ___________________________________________________________________________ 29
2.4.3. Tuples ______________________________________________________________________________ 30
2.4.5. Primitive Data Types ________________________________________________________________ 31

3. Program: ____________________________________________________________________ 33
4. Testing ______________________________________________________________________ 43
4.1. Test 1: To implement try and except _____________________________________________ 43
4.2. Test 2: To test input validation while purchasing and selling furniture ______________ 44
4.3. Test 3: To test file generation of invoice after purchasing multiple furniture(s). ______ 47
4.4. Test 4: To test file generation of invoice after selling multiple furniture(s). __________ 51
4.5. Test 5: To test change in the stock of the furniture after purchasing as well as selling
the furniture ____________________________________________________________________________ 55
5. Conclusion __________________________________________________________________ 62
Appendix ________________________________________________________________________ 64
Code of main.py ________________________________________________________________________ 64
Code of operations.py __________________________________________________________________ 67
Code of read.py ________________________________________________________________________ 88
Code of write.py ________________________________________________________________________ 90
Table of Figures
Figure 1: IDLE Logo ........................................................................................................... 2
Figure 2: draw.io Logo........................................................................................................ 3
Figure 3: Microsoft Logo..................................................................................................... 3
Figure 4: Codes of a function which returns a list ........................................................... 28
Figure 5: A list containing dictionary ................................................................................ 29
Figure 6: Showcasing use of dictionary in a function ...................................................... 29
Figure 7: Showcasing use of dictionary in the program .................................................. 30
Figure 8: Use of Boolean data type in the program ........................................................ 31
Figure 9: Use of integer data type in the program ........................................................... 31
Figure 10: Use of string in the code ................................................................................. 32
Figure 11: Use of floats in program.................................................................................. 32
Figure 12: Message after execution of program.............................................................. 33
Figure 13: Displaying inventory after user inputs "1" ...................................................... 34
Figure 14: Purchase Dashboard ...................................................................................... 34
Figure 15: Asking user input for product code and quantity............................................ 35
Figure 16: Termination of prompting user input after user inputs "n" ............................. 35
Figure 17: Displaying purchase invoice in Shell .............................................................. 36
Figure 18: Unique Text File generated for purchase invoice ......................................... 36
Figure 19: Purchase Invoice in text file ............................................................................ 37
Figure 20: Displaying main dashboard after purchase is complete ................................ 37
Figure 21: Displaying Sales Dashboard .......................................................................... 38
Figure 22: Asking user for product code and quantity for sales of furniture ................... 38
Figure 23: Termination of sales process after user inputs "n" ........................................ 39
Figure 24: Asking for customer details ............................................................................ 39
Figure 25: Displaying Sales Invoice in IDLE Shell .......................................................... 40
Figure 26: Generation of text file for invoice .................................................................... 40
Figure 27: Sales Invoice generated in a text file ............................................................. 41
Figure 28: Displaying main dashboard after completion of sales ................................... 41
Figure 29: Prompting inappropriate value for testing of try and except .......................... 43
Figure 30: Prompting a negative value in for testing input validation while purchasing . 45
Figure 31:Prompting a non-existing product code in for testing input validation while
purchasing ........................................................................................................................ 45
Figure 32: Prompting a negative value in for testing input validation while selling ........ 46
Figure 33:Prompting a non-existing product code in for testing input validation while
selling ................................................................................................................................ 46
Figure 36:Displaying of invoice in IDLE shell .................................................................. 49
Figure 37: Text File Generation after purchasing furniture(s) ......................................... 50
Figure 41: Entering other details in sales dashboard ...................................................... 53
Figure 42:Displaying of invoice in IDLE shell .................................................................. 53
Figure 43:Text File Generation after selling furniture(s).................................................. 54
Figure 44:Sales Invoice generated in a text file .............................................................. 54
Figure 45: Change in quantity in real-time after purchasing ........................................... 56
Figure 46:Change in quantity in real-time after purchasing ............................................ 57
Figure 47: Text File before purchasing furniture ............................................................. 58
Figure 48: Change in quantity of furniture(s) in text file after purchasing furniture ....... 58
Figure 49: Change in quantity in real-time after selling furniture(s) ................................ 59
Figure 50:Change in quantity in real-time after selling furniture(s) ................................. 60
Figure 51: Text File before selling furniture(s). ................................................................ 61
Figure 52: Change in quantity of furniture(s) in text file after selling furniture ............... 61

Table of Tables

Table 1: Implementation of try and except ...................................................................... 43


Table 2: Input validation while purchasing and selling furniture ..................................... 44
Table 3: File Generation of invoice after purchasing furniture(s). .................................. 47
Table 4:File Generation of invoice after selling furniture(s). .......................................... 51
Table 5: Test in change in the stock of the furniture after purchasing as well as selling
the furniture ....................................................................................................................... 55
CS4051NI/CS4059NI Fundamental of Computing

1. Introduction

1.1. Introduction to the project

With application of python, a popular and versatile programming language. Python's


simple syntax makes the code easy to read and maintain. It offers many useful libraries
that help with tasks like data handling and creating user interfaces. Python works on
different computer systems, allowing the furniture management software to run almost
anywhere. Its simplicity also means we can develop and update the system quickly.
These features make Python an excellent choice for creating efficient and user-friendly
software for furniture businesses.

This project develops a furniture management system for BRJ Furniture, which stores the
details of its furniture in a text file. The furniture management system displays the furniture
in BRJ’s inventory, asks user for input in the process of purchasing and selling the
furniture with a strict validation and most importantly, the system updates the stock of the
furniture real time in the text file. The system can create invoices for both purchase and
sales of furniture along with creation of the invoice in a unique text file for future
references. This project majorly focuses on modularity of the program which is achieved
by creating functions and calling them whenever needed. The project lays emphasis on
input validation with use of exception handling. The flow of program navigates per the
user choice. The program does not end until the user decides so.

Nirdesh Subedi 1
CS4051NI/CS4059NI Fundamental of Computing

1.2. Tools used for completion of the project

1.2.1. IDLE
IDLE is a simple coding tool that comes with Python. It's designed to help beginners learn
and write Python programs. When you install Python, you automatically get IDLE too.
IDLE's straightforward design makes it perfect for newcomers who want to focus on
learning Python basics without getting overwhelmed by complex features. It's a great
starting point for anyone taking their first steps into the world of programming with Python.
For the completion of this project, IDLE was used for writing and running python
programs. (python.org, n.d.)

Figure 1: IDLE Logo

1.2.2. draw.io
draw.io, also known as Diagrams.net, is a customized tool for creating diagrams and
charts. It offers existing automated layout options, or the user can design a custom
layout for their preferences. The tool provides a wide range of shapes and hundreds of
graphic components to let you create unique diagrams. In this project, draw.io was used
to make flowchart before writing the program. (Edirisinghe, 2023)

Nirdesh Subedi 2
CS4051NI/CS4059NI Fundamental of Computing

Figure 2: draw.io Logo

1.2.3. Microsoft Word


Microsoft Word is an element of Microsoft Office which helps with the creation, editing,
and formatting of documents. It is one of the most used word processing software in the
world. It has wide range of features which are almost suitable to almost every use-case.
It is commonly utilised by users, organisations, and schools because of its ease of use
and multiple useful features. In this project, Microsoft Word is used for documentation
purpose. (Roberts, 2023)

Figure 3: Microsoft Logo

Nirdesh Subedi 3
CS4051NI/CS4059NI Fundamental of Computing

1.3. Aims and Objectives


The aim of this project is to create a furniture management system for BRJ Furniture
using python.
The objectives of this project are listed below:
1) To develop a program that can read, write and update furniture inventory data
from a text file.
2) To design and implement an efficient data structure for storing and manipulating
furniture inventory data.
3) To display furniture inventory data to user and prompt user for input of product for
purchase and sales of furniture
4) To implement input validation to handle errors and unexpected user inputs.
5) To generate uniquely named transaction records (invoices/notes) for each sale or
purchase.
6) To develop the program in a modular way, using separate functions for different
operations.

Nirdesh Subedi 4
CS4051NI/CS4059NI Fundamental of Computing

2. Discussion and Analysis

2.1. Algorithm
Step 1: Start
Step 2: Display options to the user.
“1” for displaying the inventory
“2” for purchasing furniture
“3” for selling furniture
“4” to exit the program
Step 3: Input user choice to proceed further
Step 4: Validate user input , if user input is invalid, repeat Step 2 and Step 3
Step 5: If user input is 1, read the text file and display the furniture(s) with its detail
Step 6: Repeat Step 2 to Step 4
Step 7 If user input is 2, read the text file and display the furniture(s) with its detail
Step 8: Input product code
Step 9: Validate product code , if user input is invalid, repeat Step 6 and Step 7
Step 10: Input desired quantity for the chosen product
Step 11: Validate the quantity, if the user entered quantity is invalid, repeat Step 9
Step 12: Store the user entered product code and quantity as list into a new list
Step 13: Increase the quantity of the particular product in the text file
Step 14: Ask user to input “y” if they want to add more product or “n” if they don’t want
to add more product
Step 15: If user input is “y” , repeat Step 6 to Step 13
Step 16: If user input is “n”, ask for name of the user
Step 17: Display the invoice after performing calculations
Step 18: Create a text file with unique name and write the invoice in the text file
Step 19: Repeat Step 2 to Step 4
Step 20: If user input is 3, read the text file and display the furniture(s) with its detail
Step 21: Repeat Step 8 to 12

Nirdesh Subedi 5
CS4051NI/CS4059NI Fundamental of Computing

Step 22: Decrease the quantity of the particular product in the text file
Step 23: Repeat Step 14 to 15
Step 24: : If user input is “n”, ask for name of the user and phone number along with
shipping address based on province
Step 25: Repeat Step 17 to Step 19
Step 24: If user input is 4 , END the program

Nirdesh Subedi 6
CS4051NI/CS4059NI Fundamental of Computing

2.2. Flowchart

Nirdesh Subedi 7
CS4051NI/CS4059NI Fundamental of Computing

Nirdesh Subedi 8
CS4051NI/CS4059NI Fundamental of Computing

Nirdesh Subedi 9
CS4051NI/CS4059NI Fundamental of Computing

Nirdesh Subedi 10
CS4051NI/CS4059NI Fundamental of Computing

2.3. Pseudocode

2.3.1. Pseudocode for main.py:


START
IMPORT datetime function form the module datetime
IMPORT functions from the module operations
IMPORT functions from the module read
PRINT “-“ repeated 253 times
PRINT “ line with several tabs followed by BRJ Furniture” and “new line” followed
by line with several tabs followed by Naxal,Kathmandu-5“
PRINT “-“ repeated 253 times
CALL dashboard function and PRINT its result
WHILE True
DECLARE a variable items_in_inventory
CALL read_file function and ASSIGN its return value to the variable
items_in_inventory
DECLARE a variable product_code
CALL product_code function with items_in_inventory as argument and ASSIGN
its return value to the variable product_code
TRY
GET user input as integer and store in user_input
IF user_input==1
CALL display_inventory function with items_in_inventory
argument and PRINT its result
PRINT “ Returning to main dashboard ”
CALL dashboard function and PRINT its result
END IF
ELSE IF user_input==2
PRINT “-“ repeated 253 times
PRINT “ line with several tabs followed by Welcome to

Nirdesh Subedi 11
CS4051NI/CS4059NI Fundamental of Computing

Purchase Dashboard”
CALL prompt_purchase function with
products_code,items_in_inventory as argument and ASSIGN its
return value to the variable item_for_purchase
CALL remove_duplicates function with item_for_purchase as
argument and ASSIGN its return value to the variable
new_item_for_purchase
CALL purchase_invoice function with new_item_for_sale ,
items_in_inventory as argument and PRINT its result
PRINT “ line with several tabs followed by Returning to main
dashboard”
CALL dashboard function and PRINT its result
END IF
ELSE IF user_input==3
PRINT “-“ repeated 253 times
PRINT “ line with several tabs followed by Welcome to
Sales Dashboard”
CALL sales_prompt function with
products_code,items_in_inventory as argument and ASSIGN its
return value to the variable item_for_sale
CALL remove_duplicates function with item_for_sale as argument
and ASSIGN its return value to the variable new_item_for_sale
CALL shipping_cost function with ASSIGN its return value to the
variable ship_csot
CALL sales_invoice function with new_item_for_sale ,
items_in_inventory as argument and PRINT its result
PRINT “ line with several tabs followed by Returning to main
dashboard”
CALL dashboard function and PRINT its result
END IF
ELSE IF user_input==4
PRINT “-“ repeated 253 times

Nirdesh Subedi 12
CS4051NI/CS4059NI Fundamental of Computing

PRINT “ line with several tabs followed by Exiting the program”


PRINT “ line with several tabs followed by “-------------“”
PRINT “line with several tabs followed by Program Terminated”
PRINT “-“ repeated 253 times
BREAK from the while loop
END IF
ELSE
PRINT “-“ repeated 253 times
PRINT “ Please enter a Valid Number”
CALL dashboard function and PRINT its result
END IF
EXCEPT ValueError
PRINT “-“ repeated 253 times
PRINT “ Please enter numeric values only”
CALL dashboard function and PRINT its result
END TRY
END

Nirdesh Subedi 13
CS4051NI/CS4059NI Fundamental of Computing

2.3.2. Pseudocode for operations.py


START
IMPORT datetime function from datetime
IMPORT functions from the module read
IMPORT functions from the module write
FUNCTION dashboard()
PRINT “ line with several tabs followed by Welcome to BRJ Furniture Dashboard”
PRINT "-" repeated 253 times
PRINT "To use any services, Please Enter a Valid Number"
PRINT " Enter '1' to view the inventory" PRINT " Enter '2' to open the Purchase
dashboard"
PRINT " Enter '3' to open the Sales dashboard"
PRINT " Enter '4' to exit the Dashboard"
RETURN "-" repeated 254 times
END FUNCTION
FUNCTION display_inventory(items):
PRINT "-" repeated 253 times
PRINT “ line with several tabs followed by Welcome to BRJ Furniture Inventory”
PRINT "Product Code\t Manufacturer\t Product\t Cost Price\t Selling Price\t
Quantity in BRJ's Inventory"
PRINT "-" repeated 253 times
FOR i FROM 0 to LENGTH(items)-1
PRINT item["product_id"] "\t\t", item["manufacturer"], "\t\t",
item["product_name"], "\t\t", item["cost_price"], "\t\t", item["selling_price"],
"\t\t", item["quantity"]
END FOR
RETURN "-" repeated 253 times
END FUNCTION

Nirdesh Subedi 14
CS4051NI/CS4059NI Fundamental of Computing

FUNCTION prompt_purchase(codes, items):


DECLARE empty list purchase_item
DECLARE main_loop variable and ASSIGN it True boolean value
WHILE main_loop=True
IF purchase_item IS NOT empty:
PRINT "Products in cart currently: "
FOR i FROM 0 to LENGTH(items)-1
FOR product_id,quantity IN purchase_item:
IF int(items[i]["product_id"])==product_id:
print(items[i]["product_name"],"\t\t",
Quantity: ,quantity”
END FOR
PRINT "-" repeated 253 times
TRY
GET user input as integer and store in product_code
IF product_code IN codes:
DECLARE quantity_loop variable and ASSIGN it True
boolean value
WHILE quantity_loop==True
TRY
PRINT "-" repeated 253 times
PRINT product_code
GET user input as integer and store in
quantity
IF quantity>0
APPEND product_code and quantity as
list to the list purchase_item
CALL the function
purchase_update_product with items,
product_code and quantity as argument

Nirdesh Subedi 15
CS4051NI/CS4059NI Fundamental of Computing

SET quantity_loop to False


END IF
ELSE
PRINT "-" repeated 253 times
PRINT "Quantity must greater than 0."
END IF
EXCEPT ValueError:
PRINT "-" repeated 253 times
PRINT "Invalid Input!! Please
enter the quantity in numeric
value
END TRY
END WHILE
DECLARE yes_no_loop variable and ASSIGN it True
boolean value
WHILE yes_no_loop==True
PRINT "-" repeated 253 times
GET user input as string using lower() and strip() and
store in user_decision
IF user_decision IN [y,n]
Yes_no_loop=False
END IF
END WHILE
IF user_decision==”n”
SET main_loop to False
END IF
ELSE
CALL display_inventory functionwith items as
argument and print its result
END IF

Nirdesh Subedi 16
CS4051NI/CS4059NI Fundamental of Computing

ELSE
PRINT "-" repeated 253 times
PRINT "Invalid Product Code !! Enter a valid code!!"
PRINT "-" repeated 253 times
EXCEPT ValueError
PRINT "-" repeated 253 times
PRINT "Invalid Product Code !! Enter numeric value!!"
PRINT "-" repeated 253 times
END TRY
RETURN purchase_item
END FUNCTION
FUNCTION purchase_invoice(purchase_item, items):
DECLARE empty list purchase_invoices_list
PRINT "-" repeated 253 times
DECLARE name_loop variable and ASSIGN it True boolean value
WHILE name_loop == True
GET user input as string, strip it, and store in name
IF length of name == 0
PRINT "-" repeated 253 times
PRINT "The field can't be empty"
PRINT "Please enter your name."
PRINT "-" repeated 253 times
ELSE
SET name_loop to False
END WHILE
PRINT "-" repeated 253 times
GET current date and time components (year, month, day, hour, minute, second)
FORMAT current_date as "year-month-day"

Nirdesh Subedi 17
CS4051NI/CS4059NI Fundamental of Computing

FORMAT current_time as "hour : minute : second"


APPEND header information to purchase_invoices_list
(Store company name, address, "Purchase Invoice", date, time, customer name)
APPEND column headers to purchase_invoices_list
DECLARE total_price and INITIALIZE to 0
DECLARE sn and INITIALIZE to 1
FOR i FROM 0 To length of items - 1
FOR EACH product, quantity IN purchase_item
IF product == int(items[i]["product_id"])
EXTRACT product details from items[i]
CALCULATE total for this product
ADD total to total_price
APPEND formatted product details to purchase_invoices_list
INCREMENT sn
END IF
END FOR
END FOR

APPEND subtotal to purchase_invoices_list


CALCULATE VAT amount as 13% of total_price
APPEND VAT amount to purchase_invoices_list
APPEND grand total (total_price + VAT) to purchase_invoices_list
GENERATE unique filename using timestamp and customer name

OPEN file with generated filename in write mode


FOR EACH line IN purchase_invoices_list
WRITE line to file
END FOR

Nirdesh Subedi 18
CS4051NI/CS4059NI Fundamental of Computing

CLOSE file
RETURN "-" repeated 253 times
END FUNCTION
FUNCTION sales_prompt(codes, items):
DECLARE empty list sales_item
DECLARE main_loop variable and ASSIGN it True boolean value
WHILE main_loop=True
IF sales_item IS NOT empty:
PRINT "Products in cart currently: "
FOR i FROM 0 to LENGTH(items)-1
FOR product_id,quantity IN sales_item:
IF int(items[i]["product_id"])==product_id:
print(items[i]["product_name"],"\t\t",
Quantity: ,quantity”
END FOR
PRINT "-" repeated 253 times
TRY
GET user input as integer and store in product_code
IF product_code IN codes:
DECLARE quantity_loop variable and ASSIGN it True
boolean value
WHILE quantity_loop==True
TRY
PRINT "-" repeated 253 times
PRINT product_code
GET user input as integer and store in
quantity
IF quantity>0

Nirdesh Subedi 19
CS4051NI/CS4059NI Fundamental of Computing

APPEND product_code and quantity as


list to the list sales_item
CALL the function
sales_update_product with items,
product_code and quantity as argument
SET quantity_loop to False
END IF
ELSE
PRINT "-" repeated 253 times
PRINT "Quantity must greater than 0."
END IF
EXCEPT ValueError:
PRINT "-" repeated 253 times
PRINT "Invalid Input!! Please
enter the quantity in numeric
value
END TRY
END WHILE
DECLARE yes_no_loop variable and ASSIGN it True
boolean value
WHILE yes_no_loop==True
PRINT "-" repeated 253 times
GET user input as string using lower() and strip() and
store in user_decision
IF user_decision IN [y,n]
Yes_no_loop=False
END IF
END WHILE
IF user_decision==”n”
SET main_loop to False
END IF

Nirdesh Subedi 20
CS4051NI/CS4059NI Fundamental of Computing

ELSE
CALL display_inventory function with items as
argument and print its result
END IF
ELSE
PRINT "-" repeated 253 times
PRINT "Invalid Product Code !! Enter a valid code!!"
PRINT "-" repeated 253 times
EXCEPT ValueError
PRINT "-" repeated 253 times
PRINT "Invalid Product Code !! Enter numeric value!!"
PRINT "-" repeated 253 times
END TRY
RETURN purchase_item
END FUNCTION
FUNCTION prompt_purchase(codes, items):
DECLARE empty list purchase_item
DECLARE main_loop variable and ASSIGN it True boolean value
WHILE main_loop=True
IF purchase_item IS NOT empty:
PRINT "Products in cart currently: "
FOR i FROM 0 to LENGTH(items)-1
FOR product_id,quantity IN purchase_item:
IF int(items[i]["product_id"])==product_id:
print(items[i]["product_name"],"\t\t",
Quantity: ,quantity”
END FOR
PRINT "-" repeated 253 times
TRY

Nirdesh Subedi 21
CS4051NI/CS4059NI Fundamental of Computing

GET user input as integer and store in product_code


IF product_code IN codes:
DECLARE quantity_loop variable and ASSIGN it True
boolean value
WHILE quantity_loop==True
TRY
PRINT "-" repeated 253 times
PRINT product_code
GET user input as integer and store in
quantity
IF quantity>0
APPEND product_code and quantity as
list to the list purchase_item
CALL the function
purchase_update_product with items,
product_code and quantity as argument
SET quantity_loop to False
END IF
ELSE
PRINT "-" repeated 253 times
PRINT "Quantity must greater than 0."
END IF
EXCEPT ValueError:
PRINT "-" repeated 253 times
PRINT "Invalid Input!! Please
enter the quantity in numeric
value
END TRY
END WHILE
DECLARE yes_no_loop variable and ASSIGN it True
boolean value

Nirdesh Subedi 22
CS4051NI/CS4059NI Fundamental of Computing

WHILE yes_no_loop==True
PRINT "-" repeated 253 times
GET user input as string using lower() and strip() and
store in user_decision
IF user_decision IN [y,n]
Yes_no_loop=False
END IF
END WHILE
IF user_decision==”n”
SET main_loop to False
END IF
ELSE
CALL display_inventory functionwith items as
argument and print its result
END IF
ELSE
PRINT "-" repeated 253 times
PRINT "Invalid Product Code !! Enter a valid code!!"
PRINT "-" repeated 253 times
EXCEPT ValueError
PRINT "-" repeated 253 times
PRINT "Invalid Product Code !! Enter numeric value!!"
PRINT "-" repeated 253 times
END TRY
RETURN purchase_item
END FUNCTION

Nirdesh Subedi 23
CS4051NI/CS4059NI Fundamental of Computing

FUNCTION sales_invoice(sales_item, items):


DECLARE empty list sales_invoices_list
PRINT "-" repeated 253 times
DECLARE name_loop variable and ASSIGN it True boolean value
WHILE name_loop == True
GET user input as string, strip it, and store in name
IF length of name == 0
PRINT "-" repeated 253 times
PRINT "The field can't be empty"
PRINT "Please enter your name."
PRINT "-" repeated 253 times
ELSE
SET name_loop to False
END WHILE
PRINT "-" repeated 253 times
GET current date and time components (year, month, day, hour, minute, second)
FORMAT current_date as "year-month-day"
FORMAT current_time as "hour : minute : second"
APPEND header information to sales_invoices_list
(Store company name, address, "Sales Invoice", date, time, customer name)
APPEND column headers to sales_invoices_list
DECLARE total_price and INITIALIZE to 0
DECLARE sn and INITIALIZE to 1
FOR i FROM 0 To length of items - 1
FOR EACH product, quantity IN sales_item
IF product == int(items[i]["product_id"])
EXTRACT product details from items[i]
CALCULATE total for this product

Nirdesh Subedi 24
CS4051NI/CS4059NI Fundamental of Computing

ADD total to total_price


APPEND formatted product details to sales_invoices_list
INCREMENT sn
END IF
END FOR
END FOR

APPEND subtotal to sales_invoices_list


CALCULATE VAT amount as 13% of total_price
APPEND VAT amount to sales_invoices_list
APPEND grand total (total_price + VAT+shipping_cost) to sales_invoices_list
GENERATE unique filename using timestamp and customer name

OPEN file with generated filename in write mode


FOR EACH line IN sales_invoices_list
WRITE line to file
END FOR
CLOSE file
RETURN "-" repeated 253 times
END FUNCTION
FUNCTION print_append(line, target_list):
PRINT line
APPEND line + newline character to target_list
RETURN None
END FUNCTION

Nirdesh Subedi 25
CS4051NI/CS4059NI Fundamental of Computing

2.3.3. Pseudocode for read.py


FUNCTION read_file()
TRY
OPEN "inventory.txt" in read mode as file
DECLARE empty list inventory_list
FOR EACH line in file
REMOVE trailing whitespace from line and SPLIT by commas
CREATE dictionary item_detail with keys:
"product_id", "manufacturer", "product_name", "quantity",
"cost_price", "selling_price"
ASSIGN corresponding values from split line to item_detail
APPEND item_detail to inventory_list
END FOR
RETURN inventory_list
EXCEPT FileNotFoundError
PRINT "The text file couldn't be found!!!!"
PRINT "Please check for the text file"
END TRY
END FUNCTION
FUNCTION product_codes(items)
DECLARE empty list productcode_list
FOR i FROM 0 TO length of items - 1
SET code to integer value of items[i]["product_id"]
APPEND code to productcode_list
END FOR
RETURN productcode_list
END FUNCTION

Nirdesh Subedi 26
CS4051NI/CS4059NI Fundamental of Computing

2.3.4. Pseudo for write.py


FUNCTION write_file(_list)
OPEN "inventory.txt" in write mode as file
FOR EACH item in _list
WRITE item + newline character to file
END FOR
END FUNCTION

FUNCTION dict_to_list(items)
DECLARE** empty list dict_list
FOR i FROM 0 TO length of items - 1
SET row to list of values from items[i]
SET new_row to join row elements with comma separator
APPEND new_row to dict_list
END FOR
RETURN dict_list
END FUNCTION

Nirdesh Subedi 27
CS4051NI/CS4059NI Fundamental of Computing

2.4. Data Structure


A data structure is a specialized format for organizing, processing, retrieving and storing
data. There are several basic and advanced types of data structures, all designed to
arrange data to suit a specific purpose. Data structures make it easy for users to access
and work with the data they need. Most importantly, data structures frame the
organization of information so that machines and humans can better understand it. (Scott
Robinson, 2024)

Some data structures used in this project are explained below:

2.4.1. List
A list is ordered and mutable data structure .A list a value that contains multiple value
in ordered sequence. A list can have store multiple data type inside it. A list can store a
list inside it, which are called 2D list. In the program , we store each line of the text file in
dictionary and the dictionary are stored inside list. Furthermore, user entered product
quantity are also stored in list.

The readlines() method read each line from text file and stores each line as string in list.
Now, each index in the list is a list containing a string , the string further split by comma
and split() functions returns a list. Now, each index of the returned list is value for
dictionary. Now, the dictionary is also stored inside a list.

Figure 4: Codes of a function which returns a list

Nirdesh Subedi 28
CS4051NI/CS4059NI Fundamental of Computing

The following figure shows a list which contains dictionary.

Figure 5: A list containing dictionary

2.4.2. Dictionary
A dictionary is a mutable collection of values which are unordered and exist in a key-value
pairs. The curly brackets “{}” are used to initialize a dictionary. We can access dictionary
items by referring to its key name. The use of key-value make dictionary very easy to use.
It eliminates the tautness of remembering the index of a certain value.

The readlines() method read each line from text file and stores each line as string in list.
Now, each index in the list is a list containing a string , the string further split by comma
and split() functions returns a list. Now, each index of the returned list is value for
dictionary , while key are attributes of product such as name , quantity etc. The dictionary
is further stored in list.

Figure 6: Showcasing use of dictionary in a function

Nirdesh Subedi 29
CS4051NI/CS4059NI Fundamental of Computing

Figure 7: Showcasing use of dictionary in the program

Other data structure which are not used in program are:

2.4.3. Tuples
A tuple is a special type of data in Python that lets you create a list of values that can’t be
changed once they're set. You can put different types of values into a tuple, like numbers,
text, or lists. Tuples are useful when you want to keep a group of values together without
changing them, like keeping a record of information. (Ramos, 2023)

Example: (1,2),(“a”,1,”b”) are some examples of tuples.

2.4.4. Set

Set is a data type in python used to store several items in a single variable. It is one of
the four built-in data types. A set is mutable, i.e., we can remove or add elements to it.
Set in python is like mathematical sets, and operations like intersection, union, symmetric
difference, and more can be applied. All set items need to be unique because duplicates
are not allowed. Items in a set can be of any data type. (S, 2024)

Example: set1 = {"ab", "bc", "cd"}

set2 = {11, 15, 17, 19, 13}

Nirdesh Subedi 30
CS4051NI/CS4059NI Fundamental of Computing

2.4.5. Primitive Data Types


Booleans(bool):The Boolean data type is either True or False. In Python, Boolean
variables are defined by the True and False keywords. In the program, Boolean is used
in while loops and to specify whether product is available or not. The figure below shows
use of Boolean in the program.

Figure 8: Use of Boolean data type in the program

Integers(int): In Python, integers are zero, positive or negative whole numbers without a
fractional part. Integers are useful for mathematical calculations. In the program, integer
data type has been used thoroughly. Examples of integers data type are 1, 0, -1 etc.

Figure 9: Use of integer data type in the program

Nirdesh Subedi 31
CS4051NI/CS4059NI Fundamental of Computing

Strings(str): A string is a sequence of characters enclosed within single quotes (‘ ‘) or


double quotes (" "). It is an immutable data type, which means once a string is created,
it cannot be modified. String can be manipulated by using different string manipulation
functions provide by python. In the project, string has been used immensely. (prepbyes,
2023)

Figure 10: Use of string in the code

Floating Point Numbers(float):The float type in Python represents the floating-point


number. Float is used to represent real numbers and is written with a decimal point. For
example, 97.98,-1.9 are floating point numbers. In the project, float has been used
while calculating VAT inclusive price.

Figure 11: Use of floats in program

Nirdesh Subedi 32
CS4051NI/CS4059NI Fundamental of Computing

3. Program:
The program is a furniture management system. The details of furniture(s) in BRJ
Furniture are maintained in text file. The program reads the text file , displays the
inventory, prompts user for product code and quantity with input validation and displays
as well generates a text file for the invoices in both purchase and sales of furniture.

The modularity of the program is maintained by breaking the codes into function. The
program has four functions: read(for reading the text file), write(for writing in the text
file),operations(for purchasing and selling of the furniture) and main(where all other
function are called).

At the execution of the program, a message for navigating around program is displayed.
The user is provided with four options: “1” for displaying the inventory , “2” for Purchase
dashboard ,”3” for Sales Dashboard and “4” for exiting the program. The user is asked
for entering a numeric value based on the option shown above. The user input is
validated. If the user input is not valid, the user is prompted for input again. The program
has implementation of exception handling of Value Error throughout the program

Figure 12: Message after execution of program

Nirdesh Subedi 33
CS4051NI/CS4059NI Fundamental of Computing

If the user input is “1”, the program displays the furniture(s) with detail after reading the
text file.

Figure 13: Displaying inventory after user inputs "1"

The program again returns to the main dashboard shown in Figure 5. And, if the user
inputs “2” , purchase dashboard is displayed, where user is asked for product code and
quantity for purchasing furniture. Similarly , the user input for both product code and
quantity is validated, If user input is invalid, the user is asked for valid asked for product
code and quantity.

Figure 14: Purchase Dashboard

Nirdesh Subedi 34
CS4051NI/CS4059NI Fundamental of Computing

The user can add products until the user inputs “n”.

Figure 15: Asking user input for product code and quantity

The user is also shown a cart which shows previously prompted furniture.

Figure 16: Termination of prompting user input after user inputs "n"

Nirdesh Subedi 35
CS4051NI/CS4059NI Fundamental of Computing

After user inputs “n”, the program drives towards creating purchase, which is also created
in a unique text file.

Figure 17: Displaying purchase invoice in Shell

The invoice is also generated in a unique text file . This indicates the ending of the process
for purchasing furniture.

Figure 18: Unique Text File generated for purchase invoice

Nirdesh Subedi 36
CS4051NI/CS4059NI Fundamental of Computing

Figure 19: Purchase Invoice in text file

After invoice is generated, the main dashboard is displayed again. The program doesn’t
terminate until the user decides so.

Figure 20: Displaying main dashboard after purchase is complete

Nirdesh Subedi 37
CS4051NI/CS4059NI Fundamental of Computing

The program again returns to the main dashboard shown in figure above. And, if the user
inputs “3” , sales dashboard is displayed, where user is asked for product code and
quantity for selling furniture. Similarly , the user input for both product code and quantity
is validated, If user input is invalid, the user is asked for valid asked for product code and
quantity.

Figure 21: Displaying Sales Dashboard

The user is asked to enter product code and quantity. Multiple products can be sold at
once. The option to add more products is displayed. The program continues to prompt
for product code and quantity until user input is “n”.

Figure 22: Asking user for product code and quantity for sales of furniture

Nirdesh Subedi 38
CS4051NI/CS4059NI Fundamental of Computing

The prompting for sales terminates after user inputs “n”. Then, the program proceed
towards displaying sales invoice.

Figure 23: Termination of sales process after user inputs "n"

Details of customer such as name and phone along with shipping address is asked.

Figure 24: Asking for customer details

Nirdesh Subedi 39
CS4051NI/CS4059NI Fundamental of Computing

Similarly, like purchase, invoice for sales is also generated, which is displayed is Shell
as well as a unique text file is created for invoice.

Figure 25: Displaying Sales Invoice in IDLE Shell

For every sale, a unique text file for invoice is created, which can be useful for future
reference.

Figure 26: Generation of text file for invoice

Nirdesh Subedi 40
CS4051NI/CS4059NI Fundamental of Computing

Figure 27: Sales Invoice generated in a text file

After invoice is generated, the main dashboard is displayed again. The program doesn’t
terminate until the user decides so.

Figure 28: Displaying main dashboard after completion of sales

Nirdesh Subedi 41
CS4051NI/CS4059NI Fundamental of Computing

If user input is “4”, the program terminates.

Nirdesh Subedi 42
CS4051NI/CS4059NI Fundamental of Computing

4. Testing

4.1. Test 1: To implement try and except


To implement try and except
Objective

- Program is executed
Action - A string value is entered instead of an
integer value
Error message indicating to input numeric
Expected Result value only would be displayed.

Error message indicating to input numeric


Actual Result value only was displayed.

The test is successful.


Conclusion
Table 1: Implementation of try and except

Figure 29: Prompting inappropriate value for testing of try and except

Nirdesh Subedi 43
CS4051NI/CS4059NI Fundamental of Computing

4.2. Test 2: To test input validation while purchasing and selling furniture
To test input validation while purchasing and
Objective selling furniture
- Program is executed
Action - 2 is pressed for Purchase Dashboard
- Negative value is entered in product code field.
- Non-existing product code is entered in product
code field.
- 3 is pressed for Sales Dashboard
- Negative value is entered in product code field.
- Non-existing product code is entered in product
code field.

Error message indicating to input valid product id


Expected Result would be displayed.
Error message indicating to input valid product id
Actual Result only was displayed.
The test is successful.
Conclusion
Table 2: Input validation while purchasing and selling furniture

Nirdesh Subedi 44
CS4051NI/CS4059NI Fundamental of Computing

Figure 30: Prompting a negative value in for testing input validation while purchasing

Figure 31:Prompting a non-existing product code in for testing input validation while purchasing

Nirdesh Subedi 45
CS4051NI/CS4059NI Fundamental of Computing

Figure 32: Prompting a negative value in for testing input validation while selling

Figure 33:Prompting a non-existing product code in for testing input validation while selling

Nirdesh Subedi 46
CS4051NI/CS4059NI Fundamental of Computing

4.3. Test 3: To test file generation of invoice after purchasing multiple


furniture(s).
To test file generation after purchasing multiple
Objective furniture(s).
- Program is executed
Action - 2 is pressed for Purchase Dashboard
- Product Code as well quantity is entered for
purchasing multiple furniture(s)
- Other details are also entered.

A text file containing invoice would be generated


Expected Result as well as displayed in IDLE shell.

A text file containing invoice was generated as


Actual Result well as displayed in IDLE shell.

The test is successful.


Conclusion
Table 3: File Generation of invoice after purchasing furniture(s).

Nirdesh Subedi 47
CS4051NI/CS4059NI Fundamental of Computing

Figure 34:Entering product code and quantity for purchasing furniture

Nirdesh Subedi 48
CS4051NI/CS4059NI Fundamental of Computing

Figure 35: Entering product code and quantity for purchasing multiple furniture(s).

Figure 36:Displaying of invoice in IDLE shell

Nirdesh Subedi 49
CS4051NI/CS4059NI Fundamental of Computing

Figure 37: Text File Generation after purchasing furniture(s)

. Figure 38: Purchase Invoice generated in a text file

Nirdesh Subedi 50
CS4051NI/CS4059NI Fundamental of Computing

4.4. Test 4: To test file generation of invoice after selling multiple


furniture(s).
To test file generation after selling multiple
Objective furniture(s).
- Program is executed
Action - 3 is entered for Sales Dashboard
- Product Code as well quantity is entered for
selling multiple furniture(s)
- Other details including name, details and
shipping address are also entered.
A text file containing invoice would be generated
Expected Result as well as displayed in IDLE shell.
A text file containing invoice was generated as
Actual Result well as displayed in IDLE shell.
Conclusion The test is successful.

Table 4:File Generation of invoice after selling furniture(s).

Figure 39: Entering product code and quantity for selling furniture

Nirdesh Subedi 51
CS4051NI/CS4059NI Fundamental of Computing

Figure 40: Entering product code and quantity for selling multiple furniture(s)

Nirdesh Subedi 52
CS4051NI/CS4059NI Fundamental of Computing

Figure 41: Entering other details in sales dashboard

Figure 42:Displaying of invoice in IDLE shell

Nirdesh Subedi 53
CS4051NI/CS4059NI Fundamental of Computing

Figure 43:Text File Generation after selling furniture(s)

Figure 44:Sales Invoice generated in a text file

Nirdesh Subedi 54
CS4051NI/CS4059NI Fundamental of Computing

4.5. Test 5: To test change in the stock of the furniture after purchasing as
well as selling the furniture
To test change in the stock of the furniture after
Objective purchasing as well as selling the furniture

- Program is executed
Action - 2 is pressed for Purchase Dashboard
- Product Code as well quantity is entered for
purchasing multiple furniture(s)
- Other details are also entered.
- 3 is entered for Sales Dashboard
- Product Code as well quantity is entered for
selling multiple furniture(s)
- Other details including name, details and
shipping address are also entered.

The change in the quantity of the furniture after


Expected Result purchasing and selling the furniture would be
reflected in the text file.
The change in the quantity of the furniture after
Actual Result purchasing and selling the furniture was reflected
in the text file.
The test is successful.
Conclusion
Table 5: Test in change in the stock of the furniture after purchasing as well as selling the furniture

Nirdesh Subedi 55
CS4051NI/CS4059NI Fundamental of Computing

Figure 45: Change in quantity in real-time after purchasing

Nirdesh Subedi 56
CS4051NI/CS4059NI Fundamental of Computing

Figure 46:Change in quantity in real-time after purchasing

Nirdesh Subedi 57
CS4051NI/CS4059NI Fundamental of Computing

Figure 47: Text File before purchasing furniture

Figure 48: Change in quantity of furniture(s) in text file after purchasing furniture

Nirdesh Subedi 58
CS4051NI/CS4059NI Fundamental of Computing

Figure 49: Change in quantity in real-time after selling furniture(s)

Nirdesh Subedi 59
CS4051NI/CS4059NI Fundamental of Computing

Figure 50:Change in quantity in real-time after selling furniture(s)

Nirdesh Subedi 60
CS4051NI/CS4059NI Fundamental of Computing

Figure 51: Text File before selling furniture(s).

Figure 52: Change in quantity of furniture(s) in text file after selling furniture

Nirdesh Subedi 61
CS4051NI/CS4059NI Fundamental of Computing

5. Conclusion
The goal of the project was to build a Furniture Management System using Python. In this
project, I have successfully created a Furniture Management System in Python , based
on the provided guideline. The program can read file, display the furniture with its details
, prompt user for code and quantity of the furniture along with its validation , change the
quantity of the products in real-time after purchasing as well as buying and generation of
an invoice in a text file , which meets the provided requirement. The program uses various
data structure to store and manipulate data. The details of each furniture have been
stored in a key-value pair using dictionary, which was further stored in a list. The program
uses dictionary to eliminate tautness of remembering index of attributes. The user entered
product code and quantity and further stored in a new list, which was very useful in making
the invoices. In a nutshell , the use of 2D list and list of dictionaries as data structure in
the program provided effective way to store, access and manipulate data through for and
while loops.

The program implements a strict input validation for validating user input. The program
requires user to enter numeric values to navigate through every step-in program. The
program has implemented exception handling for exceptions like ValueError and
FileNotFoundError which avoids the termination of program and creates a smooth use
experience. The program does not end until the user decides. This factor makes the
program really user friendly. The program can update the stock of the furniture in real-
time which minimizes any calculation or logical flaws.

Throughout the development phase of the program , I have encountered several mistake
and bugs, which indeed enhanced more python and debugging skills. One of the biggest
issues I faced was improper indentation in IDLE. The program also has many nested
while and for loops. due to which I encountered many logical errors. I encountered
problems while formatting the invoice. In a hindsight, these mistakes demanded more
research and practice of Python.

The project deepened my understanding of data structures like list and dictionary more.
The constant use of nested for loops and while loops , sharpened my understanding of
how looping works in a large program. The program enhanced my ability to work to files.

Nirdesh Subedi 62
CS4051NI/CS4059NI Fundamental of Computing

The use of functions helped to achieve modularity in the program. The use of functions
helped me further to understand the scope of various variables. The program can further
be enhanced for future use of classes and OOP. The File I/O can be made further easy
by importing modules like csv and os.

In conclusion , the furniture management system developed in this program demonstrates


a user-friendly system ,developed with less complexity and user-defined functions. The
project has been a great learning opportunity to enhance python skills and general
programming consciousness.

Nirdesh Subedi 63
CS4051NI/CS4059NI Fundamental of Computing

Appendix

Code of main.py
from datetime import datetime
from operations import
prompt_purchase,purchase_invoice,sales_prompt,sales_invoice,shipping_cost,dashboa
rd,display_inventory,remove_duplicates
from read import read_file,product_codes
print("-"*253)
print("\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tBRJ Furniture\n","\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t
Naxal-5, Kathmandu")
print("-"*253)
# calling the dashboard which prints main menu
print(dashboard())
#taking user input from user about the services they want to access
# Using while True loop to continue until user decides to exit
while True:
# calling the read_file function which returns list of dict and assigning to a variable
items_in_inventory=read_file()
# calling the product_code function which returns list and assigning to a variable
products_code=product_codes(items_in_inventory)
# handling possible exception for ValueError
try:
user_input=int(input("Enter a number to continue: "))
if(user_input==1):
# calling the functions from operations to display item in text file
print(display_inventory(items_in_inventory))
print("-->"*27, "Returning to the main dashboard","<--"*27)
# calling the dashboard which prints main menu
print(dashboard())

Nirdesh Subedi 64
CS4051NI/CS4059NI Fundamental of Computing

elif(user_input==2 ):
print("-"*253)
print("\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tWelcome to Purchase Dashboard")
# calling the functions from operations to display item in text file
print(display_inventory(items_in_inventory))
# calling prompt_purchase to take user input for product code and quantity and
return value is stored in a variable item_for _purchase
item_for_purchase=prompt_purchase(products_code,items_in_inventory)
# calling the function which removes repeated product code
new_item_for_purchase=remove_duplicates(item_for_purchase)
#calling the method purchase invoice to generate purchase invoice
print(purchase_invoice(new_item_for_purchase,items_in_inventory))
print("-->"*27, "Returning to the main dashboard","<--"*27)
# calling the dashboard which prints main menu
print(dashboard())

elif(user_input==3):
print("-"*253)
print("\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tWelcome to Sales Dashboard")
# calling the functions from operations to display item in text file
print(display_inventory(items_in_inventory))
# calling sales_prompt to take user input for product code and quantity and
return value is stored in a variable item_for _purchase
item_for_sale=sales_prompt(products_code,items_in_inventory)
# calling the function which removes repeated product code
new_item_for_sale=remove_duplicates(item_for_sale)
# calling shipping_cost to determine shipping cost based on user address
ship_cost=shipping_cost()

Nirdesh Subedi 65
CS4051NI/CS4059NI Fundamental of Computing

#calling the method sales_invoice to generate sales invoice


print(sales_invoice(new_item_for_sale,items_in_inventory,ship_cost))
print("-->"*27, "Returning to the main dashboard","<--"*27)
print(dashboard())

elif(user_input==4):
# displaying messsage before exiting the program
print("-"*254)
print("\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tExiting the program")
print("\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t----------------------------")
print("\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tProgram Terminated")
print("-"*254)
# breaking from while loop to end program
break

else:
print("-"*254)
print("Please!! Enter a Valid Number")
print("-"*254)
print(dashboard())

except ValueError:
print("-"*254)
print("Plese enter numeric value only!!!!!")
print("-"*254)
print(dashboard())

Nirdesh Subedi 66
CS4051NI/CS4059NI Fundamental of Computing

Code of operations.py
from datetime import datetime
from read import read_file,product_codes
from write import dict_to_list,write_file
def dashboard():
"""This function prints the current date and time, provides options for the user to
navigate to different sections of the dashboard.
Args:
None
Returns:
str: a set of concatenated characters
"""
# displaying necessary instruction for miain menu
print("\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tWelcome to BRJ Furniture Dashboard")
print("-"*254)
print("To use any services, Please Enter a Valid Number")
print(" Enter ' 1 ' to view the inventory")
print(" Enter ' 2 ' to open the Purchase dashboard")
print("Enter ' 3' to open the Sales dashboard")
print("Enter ' 4' to exit the Dashboard")
return ("-"*254)

def display_inventory(items):
"""This function displays all the products in the text file with their attributes
Args:
items (list of dict): A list of dictionaries where each dictionary contains information
about a product in the text file
Returns:
a set of concatenated characters

Nirdesh Subedi 67
CS4051NI/CS4059NI Fundamental of Computing

"""
print("-"*253)
print("\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tBRJ Furniture's Inventory")
print("-"*253)
print(" Product Code\t ","Manufacturer\t\t ","Product\t\t","Cost Price\t","Selling
Price\t","Quantity in BRJ's Inventory")
print("-"*253)
#displaying product catalogue for purchasing
for i in range(len(items)):

print(items[i]["product_id"],"\t\t",items[i]["manufacturer"],"\t\t",items[i]["product_name"],"\t\
t",items[i]["cost_price"],"\t\t",items[i]["selling_price"],"\t\t",items[i]["quantity"])
return "-"*253

def prompt_purchase(codes,items):
"""This function asks for product along with respective quantity along with its
validation and stores the user-prompted value into a 2D-list.
Args:
codes(list):A list which contains all the product id of the items present in text file
Returns:
a 2-D list containing user-prompted products along with thier respective quantities.
"""
# a list which stores the product code and quantity as list intended for purchase
purchase_item=[]
# using while True so that the we continue to ask user for input unless they prompt
no
main_loop=True
while main_loop==True:
if len(purchase_item)!=0:
print("Products in cart currently: ")

Nirdesh Subedi 68
CS4051NI/CS4059NI Fundamental of Computing

for i in range(len(items)):
for product_id,quantity in purchase_item:
if int(items[i]["product_id"])==product_id:
print(items[i]["product_name"],"\t\t","Quantity:",quantity)
print("-"*253)
try:
product_code=int(input("Enter the product code of the product you want to
purchase: "))
# checking if the user prompted product code is valid or invalid
if product_code in codes:
#quantity of the product is asked if and only if the product code is valid
using while true
quantity_loop=True
while quantity_loop==True:
try:
print("-"*253)
print("Product Id: ",product_code)
quantity=int(input("Enter the quantity of the product: "))
if quantity>0:
# appending the product code and quantity as list in the list item
which thus creates a 2-d list only if postive and valid quantity is entered
purchase_item.append([product_code,quantity])
purchase_update_product(items,product_code,quantity)
quantity_loop=False # exiting from quantity loop by setting
qunatity_loop to false
else:
print("-"*253)
print("Quantity must greater than 0.")
except ValueError:
print("-"*253)

Nirdesh Subedi 69
CS4051NI/CS4059NI Fundamental of Computing

print("Invalid Input!! Please enter the quantity in numeric value")


# Inner loop to get valid user input for adding more products
yes_no_loop=True
while yes_no_loop==True:
print("-"*253)
user_decision = input("Do you want to continue more? (y/n):
").lower().strip()
print("-"*253)
# checking if the input is 'y' or 'n'
if user_decision in ['y', 'n']:
#if input valid , exiting from the loop
yes_no_loop=False
else:
print("Invalid input. Please enter 'y' or 'n'.")
if user_decision == "n":
# for user input "n", product in cart is displayed
print("Products in the cart: ")
for i in range(len(items)):
for product_id,quantity in purchase_item:
if int(items[i]["product_id"])==product_id:
print(items[i]["product_name"],"\t\t","Quantity:",quantity)
print("-"*253)
print( "->->->->->->->->->->->->->->->->->->->->->->->->->->->->->->->-
>->-> Your order is placed. Generating Purchase Invoice <-<-<-<-<-<-<-<-<-<-<-<-<-<-
<-<-<-<-<-<-<-<-<-<-<-<-<-<-")
main_loop=False # exiting from the main while loop by setting main_loop
to False
else:
display_inventory(items)
else:

Nirdesh Subedi 70
CS4051NI/CS4059NI Fundamental of Computing

print("-"*253)
print("Invalid Product Code !! Enter a valid code!!")
print("-"*253)

except ValueError:
print("-"*253)
print("Invalid Code!!!! Enter the product code in numeric value again!!!")
print(display_inventory(items))

return purchase_item

def purchase_invoice(purchase_item,items):
"""
This function creates and displays purchase invoice as well as writes the invoice in a
unique text file
Args:
purchase_items(list): A list which contains list having the user-prompted product id
and quantity for purchase
items (list of dict): A list of dictionaries where each dictionary contains information
about a product in the text file
Returns:
str: a set of concatenated characters"""
purchase_invoices_list=[]
print("-"*253)
name_loop=True
# validating name using while True loop
while name_loop==True:
name=input("Enter the name of the customer: ").strip()
if len(name)==0:

Nirdesh Subedi 71
CS4051NI/CS4059NI Fundamental of Computing

print("-"*253)
print(" The field cant be empty")
print("Please enter your name.")
print("-"*253)
else:
name_loop=False # breaking from while loop by setting name_loop to False
print("-"*253)
# Geting the current date and time
year=str( datetime.now().year)
month=str( datetime.now().month)
day=str( datetime.now().day)
hour=str( datetime.now().hour)
minute=str( datetime.now().minute)
second=str( datetime.now().second)
# Extracting and formatting the date part
current_date = year+"-"+month+"-"+day
# Extracting and formatting the time part
current_time = hour+" : "+minute+" : "+second
# using print_append function to print in Shell and append in a list simulataenously
print_append("\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tBRJ
Furniture\n"+"\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t Naxal-5,
Kathmandu",purchase_invoices_list)
print_append("-"*253,purchase_invoices_list)
print_append("\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t"+"Purchase
Invoice",purchase_invoices_list)
print_append("Date : "+current_date,purchase_invoices_list)
print_append("Time: "+current_time,purchase_invoices_list)
print_append("Name of the employee: "+name,purchase_invoices_list)
print_append("-"*253,purchase_invoices_list)

Nirdesh Subedi 72
CS4051NI/CS4059NI Fundamental of Computing

print_append("S.N\t"+" Product Code\t "+"Product\t\t


"+"Manufacturer\t\t"+"Price\t\t"+"Quantity \t\t"+"Total",purchase_invoices_list)
print_append("-"*253,purchase_invoices_list)
#declaring and initializing a varible total_price to 0 which stores the total price of all
the items purchased
total_price=0
sn=1
# looping through all the items in the text file from the list items and fecthing the
corresponding details about the matched product
for i in range(len(items)):
# looping the list item which has the product code and quantity to be purchased ,
which is matched with the details in txt file
for product,quantity in purchase_item:
if product==int(items[i]["product_id"]):
# after the product code is matched, other information about the product is
stored in variable and printed as invoice
product_code=items[i]["product_id"]
product_name=items[i]["product_name"]
manufacturer_name=items[i]["manufacturer"]
price=int(items[i]["cost_price"].replace("$",""))
prod_quantity=quantity
total=price*prod_quantity
total_price+=total
print_append(str(sn)+"\t "+str(product_code)+"\t\t"+product_name
+"\t\t"+manufacturer_name+"\t\t$"+str(price)+"\t\t "+str(prod_quantity)+"\t\t
$"+str(total),purchase_invoices_list)
sn=sn+1
print_append("-"*253,purchase_invoices_list)
print_append("\t\t\t\t\t\t\t\t\t\tTotal\t\t $"+str(total_price),purchase_invoices_list)
vat_amount=(total_price)*0.13

Nirdesh Subedi 73
CS4051NI/CS4059NI Fundamental of Computing

print_append("\t\t\t\t\t\t\t\t\t\t VAT
Amount(13%)\t"+"$"+str(vat_amount),purchase_invoices_list)
print_append("\t\t\t\t\t\t\t\t\t\tGrand
Total\t"+"$"+str(total_price+vat_amount),purchase_invoices_list)
filename="purchase"+year+month+day+hour+minute+second+"_"+name+".txt"
with open(filename,"w") as file:
for each in purchase_invoices_list:
file.write(each+"\n")
return("-"*253)

def sales_prompt(codes,items):
"""This functions asks for product id and quantity from users along with its validation
and stores the user-prompted value in a 2-D list
Args:
codes(list):A list which contains all the product id of the items present in text file
items(list of dict):A list of dictionaries where each dictionary contains information
about a product in the text file
Returns:
list:a 2-D list which contains the user_prompted product id along with respective
quantity"""
# a list which stores the product code and quantity as list intended for sales
sales_item=[]
# using while True loop so that we continue until the user prompts no
main_loop=True
while main_loop==True:
if len(sales_item)!=0:
print("-"*253)
print("Products in cart currently: ")
for i in range(len(items)):

Nirdesh Subedi 74
CS4051NI/CS4059NI Fundamental of Computing

for product_id,quantity in sales_item:


if int(items[i]["product_id"])==product_id:
print(items[i]["product_name"],"\t\t","Quantity:",quantity)
print("-"*253)
try:
product_code=int(input(" Enter the product code :"))
if product_code in codes:
product_available=False
# if product code is valid, we will now get the quantity of the chosen product ,
which we will then compare to the user-prompted quantity of the given product
for i in range(len(items)):
"""using for loop , fetching the quantity of the entered product , which is
stored in a variable quantity_stock
the loop iterates through every index in the list, matches the entered
product_code with the value of key "product_id" in dictionary of each index
the corresponding quantity for the given product code is stored in the
variable quantity_stock"""
if product_code==int(items[i]["product_id"]):
quantity_stock=int(items[i]["quantity"])
if quantity_stock>0:
product_available=True
break
else:
print("-"*253)
print("Sorry, this product is not available currently")
display_inventory(items)
break

if product_available==False:

Nirdesh Subedi 75
CS4051NI/CS4059NI Fundamental of Computing

continue # using continue so that we skip this iteration of loop as the


product is not available due to its quantity being zero

#using while True loop so that we continue to ask the user for quantity until it
is a valid value
quantity_loop=True
while quantity_loop==True:
try:
print("-"*253)
print("Product Id: ",product_code)
quantity=int(input("Enter the quantity : "))
#comparing the entered quantity with the quantity in our inventory
# asking for quantity again if user input is greater than qunatity in
inventory
if quantity>quantity_stock:
print("-"*253)
print("Only ",quantity_stock," in our inventory right now.")
print(" Please enter the quantity again!")
if quantity<0:
print("-"*253)
print("Quantity can't be a negative value!!!!!")
if quantity==0:
print("-"*253)
print("Quantity can't 0.")
if quantity>0 and quantity<= quantity_stock:
sales_item.append([product_code,quantity])
sales_update_product(items,product_code,quantity)
quantity_loop = False # exiting from quantity loop by setting quantity
loop to false

Nirdesh Subedi 76
CS4051NI/CS4059NI Fundamental of Computing

except ValueError:
print("-"*253)
print("Invalid Quantity Entered!!!! Please enter the quantity in numeric
form!!!")
# Inner loop to get valid user input for adding more products
yes_no_loop=True
while yes_no_loop==True:
print("-"*253)
user_decision = input("Do you want to add more products? (y/n):
").lower().strip()
if user_decision in ['y', 'n']:
yes_no_loop=False
else:
print("Invalid input. Please enter 'y' or 'n'.")
if user_decision == "n":
# displaying product cart after user prompts "n"
print("-"*253)
print("Products in the cart: ")
for i in range(len(items)):
for product_id,quantity in sales_item:
if int(items[i]["product_id"])==product_id:
print(items[i]["product_name"],"\t\t","Quantity:",quantity)
print("-"*253)
print( "->->->->->->->->->->->->->->->->->->->->->->->->->->->->->->->->-
>-> Generating Sales Invoice <-<-<-<-<-<-<-<-<-<-<-<-<-<-<-<-<-<-<-<-<-<-<-<-<-<-<-
<-")
main_loop=False # breaking from main outer while loop after user prompts
"n"
else:

Nirdesh Subedi 77
CS4051NI/CS4059NI Fundamental of Computing

display_inventory(items) # displaying inventory again after user prompts "n"


else:
print("Invalid Product Code !! Enter a valid code!!")
print("-"*253)
except ValueError:
print("-"*253)
print("Invalid Product Code!!!!! Please enter the quantity in numeric value ")
display_inventory(items)
return sales_item
def sales_invoice(sales_item,items,ship_cost):
"""This function creates and displays the sales invoice as well as writes the invoice in
a unique file.
Args:
sales_item(list): A list which contains list having the user-prompted product id and
quantity for sales
items (list of dict): A list of dictionaries where each dictionary contains information
about a product in the text file
ship_cost(int): A integer value which holds the shipping cost
Returns:
a set of concatenated characters
"""
# this list contains all the string in our invoices, which will later be used for writing in a
text file
sales_invoices_list=[]
print("-"*253)
name_loop=True
# validating name using while True loop
while name_loop==True:
name=input("Enter the name of the customer: ").strip()
# checking if name is empty

Nirdesh Subedi 78
CS4051NI/CS4059NI Fundamental of Computing

if len(name)==0:
print("-"*253)
print("The fields can't be empty")
print("Please enetr your name.")
print("-"*253)
else:
name_loop=False # if name is valid exiting from the while loop
phonenum_loop=True
# asking for phone number and validating user input
while phonenum_loop==True:
try:
phn_num=int(input("Enter your phone number: "))
if len(str(phn_num))==10:
phonenum_loop=False
else:
print("-"*253)
print("Phone Number should be 10 digits!!!")
print("-"*253)
except ValueError:
print("-"*253)
print("Please enter valid phone number ")
print("-"*253)
print("-"*253)
# Geting the current date and time
year=str( datetime.now().year)
month=str( datetime.now().month)
day=str( datetime.now().day)
hour=str( datetime.now().hour)

Nirdesh Subedi 79
CS4051NI/CS4059NI Fundamental of Computing

minute=str( datetime.now().minute)
second=str( datetime.now().second)
# Extracting and formatting the date part
current_date =year+"-"+month+"-"+day
# Extracting and formatting the time part
current_time = hour+" : "+minute+" : "+second
# using print_append function to print in Shell and append in a list simulataenously
print_append("\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tBRJ
Furniture\n"+"\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t Naxal-5,
Kathmandu",sales_invoices_list)
print_append("-"*253,sales_invoices_list)
print_append("\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t"+"Sales Invoice",sales_invoices_list)
print_append("Date : "+current_date,sales_invoices_list)
print_append("Time: "+current_time,sales_invoices_list)
print_append("Name of the customer: "+name,sales_invoices_list)
print_append("Phone Number: "+str(phn_num),sales_invoices_list)
print_append("-"*253,sales_invoices_list)
print_append("S.N\t"+" Product Code\t \t"+"Product"+ "\t\t"+"Price\t\t"+"Quantity
\t\t"+"Total",sales_invoices_list)
print_append("-"*253,sales_invoices_list)
#declaring and initializing a varible total_price to 0 which stores the total price of all
the items purchased
total_price=0
sn=1
# looping through all the items in the text file from the list items and fecthing the
corresponding details about the matched product
for i in range(len(items)):
# looping the list item which has the product code and quantity to be purchased ,
which is matched with the details in txt file
for product,quantity in sales_item:

Nirdesh Subedi 80
CS4051NI/CS4059NI Fundamental of Computing

if product==int(items[i]["product_id"]):
# after the product code is matched, other information about the product is
stored in variable and printed as invoice
product_code=items[i]["product_id"]
product_name=items[i]["product_name"]
manufacturer_name=items[i]["manufacturer"]
price=int(items[i]["selling_price"].replace("$",""))
prod_quantity=quantity
total=price*prod_quantity
total_price+=total
print_append(str(sn)+"\t "+product_code+"\t\t"+product_name
+"\t\t$"+str(price)+"\t\t "+str(prod_quantity)+"\t\t $"+str(total),sales_invoices_list)
sn=sn+1
print_append("-"*253,sales_invoices_list)
print_append("\t\t\t\t\t\t\tTotal \t\t "+"$"+str(total_price),sales_invoices_list)
vat_amount=(total_price)*0.13
print_append("\t\t\t\t\t\t\tVAT
Amount(13%)\t"+"$"+str(vat_amount),sales_invoices_list)
print_append("\t\t\t\t\t\t\t Shipping Cost\t"+"$"+str(ship_cost),sales_invoices_list)
print_append("\t\t\t\t\t\t\tGrand
Total\t"+"$"+str(total_price+vat_amount+ship_cost),sales_invoices_list)
filename="sales"+year+month+day+hour+minute+second+"_"+name+".txt"
# writing the invoice in a file
with open(filename,"w") as file:
for each in sales_invoices_list:
file.write(each+"\n")
return("-"*253)

def shipping_cost():

Nirdesh Subedi 81
CS4051NI/CS4059NI Fundamental of Computing

""" This function ask user thier address and assingns a shipping cost based on the
prompted address.
Args:
None
Returns:
int: shipping cost
"""
print("-"*253)
print( "Enter ''1'' if shipping address is inside valley")
print("Enter ''2'' if shipping address is outside valley")
print("Enter ''3'' if shipping not required")
print("-"*253)
#using while True so that we continue until a valid input is provided
outer_loop=True
while outer_loop==True:
try:
address=int(input("Enter a number based on the shipping address : "))
# when address is 1, cost is assigned a value and the loop is exited
if address==1:
cost=50
outer_loop=False
# when address is 2, cost is assigned based on the province
elif address==2:
print("-"*253)
print( "Enter '' 1'' if shipping address is Province 1" ,"Shipping cost will be
$1000")
print(" Enter ''2'' if shipping address is Madhesh Province")
print( "Enter ''3'' if shipping address is Bagmati Province(except Kathmandu
Valley)")

Nirdesh Subedi 82
CS4051NI/CS4059NI Fundamental of Computing

print(" Enter ''4'' if shipping address is Gandaki Province")


print( "Enter ''5'' if shipping address is Lumbini Province")
print("Enter ''6'' if shipping address is Karnali Province")
print( "Enter ''7'' if shipping address is SudurPaschim Province")
print("-"*253)
#using while True so that we continue until a valid input is provided
inner_loop=True
while inner_loop==True:
try:
province=int(input("Enter a number based on the shipping address : "))
# if the prompted input is matched, cost is assigned a value and loop is
exited
if province==1:
cost=100
inner_loop=False
elif province==2:
cost=80
inner_loop=False
elif province==3:
cost=65
inner_loop=False
elif province==4:
cost=80
inner_loop=False
elif province==5:
cost=100
inner_loop=False
elif province==6:
cost=120

Nirdesh Subedi 83
CS4051NI/CS4059NI Fundamental of Computing

inner_loop=False
elif province==7:
cost=150
inner_loop=False
# if province is invalid value, the input for province is asked until valid
value is entered
else:
print("-"*253)
print("Invalid Number Detected!! Please enter again!!")
print("-"*253)
except ValueError:
print("Please enter valid numeric value.")
outer_loop=False #breaking the outer loop
elif address==3:
cost=0
outer_loop=False
else:
print("-"*253)
print("Invalid Number Detected!! Please enter again!!")
print("-"*253)
except ValueError:
print("Please enter a valid numeric value")
return cost

# creating a function which prints the given argument and adds the given argument to a
list
def print_append(line,target_list):

Nirdesh Subedi 84
CS4051NI/CS4059NI Fundamental of Computing

"""This function prints the string passed in the paramater and appends the provided
string to a list.
Args:
line(string): A set of strings
target_list(list): A list where the string passed as paramter is appeneded into.
Returns:
None """
print(line)
target_list.append(line+"\n") # appending the provided string argument in to a list as
provided in argument

def purchase_update_product(items,product_code,quantity):
"""This function increases the quantity of the product after is purchased
Args:
items (list of dict): A list of dictionaries where each dictionary contains information
about a product in the text file
prouduct_code(int): User entered product_code for purchasing the particular
product
quantity(int): User entered quantity for particular product
Returns:
None
"""
# looping through the items in inventory and increasing the quantity of product in real
time
for i in range(len(items)):
if product_code==int(items[i]["product_id"]):
items[i]["quantity"]=str(int(items[i]["quantity"])+quantity)
new_list = dict_to_list(items)
write_file(new_list) # writing in thee change in file

Nirdesh Subedi 85
CS4051NI/CS4059NI Fundamental of Computing

def sales_update_product(items,product_code,quantity):
"""This function decreases the quantity of the product after is purchased
Args:
items (list of dict): A list of dictionaries where each dictionary contains information
about a product in the text file
prouduct_code(int): User entered product_code for purchasing the particular
product
quantity(int): User entered quantity for particular product
Returns:
None"""
# looping through the items in inventory and increasing the quantity of product in real
time
for i in range(len(items)):
if product_code==int(items[i]["product_id"]):
items[i]["quantity"]=str(int(items[i]["quantity"])-quantity)
new_list = dict_to_list(items)
write_file(new_list) # writing in thee change in file

def remove_duplicates(l):
""" This function eliminates the duplicate first indexes of list in a 2D list and for the
second index of duplicate value , it adds the value of second index to the existing
second index of such recurring value.
Args:
l(list): A 2D list with duplicates first indexes of list inside the 2_D list
Returns:
(list): A list with no duplicate first index of list inside the 2-D list"""

Nirdesh Subedi 86
CS4051NI/CS4059NI Fundamental of Computing

# initializing a new empty list


new_list_for_items=[]
# initializing a new dictionary
dict_for_items={}
for item in l:
# if the product code does not exist in dict, making the product a a key for
dictionary and value is corresponding quantity
if item[0] not in dict_for_items:
dict_for_items[item[0]]=item[1]
# if the product code does exist in dict, increasing the quantity value in
corresponding key(product code)
else:
dict_for_items[item[0]]+=item[1]
# appending the each key-value pair of dictionary in a 2D list
for key, value in dict_for_items.items():
new_list_for_items.append([key,value])
return new_list_for_items

Nirdesh Subedi 87
CS4051NI/CS4059NI Fundamental of Computing

Code of read.py
def read_file():
""" This methods reads each of the text file and stores each line in a key-value
pair(dictioanary) which again is appended to a list
Args:
None
Returns
list of dict: A list containing the all the details of the each product stored in the text
file in the form of key-value pair(dictionary)"""
try:
#creating a empty list, where we will store key-value pair for a particular product in
our inventory
with open("inventory.txt","r") as file:
row=file.readlines()
inventory_list=[]
for each in row:
# each line is split by comma afetr removing trailing white space
each=each.rstrip().split(",")
# each index of the list is value for the keys in the dictionary created below

item_detail={"product_id":each[0],"manufacturer":each[1],"product_name":each[2],"quan
tity":each[3],"cost_price":each[4],"selling_price":each[5]}
inventory_list.append(item_detail)
return inventory_list
except FileNotFoundError:
print(" The text file couldn't be found!!!!","\n","Please check for the text file")

#creating a function which returns a list containing product code of all the itemin text file
def product_codes(items):

Nirdesh Subedi 88
CS4051NI/CS4059NI Fundamental of Computing

"""
This method extracts product IDs from a list of dictionaries, each representing an
item read from a text file.
Args:
items (list of dict): A list of dictionaries where each dictionary contains information
about a product, including its ID.
Returns:
list: A list containing the product IDs extracted from the dictionaries in the input list.
"""
productcode_list=[]
#calling read_file() method which returns a list of dictionary after reading the txt file
for i in range(len(items)):
code=int(items[i]["product_id"])
productcode_list.append(code)
return productcode_list

Nirdesh Subedi 89
CS4051NI/CS4059NI Fundamental of Computing

Code of write.py
#creating a list which writes the the list returned by dict_to_list function in the text file
def write_file(_list):
""" This function writes the provided list of string into a text file
Args:
_list(list): a list containing strings
Returns:
None"""
with open("inventory.txt","w") as file:
for each in _list:
file.writelines(each+"\n")

#creating a method which converts the list of dictionary to a 2d-list


def dict_to_list(items):
""" This function converts a list of dictionary into a list of strings
Arguement:
items(list of dict):A list of dictionaries where each dictionary contains information
about a product in the text file
Returns:
(list) a list containing strings
"""
dict_list=[]
for i in range(len(items)):
# each value of key of a dictionary is converted to list iteratively
row=list(items[i].values())
# joining all the elements of the list into a single string , each element seperated by
comma(,)
new_row=",".join(row)

Nirdesh Subedi 90
CS4051NI/CS4059NI Fundamental of Computing

dict_list.append(new_row)
return dict_list

Nirdesh Subedi 91

You might also like