You are on page 1of 19

OLAF OCM FLATTEN MODEL (aka “datawarehouse”)

Solutions and Examples

Cases and Case stages............................................................................................................................2


Cases and Staff.......................................................................................................................................2
Support requests....................................................................................................................................2
Activities of DISPATCHER INVESTIGATION..............................................................................................3
Activities and Analysis............................................................................................................................4
Monitoring activities started in Jan 2020...............................................................................................5
Synthesis of recommendations (v_synth_recommendations family of view)........................................6
Monthly activities (v_activities_upto_1stofmonth)...............................................................................8
Contact information of documents of some Cases (in order to find document sent to specific external
entity).....................................................................................................................................................9
Staffing of AN/LC Cases on ASR and LA activities...................................................................................9
Activities up to the 1st day of current month........................................................................................10
Case staffing with UNIT, Phase, Status of the Case and active statuses of the Staff.............................13
ASR and LA requests per Case with Staff information..........................................................................13
Synthesis of Recommendations...........................................................................................................14

1/19 13 JANUARY 2022


Cases and Case stages
In BO_MVIEW schema, the classical pattern is based on JOINing bo_case and bo_case_stage on the
caseid column and filtering on the stage_name, example:

select … from bo_case a, bo_case_stage b where a.caseid = b.caseid and b.stage_name in (…)
or – better - in ANSI SQL syntax:

select … from bo_case a join bo_case_stage b on a.caseid = b.caseid where b.stage_name in


(…)

The equivalent in DW will be written:

select … from m_case_stages join m_olaf_cases on ocas_oid = cast_ocas_oid and


ocas_casetype_lib in (select * from v_case_prefixes) where cast_stagename_lib in (…)

The filtering on the Case type is required because DW’s m_olaf_cases includes the ones with case
type MISSION.

The BO version will return the results in <4 secs while - despite this required additional filtering - the
DW version returns the same set in < 0.1 secs ( stage_name in (‘INVESTIGATION’,
‘COORDINATION’) as an example).

Cases and Staff


select
ocas_casenumber_lib as case_number,
oclc_unitcode_lib as unit, oclc_stagename_lib as phase,
ocas_status_lib || '/' || ocas_substatus_lib as status,
casf_staff_lib as person_name,
casf_role_lib as role,
ostf_isactive_swi, ostf_ocmactive_swi
from m_olaf_cases
join v_case_lifecycles on oclc_ocas_oid = ocas_oid and oclc_islaststage_swi = 1
join v_case_active_staffs on casf_ocas_oid = ocas_oid
join m_olaf_staffs on casf_ostf_oid = ostf_oid
where
ocas_casetype_lib in (select * from v_case_prefixes)
and oclc_stagename_lib in ( 'SELECTION', 'INVESTIGATION', 'MONITORING', 'COORDINATION' )
order by to_number(substr(ocas_casenumber_lib,4,4)),
to_number(substr(ocas_casenumber_lib,9,4)), casf_role_lib, casf_staff_lib
;

Support requests
select * from (
select cc.ocas_casenumber_lib as case_number,
mc.ocas_casenumber_lib as linked_case_number,
oclc_unitcode_lib as unit, oclc_stagename_lib as phase,
cc.ocas_status_lib || '/' || cc.ocas_substatus_lib as status,
casf_staff_lib as person_name,
casf_role_lib as role,
ostf_isactive_swi, ostf_ocmactive_swi
from v_an_lc_cases cc
join v_case_lifecycles on oclc_ocas_oid = ocas_oid and oclc_islaststage_swi = 1

2/19 13 JANUARY 2022


join v_case_active_staffs on casf_ocas_oid = ocas_oid
join m_olaf_staffs on casf_ostf_oid = ostf_oid
join m_case_activities ca on cact_ocas_oid = ocas_oid
join m_case_child_relactivities on ccrl_cact_oid = ca.cact_oid
join m_case_activities pa on pa.cact_oid = ccrl_parentcact_oid
join m_olaf_cases mc on mc.ocas_oid = pa.cact_ocas_oid
where
ca.cact_activitytype_lib in ('ASR', 'LA')

union all

select cc.ocas_casenumber_lib as case_number,


'*** external request ***' as linked_case_number,
oclc_unitcode_lib as unit, oclc_stagename_lib as phase,
cc.ocas_status_lib || '/' || cc.ocas_substatus_lib as status,
casf_staff_lib as person_name,
casf_role_lib as role,
ostf_isactive_swi, ostf_ocmactive_swi
from v_an_lc_cases cc
join v_case_lifecycles on oclc_ocas_oid = ocas_oid and oclc_islaststage_swi = 1
join v_case_active_staffs on casf_ocas_oid = ocas_oid
join m_olaf_staffs on casf_ostf_oid = ostf_oid
join m_case_activities ca on cact_ocas_oid = ocas_oid

where
ca.cact_activitytype_lib in ('ASR', 'LA')
and not exists(select 1 from m_case_child_relactivities where ccrl_cact_oid =
ca.cact_oid)
)
order by to_number(substr(case_number,4,4)), to_number(substr(case_number,9,4)),
substr(case_number,1,2), role, person_name
;

Activities of DISPATCHER INVESTIGATION


