Initialisation by Central Admin based on Actual Period
Figure 1: Central Admin App, performing initialisation.
This is achieved by creating an instance of Planning Model and reading the member properties into script variables during the onInitialization event as shown below.
var member = PlanningModel_1.getMember("Version", "public.Budget");
var prop = member.properties;
var actual_date = prop.ACTUAL_DT;
var budget_year = prop.BudgetYear;
var inp_budget_ver = "public." + prop.INPUT_BUDGET_VER;
Table_8.getDataSource().removeDimensionFilter("Date");
Table_8.getDataSource().setDimensionFilter("Date", "[Date].[YQM].&[" + actual_date + "]");
Table_8.getDataSource().removeDimensionFilter("Version");
Table_8.getDataSource().setDimensionFilter("Version", [inp_budget_ver, "public.Actual"]);
Table_8.getDataSource().removeDimensionFilter("BUDGET_YEAR");
Table_8.getDataSource().setDimensionFilter("BUDGET_YEAR", [budget_year, "#"]);
// Populate Script Variable
ACTUAL_DT = actual_date;
BUDGET_YEAR = budget_year;
INPUT_BUDGET_VERSION = inp_budget_ver;
BUD_VERSION = prop.INPUT_BUDGET_VER;
The above logic will set the Actual Date, Budget Year, Input Budget Version to the Script variables. This will also allow restricting the Actual Date, Source (Actuals in this case) and Target Version (Input Budget Version) & Budget Year in the output.
Logic to implement Initialisation of Input Budget Version, onClick event is shown below. A Data action to initialise needs to be created beforehand.
Create Data action object in Application Designer.
var budget_year = BUDGET_YEAR; //prop.BudgetYear;
var inp_budget_ver = INPUT_BUDGET_VERSION; //prop.INPUT_BUDGET_VER;
Application.showBusyIndicator("Preparing execution...");
DataAction_1.setParameterValue("TargetVersion", inp_budget_ver);
DataAction_1.setParameterValue("SourceVersion", "public.Actual");
DataAction_1.setParameterValue("BudgetYear", budget_year);
var response = DataAction_1.execute();
if (response.status === DataActionExecutionResponseStatus.Success)
{
console.log("The execution of your data action was successful.");
if (Table_8.getPlanning().getPublicVersion(BUD_VERSION))
{
var ver = Table_8.getPlanning().getPublicVersion(BUD_VERSION).getId();
Table_8.getDataSource().removeDimensionFilter("Version");
Table_8.getDataSource().setDimensionFilter("Version", [ver, "public.Actual"]);
Table_8.getDataSource().removeDimensionFilter("BUDGET_YEAR");
console.log(ver);
}
Application.refreshData();
Application.hideBusyIndicator();
}
Figure 2: Central Admin App, entering NI and Pension rates (or assumptions).
Figure 3: Central Admin App, setting/resetting overall status.
Implemented as below on Button - OnClick
var allCstMembers = PlanningModel_1.getMembers("COSTCENTER");
if (RadioButtonGroup_1.getSelectedKey() === "SET")
{
for (var counter = 0; counter < allCstMembers.length; counter++)
{
PlanningModel_1.updateMembers("COSTCENTER", { id: allCstMembers[counter].id, properties:{CLOSE : "A"} } );
console.log( allCstMembers[counter].id);
console.log(allCstMembers[counter].properties);
}
}
else if (RadioButtonGroup_1.getSelectedKey() === "RESET")
{
for (var counter_2 = 0; counter_2 < allCstMembers.length; counter_2++)
{
PlanningModel_1.updateMembers("COSTCENTER", { id: allCstMembers[counter_2].id, properties:{CLOSE : "O"} } );
console.log( allCstMembers[counter_2].id);
console.log(allCstMembers[counter_2].properties);
}
}
Application.refreshData([Table_8.getDataSource()]);
Staff Planner makes adjustment to FTE & Proposed Budget.
After initialisation of Input Budget Version, system automatically proposes Total Cost of Employment. This is calculated as below.
Total Cost of Employment = Salary * FTE + Pension % + NI %
The system automatically calculates the budget at a post holder level using the total costs of employment calculation where:
Staff Planner opens the Application (as shown below) and sees the post holders for the cost centres he/she is assigned as a submitter, with the Status Flag (ZCLOSE) as Original (“O) or Rejected (“REJ”) by reviewer. Budgeted FTE and Adjustments can be made at this stage prior to Staff Planner submitting this for Review.
Figure 4: Staff Planner App, adjusting the Input Budget Version.
Below onInitialization function is implemented to filter data for Input Budget Version and Budget Year which are read from corresponding properties of Version member, “public.Budget”.
Further logic to restrict Cost Centre where staff planner is assigned as a submitter, with the Status Flag (ZCLOSE) as Original (“O) or Rejected (“REJ”).
var member = PlanningModel_1.getMember("Version", "public.Budget");
var prop = member.properties;
var actual_date = prop.ACTUAL_DT;
var budget_year = prop.BudgetYear;
var inp_budget_ver = "public." + prop.INPUT_BUDGET_VER;
if (Table_5.getPlanning().getPublicVersion(BUD_VERSION))
{
var ver = Table_5.getPlanning().getPublicVersion(BUD_VERSION).getId();
Table_5.getDataSource().removeDimensionFilter("Version");
Table_5.getDataSource().setDimensionFilter("Version", [ver]);
Table_5.getDataSource().removeDimensionFilter("BUDGET_YEAR");
Table_5.getDataSource().setDimensionFilter("BUDGET_YEAR", [budget_year]);
}
// Set Cost Center filter based on Status
var cctr = ArrayUtils.create(Type.string);
var cctr_rev = ArrayUtils.create(Type.string);
var allCstMembers = PlanningModel_1.getMembers("COSTCENTER");
Table_5.getDataSource().removeDimensionFilter("COSTCENTER");
var userid = cast(Type.string, Application.getUserInfo().id);
for (var counter = 0; counter < allCstMembers.length; counter++)
{
var prop_2 = allCstMembers[counter].properties;
var zsubm = cast(Type.string, prop_2.ZSUBM);
var zrevw = cast(Type.string, prop.ZREVW);
var zclose = cast(Type.string, prop_2.CLOSE);
if ((zsubm === userid) && (zclose === "O") || (zclose === "REJ"))
// Submitter but To be sumbitted
{
cctr.push(allCstMembers[counter].id);
}
}
if (cctr.length === 0)
{
Table_5.getDataSource().setDimensionFilter("COSTCENTER","#");
}
else
{
Table_5.getDataSource().setDimensionFilter("COSTCENTER",cctr);
}
// Setting Script Filter
ACT_PER = actual_date;
INPUT_BUDGET_VER = inp_budget_ver;
BUD_YEAR = budget_year;
Functionality that impact or displays the Status Flag is implemented as below.
This would display status of Cost Centre(s), assigned to the Staff Planner as a Submitter.
Cost Centre(s) in Status
The status is displayed on the popup screen as shown below.
Figure 5: Staff Planner Application, status of Cost Center where planner is assigned as Submitter.
This is implemented (as below) when user clicks “Display Submission Status” button. A popup as shown above displays Cost Centre in different dropdowns depending upon their respective status.
var allCstMembers = PlanningModel_1.getMembers("COSTCENTER");
var userid = cast(Type.string, Application.getUserInfo().id);
for (var counter = 0; counter < allCstMembers.length; counter++)
{
var prop = allCstMembers[counter].properties;
var zsubm = cast(Type.string, prop.ZSUBM);
// var zrevw = cast(Type.string, prop.ZREVW);
var zclose = cast(Type.string, prop.CLOSE);
console.log(userid);
console.log(zsubm);
console.log(zclose);
if (zsubm === userid && zclose === "O")
// Submitter but To be sumbitted
{
Dropdown_1.addItem(allCstMembers[counter].id);
console.log( allCstMembers[counter].id);
}
if ( (zsubm === userid) && (zclose === "S") )
// Submitter but Submitted
{
Dropdown_2.addItem(allCstMembers[counter].id);
console.log( allCstMembers[counter].id);
}
if ( (zsubm === userid) && (zclose === "REJ") )
// Submitter but Rejected
{
Dropdown_3.addItem(allCstMembers[counter].id);
console.log( allCstMembers[counter].id);
}
}
Popup_1.open();
Staff Planner creates Budget Version and submits to Reviewer
Create Budget Version from the Input Budget Version for Cost Centre in the view. On Creation of Budget Version, list is regenerated for Cost Centres that are yet to be submitted. Finally display list of Post Holders in Cost Centres that are yet to be submitted, ie. Original (ZCLOSE = “O”) or Rejected (ZCLOSE = “REJ”), achieved as below.
Select the Cost Centres that are restricted/filtered in the current Table into an array of strings.
Application.showBusyIndicator("Creating Budget...");
var V_Selection = Table_5.getDataSource().getDataSelections() ;
var cctr_res = ArrayUtils.create(Type.string);
var prev_cctr = cast(Type.string, " ");
if (V_Selection.length)
{
for (var res_ctr = 0; res_ctr < V_Selection.length; res_ctr++)
{
if ( V_Selection[res_ctr].COSTCENTER === prev_cctr)
{
}
else
{
cctr_res.push(V_Selection[res_ctr].COSTCENTER);
prev_cctr = V_Selection[res_ctr].COSTCENTER;
}
}
// Set Parameter 1
DataAction_1.setParameterValue("CCtr", cctr_res);
}
// Set Parameter 2
DataAction_1.setParameterValue("TargetVersion", "public.Budget");
// Set Parameter 3
DataAction_1.setParameterValue("SourceVersion", INPUT_BUDGET_VER);
// Execute Action
var response = DataAction_1.execute();
On Successful execution of Data Action
if (response.status === DataActionExecutionResponseStatus.Success) {
console.log("The execution of your data action was successful.");
// Update Status to Success
for (var sub_ctr = 0; sub_ctr < cctr_res.length; sub_ctr++)
{
PlanningModel_1.updateMembers("COSTCENTER", { id: cctr_res[sub_ctr], properties:{CLOSE : "S"} } );
}
// Set Cost Center filter based on Status
var cctr = ArrayUtils.create(Type.string);
var allCstMembers = PlanningModel_1.getMembers("COSTCENTER");
var userid = cast(Type.string, Application.getUserInfo().id);
for (var counter = 0; counter < allCstMembers.length; counter++)
{
var prop_2 = allCstMembers[counter].properties;
var zsubm = cast(Type.string, prop_2.ZSUBM);
var zclose = cast(Type.string, prop_2.CLOSE);
console.log(userid);
console.log(zsubm);
console.log(zclose);
if ((zsubm === userid))
// User is a Submitter but CCenter is yet to be sumbitted
{
if (zclose === "O")
{
console.log(zclose);
cctr.push(allCstMembers[counter].id);
}
if (zclose === "REJ")
{
console.log(zclose);
cctr.push(allCstMembers[counter].id);
}
}
}
Table_5.getDataSource().removeDimensionFilter("COSTCENTER");
Table_5.getDataSource().setDimensionFilter("COSTCENTER",cctr);
Application.refreshData();
Application.hideBusyIndicator();
}
else
{ // response.status === DataActionExecutionResponseStatus.Error
console.log("Sorry, the execution of your data action failed.");
}
if (Table_5.getPlanning().getPublicVersion(BUD_VERSION).isDirty() )
{
Table_5.getPlanning().getPublicVersion(BUD_VERSION).publish();
}
Based on access, Reviewer reviews the Budget and either accepts or rejects the same. Application allows for entering the reason for rejection, which can be viewed by Submitter from his/her view of the application.
Application opens by displaying Cost Centres for which reviewer has access to, this displays cost centres and the position holders with the total Budget. By default, it displays cost centres which are either in Submitted, Rejected or Approved Status.
Function onInitialization is implemented as below.
// Set Cost Center filter based on Status
var cctr_rev = ArrayUtils.create(Type.string);
var allCstMembers = PlanningModel_1.getMembers("COSTCENTER");
var userid = cast(Type.string, Application.getUserInfo().id);
for (var counter = 0; counter < allCstMembers.length; counter++)
{
var prop_2 = allCstMembers[counter].properties;
var zrevw = cast(Type.string, prop_2.ZREVW);
var zclose = cast(Type.string, prop_2.CLOSE);
console.log(zrevw);
console.log(zclose);
if ((zrevw === userid) && (zclose === "S" || zclose ==="REJ" || zclose === "A") )
// Reviewer, CC in Submitted, Rejected or Approved State.
{
cctr_rev.push(allCstMembers[counter].id);
}
}
Table_3.getDataSource().removeDimensionFilter("COSTCENTER");
if (cctr_rev.length === 0)
{
Table_3.getDataSource().setDimensionFilter("COSTCENTER","#");
}
else
{
Table_3.getDataSource().setDimensionFilter("COSTCENTER",cctr_rev);
}
As part of the review process, reviewer can Accept, Reject, Display Status, Switch between Plan & View Mode, Adjust, Publish Budget and Finally Submit to Revenue Budget. Some of the above functionalities described are implemented as below.
A reviewer can select Cost Centre(s) and Reject them. During the rejection, reviewer can enter comment giving reason for rejection. Once rejected, this cost centre can be visible from submitters view for re-entering the data.
User can reject one or multiple CC(s) and can provide reason for rejection all at once or on Cost Centre by Cost Centre basis. The implementation for the onClick function is detailed below.
var V_Selection = Table_3.getDataSource().getDataSelections() ;
console.log("v_selection");
console.log(V_Selection);
var cctr_res = ArrayUtils.create(Type.string);
var prev_cctr = cast(Type.string, " ");
if (V_Selection.length)
{
for (var res_ctr = 0; res_ctr < V_Selection.length; res_ctr++)
{
if ( V_Selection[res_ctr].COSTCENTER === prev_cctr)
{
}
else
{
console.log("V_Selection" + V_Selection[res_ctr].COSTCENTER);
console.log("Previous Ctr" + prev_cctr);
cctr_res.push(V_Selection[res_ctr].COSTCENTER);
prev_cctr = V_Selection[res_ctr].COSTCENTER;
PlanningModel_1.updateMembers("COSTCENTER", { id: V_Selection[res_ctr].COSTCENTER, properties:{CLOSE : "REJ"} } );
PlanningModel_1.updateMembers("COSTCENTER", { id: V_Selection[res_ctr].COSTCENTER, properties:{ZCOMMENT : InputField_1.getValue()} } );
}
}
}
InputField_1.setValue("");
Application.showBusyIndicator("Rejecting ...");
Application.refreshData();
Application.hideBusyIndicator();
Likewise, reviewer can approve Budget Occupied Data for the Cost Centre(s)
The implementation for the onClick function is detailed below.
var V_Selection = Table_3.getDataSource().getDataSelections() ;
console.log("v_selection");
console.log(V_Selection);
var cctr_res = ArrayUtils.create(Type.string);
var prev_cctr = cast(Type.string, " ");
if (V_Selection.length)
{
for (var res_ctr = 0; res_ctr < V_Selection.length; res_ctr++)
{
if ( V_Selection[res_ctr].COSTCENTER === prev_cctr)
{
}
else
{
console.log("V_Selection" + V_Selection[res_ctr].COSTCENTER);
console.log("Previous Ctr" + prev_cctr);
cctr_res.push(V_Selection[res_ctr].COSTCENTER);
prev_cctr = V_Selection[res_ctr].COSTCENTER;
PlanningModel_1.updateMembers("COSTCENTER", { id: V_Selection[res_ctr].COSTCENTER, properties:{CLOSE : "A"} } );
PlanningModel_1.updateMembers("COSTCENTER", { id: V_Selection[res_ctr].COSTCENTER, properties:{ZCOMMENT : " "} } );
}
}
}
Application.showBusyIndicator("Approving ...");
Application.refreshData();
Application.hideBusyIndicator();
Reviewer can display status of Cost Centre(s) assigned to him/her, using the functionality.
Figure 7: Budget Reviewer Application, status of Cost Center where user is assigned as Reviewer.
This is implemented as below.
var allCstMembers = PlanningModel_1.getMembers("COSTCENTER");
var userid = cast(Type.string, Application.getUserInfo().id);
for (var counter = 0; counter < allCstMembers.length; counter++)
{
var prop = allCstMembers[counter].properties;
var zsubm = cast(Type.string, prop.ZSUBM);
var zrevw = cast(Type.string, prop.ZREVW);
var zclose = cast(Type.string, prop.CLOSE);
console.log(userid);
console.log(zsubm);
console.log(zclose);
if (zrevw === userid && zclose === "O")
// Reviewer but To be sumbitted
{
Dropdown_4.addItem(allCstMembers[counter].id);
console.log( allCstMembers[counter].id);
}
if ( (zrevw === userid) && (zclose === "S") )
// Reviewer but Submitted
{
Dropdown_5.addItem(allCstMembers[counter].id);
console.log( allCstMembers[counter].id);
}
if ( (zsubm === userid) && (zclose === "REJ") )
// Reviewer but Rejected
{
Dropdown_6.addItem(allCstMembers[counter].id);
console.log( allCstMembers[counter].id);
}
if ( (zsubm === userid) && (zclose === "A") )
// Reviewer but Approved
{
Dropdown_7.addItem(allCstMembers[counter].id);
console.log( allCstMembers[counter].id);
}
}
Popup_2.open();
Central Administrator reviews overall status
Finally Central administrator reviews the overall status of the Occupied Budget process by reviewing the Status Tracking Report. This would indicate areas that are behind schedule or need progress.
Figure 8: Central Admin Application, reviews status of all Cost Centers
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
User | Count |
---|---|
8 | |
5 | |
5 | |
4 | |
4 | |
4 | |
4 | |
3 | |
3 | |
3 |