API to create Quality samples and the results

Introduction/ Issue:  This blog contains an API and that can be used in Oracle EBS to create Quality samples and the corresponding results.

Why we need to do / Cause of the issue: The business requires creating a large number of quality samples and their corresponding results using an API, without any manual effort.

How do we solve: Create an Oracle package to create Quality samples and the results.

 

CREATE OR REPLACE PACKAGE      xx_gmd_qc_sample_result_pkg AS

/***********************************************************************************************

Who                When                 Version          Description

Mohan G         04-Nov-2025            1.0              To create Sample and assign test results

 

************************************************************************************************/

g_conc_request_id number;

PROCEDURE xx_validate_samples (

errbuf   OUT VARCHAR2,

retcode  OUT NUMBER

);

— Create QC Samples

PROCEDURE xx_create_samples (

errbuf   OUT VARCHAR2,

retcode  OUT NUMBER

);

 

— Load QC Sample Results

PROCEDURE xx_load_qc_sample_results (

errbuf   OUT VARCHAR2,

retcode  OUT NUMBER, p_sample_id IN NUMBER, p_sample_no IN VARCHAR2

);

 

END xx_gmd_qc_sample_result_pkg;

/

CREATE OR REPLACE PACKAGE BODY xx_gmd_qc_sample_result_pkg IS

/***********************************************************************************************

Who                When                 Version          Description

Mohan G         04-Nov-2025            1.0              To create Sample and assign test results

************************************************************************************************/

PROCEDURE xx_validate_samples (

errbuf   OUT VARCHAR2,

retcode  OUT NUMBER

) IS

CURSOR c_validate IS

SELECT staging_id,

sample_no,

item_no,

whse_code,

lot_no,

specification,

specification_vers

FROM xx.xx_gmd_qc_samples_stg

WHERE NVL(process_flag, ‘N’) = ‘N’;

l_inv_id      mtl_system_items_b.inventory_item_id%TYPE;

l_lot_count   NUMBER;

l_spec_count  NUMBER;

l_error_msg   VARCHAR2(2000);

l_user_id     NUMBER;

l_username    VARCHAR2(30) := ‘DATA_LOAD_USER’;

l_sample_exists NUMBER :=0;

l_errbuf  VARCHAR2(2000);

l_retcode NUMBER;

l_err_message VARCHAR2(2000);

BEGIN

SELECT user_id

INTO l_user_id

FROM fnd_user

WHERE user_name = l_username;

dbms_output.put_line(‘Before Update1′);

UPDATE XX.XX_GMD_QC_SAMPLES_STG

SET creation_Date = sysdate,

Created_by = l_user_id,

request_id = g_conc_request_id

where request_id is null and nvl(process_flag,’N’) =’N’ ;

UPDATE XX.XX_GMD_QC_SAMPLES_STG

SET sample_qty = 0

where request_id is null and nvl(process_flag,’N’) =’N’

and sample_qty is null;

UPDATE XX.XX_GMD_QC_SAMPLE_RESULTS_STG

SET creation_Date = sysdate,

Created_by = l_user_id,

request_id = g_conc_request_id

where request_id is null and nvl(process_flag,’N’) =’N’ ;

commit;

retcode := 0;

errbuf  := NULL;

FOR rec IN c_validate LOOP

l_error_msg := NULL;

dbms_output.put_line(‘Inside Loop’);

BEGIN

— Validate Sample number

BEGIN

dbms_output.put_line(‘number 1’);

SELECT count(*)

INTO l_sample_exists

FROM gmd_samples

where sample_no = rec.sample_no;

IF l_sample_exists >=1 THEN

l_error_msg := ‘Given sample number is already available in the system’;

END IF;

EXCEPTION

WHEN OTHERS THEN

l_error_msg := ‘Error while validating the sample number’;

END;

dbms_output.put_line(‘l_sample_exists 1 ‘|| l_sample_exists);

IF l_error_msg IS NULL THEN

— Validate Item & Organization

dbms_output.put_line(‘l_error_msg 1 ‘|| l_error_msg);

BEGIN

SELECT msib.inventory_item_id

INTO l_inv_id

FROM mtl_system_items_b msib,

org_organization_definitions ood

WHERE msib.organization_id = ood.organization_id

AND msib.segment1 = rec.item_no

AND ood.organization_code = rec.whse_code;

EXCEPTION

WHEN NO_DATA_FOUND THEN

l_error_msg := ‘Invalid Item number / Organization’;

WHEN OTHERS THEN

