Fatura Oluşturma ve İzleme


11

Sistem her 2 haftada bir şirketler için faturalar üretecektir.

Şirket, her ayın 1'inde ve 16'sında fatura alacaktır. (Her 2 haftada bir Cron Job aracılığıyla çalışacaktır. Sipariş tablosunu tarayarak 'fatura' tablosuna ekleyecektir. Alternatif var mı?)

ordersTabloda müşteri siparişlerinin listesi vardır ve hangi şirkete ait olduğunu da gösterir ( orders.company_id)

invoiceTablosundan siparişlerin toplam maliyetini hesaplamak ordersmasaya.

Makul fatura takibini nasıl tasarlayacağımı anlamaya çalışıyorum. Bazen bir şirket bana ücretleri göndermek zorunda kalacak, ya da bazen ücretleri gönderiyorum ( invoice.amount)

Faturaları aşağıdakilerle izlemem gerekiyor:

  • şirket bana miktarı gönderdiğinde
  • tutarı şirkete ne zaman gönderdim
  • şirketten ne kadar miktar alındı
  • şirkete ne kadar miktar gönderdim
  • tutarın tamamını aldım mı (değilse, Db'de ne güncellemem gerekir?)
  • fatura durumu (Gönderilen Fatura, İptal Edildi, Alınan Tutar, Gönderilen Tutar)

İşte ben geldi veritabanı tasarımı:

şirket tablosu

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

Müşteriler web sitemden bir şirket seçebilir.

siparişler tablosu

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

iki müşteri ürünleri Şirket B'den ( orders.company_id = 2) sipariş etmiştir . Emir alanlarının yeterli olmadığını biliyorum, sadece sizin için basitleştirilmiş.

sipariş_ürünleri tablosu

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

Müşterilerin sipariş ettikleri ürünlerin listesi.

fatura tablosu

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

Fatura tabloları tasarımında oldukça sıkışıp kaldım. Nasıl yapılması gerektiğinden emin değilim. Faturalar 2 haftada bir oluşturulacaktır. Tablodan invoice.amounthesaplandığı için sonuç örneğinden 55.00orders.company_id = 2

Eğer invoice.amount-50,00 (eksi), bu ortalama Şirket bana ücretleri tutarı göndermesi gerekir.

Eğer invoice.amount50,00, o ben şirketin ücretlerini göndermek gerekir anlamına gelir.

Status_id şu olabilir: (1) Gönderilen Fatura, (2) İptal Edildi, (3) Tamamlandı

Tabloya invoice_idalan eklemem gerekir ordersmi? orders.invoice_id'Fatura' tablosuna satır eklendiğinde alanı güncelleyin .

fatura_ödeme tablosu

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

İşlemi takip edip güncelleyebileceğim yer burası .. ödeme BACS üzerinden yapılacaktır.

Bu iyi masa tasarımı mı yoksa geliştirmek için neye ihtiyacım var? Hangi alanları ve tabloları eklemeliyim?

Fatura oluşturulduysa ve daha sonra değişiklikleri orders_productsveya orderstabloları yapmam gerekiyorsa - invoice.amountalanı yeniden hesaplamalı mı? (PHP / MySQL kullanacağım).

SQL Dökümü :

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

Yanıtlamak için tabloları güncellemek / eklemek istediğinizde çekinmeyin.

Teşekkürler

Yanıtlar:


8

Nakit eşleme

Bu bir nakit eşleme problemidir. Bunu iki düzeyden birinde izleyebilirsiniz:

  • Faturalandırılmış nakit rakamlarla karşılaştırın (biraz özensiz ama aslında çoğu zaman 'yazılı ve imzalı' rapor olarak adlandırılan birçok Lloyd's Sendikası tarafından içe dönük işler için böyle yapılır.

  • Faturaya göre ayrılmış nakit ödemelerden kesin nakit tahsisi yapın.

Sorunuzdan sanırım ikincisini yapmak istiyorsunuz.

Tipik olarak bu, ayrı bir nakit işlemleri seti ve faturalara nakit ödeme tahsisi olan bir köprü tablosu ile yapılır. Değerler eşitse veya nakit ödeme tek bir fatura referansı ile geliyorsa, tahsisi otomatik olarak yapabilirsiniz. Faturalar ve ödemeler arasında bir M: M ilişkisi varsa, manuel bir eşleştirme işlemi yapmanız gerekir (bunu otomatik olarak yapmak sırt çantası sorununun bir çeşididir ).

Temel bir nakit eşleme sistemi

Bir fatura tablonuz, nakit ödeme tablonuz ve bir tahsis tablonuz olduğunu düşünün. Bir fatura düzenlediğinizde, faturalar tablosunda bir fatura kaydı ve tahsisler tablosunda bir 'alacak' veya 'ödenecek' kayıt ayarlarsınız.

  • Fatura # 1, 100 ABD doları

  • Tahsis: 1 numaralı faturaya, 'alacak' işlem türüne ve 100 dolar borcuna referansla yapılan bir kayıt. Bu kayıttaki nakit ödemeye referans yok.

Şimdi 100 $ nakit ödeme alıyorsunuz

  • Nakit ödemeler (CHQ # 12345): 100 $

  • Tahsisi: fatura # 1 ve chq # 12345, 'nakit' işlem türü ve -100 borçlu (100 $ ödenmiş) referansı olan bir kayıt.

Bunu, tek bir faturaya veya birden fazla faturayı kapsayan bir ödemeye göre birden çok ödeme aldığınız bir M: M ilişkisine genelleyebilirsiniz. Bu yapı aynı zamanda kredi kontrol raporları oluşturmayı da oldukça kolaylaştırmaktadır. Raporun, ödenmemiş bakiyeleri olan 180 günden daha eski faturaları bulması yeterlidir.

İşte şemanın bir örneği artı birkaç senaryo ve eski bir borç sorgusu. Ne yazık ki el için çalışan bir mysql örneği yok, bu yüzden bu bir SQL Server içindir.

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

Madende faturalar ve ödemeler için ayrı tablolar var. İç bağlantıya sahip ortak bir tablo kullanabilirsiniz. Nakit eşleştirme genellikle muhasebe sistemlerinde bu şekilde uygulanır.
ConcernedOfTunbridgeWells

SQL Server örneğinizi MySQL'e çevirmeyi başardım. Ben geçtim ve şimdi çok iyi anladım. AllocationTypeMüşteri parası göndermek istersem ne olur ? Ben de CashPaymenttabloya eklemek gerekir mi (diyelim ki BACS üzerinden ödeme).
geri

1
Evet, hem gelen hem de giden ödemeler için bir nakit ödeme kaydı istiyorsunuz. Nakit eşleştirme işlemleri için gerçek işlem türleri size bağlıdır.
ConcernedOfTunbridgeWells

1
İsterseniz faturaların her iki yöndeki işlemlerini tek bir ödeme ile eşleştirebilirsiniz. Örneğin: 100 $ 'lık giden fatura, 50 $ (-50) için gelen fatura ve 50 $ için gelen ödemeyi dengeleme, her iki faturayla da eşleşti.
ConcernedOfTunbridgeWells
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.