Skip to main content

Applying AR Credit Memo to AR Invoice using AR_CM_API_PUB.APPLY_ON_ACCOUNT

 

In Oracle Apps R12, the process of applying on-account credits to customer invoices can be complex. Oracle provides the AR_CM_API_PUB.APPLY_ON_ACCOUNT API to facilitate this process. This API is particularly useful when there is a need for programmatic application of credit memos (CM) to invoices.

API: AR_CM_API_PUB.APPLY_ON_ACCOUNT API


Staging Table Design:

CREATE TABLE XX_AR_CM_STG
(
   TRANSACTION_ID      NUMBER, 
   OPERATING_UNIT    VARCHAR2(240),
   ORG_ID    NUMBER, 
   CM_NUMBER           VARCHAR2(50),  -- Credit Memo Number
   INVOICE_NUMBER      VARCHAR2(50),  -- Invoice Number
   APPLIED_AMOUNT      NUMBER,  -- Amount to be applied
   APPLIED_DATE    DATE,
   CT_REFERENCE    VARCHAR2(240),
   CUSTOMER_NUMBER     VARCHAR2(50),  -- Customer number
   STATUS              VARCHAR2(1), -- NULL - Not Processed, E - Error, S - Successfully Processed
   ERROR_MESSAGE       VARCHAR2(4000),  -- Error message in case of failure
   LAST_UPDATE_DATE    DATE DEFAULT SYSDATE,
   LAST_UPDATED_BY     NUMBER
);

Procedure:


create or replace PROCEDURE xx_apply_cm_to_invoice
AS
    l_return_status               VARCHAR2 (20);
    l_msg_count                   NUMBER;
    l_msg_data                    VARCHAR2 (4000);
    l_trx_id                      ra_customer_trx_all.customer_trx_id%TYPE;
    l_cm_trx_id                   ra_customer_trx_all.customer_trx_id%TYPE;
    l_user_id                     NUMBER := fnd_global.user_id; -- Set current user ID
    l_resp_id                     NUMBER := fnd_global.resp_id; -- Set current RESP ID
    l_resp_appl_id                NUMBER := fnd_global.resp_appl_id; -- Set current RESP APPL ID
    l_error_message               VARCHAR2 (4000); -- To capture error messages
    k_api_version        CONSTANT NUMBER := 1;
    k_init_msg_list      CONSTANT VARCHAR2 (1) := fnd_api.g_false;
    k_comments                    ar_receivable_applications.comments%TYPE;
    k_commit             CONSTANT VARCHAR2 (1) := fnd_api.g_false;
    l_acctd_amount_applied_from   ar_receivable_applications_all.acctd_amount_applied_from%TYPE;
    l_acctd_amount_applied_to     ar_receivable_applications_all.acctd_amount_applied_to%TYPE;
    l_cm_app_rec                  ar_cm_api_pub.cm_app_rec_type;
    l_out_rec_application_id      NUMBER;
    l_msg_index_OUT number;
    CURSOR c1 IS
        SELECT cm_number,
               invoice_number,
               applied_amount,
               org_id,
               applied_date,
               ct_reference,
               status,
               error_message
          FROM xx_ar_cm_stg
         WHERE NVL (status, 'N') = 'N';
