diff --git a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqKdKdjlb/LqKdKdjlbCrInput.cs b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqKdKdjlb/LqKdKdjlbCrInput.cs
index 431f4bc..79db752 100644
--- a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqKdKdjlb/LqKdKdjlbCrInput.cs
+++ b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqKdKdjlb/LqKdKdjlbCrInput.cs
@@ -146,6 +146,11 @@ namespace NCC.Extend.Entitys.Dto.LqKdKdjlb
public decimal supplementAmount { get; set; }
///
+ /// 预约记录ID
+ ///
+ public string appointmentId { get; set; }
+
+ ///
/// 扣款信息
///
public List lqKdKdjlbDeductList { get; set; }
diff --git a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqKdKdjlb/LqKdKdjlbInfoOutput.cs b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqKdKdjlb/LqKdKdjlbInfoOutput.cs
index 498657a..53c5625 100644
--- a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqKdKdjlb/LqKdKdjlbInfoOutput.cs
+++ b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqKdKdjlb/LqKdKdjlbInfoOutput.cs
@@ -173,6 +173,16 @@ namespace NCC.Extend.Entitys.Dto.LqKdKdjlb
public string activityName { get; set; }
///
+ /// 预约记录ID
+ ///
+ public string appointmentId { get; set; }
+
+ ///
+ /// 预约记录时间
+ ///
+ public DateTime? appointmentTime { get; set; }
+
+ ///
/// 健康师业绩
///
public List lqKdJksyjList { get; set; }
diff --git a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqKdKdjlb/LqKdKdjlbListOutput.cs b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqKdKdjlb/LqKdKdjlbListOutput.cs
index 6ab7a25..46f5eff 100644
--- a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqKdKdjlb/LqKdKdjlbListOutput.cs
+++ b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqKdKdjlb/LqKdKdjlbListOutput.cs
@@ -167,6 +167,15 @@ namespace NCC.Extend.Entitys.Dto.LqKdKdjlb
public string createUserName { get; set; }
///
+ /// 预约记录ID
+ ///
+ public string appointmentId { get; set; }
+ ///
+ /// 预约记录时间
+ ///
+ public DateTime? appointmentTime { get; set; }
+
+ ///
/// 开单品项明细列表
///
public List ItemDetails { get; set; }
diff --git a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqYaoyjl/LqYaoyjlCrInput.cs b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqYaoyjl/LqYaoyjlCrInput.cs
index 7455f34..9789687 100644
--- a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqYaoyjl/LqYaoyjlCrInput.cs
+++ b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqYaoyjl/LqYaoyjlCrInput.cs
@@ -48,5 +48,10 @@ namespace NCC.Extend.Entitys.Dto.LqYaoyjl
///
public string lxjl { get; set; }
+ ///
+ /// 拓客编号
+ ///
+ public string tkbh { get; set; }
+
}
}
diff --git a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqYaoyjl/LqYaoyjlListOutput.cs b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqYaoyjl/LqYaoyjlListOutput.cs
index 4f9d354..af0549c 100644
--- a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqYaoyjl/LqYaoyjlListOutput.cs
+++ b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqYaoyjl/LqYaoyjlListOutput.cs
@@ -53,6 +53,11 @@ namespace NCC.Extend.Entitys.Dto.LqYaoyjl
public string lxjl { get; set; }
///
+ /// 拓客编号
+ ///
+ public string tkbh { get; set; }
+
+ ///
/// 所属门店ID
///
public string storeId { get; set; }
diff --git a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqYyjl/LqYyjlCrInput.cs b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqYyjl/LqYyjlCrInput.cs
index b060522..83ed150 100644
--- a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqYyjl/LqYyjlCrInput.cs
+++ b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqYyjl/LqYyjlCrInput.cs
@@ -73,5 +73,10 @@ namespace NCC.Extend.Entitys.Dto.LqYyjl
///
public string F_Status { get; set; }
+ ///
+ /// 邀约记录ID
+ ///
+ public string InviteId { get; set; }
+
}
}
diff --git a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqYyjl/LqYyjlInfoOutput.cs b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqYyjl/LqYyjlInfoOutput.cs
index 843a62d..b98398d 100644
--- a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqYyjl/LqYyjlInfoOutput.cs
+++ b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqYyjl/LqYyjlInfoOutput.cs
@@ -88,5 +88,19 @@ namespace NCC.Extend.Entitys.Dto.LqYyjl
///
public string F_Status { get; set; }
+ ///
+ /// 未成交说明
+ ///
+ public string NoDealRemark { get; set; }
+
+ ///
+ /// 邀约记录ID
+ ///
+ public string InviteId { get; set; }
+
+ ///
+ /// 邀约记录时间
+ ///
+ public DateTime? InviteTime { get; set; }
}
}
diff --git a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqYyjl/LqYyjlListOutput.cs b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqYyjl/LqYyjlListOutput.cs
index 7b2369d..6eaf1d2 100644
--- a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqYyjl/LqYyjlListOutput.cs
+++ b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqYyjl/LqYyjlListOutput.cs
@@ -87,5 +87,20 @@ namespace NCC.Extend.Entitys.Dto.LqYyjl
///
public string F_Status { get; set; }
+ ///
+ /// 未成交说明
+ ///
+ public string NoDealRemark { get; set; }
+
+ ///
+ /// 邀约记录ID
+ ///
+ public string InviteId { get; set; }
+
+ ///
+ /// 邀约记录时间
+ ///
+ public DateTime? InviteTime { get; set; }
+
}
}
diff --git a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Entity/lq_kd_kdjlb/LqKdKdjlbEntity.cs b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Entity/lq_kd_kdjlb/LqKdKdjlbEntity.cs
index cf18be8..5f21321 100644
--- a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Entity/lq_kd_kdjlb/LqKdKdjlbEntity.cs
+++ b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Entity/lq_kd_kdjlb/LqKdKdjlbEntity.cs
@@ -207,6 +207,12 @@ namespace NCC.Extend.Entitys.lq_kd_kdjlb
public string ActivityId { get; set; }
///
+ /// 预约记录ID(关联lq_yyjl.F_Id,用于统计预约→开单转化率)
+ ///
+ [SugarColumn(ColumnName = "F_AppointmentId")]
+ public string AppointmentId { get; set; }
+
+ ///
/// 已缴欠款
///
[SugarColumn(ColumnName = "F_PaidDebt")]
@@ -223,5 +229,23 @@ namespace NCC.Extend.Entitys.lq_kd_kdjlb
///
[SugarColumn(ColumnName = "F_SupplementAmount")]
public decimal SupplementAmount { get; set; }
+
+ ///
+ /// 升生美(再次开单时,包含生美品项的订单)
+ ///
+ [SugarColumn(ColumnName = "F_UpgradeLifeBeauty")]
+ public string UpgradeLifeBeauty { get; set; }
+
+ ///
+ /// 升科美(再次开单时,包含科美品项的订单)
+ ///
+ [SugarColumn(ColumnName = "F_UpgradeTechBeauty")]
+ public string UpgradeTechBeauty { get; set; }
+
+ ///
+ /// 升医美(再次开单时,包含医美品项的订单)
+ ///
+ [SugarColumn(ColumnName = "F_UpgradeMedicalBeauty")]
+ public string UpgradeMedicalBeauty { get; set; }
}
}
diff --git a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Entity/lq_xh_hyhk/LqXhHyhkEntity.cs b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Entity/lq_xh_hyhk/LqXhHyhkEntity.cs
index 8c5ab50..d6e383c 100644
--- a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Entity/lq_xh_hyhk/LqXhHyhkEntity.cs
+++ b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Entity/lq_xh_hyhk/LqXhHyhkEntity.cs
@@ -144,5 +144,11 @@ namespace NCC.Extend.Entitys.lq_xh_hyhk
///
[SugarColumn(ColumnName = "F_OvertimeSgfy")]
public decimal? OvertimeSgfy { get; set; }
+
+ ///
+ /// 预约记录ID(关联lq_yyjl.F_Id,用于统计预约→耗卡转化率)
+ ///
+ [SugarColumn(ColumnName = "F_AppointmentId")]
+ public string AppointmentId { get; set; }
}
}
diff --git a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Entity/lq_yyjl/LqYyjlEntity.cs b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Entity/lq_yyjl/LqYyjlEntity.cs
index 576621c..122c638 100644
--- a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Entity/lq_yyjl/LqYyjlEntity.cs
+++ b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Entity/lq_yyjl/LqYyjlEntity.cs
@@ -90,6 +90,18 @@ namespace NCC.Extend.Entitys.lq_yyjl
public string F_Status { get; set; }
///
+ /// 邀约记录ID(关联lq_yaoyjl.F_Id,用于统计邀约→预约转化率)
+ ///
+ [SugarColumn(ColumnName = "F_InviteId")]
+ public string InviteId { get; set; }
+
+ ///
+ /// 未成交说明
+ ///
+ [SugarColumn(ColumnName = "F_NoDealRemark")]
+ public string NoDealRemark { get; set; }
+
+ ///
/// 创建时间
///
[SugarColumn(ColumnName = "F_CreateTime")]
diff --git a/netcore/src/Modularity/Extend/NCC.Extend/LqKdKdjlbService.cs b/netcore/src/Modularity/Extend/NCC.Extend/LqKdKdjlbService.cs
index b8dff6a..8e165ec 100644
--- a/netcore/src/Modularity/Extend/NCC.Extend/LqKdKdjlbService.cs
+++ b/netcore/src/Modularity/Extend/NCC.Extend/LqKdKdjlbService.cs
@@ -46,6 +46,7 @@ using NCC.Extend.Entitys.lq_package_info;
using NCC.Extend.Entitys.lq_mdxx;
using NCC.Extend.Entitys.lq_card_transfer_log;
using NCC.Extend.Entitys.Dto.LqDailyReport;
+using NCC.Extend.Entitys.lq_yyjl;
namespace NCC.Extend.LqKdKdjlb
{
@@ -124,8 +125,11 @@ namespace NCC.Extend.LqKdKdjlb
{
throw NCCException.Oh(ErrorCode.COM1005, "开单记录不存在");
}
-
var output = entity.Adapt();
+ if (!string.IsNullOrEmpty(entity.AppointmentId))
+ {
+ output.appointmentTime = await _db.Queryable().Where(x => x.Id == entity.AppointmentId).Select(x => x.Yysj).FirstAsync();
+ }
if (output.activityId != null)
{
output.activityName = await _db.Queryable().Where(x => x.Id == entity.ActivityId).Select(x => x.ActivityName).FirstAsync();
@@ -317,6 +321,8 @@ namespace NCC.Extend.LqKdKdjlb
createUserName = SqlFunc.Subqueryable().Where(x => x.Id == it.CreateUser).Select(x => x.RealName),
activityId = it.ActivityId,
activityName = SqlFunc.Subqueryable().Where(x => x.Id == it.ActivityId).Select(x => x.ActivityName),
+ appointmentId = it.AppointmentId,
+ appointmentTime = it.AppointmentId == null ? (DateTime?)null : SqlFunc.Subqueryable().Where(x => x.Id == it.AppointmentId).Select(x => SqlFunc.ToDate(x.Yysj)),
})
.MergeTable()
.OrderBy(sidx + " " + input.sort)
@@ -516,6 +522,8 @@ namespace NCC.Extend.LqKdKdjlb
createUserName = SqlFunc.Subqueryable().Where(x => x.Id == kdjlb.CreateUser).Select(x => x.RealName),
activityId = kdjlb.ActivityId,
activityName = SqlFunc.Subqueryable().Where(x => x.Id == kdjlb.ActivityId).Select(x => x.ActivityName),
+ appointmentId = kdjlb.AppointmentId,
+ appointmentTime = kdjlb.AppointmentId == null ? (DateTime?)null : SqlFunc.Subqueryable().Where(x => x.Id == kdjlb.AppointmentId).Select(x => SqlFunc.ToDate(x.Yysj)),
})
.MergeTable()
.Distinct() // 去重,因为一个开单可能对应多个健康师业绩记录
@@ -670,6 +678,8 @@ namespace NCC.Extend.LqKdKdjlb
createUserName = SqlFunc.Subqueryable().Where(x => x.Id == kdjlb.CreateUser).Select(x => x.RealName),
activityId = kdjlb.ActivityId,
activityName = SqlFunc.Subqueryable().Where(x => x.Id == kdjlb.ActivityId).Select(x => x.ActivityName),
+ appointmentId = kdjlb.AppointmentId,
+ appointmentTime = kdjlb.AppointmentId == null ? (DateTime?)null : SqlFunc.Subqueryable().Where(x => x.Id == kdjlb.AppointmentId).Select(x => SqlFunc.ToDate(x.Yysj)),
})
.MergeTable()
.Distinct() // 去重,因为一个开单可能对应多个科技部老师业绩记录
@@ -747,35 +757,6 @@ namespace NCC.Extend.LqKdKdjlb
{
//开启事务
_db.BeginTran();
- //判断是否有作废关联id
- //暂时先不需要
- // if (!string.IsNullOrEmpty(input.cancelRefId))
- // {
- // //查询作废关联id
- // var cancelRefEntity = await _db.Queryable().FirstAsync(p => p.Id == input.cancelRefId);
- // if (cancelRefEntity == null || cancelRefEntity.IsEffective == StatusEnum.无效.GetHashCode())
- // {
- // throw NCCException.Oh("该开单记录已经作废");
- // }
- // // 检查作废关联记录是否可以作废
- // var (canCancel, errorMessage) = await CheckBillingCanCancelAsync(input.cancelRefId);
- // if (!canCancel)
- // {
- // throw NCCException.Oh(errorMessage);
- // }
-
- // //将作废关联id的IsEffective设置为无效
- // cancelRefEntity.IsEffective = StatusEnum.无效.GetHashCode();
- // await _db.Updateable(cancelRefEntity).ExecuteCommandAsync();
- // //把品项明细表的IsEffective设置为无效
- // await _db.Updateable().Where(p => p.Glkdbh == input.cancelRefId).UpdateColumns(p => new LqKdPxmxEntity { IsEffective = StatusEnum.无效.GetHashCode() }).ExecuteCommandAsync();
- // //把健康师业绩表的IsEffective设置为无效
- // await _db.Updateable().Where(p => p.Glkdbh == input.cancelRefId).UpdateColumns(p => new LqKdJksyjEntity { IsEffective = StatusEnum.无效.GetHashCode() }).ExecuteCommandAsync();
- // //把科技部老师业绩表的IsEffective设置为无效
- // await _db.Updateable().Where(p => p.Glkdbh == input.cancelRefId).UpdateColumns(p => new LqKdKjbsyjEntity { IsEffective = StatusEnum.无效.GetHashCode() }).ExecuteCommandAsync();
- // //把扣款信息表的IsEffective设置为无效
- // await _db.Updateable().Where(p => p.BillingId == input.cancelRefId).UpdateColumns(p => new LqKdDeductinfoEntity { IsEffective = StatusEnum.无效.GetHashCode() }).ExecuteCommandAsync();
- // }
//判断是否有补缴开单ID
if (!string.IsNullOrEmpty(input.supplementBillingId))
@@ -796,6 +777,8 @@ namespace NCC.Extend.LqKdKdjlb
//新增开单记录表记录
entity.CreateUser = userInfo.userId;
entity.DeductAmount = input.lqKdKdjlbDeductList.Sum(x => x.Amount ?? 0);//计算储扣总金额
+
+ //保存开单记录
var newEntity = await _db.Insertable(entity).IgnoreColumns(ignoreNullColumn: true).ExecuteReturnEntityAsync();
//循环品相信息
// 收集所有需要插入的实体,然后批量插入
@@ -2113,6 +2096,7 @@ namespace NCC.Extend.LqKdKdjlb
isEffective = it.IsEffective,
createUser = it.CreateUser,
createUserName = SqlFunc.Subqueryable().Where(x => x.Id == it.CreateUser).Select(x => x.RealName),
+ appointmentId = it.AppointmentId,
})
.MergeTable()
.OrderBy(sidx + " " + input.sort)
diff --git a/netcore/src/Modularity/Extend/NCC.Extend/LqKhxxService.cs b/netcore/src/Modularity/Extend/NCC.Extend/LqKhxxService.cs
index 8f431f7..238389a 100644
--- a/netcore/src/Modularity/Extend/NCC.Extend/LqKhxxService.cs
+++ b/netcore/src/Modularity/Extend/NCC.Extend/LqKhxxService.cs
@@ -28,6 +28,7 @@ using NCC.Extend.Entitys.lq_khxx;
using NCC.Extend.Entitys.lq_mdxx;
using NCC.Extend.Entitys.lq_xh_hyhk;
using NCC.Extend.Entitys.lq_xh_pxmx;
+using NCC.Extend.Entitys.lq_xmzl;
using NCC.Extend.Interfaces.LqKhxx;
using NCC.System.Entitys.Permission;
using NCC.FriendlyException;
@@ -366,6 +367,89 @@ namespace NCC.Extend.LqKhxx
}
#endregion
+ #region 判断客户是否开过指定类型的开单
+ ///
+ /// 判断客户是否开过生美的开单
+ ///
+ /// 会员ID
+ /// 1表示有,0表示没有
+ [HttpGet("has-life-beauty-billing/{memberId}")]
+ public async Task HasLifeBeautyBilling(string memberId)
+ {
+ if (string.IsNullOrEmpty(memberId))
+ {
+ throw NCCException.Oh("会员ID不能为空");
+ }
+
+ // 查询该会员是否有开过生美品项的开单
+ var hasBilling = await _db.Queryable()
+ .InnerJoin((kdjlb, pxmx) => kdjlb.Id == pxmx.Glkdbh)
+ .InnerJoin((kdjlb, pxmx, xmzl) => pxmx.Px == xmzl.Id)
+ .Where((kdjlb, pxmx, xmzl) => kdjlb.Kdhy == memberId
+ && kdjlb.IsEffective == StatusEnum.有效.GetHashCode()
+ && pxmx.IsEffective == StatusEnum.有效.GetHashCode()
+ && xmzl.IsEffective == StatusEnum.有效.GetHashCode()
+ && xmzl.Qt2 == "生美")
+ .AnyAsync();
+
+ return hasBilling ? 1 : 0;
+ }
+
+ ///
+ /// 判断客户是否开过科美的开单
+ ///
+ /// 会员ID
+ /// 1表示有,0表示没有
+ [HttpGet("has-tech-beauty-billing/{memberId}")]
+ public async Task HasTechBeautyBilling(string memberId)
+ {
+ if (string.IsNullOrEmpty(memberId))
+ {
+ throw NCCException.Oh("会员ID不能为空");
+ }
+
+ // 查询该会员是否有开过科美品项的开单
+ var hasBilling = await _db.Queryable()
+ .InnerJoin((kdjlb, pxmx) => kdjlb.Id == pxmx.Glkdbh)
+ .InnerJoin((kdjlb, pxmx, xmzl) => pxmx.Px == xmzl.Id)
+ .Where((kdjlb, pxmx, xmzl) => kdjlb.Kdhy == memberId
+ && kdjlb.IsEffective == StatusEnum.有效.GetHashCode()
+ && pxmx.IsEffective == StatusEnum.有效.GetHashCode()
+ && xmzl.IsEffective == StatusEnum.有效.GetHashCode()
+ && xmzl.Qt2 == "科美")
+ .AnyAsync();
+
+ return hasBilling ? 1 : 0;
+ }
+
+ ///
+ /// 判断客户是否开过医美的开单
+ ///
+ /// 会员ID
+ /// 1表示有,0表示没有
+ [HttpGet("has-medical-beauty-billing/{memberId}")]
+ public async Task HasMedicalBeautyBilling(string memberId)
+ {
+ if (string.IsNullOrEmpty(memberId))
+ {
+ throw NCCException.Oh("会员ID不能为空");
+ }
+
+ // 查询该会员是否有开过医美品项的开单
+ var hasBilling = await _db.Queryable()
+ .InnerJoin((kdjlb, pxmx) => kdjlb.Id == pxmx.Glkdbh)
+ .InnerJoin((kdjlb, pxmx, xmzl) => pxmx.Px == xmzl.Id)
+ .Where((kdjlb, pxmx, xmzl) => kdjlb.Kdhy == memberId
+ && kdjlb.IsEffective == StatusEnum.有效.GetHashCode()
+ && pxmx.IsEffective == StatusEnum.有效.GetHashCode()
+ && xmzl.IsEffective == StatusEnum.有效.GetHashCode()
+ && xmzl.Qt2 == "医美")
+ .AnyAsync();
+
+ return hasBilling ? 1 : 0;
+ }
+ #endregion
+
#region 导出客户资料
///
/// 导出客户资料
diff --git a/netcore/src/Modularity/Extend/NCC.Extend/LqReimbursementApplicationService.cs b/netcore/src/Modularity/Extend/NCC.Extend/LqReimbursementApplicationService.cs
index 7f01ba1..8738a6b 100644
--- a/netcore/src/Modularity/Extend/NCC.Extend/LqReimbursementApplicationService.cs
+++ b/netcore/src/Modularity/Extend/NCC.Extend/LqReimbursementApplicationService.cs
@@ -28,7 +28,7 @@ namespace NCC.Extend.LqReimbursementApplication
///
/// 报销申请表服务
///
- [ApiDescriptionSettings(Tag = "Extend",Name = "LqReimbursementApplication", Order = 200)]
+ [ApiDescriptionSettings(Tag = "Extend", Name = "LqReimbursementApplication", Order = 200)]
[Route("api/Extend/[controller]")]
public class LqReimbursementApplicationService : ILqReimbursementApplicationService, IDynamicApiController, ITransient
{
@@ -43,7 +43,7 @@ namespace NCC.Extend.LqReimbursementApplication
ISqlSugarRepository lqReimbursementApplicationRepository,
IUserManager userManager)
{
- _lqReimbursementApplicationRepository = lqReimbursementApplicationRepository;
+ _lqReimbursementApplicationRepository = lqReimbursementApplicationRepository;
_db = _lqReimbursementApplicationRepository.Context;
_userManager = userManager;
}
@@ -86,23 +86,23 @@ namespace NCC.Extend.LqReimbursementApplication
.WhereIF(!string.IsNullOrEmpty(input.amount), p => p.Amount.Contains(input.amount))
.WhereIF(!string.IsNullOrEmpty(input.approveUser), p => p.ApproveUser.Equals(input.approveUser))
.WhereIF(!string.IsNullOrEmpty(input.approveStatus), p => p.ApproveStatus.Contains(input.approveStatus))
- // .WhereIF(queryApproveTime != null, p => p.ApproveTime >= new DateTime(startApproveTime.ToDate().Year, startApproveTime.ToDate().Month, startApproveTime.ToDate().Day, 0, 0, 0))
+ // .WhereIF(queryApproveTime != null, p => p.ApproveTime >= new DateTime(startApproveTime.ToDate().Year, startApproveTime.ToDate().Month, startApproveTime.ToDate().Day, 0, 0, 0))
//.WhereIF(queryApproveTime != null, p => p.ApproveTime <= new DateTime(endApproveTime.ToDate().Year, endApproveTime.ToDate().Month, endApproveTime.ToDate().Day, 23, 59, 59))
.WhereIF(!string.IsNullOrEmpty(input.purchaseRecordsId), p => p.PurchaseRecordsId.Contains(input.purchaseRecordsId))
- .Select(it=> new LqReimbursementApplicationListOutput
+ .Select(it => new LqReimbursementApplicationListOutput
{
id = it.Id,
- applicationUserId=it.ApplicationUserId,
- applicationUserName=it.ApplicationUserName,
- applicationStoreId=it.ApplicationStoreId,
- applicationTime=it.ApplicationTime,
- amount=it.Amount,
- approveUser=it.ApproveUser,
- approveStatus=it.ApproveStatus,
- approveTime=it.ApproveTime,
- purchaseRecordsId=it.PurchaseRecordsId,
- }).MergeTable().OrderBy(sidx+" "+input.sort).ToPagedListAsync(input.currentPage, input.pageSize);
- return PageResult.SqlSugarPageResult(data);
+ applicationUserId = it.ApplicationUserId,
+ applicationUserName = it.ApplicationUserName,
+ applicationStoreId = it.ApplicationStoreId,
+ applicationTime = it.ApplicationTime,
+ amount = it.Amount,
+ approveUser = it.ApproveUser,
+ approveStatus = it.ApproveStatus,
+ approveTime = it.ApproveTime,
+ purchaseRecordsId = it.PurchaseRecordsId,
+ }).MergeTable().OrderBy(sidx + " " + input.sort).ToPagedListAsync(input.currentPage, input.pageSize);
+ return PageResult.SqlSugarPageResult(data);
}
///
@@ -116,16 +116,16 @@ namespace NCC.Extend.LqReimbursementApplication
var userInfo = await _userManager.GetUserInfo();
var entity = input.Adapt();
entity.Id = YitIdHelper.NextId().ToString();
-
+
try
{
//开启事务
_db.BeginTran();
-
+
// 保存报销申请表
var isOk = await _db.Insertable(entity).IgnoreColumns(ignoreNullColumn: true).ExecuteCommandAsync();
if (!(isOk > 0)) throw NCCException.Oh(ErrorCode.COM1000);
-
+
// 更新购买记录的审批单编号和审批状态为"待审批"
if (input.selectedPurchaseRecordIds != null && input.selectedPurchaseRecordIds.Count > 0)
{
@@ -134,14 +134,14 @@ namespace NCC.Extend.LqReimbursementApplication
.SetColumns(it => it.ApplicationId == entity.Id)
.Where(it => input.selectedPurchaseRecordIds.Contains(it.Id))
.ExecuteCommandAsync();
-
+
// 再更新ApproveStatus(分开更新确保都能执行)
await _db.Updateable()
.SetColumns(it => it.ApproveStatus == "待审批")
.Where(it => input.selectedPurchaseRecordIds.Contains(it.Id))
.ExecuteCommandAsync();
}
-
+
//关闭事务
_db.CommitTran();
}
@@ -178,23 +178,23 @@ namespace NCC.Extend.LqReimbursementApplication
.WhereIF(!string.IsNullOrEmpty(input.amount), p => p.Amount.Contains(input.amount))
.WhereIF(!string.IsNullOrEmpty(input.approveUser), p => p.ApproveUser.Equals(input.approveUser))
.WhereIF(!string.IsNullOrEmpty(input.approveStatus), p => p.ApproveStatus.Contains(input.approveStatus))
- // .WhereIF(queryApproveTime != null, p => p.ApproveTime >= new DateTime(startApproveTime.ToDate().Year, startApproveTime.ToDate().Month, startApproveTime.ToDate().Day, 0, 0, 0))
- // .WhereIF(queryApproveTime != null, p => p.ApproveTime <= new DateTime(endApproveTime.ToDate().Year, endApproveTime.ToDate().Month, endApproveTime.ToDate().Day, 23, 59, 59))
+ // .WhereIF(queryApproveTime != null, p => p.ApproveTime >= new DateTime(startApproveTime.ToDate().Year, startApproveTime.ToDate().Month, startApproveTime.ToDate().Day, 0, 0, 0))
+ // .WhereIF(queryApproveTime != null, p => p.ApproveTime <= new DateTime(endApproveTime.ToDate().Year, endApproveTime.ToDate().Month, endApproveTime.ToDate().Day, 23, 59, 59))
.WhereIF(!string.IsNullOrEmpty(input.purchaseRecordsId), p => p.PurchaseRecordsId.Contains(input.purchaseRecordsId))
- .Select(it=> new LqReimbursementApplicationListOutput
+ .Select(it => new LqReimbursementApplicationListOutput
{
id = it.Id,
- applicationUserId=it.ApplicationUserId,
- applicationUserName=it.ApplicationUserName,
- applicationStoreId=it.ApplicationStoreId,
- applicationTime=it.ApplicationTime,
- amount=it.Amount,
- approveUser=it.ApproveUser,
- approveStatus=it.ApproveStatus,
- approveTime=it.ApproveTime,
- purchaseRecordsId=it.PurchaseRecordsId,
- }).MergeTable().OrderBy(sidx+" "+input.sort).ToListAsync();
- return data;
+ applicationUserId = it.ApplicationUserId,
+ applicationUserName = it.ApplicationUserName,
+ applicationStoreId = it.ApplicationStoreId,
+ applicationTime = it.ApplicationTime,
+ amount = it.Amount,
+ approveUser = it.ApproveUser,
+ approveStatus = it.ApproveStatus,
+ approveTime = it.ApproveTime,
+ purchaseRecordsId = it.PurchaseRecordsId,
+ }).MergeTable().OrderBy(sidx + " " + input.sort).ToListAsync();
+ return data;
}
///
@@ -216,7 +216,7 @@ namespace NCC.Extend.LqReimbursementApplication
{
exportData = await this.GetNoPagingList(input);
}
- List paramList = "[{\"value\":\"申请编号\",\"field\":\"id\"},{\"value\":\"申请人编号\",\"field\":\"applicationUserId\"},{\"value\":\"申请人姓名\",\"field\":\"applicationUserName\"},{\"value\":\"申请门店\",\"field\":\"applicationStoreId\"},{\"value\":\"申请时间\",\"field\":\"applicationTime\"},{\"value\":\"总金额\",\"field\":\"amount\"},{\"value\":\"审批人\",\"field\":\"approveUser\"},{\"value\":\"审批结果\",\"field\":\"approveStatus\"},{\"value\":\"审批时间\",\"field\":\"approveTime\"},{\"value\":\"关联购买编号\",\"field\":\"purchaseRecordsId\"},]".ToList();
+ List paramList = "[{\"value\":\"申请编号\",\"field\":\"id\"},{\"value\":\"申请人编号\",\"field\":\"applicationUserId\"},{\"value\":\"申请人姓名\",\"field\":\"applicationUserName\"},{\"value\":\"申请门店\",\"field\":\"applicationStoreId\"},{\"value\":\"申请时间\",\"field\":\"applicationTime\"},{\"value\":\"总金额\",\"field\":\"amount\"},{\"value\":\"审批人\",\"field\":\"approveUser\"},{\"value\":\"审批结果\",\"field\":\"approveStatus\"},{\"value\":\"审批时间\",\"field\":\"approveTime\"},{\"value\":\"关联购买编号\",\"field\":\"purchaseRecordsId\"},]".ToList();
ExcelConfig excelconfig = new ExcelConfig();
excelconfig.FileName = "报销申请表.xls";
excelconfig.HeadFont = "微软雅黑";
@@ -259,7 +259,7 @@ namespace NCC.Extend.LqReimbursementApplication
//开启事务
_db.BeginTran();
//批量删除报销申请表
- await _db.Deleteable().In(d => d.Id,ids).ExecuteCommandAsync();
+ await _db.Deleteable().In(d => d.Id, ids).ExecuteCommandAsync();
//关闭事务
_db.CommitTran();
}
@@ -285,7 +285,7 @@ namespace NCC.Extend.LqReimbursementApplication
{
//开启事务
_db.BeginTran();
-
+
// 获取原有的关联购买记录ID
var oldEntity = await _db.Queryable().FirstAsync(p => p.Id == id);
var oldIds = new List();
@@ -294,10 +294,10 @@ namespace NCC.Extend.LqReimbursementApplication
// 获取原有购买记录ID列表
oldIds = oldEntity.PurchaseRecordsId.Split(',').Where(x => !string.IsNullOrEmpty(x)).ToList();
}
-
+
// 获取新的购买记录ID列表
var newIds = input.selectedPurchaseRecordIds ?? new List();
-
+
// 确保 purchaseRecordsId 字段包含所有选中的记录ID(逗号分隔)
if (newIds.Count > 0)
{
@@ -307,27 +307,27 @@ namespace NCC.Extend.LqReimbursementApplication
{
input.purchaseRecordsId = null;
}
-
+
// 找出需要移除关联的记录(在旧列表中但不在新列表中)
var idsToRemove = oldIds.Where(x => !newIds.Contains(x)).ToList();
if (idsToRemove.Count > 0)
{
// 清除这些购买记录的审批单编号和审批状态
await _db.Updateable()
- .SetColumns(it => new LqPurchaseRecordsEntity
- {
+ .SetColumns(it => new LqPurchaseRecordsEntity
+ {
ApplicationId = null,
ApproveStatus = "未审批"
})
.Where(it => idsToRemove.Contains(it.Id))
.ExecuteCommandAsync();
}
-
+
// 更新报销申请表(确保 purchaseRecordsId 字段被正确更新)
var entity = input.Adapt();
var isOk = await _db.Updateable(entity).IgnoreColumns(ignoreAllNullColumns: true).ExecuteCommandAsync();
if (!(isOk > 0)) throw NCCException.Oh(ErrorCode.COM1001);
-
+
// 更新所有选中的购买记录的审批单编号和审批状态为"待审批"
// 包括新追加的记录和已存在的记录(确保状态正确)
if (newIds.Count > 0)
@@ -337,14 +337,14 @@ namespace NCC.Extend.LqReimbursementApplication
.SetColumns(it => it.ApplicationId == id)
.Where(it => newIds.Contains(it.Id))
.ExecuteCommandAsync();
-
+
// 再更新ApproveStatus(分开更新确保都能执行)
await _db.Updateable()
.SetColumns(it => it.ApproveStatus == "待审批")
.Where(it => newIds.Contains(it.Id))
.ExecuteCommandAsync();
}
-
+
//关闭事务
_db.CommitTran();
}
@@ -380,18 +380,18 @@ namespace NCC.Extend.LqReimbursementApplication
var userInfo = await _userManager.GetUserInfo();
var entity = await _db.Queryable().FirstAsync(p => p.Id == id);
_ = entity ?? throw NCCException.Oh(ErrorCode.COM1005);
-
+
try
{
//开启事务
_db.BeginTran();
-
+
// 更新申请表的审批状态
entity.ApproveStatus = "已审批";
entity.ApproveTime = DateTime.Now;
entity.ApproveUser = userInfo.userId;
await _db.Updateable(entity).ExecuteCommandAsync();
-
+
// 更新关联的购买记录
if (!string.IsNullOrEmpty(entity.PurchaseRecordsId))
{
@@ -399,8 +399,8 @@ namespace NCC.Extend.LqReimbursementApplication
if (purchaseIds.Count > 0)
{
await _db.Updateable()
- .SetColumns(it => new LqPurchaseRecordsEntity
- {
+ .SetColumns(it => new LqPurchaseRecordsEntity
+ {
ApproveStatus = "已审批",
ApproveTime = DateTime.Now,
ApproveUser = userInfo.userId
@@ -409,7 +409,7 @@ namespace NCC.Extend.LqReimbursementApplication
.ExecuteCommandAsync();
}
}
-
+
//关闭事务
_db.CommitTran();
}
@@ -432,18 +432,18 @@ namespace NCC.Extend.LqReimbursementApplication
var userInfo = await _userManager.GetUserInfo();
var entity = await _db.Queryable().FirstAsync(p => p.Id == id);
_ = entity ?? throw NCCException.Oh(ErrorCode.COM1005);
-
+
try
{
//开启事务
_db.BeginTran();
-
+
// 更新申请表的审批状态
entity.ApproveStatus = "未通过";
entity.ApproveTime = DateTime.Now;
entity.ApproveUser = userInfo.userId;
await _db.Updateable(entity).ExecuteCommandAsync();
-
+
// 更新关联的购买记录
if (!string.IsNullOrEmpty(entity.PurchaseRecordsId))
{
@@ -451,8 +451,8 @@ namespace NCC.Extend.LqReimbursementApplication
if (purchaseIds.Count > 0)
{
await _db.Updateable()
- .SetColumns(it => new LqPurchaseRecordsEntity
- {
+ .SetColumns(it => new LqPurchaseRecordsEntity
+ {
ApproveStatus = "未通过",
ApproveTime = DateTime.Now,
ApproveUser = userInfo.userId
@@ -461,7 +461,7 @@ namespace NCC.Extend.LqReimbursementApplication
.ExecuteCommandAsync();
}
}
-
+
//关闭事务
_db.CommitTran();
}
diff --git a/netcore/src/Modularity/Extend/NCC.Extend/LqTkjlbService.cs b/netcore/src/Modularity/Extend/NCC.Extend/LqTkjlbService.cs
index bdf54a4..d43be6e 100644
--- a/netcore/src/Modularity/Extend/NCC.Extend/LqTkjlbService.cs
+++ b/netcore/src/Modularity/Extend/NCC.Extend/LqTkjlbService.cs
@@ -1127,7 +1127,7 @@ namespace NCC.Extend.LqTkjlb
FROM lq_tkjlb tk
INNER JOIN lq_kd_kdjlb kd ON tk.F_MemberId = kd.kdhy
AND kd.F_IsEffective = 1
- WHERE 1=1 {timeFilter} {eventFilter} {storeFilter}";
+ WHERE 1=1 AND kd.sfyj > 0 {timeFilter} {eventFilter} {storeFilter}";
var kdResult = await _db.Ado.SqlQueryAsync(kdSql);
var kdCount = Convert.ToInt32(kdResult?.FirstOrDefault()?.kd_count ?? 0);
diff --git a/netcore/src/Modularity/Extend/NCC.Extend/LqYaoyjlService.cs b/netcore/src/Modularity/Extend/NCC.Extend/LqYaoyjlService.cs
index dd1d95d..4fce802 100644
--- a/netcore/src/Modularity/Extend/NCC.Extend/LqYaoyjlService.cs
+++ b/netcore/src/Modularity/Extend/NCC.Extend/LqYaoyjlService.cs
@@ -108,6 +108,7 @@ namespace NCC.Extend.LqYaoyjl
storeName = SqlFunc.Subqueryable().Where(u => u.Id == it.StoreId).Select(u => u.Dm),
createTime = it.CreateTime,
yyrName = SqlFunc.Subqueryable().Where(u => u.Id == it.Yyr).Select(u => u.RealName),
+ tkbh = it.Tkbh,
}).MergeTable().OrderBy(sidx + " " + input.sort).ToPagedListAsync(input.currentPage, input.pageSize);
return PageResult.SqlSugarPageResult(data);
}
@@ -171,6 +172,7 @@ namespace NCC.Extend.LqYaoyjl
lxsj = it.Lxsj,
lxjl = it.Lxjl,
yyrName = SqlFunc.Subqueryable().Where(u => u.MobilePhone == it.Yyr).Select(u => u.RealName),
+ tkbh = it.Tkbh,
}).MergeTable().OrderBy(sidx + " " + input.sort).ToListAsync();
return data;
}
diff --git a/netcore/src/Modularity/Extend/NCC.Extend/LqYyjlService.cs b/netcore/src/Modularity/Extend/NCC.Extend/LqYyjlService.cs
index 52087a6..916fa11 100644
--- a/netcore/src/Modularity/Extend/NCC.Extend/LqYyjlService.cs
+++ b/netcore/src/Modularity/Extend/NCC.Extend/LqYyjlService.cs
@@ -17,6 +17,7 @@ using NCC.Dependency;
using NCC.DynamicApiController;
using NCC.Extend.Entitys.Dto.LqYyjl;
using NCC.Extend.Entitys.lq_mdxx;
+using NCC.Extend.Entitys.lq_yaoyjl;
using NCC.Extend.Entitys.lq_yyjl;
using NCC.Extend.Interfaces.LqYyjl;
using NCC.FriendlyException;
@@ -47,6 +48,7 @@ namespace NCC.Extend.LqYyjl
_db = _lqYyjlRepository.Context;
_userManager = userManager;
}
+
#region 预约记录
///
/// 获取预约记录
@@ -80,6 +82,13 @@ namespace NCC.Extend.LqYyjl
output.yyjksName = healthCoach?.RealName;
}
+ //获取邀约记录
+ if (!string.IsNullOrEmpty(entity.InviteId))
+ {
+ var invite = await _db.Queryable().Where(u => u.Id == entity.InviteId).FirstAsync();
+ output.InviteTime = invite?.Yysj;
+ }
+
return output;
}
#endregion
@@ -138,6 +147,9 @@ namespace NCC.Extend.LqYyjl
yyrName = SqlFunc.Subqueryable().Where(u => u.Id == it.Yyr).Select(u => u.RealName),
yyjksName = SqlFunc.Subqueryable().Where(u => u.Id == it.Yyjks).Select(u => u.RealName),
djmdName = SqlFunc.Subqueryable().Where(u => u.Id == it.Djmd).Select(u => u.Dm),
+ NoDealRemark = it.NoDealRemark,
+ InviteId = it.InviteId,
+ InviteTime = SqlFunc.Subqueryable().Where(u => u.Id == it.InviteId).Select(u => SqlFunc.ToDate(u.Yysj)),
})
.MergeTable()
.OrderBy(sidx + " " + input.sort)
@@ -155,12 +167,20 @@ namespace NCC.Extend.LqYyjl
[HttpPost("")]
public async Task Create([FromBody] LqYyjlCrInput input)
{
- var userInfo = await _userManager.GetUserInfo();
var entity = input.Adapt();
entity.Id = YitIdHelper.NextId().ToString();
entity.Czr = _userManager.UserId;
entity.Czsj = DateTime.Now;
entity.CreateTime = DateTime.Now;
+ //判断邀约记录是否存在
+ if (!string.IsNullOrEmpty(input.InviteId))
+ {
+ var invite = await _db.Queryable().Where(u => u.Id == input.InviteId).FirstAsync();
+ if (invite == null)
+ {
+ throw NCCException.Oh("邀约记录不存在");
+ }
+ }
var isOk = await _db.Insertable(entity).IgnoreColumns(ignoreNullColumn: true).ExecuteCommandAsync();
if (!(isOk > 0))
throw NCCException.Oh(ErrorCode.COM1000);
@@ -337,5 +357,24 @@ namespace NCC.Extend.LqYyjl
throw NCCException.Oh(ErrorCode.COM1002);
}
#endregion
+
+ #region 添加未成交说明
+ ///
+ /// 添加未成交说明
+ ///
+ /// 主键
+ /// 参数
+ ///
+ [HttpPost("AddNoDealRemark/{id}")]
+ public async Task AddNoDealRemark(string id, [FromBody] string noDealRemark)
+ {
+ var entity = await _db.Queryable().FirstAsync(p => p.Id == id);
+ _ = entity ?? throw NCCException.Oh(ErrorCode.COM1005);
+ entity.NoDealRemark = noDealRemark;
+ var isOk = await _db.Updateable(entity).IgnoreColumns(ignoreAllNullColumns: true).ExecuteCommandAsync();
+ if (!(isOk > 0))
+ throw NCCException.Oh(ErrorCode.COM1001);
+ }
+ #endregion
}
}
diff --git a/sql/查询邀约时间和联系时间不在同一天的记录.sql b/sql/查询邀约时间和联系时间不在同一天的记录.sql
new file mode 100644
index 0000000..14892f7
--- /dev/null
+++ b/sql/查询邀约时间和联系时间不在同一天的记录.sql
@@ -0,0 +1,75 @@
+-- ============================================
+-- 查询 lq_yaoyjl 表中邀约时间(yysj)和联系时间(lxsj)不在同一天的记录
+-- ============================================
+-- 说明:查询邀约时间和联系时间不在同一天的数据,用于数据校验或分析
+--
+-- 查询逻辑:
+-- 1. 两个时间都不为空,但日期不同
+-- 2. 其中一个为空,另一个不为空(视为不在同一天)
+-- 3. 两个都为空的情况不包含在结果中(因为无法判断是否在同一天)
+
+-- ============================================
+-- 基础查询:查询不在同一天的记录
+-- ============================================
+SELECT
+ F_Id AS 邀约编号,
+ yyr AS 邀约人,
+ yysj AS 邀约时间,
+ DATE(yysj) AS 邀约日期,
+ lxsj AS 联系时间,
+ DATE(lxsj) AS 联系日期,
+ yykh AS 邀约客户,
+ yykhxm AS 邀约客户姓名,
+ F_CreateTime AS 创建时间
+FROM lq_yaoyjl
+WHERE (
+ -- 两个时间都不为空,但日期不同
+ (yysj IS NOT NULL AND lxsj IS NOT NULL AND DATE(yysj) != DATE(lxsj))
+ OR
+ -- 邀约时间为空,联系时间不为空
+ (yysj IS NULL AND lxsj IS NOT NULL)
+ OR
+ -- 联系时间为空,邀约时间不为空
+ (yysj IS NOT NULL AND lxsj IS NULL)
+)
+ORDER BY F_CreateTime DESC;
+
+-- ============================================
+-- 统计查询:统计不在同一天的记录数量
+-- ============================================
+SELECT
+ COUNT(*) AS 不在同一天的记录数,
+ COUNT(CASE WHEN yysj IS NOT NULL AND lxsj IS NOT NULL AND DATE(yysj) != DATE(lxsj) THEN 1 END) AS 两个时间都有但日期不同,
+ COUNT(CASE WHEN yysj IS NULL AND lxsj IS NOT NULL THEN 1 END) AS 邀约时间为空,
+ COUNT(CASE WHEN yysj IS NOT NULL AND lxsj IS NULL THEN 1 END) AS 联系时间为空
+FROM lq_yaoyjl
+WHERE (
+ (yysj IS NOT NULL AND lxsj IS NOT NULL AND DATE(yysj) != DATE(lxsj))
+ OR (yysj IS NULL AND lxsj IS NOT NULL)
+ OR (yysj IS NOT NULL AND lxsj IS NULL)
+);
+
+-- ============================================
+-- 详细分析查询:按日期差异分组统计
+-- ============================================
+SELECT
+ CASE
+ WHEN yysj IS NULL AND lxsj IS NOT NULL THEN '邀约时间为空'
+ WHEN yysj IS NOT NULL AND lxsj IS NULL THEN '联系时间为空'
+ WHEN yysj IS NOT NULL AND lxsj IS NOT NULL THEN CONCAT('相差', DATEDIFF(lxsj, yysj), '天')
+ END AS 日期差异类型,
+ COUNT(*) AS 记录数
+FROM lq_yaoyjl
+WHERE (
+ (yysj IS NOT NULL AND lxsj IS NOT NULL AND DATE(yysj) != DATE(lxsj))
+ OR (yysj IS NULL AND lxsj IS NOT NULL)
+ OR (yysj IS NOT NULL AND lxsj IS NULL)
+)
+GROUP BY
+ CASE
+ WHEN yysj IS NULL AND lxsj IS NOT NULL THEN '邀约时间为空'
+ WHEN yysj IS NOT NULL AND lxsj IS NULL THEN '联系时间为空'
+ WHEN yysj IS NOT NULL AND lxsj IS NOT NULL THEN CONCAT('相差', DATEDIFF(lxsj, yysj), '天')
+ END
+ORDER BY 记录数 DESC;
+
diff --git a/sql/添加开单记录表升单类型字段.sql b/sql/添加开单记录表升单类型字段.sql
new file mode 100644
index 0000000..284fa86
--- /dev/null
+++ b/sql/添加开单记录表升单类型字段.sql
@@ -0,0 +1,97 @@
+-- ============================================
+-- 为开单记录表添加升单类型字段
+-- ============================================
+-- 说明:此脚本为开单记录表添加升单类型标记字段,用于标识再次开单时包含的品项类型
+--
+-- 字段说明:
+-- 1. F_UpgradeLifeBeauty:升生美(再次开单时,包含生美品项的订单)
+-- 2. F_UpgradeTechBeauty:升科美(再次开单时,包含科美品项的订单)
+-- 3. F_UpgradeMedicalBeauty:升医美(再次开单时,包含医美品项的订单)
+--
+-- 业务含义:
+-- - 升单:已经开过会员再次消费属于升单
+-- - 这三个字段用于标记升单中是否包含对应类型的品项(生美、科美、医美)
+--
+-- 注意事项:
+-- - 字段类型为VARCHAR(10),可存储"是"/"否"或其他标记值
+-- - 所有字段允许为NULL,因为历史数据可能没有这些标记
+-- - 字段位置:放在 F_SupplementAmount 之后
+
+-- ============================================
+-- 1. lq_kd_kdjlb(开单记录表) - 添加升单类型字段
+-- ============================================
+ALTER TABLE lq_kd_kdjlb
+ADD COLUMN F_UpgradeLifeBeauty VARCHAR(10) NULL COMMENT '升生美(再次开单时,包含生美品项的订单)' AFTER F_SupplementAmount,
+ADD COLUMN F_UpgradeTechBeauty VARCHAR(10) NULL COMMENT '升科美(再次开单时,包含科美品项的订单)' AFTER F_UpgradeLifeBeauty,
+ADD COLUMN F_UpgradeMedicalBeauty VARCHAR(10) NULL COMMENT '升医美(再次开单时,包含医美品项的订单)' AFTER F_UpgradeTechBeauty;
+
+-- ============================================
+-- 2. 验证字段创建
+-- ============================================
+-- 验证 lq_kd_kdjlb 表
+-- SELECT COLUMN_NAME, DATA_TYPE, IS_NULLABLE, COLUMN_COMMENT
+-- FROM INFORMATION_SCHEMA.COLUMNS
+-- WHERE TABLE_NAME = 'lq_kd_kdjlb'
+-- AND (COLUMN_NAME = 'F_UpgradeLifeBeauty'
+-- OR COLUMN_NAME = 'F_UpgradeTechBeauty'
+-- OR COLUMN_NAME = 'F_UpgradeMedicalBeauty');
+
+-- ============================================
+-- 3. 业务逻辑说明(供参考)
+-- ============================================
+-- 判断逻辑:
+-- 1. 判断是否为升单:查询该会员(kdhy)是否有历史开单记录
+-- 2. 判断是否包含生美:查询该开单的品项明细(lq_kd_pxmx)中是否有品项类型(lq_xmzl.qt2)为"生美"的记录
+-- 3. 判断是否包含科美:查询该开单的品项明细中是否有品项类型为"科美"的记录
+-- 4. 判断是否包含医美:查询该开单的品项明细中是否有品项类型为"医美"的记录
+--
+-- 示例SQL(判断升单并标记品项类型):
+-- UPDATE lq_kd_kdjlb kdjlb
+-- SET
+-- F_UpgradeLifeBeauty = CASE
+-- WHEN EXISTS (
+-- SELECT 1 FROM lq_kd_kdjlb kd2
+-- WHERE kd2.kdhy = kdjlb.kdhy
+-- AND kd2.F_Id != kdjlb.F_Id
+-- AND kd2.kdrq < kdjlb.kdrq
+-- ) AND EXISTS (
+-- SELECT 1 FROM lq_kd_pxmx pxmx
+-- INNER JOIN lq_xmzl xmzl ON pxmx.px = xmzl.F_Id
+-- WHERE pxmx.glkdbh = kdjlb.F_Id
+-- AND pxmx.F_IsEffective = 1
+-- AND xmzl.qt2 = '生美'
+-- ) THEN '是'
+-- ELSE '否'
+-- END,
+-- F_UpgradeTechBeauty = CASE
+-- WHEN EXISTS (
+-- SELECT 1 FROM lq_kd_kdjlb kd2
+-- WHERE kd2.kdhy = kdjlb.kdhy
+-- AND kd2.F_Id != kdjlb.F_Id
+-- AND kd2.kdrq < kdjlb.kdrq
+-- ) AND EXISTS (
+-- SELECT 1 FROM lq_kd_pxmx pxmx
+-- INNER JOIN lq_xmzl xmzl ON pxmx.px = xmzl.F_Id
+-- WHERE pxmx.glkdbh = kdjlb.F_Id
+-- AND pxmx.F_IsEffective = 1
+-- AND xmzl.qt2 = '科美'
+-- ) THEN '是'
+-- ELSE '否'
+-- END,
+-- F_UpgradeMedicalBeauty = CASE
+-- WHEN EXISTS (
+-- SELECT 1 FROM lq_kd_kdjlb kd2
+-- WHERE kd2.kdhy = kdjlb.kdhy
+-- AND kd2.F_Id != kdjlb.F_Id
+-- AND kd2.kdrq < kdjlb.kdrq
+-- ) AND EXISTS (
+-- SELECT 1 FROM lq_kd_pxmx pxmx
+-- INNER JOIN lq_xmzl xmzl ON pxmx.px = xmzl.F_Id
+-- WHERE pxmx.glkdbh = kdjlb.F_Id
+-- AND pxmx.F_IsEffective = 1
+-- AND xmzl.qt2 = '医美'
+-- ) THEN '是'
+-- ELSE '否'
+-- END
+-- WHERE kdjlb.F_IsEffective = 1;
+
diff --git a/sql/添加转化率统计关联字段.sql b/sql/添加转化率统计关联字段.sql
new file mode 100644
index 0000000..a8547b1
--- /dev/null
+++ b/sql/添加转化率统计关联字段.sql
@@ -0,0 +1,118 @@
+-- ============================================
+-- 为转化率统计添加关联字段
+-- ============================================
+-- 说明:此脚本为转化率统计功能添加关联字段,用于追踪邀约→预约→开单/耗卡的完整业务链路
+-- 执行顺序:按照业务链路顺序依次执行
+--
+-- 业务链路:
+-- 邀约记录 (lq_yaoyjl) → 预约记录 (lq_yyjl) → 开单记录 (lq_kd_kdjlb) / 耗卡记录 (lq_xh_hyhk)
+--
+-- 字段说明:
+-- 1. lq_yyjl.F_InviteId:关联邀约记录ID,用于统计邀约→预约转化率
+-- 2. lq_kd_kdjlb.F_AppointmentId:关联预约记录ID,用于统计预约→开单转化率
+-- 3. lq_xh_hyhk.F_AppointmentId:关联预约记录ID,用于统计预约→耗卡转化率
+--
+-- 注意事项:
+-- - 所有字段允许为NULL,因为历史数据可能没有这些关联
+-- - 字段类型为VARCHAR(50),与其他ID字段保持一致
+-- - 已为所有字段创建索引,以优化查询性能
+
+-- ============================================
+-- 1. lq_yyjl(预约记录表) - 添加邀约ID字段和未成交说明字段
+-- ============================================
+-- 说明:关联邀约记录,用于统计邀约→预约转化率
+ALTER TABLE lq_yyjl
+ADD COLUMN F_InviteId VARCHAR(50) NULL COMMENT '邀约记录ID(关联lq_yaoyjl.F_Id,用于统计邀约→预约转化率)' AFTER F_Status,
+ADD COLUMN F_NoDealRemark VARCHAR(2000) NULL COMMENT '未成交说明' AFTER F_InviteId;
+
+-- 创建索引以优化查询性能
+CREATE INDEX idx_yyjl_invite_id ON lq_yyjl(F_InviteId);
+
+-- ============================================
+-- 2. lq_kd_kdjlb(开单记录表) - 添加预约ID字段
+-- ============================================
+-- 说明:关联预约记录,用于统计预约→开单转化率
+ALTER TABLE lq_kd_kdjlb
+ADD COLUMN F_AppointmentId VARCHAR(50) NULL COMMENT '预约记录ID(关联lq_yyjl.F_Id,用于统计预约→开单转化率)' AFTER F_ActivityId;
+
+-- 创建索引以优化查询性能
+CREATE INDEX idx_kdjlb_appointment_id ON lq_kd_kdjlb(F_AppointmentId);
+
+-- ============================================
+-- 3. lq_xh_hyhk(耗卡记录表) - 添加预约ID字段
+-- ============================================
+-- 说明:关联预约记录,用于统计预约→耗卡转化率
+ALTER TABLE lq_xh_hyhk
+ADD COLUMN F_AppointmentId VARCHAR(50) NULL COMMENT '预约记录ID(关联lq_yyjl.F_Id,用于统计预约→耗卡转化率)' AFTER F_OvertimeSgfy;
+
+-- 创建索引以优化查询性能
+CREATE INDEX idx_hyhk_appointment_id ON lq_xh_hyhk(F_AppointmentId);
+
+-- ============================================
+-- 4. 验证字段创建
+-- ============================================
+-- 验证 lq_yyjl 表
+-- SELECT COLUMN_NAME, DATA_TYPE, IS_NULLABLE, COLUMN_COMMENT
+-- FROM INFORMATION_SCHEMA.COLUMNS
+-- WHERE TABLE_NAME = 'lq_yyjl'
+-- AND (COLUMN_NAME = 'F_InviteId' OR COLUMN_NAME = 'F_NoDealRemark');
+
+-- 验证 lq_kd_kdjlb 表
+-- SELECT COLUMN_NAME, DATA_TYPE, IS_NULLABLE, COLUMN_COMMENT
+-- FROM INFORMATION_SCHEMA.COLUMNS
+-- WHERE TABLE_NAME = 'lq_kd_kdjlb'
+-- AND COLUMN_NAME = 'F_AppointmentId';
+
+-- 验证 lq_xh_hyhk 表
+-- SELECT COLUMN_NAME, DATA_TYPE, IS_NULLABLE, COLUMN_COMMENT
+-- FROM INFORMATION_SCHEMA.COLUMNS
+-- WHERE TABLE_NAME = 'lq_xh_hyhk'
+-- AND COLUMN_NAME = 'F_AppointmentId';
+
+-- ============================================
+-- 5. 验证索引创建
+-- ============================================
+-- 验证索引
+-- SHOW INDEX FROM lq_yyjl WHERE Key_name = 'idx_yyjl_invite_id';
+-- SHOW INDEX FROM lq_kd_kdjlb WHERE Key_name = 'idx_kdjlb_appointment_id';
+-- SHOW INDEX FROM lq_xh_hyhk WHERE Key_name = 'idx_hyhk_appointment_id';
+
+-- ============================================
+-- 6. 转化率统计示例SQL(供参考)
+-- ============================================
+-- 示例1:邀约→预约转化率
+-- SELECT
+-- COUNT(DISTINCT yyjl.F_Id) AS 预约数量,
+-- COUNT(DISTINCT yyjl.F_InviteId) AS 来自邀约的预约数量,
+-- COUNT(DISTINCT yyjl.F_InviteId) * 100.0 / COUNT(DISTINCT yyjl.F_Id) AS 转化率百分比
+-- FROM lq_yyjl yyjl
+-- WHERE yyjl.F_CreateTime >= '2024-01-01';
+
+-- 示例2:预约→开单转化率
+-- SELECT
+-- COUNT(DISTINCT yyjl.F_Id) AS 预约数量,
+-- COUNT(DISTINCT kdjlb.F_Id) AS 开单数量,
+-- COUNT(DISTINCT kdjlb.F_Id) * 100.0 / COUNT(DISTINCT yyjl.F_Id) AS 转化率百分比
+-- FROM lq_yyjl yyjl
+-- LEFT JOIN lq_kd_kdjlb kdjlb ON kdjlb.F_AppointmentId = yyjl.F_Id AND kdjlb.F_IsEffective = 1
+-- WHERE yyjl.F_CreateTime >= '2024-01-01';
+
+-- 示例3:预约→耗卡转化率
+-- SELECT
+-- COUNT(DISTINCT yyjl.F_Id) AS 预约数量,
+-- COUNT(DISTINCT hyhk.F_Id) AS 耗卡数量,
+-- COUNT(DISTINCT hyhk.F_Id) * 100.0 / COUNT(DISTINCT yyjl.F_Id) AS 转化率百分比
+-- FROM lq_yyjl yyjl
+-- LEFT JOIN lq_xh_hyhk hyhk ON hyhk.F_AppointmentId = yyjl.F_Id AND hyhk.F_IsEffective = 1
+-- WHERE yyjl.F_CreateTime >= '2024-01-01';
+
+-- 示例4:邀约→开单转化率(跨步转化)
+-- SELECT
+-- COUNT(DISTINCT yaoyjl.F_Id) AS 邀约数量,
+-- COUNT(DISTINCT kdjlb.F_Id) AS 开单数量,
+-- COUNT(DISTINCT kdjlb.F_Id) * 100.0 / COUNT(DISTINCT yaoyjl.F_Id) AS 转化率百分比
+-- FROM lq_yaoyjl yaoyjl
+-- LEFT JOIN lq_yyjl yyjl ON yyjl.F_InviteId = yaoyjl.F_Id
+-- LEFT JOIN lq_kd_kdjlb kdjlb ON kdjlb.F_AppointmentId = yyjl.F_Id AND kdjlb.F_IsEffective = 1
+-- WHERE yaoyjl.F_CreateTime >= '2024-01-01';
+