【发布时间】:2012-01-31 19:36:29
【问题描述】:
在我现有的架构中,发票和项目之间存在 1:1 的关系。我正在修改它以允许一个项目有许多发票,但我还需要跟踪付款。
目前,单笔付款涉及一张(或多张)发票(实际上是一批发票)。理想情况下,可以跟踪每张发票的多次付款。为此,我认为发票和付款之间需要存在 M:M 关系。
那么,一旦存储了数据,如何确定一个项目还需要支付多少费用?如何确定单个客户的欠款金额?我想不出如何正确分组和求和。
到目前为止,我想出了几种方法,方法 1-3 在不同程度上基于下面代码中的表/值。我刚才想出了方法 4,目前看来是一个可行的选择,尽管它不允许您在所有情况下确定单个项目的欠款。
创建 3 个依赖于关系类型(#payinv 表中的 relType 字段)的不同查询,其中 2 个我知道如何创建。例如,
relType = '1:M',我可以在 1 侧分组,并在多侧求和;relType = 'M:1'反之亦然。但是当relType = 'M:M我不知所措。通过在每个发票/付款中包含属性
ProjectID和BillToPartyID。我可以对单个项目的所有发票和付款进行汇总和比较,但是当付款涵盖多张发票时,似乎为该项目支付了太多费用。如果我追讨 BillToParty 的欠款,我无法确定他们还欠哪个项目的钱。我可以尝试在联结表中存储发票和付款值。例如,当输入付款时,用户会将付款应用到发票上。系统将通过 3 个步骤确定在用户尝试创建的记录中输入的值。 #1 它将通过将已在联结表中的当前发票金额相加来计算剩余余额,然后从原始发票金额中减去该值。 #2 它将以类似的方式计算可用于支付的剩余资金。 #3 它将剩余余额与可用资金进行比较,并将付款和发票金额中的较小者输入到联结表中。我看到了三种 3 种可能性: a) 如果发票余额为 0,则付款和发票均关闭以供进一步使用。 b) 如果发票的余额少于付款,发票将关闭,付款仍可用于另一张发票。 c) 如果发票的余额大于付款,则付款关闭,发票保持打开状态。除了复杂性之外,我认为这个想法没有任何问题......
-
我可以将 BillToParty 分配给 Invoice Batch,Invoice Batch 将是 Invoices 和 Payments 的父级。如果客户少付,我们可以计算余额并生成新的“发票”(不是原始意义上的发票,可能不想存储这个???)。如果他们多付,我们必须开具信用证,因为我们无法将付款应用到另一批。
CREATE TABLE #inv ( invID int NOT NULL, invAMT int NULL ) ON [PRIMARY] GO ALTER TABLE #inv ADD CONSTRAINT PK_inv PRIMARY KEY CLUSTERED ( invID ) CREATE TABLE #pay ( payID varchar(50) NOT NULL, payAMT int NULL ) ON [PRIMARY] GO ALTER TABLE #pay ADD CONSTRAINT PK_pay PRIMARY KEY CLUSTERED ( payID ) CREATE TABLE #payinv ( payID varchar(50) NOT NULL, invID int NOT NULL, relType varchar(50) not null ) ON [PRIMARY] GO ALTER TABLE #payinv ADD CONSTRAINT PK_payinv PRIMARY KEY CLUSTERED ( payID, invID ) INSERT INTO #inv (invID, invAMT) select 1,110 union select 2,400 union select 3,600 union select 4,100000 union select 5,10000 union select 6,1000000; INSERT INTO #pay (payID,payAMT) select 'a',10 union select 'b',100 union select 'c',1000 union select 'd',10000 union select 'e',100000 union select 'f',1000000; INSERT INTO #payinv(payID,invID,relType) select 'a',1,'1:M' union select 'b',1,'1:M' union select 'c',2,'M:1' union select 'c',3,'M:1' union select 'd',4,'M:M' union select 'e',4,'M:M' union select 'e',5,'M:M' union select 'f',6,'1:1'; select #inv.invAMT, #inv.invID, #pay.payID, #pay.payAMT, #payinv.relType from #inv inner join #payinv on #inv.invID = #payinv.invID inner join #pay on #payinv.payID = #pay.payID
【问题讨论】:
-
为什么您的会计系统不这样做?
-
我们目前在与 QuickBooks 和异地兼职会计师关联的巨型电子表格上跟踪发票和付款。在创建发票的系统中跟踪付款似乎是合乎逻辑的步骤。能够在同一系统中报告所有统一数据将是一个加分项。
标签: sql sql-server-2008 relational-database database-schema