Recientemente hice una extensión para la aplicación My Inbox Fiori para aprobaciones de órdenes de compra y solicitudes de compra. Como principiante, no sabía por dónde empezar inicialmente. Después de investigar un poco, encontré un blog de Ragini Upadhyay (https://blogs.sap.com/2018/06/02/fiori-my-inbox-2.0-extend-approve-purchase-order-s4-hana-1610/) que estaba bien explicado pero tuve que luchar mucho. Hay pocos lugares donde esta solución no fue precisa y no funcionó. Esto podría deberse a la versión S4. Luego encontré alguna solución y finalmente puedo lograrlo. Vamos a oírlo…
Muestre los aprobadores junto con el estado en la pantalla de detalles tanto para la orden de compra como para la solicitud de compra.
La pantalla de detalles de mi bandeja de entrada para PR y PO se basa en la anotación de cds. En este caso, las anotaciones se cargan desde el modelo de servicio y los enlaces a continuación cargan estas anotaciones en la aplicación.
/sap/opu/odata/IWFND/CATALOGSERVICE;v=2/Annotations(TechnicalName="C_PURREQUISITION_FS_ANNO_MDL",Version='0001')/$value
/sap/opu/odata/IWFND/CATALOGSERVICE;v=2/Annotations(TechnicalName="C_PURCHASEORDER_FS_ANNO_MDL",Version='0001')/$value
relaciones públicas – C_PurchaseOrderFs
correos – C_PurRequisitionFs
relaciones públicas – EBAN (Detalles de encabezado PR y estrategia de publicación) -> T16FS (Códigos de lanzamiento de la estrategia de lanzamiento) -> T16FD (Códigos de versión del grupo de versión) -> T16FW (ID de usuario de los códigos de liberación) -> USR21 (Número de personal de ID de usuario) -> ADRP (Nombre completo de usuario de Número personal)
correos – EKKO (Detalles del encabezado de la orden de compra) -> T16FD (Códigos de versión del grupo de versión) -> T16FW (ID de usuario de los códigos de liberación) -> USR21 (Número de personal de ID de usuario) -> ADRP (Nombre completo del usuario del número personal)
@AbapCatalog.sqlViewName: 'ZSQ_PURORD_APP'
@AbapCatalog.compiler.compareFilter: true
@AbapCatalog.preserveKey: true
@AccessControl.authorizationCheck: #NOT_REQUIRED
@EndUserText.label: 'CDS for PO Approvals'
define view ZCDS_PUR_ORD_APP as select from ekko as _PurOrd
left outer join t16fw as _RoleRelCode
on _PurOrd.frggr = _RoleRelCode.frggr
left outer join t16fd as _RelCodeDesc
on _PurOrd.frggr = _RelCodeDesc.frggr and _RoleRelCode.frgco = _RelCodeDesc.frgco
{
_PurOrd.ebeln,
_PurOrd.frggr,
_PurOrd.frgsx,
_PurOrd.frgke,
_PurOrd.frgzu,
_RoleRelCode.objid,
_RoleRelCode.otype,
_RelCodeDesc.frgct,
_RelCodeDesc.frgco
}
Consecuencia de ZCDS_PUR_ORD_APP (Mostrando aprobadores en varias filas)
objid = ID de usuario
frgct = Posición del usuario
Ejemplo:
Aquí vamos…
@AbapCatalog.sqlViewName: 'ZSQ_PO_APPF'
@AbapCatalog.compiler.compareFilter: true
@AbapCatalog.preserveKey: true
@AccessControl.authorizationCheck: #NOT_REQUIRED
@EndUserText.label: 'PO Approvals Final V2'
define view ZCDS_PUR_ORD_APP_F as select from ZCDS_PUR_ORD_APP
association [1..1] to ZCDS_USER_DET as _UserDet on ZCDS_PUR_ORD_APP.objid = _UserDet.UserId {
ebeln,
max( case frgco when '00' then objid end ) as ApproverID1,
max( case frgco when '11' then objid end ) as ApproverID2,
max( case frgco when '36' then objid end ) as ApproverID3,
max( case frgco when '37' then objid end ) as ApproverID4,
max( case frgco when '00' then frgct end ) as ApprPosition1,
max( case frgco when '11' then frgct end ) as ApprPosition2,
max( case frgco when '36' then frgct end ) as ApprPosition3,
max( case frgco when '37' then frgct end ) as ApprPosition4,
max( case frgco when '00' then _UserDet.UserFName end ) as ApproverName1,
max( case frgco when '11' then _UserDet.UserFName end ) as ApproverName2,
max( case frgco when '36' then _UserDet.UserFName end ) as ApproverName3,
max( case frgco when '37' then _UserDet.UserFName end ) as ApproverName4,
substring(frgzu,1,1) as ApprovedLevel1,
substring(frgzu,2,1) as ApprovedLevel2,
substring(frgzu,3,1) as ApprovedLevel3,
substring(frgzu,4,1) as ApprovedLevel4
} group by ebeln, frgzu
Resultado
@AbapCatalog.sqlViewName: 'ZSQ_USRDET'
@AbapCatalog.compiler.compareFilter: true
@AbapCatalog.preserveKey: true
@AccessControl.authorizationCheck: #NOT_REQUIRED
@EndUserText.label: 'User Details'
define view ZCDS_USER_DET as select from usr21 as _User
inner join adrp as _PersDet
on _User.persnumber = _PersDet.persnumber {
key _User.bname as UserId,
_User.persnumber as PersNo,
_PersDet.name_text as UserFName
}
@AbapCatalog.sqlViewAppendName: 'ZSQ_PURORDFS_EXT'
@EndUserText.label: 'Extension for C_PurchaseOrderFs'
extend view C_PurchaseOrderFs with ZC_PurchaseOrderFs_EXT
association [1..1] to ZCDS_PUR_ORD_APP_F as _Approver on I_PurchaseOrderEnhanced.purchaseorder = _Approver.ebeln
{
@UI.fieldGroup: [{
qualifier: 'Recipient',
groupLabel: 'Recipient', groupLabel_asOtr: 'FA163EDF73161EE587C742C45B2B0F3D',
position: 40,
exclude: false,
importance: #HIGH }, {
qualifier: 'Detail3',
groupLabel: 'Recipient', groupLabel_asOtr: 'FA163EDF73161EE587C742C45B2B0F3D',
position: 40,
exclude: false,
importance: #HIGH
}]
@EndUserText.label: 'Approver Level 1'
case when _Approver.ApprovedLevel1 = 'X'
then CONCAT(_Approver.ApproverName1, ' - Approved')
else CONCAT(_Approver.ApproverName1, ' - Pending')
end as ApproverID1,
// _UserDet.UserFName as ApproverName1,
@UI.fieldGroup: [{
qualifier: 'Recipient',
groupLabel: 'Recipient', groupLabel_asOtr: 'FA163EDF73161EE587C742C45B2B0F3D',
position: 50,
exclude: false,
importance: #HIGH }, {
qualifier: 'Detail3',
groupLabel: 'Recipient', groupLabel_asOtr: 'FA163EDF73161EE587C742C45B2B0F3D',
position: 50,
exclude: false,
importance: #HIGH
}]
@EndUserText.label: 'Approver Level 2'
case when _Approver.ApprovedLevel2 = 'X'
then CONCAT(_Approver.ApproverName2, ' - Approved')
else CONCAT(_Approver.ApproverName2, ' - Pending')
end as ApproverID2,
@UI.fieldGroup: [{
qualifier: 'Recipient',
groupLabel: 'Recipient', groupLabel_asOtr: 'FA163EDF73161EE587C742C45B2B0F3D',
position: 60,
exclude: false,
importance: #HIGH }, {
qualifier: 'Detail3',
groupLabel: 'Recipient', groupLabel_asOtr: 'FA163EDF73161EE587C742C45B2B0F3D',
position: 60,
exclude: false,
importance: #HIGH
}]
@EndUserText.label: 'Approver Level 3'
case when _Approver.ApprovedLevel3 = 'X'
then CONCAT(_Approver.ApproverName3, ' - Approved')
else CONCAT(_Approver.ApproverName3, ' - Pending')
end as ApproverID3,
@UI.fieldGroup: [{
qualifier: 'Recipient',
groupLabel: 'Recipient', groupLabel_asOtr: 'FA163EDF73161EE587C742C45B2B0F3D',
position: 70,
exclude: false,
importance: #HIGH }, {
qualifier: 'Detail3',
groupLabel: 'Recipient', groupLabel_asOtr: 'FA163EDF73161EE587C742C45B2B0F3D',
position: 70,
exclude: false,
importance: #HIGH
}]
@EndUserText.label: 'Approver Level 4'
case when _Approver.ApprovedLevel4 = 'X'
then CONCAT(_Approver.ApproverName4, ' - Approved')
else CONCAT(_Approver.ApproverName4, ' - Pending')
end as ApproverID4
}
Eso es todo. Hemos terminado.
@AbapCatalog.sqlViewName: 'ZSQ_PURREQ_APP'
@AbapCatalog.compiler.compareFilter: true
@AbapCatalog.preserveKey: true
@AccessControl.authorizationCheck: #NOT_REQUIRED
@EndUserText.label: 'CDS for PR Approvals'
define view ZCDS_PUR_REQ_APP as select from eban as _PurReq
left outer join t16fs as _RelStat on _PurReq.frggr = _RelStat.frggr
and _PurReq.frgst = _RelStat.frgsx
left outer join t16fd as _RelCodeDesc on _PurReq.frggr = _RelCodeDesc.frggr
and ( _RelStat.frgc1 = _RelCodeDesc.frgco
or _RelStat.frgc2 = _RelCodeDesc.frgco
or _RelStat.frgc3 = _RelCodeDesc.frgco
or _RelStat.frgc4 = _RelCodeDesc.frgco
or _RelStat.frgc5 = _RelCodeDesc.frgco
or _RelStat.frgc6 = _RelCodeDesc.frgco
or _RelStat.frgc7 = _RelCodeDesc.frgco
or _RelStat.frgc8 = _RelCodeDesc.frgco )
left outer join t16fw as _RoleRelCode on _PurReq.frggr = _RoleRelCode.frggr
and _RelCodeDesc.frgco = _RoleRelCode.frgco
{
_PurReq.banfn,
_PurReq.frgkz,
_PurReq.frgzu,
_PurReq.frgst,
_PurReq.frggr,
_RelStat.frgc1,
_RelStat.frgc2,
_RelStat.frgc3,
_RelStat.frgc4,
_RelStat.frgc5,
_RelStat.frgc6,
_RelStat.frgc7,
_RelStat.frgc8,
_RoleRelCode.objid,
_RoleRelCode.otype,
_RelCodeDesc.frgct,
_RelCodeDesc.frgco
}
@AbapCatalog.sqlViewName: 'ZSQ_PR_APPF'
@AbapCatalog.compiler.compareFilter: true
@AbapCatalog.preserveKey: true
@AccessControl.authorizationCheck: #NOT_REQUIRED
@EndUserText.label: 'PR Approvals Final V2'
define view ZCDS_PUR_REQ_APP_F as select from ZCDS_PUR_REQ_APP
association [1..1] to ZCDS_USER_DET as _UserDet on ZCDS_PUR_REQ_APP.objid = _UserDet.UserId {
banfn,
max( case frgco when frgc1 then objid end ) as ApproverID1,
max( case frgco when frgc2 then objid end ) as ApproverID2,
max( case frgco when frgc3 then objid end ) as ApproverID3,
max( case frgco when frgc4 then objid end ) as ApproverID4,
max( case frgco when frgc5 then objid end ) as ApproverID5,
max( case frgco when frgc6 then objid end ) as ApproverID6,
max( case frgco when frgc7 then objid end ) as ApproverID7,
max( case frgco when frgc8 then objid end ) as ApproverID8,
max( case frgco when frgc1 then _UserDet.UserFName end ) as ApproverName1,
max( case frgco when frgc2 then _UserDet.UserFName end ) as ApproverName2,
max( case frgco when frgc3 then _UserDet.UserFName end ) as ApproverName3,
max( case frgco when frgc4 then _UserDet.UserFName end ) as ApproverName4,
max( case frgco when frgc5 then _UserDet.UserFName end ) as ApproverName5,
max( case frgco when frgc6 then _UserDet.UserFName end ) as ApproverName6,
max( case frgco when frgc7 then _UserDet.UserFName end ) as ApproverName7,
max( case frgco when frgc8 then _UserDet.UserFName end ) as ApproverName8,
substring(frgzu,1,1) as ApprovedLevel1,
substring(frgzu,2,1) as ApprovedLevel2,
substring(frgzu,3,1) as ApprovedLevel3,
substring(frgzu,4,1) as ApprovedLevel4,
substring(frgzu,5,1) as ApprovedLevel5,
substring(frgzu,6,1) as ApprovedLevel6,
substring(frgzu,7,1) as ApprovedLevel7,
substring(frgzu,8,1) as ApprovedLevel8
} group by banfn, frgzu
@AbapCatalog.sqlViewAppendName: 'ZSQ_PURREQFS_EXT'
@EndUserText.label: 'Extension for C_PurRequisitionFs'
extend view C_PurRequisitionFs with ZC_PurRequisitionFs_EXT
association [1..1] to ZCDS_PUR_REQ_APP_F as _Approver on I_Purchaserequisition.purchaserequisition = _Approver.banfn {
@EndUserText: {label: 'Approver Level 1'}
@UI.identification:{label: 'Approver Level 1', importance: #HIGH, position: 500}
@UI.lineItem:{label: 'Approver Level 1', importance: #MEDIUM, position: 500}
case when _Approver.ApprovedLevel1 = 'X'
then CONCAT(_Approver.ApproverName1, ' - Approved')
else CONCAT(_Approver.ApproverName1, ' - Pending')
end as ApproverID1,
@EndUserText: {label: 'Approver Level 2'}
@UI.identification:{label: 'Approver Level 2', importance: #HIGH, position: 600}
@UI.lineItem:{label: 'Approver Level 2', importance: #MEDIUM, position: 600}
case when _Approver.ApprovedLevel2 = 'X'
then CONCAT(_Approver.ApproverName2, ' - Approved')
else CONCAT(_Approver.ApproverName2, ' - Pending')
end as ApproverID2,
@EndUserText: {label: 'Approver Level 3'}
@UI.identification:{label: 'Approver Level 3', importance: #HIGH, position: 700}
@UI.lineItem:{label: 'Approver Level 3', importance: #MEDIUM, position: 700}
case when _Approver.ApprovedLevel3 = 'X'
then CONCAT(_Approver.ApproverName3, ' - Approved')
else CONCAT(_Approver.ApproverName3, ' - Pending')
end as ApproverID3,
@EndUserText: {label: 'Approver Level 4'}
@UI.identification:{label: 'Approver Level 4', importance: #HIGH, position: 800}
@UI.lineItem:{label: 'Approver Level 4', importance: #MEDIUM, position: 800}
case when _Approver.ApprovedLevel4 = 'X'
then CONCAT(_Approver.ApproverName4, ' - Approved')
else CONCAT(_Approver.ApproverName4, ' - Pending')
end as ApproverID4,
@EndUserText: {label: 'Approver Level 5'}
@UI.identification:{label: 'Approver Level 5', importance: #HIGH, position: 900}
@UI.lineItem:{label: 'Approver Level 5', importance: #MEDIUM, position: 900}
case when _Approver.ApprovedLevel5 = 'X'
then CONCAT(_Approver.ApproverName5, ' - Approved')
else CONCAT(_Approver.ApproverName5, ' - Pending')
end as ApproverID5,
@EndUserText: {label: 'Approver Level 6'}
@UI.identification:{label: 'Approver Level 6', importance: #HIGH, position: 1000}
@UI.lineItem:{label: 'Approver Level 6', importance: #MEDIUM, position: 1000}
case when _Approver.ApprovedLevel6 = 'X'
then CONCAT(_Approver.ApproverName6, ' - Approved')
else CONCAT(_Approver.ApproverName6, ' - Pending')
end as ApproverID6,
@EndUserText: {label: 'Approver Level 7'}
@UI.identification:{label: 'Approver Level 7', importance: #HIGH, position: 1100}
@UI.lineItem:{label: 'Approver Level 7', importance: #MEDIUM, position: 1100}
case when _Approver.ApprovedLevel7 = 'X'
then CONCAT(_Approver.ApproverName7, ' - Approved')
else CONCAT(_Approver.ApproverName7, ' - Pending')
end as ApproverID7,
@EndUserText: {label: 'Approver Level 8'}
@UI.identification:{label: 'Approver Level 8', importance: #HIGH, position: 1200}
@UI.lineItem:{label: 'Approver Level 8', importance: #MEDIUM, position: 1200}
case when _Approver.ApprovedLevel8 = 'X'
then CONCAT(_Approver.ApproverName8, ' - Approved')
else CONCAT(_Approver.ApproverName8, ' - Pending')
end as ApproverID8
}
Calle Eloy Gonzalo, 27
Madrid, Madrid.
Código Postal 28010
Paseo de la Reforma 26
Colonia Juárez, Cuauhtémoc
Ciudad de México 06600
Real Cariari
Autopista General Cañas,
San José, SJ 40104
Av. Jorge Basadre 349
San Isidro
Lima, LIM 15073