Consider these two use cases.
Say a store gives out store credit for customers. Store credit come from refunds, discounts, overpaying amounts etc...
The customer decides how and when to
use this credit. E.g. Say customer A
have $50 dollars in store credit and
he decides to use $25 for invoice A
and $25 for invoice B... or decides
to have the store credit sitting
there against his account for future
purchases.
The customer and store must also
have a way to look up the total of
store credit.
What is the easiest and most straight forward way to cater for this in table structure?
I currently have tables:
Transaction (For journal and reporting purpose)
Customer
Credit
Used Credit
Invoice table will have other associations like invoice lines, receipt, receipt lines etc...
Is this the best way to do this? My concern is primarily regarding ease of reporting and transaction mechanics.
Alternatively I'm considering just saving all credit entry and used credit inside the transaction table.
Updated diagram for clarification and from inputs
Correct me if I'm wrong, but I believe you want something like this.
A Customer has CreditEntrys, and CreditEntrys have UsedCredites. There are also Transactions which include links to corresponding Invoice. And finally, a Transaction has links to many UsedCreditwhich were used during this transaction. If all CreditEntry was used at a time, then there will be one UsedCredit used with this Transaction, and this UsedCredit will correspond to the entire CreditEntry
The database schema would be quite straightforward here - relations through foreign keys. You would probably want to create an additional unique constraint to reflect ONE-TO-ONE relation between Transaction and Invoice
Oh, by the way, that service that you used for diagram creation is cool.
create 4 tables, 1 for customers then another for their credit and used credit and then another for transaction and invoice. You may join transaction and invoice since they may have similar data.
Related
I have a table with products that I offer. For each product ever sold, an entry is created in the ProductInstance table. This refers to this instance of the product and contains information such as the next due date (if the product is to be billed monthly) and other information relevant to this instance (e.g. personal branding).
For understanding: The products are service contracts. The template of the contract is stored in the product table (e.g. "Monthly lawn mowing"). The product instance is then e.g. "Monthly lawn mowing in sample street" and contains information like the size of the garden or something specific to this instance of the service instead of the general product.
An invoice is created for a product instance either one time or recurring. An Invoice may consists of several entries. Each entry is represented by an element in the InvoiceEntry table. This is linked to the ProductInstance to create the reference to the invoice.
I want to extend the database with purchase orders. To do this, a record is created in the Order table. This contains a relation to the customer and e.g. the order date. The single products of the order are mapped by an OrderEntry. The initial invoice generated for the order is linked via the field "invoice_id" in the table order. The invoice items from the initial order are created per OrderEntry and create one InvoiceEntry each. However, I want the ProductInstance to be created only after the invoice is paid. Therefore the OrderEntry has a relation to the product and not only to the ProductInstance. Once the order has been created, the instance is created and linked to the OrderEntry.
I see the problem that the relation between Order and Invoice is doubled: once Order <-> Invoice and once Order <-> OrderEntry <-> InvoiceEntry <-> Invoice.
And for the Product: OrderEntry <-> Product and OrderEntry <-> ProductInstance <-> Product.
Model of the described database
My question is if this "duplicate" relation is problematic, or could cause problems later. One case that feels messy to me is, what should I do if I want to upgrade the ProductInstance later (to an other product [e.g. upgrade to bigger service])? The order would still show the old product_id but the instance would point to a new product_id.
This is a nice example of real-life messy requirements, where the 'pure' theory of normalisation has to be tempered by compromises. There's no 'slam-dunk right' approach; there's some definitely 'wrong' approaches -- your proposed schema exhibits some of those. I suspect there's not even a 'best' approach. Thank you for expanding the description of the business context -- especially for the ProductInstance table.
But still your description won't support legally required behaviour:
An invoice is created for a product instance either one time or recurring. An Invoice may consists of several entries. Each entry is represented by an element in the InvoiceEntry table.
... I want the ProductInstance to be created only after the invoice is paid.
An invoice represents an indebtedness from customer to supplier. It applies at one date only, not "recurring". (So leaving out the Invoice date has exactly got in the way of you "thinking about relations".) A recurring or cyclical billing arrangement would be represented by something like a 'contract' table, from which an Invoice is generated by some scheduled process.
Or ... your "recurring" means the invoice is paid once up-front for a recurring service(?) Still you need an Invoice date. The terms of service/its recurrence would be on the ProductInstance table.
I can see no merit in delaying recording the ProductInstance 'til after invoice payment. Where are you going to hold the terms of service in the meantime? If you're raising an invoice, your auditors/the statutory authorities will want you to provide records of what the indebtedness relates to. Create ProductInstance ab initio and put a status on it. (Or in the application look up the Invoice's paid status before actually providing the service.)
There's something else about Invoices you're currently failing to capture -- and that has also lead you to a wrong design: in general there is more making up the total $ value of an invoice than product lines, such as discounts applying to the invoice overall rather than particular products; delivery charges; installation costs or inspection/certification; taxes (local/State/Federal).
From your description perhaps the only one applying is taxes. ("in this world nothing can be said to be certain, except death and taxes.") And taxes are not specific to products/no product_instance_id is applicable on an InvoiceEntry.
For this reason, on ERP schemas in general, there is no foreign key declared from InvoiceEntry to Product/Instance. (In your case you might get away with product_instance_id being nullable, but yeuch.) There might be a system-generated XRef text column, which contains different content according to what the InvoiceEntry represents, but any referencing can't be declared to the schema. (There might be a 'fully normalised' way to represent that with an auxiliary linkage table, but maintaining that in step adds too much complexity to the application.)
I see the problem that the relation between Order and Invoice is doubled: once Order <-> Invoice and once Order <-> OrderEntry <-> InvoiceEntry <-> Invoice.
Again think about the business sequence of operations that generate these records: ordering happens as a prelude to invoicing. You can't put an invoice_id on Order, because you haven't created the Invoice yet. You might put the order_id on Invoice. But here you're again in the situation that not all Invoices arrive via Orders -- some might be cash sales/immediate delivery. (You could make order_id nullable, but yeuch.) For this reason on ERP schemas in general, there is no foreign key declared from Invoice to Order, etc, etc.
And the same thinking with OrderEntry <-> InvoiceEntry: your proposed schema has the sequencing wrong/the reference points the wrong way. (And not every InvoiceEntry will have corresponding OrderEntry.)
On OrderEntry, having all of (OrderEntry)id and product_id and product_instance_id seems to me to give you way too many opportunities for tangling it all up. Can an Order have multiple Entrys for the same product_id? -- why/how? Can it have multiple Entrys for the same product_instance_id? -- why/how? Can there be a product_instance_id which refers to a different product_id than OrderEntry.product_id? This is exactly the sort of risk for confusing entanglement that normalisation aims to remove/reduce.
The customer is ordering a ProductInstance: mowing a particular size of garden at a particular address, fortnightly on a Tuesday afternnon. So OrderEntry.product_instance_id is what you want; .product_id is wrong. So (again) you need to create ProductInstance at time of recording the Order. Furthermore I strongly suspect you don't need an id on OrderEntry; instead give it a compound key (order_entry_id, product_instance_id). [**]
[**] I see you're using 'eloquent'. I suspect this is requiring id on every table. So you're not even using a relational database, this is some sort of Object-Relational hybrid. Insisting on a dedicated single id as key on every table is toxic. It has lead schema designers astray every time I get called in to help -- as here. Please if you can at all avoid it, don't do that.
System has many users belongs to a company. Admin user of the company can entry customers and each customer may have invoices with payment amount. The customer invoice amount need to be paid and should be inserted in double entry system in transaction master table.
Data Models are followings:
User
Company
Customer
Invoice
Transaction Master
My initial approach will be:
Company will have a one to many relationship with users
in invoice table, the details will be saved.
My questions are:
Do I need to create any relationship between customers and invoices tables?
How the transaction master table will be created? (double entry system refers to have debit and credit accounts, that's all my knowledge)
Yes, you need to create a relationship between customers and invoices table. Every invoice will have one customer. Every customer will have none, one, or many invoices. You will need a unique identifier to be stored in each file.
Transaction file is a much deeper subject. I assume you mean Ledger Transactions. Generally you will group a transaction with one or more debit entries matched with one or more credit entries with an associated reference number which will point to the invoice transaction. You would group references in a batch, usually called a session, and assign a session number at batch posting time which would have the post date.
These are the basic minimum answers to a very vague question on a potentially complex subject, but hopefully it will help get you started in the right direction for further research.
Here is the pic -->
Shouldn't the sales_rep_id attribute be in the orders table instead of the accounts table?
Usually, if there is a table for customer and another for seller, I see their FK's meet in order table.
And with this ERD, if a sales_rep has been changed with a new one, and we wanted to see every sales_rep with his orders, will the old sales_rep appear with his old orders, or his old orders will belong to the new rep?
Like this
Yes, you're raising important issues.
It's hard to really say one ERD is always right or wrong - we need to keep the goals in mind.
With the diagram you shared, you do have the problem you talk about.
By only having one Sales Rep for an Account, if the Sales Rep changes, you lose the historical record of who was the Sales Rep for orders before the change; the new Sales Rep will indeed be connected to every order, past and present.
So indeed you might want to put the Sales Rep in the Orders table.
BUT... how will you connect the Sales Rep to the Account then?
Does that relationship exist? What tables will we use for that relationship? A new table just for associating Account_Id, Current_Sales_Rep_Id?
If we step back and think further, we could even say that the ERD you shared is correct, and that any time the Sales Rep changes we have a new Account.
This would also avoid the problem of "erasing" the past Sales Rep.
It's always a question of knowing what is correct for the entities you're modeling.
But, if you're not sure exactly what the system needs, don't forget the fundamentals of Normalization.
Highly Normalized data designs protect you from data loss such as this Sales Rep issue.
Here are a couple SO pages with lots of info on Normalization, if you need it:
What are database normal forms, how can you easily apply them and can you give examples?
Database Normalization
This is an problem about drawing ERD in one of my course:
A local startup is contemplating launching Jungle, a new one stop
online eCommerce site.
As they have very little experience designing and implementing
databases, they have asked you to help them design a database for
tracking their operations.
Jungle will sell a range of products, and they will need to track
information such as the name and price for each. In order to sell as
many products as possible, Jungle would like to display short reviews
alongside item listings. To conserve space, Jungle will only keep
track of the three most recent reviews for each product. Of course, if
an item is new (or just unpopular), it may have less than three
reviews stored.
Each time a customer buys something on Jungle, their details will be
stored for future access. Details collected by Jungle include
customer’s names, addresses, and phone numbers. Should a customer buy
multiple items on Jungle, their details can then be reused in future
transactions.
For maximum convenience, Jungle would also like to record credit card
information for its users. Details stored include the account and BSB
numbers. When a customer buys something on Jungle, the credit card
used is then linked to the transaction. Each customer may be linked to
one or more credit cards. However, as some users do not wish to have
their credit card details recorded, a customer may also be linked to
no credit cards. For such transactions, only the customer and product
will be recorded.
And this is the solution:
The problem is the Buys action connect with 3 others entities: Product, Customer, and Card. I find this very hard to read and understand.
Is an action involving more than 2 entities common in production? If it is, how should I understand and use it? Or if it's not, what is the better way of design for this problem?
While the bulk of relationships in practice are binary relationships, ternary and higher relationships are normal elements of the entity-relationship model. Some examples are supplies (supplier_id, product_id, region_id) or enrolled (student_id, course_id, semester_id). However, they often get converted into entity sets via the introduction of a surrogate identifier, due to dislike of composite keys or confusion with network data models in which only directed binary relationships are supported.
Reading cardinality indicators on non-binary relationships are a common source of confusion. See my answer to designing relationship between vehicle,customer and workshop in erd diagram for more info on how I handle this.
Your solution has some problems. First, Buys is indicated as an associative entity, but is used like a ternary relationship with an optional role. Neither is correct in my opinion. See my answer to When to use Associative entities? for an explanation of associative entities in the ER model.
Modeling a purchase transaction as a relationship is usually a mistake, since relationships are identified by the (keys of the) entities they relate. If (CustomerID, ProductID) is identifying, then a customer can buy a product only once, and only one product per transaction. Adding a date/time into the relationship's key is better, but still problematic. Adding a surrogate identifier and turning it into a regular entity set is almost certainly the best course of action.
Second, the Crow's foot cardinality indicators are unclear. It looks like customers and products are optional in the Buys relationship, or even as if multiple customers could be involved in the same transaction. There are three different concepts involved here - optionality, participation and cardinality - which should preferably be indicated in different ways. See my answer to is optionality (mandatory, optional) and participation (total, partial) are same? for more on the topic.
A card is optional for a purchase transaction. From the description, it sounds as if cards may participate totally, meaning we won't store information about a card unless it's used in a transaction. Furthermore, only a single card can be related to each transaction.
A customer is required for a purchase transaction, and it sounds like customers may participate totally, meaning we won't store information about customers unless they purchase something. Only a single customer can be related to each transaction.
Products are required for a purchase transaction, and since we'll offer products before they're bought, products will participate partially in transactions. However, multiple products can be related to each transaction.
I would represent transactions for this problem with something like the following structure:
I'm not saying converting a ternary or higher relationship into an entity set is always the right thing to do, but in this case it is.
Physically, that would require two tables to represent (not counting Customer, Product, Card or ProductReview) since we can denormalize TransactionCustomer and TransactionCard into Transaction, but TransactionProduct is a many-to-many relationship and requires its own table (as do ternary and higher relationships).
Transaction (TransactionID PK, TransactionDateTime, CustomerID, CardID nullable)
TransactionProduct (TransactionID PK, ProductID PK, Quantity, Price)
My application needs to implement a one to one relation between multiple tables. I have a table which store companies (which can be customers and suppliers, or both). There are twi Bit fields, Customer and Supplier.
Then I have different tables for various operations: Invoices, Bank operations, Cashdesk operations. An I need to pair payments with invoices. A payment is not exact amount of an invoice, but it can be split over each number of invoices. Also, an invoice can be split over multiple payments. Payments can be from both bank or cashdesk operations
My original approach was to have a table, PaymentRelations, with Foreign Keys InvoiceID, BankOpID, CashOpID and Amount, and for any payment between between them, I create a record with only two foreign ID's filled, and the corresponding amount. This way in any moment I can know for each operation (invoice or payment) how much was paid.
Also there are RI requirements, so if a document is involved in payment relation, it cannot be deleted (or there is cascade delete, so if a payment of invoice document is deleted, the related PaymentRelations records are deleted, so the counterpart operations are freed - they are no longer involved into payment relations so their amount can be fully used into other payment relations).
But appeared another situation. Since partners can be both customers and suppliers, it is possible to compensate between same type of operation on customer and supplier side of the same partner (e.g. a partner is both customer and supplier, he made an invoice as supplier for 100 and received an invoice as customer for 150, 50 was compensated between the received and the sent invoice and the rest of each is paid through one or multiple payment operations).
This can also happen for the other operations (e.g. he paid through a bank operation 100, he received through another bank operation 200, and 50 needs to be compensated between those two operations; same apply for caskdesk operations).
What approach would you use to model this kind of relations?
I would buy accounting software instead of writing it. Some wheels are worth reinventing; this isn't one of them.
But if you must . . .
Bitfields are the wrong way to identify customers and suppliers. This SO answer should get you over the issues with customers and suppliers.
If I had to design an accounting system, I think I'd start with a spreadsheet. I'd design a table of transactions in that spreadsheet, so I could get the feel of how certain transactions were alike, and how others were different. At this stage, I wouldn't worry about NULLs, about repeating groups, about transitive dependencies, or anything else like that.
Having developed a working(ish) model in the spreadsheet, I'd then try to normalize it to 5NF.