務(wù)校驗與數(shù)據(jù)填充實戰(zhàn)指南)
1. 項目概述為什么要在VA02保存前“動手腳”做SAP SD模塊開發(fā)或者運維的朋友對VA02這個事務(wù)碼肯定再熟悉不過了。它就是銷售訂單修改的“主戰(zhàn)場”。日常業(yè)務(wù)中銷售訂單創(chuàng)建后客戶要求變更價格、調(diào)整數(shù)量、修改交貨日期甚至是增加一個全新的行項目這些操作最終都會匯集到VA02這個界面。從技術(shù)角度看VA02的保存操作點擊那個綠色的對勾或者按CtrlS是整個訂單數(shù)據(jù)從用戶界面流向SAP數(shù)據(jù)庫的最終閘口。一旦數(shù)據(jù)保存再想修改就需要走正式的修改流程甚至可能觸發(fā)后續(xù)的發(fā)貨、開票等一連串操作。那么為什么我們常常需要在“保存前”這個關(guān)鍵時刻進(jìn)行增強呢核心驅(qū)動力是業(yè)務(wù)規(guī)則的強制校驗與數(shù)據(jù)的智能完善。SAP標(biāo)準(zhǔn)功能雖然強大但無法覆蓋所有企業(yè)千差萬別的個性化需求。舉個例子你們公司規(guī)定對于特定銷售渠道比如電商平臺的訂單必須強制填寫一個“平臺訂單號”或者對于金額超過100萬的訂單需要自動檢查客戶的信用額度并給出預(yù)警再比如需要在保存前根據(jù)物料和工廠自動從某個自定義表中抓取一個“內(nèi)部批次號”填充到訂單行項目的增強字段里。這些需求標(biāo)準(zhǔn)SAP都沒有怎么辦答案就是通過ABAP增強在數(shù)據(jù)即將寫入數(shù)據(jù)庫的瞬間介入處理。這個“保存前”的時機(jī)非常精妙。太早了不行比如在屏幕的PBOProcess Before Output階段用戶可能還沒輸完數(shù)據(jù)太晚了更不行數(shù)據(jù)一旦入庫再修改就是另一回事了。只有在“保存前”這個點用戶所有輸入的數(shù)據(jù)都已準(zhǔn)備就緒但尚未進(jìn)行最終的數(shù)據(jù)庫更新UPDATE此時進(jìn)行校驗、計算和填充既能確保規(guī)則的執(zhí)行又能保證數(shù)據(jù)的完整性和準(zhǔn)確性。我經(jīng)手的項目中超過七成的SD增強需求都集中在這個環(huán)節(jié)。它就像一道精心設(shè)計的安檢門所有數(shù)據(jù)必須通過它的檢查才能“登機(jī)”。2. 核心增強點解析不止一個USEREXIT提到VA02的增強很多人的第一反應(yīng)是USEREXIT_SAVE_DOCUMENT_PREPARE。這沒錯它是一個非常經(jīng)典且強大的出口User Exit。但根據(jù)我的經(jīng)驗只依賴這一個點是不夠的一個健壯的保存前增強方案往往需要根據(jù)校驗邏輯的復(fù)雜度和數(shù)據(jù)需求在多個增強點之間進(jìn)行選擇和組合。2.1 增強點一USEREXIT_SAVE_DOCUMENT_PREPARE (MV45AFZZ)這是最常用、最直接的增強點。它位于標(biāo)準(zhǔn)程序SAPMV45A的包含程序MV45AFZZ中。當(dāng)你在VA02中按下保存鍵標(biāo)準(zhǔn)程序在進(jìn)行了初步的格式和必填項檢查后就會調(diào)用這個出口。它的核心特點是數(shù)據(jù)完備此時所有屏幕和表格控件中的數(shù)據(jù)都已經(jīng)傳遞到了ABAP程序內(nèi)部的工作區(qū)比如銷售訂單抬頭數(shù)據(jù)VBAK、行項目數(shù)據(jù)VBAP等。你可以直接對這些內(nèi)表進(jìn)行讀取和修改。時機(jī)靠前它在最終數(shù)據(jù)庫更新UPDATE VBAK, VBAP...之前執(zhí)行是進(jìn)行業(yè)務(wù)邏輯校驗和字段默認(rèn)值填充的黃金位置。功能強大你可以在這里進(jìn)行復(fù)雜的計算調(diào)用自定義函數(shù)讀取其他模塊的數(shù)據(jù)如財務(wù)的信用數(shù)據(jù)、物料的批次特性甚至根據(jù)條件彈出警告WARNING或錯誤ERROR消息來阻止保存。一個典型的應(yīng)用場景假設(shè)公司要求所有“Z001”銷售類型的訂單行項目都必須填寫一個自定義的“項目經(jīng)理”字段假設(shè)已增強到VBAP結(jié)構(gòu)字段為ZPM。你可以在USEREXIT_SAVE_DOCUMENT_PREPARE中這樣寫DATA: lv_vbeln TYPE vbeln. LOOP AT xvbap ASSIGNING FIELD-SYMBOL(fs_vbap) WHERE auart Z001. IF fs_vbap-zpm IS INITIAL. MESSAGE e001(zsd_order) WITH fs_vbap-posnr INTO DATA(lv_msg). CALL FUNCTION MESSAGE_STORE EXPORTING arbgb ZSD_ORDER msgty E msgv1 fs_vbap-posnr. cv_error_in_save X. 設(shè)置錯誤標(biāo)志 ENDIF. ENDLOOP.注意這里使用MESSAGE_STORE函數(shù)而非直接的MESSAGE e...語句是因為在User Exit中直接彈出消息可能會與標(biāo)準(zhǔn)程序的消息處理機(jī)制沖突。將錯誤消息存儲起來標(biāo)準(zhǔn)程序會在后續(xù)統(tǒng)一處理并阻止保存。2.2 增強點二BADISALES_DOCUMENT 和 DLV_HEADER_SAVE對于更新的SAP版本ECC 6.0及以上S/4HANASAP更推薦使用業(yè)務(wù)附加項BADI進(jìn)行增強。它們更面向?qū)ο蠊芾砥饋硪哺逦?。BADISALES_DOCUMENT:這個BADI非常強大它定義了許多方法對應(yīng)銷售單據(jù)生命周期中的各個時點。其中與VA02保存前相關(guān)的主要是PREPARE_SAVE: 類似于USEREXIT_SAVE_DOCUMENT_PREPARE在保存準(zhǔn)備階段調(diào)用。你可以在這里修改單據(jù)數(shù)據(jù)。CHECK_SAVE: 在保存前進(jìn)行最終檢查。這是進(jìn)行強制性校驗的最后關(guān)卡。如果在此方法中拋出異常CX_SALES_DOCUMENT或設(shè)置錯誤消息保存將被終止。優(yōu)勢BADI方法有明確的輸入/輸出參數(shù)接口比如CHANGING參數(shù)CS_SALES_DOCUMENT就包含了完整的訂單數(shù)據(jù)對象操作起來比直接操作內(nèi)表更結(jié)構(gòu)化也更安全。BADIDLV_HEADER_SAVE:這個BADI主要針對交貨單但在某些銷售訂單保存場景也會被觸發(fā)例如當(dāng)銷售訂單自動創(chuàng)建交貨時。如果你的校驗邏輯與后續(xù)交貨流程強相關(guān)可能需要關(guān)注這個BADI。選擇User Exit還是BADI我的經(jīng)驗是優(yōu)先使用BADI。BADI是SAP主推的增強技術(shù)具有更好的向下兼容性和可管理性通過SE19可以清晰看到所有實現(xiàn)。對于新項目或新需求無腦選BADI。User Exit更多用于維護(hù)歷史遺留的增強代碼或者在BADI不滿足特定細(xì)微需求時作為補充。2.3 增強點三隱形的守衛(wèi)屏幕增強與校驗除了上述程序級的增強還有一種在數(shù)據(jù)進(jìn)入程序之前就進(jìn)行攔截的方法屏幕字段校驗。通過在訂單屏幕的字段上附加FIELD_MODULE或者在屏幕流邏輯的PROCESS AFTER INPUT (PAI)事件中編寫校驗代碼可以在用戶離開某個字段或執(zhí)行某個功能時立即進(jìn)行檢查。它的適用場景即時反饋例如用戶輸入一個物料號需要立即檢查該物料在選定工廠下是否有庫存并在旁邊顯示紅燈或綠燈。這種體驗比保存時才報錯要好得多。簡單邏輯校驗邏輯僅依賴于本字段或少數(shù)幾個其他屏幕字段的值。局限性復(fù)雜的、需要訪問大量數(shù)據(jù)庫表或進(jìn)行復(fù)雜計算的校驗不適合放在屏幕校驗里會影響界面響應(yīng)速度。這類校驗更適合放到PREPARE_SAVE或CHECK_SAVE中。實操心得一個完整的VA02保存前增強體系往往是分層級的。屏幕校驗處理簡單、即時、體驗好的檢查PREPARE_SAVE(或User Exit)處理復(fù)雜的數(shù)據(jù)計算、默認(rèn)值填充和依賴多表數(shù)據(jù)的校驗CHECK_SAVE則作為最后一道不可逾越的防線執(zhí)行那些一旦違反就必須阻止保存的“鐵律”。三者結(jié)合才能構(gòu)建出既用戶友好又堅固可靠的業(yè)務(wù)控制邏輯。3. 從零到一實現(xiàn)一個VA02保存前增強光說不練假把式。下面我以一個真實的業(yè)務(wù)需求為例帶你走一遍使用BADISALES_DOCUMENT實現(xiàn)增強的完整流程。需求是對于銷售類型為‘ZOR’網(wǎng)上零售的訂單檢查其行項目的“承諾交貨日期”VBEP-ETENR不能晚于創(chuàng)建日期VBAK-AUDAT后的30天。3.1 第一步需求分析與設(shè)計首先別急著敲代碼。先分析數(shù)據(jù)來源需要訂單抬頭信息VBAK-AUDAT和行項目計劃行信息VBEP-ETENR。校驗時機(jī)必須在保存前檢查因為一旦保存錯誤的日期可能觸發(fā)錯誤的MRP或交貨計劃。增強點選擇這是一個強業(yè)務(wù)規(guī)則校驗需要在所有數(shù)據(jù)就緒后執(zhí)行并且校驗失敗必須阻止保存。因此選擇BADISALES_DOCUMENT的CHECK_SAVE方法是最合適的。錯誤處理校驗不通過時需要向用戶明確提示是哪一行項目違反了規(guī)則。3.2 第二步查找并實現(xiàn)BADI打開事務(wù)碼SE19Business Add-In Builder。在“創(chuàng)建實施”區(qū)域輸入BADI名稱SALES_DOCUMENT然后點擊“創(chuàng)建實施”。給你的實施起一個名字比如Z_SD_ORDER_CHECK_DELIVERY并填寫描述。點擊“繼續(xù)”。在“接口”標(biāo)簽頁你會看到BADI定義的所有方法。雙擊CHECK_SAVE方法進(jìn)入代碼編輯區(qū)。3.3 第三步編寫核心校驗邏輯在CHECK_SAVE方法中系統(tǒng)會傳入一個IS_SALES_DOCUMENT參數(shù)它包含了所有要保存的銷售單據(jù)數(shù)據(jù)。我們需要從中提取抬頭和計劃行數(shù)據(jù)。METHOD if_ex_sales_document~check_save. DATA: lv_audat TYPE audat, lv_max_date TYPE d, lv_error_flag TYPE abap_bool VALUE abap_false. FIELD-SYMBOLS: fs_header TYPE vbakvb, fs_schedule TYPE vbepvb. 1. 獲取銷售訂單抬頭數(shù)據(jù) READ TABLE is_sales_document-sales_document_header ASSIGNING fs_header INDEX 1. IF sy-subrc 0 OR fs_header IS NOT ASSIGNED. RETURN. 沒有抬頭數(shù)據(jù)直接退出 ENDIF. 2. 僅對銷售類型為ZOR的訂單進(jìn)行檢查 IF fs_header-auart ZOR. RETURN. ENDIF. 3. 計算最大允許交貨日期創(chuàng)建日期30天 lv_audat fs_header-audat. lv_max_date lv_audat 30. 4. 循環(huán)檢查所有計劃行 LOOP AT is_sales_document-sales_document_schedule ASSIGNING fs_schedule. 檢查承諾日期是否晚于最大允許日期 IF fs_schedule-etenr lv_max_date. 5. 準(zhǔn)備錯誤消息 消息類ZSD_ORDER中定義消息ID 002內(nèi)容如“行項目的計劃行交貨日期不能晚于” MESSAGE e002(zsd_order) WITH fs_schedule-posnr fs_schedule-etenr lv_max_date INTO DATA(lv_message_text). 6. 記錄錯誤并設(shè)置標(biāo)志 CALL FUNCTION MESSAGE_STORE EXPORTING arbgb ZSD_ORDER msgty E msgv1 fs_schedule-posnr msgv2 fs_schedule-etenr msgv3 lv_max_date. lv_error_flag abap_true. ENDIF. ENDLOOP. 7. 如果存在任何錯誤拋出異常以阻止保存 IF lv_error_flag abap_true. RAISE EXCEPTION TYPE cx_sales_document EXPORTING textid cx_sales_documentdocument_not_saved. ENDIF. ENDMETHOD.代碼關(guān)鍵點解析IS_SALES_DOCUMENT這是一個復(fù)雜的結(jié)構(gòu)包含了抬頭HEADER、行項目ITEMS、計劃行SCHEDULE等多個內(nèi)表。你需要像剝洋蔥一樣找到需要的數(shù)據(jù)層級。MESSAGE_STORE這是在BADI或User Exit中報告錯誤的標(biāo)準(zhǔn)做法。你不能直接用MESSAGE e...因為那會中斷方法執(zhí)行并可能導(dǎo)致程序狀態(tài)混亂。MESSAGE_STORE將錯誤信息緩存起來標(biāo)準(zhǔn)程序會在適當(dāng)?shù)臅r機(jī)統(tǒng)一顯示。RAISE EXCEPTION在CHECK_SAVE中這是阻止保存的“殺手锏”。拋出CX_SALES_DOCUMENT異常后標(biāo)準(zhǔn)保存流程會中止并且之前通過MESSAGE_STORE存儲的所有錯誤消息都會在VA02界面上顯示給用戶。3.4 第四步激活與測試編寫完代碼后點擊“激活”按鈕激活整個BADI實施。進(jìn)入VA02找一個銷售類型為ZOR的現(xiàn)有訂單進(jìn)行修改。將某個行項目的計劃行交貨日期修改為超過創(chuàng)建日期30天的未來日期。點擊保存。此時你應(yīng)該會看到系統(tǒng)彈出錯誤消息明確提示哪一行違反了規(guī)則并且保存操作被阻止。將日期改回合規(guī)范圍再次保存此時訂單應(yīng)能成功保存。踩坑提醒測試時務(wù)必注意數(shù)據(jù)的完整性。有時計劃行表VBEP可能因為配置原因沒有數(shù)據(jù)你的LOOP AT可能根本進(jìn)不去。因此在增強代碼中加入適當(dāng)?shù)腎F sy-subrc 0判斷和日志記錄比如用MESSAGE s...調(diào)試是非常好的習(xí)慣。4. 高級技巧與避坑指南掌握了基礎(chǔ)實現(xiàn)我們再來聊聊那些在官方文檔里找不到但能讓你代碼更健壯、維護(hù)性更高的實戰(zhàn)技巧。4.1 如何高效調(diào)試保存前增強調(diào)試增強點尤其是保存前的邏輯有其特殊性。你不能像調(diào)試普通報表一樣直接設(shè)斷點。方法一使用外部調(diào)試器/h這是最直接的方法。在VA02界面輸入/h回車激活調(diào)試然后執(zhí)行保存操作。程序會停在保存函數(shù)如SAVE_DOCUMENT的開始處。你需要一步步執(zhí)行直到進(jìn)入你的增強代碼MV45AFZZ或你的BADI方法。缺點是步驟繁瑣容易跟丟。方法二使用ABAP斷點BREAK-POINT或日志在增強代碼的關(guān)鍵位置插入BREAK-POINT語句。當(dāng)代碼執(zhí)行到此處時只要有用戶執(zhí)行保存操作并且觸發(fā)了你的增強邏輯調(diào)試器就會自動彈出。注意這會影響所有用戶僅限開發(fā)或測試環(huán)境使用生產(chǎn)環(huán)境絕對禁止。 更安全的方式是寫入應(yīng)用日志Application Log使用事務(wù)碼SLG1可以查看。在代碼里用BAL_*系列函數(shù)記錄關(guān)鍵變量的值這是排查生產(chǎn)問題的不二法門。方法三使用“靜默”測試有時你只想看邏輯是否走通不想打斷用戶。可以在代碼里用MESSAGE s... TYPE I彈出信息窗口或者將關(guān)鍵變量賦值給一個全局的調(diào)試內(nèi)表然后寫一個簡單的報表來顯示這個內(nèi)表的內(nèi)容。4.2 處理增強中的“數(shù)據(jù)不一致”陷阱在USEREXIT_SAVE_DOCUMENT_PREPARE或BADI的PREPARE_SAVE中你操作的是程序的工作區(qū)數(shù)據(jù)如XVBAK,XVBAP。一個常見的陷阱是你以為修改了這些內(nèi)表數(shù)據(jù)就萬事大吉但標(biāo)準(zhǔn)程序在后續(xù)可能還有自己的推導(dǎo)或覆蓋邏輯。避坑法則修改時機(jī)盡量在標(biāo)準(zhǔn)程序完成其核心推導(dǎo)邏輯之后再進(jìn)行你的數(shù)據(jù)填充。對于User Exit這通常就是USEREXIT_SAVE_DOCUMENT_PREPARE本身。對于BADIPREPARE_SAVE的時機(jī)通常也合適。字段確認(rèn)修改了某個字段后如果這個字段會影響其他字段比如修改了價格可能影響定價條件你需要確認(rèn)標(biāo)準(zhǔn)程序是否會重新計算。如果不確定有時需要主動調(diào)用相應(yīng)的函數(shù)如PRICING來觸發(fā)更新。測試邊界案例重點測試數(shù)據(jù)從無到有、從有到無清空、異常值等情況。例如你根據(jù)條件自動填充了一個增強字段當(dāng)條件不滿足時你是保留原值還是清空它這需要和業(yè)務(wù)部門明確規(guī)則。4.3 性能優(yōu)化別讓增強拖慢系統(tǒng)增強代碼會在每次保存時執(zhí)行。如果代碼效率低下會直接影響所有用戶的訂單處理速度。優(yōu)化要點減少數(shù)據(jù)庫查詢避免在循環(huán)內(nèi)部執(zhí)行SELECT SINGLE。如果需要對一批物料進(jìn)行檢查應(yīng)該先用SELECT ... FOR ALL ENTRIES IN ...將所需數(shù)據(jù)一次性讀到內(nèi)表中然后在循環(huán)內(nèi)用READ TABLE來查找。 反例性能差 LOOP AT xvbap ASSIGNING fs_vbap. SELECT SINGLE mtart FROM mara INTO lv_mtart WHERE matnr fs_vbap-matnr. ... 處理邏輯 ENDLOOP. 正例性能好 DATA: lt_mara TYPE TABLE OF mara, lt_matnr TYPE TABLE OF matnr. lt_matnr VALUE #( FOR ls_vbap IN xvbap ( ls_vbap-matnr ) ). SELECT matnr, mtart INTO TABLE lt_mara FROM mara FOR ALL ENTRIES IN lt_matnr WHERE matnr lt_matnr-table_line. SORT lt_mara BY matnr. LOOP AT xvbap ASSIGNING fs_vbap. READ TABLE lt_mara ASSIGNING FIELD-SYMBOL(fs_mara) WITH KEY matnr fs_vbap-matnr BINARY SEARCH. IF sy-subrc 0. ... 使用 fs_mara-mtart 進(jìn)行處理 ENDIF. ENDLOOP.善用緩存對于一些不常變化的配置數(shù)據(jù)如自定義的檢查規(guī)則表可以在程序開始時將其讀入一個全局的、帶內(nèi)存ID的共享內(nèi)存對象或者使用CL_SHM_AREA訪問共享內(nèi)存避免每次保存都重復(fù)讀取。邏輯簡化評估你的校驗邏輯是否必要。能否前置到屏幕校驗?zāi)芊裢ㄟ^配置如條件技術(shù)、字段狀態(tài)實現(xiàn)代碼越少性能越好。4.4 增強的版本管理與傳輸BADI實施和User Exit修改都是需要傳輸?shù)腁BAP對象。務(wù)必將其納入你的正規(guī)開發(fā)流程。包分配創(chuàng)建BADI實施或修改包含程序時將其分配到一個合適的開發(fā)包Package中以便于傳輸管理。傳輸請求所有修改都必須記錄在傳輸請求Transport Request中。使用事務(wù)碼SE10管理你的傳輸請求。注釋與文檔在增強代碼的開頭使用規(guī)范的注釋塊說明增強目的、作者、日期、需求編號。復(fù)雜的邏輯需要添加行內(nèi)注釋。這能為后續(xù)維護(hù)節(jié)省大量時間。集中管理考慮使用事務(wù)碼SMOD或CMOD來管理User Exit項目這樣可以將多個相關(guān)的Exit打包便于查看和傳輸。對于BADISE19本身就是一個管理工具。5. 常見問題排查與實戰(zhàn)案例即使設(shè)計得再完美增強上線后也難免遇到問題。這里我總結(jié)幾個最常被問到的“坑”及其解決方案。5.1 問題一增強代碼不執(zhí)行癥狀在VA02保存時斷點沒觸發(fā)日志也沒記錄好像增強不存在一樣。排查步驟激活狀態(tài)首先檢查你的BADI實施或包含程序MV45AFZZ是否已激活。未激活的對象不會被執(zhí)行。過濾器值如果使用了BADI檢查實施是否有過濾器Filter。例如SALES_DOCUMENTBADI可以按銷售組織、分銷渠道等設(shè)置過濾器。確保當(dāng)前處理的訂單符合過濾條件。增強點錯誤確認(rèn)你修改的確實是正確的增強點。VA02的保存邏輯可能因不同條件如單據(jù)類型、項目類別而略有不同確保你的增強點在所有路徑上都能被調(diào)用??梢試L試在SAVE_DOCUMENT函數(shù)模塊的入口處設(shè)斷點回溯調(diào)用棧來確認(rèn)執(zhí)行路徑。命名空間確保你的User Exit函數(shù)或FORM名稱完全正確包括前綴如EXIT_SAPLV60B_001。5.2 問題二消息顯示了但訂單仍然保存成功癥狀系統(tǒng)彈出了你設(shè)置的錯誤消息但用戶點擊回車后訂單居然保存成功了。根因這幾乎可以肯定是消息類型用錯了。在USEREXIT_SAVE_DOCUMENT_PREPARE中如果你使用MESSAGE e...語句它可能無法正確中斷保存流程。更常見的是你雖然調(diào)用了MESSAGE_STORE存儲了E類型消息但沒有設(shè)置錯誤標(biāo)志或拋出異常。解決方案在User Exit中存儲E類型消息后必須將CV_ERROR_IN_SAVE參數(shù)設(shè)置為‘X’。在BADI的CHECK_SAVE方法中存儲E類型消息后必須RAISE EXCEPTION。檢查你的消息類型是E錯誤而不是W警告或I信息。5.3 問題三增強修改的數(shù)據(jù)被標(biāo)準(zhǔn)程序覆蓋了癥狀你在增強里給某個字段賦了值但保存后發(fā)現(xiàn)值變了或者沒了。排查時機(jī)太早你可能在標(biāo)準(zhǔn)程序推導(dǎo)該字段值之前就修改了它隨后標(biāo)準(zhǔn)程序的邏輯覆蓋了你的修改。嘗試將你的賦值邏輯移到更靠后的增強點或者研究標(biāo)準(zhǔn)程序?qū)υ撟侄蔚馁x值邏輯在哪里。字段是計算字段有些字段是只讀的由其他字段通過公式計算得出如凈值 數(shù)量 × 單價 - 折扣。直接修改這種字段是無效的。你需要修改它的源字段。使用標(biāo)準(zhǔn)函數(shù)對于某些關(guān)鍵字段的修改可能需要調(diào)用SAP提供的標(biāo)準(zhǔn)函數(shù)或BAPI來確保數(shù)據(jù)一致性。例如修改價格不應(yīng)直接改VBAP-KWMENG而應(yīng)通過條件技術(shù)Pricing來更新。5.4 實戰(zhàn)案例動態(tài)默認(rèn)值填充需求銷售訂單的行項目上有一個增強字段“Z_PRIORITY”優(yōu)先級。業(yè)務(wù)希望當(dāng)用戶選擇“快速交貨”的運輸路線Route時自動將該行項目的優(yōu)先級設(shè)為“高”‘H’否則為“中”‘M’。實現(xiàn)思路增強點選擇這個需求需要在數(shù)據(jù)進(jìn)入程序后、保存前根據(jù)已有數(shù)據(jù)運輸路線計算并填充另一個字段。選擇USEREXIT_SAVE_DOCUMENT_PREPARE或BADI的PREPARE_SAVE方法都很合適。邏輯實現(xiàn) 在 PREPARE_SAVE 或 User Exit 中 LOOP AT ct_sales_document-sales_document_item ASSIGNING FIELD-SYMBOL(fs_item). 獲取該行項目的運輸路線這里假設(shè)從計劃行獲取實際可能需根據(jù)配置確定來源 READ TABLE ct_sales_document-sales_document_schedule INTO DATA(ls_schedule) WITH KEY posnr fs_item-posnr. IF sy-subrc 0 AND ls_schedule-route ZFAST. 假設(shè)ZFAST是快速交貨路線 fs_item-z_priority H. 高優(yōu)先級 ELSE. fs_item-z_priority M. 中優(yōu)先級 ENDIF. ENDLOOP.注意事項這里有一個關(guān)鍵點即**“否則”邏輯**。當(dāng)路線不是‘ZFAST’時我們將其設(shè)為‘M’。但這里需要考慮用戶是否已經(jīng)手動輸入了優(yōu)先級我們的自動填充邏輯是否會覆蓋用戶的手工輸入這是一個典型的業(yè)務(wù)邏輯沖突。通常的解決方案是僅當(dāng)字段初始為空時才自動填充如果用戶已經(jīng)手動輸入了值則尊重用戶輸入不予覆蓋。代碼需要增加一個判斷IF fs_item-z_priority IS INITIAL. ... ENDIF.這個案例看似簡單卻涵蓋了增強開發(fā)中“數(shù)據(jù)來源判斷”、“業(yè)務(wù)邏輯沖突處理”等核心思想。每一次增強開發(fā)都是一次與標(biāo)準(zhǔn)程序邏輯和業(yè)務(wù)實際需求的深度對話。理解標(biāo)準(zhǔn)吃透業(yè)務(wù)你的增強代碼才能既穩(wěn)固又靈活。