Create WIP Job via External Application (APEX Integration)

Introduction/ Issue:  In Oracle E-Business Suite (EBS), WIP Discrete Jobs are typically created manually. However, when integrating with external applications like Oracle APEX, automation is required to streamline the process.

This solution provides a PL/SQL Package that allows external applications to create WIP jobs programmatically and integrate seamlessly with EBS.

Why we need to do / Cause of the issue:

  • External systems (APEX / MES / other applications) need to create jobs dynamically
  • Reduce dependency on manual EBS operations
  • Ensure accurate and consistent job data
  • Enable real-time job creation for manufacturing processes

 

How do we solve:

A custom Oracle PL/SQL package was developed to:

  • Validate Organization, Item, and Job data
  • Insert records into WIP Job Schedule Interface
  • Submit the WIP Mass Load concurrent program
  • Return status messages for integration feedback

Integration with APEX:
APEX can call this package via PL/SQL blocks allowing external users or systems to create WIP jobs directly in EBS, without manual intervention.

 

CREATE OR REPLACE PACKAGE APPS.xx_wip_job_pkg AS

 

PROCEDURE create_job_with_validation (

p_org_code          IN       VARCHAR2,

p_item_code         IN       VARCHAR2,

p_job_name          IN       VARCHAR2,

p_quantity          IN       NUMBER,

p_class_code        IN       VARCHAR2,

p_schedule_date     IN       DATE,

p_completion_date   IN       DATE,

p_batch_number      IN       VARCHAR2,

p_runcard_number    IN       VARCHAR2,

P_creation_flag in varchar2,

p_Child_job_name in Varchar2,

p_message           OUT      VARCHAR2

);

END xx_wip_job_pkg;

/

 

CREATE OR REPLACE PACKAGE BODY APPS.xx_wip_job_pkg

AS

PROCEDURE get_initialization (

p_user_id   OUT   NUMBER,

p_appl_id   OUT   NUMBER,

p_resp_id   OUT   NUMBER,

p_message   OUT   VARCHAR2

)

IS

BEGIN

SELECT user_id

INTO p_user_id

FROM apps.fnd_user

WHERE UPPER (user_name) = ‘THARUNKUMAR’;

 

SELECT application_id

INTO p_appl_id

FROM apps.fnd_application_tl

WHERE application_name = ‘Work in Process’;

 

SELECT responsibility_id

INTO p_resp_id

FROM apps.fnd_responsibility_tl

WHERE responsibility_name = ‘Work in Process’;

 

p_message := ‘SUCCESS’;

EXCEPTION

WHEN NO_DATA_FOUND

THEN

p_message := ‘Invalid Initialization.’ || SQLERRM;

ROLLBACK;

WHEN OTHERS

THEN

p_message := ‘Invalid Initialization. Contact IT Team: ‘ || SQLERRM;

ROLLBACK;

END get_initialization;

 

PROCEDURE create_job_with_validation (

p_org_code          IN       VARCHAR2,

p_item_code         IN       VARCHAR2,

p_job_name          IN       VARCHAR2,

p_quantity          IN       NUMBER,

p_class_code        IN       VARCHAR2,

p_schedule_date     IN       DATE,

p_completion_date   IN       DATE,

p_batch_number      IN       VARCHAR2,

p_runcard_number    IN       VARCHAR2,

p_creation_flag     IN       VARCHAR2,

p_child_job_name    IN       VARCHAR2,

p_message           OUT      VARCHAR2

)

IS

l_org_id               NUMBER;

l_item_id              NUMBER;

l_dummy                NUMBER;

l_group_id             NUMBER          := TO_CHAR (SYSDATE, ‘ddhhmmss’);

— fnd_global.conc_request_id;

— or a sequence if needed

l_request_id           NUMBER;

l_interface_id         NUMBER;

l_user_id              NUMBER;                        —       := 7616;

— Replace with your actual user_id

l_resp_id              NUMBER;                       —       := 20560;

— Replace with your responsibility_id

l_appl_id              NUMBER;                          —      := 706;

— Replace with your application_id (usually WIP = 401)

l_phase                VARCHAR2 (100);

l_status               VARCHAR2 (100);

l_dev_phase            VARCHAR2 (100);

l_dev_status           VARCHAR2 (100);

l_message              VARCHAR2 (4000);

l_sleep_seconds        NUMBER          := 5;   — Check every 5 seconds

l_timeout_seconds      NUMBER          := 300;

— Timeout after 5 minutes (optional)

l_start_time           DATE            := SYSDATE;

l_success              BOOLEAN;

l_job_status_flag      NUMBER;

l_exists               NUMBER;

