Tạo hóa đơn và theo dõi


11

Cứ sau 2 tuần, hệ thống sẽ tạo hóa đơn cho các công ty.

Công ty sẽ nhận được hóa đơn vào ngày 1 và 16 hàng tháng. (Nó sẽ chạy qua Cron Job mỗi 2 tuần. Nó quét qua bảng đơn hàng và sau đó thêm vào bảng 'hóa đơn'. Có cách nào khác không?)

Có danh sách các đơn đặt hàng của khách hàng trong ordersbảng và nó cũng cho biết công ty đó thuộc về ( orders.company_id)

Các invoicebảng tính toán tổng chi phí của các đơn đặt hàng từ ordersbảng.

Tôi đang cố gắng tìm ra cách thiết kế theo dõi hóa đơn hợp lý. Đôi khi công ty sẽ phải gửi cho tôi các khoản phí hoặc đôi khi tôi gửi cho họ các khoản phí ( invoice.amount)

Tôi cần theo dõi các hóa đơn như sau:

  • khi công ty gửi cho tôi số tiền
  • khi nào tôi gửi số tiền cho công ty
  • bao nhiêu đã nhận được từ công ty
  • tôi đã gửi bao nhiêu tiền cho công ty
  • Tôi đã nhận được toàn bộ số tiền chưa (nếu không, tôi cần cập nhật gì trên Db?)
  • trạng thái hóa đơn (Hóa đơn đã gửi, Đã hủy, Số tiền đã nhận, Số tiền đã gửi)

Đây là thiết kế cơ sở dữ liệu tôi đã đưa ra:

bảng công ty

mysql> select * from company;
+----+-----------+
| id | name      |
+----+-----------+
|  1 | Company A |
|  2 | Company B |
+----+-----------+

Khách hàng có thể chọn một công ty từ trang web của tôi.

bảng đơn hàng

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 |
+----+---------+------------+------------+---------------------+-----------+

hai khách hàng đã đặt hàng các sản phẩm từ Công ty B ( orders.company_id = 2). Tôi biết các trường đơn hàng là không đủ, chỉ đơn giản hóa cho bạn.

bảng order_products

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 |
+----+----------+------------+--------------+-------+

Danh sách các sản phẩm những gì khách hàng đã đặt hàng.

bảng hóa đơn

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 |
+----+------------+------------+---------------------+--------+-----------+

Đây là nơi tôi khá bế tắc trong thiết kế bảng hóa đơn. Tôi không chắc nó nên được thực hiện như thế nào. Hóa đơn sẽ được tạo ra mỗi 2 tuần. Từ ví dụ kết quả invoice.amountlà 55,00 vì nó đã được tính từ orders.company_id = 2bảng

Nếu invoice.amountlà -50,00 (trừ), điều đó có nghĩa là công ty sẽ cần gửi cho tôi số tiền lệ phí.

Nếu invoice.amountlà 50,00, điều đó có nghĩa là tôi cần gửi cho công ty các khoản phí.

Status_id có thể là: (1) Đã gửi hóa đơn, (2) Đã hủy, (3) Đã hoàn thành

Tôi có cần thêm invoice_idtrường trong ordersbảng không? Cập nhật orders.invoice_idtrường khi hàng đã được chèn vào bảng 'hóa đơn'.

bảng hóa đơn thanh toán

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 |
+----+------------+-----------------+-------------+---------------------+---------------------+

Đây là nơi tôi có thể theo dõi và cập nhật giao dịch .. thanh toán sẽ được thực hiện qua BACS.

Đây có phải là thiết kế bảng tốt hay tôi cần cải thiện điều gì? Những lĩnh vực và bảng tôi nên thêm?

Nếu hóa đơn đã được tạo và sau này tôi cần thực hiện các thay đổi trong orders_productshoặc ordersbảng - nó có nên tính toán lại invoice.amounttrường không? (Tôi sẽ sử dụng PHP / MySQL).

Kết xuất SQL :

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');

Hãy thoải mái bạn muốn cập nhật / thêm bảng để trả lời ở đây.

Cảm ơn

Câu trả lời:


8

Khớp tiền mặt