with activities as (
select ma.cact_oid, ma.cact_ocas_oid, cccx_contactname_lib,
ma.cact_activitytype_lib, ma.cact_activitysubtype_lib,
count(distinct cccx_contactname_lib) as ncontacts
from
m_activity2performers
join m_case_activities ca on ca.cact_oid = acpe_cact_oid
join m_case_parent_activities on cacp_childcact_oid = ca.cact_oid
join m_case_activities ma on ma.cact_oid = cacp_cact_oid
join m_casecontactctx on cccx_oid = acpe_cccx_oid
where sysdate < ma.cact_end_dat
and ca.cact_status_lib not in (
'CLOSED',
'REJEC',
'REJECT_OPI',
'CANCELLED',
'REJECTED',
'CANCELL',
'CANCELED',
'COMPLETED',
'ANNULLED'
)
and ma.cact_status_lib in (
'ONGOING', 'OPEN', 'TODO'
)
group by ma.cact_oid, ma.cact_ocas_oid, cccx_contactname_lib,
ma.cact_activitytype_lib, ma.cact_activitysubtype_lib
)
, results as (

3/19 13 JANUARY 2022


select
casf_staff_lib as person_name,
cact_oid as activity_id,
cact_activitytype_lib as activity_type,
ocas_oid as case_id,
ocas_casenumber_lib as case_number,
oclc_unitcode_lib as unit,
ncontacts
from m_olaf_cases
join v_case_lifecycles on oclc_ocas_oid = ocas_oid and oclc_islaststage_swi = 1
join v_case_active_staffs on casf_ocas_oid = ocas_oid
join m_olaf_staffs on casf_ostf_oid = ostf_oid
join activities on ocas_oid = cact_ocas_oid and casf_staff_lib = cccx_contactname_lib
where
ocas_casetype_lib in (select * from v_case_prefixes)
and casf_role_lib in( 'DISPATCHER INVESTIGATION' )
and oclc_stagename_lib in ( 'INVESTIGATION', 'MONITORING', 'COORDINATION' )
)
select * from results
;

Activities and Analysis


In BO_MVIEW schema, we offen JOIN bo_act_analysis and bo_case_act_link on the activityid
column:

select … from bo_act_analysis a join bo_case_act_link b on a.activityid = b.activityid

The equivalent in DW will be written:

select … from v_act_analysis join m_all_caseactivities on acan_cact_oid = acac_cact_oid

4/19 13 JANUARY 2022


Monitoring activities started in Jan 2020
Example showing how to avoid using w_reporting_stages_wus when the conditions on the Case
stage are well defined and covering only a small part of the dataset returned by this complex view.

select mong_oid, mong_activity_oid, mong_status_lib,