l_lot_number           VARCHAR2 (200);

l_completion_sub_inv   VARCHAR2 (200);

l_load_type            NUMBER;

l_process_phase        NUMBER;

l_process_status       NUMBER;

BEGIN

get_initialization (l_user_id, l_appl_id, l_resp_id, p_message);

 

IF p_message = ‘SUCCESS’

THEN

NULL;

ELSE

RETURN;

END IF;

 

IF p_creation_flag = ‘CREATION’

THEN

l_load_type := 1;

l_process_phase := 2;

l_process_status := 1;

 

BEGIN

SELECT organization_id

INTO l_org_id

FROM org_organization_definitions

WHERE organization_code = UPPER (TRIM (p_org_code));

EXCEPTION

WHEN NO_DATA_FOUND

THEN

p_message :=

‘Organization Not Exists Contact IT Team: organization Name=’

|| p_org_code;

DBMS_OUTPUT.put_line (p_message);

RETURN;

WHEN OTHERS

THEN

p_message :=

‘Organization Unexpected issue: Contact IT Team: ‘

|| SQLERRM;

RETURN;

END;

 

DBMS_OUTPUT.put_line (p_message);

 

— Step 1: Get Org ID

BEGIN

SELECT 1

INTO l_exists

FROM apps.wip_discrete_jobs_v

WHERE wip_entity_name = p_job_name AND organization_id = l_org_id;

 

p_message := ‘Job Already Exists: ‘ || p_job_name;

RETURN;

EXCEPTION

WHEN NO_DATA_FOUND

THEN

NULL;

WHEN OTHERS

THEN

p_message :=

‘Job Unexpected issue: Contact IT Team: ‘ || SQLERRM;

RETURN;

END;

 

DBMS_OUTPUT.put_line (‘p_message’ || p_message);

 

— Step 2: Get Item ID

BEGIN

SELECT inventory_item_id

INTO l_item_id

FROM apps.mtl_system_items_b

WHERE segment1 = UPPER (TRIM (p_item_code))

AND organization_id = l_org_id;

EXCEPTION

WHEN NO_DATA_FOUND

THEN

p_message :=

‘Item Not Exists Contact IT Team: Item Name=’

|| p_item_code

|| ‘ l_org_id=’

|| l_org_id;

RETURN;

WHEN OTHERS

THEN

p_message :=

‘Organization Unexpected issue: Contact IT Team: ‘

|| SQLERRM;

RETURN;

END;

 

DBMS_OUTPUT.put_line (‘p_message’ || p_message);

 

BEGIN

SELECT lookup_code

INTO l_job_status_flag

FROM apps.fnd_lookup_values

WHERE lookup_type = ‘WIP_JOB_STATUS’

AND enabled_flag = ‘Y’

AND meaning = ‘Released’;

EXCEPTION

WHEN NO_DATA_FOUND

THEN

p_message :=

‘Lookup code Not Exists fro for  lookup_type = ”WIP_JOB_STATUS” and meaning = ”Released” Contact IT Team: ‘;

RETURN;

WHEN OTHERS

THEN

p_message :=

‘Lookup code Unexpected issue: Contact IT Team: ‘

|| SQLERRM;

RETURN;

END;

/*

— Step 3: BOM Validation

BEGIN

SELECT 1

INTO l_dummy

FROM bom_bill_of_materials

WHERE assembly_item_id = l_item_id AND organization_id = l_org_id;

EXCEPTION

WHEN NO_DATA_FOUND

THEN

p_message := ‘No BOM found for Item: ‘ || p_item_code;

DBMS_OUTPUT.put_line (‘p_message’ || p_message);

RETURN;

WHEN OTHERS

THEN

p_message :=

‘bom_bill_of_materials Unexpected issue: Contact IT Team: ‘

|| SQLERRM;

RETURN;

END;*/

ELSIF p_creation_flag = ‘COMPLETE’

THEN

l_load_type := 3;

l_process_phase := 2;

l_process_status := 1;

 

BEGIN

SELECT lookup_code

INTO l_job_status_flag

FROM apps.fnd_lookup_values

WHERE lookup_type = ‘WIP_JOB_STATUS’

AND enabled_flag = ‘Y’

AND meaning = ‘Complete’;

EXCEPTION

WHEN NO_DATA_FOUND

THEN

p_message :=

‘Lookup code Not Exists fro for  lookup_type = ”WIP_JOB_STATUS” and meaning = ”Released” Contact IT Team: ‘;

RETURN;

WHEN OTHERS

THEN

p_message :=

‘Lookup code Unexpected issue: Contact IT Team: ‘

|| SQLERRM;