Đây là một vấn đề khớp tiền mặt. Bạn có thể theo dõi điều này ở một trong hai cấp độ:

  • So sánh hóa đơn với các số liệu tiền mặt (hơi cẩu thả nhưng đây thực sự là cách nó được thực hiện cho việc kinh doanh hướng nội của hầu hết các Syndicates của Lloyd, thường được gọi là báo cáo 'bằng văn bản so với ký').

  • Duy trì phân bổ tiền mặt rõ ràng từ các khoản thanh toán tiền mặt được chia nhỏ bằng hóa đơn.

Từ câu hỏi của bạn tôi nghĩ bạn muốn làm sau.

Thông thường, điều này được thực hiện bằng cách có một bộ giao dịch tiền mặt riêng biệt và một bảng bắc cầu có phân bổ thanh toán tiền mặt cho hóa đơn. Nếu các giá trị bằng nhau hoặc thanh toán bằng tiền mặt đi kèm với một tham chiếu hóa đơn, bạn có thể tự động phân bổ. Nếu có mối quan hệ M: M giữa hóa đơn và thanh toán, bạn sẽ cần thực hiện quy trình khớp thủ công (thực hiện điều này tự động thực sự là một biến thể của vấn đề về chiếc ba lô ).

Một hệ thống khớp tiền mặt cơ bản

Hãy tưởng tượng rằng bạn có bảng hóa đơn, bảng thanh toán tiền mặt và bảng phân bổ. Khi bạn phát hành hóa đơn, sau đó bạn thiết lập một bản ghi hóa đơn trong bảng hóa đơn và bản ghi 'phải thu' hoặc 'phải trả' trong bảng phân bổ.

  • Hóa đơn số 1, $ 100

  • Phân bổ: một bản ghi có tham chiếu đến hóa đơn số 1, loại giao dịch 'phải thu' và nợ $ 100. Không có tham chiếu đến một khoản thanh toán tiền mặt trong hồ sơ này.

