School Canteen Token and Sales System
Issue token slips at the counter and close the day with a sales summary.
1Introduction: the problem it solves
At break the school canteen has a queue, a cash box and no record of what was sold. At the end of the day nobody can say whether the samosas ran out because they sold well or because fewer were made.
A token slip solves the queue, and the same file that prints the slips can answer the second question for free.
A school or college canteen, a small food stall, or a fete counter.
Why it is worth computerising
A canteen counter has two problems at once during a fifteen-minute break: keeping the queue in order, and pricing each order correctly while people wait. A token slip solves the first. Mental arithmetic under pressure solves the second badly.
The second reason for computerising is that the same data, once typed, answers a question the cash box never could. At the end of the day the canteen knows how many orders it served, what it took, and what an average order was worth — figures that decide how much to cook tomorrow, and which nobody could reconstruct from a drawer of cash.
Objectives
- To give every customer a numbered token so the queue is served in order
- To price an order of several items without mental arithmetic at the counter
- To record each order the moment it is taken, so nothing depends on memory
- To close the day with the number of orders, the takings and the average order
- To start each day with a clean file, so one day's figures never mix with the next
2How the job is done today
Before writing anything it is worth asking how the work is handled at present, and why each of those answers falls short. These were examined:
The usual arrangement in a school canteen. Fast, and it answers no question at all afterwards — not what sold, not how much, not when.
What a restaurant uses. They need hardware, a printer and a subscription, which a canteen open for two breaks a day cannot justify.
Better than nothing, and it moves the arithmetic to the end of the day, which is exactly when nobody wants to do it.
3Functionalities
- Holds the menu as a dictionary of code, name and price
- Takes an order of several items with quantities and prints a numbered token slip
- Writes every order to the day's file as it is taken
- Closes the day with the number of orders, total takings and the average order
- Starts a fresh file each day, so one day's figures never leak into the next
The functions that provide them
| Function | Arguments | What it does |
|---|---|---|
take_order() | token, choices | Write one order to the day's file and print its token slip. |
day_end() | — | Add up everything sold today. |
4Technical details
| Language | Python 3 |
| Storage | Plain text and CSV files |
| Modules used |
|
5How the data is stored
One file per day, `orders.txt`, holding the token number, the items and the amount. Writing each order as it happens rather than at closing time means a power cut costs you one order, not the whole day.
orders.txt — one line per order
| Field | Type | Description |
|---|---|---|
token | integer | Token number handed to the customer |
items | text | Items and quantities, joined with a plus sign |
amount | decimal | What the order came to |
MENU — the price list held in the program
| Field | Type | Description |
|---|---|---|
code | text | What the counter clerk types: 1, 2 or 3 |
name | text | Item name as printed on the slip |
price | decimal | Price of one unit |
6How it works, step by step
take_order() looks up each item code in MENU, multiplies by the quantity and adds up the bill.
The order is appended to orders.txt straight away, before the slip is printed.
The token number and items are printed in fixed-width columns — that is the slip the customer carries.
day_end() reads the file back, counts the orders and totals the takings.
7Source code
# ---------------------------------------------------------------------------
# canteen.py
#
# Token slips for a school canteen counter, and the day's sales summary.
#
# Each order is written to the day's file the moment it is taken — before the
# slip is printed — so that a power cut costs one order rather than the whole
# day's takings.
# ---------------------------------------------------------------------------
# The menu, held as a dictionary so the counter clerk can type a short code
# instead of the whole item name. Each entry is (name, price).
MENU = {"1": ("Samosa", 15.0), "2": ("Sandwich", 30.0), "3": ("Juice", 25.0)}
ORDERS = "orders.txt" # one line per order, one file per day
def take_order(token, choices):
"""Write one order to the day's file and print its token slip."""
total = 0 # what this order comes to
lines = [] # the item descriptions, for the slip
# choices is a list of (code, quantity) pairs.
for code, qty in choices:
name, price = MENU[code] # look the code up on the menu
total = total + price * qty
lines.append("{} x{}".format(name, qty))
# Recorded first, printed second. If anything goes wrong after this point,
# the order is already safe on disk.
with open(ORDERS, "a") as f:
f.write("{},{},{:.2f}\n".format(token, "+".join(lines), total))
print("TOKEN {:>3} | {:<24} Rs {:>7.2f}".format(token, "+".join(lines), total))
def day_end():
"""Add up everything sold today."""
print("LAMBDALAB SCHOOL CANTEEN — DAY END")
count = 0 # how many orders were served
takings = 0 # how much money they came to
for line in open(ORDERS):
# Each line was written as token,items,amount — so splitting on the
# comma gives back the same three pieces.
token, items, amount = line.strip().split(",")
count = count + 1
takings = takings + float(amount) # text on the way in, number here
print("-" * 46)
print("Orders served : {}".format(count))
print("Total takings : Rs {:.2f}".format(takings))
print("Average order : Rs {:.2f}".format(takings / count))
# --- the program itself ----------------------------------------------------
open(ORDERS, "w").close() # a fresh file for a fresh day
# Three orders, as they would be taken across a break.
take_order(101, [("1", 2), ("3", 1)]) # 2 samosas and a juice
take_order(102, [("2", 1)]) # one sandwich
take_order(103, [("1", 4), ("2", 2), ("3", 2)]) # a group order
day_end()The full report as a PDF — cover page, certificate, index, code, output, future scope and references, ready to print and fill in. Or the code on its own as a zip.
8Sample output
This is a real run, not a mock-up — the transcript below is what the program actually printed.
C:\LambdaLab\Projects\Canteen> python canteen.py
TOKEN 101 | Samosa x2+Juice x1 Rs 55.00
TOKEN 102 | Sandwich x1 Rs 30.00
TOKEN 103 | Samosa x4+Sandwich x2+Juice x2 Rs 170.00
LAMBDALAB SCHOOL CANTEEN — DAY END
----------------------------------------------
Orders served : 3
Total takings : Rs 255.00
Average order : Rs 85.00Running it also wrote orders.txt. This is what that file held afterwards:
101,Samosa x2+Juice x1,55.00
102,Sandwich x1,30.00
103,Samosa x4+Sandwich x2+Juice x2,170.009Testing
Every case below was actually run and the result recorded as it appeared — including the ones expected to fail.
| Test case | Expected | Actual |
|---|---|---|
| Three orders taken, then day end | 3 orders, Rs 255.00 taken | Total takings : Rs 255.00 |
| A single order in the day | Average equals that one order | Average order : Rs 55.00 |
| An item code not on the menu | KeyError naming the missing code | KeyError: '9' |
| An order of zero items | Token issued, Rs 0.00 added | TOKEN 101 | Samosa x0 Rs 0.00 |
Two kinds of case are in there on purpose. The boundary cases test the edge of a rule, where a program is most often wrong by one. The failure cases check that it refuses cleanly and says why, instead of quietly producing a wrong answer.
10Advantages
Set against the ways the job is done today:
- The queue is served in order, because everyone holds a number
- Prices are looked up rather than remembered
- An order is recorded before the slip is printed, so a power cut costs one order
- The day's takings are known the moment the counter closes
- Tomorrow's cooking can be planned from today's figures
11Future scope
What this version does not do
A report should be honest about its own limits, and each of these is the reason for one of the additions below:
- The menu is fixed in the program; changing a price means editing the code
- There is no stock control, so the program cannot say when something has run out
- Payment is assumed to be in cash and is not recorded
- The token number is supplied by the operator rather than generated
Proposed enhancements
This is also where you make the project yours. Pick one or two of these, or something nobody here thought of:
- Show which item sold most, so the kitchen can plan tomorrow
- Keep a week of files and chart the daily takings
- Print the slip to a real thermal printer
- Add a prepaid card balance for regular students
- A simple tkinter window, so the counter clerk does not use a keyboard menu
12What you may have to teach yourself
CBSE expects some self-learning in a project, and says so. For this one, that means:
- Why the order is written to the file before the slip is printed
- String formatting well enough that the slip lines up on a narrow printer
- Optional: tkinter, if you want a counter window instead of a terminal
13Conclusion
The counter is quicker, the queue is fair, and the canteen ends the day knowing what it sold rather than only what is in the cash box.
Writing each order to the file before printing the slip was a small decision with a real consequence: whatever happens next, the order is already recorded.
14References
Every report needs a bibliography. This one used:
- Computer Science with Python, Class XII — the NCERT / CBSE prescribed textbook, for the chapters on file handling and working with text and CSV files
- Computer Science with Python, Class XI — for functions, lists, dictionaries and string handling
- Python 3 documentation — https://docs.python.org/3/
- CBSE Senior School Curriculum, Computer Science (Subject Code 083) — the project guidelines this report follows
- LambdaLab — https://www.lambdalab.in