| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259 |
- namespace Admin.NET.Plugin.AiDOP.Order;
- /// <summary>
- /// 合同评审服务 📋
- /// 路由前缀:/api/Order/contract/...
- /// 审批:由审批流插件(BizType=CONTRACT_REVIEW)+ 前端 ApprovalPanel 发起与办理;本服务仅保留列表/详情/保存/删除。
- /// </summary>
- [ApiDescriptionSettings(Order = 250, Description = "合同评审")]
- [Route("api/Order")]
- [AllowAnonymous]
- [NonUnify]
- public class ContractReviewService : IDynamicApiController, ITransient
- {
- private readonly ISqlSugarClient _db;
- private readonly SqlSugarRepository<ContractReview> _reviewRep;
- private readonly SqlSugarRepository<ContractReviewFlow> _flowRep;
- private readonly UserManager _userManager;
- public ContractReviewService(
- ISqlSugarClient db,
- SqlSugarRepository<ContractReview> reviewRep,
- SqlSugarRepository<ContractReviewFlow> flowRep,
- UserManager userManager)
- {
- _db = db;
- _reviewRep = reviewRep;
- _flowRep = flowRep;
- _userManager = userManager;
- }
- // ══════════════════════════════════════════════════════════════
- // 列表 GET /api/Order/contract/list
- // ══════════════════════════════════════════════════════════════
- /// <summary>获取合同评审分页列表 📋</summary>
- [DisplayName("获取合同评审列表")]
- [HttpGet("contract/list")]
- public async Task<object> GetContractReviewList([FromQuery] ContractReviewListInput input)
- {
- var pars = new List<SugarParameter>();
- var conditions = new List<string> { "1=1" };
- if (!string.IsNullOrWhiteSpace(input.BillNo))
- {
- conditions.Add("BillNo LIKE @BillNo");
- pars.Add(new SugarParameter("@BillNo", $"%{input.BillNo.Trim()}%"));
- }
- if (!string.IsNullOrWhiteSpace(input.Title))
- {
- conditions.Add("Title LIKE @Title");
- pars.Add(new SugarParameter("@Title", $"%{input.Title.Trim()}%"));
- }
- if (!string.IsNullOrWhiteSpace(input.CustomerName))
- {
- conditions.Add("CustomerName LIKE @CustomerName");
- pars.Add(new SugarParameter("@CustomerName", $"%{input.CustomerName.Trim()}%"));
- }
- if (!string.IsNullOrWhiteSpace(input.FlowStatus))
- {
- conditions.Add("FlowStatus = @FlowStatus");
- pars.Add(new SugarParameter("@FlowStatus", input.FlowStatus.Trim()));
- }
- var whereClause = "WHERE " + string.Join(" AND ", conditions);
- var baseSql = $"SELECT * FROM ado_contract_review {whereClause}";
- var offset = (input.Page - 1) * input.PageSize;
- var total = await _db.Ado.GetIntAsync($"SELECT COUNT(*) FROM ({baseSql}) AS t", pars);
- var list = await _db.Ado.SqlQueryAsync<ContractReviewListRow>(
- $"SELECT * FROM ({baseSql}) AS t ORDER BY t.RecID DESC LIMIT {input.PageSize} OFFSET {offset}",
- pars);
- return new { total, page = input.Page, pageSize = input.PageSize, list };
- }
- // ══════════════════════════════════════════════════════════════
- // 详情 GET /api/Order/contract/{id}
- // ══════════════════════════════════════════════════════════════
- /// <summary>获取合同评审详情(含流程节点)📋</summary>
- [DisplayName("获取合同评审详情")]
- [HttpGet("contract/{id}")]
- public async Task<object> GetContractReviewDetail(int id)
- {
- var review = await _reviewRep.GetFirstAsync(u => u.RecID == id)
- ?? throw Oops.Oh("合同评审记录不存在");
- var flows = await _flowRep.GetListAsync(u => u.ReviewRecID == id);
- return new
- {
- recID = review.RecID,
- billNo = review.BillNo,
- title = review.Title,
- customerName = review.CustomerName,
- customerNo = review.CustomerNo,
- salesCompany = review.SalesCompany,
- salesArea = review.SalesArea,
- projectCode = review.ProjectCode,
- crmNo = review.CrmNo,
- responsibleAccount = review.ResponsibleAccount,
- responsibleName = review.ResponsibleName,
- projectStartDate = review.ProjectStartDate?.ToString("yyyy-MM-dd"),
- currentStage = review.CurrentStage ?? 0,
- currentDept = review.CurrentDept,
- projectStatus = review.ProjectStatus,
- winRate = review.WinRate,
- expectedOrderMonth = review.ExpectedOrderMonth?.ToString("yyyy-MM"),
- expectedDeliveryDate = review.ExpectedDeliveryDate?.ToString("yyyy-MM-dd"),
- projectRequirement = review.ProjectRequirement,
- remark = review.Remark,
- flowStatus = review.FlowStatus ?? "draft",
- createUser = review.CreateUser,
- createTime = review.CreateTime?.ToString("yyyy-MM-dd HH:mm:ss"),
- updateTime = review.UpdateTime?.ToString("yyyy-MM-dd HH:mm:ss"),
- flows = flows.OrderBy(f => f.StageNo).ThenBy(f => f.Seq).Select(f => new
- {
- recID = f.RecID,
- reviewRecID = f.ReviewRecID,
- reviewBillNo = f.ReviewBillNo,
- stageNo = f.StageNo,
- stageName = f.StageName,
- department = f.Department,
- deptNo = f.DeptNo,
- seq = f.Seq,
- reviewerAccount = f.ReviewerAccount,
- reviewerName = f.ReviewerName,
- opinion = f.Opinion,
- startTime = f.StartTime?.ToString("yyyy-MM-dd HH:mm:ss"),
- completeTime = f.CompleteTime?.ToString("yyyy-MM-dd HH:mm:ss"),
- actualDays = f.ActualDays,
- nodeStatus = f.NodeStatus ?? "pending",
- })
- };
- }
- // ══════════════════════════════════════════════════════════════
- // 保存(新增/编辑)POST /api/Order/contract/save
- // ══════════════════════════════════════════════════════════════
- /// <summary>保存合同评审(草稿新增或编辑)📋</summary>
- [DisplayName("保存合同评审")]
- [ApiDescriptionSettings(Name = "SaveContractReview"), HttpPost("contract/save")]
- public async Task<object> SaveContractReview([FromBody] ContractReviewSaveInput input)
- {
- var now = DateTime.Now;
- var user = _userManager.Account ?? "system";
- if (input.RecID is null or 0)
- {
- // ── 新增:参照 SysJobService.AddJobDetail ──
- var month = now.ToString("yyyyMM");
- var maxSeq = await _db.Ado.GetIntAsync(
- $"SELECT IFNULL(MAX(CAST(SUBSTRING(BillNo, 9) AS UNSIGNED)), 0) FROM ado_contract_review WHERE BillNo LIKE 'CR{month}%'");
- var billNo = $"CR{month}{(maxSeq + 1):D4}";
- var entity = new ContractReview
- {
- BillNo = billNo,
- Title = input.Title,
- CustomerName = input.CustomerName,
- CustomerNo = input.CustomerNo,
- SalesCompany = input.SalesCompany,
- SalesArea = input.SalesArea,
- ProjectCode = input.ProjectCode,
- CrmNo = input.CrmNo,
- ResponsibleAccount = input.ResponsibleAccount,
- ResponsibleName = input.ResponsibleName,
- ProjectStartDate = string.IsNullOrWhiteSpace(input.ProjectStartDate) ? null : DateTime.Parse(input.ProjectStartDate),
- ProjectStatus = input.ProjectStatus,
- WinRate = input.WinRate,
- ExpectedOrderMonth = string.IsNullOrWhiteSpace(input.ExpectedOrderMonth) ? null : DateTime.Parse(input.ExpectedOrderMonth + "-01"),
- ExpectedDeliveryDate = string.IsNullOrWhiteSpace(input.ExpectedDeliveryDate) ? null : DateTime.Parse(input.ExpectedDeliveryDate),
- ProjectRequirement = input.ProjectRequirement,
- Remark = input.Remark,
- FlowStatus = "draft",
- CurrentStage = 0,
- CreateUser = user,
- CreateTime = now,
- IsActive = 1,
- };
- await _reviewRep.InsertAsync(entity);
- // 取刚插入行的 RecID
- var newId = await _db.Ado.GetIntAsync(
- "SELECT MAX(RecID) FROM ado_contract_review WHERE BillNo = @BillNo",
- new SugarParameter("@BillNo", billNo));
- return new { id = newId, billNo, message = "新增成功" };
- }
- else
- {
- // ── 编辑:参照 SysJobService.UpdateJobDetail ──
- var entity = await _reviewRep.GetFirstAsync(u => u.RecID == input.RecID.Value)
- ?? throw Oops.Oh("合同评审记录不存在");
- if (entity.FlowStatus == "reviewing")
- throw Oops.Oh("审批中的合同评审不允许编辑,如需修改请先驳回");
- entity.Title = input.Title;
- entity.CustomerName = input.CustomerName;
- entity.CustomerNo = input.CustomerNo;
- entity.SalesCompany = input.SalesCompany;
- entity.SalesArea = input.SalesArea;
- entity.ProjectCode = input.ProjectCode;
- entity.CrmNo = input.CrmNo;
- entity.ResponsibleAccount = input.ResponsibleAccount;
- entity.ResponsibleName = input.ResponsibleName;
- entity.ProjectStartDate = string.IsNullOrWhiteSpace(input.ProjectStartDate) ? null : DateTime.Parse(input.ProjectStartDate);
- entity.ProjectStatus = input.ProjectStatus;
- entity.WinRate = input.WinRate;
- entity.ExpectedOrderMonth = string.IsNullOrWhiteSpace(input.ExpectedOrderMonth) ? null : DateTime.Parse(input.ExpectedOrderMonth + "-01");
- entity.ExpectedDeliveryDate = string.IsNullOrWhiteSpace(input.ExpectedDeliveryDate) ? null : DateTime.Parse(input.ExpectedDeliveryDate);
- entity.ProjectRequirement = input.ProjectRequirement;
- entity.Remark = input.Remark;
- entity.UpdateUser = user;
- entity.UpdateTime = now;
- await _reviewRep.UpdateAsync(entity);
- return new { id = entity.RecID, billNo = entity.BillNo, message = "编辑成功" };
- }
- }
- // ══════════════════════════════════════════════════════════════
- // 删除 POST /api/Order/contract/delete
- // ══════════════════════════════════════════════════════════════
- /// <summary>删除合同评审(审批中不允许删除)📋</summary>
- [DisplayName("删除合同评审")]
- [ApiDescriptionSettings(Name = "DeleteContractReview"), HttpPost("contract/delete")]
- public async Task<object> DeleteContractReview([FromBody] ContractReviewDeleteInput input)
- {
- // 参照 SysJobService.DeleteJobDetail:先查再删,同时删关联数据
- var entity = await _reviewRep.GetFirstAsync(u => u.RecID == input.RecID)
- ?? throw Oops.Oh("合同评审记录不存在");
- if (entity.FlowStatus == "reviewing")
- throw Oops.Oh("审批中的合同评审不允许删除");
- await _flowRep.DeleteAsync(u => u.ReviewRecID == input.RecID);
- await _reviewRep.DeleteAsync(u => u.RecID == input.RecID);
- return new { message = "删除成功" };
- }
- // ──────────────── 内部查询结果映射类 ────────────────
- private sealed class ContractReviewListRow
- {
- public int RecID { get; set; }
- public string? BillNo { get; set; }
- public string? Title { get; set; }
- public string? CustomerName { get; set; }
- public string? SalesCompany { get; set; }
- public int? CurrentStage { get; set; }
- public string? CurrentDept { get; set; }
- public string? FlowStatus { get; set; }
- public string? ResponsibleAccount { get; set; }
- public string? ResponsibleName { get; set; }
- public DateTime? CreateTime { get; set; }
- public DateTime? UpdateTime { get; set; }
- }
- }
|