Database Schema for a daily delivery system? - database

I want to design a database where I have customers who daily buy varying quantities of any dairy product(milk, curd, cheese) but pay at the end of the month.
I am unable to figure out the correct database schema as I want to store each day's quantity of a particular product and a customer can buy multiple types of products.
So, what should be the way forward?
EDIT: My schema
Customer:
-Customer ID
-Name
-Mobile Number unique
-Address
-Daily Quantity(just for reference. during transaction it can increase or
decrease as per requirement)
Product:
-Product Id
-Name
-Price per unit
Transaction Table
-Customer id (foreign key)
-product id (foreign key)
-Quantity
-Date
Now, i want to generate a monthly bill for each customer by combining all the different items he bought over the month. So, will this transaction table be the best approach to do so?

I´ve add a new table Ticket so every single product bought during the day belongs to a unique Ticket.
This way you can get back to a specific ticket and see how much was spend ( this is because prices could change and there are multiple tickets during one day ).
<Ticket>
-Product id (foreign key)
-Quantity
-total
-Date
I´ve modified your Transaction table to have only ticket-customer relationship.
<Transaction>
-customer_id (foreign key)
-ticket id (foreign key)
-Date
Some SQL example
SELECT Tr.customer_id, MONTH(tr.Date), SUM(ti.total)
FROM Transaction tr, Ticket ti
WHERE tr.ticket_id = ti.id
GROUP BY MONTH(tr.Date)
WHERE Tr.customer_id = ? AND tr.Date BETWEEN ? AND ?

Related

how to set up database

I’m creating an app that tracks attendance of players in amateur football teams. And I’m just not sure how to set up the database. A bit of info: every user has a team and should only see the events within his team per season.
These are the main things:
Users
Events
User stats (for later)
Events
Training / match / social
Date
Time
Subject / opponent
Attendance
Main questions:
Do I make an event table per team per season? Or do I put all events in one big table for every user?
What is the best way to handle the attendance? They should be able to choose from
Present
absent
Fan
Thanks in advance!
I would do it this way:
User
userid PK
Name
Team
teamid PK
TeamName
UserInTeam
userid FK
teamid FK
Event
eventid PK
home_teamid FK
visiting_teamid FK
eventtypeid FK
Date
Time
Subject / opponent
Attendance
Event type
eventtypeid PK
EventType
Attendance Type
attendanceid PK
AttendanceType
UserAtEvent
userid FK
eventid FK
attendancetypeid FK
Content of Event Type
1 Training
2 Match
3 Social
Content of Attendance Type
1 Present
2 Absent
3 Fan
For Event, home_teamid and visiting_teamid can be NULL if the event is not a match
The application will show the events based on the team the user is a member of.

Creating a global ID for every row in multiple tables for notifications

I'm designing what is essentially an accounting/retailing application for MS SQL Server 2016. I have ~75 core data object types, each in their own respective table (users, organizations, invoices, payments, etc.).
What I need to create is a notification system,
e.g. "Steve paid invoice 1234", "Bob purchased product XYZ", etc. What I was going to create was a "notification types" table:
NotificationTypes:
id message
11 "{0} paid invoice {1]"
12 "{0} purchased product {1]"
...
and then have two corresponding tables that store each notification event's info, and then the values for that notification message. So for example for "Steve paid invoice 1234":
NotificationEvent:
id notificationType (FK) occured
21 11 2016-01-01 00:00:00
NotificationEventValues:
id notificationEvent (FK) XXXXX
31 21 (FK reference to Steve in users table)
32 21 (FK reference to invoice 1234 in invoices table)
Now since I can't create generic foreign keys for NotificationEventValues.XXXXX, I was going to have a single 'dataObjects' table that has FK columns for all 75 data types I have, with only one of the 'data type' columns having a value per row.
This way, every instance of a data object in my database has a unique ID I can reference in the notification field - which will mean a huge table given it has a unique ID for basically every row in the other 75 tables. The other downside is it means for every user, invoice, any 'data object', I'm wasting significant amounts of space since space will be reserved for ID references for the other 74 null-valued columns (since they're fixed size IDs and not variable).
ASK:
Is there a better way to achieve my 'global' identifier across all the tables? Or a better way to handle the notification system to avoid this problem?
Create triggers in all table that will insert a record in a table say KeyMaster with one column key which will also be the primry key whenever a record is inserted in any table. The value inserted in this table will be in the format _. For example if a record is inserted in user table with id 1 then the record inserted in KeyMaster table will be 'user_1'. Similarly if a record is inserted in invoice table with id 1 then the recor inserted in KeyMaster table will be 'invoice_1'.
In your NotificationEventValues table you will need only three columns id,notificationEvent and key (FK reference to KeyMaster table).
For getting corresponding record you need to write query similar to below:
select *
from NotificationEventValues n
inner join users u on 'user_' + u.id = n.key