BEGIN
    mo_global.init ('AR');
    mo_global.set_policy_context ('S', 101);
    fnd_global.apps_initialize (l_user_id, l_resp_id, l_resp_appl_id);
    FOR rec IN c1
    LOOP
        -- Initialize variables to NULL at the beginning of each iteration
        l_return_status := NULL;
        l_msg_count := NULL;
        l_msg_data := NULL;
        l_trx_id := NULL;
        l_cm_trx_id := NULL;
        l_error_message := NULL;           -- Initialize error message to NULL
        BEGIN
            -- Get transaction ID for the Invoice
            BEGIN
                SELECT customer_trx_id
                  INTO l_trx_id
                  FROM ra_customer_trx_all
                 WHERE     trx_number = rec.invoice_number
                       AND org_id = rec.org_id;
            EXCEPTION
                WHEN NO_DATA_FOUND
                THEN
                    l_error_message := 'Invoice number not found';
                WHEN OTHERS
                THEN
                    l_error_message :=
                        'Error fetching Invoice ID: ' || SQLERRM;
            END;
            -- Get transaction ID for the Credit Memo
            IF l_error_message IS NULL
            THEN               -- Only proceed if no error from previous block
                BEGIN
                    SELECT customer_trx_id
                      INTO l_cm_trx_id
                      FROM ra_customer_trx_all
                     WHERE trx_number = rec.cm_number AND org_id = rec.org_id;
                EXCEPTION
                    WHEN NO_DATA_FOUND
                    THEN
                        l_error_message := 'Credit Memo number not found';
                    WHEN OTHERS
                    THEN
                        l_error_message :=
                            'Error fetching Credit Memo ID: ' || SQLERRM;
                END;
            END IF;
            -- Apply the credit memo if no errors so far
            IF l_error_message IS NULL
            THEN
                l_cm_app_rec.cm_customer_trx_id := l_cm_trx_id;
                l_cm_app_rec.cm_trx_number := NULL;      -- credit memo number
                l_cm_app_rec.inv_customer_trx_id := l_trx_id;
                l_cm_app_rec.inv_trx_number := NULL;         -- invoice number
                l_cm_app_rec.installment := NULL;
                l_cm_app_rec.applied_payment_schedule_id := NULL;
                l_cm_app_rec.amount_applied := rec.applied_amount;
                l_cm_app_rec.apply_date := rec.applied_date;
                l_cm_app_rec.gl_date := rec.applied_date;
                l_cm_app_rec.inv_customer_trx_line_id := NULL;
                l_cm_app_rec.inv_line_number := NULL;
                l_cm_app_rec.show_closed_invoices := NULL;
                l_cm_app_rec.ussgl_transaction_code := NULL;
                l_cm_app_rec.attribute_category := NULL;
                l_cm_app_rec.attribute1 := NULL;
                l_cm_app_rec.attribute2 := NULL;
                l_cm_app_rec.attribute3 := NULL;
                l_cm_app_rec.attribute4 := NULL;
                l_cm_app_rec.attribute5 := NULL;
                l_cm_app_rec.attribute6 := NULL;
                l_cm_app_rec.attribute7 := NULL;
                l_cm_app_rec.attribute8 := NULL;
                l_cm_app_rec.attribute9 := NULL;
                l_cm_app_rec.attribute10 := NULL;
                l_cm_app_rec.attribute11 := NULL;
                l_cm_app_rec.attribute12 := NULL;
                l_cm_app_rec.attribute13 := NULL;
                l_cm_app_rec.attribute14 := NULL;
                l_cm_app_rec.attribute15 := NULL;
                l_cm_app_rec.global_attribute_category := NULL;
                l_cm_app_rec.global_attribute1 := NULL;
                l_cm_app_rec.global_attribute2 := NULL;
                l_cm_app_rec.global_attribute3 := NULL;
                l_cm_app_rec.global_attribute4 := NULL;
                l_cm_app_rec.global_attribute5 := NULL;
                l_cm_app_rec.global_attribute6 := NULL;
                l_cm_app_rec.global_attribute7 := NULL;
                l_cm_app_rec.global_attribute8 := NULL;
                l_cm_app_rec.global_attribute9 := NULL;
                l_cm_app_rec.global_attribute10 := NULL;
                l_cm_app_rec.global_attribute11 := NULL;
                l_cm_app_rec.global_attribute12 := NULL;
                l_cm_app_rec.global_attribute12 := NULL;
                l_cm_app_rec.global_attribute14 := NULL;
                l_cm_app_rec.global_attribute15 := NULL;
                l_cm_app_rec.global_attribute16 := NULL;
                l_cm_app_rec.global_attribute17 := NULL;
                l_cm_app_rec.global_attribute18 := NULL;
                l_cm_app_rec.global_attribute19 := NULL;
                l_cm_app_rec.global_attribute20 := NULL;
                l_cm_app_rec.comments := rec.ct_reference;
                l_cm_app_rec.called_from := null;

                ar_cm_api_pub.apply_on_account (
                    p_api_version               => k_api_version,
                    p_init_msg_list             => k_init_msg_list,
                    p_commit                    => k_commit,
                    p_cm_app_rec                => l_cm_app_rec,
                    x_return_status             => l_return_status,
                    x_msg_count                 => l_msg_count,
                    x_msg_data                  => l_msg_data,
                    x_out_rec_application_id    => l_out_rec_application_id,
                    x_acctd_amount_applied_from   =>
                        l_acctd_amount_applied_from,
                    x_acctd_amount_applied_to   => l_acctd_amount_applied_to);
                dbms_output.put_line('l_return_status: ' || l_return_status);
                dbms_output.put_line('l_msg_count: ' || l_msg_count);
                dbms_output.put_line('l_msg_data: ' || l_msg_data);
                
                -- Check return status of API call
                IF l_return_status <> 'S'
                THEN
                    -- Fetch error message if API failed
                    FOR i IN 1 .. l_msg_count
                    LOOP
                        fnd_msg_pub.get (p_msg_index   => i,
                                         p_encoded     => 'F',
                                         p_data        => l_msg_data,
                                            p_msg_index_OUT   => l_msg_index_OUT);
                        EXIT WHEN l_msg_data IS NULL;
                    END LOOP;
                    l_error_message := l_msg_data;
                END IF;
                 FOR i IN 1 .. l_msg_count
                    LOOP
                        fnd_msg_pub.get (p_msg_index   => i,
                                         p_encoded     => 'F',
                                         p_data        => l_msg_data,
                                            p_msg_index_OUT   => l_msg_index_OUT);
                                            dbms_output.put_line('Error: '|| l_msg_data);
                        EXIT WHEN l_msg_data IS NULL;
                    END LOOP;
            END IF;
            -- Update the staging table with either success or error
            UPDATE xx_ar_cm_stg
               SET status = l_return_status,
                   error_message = l_error_message, -- Update with error message if any
                   last_update_date = SYSDATE,
                   last_updated_by = l_user_id
             WHERE     cm_number = rec.cm_number
                   AND invoice_number = rec.invoice_number;
        EXCEPTION
            WHEN OTHERS
            THEN
            dbms_output.put_line('ERROR_STACK: ' || DBMS_UTILITY.FORMAT_ERROR_STACK);
