0

I'm working on a Desktop application that uses a DB to store information i.e (customers, houses, proprietors, payments). So the application must accept payments from customers to company, company to customers(in case of a refund), company to proprietor, proprietor to company. At this moment i'm thinking about this Payments table(there is more columns like dates, quantity).

| id            | int(11)     | NO   | PRI | NULL    | auto_increment |

| type          | varchar(20) | YES  |     | NULL    |                |

| reference_id  | int(11)     | YES  |     | NULL    |                |

With this table i was going to use id as the unique payment id, type to tell if it's a payment from company, proprietor, customer,etx.. and the reference_id is the unique id of the proprietor, customer, etx (the reason i store a reference_id is to find all the payments sent or received to that person)

For some reason it feels like an ugly design not only because i'm not using many-to-many relationship but also it gets kinda tricky to fetch data because you have to specify the type.

What would be a better design?

5
  • can u share the tables for customers, houses, proprietors which you have created...
    – Karthick
    Commented Jul 31, 2014 at 4:00
  • Hi Karthick, i don't have access to the DB atm but i can describe it to you, it doesn't have relationship with other tables or columns i.e Customers(id, name, phone, email), Houses(id, address, price, have_pool)Propietors(pretty much the same as customers), the application is on C# and it uses LINQ, also there is a web interface on PHP.
    – Eduardo
    Commented Jul 31, 2014 at 4:36
  • I suggest researching Cash Receipts Journal in any bookkeeping or introductory accounting resource. Failing to align with basic double-entry bookkeeping practice will only cause you grief and heartache. Commented Aug 1, 2014 at 12:33
  • Note that double-entry bookkeeping has evolved over the last 800+ years to be a completely normalized and fully parallelizable design, with each Journal/Ledger pair being managed by a single clerk in a large accounting office, with the General Ledger itself being managed by the Controller. I put forward that when an accounting system deviates from historical bookkeeping practice it automatically is a denormalization, by virtue of that deviation.. Commented Aug 1, 2014 at 12:52
  • @PieterGeerkens Thanks for your suggestion i will definitely read about double-entry bookkeeping, in fact i already started ;)
    – Eduardo
    Commented Aug 1, 2014 at 18:41

2 Answers 2

0

A better design would be to have a single table to hold all the parties to a payment. If necessary, sub-type this table so companies, proprietors and customers have their own, unique sets of columns (or a separate, related table).

The payments table will then have two foreign keys to Parties, let's call them PaymentFromPartyID and PaymentToPartyID, along with amount, date etc. This way all permutations of money transfer can be tracked.

To find all the monies a person has received use

select
    sum(p.Amount)
from Payments as p
inner join Parties as y
    on y.PartyID = p.PaymentToPartyID
where y.Name = 'The person/company/proprietor of interest';

Additional Detail

A party is anyone or anything who has in interest in a payment. This would be a proprietor, customer or company, distinguished by a type:

Parties(
    PartyID
    PartyName
    PartyType     -- customer or company or proprietor
    <customer-fields>
    <proprietor-fields>
    <company-fields>)

A payment relates a payer (of any type) to a payee (of any type):

Payments(
    PaymentFromPartyID  -- FK to Parties.PartyID
    PaymentToPartyID    -- FK to Parties.PartyID
    Amount
    Date
    etc.)

The IDs used in From and To says in which direction the money flows. There is no need to have any information about a party in the Payments table, such as a type, other than the two PartyIDs.

To get all the payments made to customers (for example) add Parties.PartyType = 'Customer' to the query given above.

The Payments_Track table you list has all the attributes I list here (bar a few surrogate IDs) but is normalised.

3
  • Hi Michael, i don't get what to store into the Parties table. or do you mean that i should add a foreignkey for every party? i.e PaymentFromCustomer, PaymentToCustomer, PaymentToProprietor, etx.. so that would make it for 6 new columns on Payments table.
    – Eduardo
    Commented Aug 1, 2014 at 1:37
  • I realized that i can make a table that holds a reference from-to with a type, like this, Table Payments_Track (id INT PK, PaymentId INT, PaymentFrom INT, PaymentTo INT, type_of_from varchar(20), type_of_to varchar(20)) so if i know is a Customer type, i can query like this SELECT * FROM Payments AS p INNER JOIN Payments_Track AS pt ON pt.PaymentId = p.id WHERE pt.type_of_from = 'Customer' , so i get all payments made from customers and can refine adding more WHERE clauses, is this approach close to your suggestion? thanks again for your time
    – Eduardo
    Commented Aug 1, 2014 at 2:17
  • Hi Michael, thanks for your explain i think i have a clear idea now, i also want to add the id of that individual (customer,propietor, etx..) on the Parties table so i can localize specific ones, i wanted to avoid creating multiple entries for 1 payment (3 in this case 2 parties, 1 payment) but it will probably be for the best.
    – Eduardo
    Commented Aug 2, 2014 at 18:15
0

First create a table for reference id if it does not exist

| ref_id            | int(11)     | NO   | PRI | NULL    | auto_increment |
| reference_id      | int(11)     | YES  |     | NULL    |                |

then create another table to store the types

| type_id            | int(11)     | NO   | PRI | NULL    | auto_increment |
| type               | varchar(20) | YES  |     | NULL    |                |

create another table to match the type with the reference

| id               | int(11)     | NO   | PRI | NULL    | auto_increment |
| type_id          | int(11)     | YES  |     | NULL    |                |
| ref_id           | int(11)     | YES  |     | NULL    |                |

This way, you can easily add more types in the future, get the list if available types too. Makes it neat and kinda organised.

2
  • Hi Toniton thanks for taking your time on this, it looks better but with this design isn't the purpose to have a many-to-many relationship why do i need the first 2 tables then?.
    – Eduardo
    Commented Aug 1, 2014 at 1:49
  • 1) your query wont be too tricky 2) it's easier to understand the database 3) you can introduce more types easily in the future 4)in case you need to get the types, let's say during a registration or assign a type to a user you just fetch the types from the type table. 5)your query would be faster. *note that now you are dealing with the integers mapping the both them... 6)for sake of documentation 7) this is the standard way i always come across in books tooo, btw it's still a many-may relationship
    – Toniton
    Commented Aug 1, 2014 at 8:58

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.