function MagellanController($scope) { } function EnhancedTrusteeReportController($scope, $route, $filter, $location, $timeout, DynamicFilter, command, Obligations, Assets, Comments, Details, MetricList, TrusteeReportRecord, FeedSources, ObservationsWithMetrics, Triggers, ReportSchedules, DocumentByReportAndObservation, MetricReportDateMaps) { $scope.reportName = ($location.path() == '/balanceSheet') ? 'Balance Sheet' : 'Trustee Report'; $scope.obligations = []; $scope.assets = []; $scope.metrics = {}; $scope.previousMetrics = {}; $scope.triggers = []; $scope.previousTriggers = {}; $scope.observations = []; // defining a tempoarary obseration array. This array holds the observations until they are fully // processed, at which point they are pushed onto $scope.observations and the view is updated. // this is done because parts of the view will not update after fields are modified due to the // 'watch-fighters' performance directives. This, combined with the function addObservationToView() // will ensure the proper ordering of observations are rendered to the page. $scope.tempobs = []; $scope.feedSources = []; $scope.showRecord = true; $scope.isObligationDataLoading = true; $scope.isAssetDataLoading = true; $scope.isMetricDataLoading = false; $scope.isReportDateSaving = false; $scope.isTriggerDataLoading = false; $scope.observationId = ($route.current.params.observationId == undefined || $route.current.params.observationId == null || $route.current.params.observationId == "" || $route.current.params.observationId == 0) ? null : parseInt($route.current.params.observationId); var RecordFeedID = 3; $scope.LoadDetails = function () { Details.get({ id: $scope.observationId }, function (rsp) { $scope.details = rsp; $scope.isReadOnly = rsp.IsReadOnly; //$scope.LoadObservations(rsp.LegalEntityID, rsp.AsOfDate, { Name: "Record", id: 3 }); ReportSchedules.query({ legalEntityId: $scope.details.LegalEntityID }, function (rsp) { $scope.ReportSchedules = [{ReportName:"All Metrics", id: -1}]; $scope.ReportSchedules = _.union($scope.ReportSchedules, rsp.DocumentSchedules); }); }); FeedSources.query({}, function (rsp) { $scope.feedSources = rsp; //$scope.feedSource = _.detect(rsp, function (elem) { return elem.id == RecordFeedID; }); //default to record? service is defaulted to record. }); }; $scope.LoadReportDates = function () { $scope.MetricReportDateMaps = []; if (!$scope.selectedReport || $scope.selectedReport == "") return; DocumentByReportAndObservation.query({ reportId: $scope.selectedReport.id, observationId: $scope.observationId }, function (rsp) { $scope.ReportInstance = rsp.ReportInstance; if ($scope.ReportInstance) { var reportInstanceId = $scope.ReportInstance.id; MetricReportDateMaps.query({ reportInstanceId: reportInstanceId, includeUnmapped: true }, function (rsp) { $scope.MetricReportDateMaps = rsp.MetricReportDateMaps; }); } }); }; $scope.SaveReportDates = function () { var self = $scope; if (!$scope.MetricReportDateMaps || $scope.MetricReportDateMaps.length == 0) return; for (var index in $scope.MetricReportDateMaps) { if ($scope.MetricReportDateMaps[index].IsPeriod && (($scope.MetricReportDateMaps[index].StartDate && !$scope.MetricReportDateMaps[index].EndDate) || (!$scope.MetricReportDateMaps[index].StartDate && $scope.MetricReportDateMaps[index].EndDate))) { alert("One or more period dates that you have specified the Start Date for do not have an End Date specified. Your report date edits have not been saved."); return; } } self.isReportDateSaving = true; command("save report dates", { ReportInstanceID: $scope.ReportInstance.id, MetricReportDateMaps: $scope.MetricReportDateMaps }, function (rsp) { if (rsp.ok === false) { self.isReportDateSaving = false; alert("There was an error while saving report dates. Your report date modifications have not been saved."); } else { self.isReportDateSaving = false; alert("Your report date modifications have been saved."); } self.$apply(); }, function (rsp) { window.error(rsp.Message); self.isReportDateSaving = false; self.$apply(); }); }; $scope.LoadObservations = function (leId, obsDate, feed) { //$scope.observations = []; if (feed == undefined || feed == null || feed == '') { $scope.isMetricDataLoading = false; return; } //return nothing if the feed type is 'Record' and no report type has been selected else if (feed.id === 3 && $scope.selectedReport === null) { $scope.isMetricDataLoading = false; return; } $scope.observations = []; $scope.tempobs = []; ObservationsWithMetrics.query({ id: leId, feedId: feed.id, obsId: $scope.observationId }, function (rsp) { if (!rsp || rsp.length <= 0) { $scope.isMetricDataLoading = false; return; } var obs = _.sortBy(rsp, function (o) { return obsDate; }); $scope.tempobs = obs.concat().reverse(); var ob = _.find($scope.tempobs, function (elem) { return elem.ObservationId == $scope.observationId }); ob.isCurrentObs = true; loadMetrics($scope, $scope.observationId, feed, false); _.each(obs, function (o) { var thefeed = feed; var theobservation = o.ObservationId; var thescope = $scope; if (o.AsOfDate === obsDate) { o.isCurrentObs = true; } else { o.isCurrentObs = false; } $timeout(function () { if (!o.isCurrentObs) //dont load metric data for current observation again loadMetrics(thescope, theobservation, thefeed, true); $scope.LoadTriggers(thescope, o.ObservationId); }, 1500, false); }); }); } $scope.LoadObligations = function () { Obligations.query({ id: $scope.observationId }, function (rsp) { $scope.isObligationDataLoading = false; if (rsp.length == 6 && rsp[5].Source != undefined) //check that an error came back from the api rsp = []; $scope.obligations = rsp; FormatCurrency(2, 200); }); }; $scope.LoadAssets = function () { Assets.query({ id: $scope.observationId }, function (rsp) { $scope.isAssetDataLoading = false; if (rsp.length == 6 && rsp[5].Source != undefined) //check that an error came back from the api rsp = []; $scope.assets = rsp; FormatCurrency(2, 200); }); }; $scope.LoadComments = function () { Comments.get({ id: $scope.observationId }, function (rsp) { _.each(rsp.Comments, function (c) { //angular needs time in HH:mm:ss.sssZ. pretty needs time as HH:mm:ss var date = c.CreatedDate.split('.'); var fixDate = date[0] + ".000Z"; var year = $filter('date')(fixDate, 'yyyy-MM-dd'); var time = $filter('date')(fixDate, 'HH:mm:ss'); var whole = year + "T" + time + "Z"; c.DateToShow = prettyDate(whole); }); $scope.comments = rsp.Comments; }); } $scope.Cell = function (obsId, metricId) { return $scope.previousMetrics[obsId.toString()][metricId.toString()]; } $scope.TriggerCell = function (obsId, testId, triggerShortName) { if (testId == undefined) //search triggers return _.find($scope.previousTriggers[obsId.toString()], function (elem) { return elem.ShortName == triggerShortName; }); else { //search tests var trigger = _.find($scope.previousTriggers[obsId.toString()], function (elem) { return elem.ShortName == triggerShortName; }); if(trigger) return _.find(trigger.Tests, function (elem) { return elem.id == testId; }); } } // the purpose of this craziness is a workaround for the "watch-fighters" // performance directives. $scope.completedObsStack = []; var addObservationToView = function (obId) { var nextObs = _.last($scope.tempobs); if (nextObs.ObservationId == obId) { $scope.observations.push($scope.tempobs.pop()); nextObs = _.last($scope.tempobs); if (!nextObs) return; var tempObservations = []; while (!!_.find($scope.completedObsStack, function (elem) { return elem == nextObs.ObservationId })) { tempObservations.push($scope.tempobs.pop()); $scope.completedObsStack = _.without($scope.completedObsStack, nextObs.ObservationId); nextObs = _.last($scope.tempobs); if (!nextObs) break; } if (tempObservations.length > 0) $scope.observations = $scope.observations.concat(tempObservations); } else { $scope.completedObsStack.push(obId); } } var filterMetricsByReport = function (metrics) { if ($scope.selectedReport == '') { //null selection return []; } else if ($scope.selectedReport && $scope.selectedReport.id != -1) { //a report was actually selected var m = _.filter(metrics, function (metric) { return metric.ReportID === $scope.selectedReport.id; }); return m; } else { //-1 was chosen, return all metrics return metrics; } }; var loadMetrics = function (scope, obsId, f, isLight) { var queryValues = { id: obsId }; var feedSource = null; if (f == null || f == undefined || f == '') return; else if (f !== null && f !== undefined) feedSource = f.Name; if (isLight == null || isLight == undefined) isLight = false; _.extend(queryValues, { feedSource: feedSource, showLight: isLight }); //return emtpy list if no report was selected if ($scope.selectedReport === '') { scope.isMetricDataLoading = false; return []; } else { if ($scope.selectedReport && $scope.selectedReport.id !== -1) { _.extend(queryValues, { repId: $scope.selectedReport.id }); } var thescope = scope; MetricList.get(queryValues, function (rsp) { if (rsp.ok === false) { window.error(rsp.Message); rsp.Metrics = []; return; } // the requested observation is not the current observation if (obsId && thescope.observationId != obsId) { if (!thescope.previousMetrics[obsId.toString()]) { thescope.previousMetrics[obsId.toString()] = {}; } _.each(rsp.Metrics, function (e) { thescope.previousMetrics[obsId.toString()][e.id.toString()] = e; }); //$scope.observations.push(_.find($scope.tempobs, function (elem) { return elem.ObservationId == obsId; })); addObservationToView(obsId); return; } var feeds = _.uniq(_.pluck(rsp.Metrics, "FeedName")); //grab unique metric feeds to group on _.each(feeds, function (elem) { var feed = { FeedName: elem, Groups: [] }; var filterFeedMetrics = _.filter(rsp.Metrics, function (m) { return m.FeedName == elem; }); var groups = _.uniq(_.pluck(filterFeedMetrics, "Group")); //grab unique metric group names to group on _.each(groups, function (elem) { var obligations = []; var assets = []; var group = { GroupName: elem, eudwFormatting: false }; var filteredMetrics = _.filter(filterFeedMetrics, function (m) { return m.Group == elem && m.TypeID != 2 && m.TypeID != 1; }); //filter out all non-obl/non-asset metrics if (feedSource == "EUDW") { var newMetrics = {}; var eudwFormat = false; _.each(filteredMetrics, function (m) { if (m.ShortName.indexOf("_BAL_PCT") != -1) { var name = m.Name.split(" - Balance Percentage")[0]; if (!newMetrics[name]) { newMetrics[name] = { Name: name, isGrouped: true }; } newMetrics[name].BalancePerc = m.StringValue; newMetrics[name].BalancePercID = m.id; } else if (m.ShortName.indexOf("_BAL") != -1) { var name = m.Name.split(" - Balance")[0]; if (!newMetrics[name]) { newMetrics[name] = { Name: name, isGrouped: true }; } eudwFormat = true; newMetrics[name].Balance = m.StringValue; newMetrics[name].BalanceID = m.id; } else if (m.ShortName.indexOf("_CNT_PCT") != -1) { var name = m.Name.split(" - Count Percentage")[0]; if (!newMetrics[name]) { newMetrics[name] = { Name: name, isGrouped: true }; } newMetrics[name].CountPerc = m.StringValue; newMetrics[name].CountPercID = m.id; } else if (m.ShortName.indexOf("_CNT") != -1) { var name = m.Name.split(" - Count")[0]; if (!newMetrics[name]) { newMetrics[name] = { Name: name, isGrouped: true }; } eudwFormat = true; newMetrics[name].Count = m.StringValue; newMetrics[name].CountID = m.id; } }); _.each(_.values(newMetrics), function (m) { if (eudwFormat) { group.eudwFormatting = true; filteredMetrics.push(m); } }); } var filteredObligations = _.filter(filterFeedMetrics, function (m) { return m.Group == elem && m.TypeID == 2; }); var obligationNames = _.uniq(_.pluck(filteredObligations, "ObligationName")); //grab unique obligation names to group on _.each(obligationNames, function (oblName) { var oblGroup = { ObligationName: oblName, ObligationMetrics: _.filter(filteredObligations, function (m) { return m.ObligationName == oblName; }) }; obligations.push(oblGroup); }); var filteredAssets = _.filter(filterFeedMetrics, function (m) { return m.Group == elem && m.TypeID == 1; }); var assetNames = _.uniq(_.pluck(filteredAssets, "AssetName")); //grab unique asset names to group on _.each(assetNames, function (aName) { var aGroup = { AssetName: aName, AssetMetrics: _.filter(filteredAssets, function (m) { return m.AssetName == aName; }) }; assets.push(aGroup); }); group.Metrics = filterMetricsByReport(filteredMetrics); group.ObligationMetrics = filterMetricsByReport(obligations); group.AssetMetrics = filterMetricsByReport(assets); feed.Groups.push(group); filteredMetrics = null; filteredObligations = null; obligations = null; obligationNames = null; filteredAssets = null; assets = null; assetNames = null; }); // the requested observation is the current observation if (thescope.observationId == obsId && $scope.currentObsIter == 0) { thescope.metrics = feed; addObservationToView($scope.observationId); // $scope.observations.push(_.find($scope.tempobs, function (o) { // return o.ObservationId == $scope.observationId; // })); //add current observation $scope.currentObsIter++; } filterFeedMetrics = null; groups = null; }); feeds = null; thescope.isMetricDataLoading = false; }); } } $scope.LoadMetrics = function (f) { $scope.metrics = {}; $scope.currentObsIter = 0; if (f != undefined && f != null && f != '') $scope.isMetricDataLoading = true; } $scope.FilterReportSchedules = function (f) { alert('Not yet implemented!!!'); } $scope.LoadRecord = function () { TrusteeReportRecord.get({ obsId: $scope.observationId }, function (rsp) { if (rsp.ok == false) $scope.showRecord = false; else { $scope.showRecord = true; $scope.record = rsp; $scope.recordRetentionDocumentTypeId = 73; //trustee report record document type id if (rsp.Null == true) $scope.action = apiUri + "/Observations/" + $scope.observationId + "/Records/DocumentTypes/" + $scope.recordRetentionDocumentTypeId + "?DBRSKey=" + dbrskey; else self.action = apiUri + "/Observations/" + $scope.observationId + "/Records/" + $scope.record.id + "?DBRSKey=" + dbrskey; } }); } $scope.LoadTriggers = function (scope, observationId) { if (observationId == null) return; $scope.isTriggerDataLoading = true; Triggers.get({ obsId: observationId }, function (rsp) { $scope.isTriggerDataLoading = false; if (rsp.Triggers.length > 0) { if (scope.observationId != observationId) { if (!scope.previousTriggers[observationId.toString()]) { scope.previousTriggers[observationId.toString()] = []; } scope.previousTriggers[observationId.toString()] = scope.previousTriggers[observationId.toString()].concat(rsp.Triggers); return; } else $scope.triggers = rsp.Triggers; } }); }; $scope.Load = function () { $scope.LoadDetails(); $scope.LoadObligations(); $scope.LoadAssets(); $scope.LoadComments(); $scope.LoadMetrics($scope.feedSource); $scope.LoadRecord(); $scope.LoadTriggers($scope, $scope.observationId); } if ($scope.observationId != null) $scope.Load(); $scope.RunAllMetrics = function () { $scope.isMetricDataLoading = true; $scope.isTriggerDataLoading = true; command("execute all metrics", { ObservationID: $scope.observationId }, function (rsp) { if (rsp.ok === true) { $scope.LoadMetrics($scope.feedSource); $scope.LoadObservations($scope.details.LegalEntityID, $scope.details.AsOfDate, $scope.feedSource); } else { $scope.isMetricDataLoading = false; $scope.isTriggerDataLoading = false; alert("There was an error while evaluating the metrics."); } }, function (rsp) { window.error(rsp.Message); $scope.isTriggerDataLoading = false; $scope.isMetricDataLoading = false; $scope.$digest(); }); } $scope.addComment = function (text) { if (!text) return; var payload = {}; payload.ObservationId = $scope.observationId; payload.Comment = text; command("add trustee report comment", payload, function (rsp) { $scope.comment = null; $scope.LoadComments(); }); }; $scope.editObligation = function (obl, elemId) { //if (jQuery(elemId).hasClass("LV_invalid_field") || obl.Balance == null || obl.Balance == undefined) return //used for livevalidation if (obl.Balance === null || obl.Balance === undefined) return; jQuery(elemId).removeClass("error"); var value = obl.Balance; value = value.replace(/\,/g, ''); var payload = { id: obl.id }; if (isNaN(value) || (value == "" && obl.Balance != "")) { jQuery(elemId).addClass("error"); alert("Please enter a number"); obl.Balance = null; return; } var payload = { id: obl.id }; value = parseFloat(value); value = value.toFixed(2); //currency rounds to 2 places _.extend(payload, { Balance: Number(value) }); command("save obligation", payload, function (rsp) { obl.Balance = (value == "NaN") ? null : Number(value); $scope.$digest(); FormatCurrency(2, 500); //using FormatCurrency from InsightDash/controllers.js }); }; $scope.editAsset = function (asset, elemId) { //if (jQuery(elemId).hasClass("LV_invalid_field") || asset.Balance == null || asset.Balance == undefined) return //used for livevalidation if (asset.Balance === null || asset.Balance === undefined) return; jQuery(elemId).removeClass("error"); var value = asset.Balance; value = value.replace(/\,/g, ''); var payload = { AssetId: asset.id, ObservationId: $scope.observationId }; if (isNaN(value) || (value == "" && asset.Balance != "")) { jQuery(elemId).addClass("error"); alert("Please enter a valid number for asset balance."); return; } value = parseFloat(value); value = value.toFixed(2); //currency rounds to 2 places _.extend(payload, { Balance: Number(value) }); command("save asset observation", payload, function (rsp) { asset.Balance = (value == "NaN") ? null : Number(value); $scope.$digest(); FormatCurrency(2, 500); //using FormatCurrency from InsightDash/controllers.js }); }; $scope.editMetrics = function (metric, elemId) { //if (jQuery(elemId).hasClass("LV_invalid_field") || metric.StringValue == metric.OriginalCurrentValue) return //used for livevalidation if (metric.StringValue === metric.OriginalCurrentValue || metric.StringValue === null) return; jQuery(elemId).removeClass("error"); //old error checking var value = metric.StringValue; var numErr = "Please enter a number"; var payload = { MetricID: metric.id, ObservationID: $scope.observationId }; if (metric.FormatID == 5 || metric.FormatID == 6) //text or date _.extend(payload, { Value: value }); else { value = value.replace(/\,/g, ''); if ((value == "" && metric.StringValue != "")) { jQuery(elemId).addClass("error"); alert(numErr); metric.StringValue = null; return; } if (isNaN(value) || value == '') {//allow strings for decimals or wholenumbers if (value == "n.a." || value == "n.m.") { _.extend(payload, { Value: value }); } else { jQuery(elemId).addClass("error"); alert(numErr + " or \"n.a.\" or \"n.m.\" for not applicable or not meaningful values"); metric.StringValue = null; jQuery(elemId).removeClass("error"); return; } } else if (metric.FormatID == 3) { value = parseFloat(value); value = value.toFixed(0); //round to whole number _.extend(payload, { Value: parseInt(value) }); } else { value = parseFloat(value); value = value.toFixed(6); //db only stored up to 6 decimal places and does not round _.extend(payload, { Value: Number(value) }); } } command("save metric history", payload, function (rsp) { if (isNaN(value) && value != 'NaN') { metric.StringValue = value; metric.OriginalCurrentValue = value; $scope.$digest(); } else { metric.StringValue = (value == "NaN") ? null : Number(value); metric.OriginalCurrentValue = (value == "NaN") ? null : Number(value); } $scope.$digest(); FormatCurrency(2, 500); //using FormatCurrency from InsightDash/controllers.js }); }; $scope.changeText = function () { DynamicFilter.query({ scope: "Observation", text: $scope.selected.Entity }, function (rsp) { $scope.AllScopeEntities = rsp; $scope.ScopeEntities = _.pluck(rsp, "name"); }); }; $scope.loadObservation = function (name) { var observation = _.detect($scope.AllScopeEntities, function (elem) { return elem.name == name; }); if (observation) { $scope.observationId = observation.id; $location.search('observationId', $scope.observationId).path($location.path()); } }; $scope.downloadRecord = function () { window.open(apiUri + "/Observations/" + $scope.observationId + "/Records/DocumentTypes/" + $scope.recordRetentionDocumentTypeId + "/" + $scope.record.id + "?DBRSKEY=" + dbrskey); }; $scope.ShowTooltip = function (metric) { return $scope.ShowFunctionTooltip(metric) || $scope.ShowNotesTooltip(metric); }; $scope.ShowFunctionTooltip = function (metric) { return ((metric.FunctionDefinition != null && metric.FunctionDefinition != undefined) || (metric.MandatoryLevel != null && metric.MandatoryLevel != undefined)) ? true : false; }; $scope.ShowNotesTooltip = function (metric) { return (metric.Notes !== null && metric.Notes !== undefined && metric.Notes !== "") ? true : false; }; $scope.setClass = function (ob) { if (ob.isCurrentObs) return "currentob"; }; $scope.GetTestValue = function (test) { if (test) { return test.StringValue; } return null; }; $scope.ShowCurrencyMetric = function (metric) { if(metric != null && metric != undefined) return metric.CurrencyID !== 10 && metric.FormatID === 4 && metric.StringValue != 'n.m.' && metric.StringValue != 'n.a.'; }; $scope.ShowNumericMetric = function (metric) { if (metric != null && metric != undefined) return metric.FormatID !== 4 && metric.FormatID !== 5 && metric.FormatID !== 6 && metric.StringValue != 'n.m.' && metric.StringValue != 'n.a.'; }; $scope.ShowTextMetric = function (metric) { if (metric != null && metric != undefined) return metric.FormatID === 5 || metric.FormatID === 6 || (metric.CurrencyID === 10 && metric.FormatID === 4) || metric.StringValue == 'n.m.' || metric.StringValue == 'n.a.'; }; $scope.ShowPercentMetric = function (metric) { if (metric != null && metric != undefined) return metric.FormatID == 1 && !!(metric.StringValue) && metric.StringValue != 'n.m.' && metric.StringValue != 'n.a.'; }; $scope.ShowMetricPass = function (metric) { if (metric != null && metric != undefined && metric.MetricHistories != undefined) return metric.MetricHistories.length > 0 && metric.MetricHistories[0].TestPassHint === true; }; $scope.ShowMetricFail = function (metric) { if (metric != null && metric != undefined && metric.MetricHistories != undefined) return metric.MetricHistories.length > 0 && metric.MetricHistories[0].TestPassHint === false; }; $scope.ShowMetricNA = function (metric) { if (metric != null && metric != undefined && metric.MetricHistories != undefined) return metric.MetricHistories.length === 0 || (metric.MetricHistories.length > 0 && metric.MetricHistories[0].TestPassHint === null); }; //load metrics for reports that are not of type "Record" (id 3). "Record" metric loading is now handled on report change. $scope.GetMetrics = function (feedSource) { $scope.selectedReport = null; //select null option when the feed type changes if (feedSource === null) { //clear metrics if user selects null feed source $scope.metrics = {}; } if (feedSource && feedSource.id != 3) { $scope.LoadMetrics(feedSource); $scope.LoadObservations($scope.details.LegalEntityID, $scope.details.AsOfDate, feedSource); } }; } function NewEnhancedTrusteeReportController($scope, $route, $filter, $location, $q, DynamicFilter, command, Obligations, Assets, Comments, Details, MetricList, TrusteeReportRecord, FeedSources, Observation, TransactionObservations) { $scope.observationId = ($route.current.params.observationId == undefined || $route.current.params.observationId == null || $route.current.params.observationId == "" || $route.current.params.observationId == 0) ? null : parseInt($route.current.params.observationId); $scope.reportName = ($location.path() == '/balanceSheet') ? 'Balance Sheet' : 'Trustee Report'; $scope.gridOpts = []; $scope.observations = []; $scope.obligations = []; $scope.assets = []; $scope.metrics = {}; $scope.feedSources = []; $scope.showRecord = true; $scope.isObligationDataLoading = true; $scope.isAssetDataLoading = true; $scope.isMetricDataLoading = true; var RecordFeedID = 3; var getPreviousObservations = function (observationId) { var deferred = $q.defer(); Observation.get({ id: observationId }, function (rsp1) { if (rsp1.ok === false) { window.error(rsp1.Message); deferred.reject([]); } TransactionObservations.get({ id: rsp1.legalEntityId }, function (rsp2) { if (rsp2.ok === false) { window.error(rsp2.Message); deferred.reject([]); } deferred.resolve(rsp2); }, function () { deferred.reject([]); }); }, function () { deferred.reject([]); }); return deferred.promise; } var parseObservationList = function (data, observationId) { // extract 4 observations // 1. the observation for observationId // 2. the next 3 observations according to AsOfDate var obs = _.find(data, function (elem) { return elem.ObservationId == observationId; }); var prevObs = []; if (obs) { prevObs = _.filter(data, function (elem) { return obs.AsOfDate >= elem.AsOfDate && obs.ObservationId != elem.ObservationId; }); prevObs = _.sortBy(prevObs, function (elem) { return elem.AsOfDate; }).reverse(); //prevObs = _.first(prevObs, 3); } prevObs.splice(0, 0, obs); return prevObs; } var getMetricSet = function (observation, f) { var deferred = $q.defer(); var result = []; var obs = observation; var queryValues = { id: observation.ObservationId }; var feedSource = null; if (f === null) //all feedSource = "all"; else if (f !== null && f !== undefined) feedSource = f.Name; _.extend(queryValues, { feedSource: feedSource }); MetricList.get(queryValues, function (rsp) { if (rsp.ok === false) { window.error(rsp.Message); deferred.reject([]); } var feeds = _.uniq(_.pluck(rsp.Metrics, "FeedName")); //grab unique metric feeds to group on _.each(feeds, function (elem) { var feed = { FeedName: elem, Observation: obs, Groups: [] }; var filterFeedMetrics = _.filter(rsp.Metrics, function (m) { return m.FeedName == elem; }); var groups = _.uniq(_.pluck(filterFeedMetrics, "Group")); //grab unique metric group names to group on _.each(groups, function (elem) { var obligations = []; var assets = []; var group = { GroupName: elem }; var filteredMetrics = _.filter(filterFeedMetrics, function (m) { return m.Group == elem && m.TypeID != 2; }); //filter out all non-obl metrics var filteredObligations = _.filter(filterFeedMetrics, function (m) { return m.Group == elem && m.TypeID == 2; }); var obligationNames = _.uniq(_.pluck(filteredObligations, "ObligationName")); //grab unique obligation names to group on _.each(obligationNames, function (oblName) { var oblGroup = { ObligationName: oblName, ObligationMetrics: _.filter(filteredObligations, function (m) { return m.ObligationName == oblName; }) }; obligations.push(oblGroup); }); var filteredAssets = _.filter(filterFeedMetrics, function (m) { return m.Group == elem && m.Type == 1; }); var assetNames = _.uniq(_.pluck(filteredAssets, "AssetName")); //grab unique asset names to group on _.each(assetNames, function (aName) { var aGroup = { AssetName: aName, AssetMetrics: _.filter(filteredAssets, function (m) { return m.AssetName == aName; }) }; assets.push(aGroup); }); group.Metrics = filteredMetrics; group.ObligationMetrics = obligations; group.AssetMetrics = assets; feed.Groups.push(group); }); result.push(feed); //$scope.metrics.push(feed); }); deferred.resolve(result); FormatCurrency(2, 200); }); return deferred.promise; } var getMetricList = function (observationList, feed) { var promise = null; var funcArray = []; _.each(observationList, function (elem) { funcArray.push(getMetricSet(elem, feed)); }); return $q.all(funcArray); } // var headerTemplate = '
{{col.displayName}}
{{col.sortPriority}}
'; // $scope.myData = [{ metricColumnTitles: "Current Factor", metricId1: "98.73%", metricId2: "98.73%", metricId3: "98.73%", metricId4: "98.73%" }, // { metricColumnTitles: "Original Balance", metricId1: "1,204,000,000.000", metricId2: "1,204,000,000.000", metricId3: "1,204,000,000.000", metricId4: "1,204,000,000.000" }, // { metricColumnTitles: "EOP Balance", metricId1: "1", metricId2: "1", metricId3: "1", metricId4: "1" }, // { metricColumnTitles: "Coupon Type", metricId1: "2", metricId2: "2", metricId3: "2", metricId4: "2" }, // { metricColumnTitles: "Current Coupon", metricId1: "3", metricId2: "3", metricId3: "3", metricId4: "3" }, // { metricColumnTitles: "Principal", metricId1: "4", metricId2: "4", metricId3: "4", metricId4: "4" }, // { metricColumnTitles: "Gross Interest", metricId1: "5", metricId2: "5", metricId3: "5", metricId4: "5" }, // { metricColumnTitles: "Margin", metricId1: "6", metricId2: "6", metricId3: "6", metricId4: "6" }, // { metricColumnTitles: "Series A CE", metricId1: "7", metricId2: "7", metricId3: "7", metricId4: "7"}]; // $scope.testOptions = { // data: 'myData', // enableRowSelection: false, // enablePinning: true, // columnDefs: [{ field: "metricColumnTitles", displayName: " ", width: 120, pinned: true, headerCellTemplate: headerTemplate }, // { field: "metricId1", displayName: "2013-02-28", width: 120, pinned: true, headerCellTemplate: headerTemplate, enableCellEdit: true }, // { field: "metricId2", displayName: "2013-01-31", width: 120, headerCellTemplate: headerTemplate, enableCellEdit: false }, // { field: "metricId3", displayName: "2013-12-31", width: 120, headerCellTemplate: headerTemplate, enableCellEdit: false }, // { field: "metricId4", displayName: "2013-11-30", width: 120, headerCellTemplate: headerTemplate, enableCellEdit: false}] // }; var getPassFail = function (testPassHint) { if (testPassHint === null) return; else if (testPassHint === true) { return "PASS"; } else if (testPassHint === false) { return "FAIL"; } } var parseMetricList = function (metricList) { var resultOpts = []; var headerTemplate = '
{{col.displayName}}
{{col.sortPriority}}
'; var aggTemplate = '
{{row.label CUSTOM_FILTERS}}
'; var editTemplate = ''; var colDefs = [{ field: "metricGroupName", displayName: "metricGroupName", width: 0, pinned: true, headerCellTemplate: headerTemplate }, { field: "metricIdColumn", displayName: " ", width: 0, pinned: true, headerCellTemplate: headerTemplate }, { field: "metricPassFail", displayName: "Test", width: 60, pinned: true, headerCellTemplate: headerTemplate }, { field: "metricColumnTitles", displayName: " ", width: 180, pinned: true, headerCellTemplate: headerTemplate }]; var rowSets = []; var obsSet = {}; if (metricList.length <= 0) return resultOpts; for (var i = 0; i < metricList.length; i++) { var observationGroup = metricList[i][0]; var colDef = { field: 'obs_' + (observationGroup.Observation.ObservationId).toString(), displayName: observationGroup.Observation.AsOfDate, width: 200, headerCellTemplate: headerTemplate }; // pin the first observation so it's fixed and editable if (observationGroup.Observation.ObservationId == $scope.observationId) _.extend(colDef, { pinned: true, enableCellEdit: true, editableCellTemplate: editTemplate }); obsSet['obs_' + (observationGroup.Observation.ObservationId).toString()] = null; colDefs.push(colDef); } var metricColumnTitles = 0; var tempData = []; for (var j = 0; j < metricList[0][0].Groups.length; j++) { var group = metricList[0][0].Groups[j]; var tempOpts = { enableCellSelection: true, enableRowSelection: false, enablePinning: true, columnDefs: colDefs, groups: ['metricGroupName'], aggregateTemplate: aggTemplate }; // loop through obligation metrics and add a row for (var oblIdx = 0; oblIdx < group.ObligationMetrics.length; oblIdx++) { // add the obligation name row and spacers var groupingRowSpacer1 = _.clone(obsSet); // spacer groupingRowSpacer1.metricGroupName = group.GroupName; tempData.push(groupingRowSpacer1); var groupingRow = _.clone(obsSet); // name groupingRow.metricGroupName = group.GroupName; groupingRow.metricColumnTitles = group.ObligationMetrics[oblIdx].ObligationName; tempData.push(groupingRow); var groupingRowSpacer2 = _.clone(obsSet); // spacer groupingRowSpacer2.metricGroupName = group.GroupName; tempData.push(groupingRowSpacer1); for (var x = 0; x < group.ObligationMetrics[oblIdx].ObligationMetrics.length; x++) { var tempRow = _.clone(obsSet); var curMetric = group.ObligationMetrics[oblIdx].ObligationMetrics[x]; tempRow.metricGroupName = group.GroupName; tempRow.metricColumnTitles = curMetric.Name; _.each(metricList, function (ml) { var grp, mt, mx, mh; if (ml && ml[0].Groups) { grp = _.find(ml[0].Groups, function (g) { return g.GroupName == group.GroupName; }); } if (grp) { mt = _.find(grp.ObligationMetrics, function (m) { return m.ObligationName == curMetric.ObligationName; }); } if (mt) { mx = _.find(mt.ObligationMetrics, function (om) { return om.id == curMetric.id; }); } if (mx) { var mh = _.first(mx.MetricHistories); } if (mh) { $scope.metrics[mx.id.toString()] = mx; // save metric for lookup later tempRow['obs_' + (mh.ObservationID).toString()] = mh.StringValue; _.extend(tempRow, { metricIdColumn: mx.id, metricPassFail: getPassFail(mh.TestPassHint) }) } }); tempData.push(tempRow); } } // loop through asset metrics and add a row for (var assIdx = 0; assIdx < group.AssetMetrics.length; assIdx++) { // add the asset name row and spacers var groupingRowSpacer1 = _.clone(obsSet); // spacer groupingRowSpacer1.metricGroupName = group.GroupName; tempData.push(groupingRowSpacer1); var groupingRow = _.clone(obsSet); // asset name groupingRow.metricGroupName = group.GroupName; groupingRow.metricColumnTitles = group.AssetName; tempData.push(groupingRow); var groupingRowSpacer2 = _.clone(obsSet); // spacer groupingRowSpacer2.metricGroupName = group.GroupName; tempData.push(groupingRowSpacer1); for (var y = 0; y < group.AssetMetrics[assIdx].AssetMetrics.length; y++) { var tempRow = _.clone(obsSet); var curMetric = group.AssetMetrics[assIdx].ObligationMetrics[y]; tempRow.metricGroupName = group.GroupName; tempRow.metricColumnTitles = curMetric.Name; _.each(metricList, function (ml) { var grp, mt, mx, mh; if (ml && ml[0].Groups) { grp = _.find(ml[0].Groups, function (g) { return g.GroupName == group.GroupName; }); } if (grp) { mt = _.find(grp.AssetMetrics, function (m) { return m.AssetName == curMetric.AssetName; }); } if (mt) { mx = _.find(mt.AssetMetrics, function (am) { return am.id == curMetric.idl }); } if (mx) { mh = _.first(mt.MetricHistories); } if (mh) { $scope.metrics[mx.id.toString()] = mx; // save metric for lookup later tempRow['obs_' + (mh.ObservationID).toString()] = mh.StringValue; _.extend(tempRow, { metricIdColumn: mx.id, metricPassFail: getPassFail(mh.TestPassHint) }) } }); tempData.push(tempRow); } } // loop through metrics and add a row for (var z = 0; z < group.Metrics.length; z++) { var tempRow = _.clone(obsSet); var curMetric = group.Metrics[z]; tempRow.metricGroupName = group.GroupName; tempRow.metricColumnTitles = curMetric.Name; _.each(metricList, function (ml) { var grp, mt, mh; if (ml && ml[0].Groups) { grp = _.find(ml[0].Groups, function (g) { return g.GroupName == group.GroupName; }); } if (grp) { mt = _.find(grp.Metrics, function (m) { return m.id == curMetric.id }); } if (mt) { mh = _.first(mt.MetricHistories); } if (mh) { $scope.metrics[mt.id.toString()] = mt; // save metric for lookup later tempRow['obs_' + (mh.ObservationID).toString()] = mh.StringValue; _.extend(tempRow, { metricIdColumn: mt.id, metricPassFail: getPassFail(mh.TestPassHint) }) } }); tempData.push(tempRow); } // $scope['groupData' + j] = tempData; // tempOpts.data = 'groupData' + j; // if (tempOpts.data) // resultOpts.push(tempOpts); } $scope.columnData = tempData; tempOpts.data = 'columnData'; if (tempOpts.data) resultOpts.push(tempOpts); return resultOpts; } var loadMetriscFailed = function () { $scope.isMetricDataLoading = false; //alert('loadmetricFailed'); } var loadDetails = function () { Details.get({ id: $scope.observationId }, function (rsp) { $scope.details = rsp; $scope.isReadOnly = rsp.IsReadOnly; }); FeedSources.query({}, function (rsp) { $scope.feedSources = rsp; $scope.feedSource = _.detect(rsp, function (elem) { return elem.id == RecordFeedID; }); //default to record? service is defaulted to record. }); }; var loadObligations = function () { Obligations.query({ id: $scope.observationId }, function (rsp) { $scope.isObligationDataLoading = false; if (rsp.length == 6 && rsp[5].Source != undefined) //check that an error came back from the api rsp = []; $scope.obligations = rsp; FormatCurrency(2, 200); }); }; var loadAssets = function () { Assets.query({ id: $scope.observationId }, function (rsp) { $scope.isAssetDataLoading = false; if (rsp.length == 6 && rsp[5].Source != undefined) //check that an error came back from the api rsp = []; $scope.assets = rsp; FormatCurrency(2, 200); }); }; var loadComments = function () { Comments.get({ id: $scope.observationId }, function (rsp) { _.each(rsp.Comments, function (c) { //angular needs time in HH:mm:ss.sssZ. pretty needs time as HH:mm:ss var date = c.CreatedDate.split('.'); var fixDate = date[0] + ".000Z"; var year = $filter('date')(fixDate, 'yyyy-MM-dd'); var time = $filter('date')(fixDate, 'HH:mm:ss'); var whole = year + "T" + time + "Z"; c.DateToShow = prettyDate(whole); }); $scope.comments = rsp.Comments; }); } var loadRecord = function () { TrusteeReportRecord.get({ obsId: $scope.observationId }, function (rsp) { if (rsp.ok == false) $scope.showRecord = false; else { $scope.showRecord = true; $scope.record = rsp; $scope.recordRetentionDocumentTypeId = 73; //trustee report record document type id if (rsp.Null == true) $scope.action = apiUri + "/Observations/" + $scope.observationId + "/Records/DocumentTypes/" + $scope.recordRetentionDocumentTypeId + "?DBRSKey=" + dbrskey; else self.action = apiUri + "/Observations/" + $scope.observationId + "/Records/" + $scope.record.id + "?DBRSKey=" + dbrskey; } }); } $scope.LoadMetrics = function (feedsource) { $scope.isMetricDataLoading = true; var observationId = $scope.observationId; var feed = feedsource; getPreviousObservations(observationId) .then(function (data) { $scope.observations = data; var prevObs = parseObservationList(data, observationId); // get the metric list return getMetricList(prevObs, feed); }) .then(function (data) { $scope.gridOpts = []; var filteredData = _.filter(data, function (elem) { return elem.length > 0; }); var opts = parseMetricList(filteredData); $scope.gridOpts = opts; $scope.isMetricDataLoading = false; }, loadMetriscFailed) } $scope.onMetricChanged = function (row, elem) { if (!row || !row.metricIdColumn || !elem || row[elem] === null) { if (row && elem && row[elem]) row[elem] = null; return }; var metric = $scope.metrics[row.metricIdColumn]; var value = row[elem]; var payload = { MetricID: row.metricIdColumn, ObservationID: $scope.observationId }; if (row.metricFormatId == 5 || row.metricFormatId == 6) { // text or date _.extend(payload, { Value: value }); } else { // if (typeof (value) == "string") //old error checking // value = value.replace(/[^0-9\.]+/g, ''); if (isNaN(value) || (value == "" && metric.StringValue != "")) { alert("Please enter a number"); row[elem] = null; return; } if (metric.FormatID == 3) { //whole number value = parseFloat(value); value = value.toFixed(0); //round to whole number _.extend(payload, { Value: parseInt(value) }); } else { value = parseFloat(value); value = value.toFixed(6); //db only stored up to 6 decimal places and does not round _.extend(payload, { Value: Number(value) }); } command("save metric history", payload, function (rsp) { if (metric.FormatID == 5 || metric.FormatID == 6) { metric.StringValue = value; metric.OriginalCurrentValue = value; } else { metric.StringValue = (value == "NaN") ? null : Number(value); metric.OriginalCurrentValue = (value == "NaN") ? null : Number(value); } $scope.$digest(); FormatCurrency(2, 1000); //using FormatCurrency from InsightDash/controllers.js }); } } $scope.Load = function () { loadDetails(); loadObligations(); loadAssets(); loadComments(); $scope.LoadMetrics($scope.feedSource); loadRecord(); FormatCurrency(2, 500); } if ($scope.observationId != null) $scope.Load(); $scope.RunAllMetrics = function () { $scope.isMetricDataLoading = true; command("execute all metrics", { ObservationID: $scope.observationId }, function (rsp) { if (rsp.ok === true) $scope.LoadMetrics($scope.feedSource); else { $scope.isMetricDataLoading = false; alert("There was an error while evaluating the metrics."); } }, function (rsp) { window.error(rsp.Message); $scope.isMetricDataLoading = false; $scope.$digest(); }); } $scope.addComment = function (text) { if (!text) return; var payload = {}; payload.ObservationId = $scope.observationId; payload.Comment = text; command("add trustee report comment", payload, function (rsp) { $scope.comment = null; loadComments(); }); }; $scope.editObligation = function (obl, elemId) { //if (jQuery(elemId).hasClass("LV_invalid_field") || obl.Balance == null || obl.Balance == undefined) return //used for livevalidation if (obl.Balance === null || obl.Balance === undefined) return; jQuery(elemId).removeClass("error"); var value = obl.Balance; if (typeof (value) == "string") value = value.replace(/[^0-9\.]+/g, ''); var payload = { id: obl.id }; if (isNaN(value) || (value == "" && obl.Balance != "")) { jQuery(elemId).addClass("error"); alert("Please enter a number"); obl.Balance = null; return; } var payload = { id: obl.id }; value = parseFloat(value); value = value.toFixed(2); //currency rounds to 2 places _.extend(payload, { Balance: Number(value) }); command("save obligation", payload, function (rsp) { obl.Balance = (value == "NaN") ? null : Number(value); $scope.$digest(); FormatCurrency(2, 500); //using FormatCurrency from InsightDash/controllers.js }); }; $scope.editAsset = function (asset, elemId) { //if (jQuery(elemId).hasClass("LV_invalid_field") || asset.Balance == null || asset.Balance == undefined) return //used for livevalidation if (asset.Balance === null || asset.Balance === undefined) return; jQuery(elemId).removeClass("error"); var value = asset.Balance; var payload = { AssetId: asset.id, ObservationId: $scope.observationId }; if (typeof (value) == "string") { value = value.replace(/[^0-9\.]+/g, ''); } if (isNaN(value) || (value == "" && asset.Balance != "")) { jQuery(elemId).addClass("error"); alert("Please enter a valid number for asset balance."); return; } value = parseFloat(value); value = value.toFixed(2); //currency rounds to 2 places _.extend(payload, { Balance: Number(value) }); command("save asset observation", payload, function (rsp) { asset.Balance = (value == "NaN") ? null : Number(value); $scope.$digest(); FormatCurrency(2, 500); //using FormatCurrency from InsightDash/controllers.js }); }; $scope.changeText = function () { DynamicFilter.query({ scope: "Observation", text: $scope.selected.Entity }, function (rsp) { $scope.AllScopeEntities = rsp; $scope.ScopeEntities = _.pluck(rsp, "name"); }); }; $scope.loadObservation = function (name) { var observation = _.detect($scope.AllScopeEntities, function (elem) { return elem.name == name; }); if (observation) { $scope.observationId = observation.id; $location.search('observationId', $scope.observationId).path($location.path()); } }; $scope.downloadRecord = function () { window.open(apiUri + "/Observations/" + $scope.observationId + "/Records/DocumentTypes/" + $scope.recordRetentionDocumentTypeId + "/" + $scope.record.id + "?DBRSKEY=" + dbrskey); }; }