reco_amounttoberecovered_num,
mona_amounttoberecovered_num, mona_amounttobeprevented_num, mona_amendment_dat,
cact_activitytype_lib, cact_start_rpt_dat,
rstg_unitcode_lib
from bo_monitorings
left join bo_monitoringamounts on mong_oid = mona_monitoring_oid
join bo_case_activities on cact_oid = mong_activity_oid
join bo_rs_monitoring on rstg_case_oid = cact_case_oid
join bo_cases on ocas_case_oid = oclc_case_oid
join bo_monrecommendations on more_monitoring_oid = mong_oid
join bo_recommendations on more_recommendation_oid = reco_oid
where
cact_activitytype_lib in ('FIN')
and cact_start_rpt_dat between to_date('01/01/2020','dd/mm/yyyy') and to_date('31/01/2020
23:59:59','dd/mm/yyyy hh24:mi:ss')
;

It could be attractive to go to v_reporting_stages_wus to select the MONITORING, however


MONITORING life cycles are a small subset of the whole life cycles and w_reporting_stages_wus
just define them as being last_tage =1, stage name = ‘MONITORING’ and sub status <> FINALIZED,
and these are the conditions in bo_rs_monitoring.

5/19 13 JANUARY 2022


Synthesis of recommendations (v_synth_recommendations family of view)

In OCM, the recommendations are linked to the monitoring information from which is then possible
to get the related contacts and the documents and their keywords, and being an object in the Case,
it’s possible to go to the Case life cycle.

As of July 2020, two different models exist in OCM, the oldest one implying that the ROLE of the
associated contact is not filled in. These recommendations will have the ‘TO BE UPDATED (old
model)’ as role. In the new model, only OFFICIAL CONTACT are returned.

The mapping of document titles has been specified as: by default the document’s associated
KEYWORD is used, in case it’s not defined then: all titles containing the RECOMMENDATION word are
mapped as RECOMMENDATION except the RECOMMENDATATION TRANSMISSION which is mapped
as a TRANSMISSION LETTER as all other titles. It’s returned as SUBJECT in the lowest layer of the
query.

In case new titles are defined the view should be updated as per default unknown titles are mapped
to NULL.

From the technical point of view, in order to identify multiple usage of same document, the RID and
the recommendation date must be concatenated with the SUBJECT.

The version _WSD of the view (With Support Document) adds LEFT JOINs on the MONITORING
AMOUNTs.

The v_amend_recommendations view is based on the v_synth_recommendations_wsd and adds the


amendment documents ordered by reference and the amended amounts and date.

6/19 13 JANUARY 2022


The v_dq_synth_recommendations (available only in the DW schema, not the Read-only schema)
filters out the lowest level of queries in v_synth_recommendation on criteria: either the subject or
the contact is not defined.

The v_synth_reco_report_units adds information about the UNIT and the LEAD INVESTIGATOR to the
v_synth_recommendations_wsd view but also outouts the situations where the LEAD INVESTIGATOR
is not defined while the STAGE is post-SELECTION.

7/19 13 JANUARY 2022


Monthly activities (v_activities_upto_1stofmonth)
This view is particular in different aspects:

 restricts the selection of results to activities started before the 1 st of the current month: this
means it will output the same results1 for the whole duration of the month;
 uses both PIVOT (and even PIVOT over PIVOT) and CUBE operations making difficult to
reproduce its behaviour with standard reporting tools.

Technically, it’s selecting the different activities of interest in different CTE: the INTERVIEW and
DIGITAL FORENSIC are selected together because they don’t related to other information than Case
and activities, ON THE SPOT CHECK and INSPECTION OF PREMISES have their own CTE to select their
custom information.

The variant v_activities_app_upto_1stofmonth looks for APPROVED activities instead of COMPLETE


ones.

Note that the CTE are also available as separated views:`

 v_act_inspections
 v_act_onthespotchecks
 v_act_digitfas
 v_act_interviews

If you need to re-calculate the report at a specific date, the function dyn_rpt_activity_ray(i_rpt_date
IN DATE, i_trunc IN VARCHAR2) RETURN t_rpt_activity_rays will give you the expected result.

The i_trunc parameter is the truncation string used to TRUNC the date.

1
not taking into account independent data quality actions

8/19 13 JANUARY 2022


Contact information of documents of some Cases (in order to find document sent
to specific external entity)
In BO or OCM schema:
select distinct doc_r.r_object_id as doc_oid, doc.object_name,
od.format, od.expedition_date,
ccx.r_object_id, ccx.object_name as ccx_name, ccx.cm_id, ccx.cm_id_1,
cmc.object_name as person_name, cmc.source as person_source, cmc.contact_type as
person_type, cmc.active as person_active,
cmc_org.object_name as org_name, cmc_org.source as org_source, cmc_org.contact_type as
org_type, cmc_org.active as org_active
from ocmprd.omdm_olaf_document_data_sp dd
left join ocmprd.omdm_outgoing_document od on od.r_object_id = dd.r_object_id
join ocmprd.omdm_olaf_document_data__sp ddr on ddr.parent_id = dd.r_object_id
join ocmprd.omdm_olaf_document_rp doc_r on doc_r.r_object_id = ddr.child_id
join ocmprd.omdm_olaf_document_sp doc on doc_r.r_object_id = doc.r_object_id
join ocmprd.omdm_doc_case_cont_ctxt_sp dccx on dccx.parent_id = doc.r_object_id
join ocmprd.omdm_case_contact_contex_sp ccx on ccx.r_object_id = dccx.child_id
join ocmprd.cm_contact_sp cmc on cmc.r_object_id = ccx.cm_id
left join ocmprd.cm_contact_sp cmc_org on cmc_org.r_object_id = ccx.cm_id_1
where doc_r.i_ancestor_id in (…)
and (doc.acl_name <> 'ocm_acl_deleted')

In DW:
select distinct doca_docu_oid, docu_name_lib,
od.docu_format_lib, od.docu_expedition_dat,
cccx_oid, m_casecontactctx.cccx_contactname_lib, cccx_cont_oid, cccx_org_cont_oid,
pers.cont_name_lib as person_name, pers.cont_source_lib as person_source,
pers.cont_type_lib as person_type, pers.cont_active_swi as person_active,
org.cont_name_lib as org_name, org.cont_source_lib as org_source, org.cont_type_lib as
org_type, org.cont_active_swi as org_active
from m_document2cases
left join m_outgoingdocs od on od.docu_oid = doca_docu_oid
join m_documents doc on doc.docu_oid = doca_docu_oid
join m_document2casecontactctx on dccx_docu_oid = doca_docu_oid
join m_casecontactctx on cccx_oid = dccx_cccx_oid
join m_contacts pers on pers.cont_oid = cccx_cont_oid
left join m_contacts org on org.cont_oid = cccx_org_cont_oid
where doca_ocas_oid in (

)
;
Benefits:

 number of JOIN operations is reduced and easier to write thanks to naming conventions,
 no need to check for acl_name <> ocm_acl_deleted (and so no risk to forget to)

Staffing of AN/LC Cases on ASR and LA activities

select * from (
select cc.ocas_casenumber_lib as case_number,
mc.ocas_casenumber_lib as linked_case_number,
oclc_unitcode_lib as unit, oclc_stagename_lib as phase,
cc.ocas_status_lib || '/' || cc.ocas_substatus_lib as status,
casf_staff_lib as person_name,
casf_role_lib as role,
ostf_isactive_swi, ostf_ocmactive_swi
from v_an_lc_cases cc
join v_case_lifecycles on oclc_ocas_oid = ocas_oid and oclc_islaststage_swi = 1
join v_case_active_staffs on casf_ocas_oid = ocas_oid

9/19 13 JANUARY 2022


join m_olaf_staffs on casf_ostf_oid = ostf_oid
join m_case_activities ca on cact_ocas_oid = ocas_oid
join m_case_child_relactivities on ccrl_cact_oid = ca.cact_oid
join m_case_activities pa on pa.cact_oid = ccrl_parentcact_oid
join m_olaf_cases mc on mc.ocas_oid = pa.cact_ocas_oid
where
ca.cact_activitytype_lib in ('ASR', 'LA')

union all

select cc.ocas_casenumber_lib as case_number,


'*** external request ***' as linked_case_number,
oclc_unitcode_lib as unit, oclc_stagename_lib as phase,
cc.ocas_status_lib || '/' || cc.ocas_substatus_lib as status,
casf_staff_lib as person_name,
casf_role_lib as role,
ostf_isactive_swi, ostf_ocmactive_swi
from v_an_lc_cases cc
join v_case_lifecycles on oclc_ocas_oid = ocas_oid and oclc_islaststage_swi = 1
join v_case_active_staffs on casf_ocas_oid = ocas_oid
join m_olaf_staffs on casf_ostf_oid = ostf_oid
join m_case_activities ca on cact_ocas_oid = ocas_oid

where
ca.cact_activitytype_lib in ('ASR', 'LA')
and not exists(select 1 from m_case_child_relactivities where ccrl_cact_oid =
ca.cact_oid)
)
order by to_number(substr(case_number,4,4)), to_number(substr(case_number,9,4)),
substr(case_number,1,2), role, person_name
;

Activities up to the 1st day of current month


Despite the fact that the DW schema flatten the OCM model, some queries will remain difficult to
generate with reporting tools like SAP/BO or Tableau because of the level of imbrications they
require and the access to specific SQL features like the PIVOT operation:

with data_intv_digitfa as (
select d.*,
null as combined_ostc, null as combined_insp, lc.oclc_unitcode_lib as unit_code
from (
select act.cact_ocas_oid as case_oid, ocas_casenumber_lib as case_number,
act.cact_activitytype_lib as activity_type,
extract(year from reqact.cact_end_rpt_dat) as activity_year
from m_case_activities act
join m_olaf_cases on ocas_oid = cact_ocas_oid
join m_case_parent_activities on cacp_cact_oid = act.cact_oid
join m_case_activities reqact on reqact.cact_oid = cacp_childcact_oid and
reqact.cact_activitytype_lib = 'REQ' and reqact.cact_status_lib ='APPROVED'
where
ocas_casetype_lib in (select * from v_case_prefixes)
and (act.cact_activitytype_lib, act.cact_activitysubtype_lib) in (('INTV', ' '),
('DIGIT_FA', ' ') )
and (act.cact_status_lib not in ('CANCELLED', 'CANCELL', 'REJECTED'))
and (act.cact_start_rpt_dat < (select trunc(sysdate,'MM') from dual))
) d
join v_case_lifecycles lc on lc.oclc_ocas_oid = d.case_oid and lc.oclc_islaststage_swi =
1
)
,data_otsc as (
select d.*, lc.oclc_unitcode_lib as unit_code
from (

10/19 13 JANUARY 2022


select act.cact_ocas_oid as case_oid, ocas_casenumber_lib as case_number,
act.cact_activitytype_lib as activity_type,
extract(year from reqact.cact_end_rpt_dat) as activity_year,
otsc_combined_swi as combined_ostc, null as combined_insp
from m_case_activities act
join m_olaf_cases on ocas_oid = cact_ocas_oid
join m_case_parent_activities on cacp_cact_oid = act.cact_oid
join m_case_activities reqact on reqact.cact_oid = cacp_childcact_oid and
reqact.cact_activitytype_lib = 'REQ' and reqact.cact_status_lib ='APPROVED'
join m_onthespotcheck2activities on osac_cact_oid = act.cact_oid
join m_onthespotchecks on osac_otsc_oid = otsc_oid
where
ocas_casetype_lib in (select * from v_case_prefixes)
and (act.cact_activitytype_lib, act.cact_activitysubtype_lib) in (('OTSC', ' '))
and (act.cact_status_lib not in ('CANCELLED', 'CANCELL', 'REJECTED'))
and (act.cact_start_rpt_dat < (select trunc(sysdate,'MM') from dual))
) d
join v_case_lifecycles lc on lc.oclc_ocas_oid= d.case_oid and lc.oclc_islaststage_swi = 1
)
,data_insp as (
select d.*, lc.oclc_unitcode_lib as unit_code
from (
select act.cact_ocas_oid as case_oid, ocas_casenumber_lib as case_number,
act.cact_activitytype_lib as activity_type,
extract(year from reqact.cact_end_rpt_dat) as activity_year,
null as combined_ostc, insp_combined_swi as combined_insp
from m_case_activities act
join m_olaf_cases on ocas_oid = cact_ocas_oid
join m_case_parent_activities on cacp_cact_oid = act.cact_oid
join m_case_activities reqact on reqact.cact_oid = cacp_childcact_oid and
reqact.cact_activitytype_lib = 'REQ' and reqact.cact_status_lib ='APPROVED'
join m_inspofpremises2activities on inac_cact_oid = act.cact_oid
join m_inspectionofpremises on inac_insp_oid = insp_oid
where
ocas_casetype_lib in (select * from v_case_prefixes)
and (act.cact_activitytype_lib, act.cact_activitysubtype_lib) in (('INSP', ' '))
and (act.cact_status_lib not in ('CANCELLED', 'CANCELL', 'REJECTED'))
and (act.cact_start_rpt_dat < (select trunc(sysdate,'MM') from dual))
) d
join v_case_lifecycles lc on lc.oclc_ocas_oid= d.case_oid and lc.oclc_islaststage_swi = 1
)
, stats_intv_digitfa as (
select case_number, unit_code, activity_year,
sum(interview) as ninterviews,
sum(digital_forensic) as ndigitfastandalones
from (
select * from data_intv_digitfa
pivot (
count(*) for activity_type in ( 'INTV' as interview, 'OTSC' as on_the_spot_check,
'DIGIT_FA' as digital_forensic, 'INSP' as inspection )
)
)
group by case_number, unit_code, activity_year
)
, stats_otsc as (
select * from (
select case_number, unit_code, activity_year,
combined_ostc as combined_flag,
sum(on_the_spot_check) as n
from (
select * from (
select * from data_otsc
)
pivot (

11/19 13 JANUARY 2022


count(*) for activity_type in ( 'INTV' as interview, 'OTSC' as on_the_spot_check,
'DIGIT_FA' as digital_forensic, 'INSP' as inspection )
)
)
group by case_number, unit_code, activity_year, combined_ostc
)
pivot (
max(n) for combined_flag in (0 as onthespotcheck_standalone,1 as
onthespotcheck_combined)
)
)
, stats_insp as (
select * from (
select case_number, unit_code, activity_year,
combined_insp as combined_flag,
sum(inspection) as n
from (
select * from (
select * from data_insp
)
pivot (
count(*) for activity_type in ( 'INTV' as interview, 'OTSC' as on_the_spot_check,
'DIGIT_FA' as digital_forensic, 'INSP' as inspection )
)
)
group by case_number, unit_code, activity_year, combined_insp
)
pivot (
max(n) for combined_flag in (0 as inspection_standalone,1 as inspection_combined)
)
)
select
decode( grouping_id, 2, '| All Cases for Year and Unit', 3, '|| All Cases and Years for
Unit', case_number) as case_number,
decode( grouping_id, 1, '| All Years for Case', 3, '----', to_char(activity_year) ) as
activity_year,
unit_code, ninterviews, ndigitfastandalones, onthespotcheck_standalone,
onthespotcheck_combined,
inspection_standalone, inspection_combined,
grouping_id
from (
select case_number, activity_year, decode(unit_code,'SIT - Special Investigation
Team','SIT',unit_code) as unit_code,
sum(ninterviews) as ninterviews,
sum(ndigitfastandalones) as ndigitfastandalones,
sum(onthespotcheck_standalone) as onthespotcheck_standalone,
sum(onthespotcheck_combined) as onthespotcheck_combined,
sum(inspection_standalone) as inspection_standalone,
sum(inspection_combined) as inspection_combined,
grouping_id(case_number, activity_year) as grouping_id
from (
select s.case_number, s.activity_year, s.unit_code, s.ninterviews, s.ndigitfastandalones,
0 as onthespotcheck_standalone,
0 as onthespotcheck_combined,
0 as inspection_standalone,
0 as inspection_combined
from stats_intv_digitfa s
union all
select s.case_number, s.activity_year, s.unit_code,
0 as ninterviews,
0 as ndigitfastandalones,
nvl(s.onthespotcheck_standalone,0) as onthespotcheck_standalone,
nvl(s.onthespotcheck_combined,0) as onthespotcheck_combined,
0 as inspection_standalone,
0 as inspection_combined

12/19 13 JANUARY 2022


from stats_otsc s
union all
select s.case_number, s.activity_year, s.unit_code,
0 as ninterviews,
0 as ndigitfastandalones,
0 as onthespotcheck_standalone,
0 as onthespotcheck_combined,
nvl(s.inspection_standalone,0) as inspection_standalone,
nvl(s.inspection_combined,0) as inspection_combined
from stats_insp s
)
group by cube(case_number, activity_year), unit_code
)
order by case_number, activity_year, unit_code, grouping_id
;

Case staffing with UNIT, Phase, Status of the Case and active statuses of the Staff

select
ocas_casenumber_lib as case_number,
oclc_unitcode_lib as unit, oclc_stagename_lib as phase,
ocas_status_lib || ‘/’ ocas_substatus_lib as status,
casf_staff_lib as person_name,
casf_role_lib as role,
ostf_isactive_swi, ostf_ocmactive_swi
from
m_olaf_cases
join v_case_lifecycles on oclc_ocas_oid = ocas_oid
join v_case_active_staffs on casf_ocas_oid = ocas_oid
join m_olaf_staffs on casf_ostf_oid = ostf_oid
where
ocas_casetype_lib in (select * from v_case_prefixes)
and oclc_stagename_lib in ( ‘SELECTION’, ‘INVESTIGATION’, ‘MONITORING’, ‘COORDINATION’)
order by to_number(ocas_casenumber_lib,4,4)), to_number(substr(ocas_casenumber_lib,9,4)),
casf_role_lib, casf_staff_lib
;

ASR and LA requests per Case with Staff information


Select Case activities of type ASR with status COMPLETED or ONGOING (excluding CANCELLED ones)
of which a related activity is linked to a REQUEST.

13/19 13 JANUARY 2022


Synthesis of Recommendations
The synthesis of recommendations related to monitoring activities is one of the most complex view
in the DW schema.

This is due to cumulating factors, each of one adding a level of complexity:

1. the complexity of the needs themselves (requiring to PIVOT the intermediary results on an
criteria calculated from different sources, …);
2. the evolution of the data model and the coexistence of different representation (finalisation
by activity or by document with different activity names and statuses according to the type of
the recommendation (financial or judicial), recommendation document linked to the
recommendation object or the related activity, complex assembly of the different sources of
information while avoiding duplicated rows in the results, …);
3. lack of information in pre-OCM data (keyword to identify the nature of the document, …)
requiring fall back technique to find the information (scanning the document title,…);
4. data quality issues due to different factors: user errors or misuse of OCM that could not
further fixed because concerning registered documents (usage of several time the same
recommendation or recommendation document in different Cases, …),
5. technical limitation of the version of ORACLE we are using (the lack of DISTINCT keyword in
LISTAGG, available only from version 19c, …)
6. lack of consistency of name of activities and status/substatus between the different kind of
recommendations

WITH doc_via_reco AS (
SELECT
reco_oid, caob_ocas_oid as ocas_oid,
mong_oid, mong_cact_oid AS mong_mainactivity_oid,
reco_recommendationtype_lib, reco_objectname_lib AS reco_name_lib,
reco_reference_lib, reco_amounttoberecovered_num, reco_amounttobeprevented_num,
mong_status_lib as mong_recommendationoutcome_lib,
doc.docu_registration_lib AS reco_rid, doc.docu_registration_dat as reco_date,
doc.docu_oid, doc.docu_registration_lib, doc.docu_registration_dat,
docu_title_lib as title, doc.docu_savenumber_lib as save_nr,
'RECOMMENDATION' as subject
FROM m_recommendations r
JOIN m_monitoring2recommendations on more_reco_oid = reco_oid
JOIN m_monitorings mon ON more_mong_oid = mong_oid
JOIN m_case_objects on caob_object_oid = reco_oid
JOIN m_doc2recommendations ON docr_reco_oid = r.reco_oid
JOIN m_documents doc on doc.docu_oid = docr_docu_oid
AND INSTR(docu_title_lib, 'ANNULLED DOCUMENT') = 0
),
doc_with_act AS (
SELECT reco_oid, caob_ocas_oid as ocas_oid, mong_oid,
mong_cact_oid AS mong_mainactivity_oid,
reco_recommendationtype_lib, reco_objectname_lib AS reco_name_lib,
reco_reference_lib, reco_amounttoberecovered_num,
reco_amounttobeprevented_num, mong_status_lib as mong_recommendationoutcome_lib,
doc.docu_registration_lib AS reco_rid, doc.docu_registration_dat as reco_date,
doc.docu_oid, doc.docu_registration_lib, doc.docu_registration_dat,
docu_title_lib as title, docu_savenumber_lib as save_nr,
NVL( actdoc_r.dock_keyword_lib,
DECODE (SUBSTR(UPPER(docu_title_lib),1,18),
'ADMINISTRATIVE REC', 'RECOMMENDATION',
'TRANSMISSION LETTE', 'TRANSMISSION LETTER',
'TRANSMISSION NOTE ', 'TRANSMISSION LETTER',

14/19 13 JANUARY 2022


'FINANCIAL RECOMMEN', 'RECOMMENDATION',
'DISCIPLINARY RECOM', 'RECOMMENDATION',
'JUDICIAL RECOMMEND', 'RECOMMENDATION',
'RECOMMENDATIONS TO', 'RECOMMENDATION',
'RECOMMENDATION TO ', 'RECOMMENDATION',
'RECOMMENDATION TRA', 'TRANSMISSION LETTER',
NULL
)
) AS subject
FROM m_recommendations r
JOIN m_monitoring2recommendations on more_reco_oid = reco_oid
JOIN m_monitorings mon ON more_mong_oid = mong_oid
JOIN m_case_objects on caob_object_oid = reco_oid
LEFT JOIN m_doc2activities on doac_cact_oid = mong_cact_oid
LEFT JOIN m_documents doc on doc.docu_oid = doac_docu_oid
AND INSTR(docu_title_lib, 'ANNULLED DOCUMENT') = 0
LEFT JOIN m_dockeywords actdoc_r ON doac_docu_oid = actdoc_r.dock_docu_oid
),
fin_by_activity AS(
SELECT reco_oid, caob_ocas_oid as ocas_oid, mong_oid,
mong_cact_oid AS mong_mainactivity_oid, reco_recommendationtype_lib,
reco_objectname_lib AS reco_name_lib, reco_reference_lib,
reco_amounttoberecovered_num, reco_amounttobeprevented_num,
mong_status_lib as mong_recommendationoutcome_lib,
'by activity' AS reco_rid,
finact.cact_end_rpt_dat as reco_date,
NULL, 'by activity' AS docu_registration_lib,
finact.cact_end_rpt_dat AS docu_registration_dat,
finact.cact_description_lib as title,
NULL as save_nr,
'FINALISATION' AS subject
FROM m_recommendations r
JOIN m_monitoring2recommendations on more_reco_oid = reco_oid
JOIN m_monitorings mon ON more_mong_oid = mong_oid
JOIN m_case_objects on caob_object_oid = reco_oid
JOIN (
SELECT act.cact_oid, act.cact_end_rpt_dat, act.cact_description_lib,
tsk.cact_activitysubtype_lib FROM m_case_activities act
JOIN m_case_parent_activities ON act.cact_oid = cacp_cact_oid
JOIN m_case_activities tsk ON tsk.cact_oid = cacp_childcact_oid AND
(
(tsk.cact_activitytype_lib = 'MON' AND
tsk.cact_activitysubtype_lib = 'END' AND tsk.cact_status_lib = 'APPROVED')
OR
(tsk.cact_activitytype_lib = 'MON' AND
tsk.cact_activitysubtype_lib = 'JUDFINAL' AND tsk.cact_status_lib = 'CLOSED')
)
) finact ON mong_cact_oid = cact_oid
AND (
(r.reco_recommendationtype_lib = 'FINANCIAL' AND finact.cact_activitysubtype_lib
= 'END')
OR
(r.reco_recommendationtype_lib = 'JUDICIAL' AND finact.cact_activitysubtype_lib =
'JUDFINAL')
/*
TODO OR to be added if support for new activity is extended
*/
)
),
synth_reco_doc AS (
SELECT * FROM doc_via_reco
UNION
SELECT * FROM doc_with_act dva WHERE subject IN (
'FINALISATION', 'RECOMMENDATION', 'TRANSMISSION LETTER'
)

15/19 13 JANUARY 2022


AND NOT EXISTS(
SELECT 1 FROM doc_via_reco dvr WHERE dvr.reco_oid = dva.reco_oid AND dva.subject =
'RECOMMENDATION')
UNION
SELECT * FROM fin_by_activity fba
WHERE NOT EXISTS(
SELECT 1 FROM doc_via_reco dvr WHERE dvr.reco_oid = fba.reco_oid AND dvr.subject =
'FINALISATION')
AND NOT EXISTS(
SELECT 1 FROM doc_with_act dva WHERE dva.reco_oid = fba.reco_oid AND dva.subject =
'FINALISATION')
)
SELECT
reco_oid as srec_reco_oid,
mong_oid as srec_mong_oid,
ocas_oid as srec_ocas_oid,
ocas_casenumber_lib as srec_casenumber_lib,
oclc_stagename_lib as srec_stagename_lib,
reco_reference_lib as srec_reference_lib,
reco_amounttoberecovered_num as srec_amounttoberecovered_num,
reco_amounttobeprevented_num as srec_amounttobeprevented_num
reco_recommendationtype_lib as srec_recommendationtype_lib,
reco_rid_lib as srec_rid_lib,
reco_registrationdate_lib as srec_registrationdate_lib,
CASE WHEN INSTR(reco_registrationdate_lib, ',') = 0 THEN
TO_DATE(reco_registrationdate_lib, 'DD/MM/YYYY') END AS srec_registration_dat,
docu_finalisationrid_lib as srec_finalisationrid_lib,
docu_finalisationdate_lib as srec_finalisationdate_lib,
CASE WHEN INSTR(docu_finalisationdate_lib, ',') = 0 THEN
TO_DATE(docu_finalisationdate_lib, 'DD/MM/YYYY') END AS srec_finalisation_dat,
docu_transmissionrid_lib as srec_transmissionrid_lib,
docu_transmissiondate_lib as srec_transmissiondate_lib,
CASE WHEN INSTR(docu_transmissiondate_lib, ',') = 0 THEN
TO_DATE(docu_transmissiondate_lib, 'DD/MM/YYYY') END AS srec_transmissionletter_dat,
cont_recipient_lib as srec_recipient_lib,
cont_recipienttype_lib as srec_recipienttype_lib,
cont_recipientacronym_lib as srec_recipientacronym_lib,
cont_recipientcountry_lib as srec_recipientcountry_lib,
mong_recommendationoutcome_lib as srec_recommendationoutcome_lib,
la.appr_approval_dat as srec_approval_dat
FROM (
SELECT
reco_oid,
ocas_oid,
mong_mainactivity_oid,
mong_oid,
ocas_casenumber_lib,
oclc_stagename_lib,
reco_reference_lib,
reco_amounttoberecovered_num,
reco_amounttobeprevented_num,
mong_recommendationoutcome_lib,
reco_recommendationtype_lib,
recommendation_rid as reco_rid_lib,
recommendation_dat_s as reco_registrationdate_lib,
finalisation_rid as docu_finalisationrid_lib,
finalisation_dat_s as docu_finalisationdate_lib,
transmission_letter_rid as docu_transmissionrid_lib,
transmission_letter_dat_s as docu_transmissiondate_lib,
contact_name AS cont_recipient_lib,
contact_type AS cont_recipienttype_lib,
org_acronym AS cont_recipientacronym_lib,
country_name as cont_recipientcountry_lib
FROM (
SELECT

16/19 13 JANUARY 2022


ocas_oid,
ocas_casenumber_lib,
oclc_stagename_lib,
reco_name_lib,
reco_oid,
mong_oid,
mong_mainactivity_oid,
reco_reference_lib,
reco_amounttoberecovered_num,
reco_amounttobeprevented_num,
mong_recommendationoutcome_lib,
reco_recommendationtype_lib,
reco_rid,
reco_date,
contact_name,
contact_type,
contact_role,
country_name,
org_acronym,
subject
FROM (
SELECT
reco_oid,
ocas_oid,
mong_oid,
mong_mainactivity_oid,
reco_recommendationtype_lib,
oclc_casenumber_lib AS ocas_casenumber_lib,
reco_name_lib,
reco_reference_lib,
reco_amounttoberecovered_num,
reco_amounttobeprevented_num,
mong_recommendationoutcome_lib,
reco_rid AS debug_reco_rid,
DECODE( LAG(reco_rid /**/ || ':' || subject /**/) OVER(PARTITION BY
reco_reference_lib, reco_rid, mong_mainactivity_oid, subject
ORDER BY subject, reco_rid NULLS LAST),
reco_rid /**/ || ':' || subject /**/, NULL, reco_rid) AS reco_rid,
TRUNC(TO_DATE(TO_CHAR(FROM_TZ(
CAST(NULLIF(
DECODE( LAG(reco_date /**/ || ':' || subject /**/) OVER(PARTITION BY
reco_reference_lib, reco_rid, mong_mainactivity_oid, subject
ORDER BY subject, reco_rid NULLS LAST), reco_date /**/ || ':' ||
subject /**/, TO_DATE(NULL), reco_date)
, TO_DATE('01010001','DDMMYYYY')) AS TIMESTAMP), 'GMT') AT TIME ZONE
'Europe/Brussels'
, 'DD/MM/YYYY HH24:MI:SS'), 'DD/MM/YYYY HH24:MI:SS'))
AS reco_date,
contact_name, contact_type,
country_name, org_acronym,
subject,
oclc_stagename_lib,
contact_role
FROM
(
SELECT reco_oid, mong_oid, mong_mainactivity_oid, ocas_oid,
reco_recommendationtype_lib, oclc_casenumber_lib,
reco_name_lib, reco_reference_lib, reco_amounttoberecovered_num,
reco_amounttobeprevented_num,
mong_recommendationoutcome_lib, reco_rid, reco_date,
cont_name_lib AS contact_name,
cont_type_lib AS contact_type,
cont_countryname_lib as country_name,
NVL(cont_acronym_lib,'ACRONYM NOT FOUND') AS org_acronym,
title, save_nr, oclc_stagename_lib,

17/19 13 JANUARY 2022


NVL(mocc_role_lib,'* TO BE UPDATED (old model) *') AS contact_role,
subject
FROM synth_reco_doc
JOIN v_case_lifecycles on oclc_ocas_oid = ocas_oid and oclc_islaststage_swi = 1
JOIN m_monitoring2cccx on mocc_mong_oid = mong_oid
JOIN m_casecontactctx ccc ON cccx_oid = mocc_cccx_oid
JOIN m_contacts on cont_oid = cccx_orgorpers_cont_oid
WHERE (mocc_role_lib IS NULL OR mocc_role_lib = 'OFFICIAL CONTACT')
AND (oclc_casetype_lib in (SELECT * FROM v_case_prefixes))
)
)
)
PIVOT (
-- TODO use DISTINCT asap we have ORACLE 19c
LISTAGG(reco_rid, ',') WITHIN GROUP ( ORDER BY reco_rid ) AS rid,
LISTAGG(TO_CHAR(reco_date, 'DD/MM/YYYY'), ',') WITHIN GROUP ( ORDER BY reco_rid ) AS
dat_s
FOR subject IN (
'FINALISATION' AS finalisation,
'RECOMMENDATION' AS recommendation,
'TRANSMISSION LETTER' AS transmission_letter
)
)
) piv
LEFT JOIN (
SELECT lapp_mainact_cact_oid, MAX(lapp_performer_dat) AS appr_approval_dat
FROM bo_latestapproval la
WHERE lapp_activitysubtype_lib IN ( 'END' , 'JUDFINAL')
AND lapp_mainact_status_lib = 'DONE'
GROUP BY lapp_mainact_cact_oid
) la
ON lapp_mainact_cact_oid = mong_mainactivity_oid

The different pieces:

doc_via_reco: collect the document directly linked to the OCM recommendation object, this one is
always the RECOMMENDATION document itself

doc_with_act: collect the documents linked to the OCM activity object, these documents maybe also
TRANSMISSION LETTER

fin_by_act: collect the FINALISATION done by activity instead of a document, the finalisation date will
then be the end date of the approved activity, otherwise it’s the registration date of the document.

synth_reco_doc: assembly of the previous results:

the doc_via_reco
+
the doc_with_act that are FINALISATION, RECOMMENDATION or TRANSMISSION LETTER but not
the ones present in doc_via_reco
+
the fin_by_act for which they are no FINALISATION document in the 2 previous subset.
Once we have the final list of documents, we have to assemble the results by JOINing the documents
found with the life cycles of the Case they belong to return the name of the current stage, and with

18/19 13 JANUARY 2022


the monitoring to Case Contact Context to retrieve the OFFICIAL CONTACT, while Cases filtering on
OC,OF, IO,IU Case’s types.

Because operational situations (or lack of understanding of business rules), have forced the end-
users to use several times the same recommendation in different Cases, we then need to assemble
the results in a way that allows the query to return only one row per (Case, Recommendation) and
this requires a SQL trick (usage of LAG analytical function and taking advantage of the fact that
LISTAGG don’t return NULL values) to get around the fact that we don’t have the DISTINCT option in
the LISTAGG function, and we need it to use to return only 1 row.

Once this operation is done, we can eventually PIVOT the results to make columns out of the
information (registration id, registration date) associated to the different kind of documents
(RECOMMENDATION, FINALISATION, TRANSMISSION).

The latest operation is to link the result to the latest approval information related to the closing
activity of which subtype depends on the kind of recommendation: END for Financial
recommendation and JUDFINAL for Judicial recommendation.

The WSD2 variation of the same view returns also the history the monitoring amount modifications.

For this reason the rule one line per (Case, Recommendation) cannot be respected anymore and the
WSD variant should not be used to aggregate results like the recovered/prevented amounts.

However, the view v_latestmonitoringamounts could be used to JOIN the


v_synth_recommendations on the MONITORING object (via mona_mong_oid = mong_oid) and build
a WSD-like solution but returning only the latest m_monitoringamounts per (Case,
Recommendation).

2
The original purpose of the WSD variation was to monitor modifications done by end-users, not to do
operational reporting.

19/19 13 JANUARY 2022

You might also like