protected override async Task SaveValidateAsync(List <ReportDefinitionForSave> entities) { var defs = _defCache.GetCurrentDefinitionsIfCached().Data; var settings = _settingsCache.GetCurrentSettingsIfCached().Data; foreach (var(entity, index) in entities.Select((e, i) => (e, i))) { if (entity.ShowInMainMenu ?? false) { if (string.IsNullOrWhiteSpace(entity.Title)) { string path = $"[{index}].{nameof(entity.Title)}"; string msg = _localizer["Error_TitleIsRequiredWhenShowInMainMenu"]; ModelState.AddModelError(path, msg); } } foreach (var(parameter, paramIndex) in entity.Parameters.Select((e, i) => (e, i))) { // TODO: Need to figure out how to retrieve the default control var errors = ControllerUtilities.ValidateControlOptions(parameter.Control, parameter.ControlOptions, _localizer, settings, defs); foreach (var msg in errors) { ModelState.AddModelError($"[{index}].{nameof(entity.Parameters)}[{paramIndex}].{nameof(parameter.ControlOptions)}", msg); } } } // No need to invoke SQL if the model state is full of errors if (ModelState.HasReachedMaxErrors) { // null Ids will cause an error when calling the SQL validation return; } // SQL validation int remainingErrorCount = ModelState.MaxAllowedErrors - ModelState.ErrorCount; var sqlErrors = await _repo.ReportDefinitions_Validate__Save(entities, top : remainingErrorCount); // Add errors to model state ModelState.AddLocalizedErrors(sqlErrors, _localizer); }
public ActionResult <DataWithVersion <DefinitionsForClient> > DefinitionsForClient() { try { // Simply retrieves the cached definitions, which were refreshed by ApiController var result = _definitionsCache.GetCurrentDefinitionsIfCached(); if (result == null) { throw new InvalidOperationException("The definitions were missing from the cache"); } return(Ok(result)); } catch (Exception ex) { _logger.LogError($"Error: {ex.Message} {ex.StackTrace}"); return(BadRequest(ex.Message)); } }
private AgentDefinitionForClient Definition() => _definitionsCache.GetCurrentDefinitionsIfCached()?.Data?.Agents? .GetValueOrDefault(DefinitionId) ?? throw new InvalidOperationException($"Definition for '{DefinitionId}' was missing from the cache");
protected override async Task SaveValidateAsync(List <DashboardDefinitionForSave> entities) { const int maxOffset = 1000; const int maxSize = 16; var defs = _defCache.GetCurrentDefinitionsIfCached().Data; var settings = _settingsCache.GetCurrentSettingsIfCached().Data; foreach (var(entity, index) in entities.Select((e, i) => (e, i))) { if (entity.ShowInMainMenu ?? false) { if (string.IsNullOrWhiteSpace(entity.Title)) { string path = $"[{index}].{nameof(entity.Title)}"; string msg = _localizer["Error_TitleIsRequiredWhenShowInMainMenu"]; ModelState.AddModelError(path, msg); } } var duplicateReportIds = entity.Widgets .GroupBy(e => e.ReportDefinitionId) .Where(g => g.Count() > 1) .Select(g => g.Key) .ToHashSet(); foreach (var(widget, widgetIndex) in entity.Widgets.Select((e, i) => (e, i))) { if (widget.OffsetX < 0) { string path = $"[{index}].{nameof(entity.Widgets)}[{widgetIndex}].{nameof(widget.OffsetX)}"; string msg = _localizer["Error_TheField0CannotBeNegative", _localizer["DashboardDefinition_OffsetX"]]; ModelState.AddModelError(path, msg); } if (widget.OffsetX >= maxOffset) { string path = $"[{index}].{nameof(entity.Widgets)}[{widgetIndex}].{nameof(widget.OffsetX)}"; string msg = _localizer["Error_Field0MaximumIs1", _localizer["DashboardDefinition_OffsetX"], maxOffset]; ModelState.AddModelError(path, msg); } if (widget.OffsetY < 0) { string path = $"[{index}].{nameof(entity.Widgets)}[{widgetIndex}].{nameof(widget.OffsetY)}"; string msg = _localizer["Error_TheField0CannotBeNegative", _localizer["DashboardDefinition_OffsetY"]]; ModelState.AddModelError(path, msg); } if (widget.OffsetY >= maxOffset) { string path = $"[{index}].{nameof(entity.Widgets)}[{widgetIndex}].{nameof(widget.OffsetY)}"; string msg = _localizer["Error_Field0MaximumIs1", _localizer["DashboardDefinition_OffsetY"], maxOffset]; ModelState.AddModelError(path, msg); } if (widget.Width < 0) { string path = $"[{index}].{nameof(entity.Widgets)}[{widgetIndex}].{nameof(widget.Width)}"; string msg = _localizer["Error_TheField0CannotBeNegative", _localizer["DashboardDefinition_Width"]]; ModelState.AddModelError(path, msg); } if (widget.Width >= maxSize) { string path = $"[{index}].{nameof(entity.Widgets)}[{widgetIndex}].{nameof(widget.Width)}"; string msg = _localizer["Error_Field0MaximumIs1", _localizer["DashboardDefinition_Width"], maxSize]; ModelState.AddModelError(path, msg); } if (widget.Height < 0) { string path = $"[{index}].{nameof(entity.Widgets)}[{widgetIndex}].{nameof(widget.Height)}"; string msg = _localizer["Error_TheField0CannotBeNegative", _localizer["DashboardDefinition_Height"]]; ModelState.AddModelError(path, msg); } if (widget.Height >= maxSize) { string path = $"[{index}].{nameof(entity.Widgets)}[{widgetIndex}].{nameof(widget.Height)}"; string msg = _localizer["Error_Field0MaximumIs1", _localizer["DashboardDefinition_Height"], maxSize]; ModelState.AddModelError(path, msg); } if (duplicateReportIds.Contains(widget.ReportDefinitionId)) { defs.Reports.TryGetValue(widget.ReportDefinitionId.Value, out ReportDefinitionForClient reportDef); string reportName = reportDef == null ? null : settings.Localize(reportDef.Title, reportDef.Title2, reportDef.Title3); string path = $"[{index}].{nameof(entity.Widgets)}[{widgetIndex}].{nameof(widget.ReportDefinitionId)}"; string msg = _localizer["Error_The01IsDuplicated", _localizer["DashboardDefinition_ReportDefinition"], reportName ?? widget.ReportDefinitionId.ToString()]; ModelState.AddModelError(path, msg); } } } // No need to invoke SQL if the model state is full of errors if (ModelState.HasReachedMaxErrors) { // null Ids will cause an error when calling the SQL validation return; } // SQL validation int remainingErrorCount = ModelState.MaxAllowedErrors - ModelState.ErrorCount; var sqlErrors = await _repo.DashboardDefinitions_Validate__Save(entities, top : remainingErrorCount); // Add errors to model state ModelState.AddLocalizedErrors(sqlErrors, _localizer); }
private LookupDefinitionForClient Definition() => _definitionsCache.GetCurrentDefinitionsIfCached()?.Data?.Lookups? .GetValueOrDefault(DefinitionId.Value) ?? throw new InvalidOperationException($"Lookup Definition with Id = {DefinitionId} is missing from the cache");
protected override async Task SaveValidateAsync(List <LineDefinitionForSave> entities) { var defs = _defCache.GetCurrentDefinitionsIfCached().Data; var settings = _settingsCache.GetCurrentSettingsIfCached().Data; // C# validation int lineDefinitionIndex = 0; entities.ForEach(lineDefinition => { // Columns int columnIndex = 0; lineDefinition.Columns.ForEach(column => { int index = column.EntryIndex.Value; if (index < 0) { string path = $"[{lineDefinitionIndex}].{nameof(LineDefinition.Columns)}[{columnIndex}].{nameof(LineDefinitionColumn.EntryIndex)}"; string msg = _localizer["Error_IndexMustBeGreaterOrEqualZero"]; ModelState.AddModelError(path, msg); } else if (index > (lineDefinition.Entries?.Count ?? 0)) { string path = $"[{lineDefinitionIndex}].{nameof(LineDefinition.Columns)}[{columnIndex}].{nameof(LineDefinitionColumn.EntryIndex)}"; string msg = _localizer["Error_NoEntryCorrespondsToIndex0", index]; ModelState.AddModelError(path, msg); } // Required state should always be <= ReadOnlyState if (column.RequiredState > column.ReadOnlyState) { string path = $"[{lineDefinitionIndex}].{nameof(LineDefinition.Columns)}[{columnIndex}].{nameof(LineDefinitionColumn.ReadOnlyState)}"; string msg = _localizer["Error_ReadOnlyStateCannotBeBeforeRequiredState"];; ModelState.AddModelError(path, msg); } columnIndex++; }); // GenerateScript if (!string.IsNullOrWhiteSpace(lineDefinition.GenerateScript)) { // If auto-generate script is specified, DefaultsToForm must be false if (lineDefinition.ViewDefaultsToForm.Value) { string path = $"[{lineDefinitionIndex}].{nameof(LineDefinition.GenerateScript)}"; string msg = _localizer["Error_CannotHaveGenerateScriptWithDefaultsToForm"]; ModelState.AddModelError(path, msg); } } // Generate parameters int paramIndex = 0; lineDefinition.GenerateParameters.ForEach(parameter => { var errors = ControllerUtilities.ValidateControlOptions(parameter.Control, parameter.ControlOptions, _localizer, settings, defs); foreach (var msg in errors) { ModelState.AddModelError($"[{lineDefinitionIndex}].{nameof(lineDefinition.GenerateParameters)}[{paramIndex}].{nameof(parameter.ControlOptions)}", msg); } paramIndex++; }); // Workflows int workflowIndex = 0; lineDefinition.Workflows.ForEach(workflow => { int signatureIndex = 0; workflow.Signatures?.ForEach(signature => { // Role is required if (signature.RuleType == RuleTypes.ByRole && signature.RoleId == null) { string path = $"[{lineDefinitionIndex}].{nameof(LineDefinition.Workflows)}[{workflowIndex}].{nameof(Workflow.Signatures)}[{signatureIndex}].{nameof(WorkflowSignature.RoleId)}"; string msg = _localizer[Constants.Error_Field0IsRequired, _localizer["WorkflowSignature_Role"]]; ModelState.AddModelError(path, msg); } // User is required if (signature.RuleType == RuleTypes.ByUser && signature.UserId == null) { string path = $"[{lineDefinitionIndex}].{nameof(LineDefinition.Workflows)}[{workflowIndex}].{nameof(Workflow.Signatures)}[{signatureIndex}].{nameof(WorkflowSignature.UserId)}"; string msg = _localizer[Constants.Error_Field0IsRequired, _localizer["WorkflowSignature_User"]]; ModelState.AddModelError(path, msg); } if (signature.RuleType == RuleTypes.ByCustodian && signature.RuleTypeEntryIndex == null) { // Entry index is required if (signature.RuleTypeEntryIndex == null) { string path = $"[{lineDefinitionIndex}].{nameof(LineDefinition.Workflows)}[{workflowIndex}].{nameof(Workflow.Signatures)}[{signatureIndex}].{nameof(WorkflowSignature.RuleTypeEntryIndex)}"; string msg = _localizer[Constants.Error_Field0IsRequired, _localizer["WorkflowSignature_RuleTypeEntryIndex"]]; ModelState.AddModelError(path, msg); } else { // Make sure Entry index is not out of bounds int index = signature.RuleTypeEntryIndex.Value; if (index < 0) { string path = $"[{lineDefinitionIndex}].{nameof(LineDefinition.Workflows)}[{workflowIndex}].{nameof(Workflow.Signatures)}[{signatureIndex}].{nameof(WorkflowSignature.RuleTypeEntryIndex)}"; string msg = _localizer["Error_IndexMustBeGreaterOrEqualZero"]; ModelState.AddModelError(path, msg); } else if (index > (lineDefinition.Entries?.Count ?? 0)) { string path = $"[{lineDefinitionIndex}].{nameof(LineDefinition.Workflows)}[{workflowIndex}].{nameof(Workflow.Signatures)}[{signatureIndex}].{nameof(WorkflowSignature.RuleTypeEntryIndex)}"; string msg = _localizer["Error_NoEntryCorrespondsToIndex0", index]; ModelState.AddModelError(path, msg); } } } if (signature.PredicateType == PredicateTypes.ValueGreaterOrEqual) { // Value is required if (signature.Value == null) { string path = $"[{lineDefinitionIndex}].{nameof(LineDefinition.Workflows)}[{workflowIndex}].{nameof(Workflow.Signatures)}[{signatureIndex}].{nameof(WorkflowSignature.Value)}"; string msg = _localizer[Constants.Error_Field0IsRequired, _localizer["WorkflowSignature_Value"]]; ModelState.AddModelError(path, msg); } // Entry Index is required if (signature.PredicateTypeEntryIndex == null) { string path = $"[{lineDefinitionIndex}].{nameof(LineDefinition.Workflows)}[{workflowIndex}].{nameof(Workflow.Signatures)}[{signatureIndex}].{nameof(WorkflowSignature.PredicateTypeEntryIndex)}"; string msg = _localizer[Constants.Error_Field0IsRequired, _localizer["WorkflowSignature_PredicateTypeEntryIndex"]]; ModelState.AddModelError(path, msg); } else { // Make sure Entry index is not out of bounds int index = signature.PredicateTypeEntryIndex.Value; if (index < 0) { string path = $"[{lineDefinitionIndex}].{nameof(LineDefinition.Workflows)}[{workflowIndex}].{nameof(Workflow.Signatures)}[{signatureIndex}].{nameof(WorkflowSignature.PredicateTypeEntryIndex)}"; string msg = _localizer["Error_IndexMustBeGreaterOrEqualZero"]; ModelState.AddModelError(path, msg); } else if (index > (lineDefinition.Entries?.Count ?? 0)) { string path = $"[{lineDefinitionIndex}].{nameof(LineDefinition.Workflows)}[{workflowIndex}].{nameof(Workflow.Signatures)}[{signatureIndex}].{nameof(WorkflowSignature.PredicateTypeEntryIndex)}"; string msg = _localizer["Error_NoEntryCorrespondsToIndex0", index]; ModelState.AddModelError(path, msg); } } } signatureIndex++; }); workflowIndex++; }); // Barcode if (lineDefinition.BarcodeColumnIndex != null) { // If barcode is enabled, BarcodeProperty must be specified if (string.IsNullOrWhiteSpace(lineDefinition.BarcodeProperty)) { string path = $"[{lineDefinitionIndex}].{nameof(LineDefinition.BarcodeProperty)}"; string msg = _localizer[Constants.Error_Field0IsRequired, _localizer["LineDefinition_BarcodeProperty"]]; ModelState.AddModelError(path, msg); } // If barcode is enabled, BarcodeExistingItemHandling must be specified if (string.IsNullOrWhiteSpace(lineDefinition.BarcodeExistingItemHandling)) { string path = $"[{lineDefinitionIndex}].{nameof(LineDefinition.BarcodeExistingItemHandling)}"; string msg = _localizer[Constants.Error_Field0IsRequired, _localizer["LineDefinition_BarcodeExistingItemHandling"]]; ModelState.AddModelError(path, msg); } // If barcode is enabled, DefaultsToForm must be false if (lineDefinition.ViewDefaultsToForm.Value) { string path = $"[{lineDefinitionIndex}].{nameof(LineDefinition.BarcodeColumnIndex)}"; string msg = _localizer["Error_CannotHaveBarcodeWithDefaultsToForm"]; ModelState.AddModelError(path, msg); } // BarcodeColumnIndex must be within Columns range var colIndex = lineDefinition.BarcodeColumnIndex.Value; if (colIndex >= lineDefinition.Columns.Count) { string path = $"[{lineDefinitionIndex}].{nameof(LineDefinition.BarcodeColumnIndex)}"; string msg = _localizer["Error_BarcodeColumnIndexOutOfRange"]; ModelState.AddModelError(path, msg); } else { // Barcode Column cannot inherit from headers var colDef = lineDefinition.Columns[colIndex]; if (colDef.InheritsFromHeader > 0) { string path = $"[{lineDefinitionIndex}].{nameof(LineDefinition.BarcodeColumnIndex)}"; string msg = _localizer["Error_BarcodeColumnCannotInheritFromHeaders"]; ModelState.AddModelError(path, msg); } // Barcode Column must be visible from DRAFT if (colDef.VisibleState > 0) { string path = $"[{lineDefinitionIndex}].{nameof(LineDefinition.BarcodeColumnIndex)}"; string msg = _localizer["Error_BarcodeColumnMustBeVisibleFromDraft"]; ModelState.AddModelError(path, msg); } // Barcode Column must be editable from DRAFT if (colDef.ReadOnlyState == 0) { string path = $"[{lineDefinitionIndex}].{nameof(LineDefinition.BarcodeColumnIndex)}"; string msg = _localizer["Error_BarcodeColumnCannotBeReadOnlyFromDraft"]; ModelState.AddModelError(path, msg); } Dictionary <string, Type> acceptableColumnNames = new Dictionary <string, Type> { { "CustodianId", typeof(Relation) }, { "CustodyId", typeof(Custody) }, { "ParticipantId", typeof(Relation) }, { "ResourceId", typeof(Resource) } }; if (string.IsNullOrWhiteSpace(colDef.ColumnName)) { // Error handled earlier } else if (!acceptableColumnNames.TryGetValue(colDef.ColumnName, out Type colType)) { // Barcode Column must have on of the supported column names string path = $"[{lineDefinitionIndex}].{nameof(LineDefinition.BarcodeColumnIndex)}"; string names = string.Join(", ", acceptableColumnNames.Keys.Select(e => _localizer["Entry_" + e[0..^ 2]]));
public async Task <(List <DocumentDefinition>, Extras)> UpdateState(List <int> ids, UpdateStateArguments args) { // Make sure int jvDefId = _defCache.GetCurrentDefinitionsIfCached()?.Data?.ManualJournalVouchersDefinitionId ?? throw new BadRequestException("The Manual Journal Voucher Id is not defined"); int index = 0; ids.ForEach(id => { if (id == jvDefId) { string path = $"[{index}]"; string msg = _localizer["Error_CannotModifySystemItem"]; ModelState.AddModelError(path, msg); } index++; }); // No point carrying on ModelState.ThrowIfInvalid(); // Check user permissions var action = "State"; var actionFilter = await UserPermissionsFilter(action, cancellation : default); ids = await CheckActionPermissionsBefore(actionFilter, ids); // C# Validation if (string.IsNullOrWhiteSpace(args.State)) { throw new BadRequestException(_localizer[Constants.Error_Field0IsRequired, _localizer["State"]]); } if (!DefStates.All.Contains(args.State)) { string validStates = string.Join(", ", DefStates.All); throw new BadRequestException($"'{args.State}' is not a valid definition state, valid states are: {validStates}"); } // Transaction using var trx = ControllerUtilities.CreateTransaction(); // Validate int remainingErrorCount = ModelState.MaxAllowedErrors - ModelState.ErrorCount; var errors = await _repo.DocumentDefinitions_Validate__UpdateState(ids, args.State, top : remainingErrorCount); ControllerUtilities.AddLocalizedErrors(ModelState, errors, _localizer); ModelState.ThrowIfInvalid(); // Execute await _repo.DocumentDefinitions__UpdateState(ids, args.State); // Prepare response List <DocumentDefinition> data = null; Extras extras = null; if (args.ReturnEntities ?? false) { (data, extras) = await GetByIds(ids, args, action, cancellation : default); } // Check user permissions again await CheckActionPermissionsAfter(actionFilter, ids, data); // Commit and return trx.Complete(); return(data, extras); }