![]() | ||||
![]() | ||||
|
[ Current Status ]   |  
[ CVS ]   |  
[ Mail List ]   |  
[ Files ]   |  
[ Jobs ]
|
|
||
|
Home
EasyPOS
|
![]() |
![]() |
Database Design
--------------------------------------------------------------------------------
-- users and security profiles required for build 1
drop table users;
create table users (
username text primary key not null,
passwd text not null,
profile text not null,
last_login abstime,
logged_in bool default 'f',
terminal int -- current terminal logged into
);
drop table user_profile;
create table user_profile (
profile text primary key not null,
default_page text,
can_bad_cust bool default 't',
can_alter_cust bool default 't',
can_pos bool default 't',
can_receipt bool default 't',
can_table bool default 't',
can_internet bool default 'f',
can_drink bool default 'f',
can_auth_timesheet bool default 'f',
can_view_purch bool default 'f',
can_purch bool default 'f',
can_book bool default 't',
can_maintain bool default 'f',
can_report bool default 't',
can_music bool default 'f',
can_cancel_ord bool default 'f',
can_change_ord bool default 'f',
can_send_email bool default 'f',
can_quit bool default 't',
no_auto_logout bool default 'f' -- this user overrides auto-logout feature of terminal
);
-- create some basic security profiles
insert into user_profile (profile,default_page) values ('TRAIN',1);
insert into user_profile (profile,default_page) values ('USER',1);
insert into user_profile (profile,default_page) values ('DRINK',7);
insert into user_profile (profile,default_page) values ('MANAGER',1);
insert into user_profile (profile,default_page) values ('OWNER',1);
update user_profile set can_internet='t',can_drink='t',can_auth_timesheet='t',
can_view_purch='t',can_music='t',can_cancel_ord='t',can_change_ord='t',
can_send_email='t' where profile='MANAGER' or profile='OWNER';
update user_profile set can_maintain='t',can_purch='t' where profile='OWNER';
-- create some users
insert into users (username,passwd,profile) values ('1','1','USER');
insert into users (username,passwd,profile) values ('TRAIN','train','TRAIN');
insert into users (username,passwd,profile) values ('DRINK','drink','DRINK');
insert into users (username,passwd,profile) values ('MANAGER','manager','MANAGER');
insert into users (username,passwd,profile) values ('JACK','sprat','OWNER');
--------------------------------------------------------------------------------
-- stores file for mulitple branches - required for build2
drop table stores;
create table stores (
id int not null primary key,
store_name text,
address text,
suburb text,
postcode text, -- US postcodes sometimes have alpha chars !!
phone text,
manager text,
modem text,
update_hour int,
update_minute int,
is_branch bool
);
-- create some stores
COPY "stores" FROM stdin;
1 Demoland Central 1 Central Tower Demoville 90210 8290 7574 Jack Sprat 82908801 \N \N f
2 Downtown Demoland 34 The Pavillion East Demoville 90211 8345 4567 Peter Tosh 8908802 3 0 t
3 Demoland Rural Division 277 Cornjack way South Demoville 90212 8233 4200 Jerry Lee Cooper 8909320 4 0 t
\.
--------------------------------------------------------------------------------
-- customers file. Required for build1
drop sequence customers_id_seq;
drop table customers;
create table customers (
id serial primary key,
name text,
address text,
phone text,
suburb text,
map_ref text,
comments text,
bad_cust bool,
date_created date,
min_order_value decimal(9,2),
deliv_charge decimal(9,2),
-- de-normalized stats held against the customer
lastorder_num int,
lastorder_date date,
total_value decimal(9,2),
last_value decimal(9,2),
avg_value decimal(9,2),
avg_period int
);
-- enable internet accounts, and gather useful marketting guff while
-- we are at it
drop table income_ranges;
create table income_ranges (
id int primary key,
descr text
);
copy income_ranges from stdin;
1 up to 20,000
2 up to 40,000
3 up to 60,000
4 up to 80,000
5 over 80,000
\.
drop table mar_status;
create table mar_status (
code char primary key,
descr text
);
copy mar_status from stdin;
S Single
M Married
D Divorced / Sep
W Widowed
\.
drop table customer_internet;
drop sequence customer_internet_id_seq;
create table customer_internet (
id serial primary key,
passwd text not null,
email text,
rating text, -- How do the staff of this shop rate this user ?
gender char, -- Male / Female that is
birthday date,
company text, -- who do they work for
income int,
mar_status char,
own_house bool,
renting bool,
make_of_car text,
year_of_car int,
how_heard text -- how did they hear about us
);
-- if nothing else you can always login to a business that has a decent database and
-- run the followin query :
-- "select i.id,c.name,c.suburb,c.phone,i.email from customers c,customer_internet i where
-- c.id = i.id and i.gender='F' and i.mar_status='S' and i.income >= 4
-- and i.make_of_car ~ "/^bm|^por|^merc|^aud/i";
--
-- of course, you may prefer Pontiacs .. each to his own
--------------------------------------------------------------------------------
-- item categories
drop table category;
create table category (
code text not null primary key,
descr text,
allow_discount bool,
icon text,
tax_rate decimal(5,2),
x_label text,
y_label text,
z_label text
);
-- create some categories now
--
-- this is deliberatly setup for a restaraunt & pizza delivery business
-- but we will include some templates for other types of businesses later on such as :
-- florist, mountain bike shop, miniature wargames shop, video shop, and second hand bookshop
COPY "category" from stdin;
P Pizza t pizza.png \N Size Topping Base
T Pasta t pasta.png \N Pasta Sauce Serve
S Steak t steak.png \N Method Style Cooking
C Chicken t chicken.png 3.5 Type Dish \N
E Seafood t seafood.png \N Type Dish \N
Z Specials f specials.png \N Type Options \N
R Drinks f drinks.png 10.0 Size Drink Mixer
A Appetisers t appetisers.png \N Type Dish \N
D Dessert f dessert.png \N Size Serve \N
\.
-- Note in our demo here, drinks and special offers are not discounted (ie - if the customer
-- has a 10% discount, that does not apply to drinks and special offers). Also, there is an
-- an additional 10% drinks tax added to drinks, as well as a 3.5% Poultry tax on all chicken
-- orders. (There is no such thing as a poultry tax - it is just an illustration)
--------------------------------------------------------------------------------
-- items database. Please read this section twice - it is easy once you get it.
--
-- In GtkPizza, items are 1-liner stock items, which is easy on the brain, but very
-- difficult to generate new sets of custom data. In gShop we use a 3 dimensional cube
-- to represent all the pricing and variations for a category of item.
--
-- Take Pizza for example - there are say 10 different topping combinations (Mexican, hawiian, etc)
-- as one dimension, and the size (small,large,family,party) as the other dimension - that is
-- 40 combinations so far. On top of this, you can order your pizza as thin, pan, cheesy crust
-- or new york style - that is now 40 * 4 = 160 combinations. GtkPizza would require 160 stock items
-- to cope with this. It gets worse when you look at pasta - fettucini, tagliatelle, rotella, etc
-- combined with a huge variety of sauces - alfredo, carbonara, fantasia, bolognaise, etc. You want
-- that entree sized or main course sir ? .. arghh !
--
-- The problem is not confined to pizza bars either - your average mountain bike shop has a similar
-- problem, as does a video shop, bookshop, florist, and miniature wargames supplier.
--
-- The solution is to define a pair of product dimensions for each category of item, that defines
-- a 2D pricing grid. On top of this is an optional third dimension that presents service options
-- that apply a fixed modification to the price.
--
-- The system can then generate unique stock codes on the fly for individual combinations of things,
-- and it fits intuitively with the touchscreen grid approach for data entry, as well as being able
-- to generate web-based order screens that dont appear to overwhelm the user with a million options.
--
-- the real stock code for an item then is going to be
-- Category-Xaxis-Yaxis-Zaxis
--
-- It also makes reporting a breeze, since (at least [my|postgre]SQL) can do regular expression searches
-- then you can ask for reports like 'How many Hawiian vs Mexican pizzas have we sold, regardless of
-- the size ?', 'What is the most popular pasta sauce ?', 'Break down our turnover into flowers wrapped
-- in plain paper vs flowers wrapped in foil' and get them out in 1 line of SQL code, without any
-- table joins.
drop table item_x;
drop table item_y;
drop table item_z;
-- horizontal x axis of the 2D pricing grid
create table item_x (
category text not null,
code text not null,
descr text,
long_descr text,
icon text
);
create unique index item_x_idx on item_x (category,code);
-- vertical y axis of the 2D pricing grid
create table item_y (
category text not null,
code text not null,
descr text,
long_descr text,
icon text
);
create unique index item_y_idx on item_y (category,code);
-- 2D pricing grid for each category
drop table price_grid;
create table price_grid (
category text not null,
code_x text not null,
code_y text not null,
price decimal(9,2)
);
create unique index price_grid_idx on price_grid (category,code_x,code_y);
-- 3rd dimension of item
create table item_z (
category text not null,
code text not null,
descr text,
icon text,
price_mod decimal(9,2)
);
create unique index item_z_idx on item_z (category,code);
-- now to create some items
COPY item_x from stdin;
P S Small Small 9inch small.png
P L Large Large 12inch large.png
P F Family Family 15inch family.png
P P Party Party Size 18inch party.png
\.
COPY item_y from stdin;
P MEX Mexican Ham, Peperoni, Chili, Caps, Mushroom mexican.png
P HAW Hawiian Ham, Pineapple hawiian.png
P AME American Cheese & Peperoni american.png
P ROM Roman Ham, Egg roman.png
P MAR Margherita Cheese and Herbs margherita.png
\.
COPY item_z from stdin;
P O Original thin.png 0.00
P P Pan thick.png 1.00
P N NewYork Style newyork.png 2.50
P C CheesyCrust cheesy.png 1.50
\.
-- That was pretty painless : we just defined 4 * 5 * 4 = 80 different types of pizza
-- Will not bother putting the pricing grid in here - it is easy to do that on the screen
--------------------------------------------------------------------------------
-- suburbs table required for build1
drop table suburbs;
create table suburbs (
suburb text not null primary key,
postcode text, -- some US postcodes are alphanumeric
map_ref text,
store_id int, -- closest or preferred store
min_order decimal(9,2),
deliv_charge decimal(9,2)
);
-- no need to create data now, as gShop will automatically build this file up from
-- the data that is entered
-- different delivery charge to each suburb depending on what store the delivery is
-- coming from. This is important for chain stores, since they all need to synchronise
-- their databases, you still want to see only the relevant delivery charges being applied
-- from any given store.
drop table suburb_min;
create table suburb_store (
suburb text,
store_id int,
min_order decimal(9,2),
deliv_charge decimal(9,2)
);
--------------------------------------------------------------------------------
-- Order headers required for build 1
drop table order_type;
create table order_type (
code text not null primary key,
descr text
);
copy order_type from stdin;
D Delivery
P Pickup
FD Future Delivery Order
FP Future Pickup Order
B Booking
IP Internet Pickup Order
ID Internet Delivery Order
SD Standing Delivery Order
SP Standing Pickup Order
T Table Account
C Cash / POS
\.
drop table orders;
drop sequence orders_id_seq;
create table orders (
id serial primary key,
store_id int,
type text,
customer_id int, -- only applys to delivery orders and internet orders
name text,
date datetime,
table_num int, -- only applys to sit down orders of type T
eta abstime, -- only applys to pickup and delivery orders
comments text,
-- denormalized fields
total_price decimal(9,2)
);
-- order detail lines
drop table ordet;
create table ordet (
store_id int, -- to match the order id
id int, -- order's id
seq_num int,
item_code text, -- see notes on the 4-part item code above = Cat-X-Y-Z
descr text,
qty decimal(5,2),
price decimal(9,2)
);
create unique index order_idx on ordet (store_id,id,seq_num);
-- basic auditing on order detail lines, so that employees cannot fake the
-- computer order up to match the till for their friends
drop table ordhist;
create table ordhist (
store_id int,
id int,
seq_num int,
date abstime,
item_code text,
descr text,
qty decimal(5,2),
price decimal(9,2)
);
--------------------------------------------------------------------------------
-- Tables table required for build1 - but not sure if 'tables' is always a valid SQL name !
drop table seating_status;
create table seating_status (
code text primary key,
descr text
);
copy seating_status from stdin;
A Available
O Occupied
U Un-available
B Booked
\.
drop table seating;
drop sequence seating_id_seq;
create table seating (
id serial primary key,
x_pos int, -- graphical screen position
y_pos int, -- graphical screen position
capacity int,
guests int,
status text,
starttime abstime, -- If occupied, when did they start, in Unixtime
-- derive the time spent at runtime = time(NULL) - starttime;
-- denormalized fields
total_bill decimal(9,2)
);
--------------------------------------------------------------------------------
-- receipting table to track what has been received
drop table receipts;
drop sequence receipts_id_seq;
create table receipts (
id serial primary key,
store_id int, -- relates back the store
date datetime,
order_id int, -- relates back to the order header
total decimal(9,2),
type text,
card_num text -- if they paid by card, what was the card number, or the eftpos receipt num
);
--------------------------------------------------------------------------------
-- info on which printers and terminals are available
drop table printers;
drop sequence printers_id_seq;
create table printers (
id serial primary key,
store int, -- which store is this printer in ?
descr text, -- make and model
spooler_name text, -- lpr -Pspooler_name is invoked, so all
-- terminals need to be setup consistently
-- to be able to hit all printers
columns int, -- how many columns can this printer do ?
double_paper bool, -- does this printer do double paper ?
-- if not, we have to spool 2 copies of a docket
cut_paper bool, -- should be sent a 'cut paper' command after
-- each job ?
cut_command text, -- hex digits to send to cut the paper
can_color bool, -- can it do color ?
color_on text, -- hex digits to turn color on
color_off text, -- hex digits to turn color off
can_cashdraw bool, -- can this printer open a cashdrawer ?
cashdraw_open text, -- hex digits to open a cashdrawer
can_receipt bool,
can_report bool
);
copy printers from stdin;
1 1 Main Receipt Printer receipt 40 f f \N f \N \N t f
2 1 Main Report Printer report 132 f f \N f \N \N f t
\.
drop table op_systems;
drop sequence op_systems_id_seq;
create table op_systems (
id serial primary key,
descr text
);
copy op_systems from stdin;
1 Linux
2 Win98
3 WinNT
4 MacOS
5 Alpha Tru64
6 Solaris
7 Other Unix
8 VMS
9 MS-DOS
10 BeOS
\.
drop table terminals;
drop sequence terminals_id_seq;
create table terminals (
id serial primary key,
store int, -- which store is this terminal in ?
descr text,
receipt_printer int,
report_printer int,
can_socket bool, -- can this terminal accept incoming sockets ?
hostname text,
port int, -- which port to use for socket connections ?
op_system int, -- relates to op system table
phone_ext text, -- telephone extension
can_music bool default 'f', -- can this terminal do music control ?
logout_timeout int, -- max seconds of inactivity before logout
has_barcode bool,
barcode_device text, -- serial port for barcode device
has_callerid bool,
callerid_device text -- serial port for callerid device
);
copy terminals from stdin;
1 1 Main gShop Server 1 2 t localhost 6801 1
\.
--------------------------------------------------------------------------------
-- Simple internal email database
drop table email;
create table email (
id serial primary key,
from_user text not null,
from_terminal int not null,
from_store int not null,
address_to int, -- 1 = specific user, 2 = profile, 3 = terminal, 4 = store, 0 = all
to_user text,
to_profile text,
to_terminal int,
to_store int,
date_sent abstime,
date_read abstime,
is_read bool default 'f',
message text
);
--------------------------------------------------------------------------------
-- in-store advertising
drop table adverts;
create table adverts (
id serial primary key,
descr text,
frame_delay int, -- milliseconds between frames
frames text[], -- mySQL porters beware !! - this field
-- uses a postgreSQL array'ed field
-- the contents of the field simply points to
-- an image file that is scaled into the advert canvas
);
--------------------------------------------------------------------------------
-- System setup table
drop table global_options;
create table global_options (
id int, -- id 1 is used
cash_till_mode bool, -- true if cash-till mode (else store-wide mode)
POS_touchscreen bool, -- use touch panel for POS transactions
POS_adverts bool, -- display adverts on POS transactions
);
--------------------------------------------------------------------------------
-- yet to do in the way of SQL tables
--
-- mySQL equivalent
-- Timesheet data
-- Bookings for tables
-- Special header extensions for future orders
-- Special header extensions for standing orders
--
--------------------------------------------------------------------------------
|