在使用 SQL 服务器函数计算到期日方面需要帮助

Need assistance in calculating Due Date using SQL Server Functions

我正在尝试根据以下限制使用发票日期计算到期日

注意上述约束在计算火期时也必须满足闰年

请帮助我成为 SQL 服务器功能的新手

我试过的代码

DECLARE  @INVOICEDATE DATETIME ='02/01/2016'
        ,@TENANTID BIGINT=29
        ,@PAYMENTTERMID BIGINT=2

BEGIN
    DECLARE @DUEDATE DATETIME
    DECLARE @ACTUALDUEDATE BIGINT
    DECLARE @CALCULATEDDATE DATETIME
    DECLARE @PAYMENTTYPES BIGINT
    DECLARE @DAYSOFMONTH BIGINT
    DECLARE @DAYSAFTERDUEDAY BIGINT
    DECLARE @NOOFDAYS BIGINT

    SELECT @PAYMENTTYPES = PAYMENT_TYPES
        ,@NOOFDAYS = NUMBER_OF_DAYS
        ,@DAYSOFMONTH = DAY_OF_MONTH
        ,@DAYSAFTERDUEDAY = DAYS_AFTER_DUE_DAY
        FROM XC_PAYMENT_TERMS_MASTER
        WHERE TENANT_ID = @TENANTID
        AND PAYMENT_TERM_ID = @PAYMENTTERMID 

    IF @PAYMENTTYPES = 1
    BEGIN
        SET @CALCULATEDDATE = DATEADD(dd, @NOOFDAYS, @INVOICEDATE)
    END
    ELSE IF @PAYMENTTYPES = 2
    BEGIN
        SET @ACTUALDUEDATE = @DAYSOFMONTH - @DAYSAFTERDUEDAY
            IF 1 = (
            IIF(DATEPART(dd, (
                        EOMONTH(CONCAT (
                                DATEPART(yyyy, @INVOICEDATE)
                                ,'0201'
                        ))
                )) = 29, 1, 0)
            )
            --LEAP YEAR
            BEGIN
            IF(@ACTUALDUEDATE <= 0)
            BEGIN
            IF DATEPART(dd, @INVOICEDATE) = 30
            AND  DATEPART(mm, @INVOICEDATE) =01
            BEGIN
            SET @CALCULATEDDATE=DATEADD(dd, 31, @INVOICEDATE)
            END
            ELSE IF DATEPART(dd, @INVOICEDATE) = 31
            AND  DATEPART(mm, @INVOICEDATE) =01
            BEGIN
            SET @CALCULATEDDATE=DATEADD(dd, 31, @INVOICEDATE)
            END
            ELSE
            BEGIN
            IF @DAYSOFMONTH = 30 OR @DAYSOFMONTH =31
            BEGIN
            SET @CALCULATEDDATE= DATEADD(s,-1,DATEADD(mm, DATEDIFF(m,0, @INVOICEDATE)+2,0))
            END
            ELSE
            BEGIN
            DECLARE @NEWNEGATIVEDATE DATETIME
            SET @NEWNEGATIVEDATE = DATEADD(DAY, @DAYSOFMONTH - DATEPART(DAY, @INVOICEDATE), @INVOICEDATE);
            SET @DUEDATE = DATEADD(mm, 1, @NEWNEGATIVEDATE)
            END
            END
            END
            ELSE IF(@ACTUALDUEDATE > 0)
            BEGIN
            SELECT 2
            DECLARE @COMBINEDDATE DATETIME
            SET @COMBINEDDATE=DATEADD(DAY, @ACTUALDUEDATE - DATEPART(DAY, @INVOICEDATE), @INVOICEDATE);
            SELECT @INVOICEDATE AS INVDATE 
            SELECT @COMBINEDDATE AS COMBDATE
            IF @INVOICEDATE > @COMBINEDDATE
            BEGIN
            SELECT 115 AS TRUE
            DECLARE @NEWDATE DATETIME
            SET @NEWDATE = DATEADD(DAY, @DAYSOFMONTH - DATEPART(DAY, @INVOICEDATE), @INVOICEDATE);
            SET @DUEDATE = DATEADD(mm, 1, @NEWDATE)
            SELECT @DUEDATE AS DATES
            END

            ELSE 
            BEGIN
            SET @DUEDATE=DATEADD(DAY, @DAYSOFMONTH - DATEPART(DAY, @INVOICEDATE), @INVOICEDATE);
            SELECT @DUEDATE AS DATEDUE
            END

            END
            END
            ELSE 
            --NOT LEAP YEAR
            BEGIN

            END

        END
        END