l_error_msg := ‘Invalid Item number / Organization’;

END;

END IF;

dbms_output.put_line(‘l_inv_id 1 ‘|| l_inv_id);

— Validate Lot

IF l_error_msg IS NULL THEN

SELECT COUNT(*)

INTO l_lot_count

FROM mtl_lot_numbers mln

WHERE mln.lot_number = rec.lot_no

AND mln.inventory_item_id = l_inv_id;

IF l_lot_count = 0 THEN

l_error_msg := ‘Given lot is not defined in the system’;

END IF;

END IF;

— Validate Specification

IF l_error_msg IS NULL THEN

BEGIN

SELECT spec_id

INTO l_spec_count

FROM gmd_specifications gs

WHERE gs.SPEC_VERS = rec.SPECIFICATION_VERS

AND gs.spec_name = rec.specification;

EXCEPTION

WHEN NO_DATA_FOUND THEN

l_error_msg := ‘Given specification not defined in the system’;

END;

END IF;

dbms_output.put_line(‘Before Update’);

— Update flag based on validation outcome

IF l_error_msg IS NULL THEN

UPDATE xx.xx_gmd_qc_samples_stg

SET process_flag  = ‘V’,

error_message = NULL

WHERE staging_id = rec.staging_id;

xx_create_samples(errbuf      => l_errbuf,

retcode     => l_retcode);

ELSE

dbms_output.put_line(‘Else Part’);

UPDATE xx.xx_gmd_qc_samples_stg

SET process_flag  = ‘E’,

error_message = l_error_msg

WHERE staging_id = rec.staging_id;

END IF;

EXCEPTION

WHEN OTHERS THEN

l_err_message := SQLERRM;

UPDATE xx.xx_gmd_qc_samples_stg

SET process_flag  = ‘E’,

error_message = l_err_message

WHERE staging_id = rec.staging_id;

dbms_output.put_line(‘Exception Part’);

commit;

END;

END LOOP;

COMMIT;

EXCEPTION

WHEN OTHERS THEN

retcode := 2;

errbuf  := ‘Error in xx_validate_samples: ‘ || SQLERRM;

ROLLBACK;

DBMS_OUTPUT.put_line(errbuf);

END xx_validate_samples;

PROCEDURE xx_create_samples (

errbuf   OUT VARCHAR2,

retcode  OUT NUMBER

) IS

CURSOR c_sample_data IS

SELECT *

FROM xx.xx_gmd_qc_samples_stg

WHERE process_flag = ‘V’;

l_inv_id                mtl_system_items_b.inventory_item_id%TYPE;

l_sample_rec            gmd_samples%ROWTYPE;

x_qc_samples_rec        gmd_samples%ROWTYPE;

x_sampling_events_rec   gmd_sampling_events%ROWTYPE;

x_sample_spec_disp      gmd_sample_spec_disp%ROWTYPE;

x_event_spec_disp_rec   gmd_event_spec_disp%ROWTYPE;

x_results_tab           gmd_api_pub.gmd_results_tab;

x_spec_results_tab      gmd_api_pub.gmd_spec_results_tab;

x_return_status         VARCHAR2(10);

x_msg_data              VARCHAR2(2000);

x_msg_count             NUMBER := 0;

l_user_id               NUMBER;

l_username              VARCHAR2(30) := ‘DATA_LOAD_USER’;

g_conc_request_id       NUMBER := fnd_profile.VALUE(‘CONC_REQUEST_ID’);

l_dummy                 VARCHAR2(1000);

l_org_id                NUMBER := 0;

l_errbuf  VARCHAR2(2000);

l_retcode NUMBER;

BEGIN

retcode := 0;

errbuf  := NULL;

SELECT user_id

INTO l_user_id

FROM fnd_user

WHERE user_name = l_username;

fnd_global.apps_initialize(user_id      => l_user_id,

resp_id      => 23805,

resp_appl_id => 552);

l_errbuf  := NULL;

l_retcode := 0;

FOR rec IN c_sample_data LOOP

BEGIN

DBMS_OUTPUT.put_line(‘Loop Started’);

— Get inventory item id again (validated already, but safe)

SELECT msib.inventory_item_id, ood.organization_id

INTO l_inv_id, l_org_id

FROM mtl_system_items_b msib,

org_organization_definitions ood

WHERE msib.organization_id = ood.organization_id

AND msib.segment1 = rec.item_no

AND ood.organization_code = rec.whse_code;

DBMS_OUTPUT.put_line(‘Inv Id’ || l_inv_id);

— Prepare record

