Quantcast
Channel: Forum Getting started with SQL Server
Viewing all articles
Browse latest Browse all 7129

T-SQL Payment Apply in Order by Oldest Date

$
0
0

I'm trying to write a sql view to apply customer payments (oldest payment applied to oldest invoice in sequential order).  I'd like to apply the customer payments based on the oldest payment date being applied to the oldest invoice date until the payment no longer has any value remaining, then the next payment for that customer and so on.

I can't change the table structure as it is tied to an ERP, payments and invoices are in the same table, payments are document type = 9 and invoices are document type 1.  There will be no negative numbers.  I can only apply up to the invoice/current amount (i.e. I cannot apply an amount that would cause a negative amount to be applied).

here is some sample data:

CREATE TABLE [dbo].[_ReceivablesDocuments](

[Customer] [char](15) NOT NULL,
[DocumentNbr] [char](21) NOT NULL,
[PaymentCID] [char](21) NOT NULL,
[DocumentType] [smallint] NOT NULL,
[DocumentDate] [datetime] NOT NULL,
[CurrentAmount] [numeric](19, 5) NOT NULL,
[_ID] [int] IDENTITY(1,1) NOT NULL
) ON [PRIMARY]


INSERT INTO _ReceivablesDocuments VALUES ('130308', 'OCK000000023830', '4328', 9, '12-05-2018', '43.60')
INSERT INTO _ReceivablesDocuments VALUES ('130308', 'OCK000000023B2C', '4328', 9, '12-06-2018', '43.60')
INSERT INTO _ReceivablesDocuments VALUES ('130666', 'OCC0000000295D7', '2232', 9, '12-20-2018', '226.10')
INSERT INTO _ReceivablesDocuments VALUES ('130666', 'RCC00000003C9AD', '2232', 9, '01-18-2019', '103.35')
INSERT INTO _ReceivablesDocuments VALUES ('131802', 'OCC00000002DF3B', '3701', 9, '01-02-2019', '200.00')
INSERT INTO _ReceivablesDocuments VALUES ('131802', 'OCC00000002DF3D', '3701', 9, '01-02-2019', '30.00')
INSERT INTO _ReceivablesDocuments VALUES ('131802', 'RCC00000002F7C3', '3701', 9, '01-02-2019', '17.65')

INSERT INTO _ReceivablesDocuments VALUES ('130308', '0130308M181231', '', 1, '12-31-2018', 16.80000)
INSERT INTO _ReceivablesDocuments VALUES ('130308', '130308-MIG-181031', '', 1, '10-31-2018', 16.80000)
INSERT INTO _ReceivablesDocuments VALUES ('130308', '130308-MIG-181130', '', 1, '11-30-2018', 26.80000)
INSERT INTO _ReceivablesDocuments VALUES ('130666', '0130666M181231', '', 1, '12-31-2018', 24.33000)
INSERT INTO _ReceivablesDocuments VALUES ('131802', '131802-MIG-181130', '', 1, '11-30-2018', 17.65000)
INSERT INTO _ReceivablesDocuments VALUES ('131802', '0131802M181231', '', 1, '12-31-2018', 131.83000)

The results should look like this (based on above):

CustomerPaymentDatePaymentNbrPaymentCID AvailableApplyAmount ApplyToDocumentNbrDocumentType InvoiceBalance InvoiceDate ApplyAmount 
13030812/5/2018OCK000000023830      4328 $                                      43.60130308-MIG-181031    1 $                    16.8010/31/2018 $                  16.80
13030812/5/2018OCK000000023830      4328 $                                      26.80130308-MIG-181130    1 $                    26.8011/30/2018 $                  26.80
13030812/6/2018OCK000000023B2C      4328 $                                      43.600130308M1812311 $                    16.8012/31/2018 $                  16.80
13066612/20/2018OCC0000000295D7      2232 $                                   226.100130666M181231       1 $                    24.3312/31/2018 $                  24.33
1318021/2/2019OCC00000002DF3B      3701 $                                   200.00131802-MIG-1811301 $                    17.6511/30/2018 $               117.65
1318021/2/2019OCC00000002DF3B      3701 $                                      82.350131802M181231       1 $                  131.8312/31/2018 $                  82.35
1318021/2/2019OCC00000002DF3D3701 $                                      30.000131802M181231       1 $                    49.4812/31/2018 $                  30.00
1318021/2/2019RCC00000002F7C33701 $                                      17.650131802M181231       1 $                    19.4812/31/2018 $                  17.65