Database: Design customer orders

I am currently creating an Android application which should use SQLite database. In my case, I need to strore "product type", "bill" and "list of all purchased products"
Bill:
id
customer
data -> link to list of all purchased products
price
Product types:
id
name
price
My question is: One customer could have more products connected to one bill. How to design it? Is using a Use a one row for every bills:
id
bill_id
product
or rather insert more products into one row and then parse it in my application? I suppose, there is a better solution that these mine. Thank you for help.
You said in your question, "One customer could have more products connected to one bill."
Another way of saying this is, one customer can have 0 or more bills, and one bill can have 1 or more products.
After rephrasing your statement, the database normalization becomes more obvious.
Customer
--------
Customer ID
Customer Name
...
Bill
----
Bill ID
Customer ID
Bill Time Stamp
Bill-Product
------------
Bill ID
Product ID
Product
-------
Product ID
Product Name
Product Price
...
To design customer order with bill we can design it as below:
This schema having basics attributes we can add more as per requirements.
Customers Table
id PK
full_name
address
phone
MenuItems Table
id PK
item_name
item_description
item_price
Order Table
id PK
customer_id FK
order_date
OrderDetails Table
id PK
order_id FK
menu_item_id fk
quantity
Bill Table
id PK
order_id FK
amount
bill_date

Exclusice Arc and multiple many to many relationships db design issue

I have an existing application that has the following entities in the database
Customer
InvoiceGroup
SalesGroup
A customer can be part of multiple groups. Currently this is mapped in the following way
Customer table
- cid (Pk)
- fname
- surname
----
---
- invgrpdid (Fk)
- salesid (Fk)
Invoicegroup table
- invgrpid (Pk)
- name
- type
---
----
Salesgroup table
- salesid (Pk)
- name
- desc
-----
-----
I now have a requirement to add a new entity campaign. A Customer can be part of multiple campaigns. A campaign is deployed for a customer group which is created by
- selecting individual customers (custom) OR
- selecting an existing invoicegroup (invoice) OR
- selecting an existing salesgroup (sales)
The campaign customer list should be
- reusable, i.e can be used for multiple campaigns
- dynamic, i.e if created from an invoice/sales group, changes across the invoice and sales group
should be reflected to the campaign customer list
I am having difficulty designing for the dynamic requirement. I have come up with the following design, but it has exclusive arcs that is one key refering to multiple foreign keys which is not the recommended approach. I have thought of supertype and subtype, but I am not clear on designing the many-to-many relationships.
campaign
- campaignid(Pk)
- name
- startdate
- status
------
campaignlist
- listid(Pk)
- listname
- listtype - Invoice, Sales, Custom
- typeid (Fk) - Refers to invoicegroupid or salesgroupid depending on listtype
-----
customercampaign
- listid (Fk)
- customerid (Fk)
- status
- dateupdated
-------------
What would be a better approach to design this considering referential integrity and normalization.
The most frequent query run multiple times daily will be to retrieve all campaign information for a customer. So need to be mindful of multiple tables and joins.
At a first stab, I would do something like this:
CampaignList
- ID (PK)
- Name
CustomerCampaignList
- CampaignListID (FK to CampaignList.ID)
- CustomerID (FK)
UNIQUE (CampaignListID, CustomerID)
SalesGroupCampaignList
- CampaignListID (PK,FK to CampaignList.ID)
- SalesGroupID (FK)
UNIQUE (CampaignListID, SalesGroupID)
InvoiceGroupCampaignList
- CampaignListID (PK,FK to CampaignList.ID)
- InvoiceGroupID (FK)
UNIQUE (CampaignListID, InvoiceGroupID)
That is, use table inheritance. This is quite a normalised design, which in my opinion is the approach to take when you're not yet clued up on specific requirements. Optionally, you could make your life easier by denormalising a little and putting a CampaignListTypeID in the CampaignList table. In this case though, it would be difficult to maintain the integrity of the data model without writing logic in a trigger.
I'm assuming that you won't ever have to do interesting combination groups e.g., 2 x sales group + invoice group + a set of customers.

