송장 생성 및 추적


11

2 주마다 시스템에서 회사에 대한 송장을 생성합니다.

회사는 매달 1 일과 16 일에 송장을받습니다. (2 주마다 Cron Job을 통해 실행됩니다. 주문 테이블을 스캔 한 다음 '인보이스'테이블에 추가합니다. 대안이 있습니까?)

표에 고객 주문 목록이 orders있으며 해당 회사가 속한 회사도 표시합니다 ( orders.company_id).

invoice테이블 은 테이블에서 주문의 총 비용을 계산 orders합니다.

합리적인 송장 추적을 디자인하는 방법을 알아 내려고 노력 중입니다. 언젠가 회사에서 수수료를 보내거나 언젠가 수수료를 보내야 할 것입니다 ( invoice.amount)

다음을 사용하여 송장을 추적해야합니다.

  • 회사가 금액을 보냈을 때
  • 언제 회사에 금액을 보냈습니까?
  • 회사로부터받은 금액
  • 회사에 얼마를 보냈습니까
  • 전체 금액을 받았습니까? (아니라면 Db에서 무엇을 업데이트해야합니까?)
  • 송장 상태 (송장 발송, 취소됨, 수취 량, 송금액)

내가 생각해 낸 데이터베이스 디자인은 다음과 같습니다.

회사 테이블

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

고객은 내 웹 사이트에서 회사를 선택할 수 있습니다.

주문 테이블

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

두 고객이 회사 B ( orders.company_id = 2) 로부터 제품을 주문했습니다 . 주문 필드로는 충분하지 않으며 간단하게 알 수 있습니다.

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

고객이 주문한 제품 목록.

송장 테이블

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

이곳은 송장 테이블 디자인에 상당히 얽매여 있습니다. 어떻게해야할지 모르겠습니다. 인보이스는 2 주마다 생성됩니다. 테이블 invoice.amount에서 계산되었으므로 결과 예의 55.00입니다.orders.company_id = 2

(가) 경우 invoice.amount-50.00 (마이너스), 그것은 평균이 회사는 나에게 수수료 금액을 보내야합니다.

(가) 경우 invoice.amount50.00, 그것은 내가 회사에게 수수료를 보낼 필요가 의미한다.

status_id는 다음과 같습니다. (1) 송장 발송, (2) 취소, (3) 완료

테이블 에 invoice_id필드 를 추가해야 orders합니까? orders.invoice_id행이 '인보이스'테이블에 삽입되면 필드를 업데이트하십시오 .

송장 지불 테이블

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

거래를 추적하고 업데이트 할 수있는 곳입니다. 결제는 BACS를 통해 이루어집니다.

이 좋은 테이블 디자인입니까 아니면 개선해야합니까? 어떤 필드와 테이블을 추가해야합니까?

송장이 생성 된 후 나중에 테이블 orders_products또는 orders테이블을 변경 해야합니다. invoice.amount필드를 다시 계산해야 합니까? (PHP / MySQL을 사용합니다).

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

응답을 위해 테이블을 업데이트 / 추가하려면 여기를 클릭하십시오.

감사

답변:


8

현금 매칭

이것은 현금 일치 문제입니다. 다음 두 레벨 중 하나에서이를 추적 할 수 있습니다.

  • 인보이스를 현금 수치와 비교하십시오 (조잡한 방법이지만 실제로는 대부분의 Lloyd 's Syndicates에서 종종 '필기 vs. 서명'보고서라고 함).

  • 송장별로 세분화 된 현금 결제에서 명시적인 현금 할당을 유지합니다.

당신의 질문에서 나는 당신이 후자를하고 싶다고 생각합니다.

일반적으로 이는 별도의 현금 거래 세트와 송장에 현금 지불이 할당 된 브리징 테이블을 통해 이루어집니다. 값이 같거나 현금 지불에 단일 송장 참조가 있으면 자동으로 할당을 수행 할 수 있습니다. 송장과 지불간에 M : M 관계가있는 경우 수동 일치 프로세스를 수행해야합니다 (이 작업은 실제로 배낭 문제 의 변형 임 ).

기본 현금 매칭 시스템

송장 테이블, 현금 지불 테이블 및 할당 테이블이 있다고 가정하십시오. 송장을 발행하면 송장 테이블에서 송장 레코드를 설정하고 할당 테이블에서 '수취 가능'또는 '지급 가능'레코드를 설정합니다.

  • 인보이스 # 1, $ 100

  • 할당 : 송장 # 1, '수취 가능'거래 유형 및 $ 100으로 인해 레코드가 있습니다. 이 기록에 대한 현금 지불에 대한 언급이 없습니다.

이제 현금으로 $ 100를받습니다

  • 현금 지불 (chq # 12345) : $ 100

  • 할당 : 송장 # 1 및 chq # 12345, '현금'거래 유형 및 -100 기한 ($ 100 지불)을 참조한 레코드.

단일 송장 또는 여러 송장에 대한 지불에 대해 여러 번 지불하는 M : M 관계로이를 일반화 할 수 있습니다. 이 구조는 또한 신용 관리 보고서를 작성하기가 매우 쉽습니다. 보고서는 여전히 미결제 잔액이있는 180 일보다 오래된 송장을 찾아야합니다.

다음은 스키마와 몇 가지 시나리오 및 오래된 부채 쿼리의 예입니다. 불행히도 실행중인 mysql 인스턴스가 없으므로 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

광산에는 송장 및 지불에 대한 별도의 테이블이 있습니다. 내부 연결이있는 공통 테이블을 사용할 수 있습니다. 현금 매칭은 종종 회계 시스템에서 그러한 방식으로 구현됩니다.
ConcernedOfTunbridgeWells

SQL Server 예제를 MySQL로 변환했습니다. 나는 겪었고 지금 매우 잘 이해했습니다. 무엇을 할 AllocationType내가 클라이언트 돈을 보내려면 것입니까? CashPayment테이블 에 삽입해야 합니까 (BACS를 통해 지불해야한다고)?
I'll-Be-Back

1
예, 입금과 지급에 대한 현금 지불 기록을 원합니다. 현금 일치 거래의 실제 거래 유형은 귀하에게 달려 있습니다.
ConcernedOfTunbridgeWells

1
원하는 경우 단일 결제 결제에 대해 양방향 송장 거래를 일치시킬 수 있습니다. 예를 들어 : $ 100에 대한 송장, $ 50 (-50)에 대한 송장 및 $ 50에 대한 입금의 균형 조정은 두 송장과 일치합니다.
ConcernedOfTunbridgeWells
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.