using System; using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; using GB5Shared.DTO.Framework.Login; using GB5Shared.DTO.Report; using GB5Shared.GenerateAutoNumber; using GB5Shared.QueryExecutor; using Microsoft.Extensions.Logging; namespace GB5Shared.CriteriaConfig { public class CriteriaConfigFastSave : ICriteriaConfigFastSave { private const int AutoCriteriaConfigType = 2; // GB4 parity: CriteriaConfigType 2 = "Auto" private readonly IQueryExecutor _queryExecutor; private readonly AutoNumber _autoNumber; private readonly ILogger _logger; public CriteriaConfigFastSave(IQueryExecutor queryExecutor, AutoNumber autoNumber, ILogger logger) { _queryExecutor = queryExecutor; _autoNumber = autoNumber; _logger = logger; } public async Task SaveCriteriaConfigFastAsync(ReportCallingDTO reportCallingDTO, LoginDTO loginDTO, CancellationToken cancellationToken = default) { try { // GB4 parity gate (Unisoft.FrameworkBLL.CriteriaConfig.CriteriaConfig.SaveCriteriaConfig): // only remember the filter for a drill-down run, and only when CriteriaRunType asked to // remember it (0 = Auto+Remember, 2 = Manual+Remember; 1/3 = "...NotRemember"). if (reportCallingDTO?.CriteriaDTO == null) return; if (reportCallingDTO.IsDrillDown != 1) return; if (reportCallingDTO.CriteriaRunType != 0 && reportCallingDTO.CriteriaRunType != 2) return; if (reportCallingDTO.MenuId == -1 || reportCallingDTO.WebserviceId == -1) return; var sections = reportCallingDTO.CriteriaDTO.SectionCriteriaList; if (sections == null || sections.Count == 0) return; var deleteParams = new { webserviceid = reportCallingDTO.WebserviceId, userid = loginDTO.UserId, ouid = loginDTO.WorkOUId, menuid = reportCallingDTO.MenuId }; await _queryExecutor.ExecuteAsync(loginDTO, CriteriaConfigFastQB.DELETE_CRITERIACONFIGATTRIBUTE_BY_KEY, deleteParams, cancellationToken: cancellationToken).ConfigureAwait(false); await _queryExecutor.ExecuteAsync(loginDTO, CriteriaConfigFastQB.DELETE_CRITERIACONFIGSECTION_BY_KEY, deleteParams, cancellationToken: cancellationToken).ConfigureAwait(false); await _queryExecutor.ExecuteAsync(loginDTO, CriteriaConfigFastQB.DELETE_CRITERIACONFIG_BY_KEY, deleteParams, cancellationToken: cancellationToken).ConfigureAwait(false); // Unlike GB4's SaveCriteriaConfigFast (which only persisted SectionCriteriaList[0], // silently dropping any further AND/OR groups), every section is saved here. int attributeCount = sections.Sum(s => s.AttributesCriteriaList?.Count ?? 0); var autoNumberDTO = await _autoNumber.GetAutoNumber(1 + sections.Count + attributeCount, "CRITERIACONFIG", loginDTO).ConfigureAwait(false); var currentTime = DateTime.UtcNow; int criteriaConfigId = autoNumberDTO.StartNumber; int nextId = criteriaConfigId + 1; var statements = new List<(string sql, object param)> { (CriteriaConfigFastQB.SAVE_CRITERIACONFIG, new { CriteriaConfigId = criteriaConfigId, CriteriaConfigName = BuildAutoName(reportCallingDTO.MenuId), CriteriaConfigCriteriaServiceId = reportCallingDTO.WebserviceId, CriteriaConfigCriteriaConfigType = AutoCriteriaConfigType, CriteriaConfigCriteriaUserId = loginDTO.UserId, CriteriaConfigPeriodFilter = reportCallingDTO.PeriodFilter, CriteriaConfigCriteriaMenuId = reportCallingDTO.MenuId, CriteriaConfigStatus = (byte)1, CriteriaConfigVersion = (short)1, CriteriaConfigCreatedById = loginDTO.UserId, CriteriaConfigCreatedOn = currentTime, CriteriaConfigModifiedById = loginDTO.UserId, CriteriaConfigModifiedOn = currentTime, CriteriaConfigCriteriaOUId = loginDTO.WorkOUId, CriteriaConfigRecordsPerPage = (short)reportCallingDTO.RecordsPerPage, ReportFormatId = reportCallingDTO.ReportFormatId, DefaultReportViewId = reportCallingDTO.ReportViewId, CriteriaConfigSourceType = loginDTO.SourceType, UserCriteriaRunType = (byte)reportCallingDTO.CriteriaRunType }) }; for (int i = 0; i < sections.Count; i++) { var srcSection = sections[i]; int sectionId = nextId++; statements.Add((CriteriaConfigFastQB.SAVE_CRITERIACONFIGSECTION, new { CriteriaConfigSectionId = sectionId, CriteriaConfigId = criteriaConfigId, CriteriaConfigSectionSlNo = (short)(i + 1), CriteriaConfigSectionSectionJoin = (byte)srcSection.OperationType, CriteriaConfigSectionStatus = (byte)1, CriteriaConfigSectionVersion = (short)1, CriteriaConfigSectionCreatedById = loginDTO.UserId, CriteriaConfigSectionCreatedOn = currentTime, CriteriaConfigSectionModifiedById = loginDTO.UserId, CriteriaConfigSectionModifiedOn = currentTime })); var attributes = srcSection.AttributesCriteriaList; if (attributes == null) continue; for (int j = 0; j < attributes.Count; j++) { var srcAttr = attributes[j]; statements.Add((CriteriaConfigFastQB.SAVE_CRITERIACONFIGATTRIBUTE, new { CriteriaConfigAttributeId = nextId++, CriteriaSectionId = sectionId, CriteriaConfigAttributeSlNo = (short)(j + 1), CriteriaAttributeId = srcAttr.CriteriaAttributeId, CriteriaConfigAttributeOperationType = (byte)srcAttr.OperationType, CriteriaConfigAttributeCriteriaFieldValue = Convert.ToString(srcAttr.FieldValue) ?? "", CriteriaConfigAttributeCriteriaFieldValueIn = "", CriteriaConfigAttributeCriteriaJoin = (byte)srcAttr.JoinType, CriteriaConfigAttributeCriteriaFieldDisplayValue = srcAttr.CriteriaAttributeValue ?? "", CriteriaConfigAttributeCriteriaVariableField = "", WebServiceCriteriaId = -1 })); } } await _queryExecutor.ExecuteInTransactionAsync(loginDTO, statements).ConfigureAwait(false); } catch (Exception ex) { // Best-effort side effect — never fail the report response over a filter-remember write. _logger.LogWarning(ex, "SaveCriteriaConfigFastAsync failed for MenuId={MenuId}, WebserviceId={WebserviceId}, UserId={UserId}.", reportCallingDTO?.MenuId, reportCallingDTO?.WebserviceId, loginDTO?.UserId); } } private static string BuildAutoName(int menuId) { string menuName = menuId.ToString(); string suffix = Guid.NewGuid().ToString("N").Substring(0, 8); return $"Default {menuName} {suffix}"; } } }