diff --git a/client/src/environments/_eula.ts b/client/src/environments/_eula.ts index 684dea6..3d7cba2 100644 --- a/client/src/environments/_eula.ts +++ b/client/src/environments/_eula.ts @@ -18,4 +18,4 @@ In any case, you must not make any such use of this software as to develop softw UNLESS EXPRESSLY AGREED OTHERWISE, 4GL APPS PROVIDES THIS SOFTWARE ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, AND IN NO EVENT AND UNDER NO LEGAL THEORY, SHALL 4GL APPS BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES OF ANY CHARACTER ARISING FROM USE OR INABILITY TO USE THIS SOFTWARE. -` +` \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 463e6d8..4b22691 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "dcfrontend", - "version": "6.2.7", + "version": "6.3.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "dcfrontend", - "version": "6.2.7", + "version": "6.3.0", "hasInstallScript": true, "devDependencies": { "@saithodev/semantic-release-gitea": "^2.1.0", diff --git a/sas/sasjs/db/datactrl/mpe_xlmap_data.ddl b/sas/sasjs/db/datactrl/mpe_xlmap_data.ddl new file mode 100644 index 0000000..c9af454 --- /dev/null +++ b/sas/sasjs/db/datactrl/mpe_xlmap_data.ddl @@ -0,0 +1,18 @@ +/** + @file + @brief DDL for MPE_XLMAP_DATA + + @version 9.3 + @author 4GL Apps Ltd + @copyright 4GL Apps Ltd +**/ + +create table &curlib..MPE_XLMAP_DATA( + LOAD_REF char(32) not null, + XLMAP_ID char(32) not null, + XLMAP_RANGE_ID char(32) not null, + ROW_NO num not null, + COL_NO num not null, + VALUE_TXT char(4000), + constraint pk_MPE_XLMAP_DATA + primary key(LOAD_REF, XLMAP_ID, XLMAP_RANGE_ID, ROW_NO, COL_NO)); diff --git a/sas/sasjs/db/datactrl/mpe_xlmap_info.ddl b/sas/sasjs/db/datactrl/mpe_xlmap_info.ddl new file mode 100644 index 0000000..0b8cc26 --- /dev/null +++ b/sas/sasjs/db/datactrl/mpe_xlmap_info.ddl @@ -0,0 +1,17 @@ +/** + @file + @brief DDL for mpe_xlmap_info + + @version 9.3 + @author 4GL Apps Ltd + @copyright 4GL Apps Ltd +**/ + +create table &curlib..mpe_xlmap_info( + tx_from num not null, + XLMAP_ID char(32) not null, + XLMAP_DESCRIPTION char(1000) not null, + XLMAP_TARGETLIBDS char(41) not null, + tx_to num not null, + constraint pk_mpe_xlmap_info + primary key(tx_from,XLMAP_ID)); diff --git a/sas/sasjs/db/datactrl/mpe_xlmap_rules.ddl b/sas/sasjs/db/datactrl/mpe_xlmap_rules.ddl new file mode 100644 index 0000000..c22000d --- /dev/null +++ b/sas/sasjs/db/datactrl/mpe_xlmap_rules.ddl @@ -0,0 +1,19 @@ +/** + @file + @brief DDL for mpe_xlmap_rules + + @version 9.3 + @author 4GL Apps Ltd + @copyright 4GL Apps Ltd +**/ + +create table &curlib..mpe_xlmap_rules( + tx_from num not null, + XLMAP_ID char(32) not null, + XLMAP_RANGE_ID char(32) not null, + XLMAP_SHEET char(32) not null, + XLMAP_START char(1000) not null, + XLMAP_FINISH char(1000), + tx_to num not null, + constraint pk_mpe_xlmap_rules + primary key(tx_from,XLMAP_ID,XLMAP_RANGE_ID)); diff --git a/sas/sasjs/db/migrations/20230115_v6.5_release.sas b/sas/sasjs/db/migrations/20230115_v6.5_release.sas new file mode 100644 index 0000000..1848cd6 --- /dev/null +++ b/sas/sasjs/db/migrations/20230115_v6.5_release.sas @@ -0,0 +1,44 @@ +/** + @file + @brief migration script to move from v5 to v6.5 of data controller + +**/ + +%let dclib=YOURDCLIB; + +libname &dclib "/your/dc/path"; + +/** + * Change 1 + * New MPE_SUBMIT table + */ +proc sql; +create table &dclib..mpe_xlmap_rules( + tx_from num not null, + XLMAP_ID char(32) not null, + XLMAP_RANGE_ID char(32) not null, + XLMAP_SHEET char(32) not null, + XLMAP_START char(1000) not null, + XLMAP_FINISH char(1000), + tx_to num not null, + constraint pk_mpe_xlmap_rules + primary key(tx_from,XLMAP_ID,XLMAP_RANGE_ID)); + +create table &dclib..MPE_XLMAP_DATA( + LOAD_REF char(32) not null, + XLMAP_ID char(32) not null, + XLMAP_RANGE_ID char(32) not null, + ROW_NO num not null, + COL_NO num not null, + VALUE_TXT char(4000), + constraint pk_MPE_XLMAP_DATA + primary key(LOAD_REF, XLMAP_ID, XLMAP_RANGE_ID, ROW_NO, COL_NO)); + +create table &dclib..mpe_xlmap_info( + tx_from num not null, + XLMAP_ID char(32) not null, + XLMAP_DESCRIPTION char(1000) not null, + XLMAP_TARGETLIBDS char(41) not null, + tx_to num not null, + constraint pk_mpe_xlmap_info + primary key(tx_from,XLMAP_ID)); diff --git a/sas/sasjs/macros/mpe_loader.sas b/sas/sasjs/macros/mpe_loader.sas index eccfc41..bc7f6f5 100755 --- a/sas/sasjs/macros/mpe_loader.sas +++ b/sas/sasjs/macros/mpe_loader.sas @@ -24,6 +24,7 @@ @li mp_lockanytable.sas @li mpe_accesscheck.sas @li mpe_alerts.sas + @li mpe_xlmapvalidate.sas @li mpe_loadfail.sas @li mpe_runhook.sas @@ -450,7 +451,7 @@ run; %do i=1 %to %sysfunc(countw(&pk)); %let iWord=%scan(&pk,&i); call symputx('duplist',symget('duplist')!! - " &iWord="!!trim(&iWord)); + " &iWord="!!cats(&iWord)); %end; run; %let msg=This upload contains duplicates on the Primary Key columns %trim( @@ -472,6 +473,10 @@ run; %return; %end; +/* If a Complex Excel Upload, needs to have the load ref added to the table */ +%mpe_xlmapvalidate(&mperef,work.staging_ds,&mpelib,&orig_libds) + +/* Run the Post Edit Hook prior to creation of staging folder */ %mpe_runhook(POST_EDIT_HOOK) /* stop if err */ diff --git a/sas/sasjs/macros/mpe_makedata.sas b/sas/sasjs/macros/mpe_makedata.sas index 2a734ac..d908ad4 100644 --- a/sas/sasjs/macros/mpe_makedata.sas +++ b/sas/sasjs/macros/mpe_makedata.sas @@ -269,6 +269,210 @@ insert into &lib..mpe_datadictionary set ,DD_SENSITIVITY="Low" ,tx_to='31DEC5999:23:59:59'dt; +/** + * mpe_xlmap_info + */ +insert into &lib..mpe_xlmap_info set + tx_from=0 + ,tx_to='31DEC5999:23:59:59'dt + ,xlmap_id='BASEL-KM1' + ,xlmap_description='Basel 3 Key Metrics report' + ,XLMAP_TARGETLIBDS="&lib..MPE_XLMAP_DATA"; + +/** + * mpe_xlmap_rules + */ +insert into &lib..mpe_xlmap_rules set + tx_from=0 + ,tx_to='31DEC5999:23:59:59'dt + ,xlmap_id='BASEL-KM1' + ,xlmap_range_id='KM1:a' + ,xlmap_sheet='KM1' + ,xlmap_start='MATCH 4 R[2]C[0]:a'; +insert into &lib..mpe_xlmap_rules set + tx_from=0 + ,tx_to='31DEC5999:23:59:59'dt + ,xlmap_id='BASEL-KM1' + ,xlmap_range_id='KM1:b' + ,xlmap_sheet='KM1' + ,xlmap_start='MATCH 4 R[2]C[0]:b'; +insert into &lib..mpe_xlmap_rules set + tx_from=0 + ,tx_to='31DEC5999:23:59:59'dt + ,xlmap_id='BASEL-KM1' + ,xlmap_range_id='KM1:c' + ,xlmap_sheet='KM1' + ,xlmap_start='MATCH 4 R[2]C[0]:c'; +insert into &lib..mpe_xlmap_rules set + tx_from=0 + ,tx_to='31DEC5999:23:59:59'dt + ,xlmap_id='BASEL-KM1' + ,xlmap_range_id='KM1:d' + ,xlmap_sheet='KM1' + ,xlmap_start='MATCH 4 R[2]C[0]:d'; +insert into &lib..mpe_xlmap_rules set + tx_from=0 + ,tx_to='31DEC5999:23:59:59'dt + ,xlmap_id='BASEL-KM1' + ,xlmap_range_id='KM1:e' + ,xlmap_sheet='KM1' + ,xlmap_start='MATCH 4 R[2]C[0]:e'; +insert into &lib..mpe_xlmap_rules set + tx_from=0 + ,tx_to='31DEC5999:23:59:59'dt + ,xlmap_id='BASEL-KM1' + ,xlmap_range_id='KM1:f' + ,xlmap_sheet='KM1' + ,xlmap_start='MATCH 4 R[2]C[0]:f'; +insert into &lib..mpe_xlmap_rules set + tx_from=0 + ,tx_to='31DEC5999:23:59:59'dt + ,xlmap_id='BASEL-KM1' + ,xlmap_range_id='KM1:1/a' + ,xlmap_sheet='KM1' + ,xlmap_start='MATCH C R[0]C[1]:Common Equity Tier 1 (CET1)'; +insert into &lib..mpe_xlmap_rules set + tx_from=0 + ,tx_to='31DEC5999:23:59:59'dt + ,xlmap_id='BASEL-KM1' + ,xlmap_range_id='KM1:1/b' + ,xlmap_sheet='KM1' + ,xlmap_start='MATCH C R[0]C[2]:Common Equity Tier 1 (CET1)'; + insert into &lib..mpe_xlmap_rules set + tx_from=0 + ,tx_to='31DEC5999:23:59:59'dt + ,xlmap_id='BASEL-KM1' + ,xlmap_range_id='KM1:1/c' + ,xlmap_sheet='KM1' + ,xlmap_start='MATCH C R[0]C[3]:Common Equity Tier 1 (CET1)'; + insert into &lib..mpe_xlmap_rules set + tx_from=0 + ,tx_to='31DEC5999:23:59:59'dt + ,xlmap_id='BASEL-KM1' + ,xlmap_range_id='KM1:1/d' + ,xlmap_sheet='KM1' + ,xlmap_start='MATCH C R[0]C[4]:Common Equity Tier 1 (CET1)'; + insert into &lib..mpe_xlmap_rules set + tx_from=0 + ,tx_to='31DEC5999:23:59:59'dt + ,xlmap_id='BASEL-KM1' + ,xlmap_range_id='KM1:1/e' + ,xlmap_sheet='KM1' + ,xlmap_start='MATCH C R[0]C[5]:Common Equity Tier 1 (CET1)'; +insert into &lib..mpe_xlmap_rules set + tx_from=0 + ,tx_to='31DEC5999:23:59:59'dt + ,xlmap_id='BASEL-KM1' + ,xlmap_range_id='KM1:1/f' + ,xlmap_sheet='KM1' + ,xlmap_start='MATCH C R[0]C[6]:Common Equity Tier 1 (CET1)'; +insert into &lib..mpe_xlmap_rules set + tx_from=0 + ,tx_to='31DEC5999:23:59:59'dt + ,xlmap_id='BASEL-KM1' + ,xlmap_range_id='KM1:1a/e' + ,xlmap_sheet='KM1' + ,xlmap_start='MATCH C R[1]C[5]:Common Equity Tier 1 (CET1)'; +insert into &lib..mpe_xlmap_rules set + tx_from=0 + ,tx_to='31DEC5999:23:59:59'dt + ,xlmap_id='BASEL-KM1' + ,xlmap_range_id='KM1:1a/f' + ,xlmap_sheet='KM1' + ,xlmap_start='MATCH C R[1]C[6]:Common Equity Tier 1 (CET1)'; +insert into &lib..mpe_xlmap_rules set + tx_from=0 + ,tx_to='31DEC5999:23:59:59'dt + ,xlmap_id='BASEL-KM1' + ,xlmap_range_id='KM1:2/a' + ,xlmap_sheet='KM1' + ,xlmap_start='ABSOLUTE D10'; +insert into &lib..mpe_xlmap_rules set + tx_from=0 + ,tx_to='31DEC5999:23:59:59'dt + ,xlmap_id='BASEL-KM1' + ,xlmap_range_id='KM1:2/b' + ,xlmap_sheet='/3' + ,xlmap_start='ABSOLUTE E10'; +insert into &lib..mpe_xlmap_rules set + tx_from=0 + ,tx_to='31DEC5999:23:59:59'dt + ,xlmap_id='BASEL-KM1' + ,xlmap_range_id='KM1:2/c' + ,xlmap_sheet='/3' + ,xlmap_start='RELATIVE R[10]C[6]'; +insert into &lib..mpe_xlmap_rules set + tx_from=0 + ,tx_to='31DEC5999:23:59:59'dt + ,xlmap_id='BASEL-KM1' + ,xlmap_range_id='KM1:2/d' + ,xlmap_sheet='/3' + ,xlmap_start='RELATIVE R[10]C[8]'; +insert into &lib..mpe_xlmap_rules set + tx_from=0 + ,tx_to='31DEC5999:23:59:59'dt + ,xlmap_id='BASEL-KM1' + ,xlmap_range_id='KM1:2/e' + ,xlmap_sheet='/3' + ,xlmap_start='RELATIVE R[10]C[9]'; +insert into &lib..mpe_xlmap_rules set + tx_from=0 + ,tx_to='31DEC5999:23:59:59'dt + ,xlmap_id='BASEL-KM1' + ,xlmap_range_id='KM1:2/f' + ,xlmap_sheet='/3' + ,xlmap_start='RELATIVE R[10]C[10]'; +insert into &lib..mpe_xlmap_rules set + tx_from=0 + ,tx_to='31DEC5999:23:59:59'dt + ,xlmap_id='BASEL-KM1' + ,xlmap_range_id='KM1:2a' + ,xlmap_sheet='KM1' + ,xlmap_start='ABSOLUTE H11' + ,xlmap_finish='RELATIVE R[0]C[1]'; +insert into &lib..mpe_xlmap_rules set + tx_from=0 + ,tx_to='31DEC5999:23:59:59'dt + ,xlmap_id='BASEL-KM1' + ,xlmap_range_id='KM1:3' + ,xlmap_sheet='KM1' + ,xlmap_start='RELATIVE R[12]C[4]' + ,xlmap_finish='ABSOLUTE I13'; +insert into &lib..mpe_xlmap_rules set + tx_from=0 + ,tx_to='31DEC5999:23:59:59'dt + ,xlmap_id='BASEL-CR2' + ,xlmap_range_id='CR2-sec1' + ,xlmap_sheet='CR2' + ,xlmap_start='ABSOLUTE D8' + ,xlmap_finish='BLANKROW'; +insert into &lib..mpe_xlmap_rules set + tx_from=0 + ,tx_to='31DEC5999:23:59:59'dt + ,xlmap_id='BASEL-CR2' + ,xlmap_range_id='CR2-sec2' + ,xlmap_sheet='CR2' + ,xlmap_start='ABSOLUTE D18' + ,xlmap_finish='LASTDOWN'; +insert into &lib..mpe_xlmap_rules set + tx_from=0 + ,tx_to='31DEC5999:23:59:59'dt + ,xlmap_id='Sample' + ,xlmap_range_id='header' + ,xlmap_sheet='/1' + ,xlmap_start='ABSOLUTE B3' + ,xlmap_finish='ABSOLUTE B8'; +insert into &lib..mpe_xlmap_rules set + tx_from=0 + ,tx_to='31DEC5999:23:59:59'dt + ,xlmap_id='Sample' + ,xlmap_range_id='data' + ,xlmap_sheet='/1' + ,xlmap_start='ABSOLUTE B13' + ,xlmap_finish='ABSOLUTE E16'; + + + /** * MPE_GROUPS */ @@ -981,6 +1185,42 @@ insert into &lib..mpe_selectbox set ,notes='Docs: https://docs.datacontroller.io/column-level-security' ,post_edit_hook='services/hooks/mpe_column_level_security_postedit' ; + insert into &lib..mpe_tables + set tx_from=0 + ,tx_to='31DEC5999:23:59:59'dt + ,libref="&lib" + ,dsn='MPE_XLMAP_INFO' + ,num_of_approvals_required=1 + ,loadtype='TXTEMPORAL' + ,var_txfrom='TX_FROM' + ,var_txto='TX_TO' + ,buskey='XLMAP_ID' + ,notes='Docs: https://docs.datacontroller.io/complex-excel-uploads' + ,post_edit_hook='services/hooks/mpe_xlmap_info_postedit' + ; + insert into &lib..mpe_tables + set tx_from=0 + ,tx_to='31DEC5999:23:59:59'dt + ,libref="&lib" + ,dsn='MPE_XLMAP_RULES' + ,num_of_approvals_required=1 + ,loadtype='TXTEMPORAL' + ,var_txfrom='TX_FROM' + ,var_txto='TX_TO' + ,buskey='XLMAP_ID XLMAP_RANGE_ID' + ,notes='Docs: https://docs.datacontroller.io/complex-excel-uploads' + ,post_edit_hook='services/hooks/mpe_xlmap_rules_postedit' + ; + insert into &lib..mpe_tables + set tx_from=0 + ,tx_to='31DEC5999:23:59:59'dt + ,libref="&lib" + ,dsn='MPE_XLMAP_DATA' + ,num_of_approvals_required=1 + ,loadtype='UPDATE' + ,buskey='LOAD_REF XLMAP_ID XLMAP_RANGE_ID ROW_NO COL_NO' + ,notes='Docs: https://docs.datacontroller.io/complex-excel-uploads' + ; insert into &lib..mpe_tables set tx_from=0 ,tx_to='31DEC5999:23:59:59'dt @@ -1253,6 +1493,27 @@ insert into &lib..MPE_VALIDATIONS set ,rule_value="services/validations/mpe_alerts.alert_lib" ,rule_active=1 ,tx_to='31DEC5999:23:59:59'dt; + +insert into &lib..MPE_VALIDATIONS set + tx_from=0 + ,base_lib="&lib" + ,base_ds="MPE_XLMAP_INFO" + ,base_col="XLMAP_ID" + ,rule_type='CASE' + ,rule_value='UPCASE' + ,rule_active=1 + ,tx_to='31DEC5999:23:59:59'dt; + +insert into &lib..MPE_VALIDATIONS set + tx_from=0 + ,base_lib="&lib" + ,base_ds="MPE_XLMAP_RULES" + ,base_col="XLMAP_ID" + ,rule_type='CASE' + ,rule_value='UPCASE' + ,rule_active=1 + ,tx_to='31DEC5999:23:59:59'dt; + insert into &lib..MPE_VALIDATIONS set tx_from=0 ,base_lib="&lib" diff --git a/sas/sasjs/macros/mpe_makedatamodel.sas b/sas/sasjs/macros/mpe_makedatamodel.sas index 08e0837..ae86152 100644 --- a/sas/sasjs/macros/mpe_makedatamodel.sas +++ b/sas/sasjs/macros/mpe_makedatamodel.sas @@ -268,6 +268,56 @@ proc datasets lib=&lib noprint; pk_mpe_excel_config=(tx_to xl_libref xl_table xl_column) /nomiss unique; quit; + +proc sql; +create table &lib..MPE_XLMAP_DATA( + LOAD_REF char(32) ¬null, + XLMAP_ID char(32) ¬null, + XLMAP_RANGE_ID char(32) ¬null, + ROW_NO num ¬null, + COL_NO num ¬null, + VALUE_TXT char(4000) +);quit; +proc datasets lib=&lib noprint; + modify MPE_XLMAP_DATA; + index create + pk_MPE_XLMAP_DATA=(load_ref xlmap_id xlmap_range_id row_no col_no) + /nomiss unique; +quit; + +proc sql; +create table &lib..mpe_xlmap_info( + tx_from num ¬null, + tx_to num ¬null, + XLMAP_ID char(32) ¬null, + XLMAP_DESCRIPTION char(1000) ¬null, + XLMAP_TARGETLIBDS char(41) ¬null +);quit; +proc datasets lib=&lib noprint; + modify mpe_xlmap_info; + index create + pk_mpe_xlmap_info=(tx_to xlmap_id) + /nomiss unique; +quit; + +proc sql; +create table &lib..mpe_xlmap_rules( + tx_from num ¬null, + tx_to num ¬null, + XLMAP_ID char(32) ¬null, + XLMAP_RANGE_ID char(32) ¬null, + XLMAP_SHEET char(32) ¬null, + XLMAP_START char(1000) ¬null, + XLMAP_FINISH char(1000), + XLMAP_TARGETLIBDS char(41) +);quit; +proc datasets lib=&lib noprint; + modify mpe_xlmap_rules; + index create + pk_mpe_xlmap_rules=(tx_to xlmap_id xlmap_range_id) + /nomiss unique; +quit; + proc sql; create table &lib..mpe_filteranytable( filter_rk num ¬null, diff --git a/sas/sasjs/macros/mpe_xlmapvalidate.sas b/sas/sasjs/macros/mpe_xlmapvalidate.sas new file mode 100644 index 0000000..226074c --- /dev/null +++ b/sas/sasjs/macros/mpe_xlmapvalidate.sas @@ -0,0 +1,28 @@ +/** + @file + @brief Validates excel map structure and adds load ref + @details Used in staging, prior to the post edit hook + + @version 9.2 + @author 4GL Apps Ltd + @copyright 4GL Apps Ltd. This code may only be used within Data Controller + and may not be re-distributed or re-sold without the express permission of + 4GL Apps Ltd. +**/ + +%macro mpe_xlmapvalidate(mperef,inds,dclib,tgtds); + + %local ismap; + proc sql noprint; + select count(*) into: ismap + from &dclib..mpe_xlmap_info + where XLMAP_TARGETLIBDS="&tgtds" and &dc_dttmtfmt. le TX_TO ; + + %if "&tgtds"="&dclib..MPE_XLMAP_DATA" or &ismap>0 %then %do; + data &inds; + set &inds; + LOAD_REF="&mperef"; + run; + %end; + +%mend mpe_xlmapvalidate; diff --git a/sas/sasjs/macros/mpe_xlmapvalidate.test.sas b/sas/sasjs/macros/mpe_xlmapvalidate.test.sas new file mode 100644 index 0000000..1e82ff2 --- /dev/null +++ b/sas/sasjs/macros/mpe_xlmapvalidate.test.sas @@ -0,0 +1,59 @@ +/** + @file + @brief Testing mpe_xlmapvalidate macro + +