1165 lines
45 KiB
JavaScript
1165 lines
45 KiB
JavaScript
app.controller('teamDetailsCalendarController', ['$scope', '$http', '$location', '$timeout', function ($scope, $http, $location, $timeout) {
|
|
$scope.CollapsedIcon = 'fa-plus-square';
|
|
$scope.NonCollapsedIcon = 'fa-minus-square';
|
|
$scope.availableExpenditures = [];
|
|
$scope.rates = [];
|
|
$scope.id;
|
|
$scope.teamId;
|
|
$scope.dataSection = "";
|
|
$scope.calendarFilters = {
|
|
IsTableModeQuantity: true,
|
|
IsViewModeMonth: true,
|
|
ScenarioId: $scope.id,
|
|
IsUOMHours: false,
|
|
ShowActuals: false,
|
|
PreferredTotalsDisplaying: false
|
|
};
|
|
$scope.typeOptions = [
|
|
{ name: 'Quantity', value: 'Quantity' },
|
|
{ name: 'Cost', value: 'Cost' }
|
|
];
|
|
$scope.reallocator = {
|
|
SourceExpCat: null,
|
|
TargetExpCat: null,
|
|
SourceWeekEnding: null,
|
|
TargetWeekEnding: null,
|
|
Percentage: 100,
|
|
ReallocateBy: $scope.typeOptions[0].value,
|
|
CurveType: 'source',
|
|
OtherCurve: null,
|
|
};
|
|
$scope.pushpuller = {
|
|
weeks: 1,
|
|
push: true,
|
|
resource: null,
|
|
startdate: null
|
|
};
|
|
|
|
// SA. ENV-815
|
|
$scope.init = function (selectedTeamId, dataSection) {
|
|
$scope.teamId = selectedTeamId;
|
|
$scope.dataSection = dataSection;
|
|
}
|
|
|
|
$scope.quickPushPull = function (push, weeks) {
|
|
for (var i = 1; i < $scope.data.ScenarioCalendar.length; i++) {
|
|
if ($scope.data.ScenarioCalendar[i].Checked)
|
|
$scope.pushPullExpCat($scope.data.ScenarioCalendar[i], i, weeks, push);
|
|
}
|
|
};
|
|
|
|
$scope.editTotal = {
|
|
ExpCat: null,
|
|
SeatsCost: $scope.typeOptions[0].value,
|
|
CurrentTotal: null,
|
|
NewTotal: null,
|
|
Curve: 'source',
|
|
OtherCurve: null,
|
|
};
|
|
|
|
$scope.formatCells = {
|
|
ExpCats: [],
|
|
SelectedExpCats: null,
|
|
StartDate: null,
|
|
EndDate: null,
|
|
DecimalPlaces: 2
|
|
};
|
|
|
|
$scope.data = null;
|
|
$scope.data2Update = {
|
|
ScenarioId: $scope.id,
|
|
ChangedExpCats: []
|
|
};
|
|
|
|
$scope.teamChanged = function (savePreferences) {
|
|
// SA. ENV-815
|
|
if (savePreferences && $scope.dataSection && ($scope.dataSection.length > 0)) {
|
|
var prefs = collectPreferences($scope.dataSection);
|
|
saveUserPagePreferences(prefs, $scope.dataSection);
|
|
}
|
|
|
|
$http.get('/Scenarios/GetTeamCapacityScenarioId?teamId=' + $scope.teamId).success(function (scenarioId) {
|
|
$scope.id = scenarioId.replace(/"/g, '');
|
|
$scope.calendarFilters.ScenarioId = $scope.id;
|
|
$http.get('/Scenarios/GetScenarioAvailableExpCategories?id=' + $scope.id).success(function (expData) {
|
|
$scope.availableExpenditures = expData;
|
|
if ($scope.availableExpenditures != null && $scope.availableExpenditures.length > 0) {
|
|
$scope.reallocator.SourceExpCat = $scope.availableExpenditures[0].Id;
|
|
$scope.reallocator.TargetExpCat = $scope.availableExpenditures.length > 1 ? $scope.availableExpenditures[1].Id : null;
|
|
$scope.reallocator.OtherCurve = $scope.availableExpenditures[0].Id;
|
|
$scope.editTotal = {
|
|
ExpCat: $scope.availableExpenditures[0].Id,
|
|
OtherCurve: $scope.availableExpenditures[0].Id,
|
|
SeatsCost: $scope.typeOptions[0].value,
|
|
Curve: 'source'
|
|
};
|
|
}
|
|
});
|
|
|
|
$scope.getRates();
|
|
$scope.getCalendar();
|
|
});
|
|
};
|
|
$scope.getRates = function () {
|
|
$http.post('/Scenarios/GetRates', { scenarioId: $scope.id, uomMode: $scope.calendarFilters.IsUOMHours }).success(function (data) {
|
|
$scope.rates = data;
|
|
}).error(function (data, status, headers, config) {
|
|
console.log("an error occurred while loading rates");
|
|
});
|
|
};
|
|
$scope.switchUOMMode = function (value) {
|
|
var newValue = value != null ? value : !$scope.calendarFilters.IsUOMHours;
|
|
$scope.calendarFilters.IsUOMHours = newValue;
|
|
$scope.getCalendar();
|
|
$scope.getRates();
|
|
};
|
|
|
|
function getExpCatById(ExpCatId) {
|
|
for (var i = 0; i < $scope.data.ScenarioCalendar.length; i++) {
|
|
if ($scope.data.ScenarioCalendar[i].ExpCatId == ExpCatId) {
|
|
return $scope.data.ScenarioCalendar[i];
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
function getResourceById(resId) {
|
|
for (var i = 0; i < $scope.data.AllResources.length; i++) {
|
|
if ($scope.data.AllResources[i].Id == resId) {
|
|
return $scope.data.AllResources[i];
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
function clearResource(expCat, resource) {
|
|
if (resource != null) {
|
|
resource.GrandTotalQuantity = 0;
|
|
|
|
var scenarioCalendarRow = null;
|
|
for (var i = 0; i < $scope.data.ScenarioCalendar.length; i++) {
|
|
if ($scope.data.ScenarioCalendar[i].ExpCatId === expCat.ExpCatId) {
|
|
scenarioCalendarRow = $scope.data.ScenarioCalendar[i];
|
|
break;
|
|
}
|
|
}
|
|
|
|
for (var i = 0; i < $scope.data.Headers.length; i++) {
|
|
expCat.RestQuantity[i] += resource.QuantityValues[i];
|
|
resource.QuantityValues[i] = 0;
|
|
|
|
applyCellChange(expCat.ExpCatId, $scope.data.Headers[i].Milliseconds, scenarioCalendarRow.ScenarioDetailIds[i],
|
|
resource.QuantityValues[i], 0, resource.Id, false, false);
|
|
}
|
|
}
|
|
}
|
|
|
|
function updateTotals(resource, colIndex, newQuantity, oldQuantity, newCost, oldCost) {
|
|
for (var i = colIndex + 1; i < $scope.data.Headers.length; i++) {
|
|
if (!$scope.data.Headers[i].IsMonth)
|
|
continue;
|
|
//update month cell
|
|
resource.QuantityValues[i] += (newQuantity - oldQuantity);
|
|
resource.GrandTotalQuantity[i] += (newQuantity - oldQuantity);
|
|
break;
|
|
}
|
|
}
|
|
|
|
function allocateResource(resource, expCat, create, allocateRest, reset) {
|
|
if (resource != null) {
|
|
resource.GrandTotalQuantity = 0;
|
|
resource.GrandTotalCost = 0;
|
|
|
|
var scenarioCalendarRow = null;
|
|
var i;
|
|
for (i = 0; i < $scope.data.ScenarioCalendar.length; i++) {
|
|
if ($scope.data.ScenarioCalendar[i].ExpCatId === expCat.ExpCatId) {
|
|
scenarioCalendarRow = $scope.data.ScenarioCalendar[i];
|
|
break;
|
|
}
|
|
}
|
|
|
|
for (i = 0; i < $scope.data.Headers.length; i++) {
|
|
var quantity = create || reset ? 0 : allocateRest ? resource.QuantityValues[i] + expCat.RestQuantity[i] : expCat.QuantityValues[i];
|
|
if (create)
|
|
resource.QuantityValues[i] = 0;
|
|
|
|
expCat.RestQuantity[i] -= quantity - resource.QuantityValues[i];
|
|
updateTotals(resource, i, quantity, resource.QuantityValues[i], 0, 0);
|
|
resource.QuantityValues[i] = quantity;
|
|
|
|
if (!$scope.data.Headers[i].IsMonth) {
|
|
resource.GrandTotalQuantity += quantity;
|
|
|
|
applyCellChange(expCat.ExpCatId, $scope.data.Headers[i].Milliseconds, scenarioCalendarRow.ScenarioDetailIds[i],
|
|
resource.QuantityValues[i], resource.CostValues[i], resource.Id, create, false);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
$scope.getCalendar = function () {
|
|
if ($scope.id === undefined || $scope.id == "" || $scope.id == "0") return;
|
|
blockUI();
|
|
$scope.data = null;
|
|
var postData = JSON.parse(JSON.stringify($scope.calendarFilters));
|
|
$http.post('/Scenarios/LoadJsonScenarioCalendar', postData).
|
|
success(function (data, status, headers, config) {
|
|
if (data.Headers.length < 1) {
|
|
unblockUI();
|
|
return;
|
|
}
|
|
$scope.data = data;
|
|
$scope.calendarFilters.IsUOMHours = data.IsUOMHours;
|
|
$scope.calendarFilters.PreferredTotalsDisplaying = data.PreferredTotalsDisplaying;
|
|
$scope.switchViewMode($scope.calendarFilters.IsViewModeMonth);
|
|
$scope.data2Update = {
|
|
ScenarioId: $scope.id,
|
|
ChangedExpCats: []
|
|
};
|
|
$scope.reallocator.SourceWeekEnding = $scope.data.Headers[0].Title;
|
|
$scope.reallocator.TargetWeekEnding = $scope.data.Headers[$scope.data.Headers.length - 2].Title;
|
|
var dec = Math.pow(10, parseInt($scope.formatCells.DecimalPlaces));
|
|
if ($scope.data.ScenarioCalendar.length > 0) {
|
|
$scope.editTotal.ExpCat = $scope.data.ScenarioCalendar[1].ExpCatId;
|
|
$scope.editTotal.SeatsCost = 'Quantity';
|
|
$scope.editTotal.CurrentTotal = Math.round($scope.data.ScenarioCalendar[1].GrandTotalQuantity * dec) / dec;
|
|
$scope.editTotal.NewTotal = null;
|
|
$scope.editTotal.Curve = 'source';
|
|
$scope.editTotal.OtherCurve = $scope.data.ScenarioCalendar[1].ExpCatId;
|
|
}
|
|
|
|
var dt = new Date($scope.data.Headers[0].Milliseconds);
|
|
$scope.formatCells.StartDate = (dt.getMonth() + 1) + "/" + dt.getDate() + "/" + dt.getFullYear();
|
|
if ($scope.data.Headers.length > 3)
|
|
dt = new Date($scope.data.Headers[$scope.data.Headers.length - 2].Milliseconds);
|
|
else
|
|
dt = new Date($scope.data.Headers[$scope.data.Headers.length - 2].Milliseconds);
|
|
$scope.formatCells.EndDate = (dt.getMonth() + 1) + "/" + dt.getDate() + "/" + dt.getFullYear();
|
|
unblockUI();
|
|
}).
|
|
error(function (data, status, headers, config) {
|
|
// called asynchronously if an error occurs
|
|
// or server returns response with an error status.
|
|
console.log("an error occurred while loading calendar");
|
|
unblockUI();
|
|
});
|
|
};
|
|
$scope.onPercentageChange = function (val) {
|
|
$scope.reallocator.Percentage = val;
|
|
};
|
|
$scope.checkEditable = function (useType) {
|
|
if (3 === useType) {
|
|
return false;
|
|
}
|
|
return true;
|
|
};
|
|
$scope.checkValue = function (data, rowId, colIndex) {
|
|
var newValue = parseFloat(data);
|
|
if (isNaN(newValue))
|
|
newValue = 0;
|
|
if (newValue < 0) {
|
|
return "Value should not be less than zero";
|
|
}
|
|
for (var i = 0; i < $scope.data.ScenarioCalendar.length; i++) {
|
|
if ($scope.data.ScenarioCalendar[i].ExpCatId === rowId) {
|
|
if ($scope.calendarFilters.IsTableModeQuantity) {
|
|
updateQuantityOrCostCell(rowId, i, colIndex, newValue, null, true);
|
|
} else {
|
|
updateQuantityOrCostCell(rowId, i, colIndex, null, newValue, false);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
//required to be false by xeditable grid
|
|
return false;
|
|
};
|
|
$scope.watchKeyInput = function (t) {
|
|
$timeout(function () {
|
|
if (t.$editable.inputEl.select)
|
|
t.$editable.inputEl.select();
|
|
else if (t.$editable.inputEl.setSelectionRange)
|
|
t.$editable.inputEl.setSelectionRange(0, t.$editable.inputEl.val().length);
|
|
}, 3);
|
|
|
|
t.$editable.inputEl.on('keydown', function (e) {
|
|
if (e.which == 9) { //when tab key is pressed
|
|
e.preventDefault();
|
|
var tab2Cell;
|
|
if (e.shiftKey) {// when shift + tab use with 'onblur' set to 'submit' for automatic submission find the parent of the editable before this one in the markup grab the editable and display it
|
|
tab2Cell = $(this).parentsUntil('table#table').prevAll(":has(.editable:visible):first").find(".editable:visible:last");
|
|
t.$form.$submit();
|
|
tab2Cell.click();
|
|
} else {// when just tab use with 'onblur' set to 'submit' for automatic submission find the parent of the editable after this one in the markup grab the editable and display it
|
|
tab2Cell = $(this).parentsUntil('table#table').nextAll(":has(.editable:visible):first").find(".editable:visible:first");
|
|
t.$form.$submit();
|
|
tab2Cell.click();
|
|
}
|
|
}
|
|
});
|
|
};
|
|
$scope.onTxtBlur = function (txt) {
|
|
txt.$form.$submit();
|
|
};
|
|
function updateQuantityOrCostCell(expCatId, rowIndex, colIndex, newQuantity, newCost, isUpdateQuantity) {
|
|
/* isUpdateQuantity - indicates whether to update by quantity or by cost.
|
|
* true - Quantity will be updated from newQuantity, Cost will be recalculated as newQuantity * rate
|
|
* false - Cost will be updated from newCost, Quantity will be recalculated as newCost / rate
|
|
* null - Quantity will be updated from newQuantity, Cost will be updated from newCost
|
|
*/
|
|
var oldQuantity = $scope.data.ScenarioCalendar[rowIndex].QuantityValues[colIndex];
|
|
var oldCost = $scope.data.ScenarioCalendar[rowIndex].CostValues[colIndex];
|
|
|
|
if (true === isUpdateQuantity) { // update quantity, recalculate cost based on exp cat rate
|
|
if (oldQuantity === newQuantity || newQuantity < 0)
|
|
return;
|
|
newCost = Math.round(newQuantity * $scope.getRate(expCatId, $scope.data.Headers[colIndex].Milliseconds) * 10000) / 10000;
|
|
} else if (false === isUpdateQuantity) { // update cost, recalculate quantity based on exp cat rate
|
|
if (oldCost === newCost || newCost < 0)
|
|
return;
|
|
newQuantity = Math.round(newCost / $scope.getRate(expCatId, $scope.data.Headers[colIndex].Milliseconds) * 10000) / 10000;
|
|
}
|
|
// update modified cell
|
|
$scope.data.ScenarioCalendar[rowIndex].RestQuantity[colIndex] += newQuantity - $scope.data.ScenarioCalendar[rowIndex].QuantityValues[colIndex];
|
|
$scope.data.ScenarioCalendar[rowIndex].CostValues[colIndex] = newCost;
|
|
$scope.data.ScenarioCalendar[rowIndex].QuantityValues[colIndex] = newQuantity;
|
|
// update row grand totals
|
|
$scope.data.ScenarioCalendar[rowIndex].GrandTotalCost += (newCost - oldCost);
|
|
$scope.data.ScenarioCalendar[rowIndex].GrandTotalQuantity += (newQuantity - oldQuantity);
|
|
// update column totals
|
|
$scope.data.ScenarioCalendar[0].CostValues[colIndex] += (newCost - oldCost);
|
|
$scope.data.ScenarioCalendar[0].QuantityValues[colIndex] += (newQuantity - oldQuantity);
|
|
// update table totals
|
|
$scope.data.ScenarioCalendar[0].GrandTotalCost += (newCost - oldCost);
|
|
$scope.data.ScenarioCalendar[0].GrandTotalQuantity += (newQuantity - oldQuantity);
|
|
// update month cell and month total cell
|
|
for (var i = colIndex + 1; i < $scope.data.Headers.length; i++) {
|
|
if (!$scope.data.Headers[i].IsMonth)
|
|
continue;
|
|
//update month cell
|
|
$scope.data.ScenarioCalendar[rowIndex].QuantityValues[i] += (newQuantity - oldQuantity);
|
|
$scope.data.ScenarioCalendar[rowIndex].CostValues[i] += (newCost - oldCost);
|
|
// update month column totals
|
|
$scope.data.ScenarioCalendar[0].CostValues[i] += (newCost - oldCost);
|
|
$scope.data.ScenarioCalendar[0].QuantityValues[i] += (newQuantity - oldQuantity);
|
|
break;
|
|
}
|
|
applyCellChange(expCatId, $scope.data.Headers[colIndex].Milliseconds, $scope.data.ScenarioCalendar[rowIndex].ScenarioDetailIds[colIndex],
|
|
$scope.data.ScenarioCalendar[rowIndex].QuantityValues[colIndex], $scope.data.ScenarioCalendar[rowIndex].CostValues[colIndex], null, false, false);
|
|
}
|
|
function applyCellChange(rowId, cellMilliseconds, cellId, cellQuantity, cellCost, resId, isAdded, isRemoved) {
|
|
var catIndex = -1;
|
|
for (var ix = 0; ix < $scope.data2Update.ChangedExpCats.length; ix++) {
|
|
if ($scope.data2Update.ChangedExpCats[ix].Id == rowId) {
|
|
catIndex = ix;
|
|
break;
|
|
}
|
|
}
|
|
if (catIndex == -1) {
|
|
$scope.data2Update.ChangedExpCats[$scope.data2Update.ChangedExpCats.length] = {
|
|
Id: rowId,
|
|
Values: [],
|
|
Resources: []
|
|
};
|
|
catIndex = $scope.data2Update.ChangedExpCats.length - 1;
|
|
}
|
|
|
|
if (resId == null) {
|
|
var dateIndex = -1;
|
|
for (var dx = 0; dx < $scope.data2Update.ChangedExpCats[catIndex].Values.length; dx++) {
|
|
if ($scope.data2Update.ChangedExpCats[catIndex].Values[dx].Id == cellId) {
|
|
dateIndex = dx;
|
|
break;
|
|
}
|
|
}
|
|
if (dateIndex == -1) {
|
|
$scope.data2Update.ChangedExpCats[catIndex].Values[$scope.data2Update.ChangedExpCats[catIndex].Values.length] = {
|
|
Id: cellId,
|
|
Milliseconds: cellMilliseconds,
|
|
Values: []
|
|
};
|
|
dateIndex = $scope.data2Update.ChangedExpCats[catIndex].Values.length - 1;
|
|
}
|
|
|
|
$scope.data2Update.ChangedExpCats[catIndex].Values[dateIndex].Cost = cellCost;
|
|
$scope.data2Update.ChangedExpCats[catIndex].Values[dateIndex].Quantity = cellQuantity;
|
|
|
|
} else {
|
|
|
|
var dateIndex = -1;
|
|
for (var dx = 0; dx < $scope.data2Update.ChangedExpCats[catIndex].Resources.length; dx++) {
|
|
if ($scope.data2Update.ChangedExpCats[catIndex].Resources[dx].Id == resId) {
|
|
dateIndex = dx;
|
|
break;
|
|
}
|
|
}
|
|
if (dateIndex == -1) {
|
|
$scope.data2Update.ChangedExpCats[catIndex].Resources[$scope.data2Update.ChangedExpCats[catIndex].Resources.length] = {
|
|
Id: resId,
|
|
Values: [],
|
|
IsAdded: isAdded,
|
|
IsRemoved: isRemoved
|
|
};
|
|
dateIndex = $scope.data2Update.ChangedExpCats[catIndex].Resources.length - 1;
|
|
if (isAdded || isRemoved)
|
|
return;
|
|
} else {
|
|
if (isRemoved) {
|
|
if ($scope.data2Update.ChangedExpCats[catIndex].Resources[dateIndex].IsAdded) {
|
|
$scope.data2Update.ChangedExpCats[catIndex].Resources.splice(dateIndex, 1);
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
|
|
var dateIndex1 = -1;
|
|
for (var dx = 0; dx < $scope.data2Update.ChangedExpCats[catIndex].Resources[dateIndex].Values.length; dx++) {
|
|
if ($scope.data2Update.ChangedExpCats[catIndex].Resources[dateIndex].Values[dx].Id == cellId) {
|
|
dateIndex1 = dx;
|
|
break;
|
|
}
|
|
}
|
|
if (dateIndex1 == -1) {
|
|
$scope.data2Update.ChangedExpCats[catIndex].Resources[dateIndex].Values[$scope.data2Update.ChangedExpCats[catIndex].Resources[dateIndex].Values.length] = {
|
|
Id: cellId,
|
|
Milliseconds: cellMilliseconds,
|
|
Values: []
|
|
};
|
|
dateIndex1 = $scope.data2Update.ChangedExpCats[catIndex].Resources[dateIndex].Values.length - 1;
|
|
}
|
|
//$scope.data2Update.ChangedExpCats[catIndex].Resources[dateIndex].Values[dateIndex1].Cost = cellCost;
|
|
$scope.data2Update.ChangedExpCats[catIndex].Resources[dateIndex].Values[dateIndex1].Quantity = cellQuantity;
|
|
}
|
|
}
|
|
$scope.saveChanges = function () {
|
|
blockUI();
|
|
var postData = JSON.parse(JSON.stringify($scope.data2Update));
|
|
postData.ScenarioFilters = $scope.calendarFilters;
|
|
$http.post('/Scenarios/SaveChanges', postData).
|
|
success(function (data, status, headers, config) {
|
|
//$scope.data = data;
|
|
$scope.data2Update = {
|
|
ScenarioId: $scope.id,
|
|
ChangedExpCats: []
|
|
};
|
|
if (typeof InitGraph === 'function')
|
|
InitGraph($scope.teamId);
|
|
if (typeof LoadGraphData === 'function')
|
|
LoadGraphData();
|
|
unblockUI();
|
|
//var tab = $("#uidemo-tabs-default-demo li.active a").attr("href");
|
|
//var retUrl = window.location.href;
|
|
//if (retUrl.indexOf("&tab=") > 0) {
|
|
// retUrl = retUrl.substr(0, retUrl.indexOf("&tab="));
|
|
//}
|
|
|
|
//window.location.href = retUrl + "&tab=" + tab.replace("#", "");
|
|
if (typeof onDataSaved === 'function')
|
|
onDataSaved();
|
|
}).
|
|
error(function (data, status, headers, config) {
|
|
console.log("an error occurred while saving calendar changes");
|
|
unblockUI();
|
|
});
|
|
};
|
|
$scope.getRate = function (expCatId, date) {
|
|
if ($scope.rates && $scope.rates.length > 0) {
|
|
for (var i = 0; i < $scope.rates.length; i++) {
|
|
if ($scope.rates[i].expCatId === expCatId) {
|
|
if ($scope.rates[i].rateValues && $scope.rates[i].rateValues.length > 0) {
|
|
for (var rIndex = 0; rIndex < $scope.rates[i].rateValues.length; rIndex++) {
|
|
if (date <= $scope.rates[i].rateValues[rIndex].weekEndDate)
|
|
return $scope.rates[i].rateValues[rIndex].rateValue;
|
|
}
|
|
return $scope.rates[i].rateValues[$scope.rates[i].rateValues.length - 1].rateValue;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return 0;
|
|
};
|
|
$scope.graphData = [];
|
|
$scope.maxGraphValue = 0;
|
|
$scope.showGraph = function () {
|
|
// prepare data
|
|
$scope.maxGraphValue = 0;
|
|
$scope.graphData = [];
|
|
|
|
var startDate = new Date($scope.data.StartDate.replace('/Date(', '').replace(')/', '') * 1);
|
|
var endDate = new Date($scope.data.EndDate.replace('/Date(', '').replace(')/', '') * 1);
|
|
var days = (endDate - startDate) / (1000 * 60 * 60 * 24);
|
|
var i;
|
|
|
|
for (i = 1; i < $scope.data.ScenarioCalendar.length; i++) {
|
|
// skip this row if it is not checked
|
|
if (!$scope.data.ScenarioCalendar[i].Checked)
|
|
continue;
|
|
|
|
var expCatData = new Array();
|
|
for (var colIndex = 0; colIndex < $scope.data.Headers.length; colIndex++) {
|
|
if ($scope.data.Headers[colIndex].IsMonth)
|
|
continue;
|
|
expCatData[expCatData.length] = [$scope.data.Headers[colIndex].Milliseconds, $scope.data.ScenarioCalendar[i].QuantityValues[colIndex]];
|
|
if (true !== $scope.calendarFilters.IsTableModeQuantity) {
|
|
expCatData[expCatData.length - 1][1] = $scope.data.ScenarioCalendar[i].CostValues[colIndex];
|
|
}
|
|
if (expCatData[expCatData.length - 1][1] > $scope.maxGraphValue)
|
|
$scope.maxGraphValue = expCatData[expCatData.length - 1][1];
|
|
expCatData[expCatData.length - 1][1] = expCatData[expCatData.length - 1][1].toFixed(2);
|
|
}
|
|
$scope.graphData[$scope.graphData.length] = {
|
|
label: $scope.data.ScenarioCalendar[i].ExpCatName,
|
|
data: expCatData,
|
|
lines: { show: true, fill: true, steps: false },
|
|
filledPoints: true,
|
|
stack: true
|
|
};
|
|
}
|
|
|
|
// show graph
|
|
$timeout(function () {
|
|
$scope.initGraph()
|
|
});
|
|
};
|
|
$scope.initGraph = function () {
|
|
// Init Chart
|
|
$('#DetailsGraphContainer').html('<div id="divDetailsGraph"></div>');
|
|
$("#modalGraph").modal("show");
|
|
|
|
// SA. ENV-574
|
|
var C_MAX_GRAPH_TICK_LABELS = 8;
|
|
var maxSeriePoints = 0;
|
|
|
|
if ($scope.graphData && $scope.graphData.length > 0) {
|
|
|
|
$.each($scope.graphData, function (index, data) {
|
|
if (data.data && (data.data.length > 0)) {
|
|
maxSeriePoints = Math.max(maxSeriePoints, data.data.length);
|
|
}
|
|
});
|
|
}
|
|
|
|
var tickStep = Math.round((maxSeriePoints / 4) / C_MAX_GRAPH_TICK_LABELS);
|
|
tickStep = (tickStep > 0) ? tickStep : 1;
|
|
|
|
$('#divDetailsGraph').pixelPlot($scope.graphData, {
|
|
series: {
|
|
points: {
|
|
show: false
|
|
},
|
|
lines: {
|
|
show: true,
|
|
}
|
|
},
|
|
xaxis: {
|
|
mode: "time",
|
|
tickSize: [tickStep, "month"]
|
|
}
|
|
}, {
|
|
height: 405,
|
|
width: 405,
|
|
tooltipText: "y + ' units at ' + (new Date(x)).toString()"
|
|
});
|
|
};
|
|
$scope.anyChecked = function () {
|
|
if ($scope.data == null || $scope.data.ScenarioCalendar == null)
|
|
return false;
|
|
for (var i = 1; i < $scope.data.ScenarioCalendar.length; i++) {
|
|
if ($scope.data.ScenarioCalendar[i].Checked)
|
|
return true;
|
|
}
|
|
return false;
|
|
};
|
|
$scope.checkedExpenditures = [];
|
|
$scope.collectchecked = function (obj) {
|
|
$scope.checkedExpenditures = [];
|
|
if ($scope.data == null || $scope.data.ScenarioCalendar == null)
|
|
return;
|
|
|
|
for (var i = 1; i < $scope.data.ScenarioCalendar.length; i++) {
|
|
if ($scope.data.ScenarioCalendar[i].Checked ||
|
|
(obj != null && !obj.Checked && obj.ExpCatId == $scope.data.ScenarioCalendar[i].ExpCatId))
|
|
$scope.checkedExpenditures.push($scope.data.ScenarioCalendar[i]);
|
|
}
|
|
};
|
|
|
|
$scope.resizeFreezAng = function () {
|
|
setTimeout(function () {
|
|
resizeFreez();
|
|
}, 0);
|
|
};
|
|
|
|
$scope.takeAll = function (resId, expCatId) {
|
|
if (confirm("Are you sure you want to re-assign category quantity and assign everything to this resource?")) {
|
|
var expCat = getExpCatById(expCatId);
|
|
var resource = null;
|
|
for (var i = 0; i < expCat.Resources.length; i++) {
|
|
|
|
if (expCat.Resources[i].Id == resId) {
|
|
resource = expCat.Resources[i];
|
|
} else {
|
|
clearResource(expCat, expCat.Resources[i]);
|
|
}
|
|
}
|
|
allocateResource(resource, expCat, false, false, false);
|
|
}
|
|
};
|
|
$scope.takeRemaining = function (resId, expCatId) {
|
|
var expCat = getExpCatById(expCatId);
|
|
if (expCat != null) {
|
|
for (var i = 0; i < expCat.Resources.length; i++) {
|
|
if (expCat.Resources[i].Id == resId) {
|
|
allocateResource(expCat.Resources[i], expCat, false, true, false);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
};
|
|
$scope.zeroResource = function (resId, expCatId) {
|
|
if (confirm("Are you sure you want fill this resource quantities with 0s?")) {
|
|
var expCat = getExpCatById(expCatId);
|
|
for (var i = 0; i < expCat.Resources.length; i++) {
|
|
if (expCat.Resources[i].Id == resId) {
|
|
allocateResource(expCat.Resources[i], expCat, false, false, true);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
$scope.assignResource = function (resId, expCatId, $event) {
|
|
if (resId == null || expCatId == null)
|
|
return;
|
|
|
|
var resource = getResourceById(resId);
|
|
if (resource != null) {
|
|
|
|
var expCat = getExpCatById(expCatId);
|
|
if (expCat != null) {
|
|
for (var j = 0; j < expCat.Resources.length; j++) {
|
|
if (expCat.Resources[j].Id == resource.Id) {
|
|
alert("The " + resource.Name + " has been assigned to the " + expCat.Name);
|
|
break;
|
|
}
|
|
}
|
|
resource = { 'Id': resource.Id, 'Name': resource.Name, 'QuantityValues': new Array($scope.data.Headers.length), 'CostValues': new Array($scope.data.Headers.length) };
|
|
}
|
|
|
|
allocateResource(resource, expCat, true, false, false);
|
|
expCat.Resources.push(resource);
|
|
var tr = $($event.target).parentsUntil('table').last().parent().find('thead tr:first');
|
|
console.log("tr: " + $(tr).html());
|
|
var thName = tr.find('th:eq(1)');
|
|
console.log("thName: " + $(thName).html());
|
|
resource.width = thName.width() + 'px';
|
|
var thTot = tr.find('th:eq(2)');
|
|
console.log("thTot: " + $(thTot).html());
|
|
resource.left = thTot.css('left');
|
|
$scope.resizeFreezAng();
|
|
}
|
|
};
|
|
$scope.removeResource = function (resId, expCatId) {
|
|
if (confirm("Are you sure you want to remove this resource?")) {
|
|
var expCat = getExpCatById(expCatId);
|
|
for (var i = 0; i < expCat.Resources.length; i++) {
|
|
if (expCat.Resources[i].Id == resId) {
|
|
expCat.Resources.splice(i, 1);
|
|
applyCellChange(expCatId, 0, 0, 0, 0, resId, false, true);
|
|
$scope.resizeFreezAng();
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
};
|
|
$scope.checkResourceValue = function (data, expCatId, resId, colIndex) {
|
|
var newValue = parseFloat(data);
|
|
if (newValue < 0) {
|
|
return "Value should not be less than zero";
|
|
}
|
|
|
|
var expCat = getExpCatById(expCatId);
|
|
var resource = null;
|
|
for (var i = 0; i < expCat.Resources.length; i++) {
|
|
if (expCat.Resources[i].Id == resId) {
|
|
resource = expCat.Resources[i];
|
|
break;
|
|
}
|
|
}
|
|
|
|
var scenarioCalendarRow = null;
|
|
for (var i = 0; i < $scope.data.ScenarioCalendar.length; i++) {
|
|
if ($scope.data.ScenarioCalendar[i].ExpCatId === expCatId) {
|
|
scenarioCalendarRow = $scope.data.ScenarioCalendar[i];
|
|
break;
|
|
}
|
|
}
|
|
if (expCat != null && resource != null) {
|
|
if ($scope.calendarFilters.IsTableModeQuantity) {
|
|
resource.GrandTotalQuantity += newValue - resource.QuantityValues[colIndex];
|
|
updateTotals(resource, colIndex, newValue, resource.QuantityValues[colIndex], 0, 0);
|
|
expCat.RestQuantity[colIndex] -= newValue - resource.QuantityValues[colIndex];
|
|
resource.QuantityValues[colIndex] = newValue;
|
|
}
|
|
|
|
applyCellChange(expCatId, $scope.data.Headers[colIndex].Milliseconds, scenarioCalendarRow.ScenarioDetailIds[colIndex],
|
|
resource.QuantityValues[colIndex], 0, resId, false, false);
|
|
}
|
|
//required to be false by xeditable grid
|
|
return false;
|
|
};
|
|
$scope.getExpCatResources = function (expCat) {
|
|
var resources = [];
|
|
for (var i = 0; i < $scope.data.AllResources.length; i++) {
|
|
if ($scope.data.AllResources[i].ExpedentureCategoryId == expCat.ExpCatId && $scope.data.AllResources[i] && $scope.data.AllResources[i].IsActiveEmployee) {
|
|
var isFound = false;
|
|
for (var j = 0; j < expCat.Resources.length; j++) {
|
|
if (expCat.Resources[j].Id == $scope.data.AllResources[i].Id) {
|
|
isFound = true;
|
|
break;
|
|
}
|
|
}
|
|
if (!isFound)
|
|
resources.push($scope.data.AllResources[i]);
|
|
}
|
|
}
|
|
|
|
return resources;
|
|
};
|
|
$scope.checkAll = function () {
|
|
$scope.checkedExpenditures = [];
|
|
var checked = !$scope.data.ScenarioCalendar[0].Checked;
|
|
if ($scope.data == null || $scope.data.ScenarioCalendar == null)
|
|
return;
|
|
for (var i = 1; i < $scope.data.ScenarioCalendar.length; i++) {
|
|
$scope.data.ScenarioCalendar[i].Checked = checked;
|
|
if (checked)
|
|
$scope.checkedExpenditures.push($scope.data.ScenarioCalendar[i]);
|
|
}
|
|
};
|
|
$scope.switchViewMode = function (value) {
|
|
var newValue = value != null ? value : !$scope.calendarFilters.IsViewModeMonth;
|
|
for (var i = 0; i < $scope.data.Headers.length; i++) {
|
|
if ($scope.data.Headers[i].IsMonth) {
|
|
$scope.data.Headers[i].Collapsed = newValue;
|
|
$scope.data.Headers[i].Show = newValue;
|
|
$scope.data.Headers[i].CollapsedClass = newValue ? $scope.CollapsedIcon : $scope.NonCollapsedIcon;
|
|
} else {
|
|
$scope.data.Headers[i].Collapsed = newValue;
|
|
$scope.data.Headers[i].Show = !newValue;
|
|
}
|
|
}
|
|
$scope.resizeFreezAng();
|
|
};
|
|
$scope.anyUpdated = function () {
|
|
return ($scope.data2Update && $scope.data2Update.ChangedExpCats && $scope.data2Update.ChangedExpCats.length > 0);
|
|
};
|
|
$scope.reallocateResource = function () {
|
|
var sourceQuantity = 0;
|
|
var sourceCost = 0;
|
|
if ($scope.reallocator.Percentage == 0) {
|
|
alert('Percentage is 0, nothing to reallocate.');
|
|
return;
|
|
}
|
|
var sourceRowIndex, targetRowIndex, curveRowIndex, sourceColIndex, targetColIndex;
|
|
var i;
|
|
for (i = 0; i < $scope.data.ScenarioCalendar.length; i++) {
|
|
if ($scope.data.ScenarioCalendar[i].ExpCatId === $scope.reallocator.SourceExpCat)
|
|
sourceRowIndex = i;
|
|
if ($scope.data.ScenarioCalendar[i].ExpCatId === $scope.reallocator.TargetExpCat)
|
|
targetRowIndex = i;
|
|
if ($scope.reallocator.CurveType == 'other' && $scope.data.ScenarioCalendar[i].ExpCatId === $scope.reallocator.OtherCurve)
|
|
curveRowIndex = i;
|
|
}
|
|
if (sourceRowIndex == targetRowIndex) {
|
|
alert('Cant reallocate within same expenditure category.');
|
|
return;
|
|
}
|
|
for (i = 0; i < $scope.data.Headers.length; i++) {
|
|
if ($scope.data.Headers[i].IsMonth)
|
|
continue;
|
|
if ($scope.data.Headers[i].Title === $scope.reallocator.SourceWeekEnding)
|
|
sourceColIndex = i;
|
|
if ($scope.data.Headers[i].Title === $scope.reallocator.TargetWeekEnding)
|
|
targetColIndex = i;
|
|
}
|
|
if (sourceColIndex == null || targetColIndex == null) {
|
|
alert('Please check selected dates to match valid week endings.');
|
|
return;
|
|
} else if (targetColIndex < sourceColIndex) {
|
|
alert('Please select To week ending date later than From week ending date.');
|
|
return;
|
|
}
|
|
|
|
var sourceSumCost = 0, sourceSumQuantity = 0, targetSumCost = 0, targetSumQuantity = 0, otherSumCost = 0, otherSumQuantity = 0;
|
|
var percentageMult = $scope.reallocator.Percentage / 100;
|
|
for (i = sourceColIndex; i <= targetColIndex ; i++) {
|
|
if ($scope.data.Headers[i].IsMonth)
|
|
continue;
|
|
sourceSumQuantity += $scope.data.ScenarioCalendar[sourceRowIndex].QuantityValues[i];
|
|
sourceSumCost += $scope.data.ScenarioCalendar[sourceRowIndex].CostValues[i];
|
|
targetSumQuantity += $scope.data.ScenarioCalendar[targetRowIndex].QuantityValues[i];
|
|
targetSumCost += $scope.data.ScenarioCalendar[targetRowIndex].CostValues[i];
|
|
if ($scope.reallocator.CurveType == 'other') {
|
|
otherSumQuantity += $scope.data.ScenarioCalendar[curveRowIndex].QuantityValues[i];
|
|
otherSumCost += $scope.data.ScenarioCalendar[curveRowIndex].CostValues[i];
|
|
}
|
|
}
|
|
|
|
if ((sourceSumQuantity == 0 || sourceSumCost == 0)) { alert('Source is zero, nothing to reallocate.'); return; }
|
|
if ((targetSumQuantity == 0 || targetSumCost == 0) && $scope.reallocator.CurveType == 'target') { alert('Target curve is zero. Please select a different curve.'); return; }
|
|
if ((otherSumQuantity == 0 || otherSumCost == 0) && $scope.reallocator.CurveType == 'other') { alert('Different curve is zero. Please select a another curve.'); return; }
|
|
var quantity2Move = 0;
|
|
var cost2Move = 0;
|
|
for (i = sourceColIndex; i <= targetColIndex ; i++) {
|
|
if ($scope.data.Headers[i].IsMonth)
|
|
continue;
|
|
if ($scope.reallocator.CurveType == 'source') {
|
|
sourceQuantity = $scope.data.ScenarioCalendar[sourceRowIndex].QuantityValues[i];
|
|
sourceCost = $scope.data.ScenarioCalendar[sourceRowIndex].CostValues[i];
|
|
// update column values in model
|
|
if ($scope.reallocator.ReallocateBy == 'Quantity') {
|
|
updateQuantityOrCostCell($scope.reallocator.SourceExpCat, sourceRowIndex, i,
|
|
sourceQuantity * (1 - percentageMult), sourceCost * (1 - percentageMult), null);
|
|
updateQuantityOrCostCell($scope.reallocator.TargetExpCat, targetRowIndex, i,
|
|
$scope.data.ScenarioCalendar[targetRowIndex].QuantityValues[i] + sourceQuantity * percentageMult, null, true);
|
|
} else {
|
|
updateQuantityOrCostCell($scope.reallocator.SourceExpCat, sourceRowIndex, i,
|
|
sourceQuantity * (1 - percentageMult), sourceCost * (1 - percentageMult), null);
|
|
updateQuantityOrCostCell($scope.reallocator.TargetExpCat, targetRowIndex, i,
|
|
null, $scope.data.ScenarioCalendar[targetRowIndex].CostValues[i] + sourceCost * percentageMult, false);
|
|
}
|
|
}
|
|
else if ($scope.reallocator.CurveType == 'target') {
|
|
sourceQuantity = $scope.data.ScenarioCalendar[sourceRowIndex].QuantityValues[i];
|
|
sourceCost = $scope.data.ScenarioCalendar[sourceRowIndex].CostValues[i];
|
|
quantity2Move = (percentageMult * sourceSumQuantity) * ($scope.data.ScenarioCalendar[targetRowIndex].QuantityValues[i] / targetSumQuantity);
|
|
cost2Move = (percentageMult * sourceSumCost) * ($scope.data.ScenarioCalendar[targetRowIndex].CostValues[i] / targetSumCost);
|
|
// update column values in model
|
|
if ($scope.reallocator.ReallocateBy == 'Quantity') {
|
|
// we cannot reallocate more than source quantity
|
|
if (quantity2Move > $scope.data.ScenarioCalendar[sourceRowIndex].QuantityValues[i])
|
|
quantity2Move = $scope.data.ScenarioCalendar[sourceRowIndex].QuantityValues[i];
|
|
if (quantity2Move > 0) {
|
|
updateQuantityOrCostCell($scope.reallocator.SourceExpCat, sourceRowIndex, i,
|
|
sourceQuantity - quantity2Move, null, true);
|
|
updateQuantityOrCostCell($scope.reallocator.TargetExpCat, targetRowIndex, i,
|
|
$scope.data.ScenarioCalendar[targetRowIndex].QuantityValues[i] + quantity2Move, null, true);
|
|
}
|
|
} else {
|
|
// we cannot reallocate more than source quantity
|
|
if (cost2Move > $scope.data.ScenarioCalendar[sourceRowIndex].CostValues[i])
|
|
cost2Move = $scope.data.ScenarioCalendar[sourceRowIndex].CostValues[i];
|
|
if (cost2Move > 0) {
|
|
updateQuantityOrCostCell($scope.reallocator.SourceExpCat, sourceRowIndex, i,
|
|
null, sourceCost - cost2Move, false);
|
|
updateQuantityOrCostCell($scope.reallocator.TargetExpCat, targetRowIndex, i,
|
|
null, $scope.data.ScenarioCalendar[targetRowIndex].CostValues[i] + cost2Move, false);
|
|
}
|
|
}
|
|
}
|
|
else if ($scope.reallocator.CurveType == 'other') {
|
|
sourceQuantity = $scope.data.ScenarioCalendar[sourceRowIndex].QuantityValues[i];
|
|
sourceCost = $scope.data.ScenarioCalendar[sourceRowIndex].CostValues[i];
|
|
quantity2Move = (percentageMult * sourceSumQuantity) * ($scope.data.ScenarioCalendar[curveRowIndex].QuantityValues[i] / otherSumQuantity);
|
|
cost2Move = (percentageMult * sourceSumCost) * ($scope.data.ScenarioCalendar[curveRowIndex].CostValues[i] / otherSumCost);
|
|
// update column values in model
|
|
if ($scope.reallocator.ReallocateBy == 'Quantity') {
|
|
// we cannot reallocate more than source quantity
|
|
if (quantity2Move > $scope.data.ScenarioCalendar[sourceRowIndex].QuantityValues[i])
|
|
quantity2Move = $scope.data.ScenarioCalendar[sourceRowIndex].QuantityValues[i];
|
|
if (quantity2Move > 0) {
|
|
updateQuantityOrCostCell($scope.reallocator.SourceExpCat, sourceRowIndex, i,
|
|
sourceQuantity - quantity2Move, null, true);
|
|
updateQuantityOrCostCell($scope.reallocator.TargetExpCat, targetRowIndex, i,
|
|
$scope.data.ScenarioCalendar[targetRowIndex].QuantityValues[i] + quantity2Move, null, true);
|
|
}
|
|
} else {
|
|
// we cannot reallocate more than source quantity
|
|
if (cost2Move > $scope.data.ScenarioCalendar[sourceRowIndex].CostValues[i])
|
|
cost2Move = $scope.data.ScenarioCalendar[sourceRowIndex].CostValues[i];
|
|
if (cost2Move > 0) {
|
|
updateQuantityOrCostCell($scope.reallocator.SourceExpCat, sourceRowIndex, i,
|
|
null, sourceCost - cost2Move, false);
|
|
updateQuantityOrCostCell($scope.reallocator.TargetExpCat, targetRowIndex, i,
|
|
null, $scope.data.ScenarioCalendar[targetRowIndex].CostValues[i] + cost2Move, false);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
$("#reallocator").modal("hide");
|
|
};
|
|
$scope.pushPull = function () {
|
|
|
|
for (var i = 1; i < $scope.data.ScenarioCalendar.length; i++) {
|
|
if ($scope.data.ScenarioCalendar[i].Checked)
|
|
$scope.pushPullExpCat($scope.data.ScenarioCalendar[i], i, $scope.pushpuller.weeks, $scope.pushpuller.push);
|
|
}
|
|
$("#push_pull").modal("hide");
|
|
};
|
|
$scope.pushPullExpCat = function (data, sourceRowIndex, weeks, push) {
|
|
var oldQuantity = 0;
|
|
var oldCost = 0;
|
|
var i;
|
|
var j;
|
|
var handledWeeks = 0;
|
|
var leftMargin; // index of the cell next to the last modified cell from the left side of the table. E.g. if we push 2 weeks, then it will be [2], or [3] if there is only one week in the first month
|
|
var rightMargin; // index of the cell previous to the first modified cell from the right side of the table. E.g. if we pull 2 weeks, then it will be [length-3], or [length-4] if there is only one week in the last month
|
|
for (i = 0; i < $scope.data.Headers.length; i++) {
|
|
if ($scope.data.Headers[i].IsMonth)
|
|
continue;
|
|
handledWeeks++;
|
|
if (handledWeeks == weeks) {
|
|
leftMargin = i + 1;
|
|
break;
|
|
}
|
|
}
|
|
handledWeeks = 0;
|
|
for (i = $scope.data.Headers.length - 1; i >= 0; i--) {
|
|
if ($scope.data.Headers[i].IsMonth)
|
|
continue;
|
|
if (i < leftMargin) {
|
|
alert('Error occurred while calculating right margin of required changes.');
|
|
return;
|
|
}
|
|
handledWeeks++;
|
|
if (handledWeeks == weeks) {
|
|
rightMargin = i - 1;
|
|
break;
|
|
}
|
|
}
|
|
if (push) {
|
|
for (i = $scope.data.Headers.length - 1; i >= 0; i--) {
|
|
if ($scope.data.Headers[i].IsMonth)
|
|
continue;
|
|
oldQuantity = 0;
|
|
oldCost = 0;
|
|
|
|
if (i < leftMargin) {
|
|
if ($scope.calendarFilters.IsTableModeQuantity) {
|
|
updateQuantityOrCostCell(data.ExpCatId, sourceRowIndex, i, 0, null, true);
|
|
} else {
|
|
updateQuantityOrCostCell(data.ExpCatId, sourceRowIndex, i, null, 0, false);
|
|
}
|
|
} else { //copy data from [i+weeks] cell
|
|
handledWeeks = 0;
|
|
for (j = i - 1; j >= 0; j--) {
|
|
if ($scope.data.Headers[j].IsMonth)
|
|
continue;
|
|
handledWeeks++;
|
|
if (handledWeeks == weeks) {
|
|
oldQuantity = data.QuantityValues[j];
|
|
oldCost = data.CostValues[j];
|
|
break;
|
|
}
|
|
}
|
|
if ($scope.calendarFilters.IsTableModeQuantity) {
|
|
updateQuantityOrCostCell(data.ExpCatId, sourceRowIndex, i, oldQuantity, null, true);
|
|
} else {
|
|
updateQuantityOrCostCell(data.ExpCatId, sourceRowIndex, i, null, oldCost, false);
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
for (i = 0; i < $scope.data.Headers.length; i++) {
|
|
if ($scope.data.Headers[i].IsMonth)
|
|
continue;
|
|
oldQuantity = 0;
|
|
oldCost = 0;
|
|
|
|
if (i <= rightMargin) { //copy data from [i+weeks] cell
|
|
handledWeeks = 0;
|
|
for (j = i + 1; j < $scope.data.Headers.length; j++) {
|
|
if ($scope.data.Headers[j].IsMonth)
|
|
continue;
|
|
handledWeeks++;
|
|
if (handledWeeks == weeks) {
|
|
oldQuantity = data.QuantityValues[j];
|
|
oldCost = data.CostValues[j];
|
|
break;
|
|
}
|
|
}
|
|
if ($scope.calendarFilters.IsTableModeQuantity) {
|
|
updateQuantityOrCostCell(data.ExpCatId, sourceRowIndex, i, oldQuantity, null, true);
|
|
} else {
|
|
updateQuantityOrCostCell(data.ExpCatId, sourceRowIndex, i, null, oldCost, false);
|
|
}
|
|
} else if (i > rightMargin) {
|
|
if ($scope.calendarFilters.IsTableModeQuantity) {
|
|
updateQuantityOrCostCell(data.ExpCatId, sourceRowIndex, i, 0, null, true);
|
|
} else {
|
|
updateQuantityOrCostCell(data.ExpCatId, sourceRowIndex, i, null, 0, false);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
};
|
|
$scope.editTotalFunc = function () {
|
|
var oldQuantity = 0;
|
|
var oldCost = 0;
|
|
if ($scope.editTotal.CurrentTotal == $scope.editTotal.NewTotal && $scope.editTotal.Curve != 'other') {
|
|
$("#editTotal").modal("hide");
|
|
return;
|
|
}
|
|
var changeMult = $scope.editTotal.NewTotal / $scope.editTotal.CurrentTotal;
|
|
var sourceRowIndex = null;
|
|
var curveRowIndex = null;
|
|
var i;
|
|
for (i = 0; i < $scope.data.ScenarioCalendar.length; i++) {
|
|
if ($scope.data.ScenarioCalendar[i].ExpCatId === $scope.editTotal.ExpCat)
|
|
sourceRowIndex = i;
|
|
if ($scope.data.ScenarioCalendar[i].ExpCatId === $scope.editTotal.OtherCurve)
|
|
curveRowIndex = i;
|
|
}
|
|
if (null === sourceRowIndex) {
|
|
alert('Cannot find expenditure category to update.');
|
|
return;
|
|
}
|
|
if (null === curveRowIndex) {
|
|
alert('Cannot find expenditure category to use as a curve.');
|
|
return;
|
|
}
|
|
|
|
var sourceSumCost = 0, sourceSumQuantity = 0, curveSumCost = 0, curveSumQuantity = 0;
|
|
for (i = 0; i < $scope.data.Headers.length ; i++) {
|
|
if ($scope.data.Headers[i].IsMonth)
|
|
continue;
|
|
sourceSumQuantity += $scope.data.ScenarioCalendar[sourceRowIndex].QuantityValues[i];
|
|
sourceSumCost += $scope.data.ScenarioCalendar[sourceRowIndex].CostValues[i];
|
|
curveSumQuantity += $scope.data.ScenarioCalendar[curveRowIndex].QuantityValues[i];
|
|
curveSumCost += $scope.data.ScenarioCalendar[curveRowIndex].CostValues[i];
|
|
}
|
|
|
|
if (curveSumQuantity == 0 || sourceSumQuantity == 0) {
|
|
changeMult = $scope.editTotal.NewTotal;
|
|
}
|
|
|
|
//console.log("sourceSumQuantity: " + sourceSumQuantity + "; curveSumQuantity: " + curveSumQuantity + "; changeMult: " + changeMult);
|
|
var numberOfWeeks = 0;
|
|
for (i = 0; i < $scope.data.Headers.length; i++) {
|
|
if ($scope.data.Headers[i].IsMonth)
|
|
continue;
|
|
numberOfWeeks++;
|
|
}
|
|
if (curveSumQuantity > 0)
|
|
for (i = 0; i < $scope.data.Headers.length; i++) {
|
|
if ($scope.data.Headers[i].IsMonth)
|
|
continue;
|
|
oldQuantity = $scope.data.ScenarioCalendar[sourceRowIndex].QuantityValues[i];
|
|
oldCost = $scope.data.ScenarioCalendar[sourceRowIndex].CostValues[i];
|
|
if ($scope.editTotal.Curve == 'other') {
|
|
var targetQuantity = $scope.data.ScenarioCalendar[curveRowIndex].QuantityValues[i];
|
|
var targetCost = $scope.data.ScenarioCalendar[curveRowIndex].CostValues[i];
|
|
if (sourceSumQuantity != 0)
|
|
updateQuantityOrCostCell($scope.editTotal.ExpCat, sourceRowIndex, i, Math.abs(sourceSumQuantity * (targetQuantity / curveSumQuantity) * changeMult), Math.abs(sourceSumCost * (targetCost / curveSumCost) * changeMult), null);
|
|
else
|
|
updateQuantityOrCostCell($scope.editTotal.ExpCat, sourceRowIndex, i, Math.abs((targetQuantity / curveSumQuantity) * changeMult), Math.abs(sourceSumCost * (targetCost / curveSumCost) * changeMult), null);
|
|
}
|
|
else updateQuantityOrCostCell($scope.editTotal.ExpCat, sourceRowIndex, i, Math.abs(oldQuantity * changeMult), Math.abs(oldCost * changeMult), null);
|
|
}
|
|
else {
|
|
for (i = 0; i < $scope.data.Headers.length; i++) {
|
|
if ($scope.data.Headers[i].IsMonth)
|
|
continue;
|
|
updateQuantityOrCostCell($scope.editTotal.ExpCat, sourceRowIndex, i, Math.abs(changeMult / numberOfWeeks), Math.abs(changeMult * $scope.getRate($scope.editTotal.ExpCat, $scope.data.Headers[i].Milliseconds) / numberOfWeeks), null);
|
|
}
|
|
}
|
|
$scope.editTotal.CurrentTotal = $scope.editTotal.NewTotal;
|
|
$("#editTotal").modal("hide");
|
|
};
|
|
$scope.recalcTotal = function () {
|
|
for (var i = 0; i < $scope.data.ScenarioCalendar.length; i++) {
|
|
if ($scope.data.ScenarioCalendar[i].ExpCatId === $scope.editTotal.ExpCat) {
|
|
if ($scope.editTotal.SeatsCost == 'Quantity')
|
|
$scope.editTotal.CurrentTotal = $scope.data.ScenarioCalendar[i].GrandTotalQuantity;
|
|
else
|
|
$scope.editTotal.CurrentTotal = $scope.data.ScenarioCalendar[i].GrandTotalCost;
|
|
break;
|
|
}
|
|
}
|
|
};
|
|
$scope.isOtherSelectedReallocator = function () {
|
|
return $scope.reallocator.CurveType == 'other';
|
|
};
|
|
$scope.isOtherSelectedTotal = function () {
|
|
return $scope.editTotal.Curve == 'other';
|
|
};
|
|
$scope.prefillFormatCells = function () {
|
|
$scope.formatCells.ExpCats = [];
|
|
for (var i = 1; i < $scope.data.ScenarioCalendar.length; i++) {
|
|
// skip this row if it is not checked
|
|
if (!$scope.data.ScenarioCalendar[i].Checked)
|
|
continue;
|
|
$scope.formatCells.ExpCats[$scope.formatCells.ExpCats.length] = {
|
|
Id: $scope.data.ScenarioCalendar[i].ExpCatId,
|
|
Name: $scope.data.ScenarioCalendar[i].ExpCatName
|
|
};
|
|
}
|
|
if ($scope.formatCells.ExpCats.length > 0)
|
|
$scope.formatCells.SelectedExpCats = $scope.formatCells.ExpCats[0].Id;
|
|
};
|
|
$scope.submitFormatCells = function () {
|
|
if ($scope.data.ScenarioType === 9)
|
|
return false;
|
|
if (isNaN($scope.formatCells.DecimalPlaces)) {
|
|
alert("Decimal Places is not set.");
|
|
return false;
|
|
}
|
|
var colIndexes2Update = [];
|
|
// gather column indexes which we're going to update
|
|
var dtStart = $scope.formatCells.StartDate.split('/');
|
|
var msStart = new Date(dtStart[2], dtStart[0] - 1, dtStart[1]).getTime();
|
|
var dtEnd = $scope.formatCells.EndDate.split('/');
|
|
var msEnd = new Date(dtEnd[2], dtEnd[0] - 1, dtEnd[1]).getTime();
|
|
for (var headerIndex = 0; headerIndex < $scope.data.Headers.length; headerIndex++) {
|
|
if ($scope.data.Headers[headerIndex].IsMonth)
|
|
continue;
|
|
if ($scope.data.Headers[headerIndex].Milliseconds >= msStart &&
|
|
$scope.data.Headers[headerIndex].Milliseconds <= msEnd &&
|
|
$scope.data.Headers[headerIndex].Milliseconds > $scope.data.ActualsEndDateMs) {
|
|
colIndexes2Update[colIndexes2Update.length] = headerIndex;
|
|
}
|
|
}
|
|
var oldQuantity = 0;
|
|
var newQuantity = 0;
|
|
var newCost = 0;
|
|
var dec = Math.pow(10, parseInt($scope.formatCells.DecimalPlaces));
|
|
for (var rowIndex = 0; rowIndex < $scope.data.ScenarioCalendar.length; rowIndex++) {
|
|
for (var catIndex = 0; catIndex < $scope.formatCells.ExpCats.length; catIndex++) {
|
|
if ($scope.formatCells.ExpCats[catIndex].Id === $scope.data.ScenarioCalendar[rowIndex].ExpCatId) {
|
|
for (var colIndex = 0; colIndex < colIndexes2Update.length; colIndex++) {
|
|
oldQuantity = $scope.data.ScenarioCalendar[rowIndex].QuantityValues[colIndexes2Update[colIndex]];
|
|
newQuantity = Math.round(oldQuantity * dec) / dec;
|
|
newCost = Math.round(newQuantity * $scope.getRate($scope.formatCells.ExpCats[catIndex].Id, $scope.data.Headers[colIndexes2Update[colIndex]].Milliseconds) * dec) / dec;
|
|
if (oldQuantity === newQuantity)
|
|
continue;
|
|
updateQuantityOrCostCell($scope.formatCells.ExpCats[catIndex].Id, rowIndex, colIndexes2Update[colIndex], newQuantity, newCost, null);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
$("#modalFormatCells").modal("hide");
|
|
return true;
|
|
};
|
|
$scope.onMonthHeaderClick = function (header) {
|
|
header.Collapsed = !header.Collapsed;
|
|
header.Show = !header.Show;
|
|
header.CollapsedClass = header.Collapsed ? $scope.CollapsedIcon : $scope.NonCollapsedIcon;
|
|
if (header.Weeks && header.Weeks.length > 0)
|
|
for (var i = 0; i < header.Weeks.length; i++) {
|
|
$scope.data.Headers[header.Weeks[i]].Collapsed = header.Collapsed;
|
|
$scope.data.Headers[header.Weeks[i]].Show = !header.Collapsed;
|
|
}
|
|
$scope.resizeFreezAng();
|
|
};
|
|
$scope.onExpCatClick = function (row) {
|
|
row.Collapsed = !row.Collapsed;
|
|
//row.Show = !row.Show;
|
|
row.CollapsedClass = row.Collapsed ? $scope.CollapsedIcon : $scope.NonCollapsedIcon;
|
|
};
|
|
}]);
|