Bây giờ, bạn nhận được khoản thanh toán bằng tiền mặt là 100 đô la

  • Thanh toán bằng tiền mặt (chq # 12345): 100 đô la

  • Phân bổ: một bản ghi có tham chiếu đến hóa đơn số 1 và chq # 12345, loại giao dịch 'tiền mặt' và -100 nợ (trả 100 đô la).

Bạn có thể khái quát hóa điều này thành mối quan hệ M: M nơi bạn nhận được nhiều khoản thanh toán so với một hóa đơn hoặc một khoản thanh toán bao gồm nhiều hóa đơn. Cấu trúc này cũng làm cho nó khá dễ dàng để xây dựng các báo cáo kiểm soát tín dụng. Báo cáo chỉ cần tìm hóa đơn cũ hơn (giả sử) 180 ngày mà vẫn có số dư chưa thanh toán.

Đây là một ví dụ về lược đồ cộng với một vài tình huống và truy vấn nợ cũ. Thật không may, tôi không có phiên bản mysql đang chạy, vì vậy phiên bản này dành cho SQL Server.

-- ==============================================================
-- === CashMatch.sql ============================================
-- ==============================================================
--


-- === Invoices =================================================
--
create table Invoice (
       InvoiceID        int identity (1,1) not null
      ,InvoiceRef       varchar (20)
      ,Amount           money
      ,InvoiceDate      datetime
)
go

alter table Invoice
  add constraint PK_Invoice 
      primary key nonclustered (InvoiceID)
go


-- === Cash Payments ============================================
--
create table CashPayment (
       CashPaymentID    int identity (1,1) not null
      ,CashPaymentRef   varchar (20)
      ,Amount           money
      ,PaidDate         datetime
)
go

alter table CashPayment
  add constraint PK_CashPayment
      primary key nonclustered (CashPaymentID)
go




-- === Allocations ==============================================
--
create table Allocation (
       AllocationID       int identity (1,1) not null
      ,CashPaymentID      int  -- Note that some records are not
      ,InvoiceID          int  -- on one side.
      ,AllocatedAmount    money
      ,AllocationType     varchar (20)
      ,TransactionDate    datetime
)
go

alter table Allocation
  add constraint PK_Allocation
      primary key nonclustered (AllocationID)
go


-- ==============================================================
-- === Scenarios ================================================
-- ==============================================================
--
declare @Invoice1ID int
       ,@Invoice2ID int
       ,@PaymentID int


-- === Raise a new invoice ======================================
--
insert Invoice (InvoiceRef, Amount, InvoiceDate)
values ('001', 100, '2012-01-01')

set @Invoice1ID = @@identity

insert Allocation (
       InvoiceID
      ,AllocatedAmount
      ,TransactionDate
      ,AllocationType
) values (@Invoice1ID, 100, '2012-01-01', 'receivable')


-- === Receive a payment ========================================
--
insert CashPayment (CashPaymentRef, Amount, PaidDate)
values ('12345', 100, getdate())

set @PaymentID = @@identity

insert Allocation (
       InvoiceID
      ,CashPaymentID
      ,AllocatedAmount
      ,TransactionDate
      ,AllocationType
) values (@Invoice1ID, @PaymentID, -100, getdate(), 'paid')



-- === Raise two invoices =======================================
--
insert Invoice (InvoiceRef, Amount, InvoiceDate)
values ('002', 75, '2012-01-01')

set @Invoice1ID = @@identity

insert Allocation (
       InvoiceID
      ,AllocatedAmount
      ,TransactionDate
      ,AllocationType
) values (@Invoice1ID, 75, '2012-01-01', 'receivable')


insert Invoice (InvoiceRef, Amount, InvoiceDate)
values ('003', 75, '2012-01-01')

set @Invoice2ID = @@identity

insert Allocation (
       InvoiceID
      ,AllocatedAmount
      ,TransactionDate
      ,AllocationType
) values (@Invoice2ID, 75, '2012-01-01', 'receivable')


-- === Receive a payment ========================================
-- The payment covers one invoice in full and part of the other.
--
insert CashPayment (CashPaymentRef, Amount, PaidDate)
values ('23456', 120, getdate()) 

set @PaymentID = @@identity

insert Allocation (
       InvoiceID
      ,CashPaymentID
      ,AllocatedAmount
      ,TransactionDate
      ,AllocationType
) values (@Invoice1ID, @PaymentID, -75, getdate(), 'paid')

insert Allocation (
       InvoiceID
      ,CashPaymentID
      ,AllocatedAmount
      ,TransactionDate
      ,AllocationType
) values (@Invoice2ID, @PaymentID, -45, getdate(), 'paid')



-- === Aged debt report ========================================
--
select i.InvoiceRef
      ,sum (a.AllocatedAmount)                 as Owing
      ,datediff (dd, i.InvoiceDate, getdate()) as Age
  from Invoice i
  join Allocation a
    on a.InvoiceID = i.InvoiceID
 group by i.InvoiceRef
         ,datediff (dd, i.InvoiceDate, getdate())
having sum (a.AllocatedAmount) > 0

Của tôi có bảng riêng cho hóa đơn và thanh toán. Bạn có thể sử dụng một bảng chung với liên kết nội bộ. Kết hợp tiền mặt thường được thực hiện theo cách đó trong các hệ thống kế toán.
Mối quan tâmOfTunbridgeWells

Tôi đã quản lý để dịch ví dụ SQL Server của bạn sang MySQL. Tôi đã đi qua và tôi hiểu rất rõ bây giờ. Điều gì sẽ AllocationTypexảy ra nếu tôi muốn gửi tiền của khách hàng? Tôi có cần phải chèn vào CashPaymentbảng không (giả sử thanh toán cho họ qua BACS)?
Tôi sẽ trở lại vào

1
Có, bạn muốn có một bản ghi thanh toán tiền mặt cho cả thanh toán đến và đi. Các loại giao dịch thực tế cho các giao dịch khớp tiền mặt là tùy thuộc vào bạn.
Mối quan tâmOfTunbridgeWells

1
Bạn có thể khớp các giao dịch từ hóa đơn theo cả hai hướng với một khoản thanh toán duy nhất nếu bạn muốn. Ví dụ: Hóa đơn gửi đi cho 100 đô la, hóa đơn đến với 50 đô la (-50) và cân bằng thanh toán đến với 50 đô la khớp với cả hai hóa đơn.
Mối quan tâmOfTunbridgeWells
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.