云计算百科
云计算领域专业知识百科平台

SAP-ABAP:FICO 模块成本控制开发:成本中心/内部订单/生产订单成本核算逻辑实现

FICO 模块成本控制开发:成本中心/内部订单/生产订单成本核算逻辑实现

博客简介:针对成本核算管理需求,讲解成本中心费用归集分配逻辑开发、内部订单预算管控增强开发、生产订单成本核算与差异分析逻辑开发、成本月结自动程序开发的方法,附“内部订单预算超支自动拦截”“作业成本自动分配”“成本差异自动结转”的实现代码,提升成本核算效率与数据准确性。

“第四十六篇讲了应收账款,本篇轮到 FICO 成本控制核心!从财务会计(FI)转到管理会计(CO)——AUFK+AUFK2+COSPC+COSTE 四表联动,成本中心分摊 + 内部订单预算拦截 + 生产订单差异分析 + 月结自动程序,附可复用的 Z_COST_MONTHLY_CLOSE 一键月结代码。”


📖 写在前面

本篇定位

前 46 篇讲的是财务会计(FI)——怎么记账、怎么清账、怎么计提。本篇转入管理会计(CO)——怎么归集成本、怎么分摊成本、怎么分析差异。FI 是“记账给外部看的”,CO 是“算账给内部管理看的”。成本控制是 CO 模块的核心,也是 SAP 中增强空间最大的模块之一。

本篇适合谁读

  • 需要在 FICO-CO 模块做成本增强的开发者
  • 负责成本核算和管控的成本会计
  • 从 FI 凭证(第四十三篇的 KOSTL/PRCTR 字段)延伸到 CO 的开发者

贯穿场景概览

#mermaid-svg-ZyZ9W8Ob6shGQg5G{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-ZyZ9W8Ob6shGQg5G .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-ZyZ9W8Ob6shGQg5G .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-ZyZ9W8Ob6shGQg5G .error-icon{fill:#552222;}#mermaid-svg-ZyZ9W8Ob6shGQg5G .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-ZyZ9W8Ob6shGQg5G .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-ZyZ9W8Ob6shGQg5G .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-ZyZ9W8Ob6shGQg5G .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-ZyZ9W8Ob6shGQg5G .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-ZyZ9W8Ob6shGQg5G .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-ZyZ9W8Ob6shGQg5G .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-ZyZ9W8Ob6shGQg5G .marker{fill:#333333;stroke:#333333;}#mermaid-svg-ZyZ9W8Ob6shGQg5G .marker.cross{stroke:#333333;}#mermaid-svg-ZyZ9W8Ob6shGQg5G svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-ZyZ9W8Ob6shGQg5G p{margin:0;}#mermaid-svg-ZyZ9W8Ob6shGQg5G .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-ZyZ9W8Ob6shGQg5G .cluster-label text{fill:#333;}#mermaid-svg-ZyZ9W8Ob6shGQg5G .cluster-label span{color:#333;}#mermaid-svg-ZyZ9W8Ob6shGQg5G .cluster-label span p{background-color:transparent;}#mermaid-svg-ZyZ9W8Ob6shGQg5G .label text,#mermaid-svg-ZyZ9W8Ob6shGQg5G span{fill:#333;color:#333;}#mermaid-svg-ZyZ9W8Ob6shGQg5G .node rect,#mermaid-svg-ZyZ9W8Ob6shGQg5G .node circle,#mermaid-svg-ZyZ9W8Ob6shGQg5G .node ellipse,#mermaid-svg-ZyZ9W8Ob6shGQg5G .node polygon,#mermaid-svg-ZyZ9W8Ob6shGQg5G .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-ZyZ9W8Ob6shGQg5G .rough-node .label text,#mermaid-svg-ZyZ9W8Ob6shGQg5G .node .label text,#mermaid-svg-ZyZ9W8Ob6shGQg5G .image-shape .label,#mermaid-svg-ZyZ9W8Ob6shGQg5G .icon-shape .label{text-anchor:middle;}#mermaid-svg-ZyZ9W8Ob6shGQg5G .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-ZyZ9W8Ob6shGQg5G .rough-node .label,#mermaid-svg-ZyZ9W8Ob6shGQg5G .node .label,#mermaid-svg-ZyZ9W8Ob6shGQg5G .image-shape .label,#mermaid-svg-ZyZ9W8Ob6shGQg5G .icon-shape .label{text-align:center;}#mermaid-svg-ZyZ9W8Ob6shGQg5G .node.clickable{cursor:pointer;}#mermaid-svg-ZyZ9W8Ob6shGQg5G .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-ZyZ9W8Ob6shGQg5G .arrowheadPath{fill:#333333;}#mermaid-svg-ZyZ9W8Ob6shGQg5G .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-ZyZ9W8Ob6shGQg5G .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-ZyZ9W8Ob6shGQg5G .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-ZyZ9W8Ob6shGQg5G .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-ZyZ9W8Ob6shGQg5G .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-ZyZ9W8Ob6shGQg5G .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-ZyZ9W8Ob6shGQg5G .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-ZyZ9W8Ob6shGQg5G .cluster text{fill:#333;}#mermaid-svg-ZyZ9W8Ob6shGQg5G .cluster span{color:#333;}#mermaid-svg-ZyZ9W8Ob6shGQg5G div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-ZyZ9W8Ob6shGQg5G .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-ZyZ9W8Ob6shGQg5G rect.text{fill:none;stroke-width:0;}#mermaid-svg-ZyZ9W8Ob6shGQg5G .icon-shape,#mermaid-svg-ZyZ9W8Ob6shGQg5G .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-ZyZ9W8Ob6shGQg5G .icon-shape p,#mermaid-svg-ZyZ9W8Ob6shGQg5G .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-ZyZ9W8Ob6shGQg5G .icon-shape .label rect,#mermaid-svg-ZyZ9W8Ob6shGQg5G .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-ZyZ9W8Ob6shGQg5G .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-ZyZ9W8Ob6shGQg5G .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-ZyZ9W8Ob6shGQg5G :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

成本控制四大核心增强场景

场景1:成本中心费用归集与分摊

场景2:内部订单预算管控

场景3:生产订单成本差异分析

场景4:成本月结自动程序

Z_COST_ALLOCATION_JOBZT_COST_ALLOCATION_RULE按人数/面积/用户数分摊

FAGL_POSTING_BADI_50ZT_INTERNAL_ORDER_CONFIG90% 预警 + 100% 拦截

BADI_CONF_COSTSZT_COST_VARIANCE_CONFIG价格/数量/混合差异分析

Z_COST_MONTHLY_CLOSE6 步骤一键月结KSII→KSV5→KO88→KK88

版本说明:本篇内容基于 SAP NetWeaver 7.51。成本分摊、内部订单、生产订单结算在 ECC 6.0+ 和 S/4 HANA 中结构一致。BADI_ORDER_CK_COST 和 BADI_CONF_COSTS 是 EHP5+ 推荐的 BAdI。


一、成本控制核心架构

1.1 FI vs CO 核心差异

维度FI 财务会计CO 成本控制(本篇)核心差异
定位 外部报告(法定要求) 内部管理(管理需要) 内外之分
核心表 BKPF/BSEG/BKPF_ADD AUFK/AUFK2/COSPC/COSTE 凭证 vs 对象
组织结构 公司代码(BUKRS) 成本控制范围(KOKRS) FI 按公司,CO 按控制范围
核心对象 会计科目(SAKNR) 成本要素(KSTAR)+ 成本中心/内部订单 科目 vs 对象
自动过账 FI 过账驱动 CO 更新 不反向驱动 FI FI→CO 单向
期间 会计期间(MONAT) 成本期间(同上) 共用
标准事务码 FB01/FB60/FB70 KS01/KS02/KO01/KK01 KS=成本中心 KO=内部订单 KK=生产订单
核心 BAdI FAGL_POSTING_BADI_50 BADI_ORDER_CK_COST / BADI_CONF_COSTS FI 过账 vs CO 归集

1.2 成本控制核心对象

成本控制三大对象:

┌──────────────────────────────────────────────────────┐
│ 成本中心(Cost Center)KS* │
│ 表:CSKS(主数据)+ COSTE(行项目) │
│ 用途:归集部门/职能的成本费用 │
│ 层级:按组织架构划分(公司→部门→团队) │
│ 示例:K-SALES 销售部 / K-RD 研发部 / K-HR 人力资源 │
└──────────────────────────────────────────────────────┘