Here is the query I have but it doesn't quite work properly...

WITH CTE AS (
SELECT
ROWNUM = ROW_NUMBER() OVER (Partition by CR.CUSTNMBR order by INV.DOCDATE, INV.DOCNUMBR),
CR.CUSTNMBR as Customer_Nbr, CR.DOCDATE as Apply_Date
       , CR.DOCNUMBR as Source_Document_Nbr, CR.CHEKNMBR as Check_Nbr
       --, CR.CHEKBKID as Checkbook_Id
   , CR.CURTRXAM as Available_Apply_Amount
       --Apply Information
       , INV.DOCNUMBR as Apply_to_Document_Nbr, INV.CURTRXAM
       , INV.DOCDATE
          , CASE WHEN CR.CURTRXAM - sum(INV.CURTRXAM) OVER (PARTITION BY CR.CUSTNMBR ORDER BY INV.DOCDATE, INV.DOCNUMBR) < 0 THEN 0 ELSE CR.CURTRXAM - sum(INV.CURTRXAM) OVER (Partition by CR.CUSTNMBR order by INV.DOCDATE, INV.DOCNUMBR) end as AvailableBalance
FROM RM20101 CR (nolock)
       JOIN RM20101 INV (nolock) ON CR.CUSTNMBR = INV.CUSTNMBR 
   INNER JOIN
(
SELECT CR1.CUSTNMBR, CR1.DOCNUMBR, MIN(DOCDATE) as MinPaymentDate
FROM RM20101 CR1
WHERE CR1.RMDTYPAL = 9
AND CR1.CURTRXAM <> 0
AND CR1.VOIDSTTS = 0
GROUP BY CR1.CUSTNMBR, CR1.DOCNUMBR
) X ON X.CUSTNMBR = CR.CUSTNMBR AND X.MinPaymentDate = CR.DOCDATE AND X.DOCNUMBR = CR.DOCNUMBR

WHERE  LEFT(INV.TRXSORCE,4) = 'SLST'
AND INV.RMDTYPAL <> 8
       AND INV.CURTRXAM <> 0
   AND CR.RMDTYPAL = 9
   AND CR.CURTRXAM <> 0
)
SELECT
CTE.Customer_Nbr, CTE.Apply_Date, CTE.Source_Document_Nbr, CTE.Check_Nbr--, CTE.Checkbook_Id, 
              , CASE WHEN prev.AvailableBalance is null THEN CTE.Available_Apply_Amount else prev.AvailableBalance end as Available_Apply_Amount,
              CTE.Apply_to_Document_Nbr, 
              CTE.CURTRXAM AS [Invoice Balance], 
              CTE.DOCDATE AS [Invoice Date],
--CASE WHEN prev.AvailableBalance is null THEN 
--CASE WHEN CTE.Available_Apply_Amount < CTE.CURTRXAM then CTE.Available_Apply_Amount ELSE CTE.CURTRXAM END 
--ELSE prev.AvailableBalance end as Apply_Amount

CASE WHEN prev.AvailableBalance is null AND CTE.Available_Apply_Amount < CTE.CURTRXAM THEN CTE.Available_Apply_Amount
WHEN prev.AvailableBalance is null AND CTE.Available_Apply_Amount >= CTE.CURTRXAM THEN CTE.CURTRXAM
WHEN prev.AvailableBalance <> 0 AND CTE.Available_Apply_Amount >= CTE.CURTRXAM THEN CTE.CURTRXAM
WHEN prev.AvailableBalance <> 0 AND (CTE.Available_Apply_Amount - CTE.CURTRXAM) > 0 THEN  (CTE.Available_Apply_Amount - CTE.CURTRXAM)
ELSE 0 END AS Apply_Amount

FROM CTE
LEFT JOIN CTE prev ON prev.rownum = CTE.rownum - 1 AND CTE.Customer_Nbr = prev.Customer_Nbr 


Viewing all articles
Browse latest Browse all 7129

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>