RETURN;

END;

 

IF p_job_name IS NOT NULL

THEN

l_lot_number := p_job_name;

l_completion_sub_inv := ‘Shop Floor’;                –Shop Floor

ELSE

p_message := ‘ job_name is null  P_job_name: ‘ || p_job_name;

END IF;

 

BEGIN

SELECT organization_id

INTO l_org_id

FROM org_organization_definitions

WHERE organization_code = UPPER (TRIM (p_org_code));

EXCEPTION

WHEN NO_DATA_FOUND

THEN

p_message :=

‘Organization Not Exists Contact IT Team: organization Name=’

|| p_org_code;

DBMS_OUTPUT.put_line (p_message);

RETURN;

WHEN OTHERS

THEN

p_message :=

‘Organization Unexpected issue: Contact IT Team: ‘

|| SQLERRM;

RETURN;

END;

 

DBMS_OUTPUT.put_line (p_message);

 

— Step 1: Get Org ID

BEGIN

SELECT 1

INTO l_exists

FROM apps.wip_discrete_jobs_v

WHERE wip_entity_name = p_job_name AND organization_id = l_org_id;

EXCEPTION

WHEN NO_DATA_FOUND

THEN

p_message := ‘Job Not Exists: ‘ || p_job_name;

RETURN;

WHEN OTHERS

THEN

p_message :=

‘Job Unexpected issue: Contact IT Team: ‘ || SQLERRM;

RETURN;

END;

 

DBMS_OUTPUT.put_line (‘p_message’ || p_message);

 

— Step 2: Get Item ID

BEGIN

SELECT inventory_item_id

INTO l_item_id

FROM apps.mtl_system_items_b

WHERE segment1 = UPPER (TRIM (p_item_code))

AND organization_id = l_org_id;

EXCEPTION

WHEN NO_DATA_FOUND

THEN

p_message :=

‘Item Not Exists Contact IT Team: Item Name=’

|| p_item_code

|| ‘ l_org_id=’

|| l_org_id;

RETURN;

WHEN OTHERS

THEN

p_message :=

‘Organization Unexpected issue: Contact IT Team: ‘

|| SQLERRM;

RETURN;

END;

ELSIF p_creation_flag = ‘CLOSED’

THEN

BEGIN

SELECT lookup_code

INTO l_job_status_flag

FROM apps.fnd_lookup_values

WHERE lookup_type = ‘WIP_JOB_STATUS’

AND enabled_flag = ‘Y’

AND meaning = ‘Closed’;

EXCEPTION

WHEN NO_DATA_FOUND

THEN

p_message :=

‘Lookup code Not Exists fro for  lookup_type = ”WIP_JOB_STATUS” and meaning = ”Released” Contact IT Team: ‘;

RETURN;

WHEN OTHERS

THEN

p_message :=

‘Lookup code Unexpected issue: Contact IT Team: ‘

|| SQLERRM;

RETURN;

END;

ELSE

p_message := ‘Creation Flag Not Valid for : ‘ || p_creation_flag;

END IF;

 

–Released  –3

–Complete –4

–Closed–12

 

— Step 4: Insert into WIP_JOB_SCHEDULE_INTERFACE

SELECT apps.wip_job_schedule_interface_s.NEXTVAL

INTO l_interface_id

FROM DUAL;

 

—WIP.WIP_INTERFACE_ERRORS

BEGIN

INSERT INTO apps.wip_job_schedule_interface

(interface_id, GROUP_ID, organization_id, job_name,

primary_item_id, start_quantity, net_quantity,

first_unit_start_date, class_code, status_type,

load_type, process_phase, process_status,

creation_date, created_by, last_update_date,

last_updated_by, attribute1, attribute2,

attribute3, attribute4, completion_subinventory,

lot_number

)

VALUES (l_interface_id, l_group_id, l_org_id, p_job_name,

l_item_id, p_quantity, p_quantity,

p_schedule_date, p_class_code,           –p_class_code,

l_job_status_flag,

— released,closed,comolete

l_load_type,

— Create Standard Discrete Job

l_process_phase,         — Validation phase

l_process_status, — Pending

SYSDATE, l_user_id                            — user id

, SYSDATE,

l_user_id,                                   — user id,

p_child_job_name, p_runcard_number,

— job card no

p_batch_number,                — original job referance

p_batch_number, l_completion_sub_inv,

l_lot_number

);

 

DBMS_OUTPUT.put_line (‘l_org_id: ‘ || l_org_id);

DBMS_OUTPUT.put_line (‘p_job_name: ‘ || p_job_name);

DBMS_OUTPUT.put_line (‘l_item_id: ‘ || l_item_id);

