Company will receive an invoice on the 1st and 16th every month. (It will run via Cron Job every 2 week. It scan through the order table and then add into 'invoice' table. Is there alternative?)
There are list of customers orders in the orders table and it also indicate which company it belong to (orders.company_id)
The invoice table calculate the total cost of the orders from orders table.
I am trying to figure it out how to design reasonable invoices tracking. Sometime company will have to send me the fees or sometime I send them the fees (invoice.amount)
I need to track the invoices with the following:
when the company have sent me the amount
when did I sent the amount to the company
how much amount has been received from the company
how much amount did I sent to the company
did I receive the full amount (if not, what do I need to update on the Db?)
invoice status (Invoice Sent, Cancelled, Amount Received, Amount Sent)
Here is the database design I have came up with:
company table
mysql> select * from company;
+----+-----------+
| id | name |
+----+-----------+
| 1 | Company A |
| 2 | Company B |
+----+-----------+
Customers can select a company from my website.
orders table
mysql> select * from orders;
+----+---------+------------+------------+---------------------+-----------+
| id | user_id | company_id | total_cost | order_date | status_id |
+----+---------+------------+------------+---------------------+-----------+
| 1 | 5 | 2 | 25.00 | 2012-02-03 23:30:24 | 1 |
| 2 | 7 | 2 | 30.00 | 2012-02-13 18:06:12 | 1 |
+----+---------+------------+------------+---------------------+-----------+
two customers have ordered the products from Company B (orders.company_id = 2). I know the orders fields is not enough, just simplified for you.
orders_products table
mysql> select * from orders_products;
+----+----------+------------+--------------+-------+
| id | order_id | product_id | product_name | cost |
+----+----------+------------+--------------+-------+
| 1 | 1 | 34 | Chair | 10.00 |
| 2 | 1 | 25 | TV | 10.00 |
| 3 | 1 | 27 | Desk | 2.50 |
| 4 | 1 | 36 | Laptop | 2.50 |
| 5 | 2 | 75 | PHP Book | 25.00 |
| 6 | 2 | 74 | MySQL Book | 5.00 |
+----+----------+------------+--------------+-------+
List of products what customers have ordered.
invoice table
mysql> select * from invoice;
+----+------------+------------+---------------------+--------+-----------+
| id | company_id | invoice_no | invoice_date | amount | status_id |
+----+------------+------------+---------------------+--------+-----------+
| 7 | 2 | 123 | 2012-02-16 23:59:59 | 55.00 | 1 |
+----+------------+------------+---------------------+--------+-----------+
This is where I am quite stuck on invoice tables design. I am not sure how it should be done. Invoices will be generated every 2 weeks. From the result example invoice.amount is 55.00 because it has been calculated from orders.company_id = 2 table
If the invoice.amount is -50.00 (minus), it mean company will need to send me the fees amount.
If the invoice.amount is 50.00, it mean I need to send the company the fees.
The status_id could be: (1)Invoice Sent, (2)Cancelled, (3)Completed
Do I need to add invoice_id field in the orders table? Update the orders.invoice_id field when row has been inserted into 'invoice' table.
invoice_payment table
mysql> select * from invoice_payment;
+----+------------+-----------------+-------------+---------------------+---------------------+
| id | invoice_id | amount_received | amount_sent | date_received | date_sent |
+----+------------+-----------------+-------------+---------------------+---------------------+
| 1 | 1 | 0.00 | 55.00 | 0000-00-00 00:00:00 | 2012-02-18 22:20:53 |
+----+------------+-----------------+-------------+---------------------+---------------------+
This is where I can track and update transaction.. the payment will be made via BACS.
Is this good tables design or what do I need to improve? What fields and tables I should add?
If the invoice has been generated and later I need to make the changes in orders_products or orders tables - should it recalculate the invoice.amount field? (I will be using PHP / MySQL).
SQL Dump:
CREATE TABLE IF NOT EXISTS `company` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(25) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=3 ;
INSERT INTO `company` (`id`, `name`) VALUES
(1, 'Company A'),
(2, 'Company B');
CREATE TABLE IF NOT EXISTS `invoice` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`company_id` int(11) NOT NULL,
`invoice_no` int(11) NOT NULL,
`invoice_date` datetime NOT NULL,
`amount` decimal(6,2) NOT NULL,
`status_id` tinyint(1) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=8 ;
INSERT INTO `invoice` (`id`, `company_id`, `invoice_no`, `invoice_date`, `amount`, `status_id`) VALUES
(7, 2, 123, '2012-02-16 23:59:59', '55.00', 1);
CREATE TABLE IF NOT EXISTS `invoice_payment` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`invoice_id` int(11) NOT NULL,
`amount_received` decimal(6,2) NOT NULL,
`amount_sent` decimal(6,2) NOT NULL,
`date_received` datetime NOT NULL,
`date_sent` datetime NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=2 ;
INSERT INTO `invoice_payment` (`id`, `invoice_id`, `amount_received`, `amount_sent`, `date_received`, `date_sent`) VALUES
(1, 1, '0.00', '55.00', '0000-00-00 00:00:00', '2012-02-18 22:20:53');
CREATE TABLE IF NOT EXISTS `orders` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`user_id` int(11) NOT NULL,
`company_id` int(11) NOT NULL,
`total_cost` decimal(6,2) NOT NULL,
`order_date` datetime NOT NULL,
`status_id` int(11) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=3 ;
INSERT INTO `orders` (`id`, `user_id`, `company_id`, `total_cost`, `order_date`, `status_id`) VALUES
(1, 5, 2, '25.00', '2012-02-03 23:30:24', 1),
(2, 7, 2, '30.00', '2012-02-13 18:06:12', 1);
CREATE TABLE IF NOT EXISTS `orders_products` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`order_id` int(11) NOT NULL,
`product_id` int(11) NOT NULL,
`product_name` varchar(100) NOT NULL,
`cost` decimal(6,2) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=7 ;
INSERT INTO `orders_products` (`id`, `order_id`, `product_id`, `product_name`, `cost`) VALUES
(1, 1, 34, 'Chair', '10.00'),
(2, 1, 25, 'TV', '10.00'),
(3, 1, 27, 'Desk', '2.50'),
(4, 1, 36, 'Laptop', '2.50'),
(5, 2, 75, 'PHP Book', '25.00'),
(6, 2, 74, 'MySQL Book', '5.00');
Feel free you want to updates/add tables to Answer here.
Thanks
Have a look at my add-on for Gemini - SimplyFi. It will allow you to brand your invoices accordingly, can auto email them to customers when they generated, can log payments and send reminders for payments not received (statements) and has a full REST based API you can use to integrate into your system. Also may be able to benefit off the recurring billing it features.
Where you mention negative invoice amounts, those are effectively "Credit Notes" (from what I've understood from your post). Generally, you should not be changing invoices themselves after they have been issued to a client - if you need to make amendments to an amount (ie: add on, or subtract off) then you should be issuing a new invoice (for added amount), or a credit note, for subtracted amount.
Also, I would suggest you don;t send the customer money back if they are going to receive a new invoice in a few weeks time, simply keep track of their account balance, and only issue invoices or credit notes when necessary. Moving money around costs money, and you don't need to do it if it's not necessary. Just my 2 cents
Related
I have four tables:
CREATE TABLE `A` (
`AID` bigint(20) NOT NULL AUTO_INCREMENT,
`Name` varchar(150) DEFAULT NULL,
PRIMARY KEY (`AID`)
);
CREATE TABLE `B` (
`BID` bigint(20) NOT NULL AUTO_INCREMENT,
`DtStart` datetime DEFAULT NULL,
`DtStop` datetime DEFAULT NULL,
`AID` bigint(20) DEFAULT NULL,
`CID` bigint(20) DEFAULT NULL,
PRIMARY KEY (`BID`)
);
CREATE TABLE `C` (
`CID` bigint(20) NOT NULL AUTO_INCREMENT,
`FLAGS` smallint(6) DEFAULT NULL,
PRIMARY KEY (`CID`)
);
CREATE TABLE `D` (
`DID` bigint(20) NOT NULL AUTO_INCREMENT,
`CID` bigint(20) DEFAULT NULL,
`Name` varchar(150) DEFAULT NULL,
PRIMARY KEY (`DID`)
);
I'm feeding data like this,
INSERT INTO A (Name) VALUES ("First");
INSERT INTO C (FLAGS) VALUES (1);
INSERT INTO B (DtStart, DtStop, AID, CID) VALUES ("2016-09-07", "2017-09-07", 1, 1);
INSERT INTO D (CID, Name) VALUES (1, "Alan");
INSERT INTO C (FLAGS) VALUES (2);
INSERT INTO B (DtStart, DtStop, AID, CID) VALUES ("2016-09-15", "2017-09-23", 1, 2);
INSERT INTO D (CID, Name) VALUES (2, "John");
When I hit the query:
SELECT
A.Name as Object, B.DtStart, B.DtStop, C.FLAGS, D.Name as User
FROM A
LEFT JOIN B ON B.AID=A.AID
LEFT JOIN C ON C.CID=B.CID
LEFT JOIN D ON D.CID=C.CID
WHERE "2017-09-01" <= B.DtStop AND "2017-10-01" > B.DtStart;
I get the result:
+--------+---------------------+---------------------+-------+------+
| Object | DtStart | DtStop | FLAGS | User |
+--------+---------------------+---------------------+-------+------+
| First | 2016-09-07 00:00:00 | 2017-09-07 00:00:00 | 1 | Alan |
| First | 2016-09-15 00:00:00 | 2017-09-23 00:00:00 | 2 | John |
+--------+---------------------+---------------------+-------+------+
2 rows in set (0.00 sec)
How could I find all the rows which also include gaps for the given date range?
In my example, I'm looking for the report (Sep 1, 2017 to Sep 30, 2017) so I want result like this:
+--------+---------------------+---------------------+-------+------+
| Object | DtStart | DtStop | FLAGS | User |
+--------+---------------------+---------------------+-------+------+
| First | 2016-09-07 00:00:00 | 2017-09-07 00:00:00 | 1 | Alan |
| First | 2017-09-08 00:00:00 | 2017-09-14 00:00:00 | NULL | NULL |
| First | 2016-09-15 00:00:00 | 2017-09-23 00:00:00 | 2 | John |
| First | 2016-09-24 00:00:00 | 2017-09-30 00:00:00 | NULL | NULL |
+--------+---------------------+---------------------+-------+------+
4 rows in set (0.00 sec)
This is just models of my original tables, I have multiple joins over 10 tables in my query
When should one create a new table in a database and use new ids? Example in a database for tickets for concerts, should I create a new table for each concert then delete it afterwards?
Keeping all the tickets in one database with unique ID's for each does not sound like a scalable solution.
This is a theory question rather than a practical coding question.
Here is a sample example of how you could do this in a relational pattern:
SCHEMA:
Table: USER
+---------------+-------------------+---------------+
| UserID | First Name | Last Name |
+---------------+-------------------+---------------+
| 1 | John | Doe |
|---------------|-------------------|---------------|
| 2 | Jane | Doe |
+---------------+-------------------+---------------+
Table: CONCERT
+---------------+-------------------+-----------+---------------+
| ConcertID | Concert Name | Artist | Date |
+---------------+-------------------+-----------+---------------+
| 1 | Rock Concert | Rob | Jan-1-2014 |
|---------------|-------------------|-----------|---------------|
| 2 | Rap Concert | Jay | Feb-3-2014 |
+---------------+-------------------+-----------+---------------+
Table: TICKET
+-----------+---------------+---------------+
| UserID | ConcertID | Quantity |
+-----------+---------------+---------------+
| 1 | 1 | 1 |
|-----------|---------------|---------------|
| 1 | 2 | 3 |
|-----------|---------------|---------------|
| 2 | 1 | 2 |
+-----------+---------------+---------------+
Raw SQL to create above schema:
CREATE TABLE USER (
`UserID` int unsigned primary key,
`First Name` varchar(4) not null,
`Last Name` varchar(3) not null
) engine=innodb charset=utf8;
INSERT INTO USER
(`UserID`, `First Name`, `Last Name`)
VALUES
(1, 'John', 'Doe'),
(2, 'Jane', 'Doe')
;
CREATE TABLE CONCERT (
`ConcertID` int unsigned primary key,
`Concert Name` varchar(12) not null,
`Artist` varchar(3) not null,
`Date` datetime not null
) engine=innodb charset=utf8;
INSERT INTO CONCERT
(`ConcertID`, `Concert Name`, `Artist`, `Date`)
VALUES
(1, 'Rock Concert', 'Rob', '2014-01-01 00:00:00'),
(2, 'Rap Concert', 'Jay', '2014-02-03 00:00:00')
;
CREATE TABLE TICKET (
`Ticket No` int unsigned primary key auto_increment,
`UserID` int unsigned,
`ConcertID` int unsigned,
Foreign Key(`UserID`) references `USER`(`UserID`),
Foreign Key(`ConcertID`) references `CONCERT`(`ConcertID`)
) engine=innodb charset=utf8;
INSERT INTO TICKET
(`Ticket No`, `UserID`, `ConcertID`)
VALUES
(1, 1, 1),
(2, 1, 2),
(3, 2, 1)
;
You need to break apart your tables in such a way that you have one-to-one or one-to-many relationships without having a many-to-many relationship. By using a simple three table setup as described above, one user can purchase multiple tickets to multiple concerts. However, because of the itermediary table TICKET, we are never left with a many-to-many relationship. This also allows us to maintain referential integrity by tying the UserID in the TICKET table to the UserID in the USER table. In addtion, the ConcertID in the TICKET table to the ConcertID in the CONCERT table.
Finally, we are able to generate some simple queries to pull back information we need by joining the tables together. I've included two sample queries below:
SAMPLE QUERY #1 - Retrieve all tickets of a particular user by first and last name
SELECT
`conc`.`Concert Name`,
`conc`.`Artist`,
`conc`.`Date`,
`tick`.`Ticket No`
FROM `CONCERT` AS `conc`
INNER JOIN `TICKET` AS `tick` ON `conc`.`ConcertID` = `tick`.`ConcertID`
INNER JOIN `USER` AS `user` ON `tick`.`UserID` = `user`.`UserID`
WHERE `user`.`First Name` = "John" AND `user`.`Last Name` = "Doe";
Result:
+--------------------+--------------+---------------------------------+-----------------+
| Concert Name | Artist | Date | Ticket No |
+--------------------+--------------+---------------------------------+-----------------+
| Rock Concert | Rob | January, 01 2014 00:00:00+0000 | 1 |
|--------------------|--------------|---------------------------------|-----------------|
| Rap Concert | Jay | February, 03 2014 00:00:00+0000 | 2 |
+--------------------+--------------+---------------------------------+-----------------+
SAMPLE QUERY #2 - Retrieve total number of tickets for a given concert by artist name
SELECT
COUNT(`tick`.`Ticket No`)
FROM `TICKET` as `tick`
INNER JOIN `CONCERT` AS `conc` ON `tick`.`ConcertID` = `conc`.`ConcertID`
WHERE `conc`.`Artist` = "Rob";
Result:
+--------------------+
| Ticket Count |
+--------------------+
| 2 |
+--------------------+
As an extra note, because we are using foreign key constraints, we have indexes defined on the particular columns. This helps SQL better manage and scale the queries/data leading to continued performance even with large numbers (millions) of rows.
Hope this helps. From here, you should be able to develop a lot of different queries to pull back all the information you desire. An exact working demo of the above code can be found below:
DEMO: sqlfiddle.com
A compromise solution to this would be to create a new table in the same database for each concert, and to delete tables if there are space concerns. This would allow you to keep old data around without cluttering one table too much.
I have designed database tables of Mobile Phones & Tariffs.
It should support multiple mobile networks, sale type and the related affiliate.
Points (for operators) are vary depending on the selected phone, tariff, network and sale Type.
Example Price Plans:
T-Mobile: Consumer Upgrade
Samsung Galaxy S3
Tariff: Super One (Monthly Cost: $12.00)
This sale affiliate with 'Retailer One'
Total Point: 3.3
T-Mobile: Consumer New Connection
Samsung Galaxy S3
Tariff: Super One (Monthly Cost: $35.00)
This sale affiliate with 'Retailer Two'
Total Point: 7.3
AT&T: 'Sim Only Deal' (Without Phone)
Tariff: X-Deal Two (Monthly Cost: $18.00)
This sale affiliate with 'Retailer One'
Total Point: 10.0
See the tables design below, is this how it should be done? or how can it be improved?
Database Design:
CREATE TABLE IF NOT EXISTS `affiliate` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(50) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=3 ;
INSERT INTO `affiliate` (`id`, `name`) VALUES
(1, 'Retailer One'),
(2, 'Retailer Two');
CREATE TABLE IF NOT EXISTS `network` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(20) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=3 ;
INSERT INTO `network` (`id`, `name`) VALUES
(1, 'T-Mobile'),
(2, 'AT&T');
CREATE TABLE IF NOT EXISTS `network_saletype` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`network_id` int(11) NOT NULL,
`saletype_id` int(11) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=3 ;
INSERT INTO `network_saletype` (`id`, `network_id`, `saletype_id`) VALUES
(1, 1, 1),
(2, 2, 3);
CREATE TABLE IF NOT EXISTS `phone` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(50) NOT NULL,
`description` varchar(150) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=3 ;
INSERT INTO `phone` (`id`, `name`, `description`) VALUES
(1, 'Samsung Galaxy S3', ' Quad-core, NFC, AMOLED'),
(2, 'Apple iPhone 4S', 'A5 chip, 8MP camera, Siri voice');
CREATE TABLE IF NOT EXISTS `phone_points` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`phone_id` int(11) NOT NULL,
`tarrif_id` int(11) NOT NULL,
`affilicate_id` int(11) NOT NULL,
`point` float NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=3 ;
INSERT INTO `phone_points` (`id`, `phone_id`, `tarrif_id`, `affilicate_id`, `point`) VALUES
(1, 1, 1, 1, 3.3),
(2, 1, 2, 2, 7.3);
CREATE TABLE IF NOT EXISTS `saletype` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(50) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=4 ;
INSERT INTO `saletype` (`id`, `name`) VALUES
(1, 'Consumer Upgrade'),
(2, 'Consumer New Connection'),
(3, 'Sim-Only Deal');
CREATE TABLE IF NOT EXISTS `tariff_point` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`tarrif_id` int(11) NOT NULL,
`affilicate_id` int(11) NOT NULL,
`point` float NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=4 ;
INSERT INTO `tariff_point` (`id`, `tarrif_id`, `affilicate_id`, `point`) VALUES
(3, 3, 1, 10);
CREATE TABLE IF NOT EXISTS `tarrif` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`network_saletype_id` int(11) NOT NULL,
`name` varchar(50) NOT NULL,
`tariff_duration` int(11) NOT NULL,
`monthly_cost` decimal(6,2) NOT NULL,
`description` varchar(150) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=4 ;
INSERT INTO `tarrif` (`id`, `network_saletype_id`, `name`, `tariff_duration`, `monthly_cost`, `description`) VALUES
(1, 1, 'Super One', 12, '12.00', '200 Mins, 400 Texts, 500MB Internet'),
(2, 1, 'Super One', 12, '35.00', '200 Mins, 400 Texts, 500MB Internet'),
(3, 2, 'X-Deal Two', 12, '18.00', '');
Result
mysql> select * from network;
+----+----------+
| id | name |
+----+----------+
| 1 | T-Mobile |
| 2 | AT&T |
+----+----------+
mysql> select * from affiliate;
+----+--------------+
| id | name |
+----+--------------+
| 1 | Retailer One |
| 2 | Retailer Two |
+----+--------------+
mysql> select * from saletype;
+----+-------------------------+
| id | name |
+----+-------------------------+
| 1 | Consumer Upgrade |
| 2 | Consumer New Connection |
| 3 | Sim-Only Deal |
+----+-------------------------+
mysql> select * from network_saletype;
+----+------------+-------------+
| id | network_id | saletype_id |
+----+------------+-------------+
| 1 | 1 | 1 |
| 2 | 2 | 3 |
+----+------------+-------------+
mysql> select * from tarrif;
+----+---------------------+------------+-----------------+--------------+-------------------------------------+
| id | network_saletype_id | name | tariff_duration | monthly_cost | description |
+----+---------------------+------------+-----------------+--------------+-------------------------------------+
| 1 | 1 | Super One | 12 | 12.00 | 200 Mins, 400 Texts, 500MB Internet |
| 2 | 1 | Super One | 12 | 35.00 | 200 Mins, 400 Texts, 500MB Internet |
| 3 | 2 | X-Deal Two | 12 | 18.00 | |
+----+---------------------+------------+-----------------+--------------+-------------------------------------+
mysql> select * from tariff_point;
+----+-----------+---------------+-------+
| id | tarrif_id | affilicate_id | point |
+----+-----------+---------------+-------+
| 3 | 3 | 1 | 10 |
+----+-----------+---------------+-------+
mysql> select * from phone;
+----+-------------------+---------------------------------+
| id | name | description |
+----+-------------------+---------------------------------+
| 1 | Samsung Galaxy S3 | Quad-core, NFC, AMOLED |
| 2 | Apple iPhone 4S | A5 chip, 8MP camera, Siri voice |
+----+-------------------+---------------------------------+
mysql> select * from phone_points;
+----+----------+-----------+---------------+-------+
| id | phone_id | tarrif_id | affilicate_id | point |
+----+----------+-----------+---------------+-------+
| 1 | 1 | 1 | 1 | 3.3 |
| 2 | 1 | 2 | 2 | 7.3 |
+----+----------+-----------+---------------+-------+
Edit: My question was is the relationship design between phone, tarrif, network and saleType is ok? Basically operator can select a retailer which then select Mobile Network.. then select what type of sale (eg: consumer upgrade) and then select phone with related related tariffs. Depending what tarrifs and/or phone they have selected - operator gets number of points.
This table implies that it's ok for 2 or 5 or 1,847 affiliates to have the same name.
CREATE TABLE IF NOT EXISTS `affiliate` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(50) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=3 ;
These inserts will work. They probably shouldn't.
INSERT INTO `affiliate` (`id`, `name`) VALUES
(1, 'Retailer One'),
(2, 'Retailer One'),
(3, 'Retailer One'),
(4, 'Retailer One'),
(5, 'Retailer One');
The problem is that, while you've defined a meaningless (surrogate) integer as a primary key, you haven't defined what that thing is a surrogate for. All those tables should have a unique constraint on some combination of columns besides the surrogate ID number.
You've also defined no foreign keys at all. This is almost certainly a mistake.
When insert statements like this succeed, you've got work to do.
insert into phone_points values (1078, 3000, 2743, 10234, -33344.03);
Example table content
'main'
| id | total |
| 1 | 10 |
| 2 | 20 |
'timed'
| id | id_main | date_from | date_to | total |
| 1 | 2 | 2012-03-29 | 2012-04-29 | 50 |
Desired result
| id | total |
| 1 | 10 |
| 2 | 50 |
Not exactly working query
SELECT main.id AS id, COALESCE(timed.total, main.total) AS total
FROM main
LEFT JOIN timed
ON main.id = timed.id_main
WHERE SYSDATE() BETWEEN timed.date_from AND timed.date_to
Result
| id | total |
| 2 | 50 |
In tables 'main' and 'timed' 'total' field will never be NULL.
In some 'timed' records there will be no relative 'id_main', or there will be few, but they will differ, 'date_from' 'date_to' never intersect.
Table 'main' is large, but in 'timed' will always be two or three relative records.
CREATE TABLE `main` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`total` decimal(10,2) unsigned NOT NULL DEFAULT '0.00',
PRIMARY KEY (`id`)
) ENGINE=InnoDB;
INSERT INTO `main` VALUES (1,10);
INSERT INTO `main` VALUES (2,20);
CREATE TABLE `timed` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`id_main` int(11) unsigned NOT NULL DEFAULT '0',
`date_from` date DEFAULT NULL,
`date_to` date DEFAULT NULL,
`total` decimal(10,2) unsigned NOT NULL DEFAULT '0.00',
PRIMARY KEY (`id`),
KEY `link` (`id_main`)
) ENGINE=InnoDB;
INSERT INTO `timed` VALUES (1,2,'2012-03-29','2012-03-30',50);
ALTER TABLE `timed`
ADD CONSTRAINT `link` FOREIGN KEY (`id_main`)
REFERENCES `main` (`id`) ON DELETE CASCADE ON UPDATE CASCADE;
Sorry for my english.
You should move the date condition in the join condition:
SELECT main.id AS id, COALESCE(timed.total, main.total) AS total
FROM main
LEFT JOIN timed
ON main.id = timed.id_main and SYSDATE() BETWEEN timed.date_from AND timed.date_to
In your query, those rows not matched are filtered out by the WHERE condition because timed.date_form and timed.date_to are null, so sysdate can't be between them :)
An invoice can contain 1 or more orders, how to archive this?
Example of Invoice:
OrderID | Order Date | Amount
31 10/02/2011 £1.50
43 12/02/2011 £1.50
74 13/02/2011 £5.00
=======
Total £8.00
If the Total is minus (eg: -8.00), it mean client owes me money.
Without minus, I pay client some money.
Here what I came up with:
Orders Table
CREATE TABLE IF NOT EXISTS `orders` (
`OrderID` int(11) NOT NULL AUTO_INCREMENT,
`Total` decimal(6,2) NOT NULL,
`OrderDate` datetime NOT NULL,
`Status` int(11) NOT NULL,
`userID` int(11) NOT NULL,
`InvoiceID` int(11) NOT NULL,
PRIMARY KEY (`OrderID`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=4 ;
Invoice Table
CREATE TABLE IF NOT EXISTS `invoice` (
`InvoiceID` int(11) NOT NULL DEFAULT '0',
`InvoiceDate` datetime NOT NULL,
`Amount` decimal(6,2) NOT NULL,
`Status` int(11) NOT NULL,
PRIMARY KEY (`InvoiceID`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
invoice.Status (0 Processing, 1 Invoice Sent, 2 Cancelled, 3 Completed)
or what better status can be?
Payment Table
CREATE TABLE IF NOT EXISTS `payment` (
`PaymentID` int(11) NOT NULL AUTO_INCREMENT,
`InvoiceID` int(11) NOT NULL,
`Amount` decimal(6,2) NOT NULL,
`DatePayment` datetime NOT NULL,
`PaymentType` int(11) NOT NULL,
PRIMARY KEY (`PaymentID`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;
payment.PaymentType = (1: Payment Received From Customer (Owes Money), 2: Payment Sent To Customer)
Database Result:
mysql> select * from orders;
+---------+-------+---------------------+--------+--------+-----------+
| OrderID | Total | OrderDate | Status | userID | InvoiceID |
+---------+-------+---------------------+--------+--------+-----------+
| 1 | 20.00 | 2011-06-18 15:51:51 | 1 | 123 | 1 |
| 2 | 10.00 | 2011-06-19 15:51:57 | 1 | 123 | 1 |
| 3 | 5.00 | 2011-06-20 15:52:00 | 1 | 123 | 1 |
+---------+-------+---------------------+--------+--------+-----------+
mysql> select * from invoice;
+-----------+---------------------+--------+--------+
| InvoiceID | InvoiceDate | Amount | Status |
+-----------+---------------------+--------+--------+
| 1 | 2011-06-30 15:55:21 | 35.00 | 1 |
+-----------+---------------------+--------+--------+
mysql> select * from payment;
+-----------+-----------+--------+---------------------+-------------+
| PaymentID | InvoiceID | Amount | DatePayment | PaymentType |
+-----------+-----------+--------+---------------------+-------------+
| 1 | 1 | 35.00 | 2011-06-29 15:56:16 | 1 |
+-----------+-----------+--------+---------------------+-------------+
Im I on the right path? What can be improved/changed or suggestion?
Thanks.
Ok, you have some serious issues here. Orders have mulitple items, invoices have multiple orders and payments may apply to mulitple orders and invoices. Orders may appear on multiple invoices (if they don't pay right aways which is common).
So what you need are linking tables. You should start with an ORDERINVOICE table which has both the order id and the invoice ID. Then an ORDERPAYMENT table with paymentid and Order id.
You also need to consider that in an ordering situation, you must record the details of the order as it occurred at the time. That means that while you should have the user_id to link to the current user, you should record the user's name, billing address and shipping addres as it was at the time of the order. You will need this information later to deal with any questions on the order. Further you need to ensure that you store the details of the order in a separate table called ORDERDETAILS which store the indivdual line items, the price at the time of the order and the name of the item ordered. You will need this for accounting reasons. You do not under any cuircumstances want to rely on a join to a product table to figure out the price of an order in the past. This will cause your finanacial records to be inaccurate.
Looks good.
The only thing I would add are some details like transaction id / check number to the payment table. This way you keep all the payment details together.
It looks alright to me, this is what i would have done aswell.
(I would think a payment is linked with an order, but if you intended to link it to an invoice this is fine)
Regards,
MN
Without knowing more about your requirements, so far so good.
Be sure to store your Invoice Status and Payment Type decodes in a lookup table so that they can be enforced in the database and don't have to rely on programmers coding it correctly.