┌──────────────────────────────────────────────────────┐
│ 内部订单(Internal Order)KO* │
│ 表:AUFK(主数据)+ AUFK2(预算)+ COSPC(计划/实际)│
│ 用途:归集一次性项目/活动成本 │
│ 层级:独立的成本对象(可跨部门) │
│ 示例:IO2026001 年会项目 / IO2026002 新品推广 │
│ 独有特性:有预算管理功能(BAPI_BUDGET_ALLOCATION) │
└──────────────────────────────────────────────────────┘

┌──────────────────────────────────────────────────────┐
│ 生产订单(Production Order)KK* / WO* │
│ 表:AUFK(主数据)+ COSPC(计划/实际)+ AFPO(物料) │
│ 用途:归集产品生产成本 │
│ 层级:按物料+工厂划分 │
│ 独有特性:有结算功能(结算到 CO-PA 获利分析) │
│ 核心差异:实际成本 vs 标准成本 = 差异分析的来源 │
└──────────────────────────────────────────────────────┘

1.3 成本过账流程

#mermaid-svg-RWRJqYzxkW1ku4mh{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-RWRJqYzxkW1ku4mh .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-RWRJqYzxkW1ku4mh .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-RWRJqYzxkW1ku4mh .error-icon{fill:#552222;}#mermaid-svg-RWRJqYzxkW1ku4mh .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-RWRJqYzxkW1ku4mh .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-RWRJqYzxkW1ku4mh .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-RWRJqYzxkW1ku4mh .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-RWRJqYzxkW1ku4mh .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-RWRJqYzxkW1ku4mh .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-RWRJqYzxkW1ku4mh .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-RWRJqYzxkW1ku4mh .marker{fill:#333333;stroke:#333333;}#mermaid-svg-RWRJqYzxkW1ku4mh .marker.cross{stroke:#333333;}#mermaid-svg-RWRJqYzxkW1ku4mh svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-RWRJqYzxkW1ku4mh p{margin:0;}#mermaid-svg-RWRJqYzxkW1ku4mh .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-RWRJqYzxkW1ku4mh .cluster-label text{fill:#333;}#mermaid-svg-RWRJqYzxkW1ku4mh .cluster-label span{color:#333;}#mermaid-svg-RWRJqYzxkW1ku4mh .cluster-label span p{background-color:transparent;}#mermaid-svg-RWRJqYzxkW1ku4mh .label text,#mermaid-svg-RWRJqYzxkW1ku4mh span{fill:#333;color:#333;}#mermaid-svg-RWRJqYzxkW1ku4mh .node rect,#mermaid-svg-RWRJqYzxkW1ku4mh .node circle,#mermaid-svg-RWRJqYzxkW1ku4mh .node ellipse,#mermaid-svg-RWRJqYzxkW1ku4mh .node polygon,#mermaid-svg-RWRJqYzxkW1ku4mh .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-RWRJqYzxkW1ku4mh .rough-node .label text,#mermaid-svg-RWRJqYzxkW1ku4mh .node .label text,#mermaid-svg-RWRJqYzxkW1ku4mh .image-shape .label,#mermaid-svg-RWRJqYzxkW1ku4mh .icon-shape .label{text-anchor:middle;}#mermaid-svg-RWRJqYzxkW1ku4mh .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-RWRJqYzxkW1ku4mh .rough-node .label,#mermaid-svg-RWRJqYzxkW1ku4mh .node .label,#mermaid-svg-RWRJqYzxkW1ku4mh .image-shape .label,#mermaid-svg-RWRJqYzxkW1ku4mh .icon-shape .label{text-align:center;}#mermaid-svg-RWRJqYzxkW1ku4mh .node.clickable{cursor:pointer;}#mermaid-svg-RWRJqYzxkW1ku4mh .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-RWRJqYzxkW1ku4mh .arrowheadPath{fill:#333333;}#mermaid-svg-RWRJqYzxkW1ku4mh .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-RWRJqYzxkW1ku4mh .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-RWRJqYzxkW1ku4mh .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-RWRJqYzxkW1ku4mh .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-RWRJqYzxkW1ku4mh .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-RWRJqYzxkW1ku4mh .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-RWRJqYzxkW1ku4mh .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-RWRJqYzxkW1ku4mh .cluster text{fill:#333;}#mermaid-svg-RWRJqYzxkW1ku4mh .cluster span{color:#333;}#mermaid-svg-RWRJqYzxkW1ku4mh div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-RWRJqYzxkW1ku4mh .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-RWRJqYzxkW1ku4mh rect.text{fill:none;stroke-width:0;}#mermaid-svg-RWRJqYzxkW1ku4mh .icon-shape,#mermaid-svg-RWRJqYzxkW1ku4mh .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-RWRJqYzxkW1ku4mh .icon-shape p,#mermaid-svg-RWRJqYzxkW1ku4mh .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-RWRJqYzxkW1ku4mh .icon-shape .label rect,#mermaid-svg-RWRJqYzxkW1ku4mh .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-RWRJqYzxkW1ku4mh .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-RWRJqYzxkW1ku4mh .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-RWRJqYzxkW1ku4mh :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

FB01 过账 FI 凭证BSEG-KOSTL/AUFNR/PRCTR

SAP 自动更新 COKONK 确定成本要素

COSTE 成本中心行项目COSPC 订单行项目

KSV5/KO88/KK88分摊+结算


FI 过账 → 自动更新 CO 的完整链路:

FB01 过账 FI 凭证
│
├─ BSEG-KOSTL(成本中心)有值
│ → SAP 自动写 COSTE 表(成本中心行项目)
│
├─ BSEG-AUFNR(内部订单/生产订单)有值
│ → SAP 自动写 COSPC 表(订单行项目)
│
└─ BSEG-PRCTR(利润中心)有值
→ SAP 自动写 CEPC 相关表(利润中心)

第四十三篇 FAGL_ITEMS_SUBSTITUTION:
成本中心/利润中心自动派生 → 自动填入 BSEG → 自动驱动 CO 更新
→ 一篇文章打通 FI→CO 的入口!


二、场景 1:成本中心费用归集与分摊

2.1 分摊规则配置表

表名:ZT_COST_ALLOCATION_RULE(成本分摊规则)
MANDT TYPE MANDT
RULE_ID TYPE CHAR20
COST_CENTER_SRC TYPE KOSTL " 源成本中心(费用发生地)
COST_CENTER_DST TYPE KOSTL " 目标成本中心(费用承受方)
ALLOCATION_TYPE TYPE CHAR1 " P=百分比/F=固定金额/S=统计指标
PERCENTAGE TYPE DEC5_2 " 分摊百分比
AMOUNT TYPE CURR15 " 固定分摊金额
STAT_KF TYPE CHAR10 " 统计指标(如员工数)
VALID_FROM TYPE DATUM
VALID_TO TYPE DATUM
ACTIVE TYPE FLAG
PRIORITY TYPE NUMC2

示例数据(食堂成本按人数分摊):
┌───────┬──────────┬──────────┬────────┬─────────────┬─────────┬──────┐
│ RULE_ │ SRC_CC │ DST_CC │ TYPE │ PERCENTAGE │ ACTIVE │ PRIO │
│ ID │ │ │ │ │ │ │
├───────┼──────────┼──────────┼────────┼─────────────┼─────────┼──────┤
│ A001 │ K-CAFE │ K-SALES │ P │ 30.00 │ X │ 1 │
│ A002 │ K-CAFE │ K-RD │ P │ 50.00 │ X │ 1 │
│ A003 │ K-CAFE │ K-HR │ P │ 10.00 │ X │ 1 │
│ A004 │ K-CAFE │ K-FINANCE│ P │ 10.00 │ X │ 1 │
└───────┴──────────┴──────────┴────────┴─────────────┴─────────┴──────┘

2.2 自定义分摊 Job 实现

"=======================================================================
" 后台 Job:Z_COST_ALLOCATION_JOB
" 功能:月末按配置表分摊成本中心费用 → 生成 COSPC 凭证 → 自动更新 COSTE
" 调度:每月 25 日 22:00(月结前)
" 核心:SAP 标准 OKGA 分摊循环做不到的场景(按配置表灵活分摊)
"=======================================================================

REPORT zcost_allocation_job.

TABLES: csks, coste, cospc.

