之前一直对这个功能感觉很神秘。最近有个需求要客制化这点(将客制的PR的栏位自动带到PO里面),所以针对这个自动创建的逻辑过程了解了一下。
这些写下来,好让有需要了解或者有需求要修改的人可以知道这个是啥逻辑的。
-----------------------------
自动创建Form:POXBWVRP
点创建对应的按钮:NEW_DOCUMENT.OK
执行代码:
action.autocreate_button('WHEN-BUTTON-PRESSED');
接着找,对应执行的代码:
核心处理库:POXBWVRP.pll
new_document5.ok('WHEN-BUTTON-PRESSED');
核心PR自动创建PO的过程:action4.autocreate_documents;
------------------------------
简而言之,其实所谓的PR自动创建PO,程序的逻辑是:
先根据PR的数据塞PO的接口表po_headers_interface/po_lines_interface,
然后再调用API(PO_INTERFACE_S.create_documents)生成对应的PO信息。
当然,这里我说的只是最核心的逻辑,前面的一大堆PR是否可以自动生成PO等等的验证,还有另外的连带的数据产生等等也是必须的。
------------------------------
action4.autocreate_documents;部分代码:
begin
insert into po_headers_interface
(interface_header_id,
interface_source_code,
batch_id,
process_code, /* This used to be process_flag */
action, /* This used to be action_type_code */
document_type_code,
document_subtype,
document_num,
group_code,
vendor_id,
vendor_site_id,
release_num,
release_date,
agent_id,
currency_code,
rate_type_code, /* This used to be rate_type */
rate_date,
rate,
vendor_list_header_id,
-- quote_type_lookup_code, <-- no longer in headers_interface
-- quotation_class_code, <-- no longer in headers_interface
--DPCARD{
pcard_id,
--DPCARD}
creation_date,
created_by,
last_update_date,
last_updated_by,
org_id, --<R12 MOAC>
style_id) --<R12 STYLES PHASE II >
values
(x_interface_header_id,
'PO',
x_batch_id,
x_action_type_code_hdr,
x_document_mode,
x_document_type,
x_document_subtype,
x_segment1,
x_group_code,
x_vendor_id,
x_vendor_site_id,
x_release_number,
x_release_date,
x_agent_id,
x_currency_code,
x_rate_type,
x_rate_date,
x_rate,
x_vendor_list_header_id,
-- x_quote_type_lookup_code,
-- x_quotation_class_code,
--DPCARD{
x_pcard_id,
--DPCARD}
x_creation_date,
x_created_by,
x_last_update_date,
x_last_updated_by,
l_purchasing_org_id, --<R12 MOAC>
l_style_id); --<R12 STYLES PHASE II >
exception
when others then
fnd_message.debug('In exception when trying to insert into po_headers');
raise form_trigger_failure;
end;
/******************************************************************
PO_LINES_INTERFACE stuff
******************************************************************/
/* Loop thru the selected req lines and insert into
* the po_lines_interface table.
*/
x_progress:='003';
for i in 1..x_num_records loop
/* Get the action_type_code_line = NEW, ADD, NULL */
if (name_in('POXBWVRP_WORLD.IN_PLACEMENT_MODE') = 'TRUE') then
x_action_type_code_line := get_group_char_cell (
'CURRENT_STATE.ACTION_TYPE_CODE_LINE',
i);
x_line_num := get_group_number_cell(
'CURRENT_STATE.PO_LINE_NUMBER',
i);
x_requisition_line_id := get_group_number_cell(
'CURRENT_STATE.REQUISITION_LINE_ID',
i);
x_originally_on_doc := get_group_char_cell(
'CURRENT_STATE.ORIGINALLY_ON_DOC',
i);
else
x_action_type_code_line := null;
x_line_num := null;
x_requisition_line_id := get_group_number_cell(
'REQ_LINES_MULTI.REQUISITION_LINE_ID',
i);
x_originally_on_doc := 'N';
/* Bug 421496. gtummala. 11/9/97
* We need to allow one-time req lines to be autocreated onto blanket
* releases. To allow this we need at least 80.9 of POXBWPOB.pls. The backend
* procedure needs us to populate the blanket source line and also set the
* line action code to 'ADD'.
*/
x_item_id := get_group_number_cell('REQ_LINES_MULTI.ITEM_ID', i);
if (name_in('ACTION.DOCUMENT_TYPE') = 'RELEASE') and
(x_item_id is NULL) then
x_progress:='004';
/* Need to get the blanket source line that matches */
x_line_num := action4.get_blanket_line_num(
name_in('new_document.document_number'),
i);
/* Backend needs action=ADD for one-time items to be handled */
x_action_type_code_line := 'ADD';
end if;
end if;
x_progress:='005';
-- Validations ========================================================
/* Before we do anything, got to make sure that the req. lines
* have not in any changed by another user/session since they
* were queried by this session.
*
* If it fails then get out of this loop and don't insert into
* po_lines_interface.
*/
if (x_originally_on_doc = 'N') then
x_req_line_ok_to_autocreate:= action5.req_line_ok_to_autocreate
(x_rec_group,
get_group_char_cell(x_rec_group||'.REQ_NUMBER',i),
get_group_number_cell(x_rec_group||'.REQ_LINE_NUMBER',i),
x_requisition_line_id);
end if;
/* FPI GA start */
/* Populate the reference document */
/* Reference docs need to be populated only for standard PO's (bug 2714252) */
/* FPI GA end */
-- Insert into Interface Table ========================================
/* INSERT into lines interface table */
/* Do not insert those lines already on the document when in the
* the current_state mode.
*/
if ((name_in('POXBWVRP_WORLD.IN_PLACEMENT_MODE') = 'TRUE' AND
x_originally_on_doc = 'Y')) OR
(x_req_line_ok_to_autocreate=FALSE) then
null;
else
IF (name_in('ACTION.DOCUMENT_TYPE') = 'STANDARD') THEN
GA_REFERENCE.populate_ref_info(x_requisition_line_id ,
x_src_header_id ,
x_src_line_id ,
x_consigned_flag, -- CONSIGNED FPI
l_contract_id); -- <GC FPJ>
--<bug#4387937 START> Added code to null out the contract id if a
--global agreement is specified during document creation.
IF (NAME_IN('NEW_DOCUMENT.GLOBAL_AGREEMENT_ID') IS NOT NULL)THEN
l_contract_id:= null;
END IF;
--<bug#4387937 END>
END IF;
/* Get the next available interface_line_id */
SELECT po_lines_interface_s.nextval
INTO x_interface_line_id
FROM dual;
x_progress:='006';
begin
insert into po_lines_interface
(interface_header_id,
interface_line_id,
action, /* This used to be action_type_code */
line_num,
shipment_num,
requisition_line_id,
creation_date,
created_by,
from_header_id, -- GA FPI
from_line_id, -- GA FPI
consigned_flag, -- CONSIGNED FPI
contract_id, -- <GC FPJ>
last_update_date,
last_updated_by)
values
(x_interface_header_id,
x_interface_line_id,
x_action_type_code_line,
x_line_num,
null,
x_requisition_line_id,
x_creation_date,
x_created_by,
x_src_header_id, -- GA FPI
x_src_line_id, -- GA FPI
x_consigned_flag, -- CONSIGNED FPI
l_contract_id, -- <GC FPJ>
x_last_update_date,
x_last_updated_by);
exception
when others then
fnd_message.debug('In exception when trying to insert into po_lines');
raise form_trigger_failure;
end;
end if;
end loop;
/* Start Bug 3487756: Insert vendor contact id into po_headers_interface.
* Only insert the contact id at the interface header level
* if all the req. lines being autocreated have the same contact id.
*/
-- Derive unique vendor contact id on all the requisiton lines.
BEGIN
SELECT distinct porl.vendor_contact_id
INTO x_vendor_contact_id
FROM po_lines_interface poli
, po_requisition_lines_all porl
WHERE poli.interface_header_id = x_interface_header_id
AND poli.requisition_line_id = porl.requisition_line_id;
EXCEPTION
WHEN too_many_rows THEN
-- more than one vendor contact id; do not copy to header interface
x_vendor_contact_id := NULL;
WHEN no_data_found THEN
x_vendor_contact_id := NULL;
WHEN others THEN
fnd_message.debug('In exception when selecting vendor contact id');
raise form_trigger_failure;
END;
-- Validate contact id and then update headers interface.
BEGIN
-- Check if the contact is valid for the supplier site.
IF (x_vendor_contact_id IS NOT NULL)
THEN
SELECT (count(vendor_contact_id))
INTO x_vendor_contact_count
FROM po_vendor_contacts
WHERE vendor_site_id = x_vendor_site_id
AND vendor_contact_id = x_vendor_contact_id
AND nvl(inactive_date, sysdate+1) > sysdate;
IF (x_vendor_contact_count <= 0)
THEN
x_vendor_contact_id := NULL;
END IF;
END IF;
-- Update headers interface table with contact_id derived above.
UPDATE po_headers_interface
SET vendor_contact_id = x_vendor_contact_id
WHERE interface_header_id = x_interface_header_id;
EXCEPTION
WHEN others THEN
fnd_message.debug('In exception when updating po headers interface with vendor contact id');
raise form_trigger_failure;
END;
/* End Bug 3487756 */
/* Call the main sever side routine to actually create
* the documents, ie:
* - default in values not populated
* - group accordingly
* - insert into the main tables from the
* the interface tables.
*
* x_document_id is populated with po_header_id for pos and
* po_release_id for releases from the backend only when newly
* created. In add to scenarios we have to get the value ourselves.
* This is done in the wbp trigger for the ok button in the
* add to window.
*/
x_progress:='007';
--<Shared Proc FPJ START>
l_requesting_org_id := to_number(name_in('POXBWVRP_WORLD.current_org_id'));
--<R12 STYLES PHASE II START>
if PO_DOC_STYLE_PVT.is_progress_payments_enabled(l_style_id) then
if l_requesting_org_id <> l_purchasing_org_id then
FND_MESSAGE.set_name('PO', 'PO_REQLINE_PURCH_ORG_MISMATCH');
FND_MESSAGE.SHOW;
RAISE style_validate_failure;
end if;
end if;
--<R12 STYLES PHASE II END>
--Changing the call to new signature of Autocreate Backend
PO_INTERFACE_S.create_documents (
p_api_version => 1.0,
x_return_status => l_return_status,
x_msg_count => l_msg_count,
x_msg_data => l_msg_data,
p_batch_id => x_interface_header_id,
p_req_operating_unit_id => l_requesting_org_id,
p_purch_operating_unit_id => l_purchasing_org_id,
x_document_id => x_document_id,
x_number_lines => x_num_lines_processed,
x_document_number => l_document_number,
-- Bug 3648268 Use lookup code instead of hardcoded value
p_document_creation_method => 'AUTOCREATE', -- <DBI FPJ>
p_orig_org_id => l_purchasing_org_id --<R12 MOAC>
);