/****************************************************************************** ** Macro: Visual Forecasting - New Iteration ** ** Description: Invoke Visual Forecasting REST API to run an existing project with new data. ** ******************************************************************************/ %macro vf_new_iteration(protocol, host, port, username, password, projectId); filename resp TEMP; /****************************************************************************** ** Get authorization token... ******************************************************************************/ %put Get authorization token...; %global authtoken; proc http method="POST" url="&protocol.://&host.:&port./SASLogon/oauth/token" in="grant_type=password%nrstr(&)username=&username.%nrstr(&)password=&password." out=resp; headers "Authorization"="Basic c2FzLmVjOg==" "Accept"="application/json" "Content-Type"="application/x-www-form-urlencoded"; run; %put Response status: &SYS_PROCHTTP_STATUS_CODE; libname respjson JSON fileref=resp; data _null_; set respjson.root; call symput('authtoken', access_token); run; %put authtoken = &authtoken; %if not (&SYS_PROCHTTP_STATUS_CODE = 200) %then %do; %put ERROR: An invalid response was received.; %abort; %end; /****************************************************************************** ** Acquire project lock if necessary... ******************************************************************************/ %put Fetching project...; proc http method="GET" url="&protocol.://&host.:&port./analyticsGateway/projects/&projectId." out=resp; headers "Authorization"="bearer &authtoken."; run; libname respjson JSON fileref=resp; data _null_; set respjson.root; call symput('shared', shared); run; %put shared = &shared; %if (&shared = 1) %then %do; %put Acquire project lock...; proc http method="POST" url="&protocol.://&host.:&port./analyticsGateway/projects/&projectId./lock?lockPeriod=300" out=resp; headers "Authorization"="bearer &authtoken."; run; %put Response status: &SYS_PROCHTTP_STATUS_CODE; %if not (&SYS_PROCHTTP_STATUS_CODE = 200) %then %do; %put ERROR: An invalid response was received.; %abort; %end; %end; /****************************************************************************** ** Load project data... ******************************************************************************/ %put Loading project data...; proc http method="PUT" url="&protocol.://&host.:&port./forecastingGateway/projects/&projectId./dataState" out=resp; headers "Authorization"="bearer &authtoken."; run; %put Response status: &SYS_PROCHTTP_STATUS_CODE; %if not (&SYS_PROCHTTP_STATUS_CODE = 204) %then %do; %put ERROR: An invalid response was received.; %abort; %end; /****************************************************************************** ** Fetch data specification, checking for updated input data... ******************************************************************************/ %put Fetch data specification, checking for updated input data...; proc http method="GET" url="&protocol.://&host.:&port./forecastingGateway/projects/&projectId./dataDefinitions/@current?checkForUpdates=true" out=resp; headers "Authorization"="bearer &authtoken." "Accept"="application/vnd.sas.analytics.forecasting.data.definition+json"; run; %put Response status: &SYS_PROCHTTP_STATUS_CODE; %if not (&SYS_PROCHTTP_STATUS_CODE = 200) %then %do; %put ERROR: An invalid response was received.; %abort; %end; /****************************************************************************** ** If necessary, import new input data... ******************************************************************************/ %put If necessary, import new input data...; proc http method="POST" url="&protocol.://&host.:&port./forecastingGateway/projects/&projectId./dataDefinitions/@current/dataUpdateJobs?category=INPUT" out=resp; headers "Authorization"="bearer &authtoken."; run; %put Response status: &SYS_PROCHTTP_STATUS_CODE; %if not (&SYS_PROCHTTP_STATUS_CODE = 202) %then %do; %put ERROR: An invalid response was received.; %abort; %end; /****************************************************************************** ** Run all pipelines... ******************************************************************************/ %put Run all pipelines...; proc http method="POST" url="&protocol.://&host.:&port./forecastingGateway/projects/&projectId./pipelineJobs" out=resp; headers "Authorization"="bearer &authtoken." "Accept"="application/vnd.sas.job.execution.job+json"; run; %put Response status: &SYS_PROCHTTP_STATUS_CODE; %if not (&SYS_PROCHTTP_STATUS_CODE = 202) %then %do; %put ERROR: An invalid response was received.; %abort; %end; /****************************************************************************** ** Wait for pipelines to finish running... ******************************************************************************/ %put Wait for pipelines to finish running...; %global jobState; %do %until(&jobState ^= running); proc http method="GET" url="&protocol.://&host.:&port./forecastingGateway/projects/&projectId./pipelineJobs/@currentJob" out=resp; headers "Authorization"="bearer &authtoken." "Accept"="application/vnd.sas.job.execution.job+json"; run; %put Response status: &SYS_PROCHTTP_STATUS_CODE; libname respjson JSON fileref=resp; data _null_; set respjson.root; call symput('jobState', state); run; %put jobState = &jobState; data _null_; call sleep(10000); run; %end; %if not (&jobState = completed) %then %do; %put ERROR: An invalid response was received.; %abort; %end; /****************************************************************************** ** Check for overrides in pending or conflict state... ******************************************************************************/ %put Check for overrides in pending or conflict state...; %global pendingOverridesCount; proc http method="GET" url="&protocol.://&host.:&port./forecastingGateway/projects/&projectId./specificationDetails?start=0%nrstr(&)limit=1%nrstr(&)filter=or(eq(status,%27conflict%27),eq(status,%27pending%27))" out=resp; headers "Authorization"="bearer &authtoken." "Accept"="application/vnd.sas.collection+json"; run; %put Response status: &SYS_PROCHTTP_STATUS_CODE; libname respjson JSON fileref=resp; data _null_; set respjson.root; call symput('pendingOverridesCount', count); run; %put pendingOverridesCount = &pendingOverridesCount; %if not (&pendingOverridesCount = 0) %then %do; %put ERROR: Overrides were found in pending or conflict state. Please submit these overrides first.; %abort; %end; /****************************************************************************** ** Prepare for overrides... ******************************************************************************/ %put Prepare for overrides...; proc http method="POST" url="&protocol.://&host.:&port./forecastingGateway/projects/&projectId./dataDefinitions/@current/dataUpdateJobs?category=FORECAST" out=resp; headers "Authorization"="bearer &authtoken." "Content-Type"="application/vnd.sas.analytics.forecasting.data.specification+json"; run; %put Response status: &SYS_PROCHTTP_STATUS_CODE; %if not (&SYS_PROCHTTP_STATUS_CODE = 202) %then %do; %put ERROR: An invalid response was received.; %abort; %end; /****************************************************************************** ** Wait for all overrides to be prepared... ******************************************************************************/ %put Wait for all overrides to be prepared...; %global unpreparedTransactionCount; %do %until(&unpreparedTransactionCount = 0); proc http method="GET" url="&protocol.://&host.:&port./forecastingGateway/projects/&projectId./transactions?filter=eq(status,%27applied%27)" out=resp; headers "Authorization"="bearer &authtoken." "Accept"="application/vnd.sas.collection+json"; run; %put Response status: &SYS_PROCHTTP_STATUS_CODE; libname respjson JSON fileref=resp; data _null_; set respjson.root; call symput('unpreparedTransactionCount', count); run; %put unpreparedTransactionCount = &unpreparedTransactionCount; data _null_; call sleep(3000); run; %end; /****************************************************************************** ** Check for overrides availability... ******************************************************************************/ %put Check for overrides availability...; %global resubmitRequiredTransactionCount; proc http method="GET" url="&protocol.://&host.:&port./forecastingGateway/projects/&projectId./transactions?filter=or(eq(status,%27resubmitPending%27),eq(status,%27resubmitConflict%27))" out=resp; headers "Authorization"="bearer &authtoken." "Accept"="application/vnd.sas.collection+json"; run; %put Response status: &SYS_PROCHTTP_STATUS_CODE; libname respjson JSON fileref=resp; data _null_; set respjson.root; call symput('resubmitRequiredTransactionCount', count); run; %put resubmitRequiredTransactionCount = &resubmitRequiredTransactionCount; %if not (&resubmitRequiredTransactionCount > 0) %then %do; %put NOTE: No overrides need to be resubmitted. Existing overrides may have become archived or expired.; /****************************************************************************** Release project lock if necessary... ******************************************************************************/ %if (&shared = 1) %then %do; %put Release project lock...; proc http method="DELETE" url="&protocol.://&host.:&port./analyticsGateway/projects/&projectId./lock" out=resp; headers "Authorization"="bearer &authtoken."; run; %put Response status: &SYS_PROCHTTP_STATUS_CODE; %end; %return; %end; /****************************************************************************** ** Resubmit overrides... ******************************************************************************/ %put Resubmit overrides...; %global transactionJobId; proc http method="POST" url="&protocol.://&host.:&port./forecastingGateway/projects/&projectId./transactionJobs" in="{""firstTransaction"":""@first"",""lastTransaction"":""@last"",""autoResolve"":true}" out=resp; headers "Authorization"="bearer &authtoken." "Accept"="application/vnd.sas.forecasting.overrides.transaction.collection.job+json" "Content-Type"="application/vnd.sas.forecasting.overrides.transaction.collection.job.request+json"; run; %put Response status: &SYS_PROCHTTP_STATUS_CODE; libname respjson JSON fileref=resp; data _null_; set respjson.root; call symput('transactionJobId', id); run; %put transactionJobId = &transactionJobId; %if not (&SYS_PROCHTTP_STATUS_CODE = 202) %then %do; %put ERROR: An invalid response was received.; %abort; %end; /****************************************************************************** ** Wait for all overrides to be resubmitted... ******************************************************************************/ %put Wait for all overrides to be resubmitted...; %global transactionJobState; %do %until(&transactionJobState ^= running); proc http method="GET" url="&protocol.://&host.:&port./forecastingGateway/projects/&projectId./transactionJobs/&transactionJobId." out=resp; headers "Authorization"="bearer &authtoken." "Accept"="application/vnd.sas.forecasting.overrides.transaction.collection.job+json"; run; %put Response status: &SYS_PROCHTTP_STATUS_CODE; libname respjson JSON fileref=resp; data _null_; set respjson.root; call symput('transactionJobState', state); run; %put transactionJobState = &transactionJobState; data _null_; call sleep(3000); run; %end; %if not (&transactionJobState = completed) %then %do; %put ERROR: An invalid response was received.; %abort; %end; /****************************************************************************** Release project lock if necessary... ******************************************************************************/ %if (&shared = 1) %then %do; %put Release project lock...; proc http method="DELETE" url="&protocol.://&host.:&port./analyticsGateway/projects/&projectId./lock" out=resp; headers "Authorization"="bearer &authtoken."; run; %put Response status: &SYS_PROCHTTP_STATUS_CODE; %end; %mend; /* Call the macro */ %let protocol = http; %let host = ; %let port = 80; %let username = ; %let password = ; %let projectId = ; %vf_new_iteration(&protocol, &host, &port, &username, &password, &projectId);