Разработка схемы для счетов и платежей - лучшая модель, чем отношения M: M? - PullRequest
0 голосов
/ 31 января 2012

В моей существующей схеме есть связь 1: 1 между счетами и проектами. Я нахожусь в процессе его изменения, чтобы в одном проекте было много счетов, но мне также нужно отслеживать платежи.

В настоящее время один платеж относится к 1 (или более) счетам (на самом деле это пакет счетов). В идеале можно отслеживать несколько платежей за один счет. Для этого, я думаю, должна быть взаимосвязь M: M между счетами и платежами.

Итак, как только данные сохранены, как определить, сколько осталось заплатить за один проект? Как определить, сколько должен один клиент? Я не могу придумать, как правильно группировать и суммировать.

До сих пор я дал несколько методов, методы 1-3, в различной степени, основаны на таблицах / значениях в коде ниже. Я только что придумал метод 4, и в настоящее время он выглядит как работоспособный вариант, хотя он не позволяет вам определять, что причитается за один проект во всех сценариях.

  1. Создайте 3 разных запроса, основанных на типе отношения (поле relType в таблице #payinv), 2 из которых я знаю, как сделать. Например, где relType = '1:M', я могу сгруппировать на 1 стороне и суммировать многие стороны; и наоборот для relType = 'M:1'. Но когда relType = 'M:M я в растерянности.

  2. Включая атрибуты ProjectID и BillToPartyID в каждом счете / платеже. Я могу суммировать и сравнивать все счета-фактуры и платежи для одного проекта, но когда платеж покрывает несколько счетов-фактур, окажется, что слишком много было уплачено за этот один проект. Если я возьму то, что задолжал BillToParty, я не смогу точно определить, по какому проекту они все еще должны деньги.

  3. Я могу попытаться сохранить значения счетов и платежей в соединительной таблице. Например, при вводе платежей пользователь применяет платеж к счету. Система будет определять, какие значения вводить в запись, которую пользователь пытается создать, за 3 шага. # 1 Он рассчитал бы оставшееся сальдо путем суммирования сумм текущего счета-фактуры, уже находящихся в соединительной таблице, с последующим вычитанием этого значения из первоначальной суммы счета-фактуры. # 2 Он будет рассчитывать оставшиеся средства для оплаты аналогичным образом. # 3 он сравнил бы оставшийся остаток с доступными средствами и ввел меньшую из обеих сумм как для оплаты, так и для счета в таблицу соединений. Я вижу три варианта: а) Если остаток на счете равен 0, платеж и счет закрываются для дальнейшего использования. б) Если остаток счета-фактуры меньше, чем платеж, счет закрывается, и платеж остается доступным для применения к другому счету. c) Если остаток на счете превышает платеж, платеж закрывается, а счет остается открытым. Кроме сложности, я не вижу проблем с этой идеей ...

  4. Я могу назначить BillToParty для партии счетов-фактур, партия счетов-фактур будет родительской как для счетов-фактур, так и для платежей. Если клиент недоплачивает, мы можем рассчитать оставшийся остаток и сгенерировать новый «счет» (не в первоначальном смысле, и, вероятно, не хотите его хранить ???). Если они переплатят, мы должны оформить кредит, потому что мы не можем применить платеж к другой партии.

        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
    

1 Ответ

0 голосов
/ 01 февраля 2012

Вам нужен ваш billToPartyID (или customerID, я предполагаю, что это одно и то же, или между ними есть отношение 1-> 1) в вашем проекте, счете и таблицах платежей как часть PK.Тогда ваши отношения таковы:

«у клиента / billToParty может быть много проектов, в которых может быть много счетов. Платеж, осуществляемый клиентом / billToParty, может применяться ко многим счетам клиента, которые необходимо указать».

Тогда будет проще отследить итоги по идентификатору клиента, как выполненные платежи, так и неоплаченные суммы счета.

...