l_sample_rec.sample_no            := rec.sample_no;

l_sample_rec.sample_desc          := rec.sample_desc;

l_sample_rec.source               := rec.source;

l_sample_rec.sample_qty           := rec.sample_qty;

l_sample_rec.sample_qty_uom       := rec.sample_uom;

l_sample_rec.sampler_id           := l_user_id;

l_sample_rec.lab_organization_id  := NVL(rec.lab_org,l_org_id);

l_sample_rec.organization_id      := l_org_id;

l_sample_rec.inventory_item_id    := l_inv_id;

l_sample_rec.sample_disposition   := rec.sample_disposition;

l_sample_rec.delete_mark          := 0;

l_sample_rec.sample_type          := rec.sample_type;

l_sample_rec.priority             := rec.priority;

l_sample_rec.attribute2           := rec.attribute2;

l_sample_rec.lot_number           := rec.lot_no;

l_sample_rec.date_drawn           := rec.date_drawn;

— Call API

gmd_samples_pub.create_samples(

p_api_version             => 3.0,

p_init_msg_list           => fnd_api.g_false,

p_commit                  => fnd_api.g_false,

p_validation_level        => fnd_api.g_valid_level_full,

p_qc_samples_rec          => l_sample_rec,

p_user_name               => l_username,

p_find_matching_spec      => ‘Y’,

p_grade                   => NULL,

p_lpn                     => NULL,

p_create_new_sample_group => ‘N’,

x_qc_samples_rec          => x_qc_samples_rec,

x_sampling_events_rec     => x_sampling_events_rec,

x_sample_spec_disp        => x_sample_spec_disp,

x_event_spec_disp_rec     => x_event_spec_disp_rec,

x_results_tab             => x_results_tab,

x_spec_results_tab        => x_spec_results_tab,

x_return_status           => x_return_status,

x_msg_count               => x_msg_count,

x_msg_data                => x_msg_data

);

IF x_return_status = fnd_api.g_ret_sts_success THEN

DBMS_OUTPUT.put_line(‘Sample Created: ‘ || x_qc_samples_rec.sample_no);

UPDATE xx.xx_gmd_qc_samples_stg

SET process_flag  = ‘S’,

error_message = NULL

–sample_id     = x_qc_samples_rec.sample_id

WHERE staging_id = rec.staging_id;

UPDATE XX.XX_GMD_QC_SAMPLE_RESULTS_STG xgsr

set xgsr.sample_id = x_qc_samples_rec.sample_id

where xgsr.sample_no = rec.sample_no;

xx_load_qc_sample_results(l_errbuf,l_retcode,x_qc_samples_rec.sample_id, rec.sample_no);

ELSE

— Collect API messages

FOR i IN 1 .. fnd_msg_pub.count_msg LOOP

fnd_msg_pub.get(i, fnd_api.g_false, x_msg_data, l_dummy);

DBMS_OUTPUT.put_line(‘API Error: ‘ || x_msg_data);

END LOOP;

UPDATE xx.xx_gmd_qc_samples_stg

SET process_flag  = ‘E’,

error_message = SUBSTR(x_msg_data, 1, 2000)

WHERE staging_id = rec.staging_id;

END IF;

EXCEPTION

WHEN OTHERS THEN

UPDATE xx.xx_gmd_qc_samples_stg

SET process_flag  = ‘E’,

error_message = SUBSTR(‘Unexpected error during creation: ‘ || 1, 2000)

WHERE staging_id = rec.staging_id;

DBMS_OUTPUT.put_line(‘Unexpected error: ‘ || SQLERRM);

END;

END LOOP;

COMMIT;

EXCEPTION

WHEN OTHERS THEN

retcode := 2;

errbuf  := ‘Error in xx_create_samples: ‘ || SQLERRM;

ROLLBACK;

DBMS_OUTPUT.put_line(errbuf);

END xx_create_samples;

———————————————————————

— Procedure: xx_load_qc_sample_results

— Purpose  : Record QC test results for given sample

———————————————————————

PROCEDURE xx_load_qc_sample_results (

errbuf   OUT VARCHAR2,

retcode  OUT NUMBER, p_sample_id IN NUMBER, p_sample_no IN VARCHAR2

) IS

CURSOR c_test_results IS

SELECT xgqs.staging_id,

xgqs.sample_no,

xgqs.seq,

xgqs.test_code,

— xgqs.test_id,

xgqs.result_value_num,

xgqs.result_value_char,

xgqs.result_date,

xgqs.test_replicate_cnt,

