Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

codebyshami's avatar

NEED ADVICE

I am building an invoice system where there are two types of Invoices Sale Invoice and Purchase Invoice Customer assoc with sale invoice and vendor assoc with purchase invoice NOW I have a Vendors and Customers table with the same attributes/columns name email number tax_number address

now what should I do? What is the best design schema for this

0 likes
5 replies
LaryAI's avatar
Level 58

To design a schema for your invoice system where you have both Customers and Vendors with similar attributes, you have a couple of options. Here are two common approaches:

Option 1: Separate Tables for Customers and Vendors

In this approach, you maintain separate tables for Customers and Vendors. This is straightforward and keeps the data logically separated.

Schema Design

CREATE TABLE customers (
    id INT AUTO_INCREMENT PRIMARY KEY,
    name VARCHAR(255) NOT NULL,
    email VARCHAR(255) NOT NULL,
    number VARCHAR(50),
    tax_number VARCHAR(50),
    address TEXT
);

CREATE TABLE vendors (
    id INT AUTO_INCREMENT PRIMARY KEY,
    name VARCHAR(255) NOT NULL,
    email VARCHAR(255) NOT NULL,
    number VARCHAR(50),
    tax_number VARCHAR(50),
    address TEXT
);

CREATE TABLE invoices (
    id INT AUTO_INCREMENT PRIMARY KEY,
    type ENUM('sale', 'purchase') NOT NULL,
    customer_id INT,
    vendor_id INT,
    amount DECIMAL(10, 2) NOT NULL,
    date DATE NOT NULL,
    FOREIGN KEY (customer_id) REFERENCES customers(id),
    FOREIGN KEY (vendor_id) REFERENCES vendors(id)
);

Explanation

  • customers table stores customer-specific information.
  • vendors table stores vendor-specific information.
  • invoices table has a type column to distinguish between sale and purchase invoices, and foreign keys to either customer_id or vendor_id.

Option 2: Single Table for Both Customers and Vendors

In this approach, you use a single table to store both Customers and Vendors, and add a column to distinguish between them.

Schema Design

CREATE TABLE parties (
    id INT AUTO_INCREMENT PRIMARY KEY,
    type ENUM('customer', 'vendor') NOT NULL,
    name VARCHAR(255) NOT NULL,
    email VARCHAR(255) NOT NULL,
    number VARCHAR(50),
    tax_number VARCHAR(50),
    address TEXT
);

CREATE TABLE invoices (
    id INT AUTO_INCREMENT PRIMARY KEY,
    type ENUM('sale', 'purchase') NOT NULL,
    party_id INT,
    amount DECIMAL(10, 2) NOT NULL,
    date DATE NOT NULL,
    FOREIGN KEY (party_id) REFERENCES parties(id)
);

Explanation

  • parties table stores both customers and vendors, distinguished by the type column.
  • invoices table has a type column to distinguish between sale and purchase invoices, and a foreign key to party_id.

Which Option to Choose?

  • Option 1 is more straightforward and keeps the data logically separated, which can be easier to manage and understand.
  • Option 2 reduces redundancy and can simplify queries if you often need to treat customers and vendors similarly.

Choose the option that best fits your application's requirements and complexity. If you expect the attributes of customers and vendors to diverge in the future, Option 1 might be more flexible. If you want to keep things simple and DRY (Don't Repeat Yourself), Option 2 might be more suitable.

MohamedTammam's avatar

I would create a centralized place (trait for example) to store all the logic related to invoices. And then, I would use that trait in both models.

Is that what you're asking for?

2 likes
codebyshami's avatar

@MohamedTammam No Well i am asking that Should I go for one table with has Many relationship of invoices

Or

Two different table with polymorphic relationship woth invoices

jlrdw's avatar

@codebyshami do you have many vendors that are also customers? If so one table with a field denoting which, like a checkbox (called a flag).

Otherwise I would use two tables, but just my opinion.

You could also setup a polymorphic relationship. But a flag is much easier. In fact most polymorphic relationships I see people use is simpler with a flag instead. I see no need for a polymorphic relationship.

2 likes
martinbean's avatar

@codebyshami An invoice is an invoice. An invoice has an issuer (the sender) and a customer (the recipient). So I don’t see why this needs splitting across two tables with exactly the same schemas.

2 likes

Please or to participate in this conversation.