Calculate "Number of days to pay" logic

  • I would like to ask for help to write a query that helps me calculate the number of days (approx) that it takes to a customer to pay an invoice.

    Document Types

    1 Payment

    2 Invoice

    3 Credit Memo

    4 Finance Charge Memo

    5 Reminder

    6 Refund

    There are three methods to consider when calculating the days to pay logic.

    Method 1 - Simple

    Look for Document Type 2 (Invoice), if "closed at date" > "posting date" then number of days = ("closed at date" - "posting date")

    Method 2 - A Document Type 1 (payment) closes a Document Type 2 (Invoice)

    For this method the formula would be: Payment Record (1) "posting date" - Invoice Record (2) "posting date"

    Method 3 - An Invoice closes the payment.

    On a payment entry “closed by entry no.” refers to an Invoice entry.

    a. In our code we are not on the payment looking for the invoice, we are on the invoice.

    i. Because of this we need to find the entry that our current invoiced has closed.

    I am taking this from a page that has the pascal code that I need to translate to SQL.

    I know this is a sql server forum, but I am including that code in case it helps to get sql accurate. I am really not familiar with the syntax.

    IF (CustLedgEntry2."Document Type" = CustLedgEntry2."Document Type"::Invoice) AND

    NOT CustLedgEntry2.Open

    THEN

    IF CustLedgEntry2."Closed at Date" > CustLedgEntry2."Posting Date" THEN

    UpdateDaysToPay(CustLedgEntry2."Closed at Date" - CustLedgEntry2."Posting Date")

    ELSE

    IF CustLedgEntry2."Closed by Entry No." <> 0 THEN BEGIN

    IF CustLedgEntry3.GET(CustLedgEntry2."Closed by Entry No.") THEN

    UpdateDaysToPay(CustLedgEntry3."Posting Date" - CustLedgEntry2."Posting Date");

    END ELSE BEGIN

    CustLedgEntry3.SETCURRENTKEY("Closed by Entry No.");

    CustLedgEntry3.SETRANGE("Closed by Entry No.",CustLedgEntry2."Entry No.");

    IF CustLedgEntry3.FIND('+') THEN

    UpdateDaysToPay(CustLedgEntry3."Posting Date" - CustLedgEntry2."Posting Date");

    END;

    I am also including create table and insert data scripts in hopes to get some help to figure this out.

    Thank you very much.

  • Great job posting ddl and sample data. Any chance you can trim the data to a few dozen rows instead of thousands? Also, what we need to understand is what is the output you are expecting? Once you trim down the sample data to a manageable size we would want to know what the output should be for the sample data.

    _______________________________________________________________

    Need help? Help us help you.

    Read the article at http://www.sqlservercentral.com/articles/Best+Practices/61537/ for best practices on asking questions.

    Need to split a string? Try Jeff Modens splitter http://www.sqlservercentral.com/articles/Tally+Table/72993/.

    Cross Tabs and Pivots, Part 1 – Converting Rows to Columns - http://www.sqlservercentral.com/articles/T-SQL/63681/
    Cross Tabs and Pivots, Part 2 - Dynamic Cross Tabs - http://www.sqlservercentral.com/articles/Crosstab/65048/
    Understanding and Using APPLY (Part 1) - http://www.sqlservercentral.com/articles/APPLY/69953/
    Understanding and Using APPLY (Part 2) - http://www.sqlservercentral.com/articles/APPLY/69954/

  • Hi Sean, I trimmed the number of rows to 500 just to make sure there is enough data to work the 3 methods that calculate the DaysToPay value.

    The output I need is a field that contains the value AvgDaysToPay, grouped by customer for records only for this year.

    The formula is:

    AvgDaysToPay = DaysToPay / NoOfInv

  • itortu (6/25/2014)


    Hi Sean, I trimmed the number of rows to 500 just to make sure there is enough data to work the 3 methods that calculate the DaysToPay value.

    The output I need is a field that contains the value AvgDaysToPay, grouped by customer for records only for this year.

    The formula is:

    AvgDaysToPay = DaysToPay / NoOfInv

    I meant the actual values of what you expect as output. That way we can compare our results to what you say is correct.

    _______________________________________________________________

    Need help? Help us help you.

    Read the article at http://www.sqlservercentral.com/articles/Best+Practices/61537/ for best practices on asking questions.

    Need to split a string? Try Jeff Modens splitter http://www.sqlservercentral.com/articles/Tally+Table/72993/.

    Cross Tabs and Pivots, Part 1 – Converting Rows to Columns - http://www.sqlservercentral.com/articles/T-SQL/63681/
    Cross Tabs and Pivots, Part 2 - Dynamic Cross Tabs - http://www.sqlservercentral.com/articles/Crosstab/65048/
    Understanding and Using APPLY (Part 1) - http://www.sqlservercentral.com/articles/APPLY/69953/
    Understanding and Using APPLY (Part 2) - http://www.sqlservercentral.com/articles/APPLY/69954/

  • And you might want to take a look at your sample data. It will not execute as posted. You are missing ' around all your dates.

    _______________________________________________________________

    Need help? Help us help you.

    Read the article at http://www.sqlservercentral.com/articles/Best+Practices/61537/ for best practices on asking questions.

    Need to split a string? Try Jeff Modens splitter http://www.sqlservercentral.com/articles/Tally+Table/72993/.

    Cross Tabs and Pivots, Part 1 – Converting Rows to Columns - http://www.sqlservercentral.com/articles/T-SQL/63681/
    Cross Tabs and Pivots, Part 2 - Dynamic Cross Tabs - http://www.sqlservercentral.com/articles/Crosstab/65048/
    Understanding and Using APPLY (Part 1) - http://www.sqlservercentral.com/articles/APPLY/69953/
    Understanding and Using APPLY (Part 2) - http://www.sqlservercentral.com/articles/APPLY/69954/

  • I fixed the data.

  • itortu (6/25/2014)


    I fixed the data.

    Now if you can post what you expect as output we can get started on working on a solution. I think we should reduce the amount of data significantly. Maybe just 3-4 customers. Enough to cover the logic.

    _______________________________________________________________

    Need help? Help us help you.

    Read the article at http://www.sqlservercentral.com/articles/Best+Practices/61537/ for best practices on asking questions.

    Need to split a string? Try Jeff Modens splitter http://www.sqlservercentral.com/articles/Tally+Table/72993/.

    Cross Tabs and Pivots, Part 1 – Converting Rows to Columns - http://www.sqlservercentral.com/articles/T-SQL/63681/
    Cross Tabs and Pivots, Part 2 - Dynamic Cross Tabs - http://www.sqlservercentral.com/articles/Crosstab/65048/
    Understanding and Using APPLY (Part 1) - http://www.sqlservercentral.com/articles/APPLY/69953/
    Understanding and Using APPLY (Part 2) - http://www.sqlservercentral.com/articles/APPLY/69954/

  • Here is some output I verified for some customers.

    Customer NumberAverage Days To Pay

    1000234

    100031

    1000639

    1001447

    1001994

    1002012

    1002223

    1002325

    10024-2

    1002654

    1002717

    100310

    1003939

    1004122

    1004254

    I hope this is good to get help for solution.

    I truly appreciate your willingness to help.

  • itortu (6/25/2014)


    Here is some output I verified for some customers.

    Customer NumberAverage Days To Pay

    1000234

    100031

    1000639

    1001447

    1001994

    1002012

    1002223

    1002325

    10024-2

    1002654

    1002717

    100310

    1003939

    1004122

    1004254

    I hope this is good to get help for solution.

    I truly appreciate your willingness to help.

    Boy this is really a long haul to get information here. How did you come up with those numbers? You said previously:

    The formula is:

    AvgDaysToPay = DaysToPay / NoOfInv

    What are DaysToPay and NoOfInv? I don't at all understand how for customer 10002 you can come up with 34. From your sample data the earliest PostingDate (I assume you want to use this column?) is 1/23/2014 and the most recent value is 2/20/2014. That is only 28 days. I did not look past that because this is so far off. Help me to help you by giving me the information required to help you find a solution.

    _______________________________________________________________

    Need help? Help us help you.

    Read the article at http://www.sqlservercentral.com/articles/Best+Practices/61537/ for best practices on asking questions.

    Need to split a string? Try Jeff Modens splitter http://www.sqlservercentral.com/articles/Tally+Table/72993/.

    Cross Tabs and Pivots, Part 1 – Converting Rows to Columns - http://www.sqlservercentral.com/articles/T-SQL/63681/
    Cross Tabs and Pivots, Part 2 - Dynamic Cross Tabs - http://www.sqlservercentral.com/articles/Crosstab/65048/
    Understanding and Using APPLY (Part 1) - http://www.sqlservercentral.com/articles/APPLY/69953/
    Understanding and Using APPLY (Part 2) - http://www.sqlservercentral.com/articles/APPLY/69954/

  • I attached one more time the insert data script.

    I made sure I ran it in my development environment and for only a few customers:

    ('10002', '10003', '10006', '10014', '10019', '10020', '10022', '10023', '10024', '10026', '10027', '10031', '10039', '10041', '10042')

    Then I got into the software in the development environment that uses the pascal code I posted in the first comment and the Number Average Days To Pay per Customer are:

    Customer NumberDays To Pay

    1000228 <<<<< You were right on the number of days to pay

    1000311

    1000639

    1001447

    100190

    1002012

    1002266

    1002325

    10024-2

    100260

    1002713

    100310

    1003934

    1004117

    1004255

    The Number of Invoices is calculated in the code:

    IF CustLedgEntry2.FIND('+') THEN

    REPEAT

    j := CustLedgEntry2."Document Type";

    IF j > 0 THEN

    NoOfDoc[j] := NoOfDoc[j] + 1;

    CustLedgEntry2.CALCFIELDS("Amount (LCY)");

    CustBalanceLCY := CustBalanceLCY - CustLedgEntry2."Amount (LCY)";

    IF CustBalanceLCY > HighestBalanceLCY THEN

    HighestBalanceLCY := CustBalanceLCY;

    // Optimized Approximation

    IF (CustLedgEntry2."Document Type" = CustLedgEntry2."Document Type"::Invoice) AND

    NOT CustLedgEntry2.Open

    THEN

    IF CustLedgEntry2."Closed at Date" > CustLedgEntry2."Posting Date" THEN

    UpdateDaysToPay(CustLedgEntry2."Closed at Date" - CustLedgEntry2."Posting Date")

    ELSE

    IF CustLedgEntry2."Closed by Entry No." <> 0 THEN BEGIN

    IF CustLedgEntry3.GET(CustLedgEntry2."Closed by Entry No.") THEN

    UpdateDaysToPay(CustLedgEntry3."Posting Date" - CustLedgEntry2."Posting Date");

    END ELSE BEGIN

    CustLedgEntry3.SETCURRENTKEY("Closed by Entry No.");

    CustLedgEntry3.SETRANGE("Closed by Entry No.",CustLedgEntry2."Entry No.");

    IF CustLedgEntry3.FIND('+') THEN

    UpdateDaysToPay(CustLedgEntry3."Posting Date" - CustLedgEntry2."Posting Date");

    END;

    UNTIL CustLedgEntry2.NEXT(-1) = 0;

    IF NoOfInv <> 0 THEN

    AvgDaysToPay := DaysToPay / NoOfInv;

    If you notice, it checks for a Document Type of Invoice, right after // Optimized Approximation, and also for the column Open to be 0

    Then the 3 methods begin.

    There is also a check when the second method check begins: IF CustLedgEntry2."Closed by Entry No." <>

    I apologize for making this a long process. I do struggle with clarity when making posts. I am trying to the best of my abilities.

    Thank you for your help.

  • You are going to have to provide some of the business rules. Simply pasting a portion of some code is not going to cut it. It appears from the code that there are some rules based on the order of the data. What is the order? There are lots of people around that can help but you have to put in some effort. We need to know what the rules are.

    Why is CustomerNo 10003 11? Why isn't it 22?

    _______________________________________________________________

    Need help? Help us help you.

    Read the article at http://www.sqlservercentral.com/articles/Best+Practices/61537/ for best practices on asking questions.

    Need to split a string? Try Jeff Modens splitter http://www.sqlservercentral.com/articles/Tally+Table/72993/.

    Cross Tabs and Pivots, Part 1 – Converting Rows to Columns - http://www.sqlservercentral.com/articles/T-SQL/63681/
    Cross Tabs and Pivots, Part 2 - Dynamic Cross Tabs - http://www.sqlservercentral.com/articles/Crosstab/65048/
    Understanding and Using APPLY (Part 1) - http://www.sqlservercentral.com/articles/APPLY/69953/
    Understanding and Using APPLY (Part 2) - http://www.sqlservercentral.com/articles/APPLY/69954/

Viewing 11 posts - 1 through 10 (of 10 total)

You must be logged in to reply to this topic. Login to reply