TYPES:
BEGIN OF ty_src_cost,
kostl TYPE kostl,
kstar TYPE kstar,
period_amt TYPE curr15,
END OF ty_src_cost,
BEGIN OF ty_alloc_pair,
src_cc TYPE kostl,
dst_cc TYPE kostl,
pct TYPE dec5_2,
amt TYPE curr15,
period_amt TYPE curr15, " 源成本中心本期实际费用
alloc_amt TYPE curr15, " 分摊金额
END OF ty_alloc_pair.

SELECTION-SCREEN BEGIN OF BLOCK b1.
PARAMETERS: p_kokrs TYPE kokrs,
p_period TYPE char6,
p_test TYPE flag DEFAULT 'X'.
SELECTION-SCREEN END OF BLOCK b1.

START-OF-SELECTION.

DATA: lt_src_costs TYPE TABLE OF ty_src_cost,
lt_pairs TYPE TABLE OF ty_alloc_pair.

PERFORM get_source_cost USING p_kokrs p_period
CHANGING lt_src_costs.

IF lt_src_costs IS INITIAL.
WRITE: / '没有需要分摊的成本'.
RETURN.
ENDIF.

PERFORM build_alloc_pairs USING lt_src_costs p_kokrs
CHANGING lt_pairs.

IF lt_pairs IS INITIAL.
WRITE: / '没有匹配的分摊规则'.
RETURN.
ENDIF.

WRITE: / '找到', lines( lt_pairs ), '条分摊明细'.
WRITE: / '—————————-'.

LOOP AT lt_pairs INTO DATA(ls_pair).

WRITE: / ls_pair-src_cc, '→', ls_pair-dst_cc,
'分摊', ls_pair-alloc_amt,
'(源总额', ls_pair-period_amt, '占', ls_pair-pct, '%)'.

ENDLOOP.

IF p_test = 'X'.
WRITE: /, '【干跑模式】未执行实际分摊过账'.
RETURN.
ENDIF.

DATA: lv_cnt TYPE numc4.
PERFORM execute_allocation USING lt_pairs p_kokrs p_period
CHANGING lv_cnt.

COMMIT WORK.
WRITE: /, '分摊完成!共', lv_cnt, '条记录过账'.

END-OF-SELECTION.

"=======================================================================
" 内部 FORM:取源成本中心的本期实际费用(FOR ALL ENTRIES 查 COSTE)
"=======================================================================
FORM get_source_cost
USING iv_kokrs TYPE kokrs
iv_period TYPE char6
CHANGING ct_src TYPE TABLE OF ty_src_cost.

" Step 1:查所有分摊规则的源成本中心
SELECT DISTINCT cost_center_src INTO TABLE @DATA(lt_src_ccs)
FROM zt_cost_allocation_rule
WHERE allocation_type IN ('P', 'F', 'S')
AND active = 'X'
AND ( valid_from <= @sy-datum OR valid_from IS NULL )
AND ( valid_to >= @sy-datum OR valid_to IS NULL ).

IF lt_src_ccs IS INITIAL.
RETURN.
ENDIF.

" Step 2:FOR ALL ENTRIES 查 COSTE 表的本期实际费用
SELECT coste~kostl, SUM( coste~wtg001 ) AS period_amt
INTO TABLE @ct_src
FROM coste
FOR ALL ENTRIES IN @lt_src_ccs
WHERE coste~kokrs = @iv_kokrs
AND coste~kostl = @lt_src_ccs-cost_center_src
AND coste~gjahr = @iv_period(4)
AND coste~perio = @iv_period+4(2)
AND coste~koart = 'K' " 实际费用
GROUP BY coste~kostl.

ENDFORM.

"=======================================================================
" 内部 FORM:构造分摊对(源→目标+金额)
"=======================================================================
FORM build_alloc_pairs
USING it_src_costs TYPE TABLE OF ty_src_cost
iv_kokrs TYPE kokrs
CHANGING ct_pairs TYPE TABLE OF ty_alloc_pair.

LOOP AT it_src_costs INTO DATA(ls_src).

" 查该源成本中心的所有分摊规则
SELECT *
FROM zt_cost_allocation_rule
INTO TABLE @DATA(lt_rules)
WHERE cost_center_src = @ls_src-kostl
AND active = 'X'
ORDER BY priority DESCENDING.

LOOP AT lt_rules INTO DATA(ls_rule).

DATA: ls_pair TYPE ty_alloc_pair.
ls_pair-src_cc = ls_rule-cost_center_src.
ls_pair-dst_cc = ls_rule-cost_center_dst.
ls_pair-pct = ls_rule-percentage.
ls_pair-period_amt = ls_src-period_amt.

" 按规则类型计算分摊金额
CASE ls_rule-allocation_type.
WHEN 'P'. " 百分比
ls_pair-alloc_amt = ls_src-period_amt * ls_rule-percentage / 100.
WHEN 'F'. " 固定金额
ls_pair-alloc_amt = ls_rule-amount.
WHEN 'S'. " 统计指标(简化)
ls_pair-alloc_amt = ls_src-period_amt * ls_rule-percentage / 100.
ENDCASE.

IF ls_pair-alloc_amt > 0.
APPEND ls_pair TO ct_pairs.
ENDIF.

ENDLOOP.

ENDLOOP.

ENDFORM.

"=======================================================================
" 内部 FORM:执行分摊过账(FI 凭证驱动 CO 更新)
" 简化:用 SAP 标准 BAPI_ACC_DOCUMENT_POST,生产环境用 KSU5/KSW5 增强
"=======================================================================
FORM execute_allocation
USING it_pairs TYPE TABLE OF ty_alloc_pair
iv_kokrs TYPE kokrs
iv_period TYPE char6
CHANGING cv_cnt TYPE numc4.

DATA: lt_items TYPE TABLE OF bapiacgl09,
ls_item TYPE bapiacgl09,
lt_return TYPE TABLE OF bapiret2.

cv_cnt = 0.

" 汇总所有分摊对到一张 FI 凭证(借贷平衡)
LOOP AT it_pairs INTO DATA(ls_p).

" 源成本中心贷方(减少)
CLEAR ls_item.
ls_item-costcenter = ls_p-src_cc.
ls_item-amt_doccur = – ls_p.alloc_amt.
ls_item-comp_code = '1000'.
ls_item-gl_account = '4200000001'. " 分摊成本要素
APPEND ls_item TO lt_items.

" 目标成本中心借方(增加)
CLEAR ls_item.
ls_item-costcenter = ls_p-dst_cc.
ls_item-amt_doccur = ls_p.alloc_amt.
ls_item-comp_code = '1000'.
ls_item-gl_account = '4200000001'.
APPEND ls_item TO lt_items.

ENDLOOP.

IF lt_items IS INITIAL.
RETURN.
ENDIF.

" 调用 BAPI 过账 FI 凭证(FI 过账自动触发 CO 更新)
CALL FUNCTION 'BAPI_ACC_DOCUMENT_POST'
EXPORTING
documentheader = VALUE bapiache09(
comp_code = '1000'
doc_type = 'SA'
pstng_date = sy-datum
currency = 'CNY'
header_txt = |成本分摊-{ iv_period }| )
TABLES
accountgl = lt_items
return = lt_return.

READ TABLE lt_return INTO DATA(ls_ret) WITH KEY type = 'E'.

IF sy-subrc = 0.
WRITE: / '分摊过账失败:', ls_ret-message.
ROLLBACK WORK.
ELSE.
CALL FUNCTION 'BAPI_TRANSACTION_COMMIT'
EXPORTING wait = 'X'.
cv_cnt = lines( it_pairs ).
ENDIF.

ENDFORM.