最终通过创建以下函数解决了它

CREATE FUNCTION [dbo].[XC_CALCULATE_DUE_DATE] (
    @INVOICEDATE DATETIME
    ,@TENANTID BIGINT
    ,@PAYMENTTERMID BIGINT
    )
RETURNS DATETIME
AS
BEGIN
    DECLARE @DAYOFMONTH BIGINT
    DECLARE @DAYOFNEXTMONTH BIGINT
    DECLARE @PAYMENTTYPES BIGINT
    DECLARE @NOOFDAYS BIGINT

    SELECT @PAYMENTTYPES = PAYMENT_TYPES
        ,@NOOFDAYS = NUMBER_OF_DAYS
        ,@DAYOFMONTH = DAY_OF_MONTH
        ,@DAYOFNEXTMONTH = DAYS_AFTER_DUE_DAY
    FROM XC_PAYMENT_TERMS_MASTER
    WHERE TENANT_ID = @TENANTID
        AND PAYMENT_TERM_ID = @PAYMENTTERMID

    DECLARE @DIFFERENCE BIGINT = ISNULL(@DAYOFMONTH, 0) - ISNULL(@DAYOFNEXTMONTH, 0)
    DECLARE @DUEDATE DATETIME
    DECLARE @ACTUALDUEDATE BIGINT
    DECLARE @CALCULATEDDATE DATETIME

    IF @PAYMENTTYPES = 1
    BEGIN
        SET @DUEDATE = DATEADD(dd, @NOOFDAYS, @INVOICEDATE)
    END
    ELSE IF @PAYMENTTYPES = 2
    BEGIN
        DECLARE @LEAPYEAR TINYINT = IIF(DATEPART(dd, (
                        EOMONTH(CONCAT (
                                DATEPART(yyyy, @INVOICEDATE)
                                ,'0201'
                                ))
                        )) = 29, 1, 0)

        IF @DIFFERENCE <= 0
        BEGIN
            DECLARE @STARTINGDATE DATETIME
            DECLARE @NEWDATE DATETIME
            DECLARE @NEXTMONTH DATETIME

            IF 1 = @LEAPYEAR
            BEGIN
                SET @STARTINGDATE = DATEADD(month, DATEDIFF(month, 0, @INVOICEDATE), 0)
                SET @NEXTMONTH = DATEADD(MONTH, 1, @STARTINGDATE)

                IF 1 = DATEPART(MONTH, @INVOICEDATE)
                BEGIN
                    IF @DAYOFMONTH = 30
                    BEGIN
                        SET @DUEDATE = DATEADD(month, DATEDIFF(month, 0, DATEADD(MONTH, 2, @INVOICEDATE)), 0)
                    END
                    ELSE IF @DAYOFMONTH = 31
                    BEGIN
                        SET @DUEDATE = DATEADD(DAY, 1, DATEADD(month, DATEDIFF(month, 0, DATEADD(MONTH, 2, @INVOICEDATE)), 0))
                    END
                    ELSE
                    BEGIN
                        SET @DUEDATE = DATEADD(DAY, @DAYOFMONTH - 1, @NEXTMONTH)
                    END
                END
                ELSE
                BEGIN
                    SET @DUEDATE = DATEADD(DAY, @DAYOFMONTH - 1, @NEXTMONTH)
                END
            END
            ELSE
            BEGIN
                SET @STARTINGDATE = DATEADD(month, DATEDIFF(month, 0, @INVOICEDATE), 0)
                SET @NEXTMONTH = DATEADD(MONTH, 1, @STARTINGDATE)

                IF 1 = DATEPART(MONTH, @INVOICEDATE)
                BEGIN
                    IF @DAYOFMONTH = 29
                    BEGIN
                        SET @DUEDATE = DATEADD(month, DATEDIFF(month, 0, DATEADD(MONTH, 2, @INVOICEDATE)), 0)
                    END
                    ELSE IF @DAYOFMONTH = 30
                    BEGIN
                        SET @DUEDATE = DATEADD(DAY, 1, DATEADD(month, DATEDIFF(month, 0, DATEADD(MONTH, 2, @INVOICEDATE)), 0))
                    END
                    ELSE IF @DAYOFMONTH = 31
                    BEGIN
                        SET @DUEDATE = DATEADD(DAY, 2, DATEADD(month, DATEDIFF(month, 0, DATEADD(MONTH, 2, @INVOICEDATE)), 0))
                    END
                    ELSE
                    BEGIN
                        SET @DUEDATE = DATEADD(DAY, @DAYOFMONTH - 1, @NEXTMONTH)
                    END
                END
                ELSE
                BEGIN
                    SET @DUEDATE = DATEADD(DAY, @DAYOFMONTH - 1, @NEXTMONTH)
                END
            END
        END
        ELSE
        BEGIN
            DECLARE @SDATES DATETIME = DATEADD(month, DATEDIFF(month, 0, @INVOICEDATE), 0)
            DECLARE @NMONTH DATETIME = DATEADD(MONTH, 1, @SDATES)

            IF DATEPART(DD, @INVOICEDATE) > @DIFFERENCE
            BEGIN
                IF @DAYOFMONTH > 30
                    AND DATEPART(DD, @INVOICEDATE) <> @DIFFERENCE
                BEGIN
                    SET @DUEDATE = DATEADD(s, - 1, DATEADD(mm, DATEDIFF(m, 0, @NMONTH) + 1, 0))
                END
                ELSE
                BEGIN
                    SET @DUEDATE = DATEADD(DAY, @DAYOFMONTH - 1, @NMONTH)
                END
            END
            ELSE
            BEGIN
                IF @DAYOFMONTH > 30
                    AND DATEPART(DD, @INVOICEDATE) <> @DIFFERENCE
                BEGIN
                    SET @DUEDATE = DATEADD(s, - 1, DATEADD(mm, DATEDIFF(m, 0, @NMONTH) + 1, 0))
                END
                ELSE IF @DAYOFMONTH > 30
                    AND DATEPART(DD, @INVOICEDATE) = @DIFFERENCE
                BEGIN
                    SET @DUEDATE = DATEADD(s, - 1, DATEADD(mm, DATEDIFF(m, 0, @SDATES) + 1, 0))
                END
                ELSE
                BEGIN
                    SET @DUEDATE = DATEADD(DAY, @DAYOFMONTH - 1, @SDATES)
                END
            END

            IF 1 = @LEAPYEAR
            BEGIN
                IF 1 = DATEPART(MONTH, @INVOICEDATE)
                    AND DATEPART(DD, @INVOICEDATE) <> @DIFFERENCE
                BEGIN
                    IF @DAYOFMONTH > 29
                    BEGIN
                        SET @DUEDATE = DATEADD(s, - 1, DATEADD(mm, DATEDIFF(m, 0, @NMONTH) + 1, 0))
                    END
                END
            END
            ELSE
            BEGIN
                IF 1 = DATEPART(MONTH, @INVOICEDATE)
                    AND DATEPART(DD, @INVOICEDATE) <> @DIFFERENCE
                BEGIN
                    IF @DAYOFMONTH >= 29
                    BEGIN
                        SET @DUEDATE = DATEADD(s, - 1, DATEADD(mm, DATEDIFF(m, 0, @NMONTH) + 1, 0))
                    END
                END
            END
        END
    END

    RETURN @DUEDATE
END