gr.sample_id,

gr.test_id

FROM xx.XX_GMD_QC_SAMPLE_results_STG xgqs,gmd_results gr

WHERE xgqs.sample_id = gr.sample_id

and xgqs.seq = gr.seq

AND NVL(xgqs.process_flag, ‘N’) = ‘N’

and gr.sample_id = p_sample_id

and xgqs.sample_no = p_sample_no;

l_results_rec        gmd_results_pub.results_rec;

l_results_out        gmd_results%ROWTYPE;

l_spec_results_out   gmd_spec_results%ROWTYPE;

l_org_id             NUMBER;

l_status             VARCHAR2(1);

l_msg_data           VARCHAR2(4000);

l_msg_count          NUMBER := 0;

l_username           VARCHAR2(30) := ‘DATA_LOAD_USER’;

l_user_id            NUMBER;

l_errbuf  VARCHAR2(2000);

l_retcode NUMBER;

l_dummy    VARCHAR2(1000);

BEGIN

SELECT user_id

INTO l_user_id

FROM fnd_user

WHERE user_name = l_username;

fnd_global.apps_initialize(user_id      => l_user_id,

resp_id      => 23805,

resp_appl_id => 552);

UPDATE XX.XX_GMD_QC_SAMPLE_results_STG

SET creation_Date = sysdate,

Created_by = l_user_id,

request_id = g_conc_request_id

where request_id is null and nvl(process_flag,’N’) =’N’;

UPDATE XX.XX_GMD_QC_SAMPLE_RESULTS_STG

SET creation_Date = sysdate,

Created_by = l_user_id,

request_id = g_conc_request_id

where request_id is null and nvl(process_flag,’N’) =’N’ ;

commit;

SELECT organization_id

INTO l_org_id

FROM gmd_samples

WHERE sample_id = p_sample_id;

retcode := 0;

errbuf  := NULL;

FOR rec IN c_test_results LOOP

l_results_rec.sample_id := p_sample_id;

l_results_rec.test_id := rec.test_id;

l_results_rec.test_code := rec.test_code;

l_results_rec.result_value := NVL(rec.result_value_num, rec.result_value_char);

l_results_rec.result_date := rec.result_date;

l_results_rec.organization_id := l_org_id;

l_results_rec.seq       := rec.seq;

— l_results_rec.lab_organization_id := l_org_id;

l_results_rec.test_replicate_cnt := rec.test_replicate_cnt;

gmd_results_pub.record_results (

p_api_version   => 3.0,

p_init_msg_list => fnd_api.g_false,

p_commit        => fnd_api.g_false,

p_validation_level => fnd_api.g_valid_level_full,

p_results_rec   => l_results_rec,

p_user_name     => l_username,

x_results_rec   => l_results_out,

x_spec_results_rec => l_spec_results_out,

x_return_status => l_status,

x_msg_count     => l_msg_count,

x_msg_data      => l_msg_data,

p_user_responsibility_id => 0

);

IF l_status = fnd_api.g_ret_sts_success THEN

DBMS_OUTPUT.put_line(‘Result Loaded ? Sample: ‘ || p_sample_id ||

‘, Test ID: ‘ || rec.test_id ||

‘, Test Code: ‘ || rec.test_code ||

‘, Status: ‘ || l_status ||

‘, Message: ‘ || l_msg_data);

UPDATE xx.XX_GMD_QC_SAMPLE_RESULTS_STG

SET process_flag  = ‘S’,

error_message = NULL

–sample_id     = x_qc_samples_rec.sample_id

WHERE staging_id = rec.staging_id;

ELSE

— Collect API messages

FOR i IN 1 .. fnd_msg_pub.count_msg LOOP

fnd_msg_pub.get(i, fnd_api.g_false, l_msg_data, l_dummy);

DBMS_OUTPUT.put_line(‘API Error: ‘ || l_msg_data);

END LOOP;

UPDATE xx.XX_GMD_QC_SAMPLE_RESULTS_STG

SET process_flag  = ‘E’,

error_message = SUBSTR(l_msg_data, 1, 2000)

WHERE staging_id = rec.staging_id;

END IF;

 

COMMIT;

END LOOP;

 

EXCEPTION

WHEN OTHERS THEN

retcode := 2;

errbuf := ‘Error in xx_load_qc_sample_results: ‘ || SQLERRM;

DBMS_OUTPUT.put_line(errbuf);

END xx_load_qc_sample_results;

END xx_gmd_qc_sample_result_pkg;

/

 

Recent Posts