

In the previous article we talked about the process of loading BEE values into Oracle from the front end forms. The manual entry on the form takes the maximum time. If instead of the manual form entry we use the WebADI process then the time reduces a lot. We can design an interface to load the values very fast, The process will be as follows,
Step 1: Decide the data file format
The data file format has been decided to be like the following,
Batch Sequence | Batch Name | Element Name | Effective Date | Employee Number | Value | Business Group | Reason | Effective Start Date | Effective End Date | Batch Line Status |
Step 2: Design the custom database objects
We need to create the following A custom table to store the BEE values A custom sequence to assign each BEE line with a unique ID A custom secure view to pick up only the unprocessed BEE data. This view is very useful for designing a custom form on top of the custom table. Apply grants on all the custom objects to APPS as the objects will be created in the custom schema Create synonyms for all the custom objects in APPS schema
-- The code in custom schema CREATE TABLE hcl_bee_load_data ( load_id NUMBER, batch_sequence NUMBER, batch_name VARCHAR2(100), element_name VARCHAR2(140), element_id NUMBER, effective_date DATE, assignment_number VARCHAR2(40), VALUE NUMBER, business_group_id NUMBER, reason VARCHAR2(200), effective_start_date DATE, effective_end_date DATE, batch_line_status VARCHAR2(100), CONSTRAINT load_pk PRIMARY KEY (load_id) ) GRANT ALL ON HCL_BEE_LOAD_DATA TO APPS / DROP SEQUENCE HCL.HCL_BEE_SEQ / CREATE SEQUENCE hcl.hcl_bee_seq START WITH 100 MAXVALUE 999999999999999999999999999 MINVALUE 100 NOCYCLE NOCACHE NOORDER / GRANT ALL ON HCL_BEE_SEQ TO APPS / CREATE SYNONYM pay_batch_element_entry_api FOR apps.pay_batch_element_entry_api / CREATE OR REPLACE VIEW hcl_bee_batch_v AS SELECT batch_name, business_group_id, COUNT (batch_name) num FROM hcl_bee_load_data WHERE batch_line_status = 'Unprocessed' AND business_group_id = fnd_profile.VALUE ('PER_BUSINESS_GROUP_ID') GROUP BY batch_name, business_group_id / GRANT ALL ON hcl_bee_batch_v TO APPS / GRANT ALL ON hcl_bee_upload_pkg to APPS / -- The code for APPS schema CREATE OR REPLACE SYNONYM HCL_BEE_LOAD_DATA FOR HCL.HCL_BEE_LOAD_DATA / CREATE OR REPLACE SYNONYM HCL_BEE_SEQ FOR HCL.HCL_BEE_SEQ / CREATE OR REPLACE SYNONYM hcl_bee_batch_v FOR HCL.hcl_bee_batch_v / GRANT EXECUTE ON pay_batch_element_entry_api TO hcl / CREATE OR REPLACE SYNONYM HCL_BEE_UPLOAD_PKG FOR HCL.HCL_BEE_UPLOAD_PKG /
Step 3: Develop the control file for SQL Loader
The control file was developed based on the input file format.
OPTIONS (SKIP=1,ERRORS=5000) LOAD DATA APPEND INTO TABLE "HCL"."HCL_BEE_LOAD_DATA" FIELDS TERMINATED BY "," OPTIONALLY ENCLOSED BY '"' TRAILING NULLCOLS ( Batch_sequence "TRIM(:Batch_sequence)", Batch_name "TRIM(:Batch_name)", Element_name "TRIM(:Element_name)", Effective_Date "TRIM(TO_DATE(:Effective_Date,'DD-MON-RRRR'))", Employee_number "TRIM(:Employee_number)", Value "TRIM(:Value)", Business_group_id "TRIM(:Business_group_id)", Reason "TRIM(:Reason)", Effective_start_Date "TRIM(TO_DATE(:Effective_start_Date,'DD-MON-RRRR'))", Effective_end_Date "TRIM(TO_DATE(:Effective_end_Date,'DD-MON-RRRR'))", Batch_line_status "TRIM(:Batch_line_status)", Load_id "HCL_BEE_SEQ.NEXTVAL" )
Step 4: Develop the custom interface code
The custom interface code
CREATE OR REPLACE PACKAGE hcl_bee_upload_pkg AUTHID CURRENT_USER IS PROCEDURE load_bee_data (p_batch_name VARCHAR2, errbuf OUT VARCHAR2, retcode OUT NUMBER); END hcl_bee_upload_pkg; CREATE OR REPLACE PACKAGE BODY hcl_bee_upload_pkg IS PROCEDURE load_bee_data (p_batch_name VARCHAR2, errbuf OUT VARCHAR2, retcode OUT NUMBER) IS e_headerexist EXCEPTION; PRAGMA EXCEPTION_INIT (e_headerexist, -20020); TYPE cur_ref_type IS REF CURSOR; c_ref_cursor cur_ref_type; l_batch_id NUMBER; l_ovn NUMBER; v_batch_header_id NUMBER; l_assignment_number NUMBER; l_element_type_id NUMBER; v_batch_line_id NUMBER; v_date_track DATE; v_cursor_query VARCHAR2 (2000); v_batch_header hcl_bee_load_data.batch_name%TYPE; v_num NUMBER; v_business_group_id NUMBER; v_header_count NUMBER := 0; v_line_count NUMBER := 0; v_line_err_count NUMBER := 0; CURSOR c_batch_headers IS SELECT batch_name, COUNT (batch_name) num FROM hcl_bee_load_data WHERE batch_line_status = 'Unprocessed'; TYPE type_batch_headers IS TABLE OF c_batch_headers%ROWTYPE INDEX BY BINARY_INTEGER; t_batch_headers type_batch_headers; CURSOR c_batch_lines (p_batch_name VARCHAR2) IS SELECT batch_det.load_id, batch_det.batch_sequence, batch_det.element_name, batch_det.ora_element_name, batch_det.element_type_id, batch_det.VALUE, batch_det.reason, batch_det.effective_date, batch_det.effective_start_date, batch_det.effective_end_date, batch_det.batch_line_status, assignment.assignment_number FROM (SELECT hbl.load_id, hbl.batch_sequence, hbl.element_name, hem.ora_element_name, pet.element_type_id, hbl.VALUE, hbl.reason, hbl.effective_date, hbl.effective_start_date, hbl.effective_end_date, hbl.batch_line_status FROM pay_element_types_f pet, hcl_bee_load_data hbl, hcl_element_mapping hem WHERE hbl.batch_line_status = 'Unprocessed' AND hbl.business_group_id = pet.business_group_id AND hem.business_group_id = pet.business_group_id AND hbl.business_group_id = fnd_profile.VALUE ('PER_BUSINESS_GROUP_ID') AND hem.hcl_element_name = hbl.element_name AND hem.ora_element_name = pet.element_name AND hbl.batch_name = p_batch_name) batch_det, (SELECT hbl.batch_sequence, ppx.employee_number assignment_number FROM per_people_x ppx, per_assignments_x pax, hcl_bee_load_data hbl WHERE hbl.business_group_id = ppx.business_group_id AND pax.business_group_id = pax.business_group_id AND pax.person_id = ppx.person_id AND ppx.employee_number = hbl.employee_number AND hbl.batch_line_status = 'Unprocessed' AND hbl.business_group_id = fnd_profile.VALUE ('PER_BUSINESS_GROUP_ID')) assignment WHERE assignment.batch_sequence = batch_det.batch_sequence ORDER BY 1; TYPE type_batch_lines IS TABLE OF c_batch_lines%ROWTYPE INDEX BY BINARY_INTEGER; t_batch_lines type_batch_lines; BEGIN v_business_group_id := fnd_profile.VALUE ('PER_BUSINESS_GROUP_ID'); fnd_file.put_line (fnd_file.output, '-------------------------------------------------------------------'); fnd_file.put_line (fnd_file.output, '------------------- BEE Load program -------------------'); fnd_file.put_line (fnd_file.output, '-------------------------------------------------------------------'); -- Check if batch name has been passed IF p_batch_name IS NULL THEN -- If batch name is null then pick up all batch headers for this business group which are unprocessed v_cursor_query := 'SELECT batch_name, COUNT (batch_name) num FROM hcl_bee_load_data WHERE batch_line_status = ''Unprocessed'' AND business_group_id = :business_group_id GROUP BY batch_name'; ELSE -- If batch name is passed then pick up only that batch header for processing v_cursor_query := 'SELECT batch_name, COUNT (batch_name) num FROM hcl_bee_load_data WHERE batch_line_status = ''Unprocessed'' AND business_group_id = :business_group_id AND batch_name = ''' || p_batch_name || ''' GROUP BY batch_name'; END IF; OPEN c_ref_cursor FOR v_cursor_query USING fnd_profile.VALUE ('PER_BUSINESS_GROUP_ID'); <<bee_batch_header_loop>> LOOP FETCH c_ref_cursor INTO v_batch_header, v_num; EXIT WHEN c_ref_cursor%NOTFOUND; BEGIN -- Check whether the batch exists before creating the header BEGIN SELECT batch_id INTO v_batch_header_id FROM pay_batch_headers WHERE batch_name = v_batch_header; -- The header exist. Exit program IF v_batch_header_id IS NOT NULL THEN RAISE e_headerexist; NULL; END IF; EXCEPTION WHEN NO_DATA_FOUND THEN -- The header does not exist. Hence create the header fnd_file.put_line (fnd_file.output, 'The batch header ' || v_batch_header || ' does not exist. Creating batch header'); END; pay_batch_element_entry_api.create_batch_header (p_validate => FALSE, p_session_date => SYSDATE, p_batch_name => v_batch_header, p_batch_status => 'U', p_business_group_id => fnd_profile.VALUE ('PER_BUSINESS_GROUP_ID'), p_action_if_exists => 'U', p_batch_reference => v_batch_header, p_batch_source => 'BEE Load Program', p_comments => NULL, p_date_effective_changes => 'U', p_purge_after_transfer => 'N', p_reject_if_future_changes => 'Y', p_batch_id => l_batch_id, p_object_version_number => l_ovn, p_reject_if_results_exists => 'Y', p_purge_after_rollback => 'N', p_batch_type => 'Batch Entry', p_reject_entry_not_removed => 'N', p_rollback_entry_updates => 'N' ); SELECT batch_id INTO v_batch_header_id FROM pay_batch_headers WHERE batch_name = v_batch_header; EXCEPTION WHEN e_headerexist THEN -- The header exists already. Terminate program fnd_file.put_line (fnd_file.output, 'The batch header ' || v_batch_header || ' exists already.'); fnd_file.put_line (fnd_file.output, 'Hence the program will delete all records for this batch header will be deleted'); fnd_file.put_line (fnd_file.output, 'Please use a new name for batch header and load these records'); -- Deleting the records so that these are not processed again DELETE FROM hcl_bee_load_data WHERE batch_line_status = 'Unprocessed' AND business_group_id = fnd_profile.VALUE ('PER_BUSINESS_GROUP_ID') AND batch_name = v_batch_header; COMMIT; retcode := 1; END; -- Lines are being loaded now OPEN c_batch_lines (v_batch_header); <<bee_batch_lines_loop>> LOOP FETCH c_batch_lines BULK COLLECT INTO t_batch_lines LIMIT 500; EXIT WHEN t_batch_lines.COUNT = 0; FOR i IN 1 .. t_batch_lines.COUNT LOOP BEGIN pay_batch_element_entry_api.create_batch_line (p_validate => FALSE, p_session_date => NVL (v_date_track, SYSDATE), p_batch_id => v_batch_header_id, p_assignment_id => NULL, p_assignment_number => t_batch_lines (i).assignment_number, p_batch_sequence => t_batch_lines (i).batch_sequence, --l_success_rec+1 p_effective_date => t_batch_lines (i).effective_date, p_element_type_id => t_batch_lines (i).element_type_id, p_entry_type => 'E', p_value_1 => t_batch_lines (i).VALUE, p_batch_line_id => v_batch_line_id, p_object_version_number => l_ovn ); fnd_file.put_line (fnd_file.LOG, 'Created Line with Assignment Num ' || t_batch_lines (i).assignment_number || ' Batch sequence: ' || t_batch_lines (i).batch_sequence || ' Effective date: ' || t_batch_lines (i).effective_date || ' Element type id: ' || t_batch_lines (i).element_type_id || ' Value: ' || t_batch_lines (i).VALUE); UPDATE hcl_bee_load_data SET batch_line_status = 'Processed' WHERE load_id = t_batch_lines (i).load_id; -- Increase counter by 1 v_line_count := v_line_count + 1; EXCEPTION WHEN OTHERS THEN -- Update the line with status Error UPDATE hcl_bee_load_data SET batch_line_status = 'Error' WHERE load_id = t_batch_lines (i).load_id; fnd_file.put_line (fnd_file.output, '-------------------------------------------------------------------'); fnd_file.put_line (fnd_file.output, 'Error for Line with Assignment Num ' || t_batch_lines (i).assignment_number || ' Batch sequence: ' || t_batch_lines (i).batch_sequence || ' Effective date: ' || t_batch_lines (i).effective_date || ' Element type id: ' || t_batch_lines (i).element_type_id || ' Value: ' || t_batch_lines (i).VALUE); fnd_file.put_line (fnd_file.output, 'Error is ' || SQLCODE || ' - ' || SQLERRM); -- Increase line error count v_line_err_count := v_line_err_count + 1; END; END LOOP; END LOOP bee_batch_lines_loop; fnd_file.put_line (fnd_file.output, 'Batch Header: ' || v_batch_header); fnd_file.put_line (fnd_file.output, 'Number of lines processed: ' || v_line_count); fnd_file.put_line (fnd_file.output, 'Number of error lines: ' || v_line_err_count); fnd_file.put_line (fnd_file.output, '-------------------------------------------------------------------'); -- Initialize the line counters to 0 for the next header v_line_count := 0; v_line_err_count := 0; END LOOP bee_batch_header_loop; CLOSE c_ref_cursor; fnd_file.put_line (fnd_file.output, '-------------------------------------------------------------------'); END load_bee_data; END hcl_bee_upload_pkg;
Step 5: Register the AOL objects
All the AOL objects need to be created and registered. Here are the AOL objects. HCL BEE Upload SQL Loader program
HCL BEE Wrapper program
BEE request set
Define stages
Requests
Link stages
Test the process
We created a CSV file in MS Excel and dropped the file on the server on the custom top directory as the control file is located there. Then the request set, HCL BEE Loading process, was executed to load the BEE values. The CSV file was populated like this,
Batch Sequence | Batch Name | Element Name | Effective Date | Employee Number | Value | Business Group | Reason | Effective Start Date | Effective End Date | Batch Line Status |
1 | Test100 | Others Pay |
1-Apr-10 |
83228 |
27660 |
81 |
1-Apr-10 |
Unprocessed | ||
2 | Test100 | Pay Advance Recovery |
1-Apr-10 |
81034 |
28190 |
81 |
1-Apr-10 |
Unprocessed | ||
3 | Test100 | Pay Advance Recovery |
1-Apr-10 |
83228 |
28490 |
81 |
1-Apr-10 |
Unprocessed | ||
4 | Test100 | Others Pay |
1-Apr-10 |
83232 |
28190 |
81 |
1-Apr-10 |
Unprocessed | ||
5 | Test100 | Others Pay |
1-Apr-10 |
2 |
27260 |
81 |
1-Apr-10 |
Unprocessed | ||
6 | Test100 | Pay Advance Recovery |
1-Apr-10 |
2 |
27260 |
81 |
1-Apr-10 |
Unprocessed | ||
7 | Test100 | Pay Advance Recovery |
1-Apr-10 |
83232 |
27380 |
81 |
1-Apr-10 |
Unprocessed | ||
8 | Test100 | Others Pay |
1-Apr-10 |
81034 |
27500 |
81 |
1-Apr-10 |
Unprocessed |
After executing the request set HCL BEE Loading process all the records will be ready to be imported into Oracle. Cheers!
The P2P or Procure To Pay cycle is vital to an organization as in this process the organization buys and received goods or services from its vendors and makes necessary payments.
The P2P cycle comprises of the following steps,
Step 1: Create requisition
Responsibility: Any Purchasing responsibility
Navigation: Requisition > Requisition Summary
Click on New button
Create a new Purchase Requisition.
Enter the requisition details and save the form.
Step 2: Approve the requisition
After the requisition is saved the Approve button is enabled.
Click on the Approve button to send the requisition for approval.
Click on OK button and the requisition will be sent for approval.
Now go into Workflow Administrator responsibility to approve the workflow.
Check Activity History.
Open the Notification and approve it
After the requisition is approved the status of the requisition will change to Approved.
Step 3: Create the Purchase Order from the requisition
When the Requisition is approved we need to create a Purchase Order for it. We shall use the AutoCreate feature of Purchasing to do the conversion from Requisition to Purchase Order.
Responsibility: Purchasing responsibility
Navigation: AutoCreate
Enter the requisition number, 112005226, and click on Find.
You might get the message above. This because a Buyer (shown on the screen) is not assigned to the requisition.
Navigation: Management > Manage Buyer Workload
Enter the requisition number, 112005226, and click on Find button.
Now assign a Buyer to the requisition so that this requisition can be picked up by him to create the Purchase order.
We shall assign a new buyer, Uzair Ahmed Khan, and select the requisition.
Save the form.
You will get a confirmation message.
Now you need to log into oracle as the Uzair Ahmed Khan (i.e. the buyer who was set on the requisition). After logging in to Oracle, go to a Purchasing responsibility.
Open the AutoCreate form.
Enter the requisition number, 112005226, and click on Find button. The AutoCreate Documents form opens with the requisition details.
Select the requisition. We shall take the default values,
Action: Create
Document Type: Standard PO
Grouping: Default
Click on Automatic button.
Click on Create button to create the PO. The PO form opens with the new PO details that has been created from the requisition.
The PO number is 412005703.
Step 4: Approve the Purchase Order
Enter the Supplier and the supplier site on this PO. As the PO description is set to mandatory enter some text as description.
Save the PO. Click on the Shipments button.
The Shipments form opens. We find the shipping org is set to IFS. This means that the goods will be received in the IFS org when it is shipped by the supplier (Step 5).
Close the Shipment form to go back to the PO form. Click on Approve button to send the PO for approval.
The Approve Document form opens. Click on OK button to send the PO for approval.
The Budgetary control message appears. Click on OK and the PO will go for approval.
Once the PO is approved the status changes to Approved, Reserved.
Step 5: Receive the goods/items
Once the PO is sent to the supplier to be fulfilled the supplier sends the goods to the organization. The goods now have to be received in Oracle.
To receive goods go to any Purchasing responsibility that has the receiving functionality.
Navigation: Receiving > Receipts
The Organization screen opens. Select IFS (As checked in PO shipment in Step 4) and click on OK.
Enter the PO number and the supplier name is populated automatically.
Click on Find button. The receipt header form opens.
Close this form and the Receipts form opens.
Select the Line. You can change the quantity received at this juncture. We shall change the quantity received from 10 to 5.
Save the form.
To get the receipt number, click on the Header button.
You now have the receipt number, 111208387.
Close all the forms
Step 6: Inspect the goods
Now that we have received the goods based on the PO (even though the shipment was partial) we need to have the goods inspected and QA check done (This is required if the PO is based on 4 way matching, else the payment cannot be made).
Responsibility: Purchasing responsibility that has the Receiving Transactions or QA functionality enabled
Navigation: Receiving > Receiving Transactions
Enter the Purchase Order Number, i.e. 412005703.
The supplier number is populated automatically. Now click on Find button.
Note that the Inspection status shows as Not Inspected – Standard Receipt and the Destination Type is Inventory.
Click on Inspect button. The inspection window opens.
We are going to pass all 5 goods as part of the QA check process. We shall select Quality Code from the list of values as Excellent.
Enter a comment on the right most field.
Press OK button. The window will close and the receipt status will change to Inspect. Requery the receiving transaction on the PO.
Note that the Inspection field has the value, Accepted – Standard Receipt. QA check has been completed. Close the form.
Step 7: Create Payables invoice
Responsibility: Payables responsibility to create an AP invoice
Navigation: Invoice > Entry > Invoices
Create an Invoice for supplier 7 EMIRATES SUPERMARKETS. This is the supplier which had received the PO (Refer to Step 3 or 4).
Note:
We are creating the invoice manually in this case. The invoice can be created automatically by executing the concurrent program named, Pay on Receipt AutoInvoice, from the Purchasing responsibility and entering the goods receipt number (GRN) as the parameter.
Click on Match button at the bottom right of the form.
Important:
We shall not enter the invoice distribution as this will come automatically from matching the invoice with PO receipt.
There are 3 options for matching.
We are matching Receipt to this invoice so that the supplier is paid for only the amount that has been received in the store.
Matching is done in 3 ways
Type of matching | Description |
2-way | PO and Invoice quantity and total amounts are matched |
3-way | PO, Invoice, Receipt quantity and total amounts are matched |
4-way | PO, Invoice, Receipt, QA (Acceptance) quantity and total amounts are matched |
Find Receipts form opens.
Enter the Receipt number (End of Step 5)
Click on Find button. Match to Receipts form opens.
Check the box under Match.
Notice that the Distribution Total is in Red. It means that the Invoice header amount and distribution amounts are not matching. Click on Match button at the bottom
You will be taken back to the Invoice form. Modify the Invoice header amount to match the amount of the distribution.
Now you can validate the Invoice by clicking on Actions button on the Invoice form and selecting Validate.
Click on OK button.
Now the invoice status changes to Validated.
Close the invoice form.
Step 8: Pay the invoice
We are going to create a single payment to pay the invoice (invoice number #BALLPENS1) created earlier.
Responsibility: Payables responsibility with payment functionality
Navigation: Payments > Entry > Payments
Enter the bank and supplier details
Click on Enter/Adjust Invoices button to enter the invoice
Save and close this window.
Click on Actions button. Select Format and Print Remittance Advice.
Click on OK. The Payment Process Manager will handle the payment and will execute the remittance program as well to make the payment.
After the processes are over the supplier is paid fully for the goods that he has supplied.
Step 9: Receive the remaining goods or Close the Invoice line
The supplier has been paid for the goods that have been received in the stores but we have received 5 goods out of the total number of 10. Therefore we have the option of receiving 5 more to complete the PO. If we receive the other 5 goods then we have to create another invoice to pay off those received goods.
If we do not want to receive the remaining goods but instead we want to close the PO at this stage then we need to Close the PO line so that the remaining quantity is cancelled and the PO is closed.
Note:
If we do not finish this step the PO will remain in open state and the amount will go into encumbrance, i.e. the open amount will be carried over to the next periods as the amount which will need to be paid to the supplier.
Responsibility: Purchasing responsibility
Navigation: Purchase Orders > Purchase Order Summary
Query for the PO, i.e. 412005703.
Click on Find.
Click on Lines button.
On the top menu click on Tools > Control. You will get a popup message.
Click on OK.
The Control Documents window opens. Select Finally Close and enter a reason.
Click on OK button.
Click on OK button. Now requery the PO.
The PO is now Closed. Note the PO status, Approved, Closed, Reserved.
Step 10: Transfer Payables data to General Ledger
Responsibility: Payables
Navigation: View > Requests
Execute the program. Payables Transfer to General Ledger
After the program completes check the output.
Note the value of Journal Import Group ID. It is 609337.
Step 11: Import Journal into General Ledger
Responsibility: General Ledger responsibility which can run Journal Import
Navigation: Journal > Import > Run
The Journal Import form opens. Select Source as Payables and Selection Criteria as Specific Group Ids. Enter the value of the Group Id from the previous step, i.e. 609337.
Click on Import
Click on Yes.
You get the concurrent request ID as 20165930.
Now go to View > Requests and click on Find and check the concurrent program.
Once the program completes check the output. The output shows the details of the journals created. You can open the journal for viewing and posting.
The P2P cycle is now complete.
Cheers!