Best structure for inventory database

I want to create a small database for my inventory but I have some problems on picking a structure. The inventory will be updated daily at the end of the day.
The problem I am facing is the following.
I have a table for my products, having an
id, name, price, quantity.
Now I have another table for my sales, but there is my problem. What kind of fields do I need to have. At the end of the day I want to store a record like this:
20 product_x $ 5,00 $ 100,-
20 product_y $ 5,00 $ 100,-
20 product_z $ 5,00 $ 100,-
20 product_a $ 5,00 $ 100,-
-------------------------------------------------
$ 400,-
So how do I model this in a sales record. Do I just create a concatenated record with the product id's comma separated.
Or is there another way do model this the right way.
This is a model which supports many aspects,
Supports Sites, Locations and Warehouses etc.
Supports Categorization and Grouping
Support Generic Product (Ex. "Table Clock" and specific product "Citizen C123 Multi Alarm Clock" )
Also support Brand Variants (by various manufacturers)
Has CSM (color / size / model support) Ex. Bata Sandles (Color 45 Inch Blue color)
Product Instances with serials (such as TVs , Refrigerators etc.)
Lot control / Batch control with serial numbers.
Pack Size / UOM and UOM Conversion
Manufacturer and Brands as well as Suppliers
Also included example transaction table (Purchase order)
There are many other transaction types such as Issues, Transfers, Adjustments etc.
Hope this would help. Please let me know if you need further information on each table.
Cheers...!!!
Wajira Weerasinghe.
Sites
id
site_code
Site_name
Warehouse
id
site_id
warehouse_code
warehouse_name
Item Category
id
category_code
category_name
Item Group
id
group_code
group_name
Generic Product
id
generic_name
Product
id
product_code
category_id
group_id
brand_id
generic_id
model_id/part_id
product_name
product_description
product_price (current rate)
has_instances(y/n)
has_lots (y/n)
has_attributes
default_uom
pack_size
average_cost
single_unit_product_code (for packs)
dimension_group (pointing to dimensions)
lot_information
warranty_terms (general not specific)
is_active
deleted
product attribute type (color/size etc.)
id
attribute_name
product_attribute
id
product_id
attribute_id
product attribute value (this product -> red)
id
product_attribute_id
value
product_instance
id
product_id
instance_name (as given by manufacturer)
serial_number
brand_id (is this brand)
stock_id (stock record pointing qih, location etc.)
lot_information (lot_id)
warranty_terms
product attribute value id (if applicable)
product lot
id
lot_code/batch_code
date_manufactured
date_expiry
product attribute value id (if applicable)
Brand
id
manufacturer_id
brand_code
brand_name
Brand Manufacturer
id
manufacturer_name
Stock
id
product_id
warehouse_id, zone_id, level_id, rack_id etc.
quantity in hand
product attribute value id (if applicable) [we have 4 red color items etc.]
Product Price Records
product_id
from_date
product_price
Purchase Order Header
id
supplier_id
purchase_date
total_amount
Purchase Order Line
id
po_id
product_id
unit_price
quantity
Supplier
id
supplier_code
supplier_name
supplier_type
product_uom
id
uom_name
product_uom_conversion
id
from_uom_id
to_uom_id
conversion_rule
I'd have a table with a row per item per day - store the date, the item ID, the quantity sold, and the price sold at (store this even though it's also in the product table - if that changes, you want the value you actually sold at preserved). You can compute totals per item-day and totals per day in queries.
Tables:
create table product (
id integer primary key,
name varchar(100) not null,
price decimal(6,2) not null,
inventory integer not null
);
create table sale (
saledate date not null,
product_id integer not null references product,
quantity integer not null,
price decimal(6,2) not null,
primary key (saledate, product_id)
);
Reporting on a day:
select s.product_id, p.name, s.quantity, s.price, (s.quantity * s.price) as total
from product p, sale s
where p.id = s.product_id
and s.saledate = date '2010-12-5';
Reporting on all days:
select saledate, sum(quantity * price) as total
from sale
group by saledate
order by saledate;
A nice master report over all days, with a summary line:
select *
from (
(select s.saledate, s.product_id, p.name, s.quantity, s.price, (s.quantity * s.price) as total
from product p, sale s
where p.id = s.product_id)
union
(select saledate, NULL, 'TOTAL', sum(quantity), NULL, sum(quantity * price) as total
from sale group by saledate)
) as summedsales
order by saledate, product_id;
Try modelling your sales as a transaction - with a "header", i.e. who sold to, when sold, invoice # (if applicable), etc. and "line items", i.e. 20 * product_x # $5 = $100. The safest approach is to avoid relying upon prices etc. from the products table - as these will presumably change over time, and instead copy much of the product information (if not all) into your line item - so even when prices, item descriptions etc. change, the transaction information remains as was at the time the transaction was made.
Inventory can get quite complex to model. First you need to understand that you need to be able to tell the value of the inventory onhand based on what you paid for it. This means you cannot rely on a product table that is updated to the current price. While you might want such a table to help you figure out what to sell it for, there are tax reasons why you need to know the actual vlaue you paid for each item in the warehouse.
So first you need the product table (you might want to make sure you have an updated date column in this, it can be handy to know if your prices seem out of date).
Then you need a table that stores the actual warehouse location of each part and the price at purchase. If the items are large enough, you need a way to individually mark each item, so that you know what was taken out. Usually people use barcodes for that. This table needs to be updated to record that the part is no longer there when you sell it. I prefer to make the record inactive and have a link to my sales data to that record, so I know exactly what I paid for and what I sold each part for.
Sales should have at least two tables. One for the general information about the sale, the customername (there should also be a customer table most of the time to get this data from), the date, where it was shipped to etc.
Then a sales detail table that includes a record for each line item in the order. Include all the data you need about the part, color, size, quantity, price. This is not denormalizing, this is storing historical data. The one thing you do not want to do is rely on the prices in the product table for anything except the inital entry to this table. You do not want to do a sales report and have the numbers come out wrong becasue the product prices changed the day before.
Do not design an inventory database without consulting with an accountant or specialist in taxes. You also should do some reading on internal controls. It is easy to steal from a company undetected that has not done their work on internal controls in the database.
I think you need a table with fields showing the transaction properties per customer
OR
a table with fields - date, product(foreign), quantity - this way you'll have no problem with new products
Try multiple tables with links
table_products
id
name
table_product_sales
id
product_id
quantity
price_per
transaction_time AS DATETIME
SELECT table_product_sales.*, table_product.name
FROM table_product
JOIN table_product_sales
ON table_product_sales.product_id = table_product.id
GROUP BY DATE(transaction_time)
Haven't tried it but will something like that work? That allows you to keep each transactions separate so you can query things like average number sold per sale, total sold per date, total sales each day, etc.

Resources