⚠️ 关键修正:

  • 消息类统一为 ZFI_ENH(FICO 模块统一前缀)。
  • SELECT SINGLE 加 @ 转义,字段列表用逗号分隔,WHERE 条件加 @。
  • BAPI_ACC_DOCUMENT_POST 参数改为标准接口(accountgl、return),返回用 BAPI_TRANSACTION_COMMIT。
  • COSTE 表字段 WTG001 代表期间 1 的实际金额,实际项目需按动态期间取字段。
  • 分摊过账走 FI 凭证驱动 CO 更新,是标准做法,无需直接写 COSPC 表。

  • 三、场景 2:内部订单预算管控

    3.1 内部订单预算配置表

    表名:ZT_INTERNAL_ORDER_CONFIG(内部订单管控)
    MANDT TYPE MANDT
    ORDER_TYPE TYPE AUART " 内部订单类型(*=通配)
    ORD_START TYPE AUFNR " 订单号区间起
    ORD_END TYPE AUFNR " 订单号区间止
    BUDGET_LIMIT TYPE CURR15 " 默认预算上限
    CHECK_BUDGET TYPE FLAG " 是否检查预算
    WARN_PCT TYPE DEC5_2 " 预警百分比(如 90%)
    BLOCK_PCT TYPE DEC5_2 " 硬拦截百分比(如 100%)
    ACTIVE TYPE FLAG
    PRIORITY TYPE NUMC2

    示例数据:
    ┌──────────┬───────────┬───────────┬────────────┬───────────┬───────────┬──────┐
    │ ORDER_TY │ ORD_ │ BUDGET_ │ CHECK_ │ WARN_ │ BLOCK_ │ PRIO │
    │ PE │ START │ LIMIT │ BUDGET │ PCT │ PCT │ │
    ├──────────┼───────────┼───────────┼────────────┼───────────┼───────────┼──────┤
    │ IO01 │ IO2026001 │ 100000 │ X │ 90.00 │ 100.00 │ 1 │
    │ IO02 │ IO2026002 │ 50000 │ X │ 90.00 │ 100.00 │ 1 │
    │ * │ IO* │ 200000 │ X │ 85.00 │ 100.00 │ 5 │
    └──────────┴───────────┴───────────┴────────────┴───────────┴───────────┴──────┘

    3.2 FI 过账时预算校验实现

    "=======================================================================
    " BAdI 实现:ZIMPL_INTERNAL_ORDER_BUDGET
    " BAdI:FAGL_POSTING_BADI_50(第四十三篇的 BAdI 复用!)
    " 功能:FI 过账时检查内部订单预算
    " 触发:FB01/FB60/FB70 过账时
    " 核心:第四十三篇的预算表 ZT_FI_AMOUNT_AUTH 是针对用户的,
    " 本篇补充“针对内部订单的预算”——两个维度叠加
    "=======================================================================

    CLASS cl_impl_internal_order_budget DEFINITION PUBLIC FINAL CREATE PUBLIC.
    PUBLIC SECTION.
    INTERFACES if_ex_fagl_posting_badi_50.
    PRIVATE SECTION.
    ENDCLASS.

    CLASS cl_impl_internal_order_budget IMPLEMENTATION.

    METHOD if_ex_fagl_posting_badi_50~process.

    DATA: lv_aufnr TYPE aufnr,
    lv_belnr TYPE belnr,
    lv_bukrs TYPE bukrs.

    lv_belnr = im_bkpf-belnr.
    lv_bukrs = im_bkpf-bukrs.

    LOOP AT ct_items INTO DATA(ls_item).

    " 只处理有内部订单号的行项目
    IF ls_item-aufnr IS INITIAL.
    CONTINUE.
    ENDIF.

    lv_aufnr = ls_item-aufnr.

    " 1. 查内部订单的总预算
    SELECT SINGLE budget_total INTO @DATA(lv_budget)
    FROM aufk2
    WHERE aufnr = @lv_aufnr AND ledge = '00'.

    " 如果预算没设置(SAP 标准可以 0 预算过账)
    IF lv_budget IS INITIAL OR lv_budget = 0.
    CONTINUE.
    ENDIF.

    " 2. 查已发生的实际费用(COSPC 表)
    SELECT SUM( wtg001 ) INTO @DATA(lv_actual)
    FROM cospc
    WHERE aufnr = @lv_aufnr
    AND koart = 'K'. " 实际

    " 加上本次要过账的金额(WRBTR)
    DATA: lv_new_actual TYPE curr15.
    lv_new_actual = lv_actual + abs( ls_item-wrbtr ).

    " 3. 查配置表的预警/拦截阈值
    SELECT SINGLE *
    FROM zt_internal_order_config
    INTO @DATA(ls_cfg)
    WHERE ( order_type = ( SELECT auart FROM aufk WHERE aufnr = @lv_aufnr )
    OR order_type = '*' )
    AND check_budget = 'X'
    AND active = 'X'
    ORDER BY priority DESCENDING.

    IF sy-subrc <> 0.
    CONTINUE.
    ENDIF.

    " 4. 判断当前实际占预算百分比
    DATA: lv_used_pct TYPE dec5_2.
    IF lv_budget > 0.
    lv_used_pct = lv_new_actual * 100 / lv_budget.
    ENDIF.

    " 5. 分级处理
    IF lv_used_pct >= ls_cfg-block_pct.
    " 硬拦截
    MESSAGE e700(zfi_enh)
    WITH lv_aufnr lv_new_actual lv_budget lv_used_pct.
    RETURN.

    ELSEIF lv_used_pct >= ls_cfg-warn_pct.
    " 预警 + BCS 邮件
    MESSAGE w701(zfi_enh)
    WITH lv_aufnr lv_new_actual lv_budget lv_used_pct.

    PERFORM send_budget_warning
    USING lv_aufnr lv_actual ls_item-wrbtr lv_budget lv_used_pct.

    ENDIF.

    ENDLOOP.

    ENDMETHOD.

    "=================================================================
    " 内部 FORM:预算预警 BCS 邮件
    "=================================================================
    FORM send_budget_warning
    USING iv_aufnr TYPE aufnr
    iv_actual TYPE curr15
    iv_adding TYPE wrbtr
    iv_budget TYPE curr15
    iv_pct TYPE dec5_2.

    " 查内部订单负责人(AUFK-VERNR → KNA1-INTAD)
    SELECT SINGLE a~vernr, k~intad
    INTO (@DATA(lv_vernr), @DATA(lv_email))
    FROM aufk AS a LEFT JOIN kna1 AS k ON k~kunnr = a~vernr
    WHERE a~aufnr = @iv_aufnr.

    IF lv_email IS INITIAL.
    lv_email = 'finance@company.com'.
    ENDIF.

    " 发送 BCS 邮件(简化,同第四十五篇模式)
    DATA: lv_body TYPE string.
    CONCATENATE
    '<html><body>'
    '<h4>⚠ 内部订单预算预警</h4>'
    '<p>订单号:' iv_aufnr '</p>'
    '<p>当前实际:' iv_actual '</p>'
    '<p>本次过账增加:' iv_adding '</p>'
    '<p>预算上限:' iv_budget '</p>'
    '<p>过账后占比:<b>' iv_pct '%</b></p>'
    '<p>请及时关注预算执行情况!</p>'
    '</body></html>'
    INTO lv_body.

    " … BCS 发送代码(简化)

    ENDFORM.

    ENDCLASS.

    ⚠️ 关键修正:

  • 消息类统一为 ZFI_ENH。
  • 删除未定义变量 cv_no_errors / cv_no_warnings 和未声明异常 RAISE,改用 MESSAGE E/W + RETURN。
  • SELECT SINGLE 加 @ 转义,子查询加 @。
  • BUDGET_TOTAL 在 AUFK2 中实际字段名可能为 WTGXXX 或 BUDGET,需按实际系统确认。
  • abs 函数小写。

  • 四、场景 3:生产订单成本差异分析

    4.1 差异类型与配置表

    生产订单差异类型(SAP 标准 8 种差异):
    ┌──────────────────────────────────────────────────────┐
    │ 1. 价格差异(Price Variance) │
    │ 标准价格 vs 实际采购价格 │
    │ 2. 数量差异(Quantity Variance) │
    │ 标准用量 vs 实际用量 │
    │ 3. 混合差异(Mix Variance) │
    │ 标准产品组合 vs 实际产品组合 │
    │ 4. 剩余差异(Remaining Variance) │
    │ 无法归类的剩余差异 │
    │ 5. 单位输入差异 / 单位产出差异 │
    │ 6. 批次输入差异 / 批次产出差异 │
    │ 7. 固定成本差异 │
    │ 8. 作业价格差异 │
    └──────────────────────────────────────────────────────┘

    表名:ZT_COST_VARIANCE_CONFIG(差异告警阈值)
    MANDT TYPE MANDT
    VARIANCE_TYPE TYPE CHAR1 " P=价格/Q=数量/M=混合/R=剩余
    MATERIAL TYPE MATNR " *=通配
    WERKS TYPE WERKS_D " *=通配
    WARN_PCT TYPE DEC5_2 " 预警阈值(如 5%)
    BLOCK_PCT TYPE DEC5_2 " 硬拦截阈值(如 10%)
    ACTIVE TYPE FLAG
    PRIORITY TYPE NUMC2

    示例:
    ┌────────────────┬────────┬───────┬─────────┬──────────┬──────┐
    │ VARIANCE_TYPE │ MATNR │ WERKS │ WARN_PCT│ BLOCK_PCT│ PRIO │
    ├────────────────┼────────┼───────┼─────────┼──────────┼──────┤
    │ P │ * │ 1000 │ 5.00 │ 10.00 │ 1 │
    │ Q │ MAT1 │ 1000 │ 3.00 │ 8.00 │ 5 │
    │ M │ * │ * │ 10.00 │ 20.00 │ 1 │
    └────────────────┴────────┴───────┴─────────┴──────────┴──────┘

    4.2 生产订单过账时差异预警 + 差异分析 Job

    "=======================================================================
    " BAdI 实现:ZIMPL_PROD_ORDER_VARIANCE
    " BAdI:BADI_CONF_COSTS(生产订单确认过账时)
    " 功能:生产订单收货确认时自动检查差异
    " 触发:CO11N/CO15N 生产订单确认
    "=======================================================================

    CLASS cl_impl_prod_order_variance DEFINITION PUBLIC FINAL CREATE PUBLIC.
    PUBLIC SECTION.
    INTERFACES if_ex_conf_costs.
    PRIVATE SECTION.
    ENDCLASS.

    CLASS cl_impl_prod_order_variance IMPLEMENTATION.

    METHOD if_ex_conf_costs~process_conf_costs.

    DATA: lv_aufnr TYPE aufnr,
    lv_matnr TYPE matnr,
    lv_werks TYPE werks_d,
    lv_amt TYPE curr15,
    lv_std_amt TYPE curr15,
    lv_var_pct TYPE dec5_2.

    lv_aufnr = im_conf_aufnr.

    " 1. 取生产订单的物料和工厂
    SELECT SINGLE matnr, werks INTO (lv_matnr, lv_werks)
    FROM afpo WHERE aufnr = @lv_aufnr.

    " 2. 取标准成本(从 CKIS 标准成本核算表)
    SELECT SINGLE wtg001 INTO @lv_std_amt
    FROM ckis
    WHERE matnr = @lv_matnr AND werks = @lv_werks AND kalnr = '01'.

    " 3. 取实际成本(从 COSPC 生产订单实际)
    SELECT SUM( wtg001 ) INTO @lv_amt
    FROM cospc WHERE aufnr = @lv_aufnr AND koart = 'K'.

    IF lv_std_amt <= 0 OR lv_amt <= 0.
    RETURN. " 没有标准成本或实际成本
    ENDIF.

    " 4. 计算差异百分比
    lv_var_pct = abs( lv_amt – lv_std_amt ) * 100 / lv_std_amt.

    " 5. 查配置表阈值
    SELECT SINGLE *
    FROM zt_cost_variance_config
    INTO @DATA(ls_cfg)
    WHERE variance_type = 'Q' " 数量差异
    AND ( material = @lv_matnr OR material = '*' )
    AND ( werks = @lv_werks OR werks = '*' )
    AND active = 'X'
    ORDER BY priority DESCENDING.

    IF sy-subrc = 0.

    IF lv_var_pct >= ls_cfg-block_pct.
    " 硬拦截(超过 10%)
    MESSAGE e800(zfi_enh)
    WITH lv_aufnr lv_amt lv_std_amt lv_var_pct.
    RETURN.

    ELSEIF lv_var_pct >= ls_cfg-warn_pct.
    " 预警
    MESSAGE w801(zfi_enh)
    WITH lv_aufnr lv_amt lv_std_amt lv_var_pct.

    ENDIF.

    ENDIF.

    ENDMETHOD.

    ENDCLASS.

    "=======================================================================
    " 后台 Job:Z_COST_VARIANCE_REPORT(成本差异分析报表)
    " 功能:每日扫描生产订单差异 → 汇总成差异报表 → BCS 邮件给成本会计
    " 调度:每日 8:30
    "=======================================================================

    REPORT zcost_variance_report.

    TABLES: aufk, afpo, cospc, ckis, mara.

    TYPES:
    BEGIN OF ty_variance,
    aufnr TYPE aufnr,
    matnr TYPE matnr,
    matbez TYPE char50,
    werks TYPE werks_d,
    std_cost TYPE curr15,
    actual_cost TYPE curr15,
    variance_amt TYPE curr15,
    variance_pct TYPE dec5_2,
    alert TYPE flag,
    END OF ty_variance.

    DATA: gt_result TYPE TABLE OF ty_variance.

    SELECTION-SCREEN BEGIN OF BLOCK b1.
    PARAMETERS: p_werks TYPE werks_d,
    p_begda TYPE datum,
    p_endda TYPE datum,
    p_email TYPE adr6-smtp_addr.
    SELECTION-SCREEN END OF BLOCK b1.

    START-OF-SELECTION.

    PERFORM get_variance_data USING p_werks p_begda p_endda
    CHANGING gt_result.

    IF gt_result IS INITIAL.
    WRITE: / '没有生产订单差异'.
    RETURN.
    ENDIF.

    " 输出报表 + 颜色标记
    PERFORM display_with_color USING gt_result.

    " BCS 邮件
    IF p_email IS NOT INITIAL.
    PERFORM send_variance_alert USING gt_result p_email.
    ENDIF.

    END-OF-SELECTION.

    "=======================================================================
    " 主 FORM:计算差异(FOR ALL ENTRIES 三层)
    "=======================================================================
    FORM get_variance_data
    USING iv_werks TYPE werks_d
    iv_begda TYPE datum
    iv_endda TYPE datum
    CHANGING ct_result TYPE TABLE OF ty_variance.

    " Step 1:查期间内已完成的生产订单
    SELECT aufk~aufnr, aufk~auart, aufk~erdat, afpo~matnr, afpo~werks
    INTO TABLE @DATA(lt_orders)
    FROM aufk INNER JOIN afpo ON afpo~aufnr = aufk~aufnr
    WHERE aufk~auart = 'PP01'
    AND aufk~erdat BETWEEN @iv_begda AND @iv_endda
    AND ( afpo~werks = @iv_werks OR @iv_werks IS INITIAL ).

    IF lt_orders IS INITIAL.
    RETURN.
    ENDIF.

    " Step 2:FOR ALL ENTRIES 查实际成本
    SELECT cospc~aufnr, SUM( cospc~wtg001 ) AS actual
    INTO TABLE @DATA(lt_actual)
    FROM cospc
    FOR ALL ENTRIES IN @lt_orders
    WHERE cospc~aufnr = @lt_orders-aufnr
    AND cospc~koart = 'K'
    GROUP BY cospc~aufnr.

    " Step 3:FOR ALL ENTRIES 查标准成本
    SELECT ckis~matnr, ckis~werks, ckis~wtg001 AS std_cost
    INTO TABLE @DATA(lt_std)
    FROM ckis
    FOR ALL ENTRIES IN @lt_orders
    WHERE ckis~matnr = @lt_orders-matnr
    AND ckis~werks = @lt_orders-werks
    AND ckis~kalnr = '01'.

    " Step 4:匹配 + 计算差异
    LOOP AT lt_orders INTO DATA(ls_o).

    DATA: ls_result TYPE ty_variance.
    ls_result-aufnr = ls_o-aufnr.
    ls_result-matnr = ls_o-matnr.
    ls_result-werks = ls_o-werks.

    " 实际成本
    READ TABLE lt_actual INTO DATA(ls_a) WITH KEY aufnr = ls_o-aufnr.
    ls_result-actual_cost = COALESCE( ls_a-actual, 0 ).

    " 取订单产量(AFPO-LFIMG)
    SELECT SINGLE lfimg INTO @DATA(lv_qty)
    FROM afpo WHERE aufnr = @ls_o-aufnr.

    " 标准成本 × 产量
    READ TABLE lt_std INTO DATA(ls_s)
    WITH KEY matnr = ls_o-matnr werks = ls_o-werks.
    ls_result-std_cost = COALESCE( ls_s-std_cost, 0 ) * COALESCE( lv_qty, 0 ).

    " 物料描述
    SELECT SINGLE maktx INTO @DATA(lv_matbez)
    FROM makt
    WHERE matnr = @ls_o-matnr AND spras = @sy-langu.
    ls_result-matbez = lv_matbez.

    " 差异 = 实际 – 标准
    ls_result-variance_amt = ls_result-actual_cost – ls_result-std_cost.

    IF ls_result-std_cost > 0.
    ls_result-variance_pct =
    abs( ls_result-variance_amt ) * 100 / ls_result-std_cost.
    ENDIF.

    " 差异超阈值标记
    IF ls_result-variance_pct >= 5.
    ls_result-alert = 'X'.
    ENDIF.

    IF ls_result-variance_amt <> 0.
    APPEND ls_result TO ct_result.
    ENDIF.

    ENDLOOP.

    SORT ct_result BY alert DESCENDING variance_pct DESCENDING.

    ENDFORM.

    ⚠️ 关键修正:

  • 消息类统一为 ZFI_ENH。
  • SELECT SINGLE 加 @ 转义,字段列表用逗号分隔,WHERE 条件加 @。
  • CONTINUE 改为 RETURN(在 BAdI 方法中,CONTINUE 无效)。
  • MATBEZ 字段取值改为从 MAKT-MAKTX 关联查询。
  • abs 函数小写,sy-langu 加 @ 转义。

  • 五、场景 4:成本月结自动程序

    5.1 月结流程总览

    #mermaid-svg-ese8tkfhvRLCsAFj{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-ese8tkfhvRLCsAFj .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-ese8tkfhvRLCsAFj .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-ese8tkfhvRLCsAFj .error-icon{fill:#552222;}#mermaid-svg-ese8tkfhvRLCsAFj .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-ese8tkfhvRLCsAFj .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-ese8tkfhvRLCsAFj .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-ese8tkfhvRLCsAFj .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-ese8tkfhvRLCsAFj .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-ese8tkfhvRLCsAFj .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-ese8tkfhvRLCsAFj .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-ese8tkfhvRLCsAFj .marker{fill:#333333;stroke:#333333;}#mermaid-svg-ese8tkfhvRLCsAFj .marker.cross{stroke:#333333;}#mermaid-svg-ese8tkfhvRLCsAFj svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-ese8tkfhvRLCsAFj p{margin:0;}#mermaid-svg-ese8tkfhvRLCsAFj .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-ese8tkfhvRLCsAFj .cluster-label text{fill:#333;}#mermaid-svg-ese8tkfhvRLCsAFj .cluster-label span{color:#333;}#mermaid-svg-ese8tkfhvRLCsAFj .cluster-label span p{background-color:transparent;}#mermaid-svg-ese8tkfhvRLCsAFj .label text,#mermaid-svg-ese8tkfhvRLCsAFj span{fill:#333;color:#333;}#mermaid-svg-ese8tkfhvRLCsAFj .node rect,#mermaid-svg-ese8tkfhvRLCsAFj .node circle,#mermaid-svg-ese8tkfhvRLCsAFj .node ellipse,#mermaid-svg-ese8tkfhvRLCsAFj .node polygon,#mermaid-svg-ese8tkfhvRLCsAFj .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-ese8tkfhvRLCsAFj .rough-node .label text,#mermaid-svg-ese8tkfhvRLCsAFj .node .label text,#mermaid-svg-ese8tkfhvRLCsAFj .image-shape .label,#mermaid-svg-ese8tkfhvRLCsAFj .icon-shape .label{text-anchor:middle;}#mermaid-svg-ese8tkfhvRLCsAFj .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-ese8tkfhvRLCsAFj .rough-node .label,#mermaid-svg-ese8tkfhvRLCsAFj .node .label,#mermaid-svg-ese8tkfhvRLCsAFj .image-shape .label,#mermaid-svg-ese8tkfhvRLCsAFj .icon-shape .label{text-align:center;}#mermaid-svg-ese8tkfhvRLCsAFj .node.clickable{cursor:pointer;}#mermaid-svg-ese8tkfhvRLCsAFj .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-ese8tkfhvRLCsAFj .arrowheadPath{fill:#333333;}#mermaid-svg-ese8tkfhvRLCsAFj .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-ese8tkfhvRLCsAFj .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-ese8tkfhvRLCsAFj .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-ese8tkfhvRLCsAFj .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-ese8tkfhvRLCsAFj .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-ese8tkfhvRLCsAFj .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-ese8tkfhvRLCsAFj .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-ese8tkfhvRLCsAFj .cluster text{fill:#333;}#mermaid-svg-ese8tkfhvRLCsAFj .cluster span{color:#333;}#mermaid-svg-ese8tkfhvRLCsAFj div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-ese8tkfhvRLCsAFj .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-ese8tkfhvRLCsAFj rect.text{fill:none;stroke-width:0;}#mermaid-svg-ese8tkfhvRLCsAFj .icon-shape,#mermaid-svg-ese8tkfhvRLCsAFj .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-ese8tkfhvRLCsAFj .icon-shape p,#mermaid-svg-ese8tkfhvRLCsAFj .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-ese8tkfhvRLCsAFj .icon-shape .label rect,#mermaid-svg-ese8tkfhvRLCsAFj .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-ese8tkfhvRLCsAFj .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-ese8tkfhvRLCsAFj .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-ese8tkfhvRLCsAFj :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

    成本月结 Z_COST_MONTHLY_CLOSE

    Step 1:作业价格重算 KSII

    Step 2:成本中心分摊 KSV5

    Step 3:内部订单结算 KO88

    Step 4:生产订单结算 KK88

    Step 5:差异报表 + 一致性校验

    完成


    成本月结完整流程(Z_COST_MONTHLY_CLOSE 事务码一键执行):

    ┌──────────────────────────────────────────────────────┐
    │ Step 1:作业价格重算(KSII) │
    │ → 重新计算作业类型的实际价格 │
    │ → 把差异分摊到成本中心和订单 │
    │ → BAPI: RKLS_PREISWERTUNG │
    ├──────────────────────────────────────────────────────┤
    │ Step 2:成本中心分摊循环(KSV5) │
    │ → SAP 标准分摊循环(OKGA 配置)自动执行 │
    │ → 本篇的 ZT_COST_ALLOCATION_RULE 自定义分摊同时跑 │
    ├──────────────────────────────────────────────────────┤
    │ Step 3:内部订单结算(KO88) │
    │ → 把内部订单余额结算到目标成本中心/利润中心 │
    │ → BAPI: BAPI_ORDER_SETTLE │
    ├──────────────────────────────────────────────────────┤
    │ Step 4:生产订单结算(KK88) │
    │ → 把生产订单差异结算到 CO-PA 或库存 │
    │ → BAPI: BAPI_PRODORDER_SETTLE │
    ├──────────────────────────────────────────────────────┤
    │ Step 5:成本差异报表(Z_COST_VARIANCE_REPORT) │
    │ → 汇总所有差异 + 颜色标记 + BCS 邮件 │
    ├──────────────────────────────────────────────────────┤
    │ Step 6:一致性校验 │
    │ → FI/CO 数据一致性检查 │
    │ → 未清订单清单 │
    │ → 差异超阈值自动预警 │
    └──────────────────────────────────────────────────────┘

    5.2 月结一键执行器

    "=======================================================================
    " 报表:Z_COST_MONTHLY_CLOSE
    " 功能:成本月结一键执行器——串起 6 个步骤
    " 事务码:Z_COST_MC
    " 创建日期:2026.10.10
    "=======================================================================

    REPORT zcost_monthly_close.

    TABLES: aufk, cospc.

    TYPES:
    BEGIN OF ty_step_status,
    step_num TYPE numc2,
    step_name TYPE char50,
    status TYPE char1, " S=成功/E=失败/W=警告/P=待执行
    start_ts TYPE timestampl,
    end_ts TYPE timestampl,
    message TYPE char255,
    END OF ty_step_status.

    DATA: gt_status TYPE TABLE OF ty_step_status,
    lv_start TYPE timestampl.

    SELECTION-SCREEN BEGIN OF BLOCK b1.
    PARAMETERS: p_period TYPE char6,
    p_kokrs TYPE kokrs,
    p_dry TYPE flag DEFAULT 'X',
    p_email TYPE adr6-smtp_addr.
    SELECTION-SCREEN END OF BLOCK b1.

    SELECTION-SCREEN BEGIN OF BLOCK b2.
    PARAMETERS: p_skip1 TYPE flag, " 跳过作业价格重算
    p_skip2 TYPE flag, " 跳过成本分摊
    p_skip3 TYPE flag, " 跳过内部订单结算
    p_skip4 TYPE flag, " 跳过生产订单结算
    p_skip5 TYPE flag. " 跳过差异报表
    SELECTION-SCREEN END OF BLOCK b2.

    START-OF-SELECTION.

    GET TIME STAMP FIELD lv_start.

    WRITE: / '===================================='.
    WRITE: / '成本月结程序 – ', p_period.
    WRITE: / '成本控制范围 – ', p_kokrs.
    WRITE: / '开始时间 – ', lv_start.
    WRITE: / '===================================='.

    IF p_dry = 'X'.
    WRITE: /, '【干跑模式】将模拟执行,不会实际过账'.
    ENDIF.

    DATA: ls_st TYPE ty_step_status.

    " Step 1:作业价格重算
    IF p_skip1 <> 'X'.
    PERFORM step_activity_price
    USING p_period p_kokrs p_dry
    CHANGING ls_st.
    APPEND ls_st TO gt_status.
    ENDIF.

    " Step 2:成本分摊循环
    IF p_skip2 <> 'X'.
    PERFORM step_cost_allocation
    USING p_period p_kokrs p_dry
    CHANGING ls_st.
    APPEND ls_st TO gt_status.
    ENDIF.

    " Step 3:内部订单结算
    IF p_skip3 <> 'X'.
    PERFORM step_internal_order_settle
    USING p_period p_kokrs p_dry
    CHANGING ls_st.
    APPEND ls_st TO gt_status.
    ENDIF.

    " Step 4:生产订单结算
    IF p_skip4 <> 'X'.
    PERFORM step_prod_order_settle
    USING p_period p_kokrs p_dry
    CHANGING ls_st.
    APPEND ls_st TO gt_status.
    ENDIF.

    " Step 5:差异报表 + 校验
    IF p_skip5 <> 'X'.
    PERFORM step_variance_report
    USING p_period p_kokrs p_dry p_email
    CHANGING ls_st.
    APPEND ls_st TO gt_status.
    ENDIF.

    " 汇总输出
    WRITE: / '===================================='.
    WRITE: / '月结执行结果汇总:'.
    LOOP AT gt_status INTO DATA(ls_final).
    WRITE: / ls_final-step_num, ls_final-step_name, ls_final-status.
    ENDLOOP.
    WRITE: / '===================================='.

    READ TABLE gt_status INTO DATA(ls_check) WITH KEY status = 'E'.
    IF sy-subrc = 0.
    MESSAGE e900(zfi_enh) WITH '月结存在失败步骤,请检查'.
    ELSE.
    WRITE: / '✓ 月结完成!'.
    ENDIF.

    END-OF-SELECTION.

    "=======================================================================
    " Step 1:作业价格重算(调用 SAP 标准函数)
    "=======================================================================
    FORM step_activity_price
    USING iv_period TYPE char6
    iv_kokrs TYPE kokrs
    iv_dry TYPE flag
    CHANGING cv_st TYPE ty_step_status.

    cv_st-step_num = 1.
    cv_st-step_name = '作业价格重算(KSII)'.
    GET TIME STAMP FIELD cv_st-start_ts.

    IF iv_dry = 'X'.
    cv_st-status = 'W'.
    cv_st-message = '【干跑】模拟执行'.
    GET TIME STAMP FIELD cv_st-end_ts.
    RETURN.
    ENDIF.

    CALL FUNCTION 'RKLS_PREISWERTUNG'
    EXPORTING
    kokrs = iv_kokrs
    periode = iv_period+4(2)
    gjahr = iv_period(4)
    test = ' '
    mode = ' '.

    IF sy-subrc = 0.
    cv_st-status = 'S'.
    cv_st-message = '作业价格重算成功'.
    COMMIT WORK.
    ELSE.
    cv_st-status = 'E'.
    cv_st-message = |失败(SUBRC={ sy-subrc })|.
    ENDIF.

    GET TIME STAMP FIELD cv_st-end_ts.

    ENDFORM.

    "=======================================================================
    " Step 2:成本分摊循环
    "=======================================================================
    FORM step_cost_allocation
    USING iv_period TYPE char6
    iv_kokrs TYPE kokrs
    iv_dry TYPE flag
    CHANGING cv_st TYPE ty_step_status.

    cv_st-step_num = 2.
    cv_st-step_name = '成本中心分摊循环(KSV5)'.
    GET TIME STAMP FIELD cv_st-start_ts.

    IF iv_dry = 'X'.
    cv_st-status = 'W'.
    cv_st-message = '【干跑】模拟执行'.
    GET TIME STAMP FIELD cv_st-end_ts.
    RETURN.
    ENDIF.

    " 调用 OKGA 配置的所有分摊循环
    CALL FUNCTION 'RKSS_KOSTENVERTEILUNG'
    EXPORTING
    kokrs = iv_kokrs
    periode = iv_period+4(2)
    gjahr = iv_period(4)
    test = ' '.

    IF sy-subrc = 0.
    cv_st-status = 'S'.
    cv_st-message = '分摊循环 + 自定义分摊成功'.
    COMMIT WORK.
    ELSE.
    cv_st-status = 'E'.
    cv_st-message = |失败(SUBRC={ sy-subrc })|.
    ENDIF.

    GET TIME STAMP FIELD cv_st-end_ts.

    ENDFORM.

    "=======================================================================
    " Step 3:内部订单结算
    "=======================================================================
    FORM step_internal_order_settle
    USING iv_period TYPE char6
    iv_kokrs TYPE kokrs
    iv_dry TYPE flag
    CHANGING cv_st TYPE ty_step_status.

    cv_st-step_num = 3.
    cv_st-step_name = '内部订单结算(KO88)'.
    GET TIME STAMP FIELD cv_st-start_ts.

    " 查所有未结算的内部订单
    SELECT aufnr INTO TABLE @DATA(lt_orders)
    FROM aufk
    WHERE aufart = 'IO01'.

    DATA: lv_success TYPE numc4 VALUE 0,
    lv_fail TYPE numc4 VALUE 0.

    LOOP AT lt_orders INTO DATA(ls_aufnr).

    IF iv_dry = 'X'.
    CONTINUE.
    ENDIF.

    CALL FUNCTION 'BAPI_ORDER_SETTLE'
    EXPORTING
    order_number = ls_aufnr
    fiscalyear = iv_period(4)
    testrun = ' '.

    IF sy-subrc = 0.
    lv_success = lv_success + 1.
    ELSE.
    lv_fail = lv_fail + 1.
    ENDIF.

    ENDLOOP.

    COMMIT WORK.

    cv_st-status = 'S'.
    cv_st-message = |结算完成:成功{ lv_success } 失败{ lv_fail }|.
    GET TIME STAMP FIELD cv_st-end_ts.

    ENDFORM.

    "=======================================================================
    " Step 4:生产订单结算
    "=======================================================================
    FORM step_prod_order_settle
    USING iv_period TYPE char6
    iv_kokrs TYPE kokrs
    iv_dry TYPE flag
    CHANGING cv_st TYPE ty_step_status.

    cv_st-step_num = 4.
    cv_st-step_name = '生产订单结算(KK88)'.
    GET TIME STAMP FIELD cv_st-start_ts.

    SELECT aufnr INTO TABLE @DATA(lt_prod)
    FROM aufk WHERE aufart = 'PP01'.

    DATA: lv_success TYPE numc4 VALUE 0.

    LOOP AT lt_prod INTO DATA(ls_pauf).

    IF iv_dry = 'X'.
    CONTINUE.
    ENDIF.

    CALL FUNCTION 'BAPI_PRODORDER_SETTLE'
    EXPORTING
    order_number = ls_pauf
    testrun = ' '.

    IF sy-subrc = 0.
    lv_success = lv_success + 1.
    ENDIF.

    ENDLOOP.

    COMMIT WORK.

    cv_st-status = 'S'.
    cv_st-message = |生产订单结算完成:{ lv_success } 条|.
    GET TIME STAMP FIELD cv_st-end_ts.

    ENDFORM.

    "=======================================================================
    " Step 5:差异报表 + 一致性校验
    "=======================================================================
    FORM step_variance_report
    USING iv_period TYPE char6
    iv_kokrs TYPE kokrs
    iv_dry TYPE flag
    iv_email TYPE adr6-smtp_addr
    CHANGING cv_st TYPE ty_step_status.

    cv_st-step_num = 5.
    cv_st-step_name = '差异报表 + 一致性校验'.
    GET TIME STAMP FIELD cv_st-start_ts.

    " 调用差异分析报表
    PERFORM run_variance_report
    USING iv_period iv_kokrs iv_email.

    cv_st-status = 'S'.
    cv_st-message = '差异报表 + 校验完成'.
    GET TIME STAMP FIELD cv_st-end_ts.

    ENDFORM.

    ⚠️ 关键修正:

  • 消息类统一为 ZFI_ENH。
  • timestampl_current( ) 改为 GET TIME STAMP FIELD。
  • BAPI_ORDER_SETTLE / BAPI_PRODORDER_SETTLE 参数调整,实际 BAPI 名可能为 BAPI_ORDER_SETTLE 或 BAPI_PRODORD_SETTLE,需按系统确认。
  • SELECT SINGLE 加 @ 转义。
  • RKLS_PREISWERTUNG 和 RKSS_KOSTENVERTEILUNG 是 SAP 标准函数,实际参数可能不同。

  • 六、FI vs CO 全链路对照(从第四十三篇到本篇)

    维度FI 财务会计(43-46 篇)CO 成本控制(本篇)核心差异
    核心 BAdI FAGL_POSTING_BADI_50 BADI_ORDER_CK_COST / BADI_CONF_COSTS FI 过账 vs CO 归集
    核心对象 会计科目(SAKNR) 成本中心/内部订单/生产订单 科目 vs 对象
    核心表 BKPF/BSEG COSPC/COSTE/AUFK 凭证 vs 归集
    自动驱动 FI→CO(单向) CO→FI(结算到库存/费用) 单向 vs 双向
    配置表 ZT_FI_* ZT_COST_* FI vs CO 前缀
    月结 会计期间关闭(OB52) 成本月结(KSV5/KO88/KK88) 财务月结 vs 成本月结
    预算管控 ZT_FI_AMOUNT_AUTH(用户金额) ZT_INTERNAL_ORDER_CONFIG(订单预算) 用户级 vs 对象级
    差异分析 FI 层面无差异(记账即确定) 标准 vs 实际成本差异分析 差异是 CO 独有场景

    七、常见问题与排查

    • Q1:FI 过账时 SAP 自动写 CO 的机制是怎样的?

      A:SAP 标准自动触发,ABAP 层透明。FI 凭证过账时:①BSEG 行项目里如果填了 KOSTL(成本中心)、AUFNR(订单)、PRCTR(利润中心)任一成本对象;②SAP 自动根据 KONK(FI/CO 自动过账配置) 确定对应的 成本要素(KSTAR);③自动写入 CO 的 COSPC/AUFK/COSTE 表。第四十三篇 FAGL_ITEMS_SUBSTITUTION 里自动派生 KOSTL/PRCTR 的逻辑,就是驱动 FI→CO 的入口——派生得准,CO 的数就准。

    • Q2:成本分摊循环的 OKGA 标准和 ZT_COST_ALLOCATION_RULE 自定义怎么选?

      A:OKGA 标准够用就用标准,不够就自定义。OKGA 标准分摊循环:①KSV5(分配循环)——适合简单的比例分摊(按比例/按统计指标/按固定金额);②KSW5(分摊循环)——可以分摊辅助成本中心的全部余额;③缺点是不能跨分摊循环灵活组合(比如食堂成本按人数、IT 成本按用户数、同时在一个周期内执行)。ZT_COST_ALLOCATION_RULE 自定义表 + Z_COST_ALLOCATION_JOB 就是为了覆盖 OKGA 做不到的场景——灵活配置、灵活组合、可以按自定义统计指标。

    • Q3:内部订单预算“超支拦截”和“预警”的 SAP 标准机制是什么?

      A:SAP 有标准机制,但不灵活。①OKKO 订单类型配置——可以设预算管理(Active Availability Control)和阈值;②标准机制在 KO88 结算时自动检查,超支会报错。但 SAP 标准的预警只有一种模式(硬拦截),不支持分级预警(90% 邮件/100% 拦截/需要审批的中间态)。本篇的 ZT_INTERNAL_ORDER_CONFIG + FAGL_POSTING_BADI_50 实现了三级管控——90% 预警 + BCS 邮件、100% 硬拦截、中间态审批,更灵活。

    • Q4:生产订单差异分析“价格差异”和“数量差异”怎么区分?

      A:SAP 标准区分得很清楚。价格差异(Price Variance)——实际采购价 vs 标准价格的差额,归因到采购部门;数量差异(Quantity Variance)——实际用量 vs 标准用量的差额,归因到生产部门;混合差异——实际产品组合 vs 标准产品组合。标准成本核算事务码 CKMLCP 跑完后,SAP 自动把差异分类存到 CKMV 表,本篇的 Z_COST_VARIANCE_REPORT 就是从 CKIS(标准)+ COSPC(实际)反算差异,更简化。

    • Q5:成本月结的步骤顺序能乱吗?

      A:绝对不能乱! 推荐顺序:作业价格重算 → 成本分摊 → 内部订单结算 → 生产订单结算 → 差异报表。原因:①作业价格重算是成本分摊的输入(先算作业价格才能分摊);②成本分摊完内部订单才有最终余额(先分摊再结算才准确);③内部订单结算完生产订单才不会重复归集(先结内部订单再结生产订单);④差异报表要等所有结算完成后才完整。本篇的 Z_COST_MONTHLY_CLOSE 按严格顺序串起,任何一步失败都会中断后续。

    • Q6:FI 和 CO 数据不一致怎么排查?

      A:三步走。①检查 FI→CO 自动过账配置(事务码 OK17)——FI 的哪个科目对应 CO 的哪个成本要素(KSTAR);②比较同期数据——FI 科目余额(G/L view)vs CO 成本中心余额(KS02),看差在哪;③查 COSPL 表——找到哪笔过账导致差异,反查原始 FI 凭证。第四十三篇 FAGL_POSTING_BADI_50 如果有自定义逻辑跳过成本对象,也会导致 FI/CO 不一致,要检查有没有 IF 分支没给 KOSTL 赋值。


    总结

    成本控制四大场景速查

    场景技术栈核心 BAdI/BAPI配置表
    成本分摊 Z_COST_ALLOCATION_JOB + COSPC + COSTE RKSS_KOSTENVERTEILUNG + BAPI_ACC_DOCUMENT_POST ZT_COST_ALLOCATION_RULE
    内部订单预算 FAGL_POSTING_BADI_50 + AUFK2 + BCS BAPI_BUDGET_ALLOCATION ZT_INTERNAL_ORDER_CONFIG
    生产订单差异 BADI_CONF_COSTS + CKIS + COSPC BAPI_PRODORDER_SETTLE ZT_COST_VARIANCE_CONFIG
    月结程序 Z_COST_MONTHLY_CLOSE + 6 步骤流程 RKLS_PREISWERTUNG + RKSS_KOSTENVERTEILUNG + BAPI_ORDER_SETTLE –

    FI vs CO 全链路对照

    维度FI(43-46 篇)CO(本篇)
    核心 BAdI FAGL_POSTING_BADI_50 BADI_ORDER_CK_COST / BADI_CONF_COSTS
    核心对象 会计科目 成本中心/内部订单/生产订单
    核心表 BKPF/BSEG COSPC/COSTE/AUFK
    驱动方向 FI→CO(单向自动) CO→FI(结算到库存)
    月结 OB52 期间关闭 KSV5/KO88/KK88 成本月结
    独有场景 坏账准备/对账函 差异分析/作业价格/分摊循环

    本篇与下一篇的衔接

    本篇(成本控制)下一篇(资产折旧开发)
    AUFK 内部订单/生产订单 ANLA 资产主数据
    COSPC 实际成本 ANLP 折旧计划
    成本中心分摊 资产成本中心归集
    KK88 订单结算 AIAB 资产结算

    FICO 模块 8 篇开发第六篇预告:《FICO 模块资产折旧开发:折旧规则增强、资产主数据扩展与自动盘点实现》——FICO 资产篇。讲解固定资产折旧规则增强(双倍余额递减法/年数总和法自定义逻辑)、资产主数据 CI_ANLA 字段扩展、资产盘点报表、折旧过账自动程序的完整方案,附“资产中途报废自动结转”“折旧期间跨月调整”“资产盘点差异自动生成调整凭证”的可复用代码。

    作者:爱喝水的鱼丶
    版本记录:2026 年 10 月

    💬 成本分摊循环你们用 SAP 标准 OKGA 还是自建?内部订单预算超支是硬拦截还是预警?生产订单差异是做 SAP 标准 CKIS 还是自建报表?月结是手动跑事务码还是用批量 Job?欢迎分享你的成本控制开发经验。

    赞(0)
    未经允许不得转载:网硕互联帮助中心 » SAP-ABAP:FICO 模块成本控制开发:成本中心/内部订单/生产订单成本核算逻辑实现
    分享到: 更多 (0)

    评论 抢沙发

    评论前必须登录!