dbms_output.put_line('ERROR_BACKTRACE: ' || DBMS_UTILITY.FORMAT_ERROR_BACKTRACE);
                l_error_message := 'Unhandled exception: ' || SQLERRM;
                -- Single update for unhandled exceptions
                UPDATE xx_ar_cm_stg
                   SET status = 'E',
                       error_message = l_error_message,
                       last_update_date = SYSDATE,
                       last_updated_by = l_user_id
                 WHERE     cm_number = rec.cm_number
                       AND invoice_number = rec.invoice_number;
        END;
    END LOOP;
END xx_apply_cm_to_invoice;

Execution:

set SERVEROUTPUT on;
BEGIN
  XX_APPLY_CM_TO_INVOICE();
--rollback; 
END;

/


Error Handling:

The AR_CM_API_PUB.APPLY_ON_ACCOUNT API provides error messages through the FND_MSG_PUB package. In the above code, we loop through any returned messages and store them in the staging table for troubleshooting.


Comments

Popular posts from this blog

API to Create & Update Price Adjustment and Order Lines

Important Tables: select header_id from oe_order_headers_all; select line_id from oe_order_lines_all; select list_header_id from qp_list_headers_all; select list_line_id from qp_list_lines; CREATE OR REPLACE PROCEDURE apps.xxapply_discount (p_header_id number) IS    v_api_version_number           number := 1;    v_return_status                varchar2 (2000);    v_msg_count                    number;    v_msg_data                     varchar2 (2000);    -- in variables --    v_header_rec                   oe_order_pub.header_rec_type;    v_line_tbl                     oe_order_pub.line_tbl_type;    v_action_request_tbl   ...

LDT Commands in Oracle Apps

 Oracle Applications (Oracle E-Business Suite) use Loader Data files (LDT files) for migrating application configurations and data between instances. What are LDT Files? LDT files are plain text files used by the FNDLOAD utility in Oracle E-Business Suite to upload or download data from the database. They are commonly used for migrating setups, such as concurrent programs, value sets, and lookups, across different environments. LDT Commands: 1.        Download Data to LDT File FNDLOAD apps/apps_pwd 0 Y DOWNLOAD $FND_TOP/patch/115/import/afcpprog.lct output_file.ldt FND_PROGRAM APPLICATION_SHORT_NAME="Application_Short_Name" CONCURRENT_PROGRAM_NAME="Program_Name" 2.        Upload Data from LDT File FNDLOAD apps/apps_pwd 0 Y UPLOAD $FND_TOP/patch/115/import/afcpprog.lct input_file.ldt Key Parameters apps/apps_pwd : The username and password for the Oracle Apps database. 0 Y...

Uninvoiced Receipts Query Oracle r12

Uninvoiced Receipts: SELECT   pha.segment1 po_number,          TO_CHAR (pha.creation_date, 'DD-MON-RRRR') po_date,          (SELECT   vendor_name             FROM   ap_suppliers ap            WHERE   ap.vendor_id = pha.vendor_id)             supplier_name,          pla.quantity,          pla.unit_price,          pla.quantity * pla.unit_price AS line_amount,          (SELECT   concatenated_segments             FROM   gl_code_combinations_kfv gcc            WHERE   gcc.code_combination_id = pda.code_combination_id)             charge_account,          rsh...