diff --git a/QYZH.InteractiveMagazine.IService/IJournalPageTaskService.cs b/QYZH.InteractiveMagazine.IService/IJournalPageTaskService.cs index 24faa58..3a64d73 100644 --- a/QYZH.InteractiveMagazine.IService/IJournalPageTaskService.cs +++ b/QYZH.InteractiveMagazine.IService/IJournalPageTaskService.cs @@ -9,7 +9,6 @@ public interface IJournalPageTaskService : IBaseService { Task InsertAsync(JournalPageTaskAddInput input); Task UpdateAsync(JournalPageTaskUpdateInput input); - Task KeywordAnalysisAsync(JournalPageTaskKeywordAnalysis input); Task DetailAsync(long id); Task DeleteAsync(long id); diff --git a/QYZH.InteractiveMagazine.Models/Dto/Journal/JournalPageTaskOutput.cs b/QYZH.InteractiveMagazine.Models/Dto/Journal/JournalPageTaskOutput.cs index bff386a..4a531fd 100644 --- a/QYZH.InteractiveMagazine.Models/Dto/Journal/JournalPageTaskOutput.cs +++ b/QYZH.InteractiveMagazine.Models/Dto/Journal/JournalPageTaskOutput.cs @@ -1,4 +1,4 @@ -using QYZH.InteractiveMagazine.Models.Enum; +using QYZH.InteractiveMagazine.Models.Enum; using QYZH.InteractiveMagazine.Common.Extensions; using QYZH.InteractiveMagazine.Common.Helpers; using QYZH.InteractiveMagazine.Models.Enum; @@ -47,36 +47,56 @@ namespace QYZH.InteractiveMagazine.Models.Dto.Journal } /// - /// 选项 + /// 答案列表 /// - public string Options { get; set; } + public List Answers { get; set; } - private string _answer; + private string _imageUrl; /// - /// 答案 + /// 图片地址 /// - public string Answer + public string ImageUrl { - get { return _answer.AddDomain(DomainHelper.OssDomain); } - set { _answer = value; } + get { return DomainHelper.OssFullUrl(_imageUrl); } + set { _imageUrl = value; } } - private string _analysis; - /// - /// 解析 - /// - public string Analysis - { - get { return _analysis.AddDomain(DomainHelper.OssDomain); } - set { _analysis = value; } - } - - public string AnalysisUrl { get; set; } + public List ImageUrls { get; set; } /// - /// 问题分数 + /// 积分 /// - public float TaskScore { get; set; } + public float Points { get; set; } + + /// + /// 成长值 + /// + public float GrowthPoint { get; set; } + + /// + /// 理解力评分 + /// + public float Comprehension { get; set; } + + /// + /// 判断力评分 + /// + public float Judgment { get; set; } + + /// + /// 表达力评分 + /// + public float Expression { get; set; } + + /// + /// 说服力评分 + /// + public float Persuasiveness { get; set; } + + /// + /// 作答参考时间(秒) + /// + public int AnswerTime { get; set; } private string _audioUrl; /// @@ -108,28 +128,6 @@ namespace QYZH.InteractiveMagazine.Models.Dto.Journal set { _pointsUrl = value; } } - private string _imageUrl; - /// - /// 图片地址 - /// - public string ImageUrl - { - get { return DomainHelper.OssFullUrl(_imageUrl); } - set { _imageUrl = value; } - } - - public List ImageUrls { get; set; } - - /// - /// 问题分数 - /// - public float Score { get; set; } - - /// - /// 回答时间(秒) - /// - public int AnswerTime { get; set; } - /// /// 音频开始时间 /// @@ -145,14 +143,37 @@ namespace QYZH.InteractiveMagazine.Models.Dto.Journal /// public string KnowledgePointIds { get; set; } - /// - /// 回答项解析 - /// - public string KeywordAnalysis { get; set; } - /// /// 年级 /// public int Grade { get; set; } } + + /// + /// 答案输出 + /// + public class JournalTaskAnswerOutput + { + public long Id { get; set; } + + private string _answer; + /// + /// 参考答案 + /// + public string Answer + { + get { return _answer.AddDomain(DomainHelper.OssDomain); } + set { _answer = value; } + } + + private string _answerUrl; + /// + /// 参考答案图片 + /// + public string AnswerUrl + { + get { return _answerUrl.AddDomain(DomainHelper.OssDomain); } + set { _answerUrl = value; } + } + } } diff --git a/QYZH.InteractiveMagazine.Models/Dto/Journal/JournalPageTaskUpdateInput.cs b/QYZH.InteractiveMagazine.Models/Dto/Journal/JournalPageTaskUpdateInput.cs index 8420e79..1ce5927 100644 --- a/QYZH.InteractiveMagazine.Models/Dto/Journal/JournalPageTaskUpdateInput.cs +++ b/QYZH.InteractiveMagazine.Models/Dto/Journal/JournalPageTaskUpdateInput.cs @@ -13,11 +13,10 @@ namespace QYZH.InteractiveMagazine.Models.Dto.Journal public long Id { get; set; } /// - /// 书Id + /// 杂志Id /// public long JournalId { get; set; } - /// /// 书页id /// @@ -38,60 +37,41 @@ namespace QYZH.InteractiveMagazine.Models.Dto.Journal /// public string Task { get; set; } - /// - /// 选项 - /// - public string Options { get; set; } - /// /// 答案 /// - public string Answer { get; set; } + public List TaskAnswer { get; set; } /// - /// 答案图片 + /// 积分 /// - public string AnswerUrl { get; set; } - + public int Points { get; set; } /// - /// 解析 + /// 成长值 /// - public string Analysis { get; set; } - + public float GrowthPoint { get; set; } /// - /// 解析图片地址 + /// 理解力评分 /// - public string AnalysisUrl { get; set; } - + public float Comprehension { get; set; } /// - /// 问题分数 + /// 判断力评分 /// - public float Score { get; set; } + public float Judgment { get; set; } + /// + /// 表达力评分 + /// + public float Expression { get; set; } + /// + /// 说服力评分 + /// + public float Persuasiveness { get; set; } /// /// 回答时间秒 /// public int AnswerTime { get; set; } - /// - /// 图片 - /// - public string ImageUrl { get; set; } - - /// - /// 视频 - /// - public string VideoUrl { get; set; } - - /// - /// 学科Id - /// - public long SubjectId { get; set; } - - /// - /// 关联的知识点ids - /// - public string KnowledgepointIds { get; set; } } public class JournalPageTaskComplementInput diff --git a/QYZH.InteractiveMagazine.Models/Dto/Journal/JournalPageV2Output.cs b/QYZH.InteractiveMagazine.Models/Dto/Journal/JournalPageV2Output.cs index 06de1c9..e8a97d1 100644 --- a/QYZH.InteractiveMagazine.Models/Dto/Journal/JournalPageV2Output.cs +++ b/QYZH.InteractiveMagazine.Models/Dto/Journal/JournalPageV2Output.cs @@ -61,19 +61,9 @@ namespace QYZH.InteractiveMagazine.Models.Dto.Journal public string ShowType => Type.GetDescription(); /// - /// 选项 + /// 答案列表 /// - public string Options { get; set; } - - /// - /// 答案 - /// - public string Answers { get; set; } - - /// - /// 解析 - /// - public string Analysis { get; set; } + public List Answers { get; set; } /// /// 是否分配 diff --git a/QYZH.InteractiveMagazine.Models/Dto/Journal/JournalTaskAnswerInput.cs b/QYZH.InteractiveMagazine.Models/Dto/Journal/JournalTaskAnswerInput.cs new file mode 100644 index 0000000..43d87e1 --- /dev/null +++ b/QYZH.InteractiveMagazine.Models/Dto/Journal/JournalTaskAnswerInput.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace QYZH.InteractiveMagazine.Models.Dto.Journal +{ + public class JournalTaskAnswerInput + { + /// + /// 参考答案 + /// + public string Answer { get; set; } + /// + /// 参考答案图片 + /// + public string AnswerUrl { get; set; } + } +} diff --git a/QYZH.InteractiveMagazine.Models/Entity/JournalPageTask.cs b/QYZH.InteractiveMagazine.Models/Entity/JournalPageTask.cs index 3af953c..06e9f5b 100644 --- a/QYZH.InteractiveMagazine.Models/Entity/JournalPageTask.cs +++ b/QYZH.InteractiveMagazine.Models/Entity/JournalPageTask.cs @@ -12,94 +12,135 @@ namespace QYZH.InteractiveMagazine.Models.Entity [SugarTable("JournalPageTask")] public partial class JournalPageTask : SqlSugarBaseEntity { - public JournalPageTask(){ + public JournalPageTask() + { - } + } - /// - /// Desc:书id - /// Default: - /// Nullable:False - /// - public long JournalId {get;set;} + /// + /// Desc:书id + /// Default: + /// Nullable:False + /// + public long JournalId { get; set; } - /// - /// Desc:书页id - /// Default: - /// Nullable:False - /// - public long JournalPageId {get;set;} + /// + /// Desc:书页id + /// Default: + /// Nullable:False + /// + public long JournalPageId { get; set; } + /// + /// Desc:分组 + /// Default: + /// Nullable:False + /// + public long GroupId { get; set; } + /// + /// Desc:题号 + /// Default: + /// Nullable:True + /// + public string No { get; set; } - /// - /// Desc:题号 - /// Default: - /// Nullable:True - /// - public string No {get;set;} + /// + /// Desc:题型 + /// Default: + /// Nullable:False + /// + public TaskBankTypeEnum Type { get; set; } - /// - /// Desc:题型 - /// Default: - /// Nullable:False - /// - public TaskBankTypeEnum Type {get;set;} + /// + /// Desc:任务 + /// Default: + /// Nullable:True + /// + public string Task { get; set; } - /// - /// Desc:任务 - /// Default: - /// Nullable:True - /// - public string Task {get;set;} - /// - /// Desc:分组 - /// Default: - /// Nullable:False - /// - public long GroupId {get;set;} + /// + /// Desc:成长值设置 + /// Default:0 + /// Nullable:True + /// + public int? GrowthPoint { get; set; } - /// - /// Desc:乐观锁 - /// Default: - /// Nullable:False - /// - public int Revision {get;set;} + /// + /// Desc:积分设置 + /// Default:0 + /// Nullable:True + /// + public int Points { get; set; } + /// + /// Desc:理解力评分 + /// Default:0 + /// Nullable:False + /// + public float Comprehension { get; set; } - /// - /// Desc:任务图片地址 - /// Default: - /// Nullable:True - /// - public string TaskUrl {get;set;} + /// + /// Desc:判断力评分 + /// Default:0 + /// Nullable:False + /// + public float Judgment { get; set; } - /// - /// Desc:选项 - /// Default: - /// Nullable:True - /// - public string Options {get;set;} + /// + /// Desc:表达力评分 + /// Default:0 + /// Nullable:False + /// + public float Expression { get; set; } - /// - /// Desc:是否需要AI处理 - /// Default:true - /// Nullable:False - /// - public bool NeedAiProcess {get;set;} + /// + /// Desc:说服力评分 + /// Default:0 + /// Nullable:False + /// + public float Persuasiveness { get; set; } + /// + /// Desc:乐观锁 + /// Default: + /// Nullable:False + /// + public int Revision { get; set; } - /// - /// Desc:基础Prompt配置ID(为空则使用IsDefault=1的模板) - /// Default: - /// Nullable:True - /// - public long? BasePromptId {get;set;} + /// + /// Desc:任务图片地址 + /// Default: + /// Nullable:True + /// + public string TaskUrl { get; set; } - /// - /// Desc:个性化Prompt(追加到基础Prompt后面,可为空) - /// Default: - /// Nullable:True - /// - public string CustomPrompt {get;set;} + + /// + /// Desc:是否需要AI处理 + /// Default:true + /// Nullable:False + /// + public bool NeedAiProcess { get; set; } + + /// + /// Desc:基础Prompt配置ID(为空则使用IsDefault=1的模板) + /// Default: + /// Nullable:True + /// + public long? BasePromptId { get; set; } + + /// + /// Desc:个性化Prompt(追加到基础Prompt后面,可为空) + /// Default: + /// Nullable:True + /// + public string CustomPrompt { get; set; } + + /// + /// Desc:作答参考时间 + /// Default: + /// Nullable:True + /// + public int AnswerTime { get; set; } } } diff --git a/QYZH.InteractiveMagazine.Models/Entity/JournalPageTaskAnswer.cs b/QYZH.InteractiveMagazine.Models/Entity/JournalPageTaskAnswer.cs index c892f0d..920666d 100644 --- a/QYZH.InteractiveMagazine.Models/Entity/JournalPageTaskAnswer.cs +++ b/QYZH.InteractiveMagazine.Models/Entity/JournalPageTaskAnswer.cs @@ -35,70 +35,7 @@ namespace QYZH.InteractiveMagazine.Models.Entity /// Default: /// Nullable:True /// - public string Analysis {get;set;} - - /// - /// Desc:回答时间(秒) - /// Default:0 - /// Nullable:False - /// - public int AnswerTime {get;set;} - - /// - /// Desc:任务分数 - /// Default:0 - /// Nullable:False - /// - public float Score {get;set;} - - /// - /// Desc:关键解析json - /// Default: - /// Nullable:True - /// - public string KeywordAnalysis {get;set;} - - /// - /// Desc:成长值设置 - /// Default:0 - /// Nullable:True - /// - public int? GrowthPoint {get;set;} - - /// - /// Desc:积分设置 - /// Default:0 - /// Nullable:True - /// - public int? Points {get;set;} - - /// - /// Desc:理解力评分 - /// Default:0 - /// Nullable:False - /// - public float Comprehension {get;set;} - - /// - /// Desc:判断力评分 - /// Default:0 - /// Nullable:False - /// - public float Judgment {get;set;} - - /// - /// Desc:表达力评分 - /// Default:0 - /// Nullable:False - /// - public float Expression {get;set;} - - /// - /// Desc:说服力评分 - /// Default:0 - /// Nullable:False - /// - public float Persuasiveness {get;set;} + public string AnswerUrL { get;set;} } } diff --git a/QYZH.InteractiveMagazine.Service/JournalPageService.cs b/QYZH.InteractiveMagazine.Service/JournalPageService.cs index d170798..d882303 100644 --- a/QYZH.InteractiveMagazine.Service/JournalPageService.cs +++ b/QYZH.InteractiveMagazine.Service/JournalPageService.cs @@ -143,20 +143,33 @@ public class JournalPageService(BaseRepository JournalRepository, if (output != null) { - output.Tasks = await JournalPageTaskRepository.Queryable() - .LeftJoin((a, ans) => ans.JournalPageTaskId == a.Id) - .Where((a, ans) => a.JournalPageId == output.JournalPageId) - .Select((a, ans) => new JournalPageTaskV2Output - { - Id = a.Id, - GroupId = a.GroupId, - No = a.No, - Type = (TaskBankTypeEnum)a.Type, - Options = a.Options, - Answers = ans.Answer, - Analysis = ans.Analysis, - }) + var tasks = await JournalPageTaskRepository.Queryable() + .Where(a => a.JournalPageId == output.JournalPageId) .ToListAsync(); + + if (tasks.Count > 0) + { + var taskIds = tasks.Select(t => t.Id).ToList(); + var allAnswers = await JournalPageTaskAnswerRepository.Queryable() + .Where(a => taskIds.Contains(a.JournalPageTaskId)) + .ToListAsync(); + + output.Tasks = tasks.Select(t => new JournalPageTaskV2Output + { + Id = t.Id, + GroupId = t.GroupId, + No = t.No, + Type = t.Type, + Answers = allAnswers + .Where(a => a.JournalPageTaskId == t.Id) + .Select(a => new JournalTaskAnswerOutput + { + Id = a.Id, + Answer = a.Answer, + AnswerUrl = a.AnswerUrL + }).ToList() + }).ToList(); + } } //if (output?.Areas != null) // output.Areas = await _JournalPageOtherRepository.Queryable().Where(w => w.JournalPageId == output.JournalPageId).Select().ToListAsync(); diff --git a/QYZH.InteractiveMagazine.Service/JournalPageTaskService.cs b/QYZH.InteractiveMagazine.Service/JournalPageTaskService.cs index c3f228d..48277a1 100644 --- a/QYZH.InteractiveMagazine.Service/JournalPageTaskService.cs +++ b/QYZH.InteractiveMagazine.Service/JournalPageTaskService.cs @@ -33,36 +33,7 @@ public class JournalPageTaskService(BaseRepository journalRepository, O map.Type = groupTask.Type; } - var data = await base.InsertAsync(map); - - // 创建默认答案记录 - var answer = new JournalPageTaskAnswer - { - JournalPageTaskId = map.Id, - CreatedBy = "System", - UpdatedBy = "System", - CreatedAt = DateTime.Now, - UpdatedAt = DateTime.Now, - IsDeleted = false - }; - - // 如果是关联跨页题目,从第一部分的 Answer 复制 Score 和 AnswerTime - if (no.Last() >= 2) - { - var startNo = $"{no[0]}-{no[1]}-{no[2]}-1"; - var firstTask = await Queryable().Where(w => w.No == startNo && w.JournalId == input.JournalId).FirstAsync(); - if (firstTask != null) - { - var firstAnswer = await answerRepository.Queryable().Where(a => a.JournalPageTaskId == firstTask.Id).FirstAsync(); - if (firstAnswer != null) - { - answer.Score = firstAnswer.Score; - answer.AnswerTime = firstAnswer.AnswerTime; - } - } - } - - await answerRepository.InsertAsync(answer); + await base.InsertAsync(map); return map?.Id; } @@ -82,13 +53,20 @@ public class JournalPageTaskService(BaseRepository journalRepository, O var key = $"journal/{task.JournalId}/{task.JournalPageId}/{task.GroupId}"; - // 题目侧字段处理 + // 题目内容处理 input.Task = Deal(task.Task, input.Task, key, "task"); task.Type = input.Type; task.Task = input.Task; - task.Options = input.Options; task.No = input.No; + task.Points = input.Points; + task.GrowthPoint = (int?)input.GrowthPoint; + task.Comprehension = input.Comprehension; + task.Judgment = input.Judgment; + task.Expression = input.Expression; + task.Persuasiveness = input.Persuasiveness; + task.AnswerTime = input.AnswerTime; + var no = input.No.Split('-').Select(int.Parse).ToArray(); if (no.Last() >= 2) { @@ -101,89 +79,68 @@ public class JournalPageTaskService(BaseRepository journalRepository, O var taskResult = await base.Updateable(task).ExecuteCommandAsync() > 0; - // 答案侧字段处理 - var answer = await answerRepository.Queryable().Where(a => a.JournalPageTaskId == task.Id).FirstAsync(); - if (answer == null) - { - // 兼容旧数据:如果 Answer 记录不存在则创建 - answer = new JournalPageTaskAnswer - { - JournalPageTaskId = task.Id, - CreatedBy = "System", - CreatedAt = DateTime.Now, - IsDeleted = false - }; - } + // 答案处理:先删后插 + await answerRepository.DeleteAsync(a => a.JournalPageTaskId == task.Id); - // 答案/解析内容处理 - answer.Answer = Deal(answer.Answer, input.Answer, key, "answer"); - answer.Analysis = Deal(answer.Analysis, input.Analysis, key, "analysis"); - answer.Score = input.Score; - answer.AnswerTime = input.AnswerTime; - answer.UpdatedBy = "System"; - answer.UpdatedAt = DateTime.Now; - - if (no.Last() >= 2) + if (input.TaskAnswer != null && input.TaskAnswer.Count > 0) { - var startNo = $"{no[0]}-{no[1]}-{no[2]}-1"; - var firstTask = await Queryable().Where(w => w.No == startNo && w.JournalId == input.JournalId).FirstAsync(); - if (firstTask != null) + foreach (var ansInput in input.TaskAnswer) { - var firstAnswer = await answerRepository.Queryable().Where(a => a.JournalPageTaskId == firstTask.Id).FirstAsync(); - if (firstAnswer != null) + // 处理答案中的文件OSS拷贝 + ansInput.Answer = Deal(null, ansInput.Answer, key, "answer"); + ansInput.AnswerUrl = Deal(null, ansInput.AnswerUrl, key, "answerUrl"); + + var answerEntity = new JournalPageTaskAnswer { - answer.Score = firstAnswer.Score; - answer.AnswerTime = firstAnswer.AnswerTime; - } + JournalPageTaskId = task.Id, + Answer = ansInput.Answer, + AnswerUrL = ansInput.AnswerUrl, + CreatedBy = "System", + CreatedAt = DateTime.Now, + IsDeleted = false + }; + await answerRepository.InsertAsync(answerEntity); } } - if (answer.Id == 0) - { - await answerRepository.InsertAsync(answer); - } - else - { - await answerRepository.UpdateAsync(answer); - } - return taskResult; } - public async Task KeywordAnalysisAsync(JournalPageTaskKeywordAnalysis input) - { - // KeywordAnalysis 已移至 Answer 表,通过 GroupId 关联的 Task 找到对应的 Answer 记录进行更新 - var taskIds = await Queryable().Where(w => w.GroupId == input.Id).Select(w => w.Id).ToListAsync(); - if (taskIds.Count == 0) return false; - - return await answerRepository.Updateable() - .SetColumns(s => s.KeywordAnalysis, input.KeywordAnalysis) - .Where(a => taskIds.Contains(a.JournalPageTaskId)) - .ExecuteCommandAsync() > 0; - } - public async Task DetailAsync(long id) { - var data = await base.Queryable() - .InnerJoin((w, a) => a.JournalPageTaskId == w.Id) - .Where((w, a) => w.Id == id) - .Select((w, a) => new JournalPageTaskOutput() - { - Id = w.Id, - JournalId = w.JournalId, - JournalPageId = w.JournalPageId, - No = w.No, - Type = (TaskBankTypeEnum)w.Type, - Task = w.Task, - Options = w.Options, - Answer = a.Answer, - Analysis = a.Analysis, - Score = a.Score, - AnswerTime = a.AnswerTime, - KeywordAnalysis = a.KeywordAnalysis - }, true).FirstAsync(); - return data; + var task = await base.Queryable().Where(w => w.Id == id).FirstAsync(); + if (task == null) return null; + var data = new JournalPageTaskOutput + { + Id = task.Id, + JournalId = task.JournalId, + JournalPageId = task.JournalPageId, + No = task.No, + Type = task.Type, + Task = task.Task, + Points = task.Points, + GrowthPoint = task.GrowthPoint ?? 0, + Comprehension = task.Comprehension, + Judgment = task.Judgment, + Expression = task.Expression, + Persuasiveness = task.Persuasiveness, + AnswerTime = task.AnswerTime, + }; + + // 查询答案列表 + var answers = await answerRepository.Queryable() + .Where(a => a.JournalPageTaskId == id) + .ToListAsync(); + + data.Answers = answers.Select(a => new JournalTaskAnswerOutput + { + Id = a.Id, + Answer = a.Answer, + AnswerUrl = a.AnswerUrL + }).ToList(); + + return data; } public async Task DeleteAsync(long id) diff --git a/QYZH.InteractiveMagazine.WebApi/Controllers/JournalController.cs b/QYZH.InteractiveMagazine.WebApi/Controllers/JournalController.cs index c4cd2ef..4f32dde 100644 --- a/QYZH.InteractiveMagazine.WebApi/Controllers/JournalController.cs +++ b/QYZH.InteractiveMagazine.WebApi/Controllers/JournalController.cs @@ -461,18 +461,6 @@ namespace QYZH.InteractiveMagazine.WebApi.Controllers return BaseResponse.Success(data.Value); } - /// - /// 书页问题单项解析 - /// - /// - [HttpPost, Route("page/task/keyword-analysis")] - [ProducesResponseType(typeof(BaseResponse), 200)] - public async Task> KeywordAnalysisAsync(JournalPageTaskKeywordAnalysis input) - { - var data = await JournalPageTaskService.KeywordAnalysisAsync(input); - return BaseResponse.Success(data); - } - /// /// 书页问题更新 /// diff --git a/QYZH.InteractiveMagazine.WebApi/Controllers/WeChat/WeChatAuthController.cs b/QYZH.InteractiveMagazine.WebApi/Controllers/WeChat/WeChatAuthController.cs index 3e0bcae..3c82d15 100644 --- a/QYZH.InteractiveMagazine.WebApi/Controllers/WeChat/WeChatAuthController.cs +++ b/QYZH.InteractiveMagazine.WebApi/Controllers/WeChat/WeChatAuthController.cs @@ -33,8 +33,9 @@ public class WeChatAuthController : WeChatBaseController { try { - var result = await _weChatAuthService.LoginAsync(input); - return Success(result); + //var result = await _weChatAuthService.LoginAsync(input); + //return Success(result); + return BaseResponse.Fail("微信登录失败,请稍后重试"); } catch (BusinessException ex) {