protected override async Task <List <int> > SaveExecuteAsync(List <ReportDefinitionForSave> entities, bool returnIds) { var defs = await _behavior.Definitions(); var settings = await _behavior.Settings(); foreach (var(entity, index) in entities.Indexed()) { if (entity.Roles.Any()) { if (string.IsNullOrWhiteSpace(entity.Title)) { string path = $"[{index}].{nameof(entity.Title)}"; string msg = _localizer["Error_TitleIsRequiredWhenShowInMainMenu"]; ModelState.AddError(path, msg); } } foreach (var(parameter, paramIndex) in entity.Parameters.Indexed()) { // TODO: Need to figure out how to retrieve the default control var errors = ApplicationUtil.ValidateControlOptions(parameter.Control, parameter.ControlOptions, _localizer, settings, defs); foreach (var msg in errors) { ModelState.AddError($"[{index}].{nameof(entity.Parameters)}[{paramIndex}].{nameof(parameter.ControlOptions)}", msg); } } } SaveOutput result = await _behavior.Repository.ReportDefinitions__Save( entities : entities, returnIds : returnIds, validateOnly : ModelState.IsError, top : ModelState.RemainingErrors, userId : UserId); AddErrorsAndThrowIfInvalid(result.Errors); return(result.Ids); }
protected override async Task <List <int> > SaveExecuteAsync(List <LineDefinitionForSave> entities, bool returnIds) { var defs = await _behavior.Definitions(); var settings = await _behavior.Settings(); // 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.AddError(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.AddError(path, msg); } // Required state should always be <= ReadOnlyState if (column.VisibleState > column.RequiredState) { string path = $"[{lineDefinitionIndex}].{nameof(LineDefinition.Columns)}[{columnIndex}].{nameof(LineDefinitionColumn.RequiredState)}"; string msg = _localizer["Error_RequiredStateCannotBeBeforeVisibleState"];; ModelState.AddError(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.AddError(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.AddError(path, msg); } } // Generate parameters int paramIndex = 0; lineDefinition.GenerateParameters.ForEach(parameter => { var errors = ApplicationUtil.ValidateControlOptions(parameter.Control, parameter.ControlOptions, _localizer, settings, defs); foreach (var msg in errors) { ModelState.AddError($"[{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[ErrorMessages.Error_Field0IsRequired, _localizer["WorkflowSignature_Role"]]; ModelState.AddError(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[ErrorMessages.Error_Field0IsRequired, _localizer["WorkflowSignature_User"]]; ModelState.AddError(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[ErrorMessages.Error_Field0IsRequired, _localizer["WorkflowSignature_RuleTypeEntryIndex"]]; ModelState.AddError(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.AddError(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.AddError(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[ErrorMessages.Error_Field0IsRequired, _localizer["WorkflowSignature_Value"]]; ModelState.AddError(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[ErrorMessages.Error_Field0IsRequired, _localizer["WorkflowSignature_PredicateTypeEntryIndex"]]; ModelState.AddError(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.AddError(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.AddError(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[ErrorMessages.Error_Field0IsRequired, _localizer["LineDefinition_BarcodeProperty"]]; ModelState.AddError(path, msg); } // If barcode is enabled, BarcodeExistingItemHandling must be specified if (string.IsNullOrWhiteSpace(lineDefinition.BarcodeExistingItemHandling)) { string path = $"[{lineDefinitionIndex}].{nameof(LineDefinition.BarcodeExistingItemHandling)}"; string msg = _localizer[ErrorMessages.Error_Field0IsRequired, _localizer["LineDefinition_BarcodeExistingItemHandling"]]; ModelState.AddError(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.AddError(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.AddError(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.AddError(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.AddError(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.AddError(path, msg); } var acceptableColumnNames = new Dictionary <string, Type> { { nameof(Entry.AgentId), typeof(Agent) }, { nameof(Entry.NotedAgentId), typeof(Agent) }, { nameof(Entry.ResourceId), typeof(Resource) }, { nameof(Entry.NotedResourceId), typeof(Resource) }, }; if (string.IsNullOrWhiteSpace(colDef.ColumnName)) { // Error handled earlier } else if (!acceptableColumnNames.TryGetValue(colDef.ColumnName, out Type colType)) { // Barcode Column must have one of the supported column names string path = $"[{lineDefinitionIndex}].{nameof(LineDefinition.BarcodeColumnIndex)}"; string names = string.Join(", ", acceptableColumnNames.Keys.Select(e => _localizer["Entry_" + e[0..^ 2]]));