DBMS_OUTPUT.put_line (‘p_quantity: ‘ || p_quantity);

DBMS_OUTPUT.put_line (‘p_class_code: ‘ || p_class_code);

DBMS_OUTPUT.put_line (‘l_job_status_flag: ‘ || l_job_status_flag);

DBMS_OUTPUT.put_line (‘p_Child_job_name: ‘ || p_child_job_name);

DBMS_OUTPUT.put_line (‘p_runcard_number: ‘ || p_runcard_number);

DBMS_OUTPUT.put_line (‘l_completion_sub_inv: ‘

|| l_completion_sub_inv

);

DBMS_OUTPUT.put_line (‘l_lot_number: ‘ || l_lot_number);

EXCEPTION

WHEN OTHERS

THEN

p_message :=

‘Insert Unexpected issue: Contact IT Team: ‘ || SQLERRM;

RETURN;

END;

 

COMMIT;

— Step 5: Submit WIP Mass Load

apps.fnd_global.apps_initialize (user_id           => l_user_id,

–fnd_global.user_id,

resp_id           => l_resp_id,

–fnd_global.resp_id,

resp_appl_id      => l_appl_id

–fnd_global.resp_appl_id

);

 

BEGIN

l_request_id :=

fnd_request.submit_request

(application      => ‘WIP’,

program          => ‘WICMLP’,

description      => ‘WIP Mass Load from APEX’,

start_time       => NULL,

sub_request      => FALSE,

argument1        => l_group_id,

argument2        => 1

);

COMMIT;

p_message := ‘WIP Mass Load submitted. Request ID: ‘ || l_request_id;

 

— Wait for completion

LOOP

— Check status

l_success :=

apps.fnd_concurrent.wait_for_request

(request_id      => l_request_id,

INTERVAL        => 5,

max_wait        => 300,

phase           => l_phase,

status          => l_status,

dev_phase       => l_dev_phase,

dev_status      => l_dev_status,

MESSAGE         => l_message

);

 

IF l_success

THEN

DBMS_OUTPUT.put_line (‘Request Completed.’);

DBMS_OUTPUT.put_line (‘Phase: ‘ || l_dev_phase);

DBMS_OUTPUT.put_line (‘Status: ‘ || l_dev_status);

DBMS_OUTPUT.put_line (‘Message: ‘ || l_message);

ELSE

DBMS_OUTPUT.put_line

(‘Failed to wait for request or it timed out.’);

END IF;

 

EXIT WHEN l_dev_phase = ‘COMPLETE’;

 

— Optional: timeout check

IF (SYSDATE – l_start_time) * 86400 > l_timeout_seconds

THEN

raise_application_error (-20001,

‘Timeout waiting for request ‘

|| l_request_id

);

END IF;

 

DBMS_LOCK.sleep (l_sleep_seconds);

END LOOP;

 

— Output result

DBMS_OUTPUT.put_line (‘Request Completed. Status: ‘ || l_dev_status);

 

IF l_dev_status = ‘NORMAL’

THEN

p_message := ‘SUCCESS’;

ELSE

FOR rec IN (SELECT ERROR_TYPE MESSAGE_TYPE,

error AS MESSAGE_TEXT

FROM wip.wip_interface_errors

WHERE interface_id = l_interface_id)

LOOP

DBMS_OUTPUT.put_line (‘Error Type: ‘ || rec.MESSAGE_TYPE);

p_message := rec.MESSAGE_TEXT;

END LOOP;

 

— Delete interface record

/*DELETE FROM apps.wip_job_schedule_interface

WHERE interface_id = l_interface_id;*/

COMMIT;                                         — Commit deletion

DBMS_OUTPUT.put_line (‘Interface record deleted.’);

DBMS_OUTPUT.put_line (   ‘Request Failed or Warning. Message: ‘

|| l_message

);

END IF;

EXCEPTION

WHEN OTHERS

THEN

DBMS_OUTPUT.put_line (‘Error occurred: ‘ || SQLERRM);

RAISE;

END;

 

— Optional: Log

/* INSERT INTO xxttk_wip_job_log (

interface_id,

job_name,

item_code,

org_code,

bom_validated,

status,

message

) VALUES (

l_interface_id,

p_job_name,

p_item_code,

p_org_code,

‘YES’,

‘SUBMITTED’,

p_message

);*/

COMMIT;

EXCEPTION

WHEN OTHERS

THEN

p_message := ‘Error: ‘ || SQLERRM;

ROLLBACK;

END create_job_with_validation;

 

 

END xx_wip_job_pkg;

/

 

 

Recent Posts