diff --git a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqKdKdjlb/BillingItemDetailListOutput.cs b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqKdKdjlb/BillingItemDetailListOutput.cs index 132e466..d3b0432 100644 --- a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqKdKdjlb/BillingItemDetailListOutput.cs +++ b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqKdKdjlb/BillingItemDetailListOutput.cs @@ -66,6 +66,16 @@ namespace NCC.Extend.Entitys.Dto.LqKdKdjlb /// 备注 /// public string remark { get; set; } + + /// + /// 门店ID + /// + public string storeId { get; set; } + + /// + /// 门店名称 + /// + public string storeName { get; set; } } } diff --git a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqKdKdjlb/BillingItemDetailListQueryInput.cs b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqKdKdjlb/BillingItemDetailListQueryInput.cs index 1d5f3a4..b5669e6 100644 --- a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqKdKdjlb/BillingItemDetailListQueryInput.cs +++ b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqKdKdjlb/BillingItemDetailListQueryInput.cs @@ -66,6 +66,11 @@ namespace NCC.Extend.Entitys.Dto.LqKdKdjlb /// 来源类型(购买/赠送/体验) /// public string SourceType { get; set; } + + /// + /// 门店ID + /// + public string StoreId { get; set; } } } 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..9927f26 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 @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using NCC.Extend.Entitys.Dto.LqKdDeductinfo; namespace NCC.Extend.Entitys.Dto.LqKdKdjlb { @@ -167,6 +168,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; } @@ -180,5 +190,10 @@ namespace NCC.Extend.Entitys.Dto.LqKdKdjlb /// 科技部老师业绩列表 /// public List lqKdKjbsyjList { get; set; } + + /// + /// 储扣扣款信息列表 + /// + public List lqKdDeductList { get; set; } } } diff --git a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqPersonTimesRecord/LqPersonTimesRecordCrInput.cs b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqPersonTimesRecord/LqPersonTimesRecordCrInput.cs new file mode 100644 index 0000000..6f6b509 --- /dev/null +++ b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqPersonTimesRecord/LqPersonTimesRecordCrInput.cs @@ -0,0 +1,67 @@ +using System; + +namespace NCC.Extend.Entitys.Dto.LqPersonTimesRecord +{ + /// + /// 人次记录创建输入参数 + /// + public class LqPersonTimesRecordCrInput + { + /// + /// 主键ID + /// + public string id { get; set; } + + /// + /// 关联业务记录ID + /// + public string businessId { get; set; } + + /// + /// 业务类型(耗卡/开单) + /// + public string businessType { get; set; } + + /// + /// 人员类型(健康师/科技老师) + /// + public string personType { get; set; } + + /// + /// 人员ID + /// + public string personId { get; set; } + + /// + /// 人员姓名 + /// + public string personName { get; set; } + + /// + /// 客户ID + /// + public string memberId { get; set; } + + /// + /// 客户姓名 + /// + public string memberName { get; set; } + + /// + /// 工作日期(用于人次统计,格式:YYYY-MM-DD) + /// + public DateTime? workDate { get; set; } + + /// + /// 工作月份(用于人头统计,格式:202511) + /// + public string workMonth { get; set; } + + /// + /// 数量 + /// + public decimal? quantity { get; set; } + } +} + + diff --git a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqPersonTimesRecord/LqPersonTimesRecordInfoOutput.cs b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqPersonTimesRecord/LqPersonTimesRecordInfoOutput.cs new file mode 100644 index 0000000..20563cd --- /dev/null +++ b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqPersonTimesRecord/LqPersonTimesRecordInfoOutput.cs @@ -0,0 +1,77 @@ +using System; + +namespace NCC.Extend.Entitys.Dto.LqPersonTimesRecord +{ + /// + /// 人次记录信息输出参数 + /// + public class LqPersonTimesRecordInfoOutput + { + /// + /// 主键ID + /// + public string id { get; set; } + + /// + /// 关联业务记录ID + /// + public string businessId { get; set; } + + /// + /// 业务类型(耗卡/开单) + /// + public string businessType { get; set; } + + /// + /// 人员类型(健康师/科技老师) + /// + public string personType { get; set; } + + /// + /// 人员ID + /// + public string personId { get; set; } + + /// + /// 人员姓名 + /// + public string personName { get; set; } + + /// + /// 客户ID + /// + public string memberId { get; set; } + + /// + /// 客户姓名 + /// + public string memberName { get; set; } + + /// + /// 工作日期(用于人次统计,格式:YYYY-MM-DD) + /// + public DateTime? workDate { get; set; } + + /// + /// 工作月份(用于人头统计,格式:202511) + /// + public string workMonth { get; set; } + + /// + /// 数量 + /// + public decimal? quantity { get; set; } + + /// + /// 创建时间 + /// + public DateTime? createTime { get; set; } + + /// + /// 是否有效 + /// + public int isEffective { get; set; } + } +} + + diff --git a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqPersonTimesRecord/LqPersonTimesRecordListOutput.cs b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqPersonTimesRecord/LqPersonTimesRecordListOutput.cs new file mode 100644 index 0000000..ef3d419 --- /dev/null +++ b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqPersonTimesRecord/LqPersonTimesRecordListOutput.cs @@ -0,0 +1,77 @@ +using System; + +namespace NCC.Extend.Entitys.Dto.LqPersonTimesRecord +{ + /// + /// 人次记录列表输出参数 + /// + public class LqPersonTimesRecordListOutput + { + /// + /// 主键ID + /// + public string id { get; set; } + + /// + /// 关联业务记录ID + /// + public string businessId { get; set; } + + /// + /// 业务类型(耗卡/开单) + /// + public string businessType { get; set; } + + /// + /// 人员类型(健康师/科技老师) + /// + public string personType { get; set; } + + /// + /// 人员ID + /// + public string personId { get; set; } + + /// + /// 人员姓名 + /// + public string personName { get; set; } + + /// + /// 客户ID + /// + public string memberId { get; set; } + + /// + /// 客户姓名 + /// + public string memberName { get; set; } + + /// + /// 工作日期(用于人次统计,格式:YYYY-MM-DD) + /// + public DateTime? workDate { get; set; } + + /// + /// 工作月份(用于人头统计,格式:202511) + /// + public string workMonth { get; set; } + + /// + /// 数量 + /// + public decimal? quantity { get; set; } + + /// + /// 创建时间 + /// + public DateTime? createTime { get; set; } + + /// + /// 是否有效 + /// + public int isEffective { get; set; } + } +} + + diff --git a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqPersonTimesRecord/LqPersonTimesRecordUpInput.cs b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqPersonTimesRecord/LqPersonTimesRecordUpInput.cs new file mode 100644 index 0000000..49f8d0c --- /dev/null +++ b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqPersonTimesRecord/LqPersonTimesRecordUpInput.cs @@ -0,0 +1,15 @@ +namespace NCC.Extend.Entitys.Dto.LqPersonTimesRecord +{ + /// + /// 人次记录更新输入参数 + /// + public class LqPersonTimesRecordUpInput : LqPersonTimesRecordCrInput + { + /// + /// 主键ID + /// + public string id { get; set; } + } +} + + diff --git a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqXhHyhk/LqXhHyhkCrInput.cs b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqXhHyhk/LqXhHyhkCrInput.cs index ceb7214..87fa62f 100644 --- a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqXhHyhk/LqXhHyhkCrInput.cs +++ b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqXhHyhk/LqXhHyhkCrInput.cs @@ -84,6 +84,10 @@ namespace NCC.Extend.Entitys.Dto.LqXhHyhk /// public decimal? overtimeCoefficient { get; set; } = 0; + /// + /// 预约记录ID + /// + public string appointmentId { get; set; } /// /// 耗卡_品项明细 diff --git a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqXhHyhk/LqXhHyhkInfoOutput.cs b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqXhHyhk/LqXhHyhkInfoOutput.cs index db77441..8d8060b 100644 --- a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqXhHyhk/LqXhHyhkInfoOutput.cs +++ b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqXhHyhk/LqXhHyhkInfoOutput.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using NCC.Extend.Entitys.Dto.LqPersonTimesRecord; using NCC.Extend.Entitys.Dto.LqXhJksyj; using NCC.Extend.Entitys.Dto.LqXhKjbsyj; using NCC.Extend.Entitys.Dto.LqXhPxmx; @@ -141,5 +142,15 @@ namespace NCC.Extend.Entitys.Dto.LqXhHyhk /// public List lqXhPxmxList { get; set; } + /// + /// 预约记录ID + /// + public string appointmentId { get; set; } + + /// + /// 人次记录列表 + /// + public List personTimesRecordList { get; set; } + } } diff --git a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqXhHyhk/LqXhHyhkListOutput.cs b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqXhHyhk/LqXhHyhkListOutput.cs index 01c61e3..55b6fb4 100644 --- a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqXhHyhk/LqXhHyhkListOutput.cs +++ b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqXhHyhk/LqXhHyhkListOutput.cs @@ -1,8 +1,10 @@ using System; using System.Collections.Generic; +using NCC.Extend.Entitys.Dto.LqPersonTimesRecord; using NCC.Extend.Entitys.Dto.LqXhJksyj; using NCC.Extend.Entitys.Dto.LqXhKjbsyj; using NCC.Extend.Entitys.Dto.LqXhPxmx; +using NCC.Extend.Entitys.Dto.LqYyjl; namespace NCC.Extend.Entitys.Dto.LqXhHyhk { @@ -122,5 +124,15 @@ namespace NCC.Extend.Entitys.Dto.LqXhHyhk /// public List lqXhKjbsyjList { get; set; } + /// + /// 预约记录ID + /// + public string appointmentId { get; set; } + + /// + /// 人次记录列表 + /// + public List personTimesRecordList { get; set; } + } } diff --git a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqXhPxmx/LqXhPxmxCrInput.cs b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqXhPxmx/LqXhPxmxCrInput.cs index 3b55700..fc1444c 100644 --- a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqXhPxmx/LqXhPxmxCrInput.cs +++ b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqXhPxmx/LqXhPxmxCrInput.cs @@ -1,5 +1,7 @@ using System; using System.Collections.Generic; +using NCC.Extend.Entitys.Dto.LqXhJksyj; +using NCC.Extend.Entitys.Dto.LqXhKjbsyj; namespace NCC.Extend.Entitys.Dto.LqXhPxmx { @@ -66,11 +68,11 @@ namespace NCC.Extend.Entitys.Dto.LqXhPxmx /// /// 健康师业绩 /// - public List lqXhJksyjList { get; set; } + public List lqXhJksyjList { get; set; } /// /// 科技部老师业绩 /// - public List lqXhKjbsyjList { get; set; } + public List lqXhKjbsyjList { 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/LqYyjlAddNoDealRemarkInput.cs b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqYyjl/LqYyjlAddNoDealRemarkInput.cs new file mode 100644 index 0000000..2d29e36 --- /dev/null +++ b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqYyjl/LqYyjlAddNoDealRemarkInput.cs @@ -0,0 +1,19 @@ +namespace NCC.Extend.Entitys.Dto.LqYyjl +{ + /// + /// 添加未成交说明输入参数 + /// + public class LqYyjlAddNoDealRemarkInput + { + /// + /// 预约记录ID + /// + public string id { get; set; } + + /// + /// 未成交说明 + /// + public string noDealRemark { 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_hytk_mx/LqHytkMxEntity.cs b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Entity/lq_hytk_mx/LqHytkMxEntity.cs index 75272ee..1d90d14 100644 --- a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Entity/lq_hytk_mx/LqHytkMxEntity.cs +++ b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Entity/lq_hytk_mx/LqHytkMxEntity.cs @@ -49,6 +49,12 @@ namespace NCC.Extend.Entitys.lq_hytk_mx public string Pxmc { get; set; } /// + /// 品项分类 + /// + [SugarColumn(ColumnName = "F_ItemCategory")] + public string ItemCategory { get; set; } + + /// /// 品项价格 /// [SugarColumn(ColumnName = "pxjg")] diff --git a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Entity/lq_kd_deductinfo/LqKdDeductinfoEntity.cs b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Entity/lq_kd_deductinfo/LqKdDeductinfoEntity.cs index 3a94f44..ea559d0 100644 --- a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Entity/lq_kd_deductinfo/LqKdDeductinfoEntity.cs +++ b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Entity/lq_kd_deductinfo/LqKdDeductinfoEntity.cs @@ -66,6 +66,12 @@ namespace NCC.Extend.Entitys.lq_kd_deductinfo public string ItemId { get; set; } /// + /// 品项分类 + /// + [SugarColumn(ColumnName = "F_ItemCategory")] + public string ItemCategory { get; set; } + + /// /// 创建时间 /// [SugarColumn(ColumnName = "F_CreateTime")] 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_kd_pxmx/LqKdPxmxEntity.cs b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Entity/lq_kd_pxmx/LqKdPxmxEntity.cs index 735aba4..e7d26c8 100644 --- a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Entity/lq_kd_pxmx/LqKdPxmxEntity.cs +++ b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Entity/lq_kd_pxmx/LqKdPxmxEntity.cs @@ -36,6 +36,12 @@ namespace NCC.Extend.Entitys.lq_kd_pxmx public string Pxmc { get; set; } /// + /// 品项分类 + /// + [SugarColumn(ColumnName = "F_ItemCategory")] + public string ItemCategory { get; set; } + + /// /// 品项价格 /// [SugarColumn(ColumnName = "pxjg")] diff --git a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Entity/lq_person_times_record/LqPersonTimesRecordEntity.cs b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Entity/lq_person_times_record/LqPersonTimesRecordEntity.cs new file mode 100644 index 0000000..c75e06a --- /dev/null +++ b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Entity/lq_person_times_record/LqPersonTimesRecordEntity.cs @@ -0,0 +1,94 @@ +using System; +using NCC.Common.Const; +using NCC.Extend.Entitys.Enum; +using SqlSugar; + +namespace NCC.Extend.Entitys.lq_person_times_record +{ + /// + /// 人次记录表 + /// + [SugarTable("lq_person_times_record")] + [Tenant(ClaimConst.TENANT_ID)] + public class LqPersonTimesRecordEntity + { + /// + /// 主键ID + /// + [SugarColumn(ColumnName = "F_Id", IsPrimaryKey = true)] + public string Id { get; set; } + + /// + /// 关联业务记录ID + /// + [SugarColumn(ColumnName = "F_BusinessId")] + public string BusinessId { get; set; } + + /// + /// 业务类型(耗卡/开单) + /// + [SugarColumn(ColumnName = "F_BusinessType")] + public string BusinessType { get; set; } + + /// + /// 人员类型(健康师/科技老师) + /// + [SugarColumn(ColumnName = "F_PersonType")] + public string PersonType { get; set; } + + /// + /// 人员ID + /// + [SugarColumn(ColumnName = "F_PersonId")] + public string PersonId { get; set; } + + /// + /// 人员姓名 + /// + [SugarColumn(ColumnName = "F_PersonName")] + public string PersonName { get; set; } + + /// + /// 客户ID + /// + [SugarColumn(ColumnName = "F_MemberId")] + public string MemberId { get; set; } + + /// + /// 客户姓名 + /// + [SugarColumn(ColumnName = "F_MemberName")] + public string MemberName { get; set; } + + /// + /// 工作日期(用于人次统计,格式:YYYY-MM-DD) + /// + [SugarColumn(ColumnName = "F_WorkDate")] + public DateTime? WorkDate { get; set; } + + /// + /// 工作月份(用于人头统计,格式:202511) + /// + [SugarColumn(ColumnName = "F_WorkMonth")] + public string WorkMonth { get; set; } + + /// + /// 数量 + /// + [SugarColumn(ColumnName = "F_Quantity")] + public decimal? Quantity { get; set; } + + /// + /// 创建时间 + /// + [SugarColumn(ColumnName = "F_CreateTime")] + public DateTime? CreateTime { get; set; } + + /// + /// 是否有效 + /// + [SugarColumn(ColumnName = "F_IsEffective")] + public int IsEffective { get; set; } = StatusEnum.有效.GetHashCode(); + } +} + 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_xh_pxmx/LqXhPxmxEntity.cs b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Entity/lq_xh_pxmx/LqXhPxmxEntity.cs index 8e7075e..77a2fd2 100644 --- a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Entity/lq_xh_pxmx/LqXhPxmxEntity.cs +++ b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Entity/lq_xh_pxmx/LqXhPxmxEntity.cs @@ -42,6 +42,12 @@ namespace NCC.Extend.Entitys.lq_xh_pxmx public string Pxmc { get; set; } /// + /// 品项分类 + /// + [SugarColumn(ColumnName = "F_ItemCategory")] + public string ItemCategory { get; set; } + + /// /// 品项价格 /// [SugarColumn(ColumnName = "pxjg")] 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/LqHytkHytkService.cs b/netcore/src/Modularity/Extend/NCC.Extend/LqHytkHytkService.cs index 56bd52c..2906262 100644 --- a/netcore/src/Modularity/Extend/NCC.Extend/LqHytkHytkService.cs +++ b/netcore/src/Modularity/Extend/NCC.Extend/LqHytkHytkService.cs @@ -25,6 +25,7 @@ using NCC.Extend.Entitys.lq_hytk_jksyj; using NCC.Extend.Entitys.lq_hytk_kjbsyj; using NCC.Extend.Entitys.lq_hytk_mx; using NCC.Extend.Entitys.lq_kd_pxmx; +using NCC.Extend.Entitys.lq_xmzl; using NCC.Extend.Interfaces.LqHytkHytk; using NCC.FriendlyException; using NCC.JsonSerialization; @@ -408,6 +409,7 @@ namespace NCC.Extend.LqHytkHytk SourceType = item.F_SourceType, TotalPrice = item.F_TotalPrice ?? (item.pxjg * (item.F_ProjectNumber ?? 1)), IsEffective = StatusEnum.有效.GetHashCode(), + ItemCategory = await _db.Queryable().Where(x => x.Id == item.px).Select(x => x.Qt2).FirstAsync(), }; allMxEntities.Add(lqHytkMxEntity); @@ -559,6 +561,7 @@ namespace NCC.Extend.LqHytkHytk ProjectNumber = item.F_ProjectNumber ?? 1, SourceType = item.F_SourceType, TotalPrice = item.F_TotalPrice ?? (item.pxjg * (item.F_ProjectNumber ?? 1)), + ItemCategory = await _db.Queryable().Where(x => x.Id == item.px).Select(x => x.Qt2).FirstAsync(), }; allMxEntities.Add(lqHytkMxEntity); diff --git a/netcore/src/Modularity/Extend/NCC.Extend/LqKdKdjlbService.cs b/netcore/src/Modularity/Extend/NCC.Extend/LqKdKdjlbService.cs index a81735b..ad43a60 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) @@ -357,65 +363,77 @@ namespace NCC.Extend.LqKdKdjlb var jksyjList = new List(); if (billingIds.Any()) { - jksyjList = await _db.Queryable() - .Where(x => billingIds.Contains(x.Glkdbh) && x.IsEffective == StatusEnum.有效.GetHashCode()) - .Select(x => new LqKdJksyjInfoOutput - { - id = x.Id, - glkdbh = x.Glkdbh, - kdpxid = x.Kdpxid, - jks = x.Jks, - jksxm = x.Jksxm, - jkszh = x.Jkszh, - jksyj = x.Jksyj, - yjsj = x.Yjsj, - jsj_id = x.Jsj_id, - isEffective = x.IsEffective - }) - .ToListAsync(); + jksyjList = await _db.Queryable().Where(x => billingIds.Contains(x.Glkdbh) && x.IsEffective == StatusEnum.有效.GetHashCode()).Select(x => new LqKdJksyjInfoOutput + { + id = x.Id, + glkdbh = x.Glkdbh, + kdpxid = x.Kdpxid, + jks = x.Jks, + jksxm = x.Jksxm, + jkszh = x.Jkszh, + jksyj = x.Jksyj, + yjsj = x.Yjsj, + jsj_id = x.Jsj_id, + isEffective = x.IsEffective + }).ToListAsync(); } // 批量查询科技部老师业绩(性能优化:一次性查询所有开单的科技部老师业绩) var kjbsyjList = new List(); if (billingIds.Any()) { - kjbsyjList = await _db.Queryable() - .Where(x => billingIds.Contains(x.Glkdbh) && x.IsEffective == StatusEnum.有效.GetHashCode()) - .Select(x => new LqKdKjbsyjInfoOutput + kjbsyjList = await _db.Queryable().Where(x => billingIds.Contains(x.Glkdbh) && x.IsEffective == StatusEnum.有效.GetHashCode()).Select(x => new LqKdKjbsyjInfoOutput + { + id = x.Id, + glkdbh = x.Glkdbh, + kdpxid = x.Kdpxid, + kjbls = x.Kjbls, + kjblsxm = x.Kjblsxm, + kjblszh = x.Kjblszh, + kjblsyj = x.Kjblsyj, + yjsj = x.Yjsj, + isEffective = x.IsEffective + }) + .ToListAsync(); + } + + // 批量查询储扣扣款信息(性能优化:一次性查询所有开单的储扣扣款信息) + var deductinfoList = new List(); + if (billingIds.Any()) + { + deductinfoList = await _db.Queryable().Where(x => billingIds.Contains(x.BillingId) && x.IsEffective == StatusEnum.有效.GetHashCode()) + .Select(x => new LqKdDeductinfoInfoOutput { id = x.Id, - glkdbh = x.Glkdbh, - kdpxid = x.Kdpxid, - kjbls = x.Kjbls, - kjblsxm = x.Kjblsxm, - kjblszh = x.Kjblszh, - kjblsyj = x.Kjblsyj, - yjsj = x.Yjsj, - isEffective = x.IsEffective + deductType = x.DeductType, + deductId = x.DeductId, + billingId = x.BillingId, + amount = x.Amount, + isEffective = x.IsEffective, + unitPrice = x.UnitPrice, + itemName = x.ItemName, + itemId = x.ItemId, + createTime = x.CreateTime, + projectNumber = x.ProjectNumber, + }) .ToListAsync(); } + // 按开单ID分组储扣扣款信息 + var deductinfoGrouped = deductinfoList.GroupBy(x => x.billingId).ToDictionary(g => g.Key, g => g.ToList()); // 按开单ID分组健康师业绩 - var jksyjGrouped = jksyjList.GroupBy(x => x.glkdbh) - .ToDictionary(g => g.Key, g => g.ToList()); - + var jksyjGrouped = jksyjList.GroupBy(x => x.glkdbh).ToDictionary(g => g.Key, g => g.ToList()); // 按开单ID分组科技部老师业绩 - var kjbsyjGrouped = kjbsyjList.GroupBy(x => x.glkdbh) - .ToDictionary(g => g.Key, g => g.ToList()); + var kjbsyjGrouped = kjbsyjList.GroupBy(x => x.glkdbh).ToDictionary(g => g.Key, g => g.ToList()); // 为每个开单记录分配品项明细、健康师业绩和科技部老师业绩 foreach (var item in data.list) { - item.ItemDetails = itemDetailsGrouped.ContainsKey(item.id) - ? itemDetailsGrouped[item.id] - : new List(); - item.lqKdJksyjList = jksyjGrouped.ContainsKey(item.id) - ? jksyjGrouped[item.id] - : new List(); - item.lqKdKjbsyjList = kjbsyjGrouped.ContainsKey(item.id) - ? kjbsyjGrouped[item.id] - : new List(); + item.ItemDetails = itemDetailsGrouped.ContainsKey(item.id) ? itemDetailsGrouped[item.id] : new List(); + item.lqKdJksyjList = jksyjGrouped.ContainsKey(item.id) ? jksyjGrouped[item.id] : new List(); + item.lqKdKjbsyjList = kjbsyjGrouped.ContainsKey(item.id) ? kjbsyjGrouped[item.id] : new List(); + item.lqKdDeductList = deductinfoGrouped.ContainsKey(item.id) ? deductinfoGrouped[item.id] : new List(); } return PageResult.SqlSugarPageResult(data); @@ -516,6 +534,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 +690,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 +769,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 +789,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(); //循环品相信息 // 收集所有需要插入的实体,然后批量插入 @@ -819,6 +814,7 @@ namespace NCC.Extend.LqKdKdjlb ItemId = item.ItemId, IsEffective = StatusEnum.有效.GetHashCode(), // 设置为有效 CreateTime = DateTime.Now, // 设置创建时间 + ItemCategory = await _db.Queryable().Where(x => x.Id == item.ItemId).Select(x => x.Qt2).FirstAsync(), }; allDeductEntities.Add(lqKdDeductEntity); } @@ -844,6 +840,7 @@ namespace NCC.Extend.LqKdKdjlb Remark = item.remark, IsEffective = StatusEnum.有效.GetHashCode(), ActivityId = input.activityId, + ItemCategory = await _db.Queryable().Where(x => x.Id == item.px).Select(x => x.Qt2).FirstAsync(), }; allPxmxEntities.Add(lqKdPxmxEntity); @@ -1563,6 +1560,7 @@ namespace NCC.Extend.LqKdKdjlb ItemId = item.ItemId, IsEffective = StatusEnum.有效.GetHashCode(), // 设置为有效 CreateTime = DateTime.Now, // 设置创建时间 + ItemCategory = await _db.Queryable().Where(x => x.Id == item.DeductId).Select(x => x.Qt2).FirstAsync(), }; allDeductEntities.Add(lqKdDeductEntity); } @@ -1588,6 +1586,7 @@ namespace NCC.Extend.LqKdKdjlb Remark = item.remark, IsEffective = StatusEnum.有效.GetHashCode(), ActivityId = input.activityId, + ItemCategory = await _db.Queryable().Where(x => x.Id == item.px).Select(x => x.Qt2).FirstAsync(), }; allPxmxEntities.Add(lqKdPxmxEntity); @@ -2113,6 +2112,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) @@ -3237,7 +3237,8 @@ namespace NCC.Extend.LqKdKdjlb /// "ItemId": "品项ID", /// "ItemName": "品项名称", /// "ItemType": "品项类型", - /// "SourceType": "来源类型" + /// "SourceType": "来源类型", + /// "StoreId": "门店ID" /// } /// ``` /// @@ -3258,6 +3259,7 @@ namespace NCC.Extend.LqKdKdjlb /// - ItemName: 品项名称(可选,模糊查询) /// - ItemType: 品项类型(可选,精确匹配,对应项目资料表的qt2字段) /// - SourceType: 来源类型(可选,精确匹配,如:购买、赠送、体验) + /// - StoreId: 门店ID(可选,精确匹配,根据开单记录表的门店ID筛选) /// /// 返回数据结构: /// ```json @@ -3280,7 +3282,9 @@ namespace NCC.Extend.LqKdKdjlb /// "actualPrice": 500.00, /// "projectNumber": 5.0, /// "sourceType": "购买", - /// "remark": "备注" + /// "remark": "备注", + /// "storeId": "门店ID", + /// "storeName": "门店名称" /// } /// ] /// } @@ -3299,6 +3303,8 @@ namespace NCC.Extend.LqKdKdjlb /// - projectNumber: 项目次数(decimal类型,支持小数) /// - sourceType: 来源类型(字符串,如:购买、赠送、体验) /// - remark: 备注(字符串) + /// - storeId: 门店ID(关联开单记录表的门店ID) + /// - storeName: 门店名称(关联门店表的店名字段) /// /// 查询参数 /// 开单品项明细记录列表(分页) @@ -3341,7 +3347,8 @@ namespace NCC.Extend.LqKdKdjlb // 2. 通过 EXISTS 子查询筛选关联字段(在分页前筛选,确保分页准确) baseQuery = baseQuery.WhereIF(!string.IsNullOrEmpty(input.MemberName), pxmx => SqlFunc.Subqueryable().Where(x => x.Id == pxmx.MemberId && x.Khmc != null && x.Khmc.Contains(input.MemberName)).Any()) .WhereIF(!string.IsNullOrEmpty(input.MemberPhone), pxmx => SqlFunc.Subqueryable().Where(x => x.Id == pxmx.MemberId && x.Sjh == input.MemberPhone).Any()) - .WhereIF(!string.IsNullOrEmpty(input.ItemType), pxmx => SqlFunc.Subqueryable().Where(x => x.Id == pxmx.Px && x.Fl4 == input.ItemType).Any()); + .WhereIF(!string.IsNullOrEmpty(input.ItemType), pxmx => SqlFunc.Subqueryable().Where(x => x.Id == pxmx.Px && x.Fl4 == input.ItemType).Any()) + .WhereIF(!string.IsNullOrEmpty(input.StoreId), pxmx => SqlFunc.Subqueryable().Where(x => x.Id == pxmx.Glkdbh && x.Djmd == input.StoreId).Any()); // 3. 先分页查询主表数据(查询实体类,提高性能) var pagedData = await baseQuery.OrderBy(sidx + " " + sort).ToPagedListAsync(input.currentPage, input.pageSize); @@ -3351,6 +3358,7 @@ namespace NCC.Extend.LqKdKdjlb var memberIds = pagedData.list.Where(x => !string.IsNullOrEmpty(x.MemberId)).Select(x => x.MemberId).Distinct().ToList(); var activityIds = pagedData.list.Where(x => !string.IsNullOrEmpty(x.ActivityId)).Select(x => x.ActivityId).Distinct().ToList(); var projectIds = pagedData.list.Where(x => !string.IsNullOrEmpty(x.Px)).Select(x => x.Px).Distinct().ToList(); + var billingIds = pagedData.list.Where(x => !string.IsNullOrEmpty(x.Glkdbh)).Select(x => x.Glkdbh).Distinct().ToList(); // 批量查询会员信息 var memberDict = new Dictionary(); @@ -3376,6 +3384,23 @@ namespace NCC.Extend.LqKdKdjlb projectDict = projects.ToDictionary(x => x.Id, x => x.Qt2 ?? ""); } + // 批量查询开单记录,获取门店ID + var billingStoreDict = new Dictionary(); + if (billingIds.Any()) + { + var billings = await _db.Queryable().Where(x => billingIds.Contains(x.Id)).Select(x => new { x.Id, x.Djmd }).ToListAsync(); + billingStoreDict = billings.ToDictionary(x => x.Id, x => x.Djmd ?? ""); + } + + // 批量查询门店信息 + var storeDict = new Dictionary(); + var storeIds = billingStoreDict.Values.Where(x => !string.IsNullOrEmpty(x)).Distinct().ToList(); + if (storeIds.Any()) + { + var stores = await _db.Queryable().Where(x => storeIds.Contains(x.Id)).Select(x => new { x.Id, x.Dm }).ToListAsync(); + storeDict = stores.ToDictionary(x => x.Id, x => x.Dm ?? ""); + } + // 5. 组装返回数据 var resultList = pagedData.list.Select(pxmx => new BillingItemDetailListOutput { @@ -3390,7 +3415,9 @@ namespace NCC.Extend.LqKdKdjlb actualPrice = pxmx.ActualPrice, projectNumber = pxmx.ProjectNumber, sourceType = pxmx.SourceType, - remark = pxmx.Remark + remark = pxmx.Remark, + storeId = pxmx.Glkdbh != null && billingStoreDict.ContainsKey(pxmx.Glkdbh) ? billingStoreDict[pxmx.Glkdbh] : "", + storeName = pxmx.Glkdbh != null && billingStoreDict.ContainsKey(pxmx.Glkdbh) && !string.IsNullOrEmpty(billingStoreDict[pxmx.Glkdbh]) && storeDict.ContainsKey(billingStoreDict[pxmx.Glkdbh]) ? storeDict[billingStoreDict[pxmx.Glkdbh]] : "" }).ToList(); // 6. 返回分页结果 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/LqXhHyhkService.cs b/netcore/src/Modularity/Extend/NCC.Extend/LqXhHyhkService.cs index 3870d34..74b003c 100644 --- a/netcore/src/Modularity/Extend/NCC.Extend/LqXhHyhkService.cs +++ b/netcore/src/Modularity/Extend/NCC.Extend/LqXhHyhkService.cs @@ -16,18 +16,22 @@ using NCC.Common.Model.NPOI; using NCC.DataEncryption; using NCC.Dependency; using NCC.DynamicApiController; +using NCC.Extend.Entitys.Dto.LqPersonTimesRecord; using NCC.Extend.Entitys.Dto.LqXhHyhk; using NCC.Extend.Entitys.Dto.LqXhJksyj; using NCC.Extend.Entitys.Dto.LqXhKjbsyj; using NCC.Extend.Entitys.Dto.LqXhPxmx; +using NCC.Extend.Entitys.Dto.LqYyjl; using NCC.Extend.Entitys.Enum; using NCC.Extend.Entitys.lq_kd_kdjlb; using NCC.Extend.Entitys.lq_kd_pxmx; using NCC.Extend.Entitys.lq_khxx; +using NCC.Extend.Entitys.lq_person_times_record; using NCC.Extend.Entitys.lq_xh_hyhk; using NCC.Extend.Entitys.lq_xh_jksyj; using NCC.Extend.Entitys.lq_xh_kjbsyj; using NCC.Extend.Entitys.lq_xh_pxmx; +using NCC.Extend.Entitys.lq_xmzl; using NCC.Extend.Interfaces.LqXhHyhk; using NCC.FriendlyException; using NCC.JsonSerialization; @@ -111,13 +115,12 @@ namespace NCC.Extend.LqXhHyhk // 2. 查询品项明细列表 var lqXhPxmxList = await _db.Queryable().Where(w => w.ConsumeInfoId == entity.Id).ToListAsync(); - // 3. 查询健康师业绩列表 var lqXhJksyjList = await _db.Queryable().Where(w => w.Glkdbh == entity.Id).ToListAsync(); - // 4. 查询科技部老师业绩列表 var lqXhKjbsyjList = await _db.Queryable().Where(w => w.Glkdbh == entity.Id).ToListAsync(); - + // 获取人次记录列表 + var personTimesRecordList = await _db.Queryable().Where(x => x.BusinessId == entity.Id && x.IsEffective == StatusEnum.有效.GetHashCode()).ToListAsync(); // 5. 构建品项明细输出,每个品项关联对应的业绩信息 var pxmxOutputList = new List(); foreach (var pxmx in lqXhPxmxList) @@ -299,8 +302,7 @@ namespace NCC.Extend.LqXhHyhk // 如果两个都传入了,需要同时JOIN两个表 if (!string.IsNullOrEmpty(input.jksId) && !string.IsNullOrEmpty(input.kjblsId)) { - query = _db.Queryable( - (jksyj, kjbsyj, hyhk) => jksyj.Glkdbh == hyhk.Id && kjbsyj.Glkdbh == hyhk.Id) + query = _db.Queryable((jksyj, kjbsyj, hyhk) => jksyj.Glkdbh == hyhk.Id && kjbsyj.Glkdbh == hyhk.Id) .Where((jksyj, kjbsyj, hyhk) => jksyj.Jkszh == input.jksId && jksyj.IsEffective == StatusEnum.有效.GetHashCode()) .Where((jksyj, kjbsyj, hyhk) => kjbsyj.Kjblszh == input.kjblsId && kjbsyj.IsEffective == StatusEnum.有效.GetHashCode()) .Select((jksyj, kjbsyj, hyhk) => hyhk) @@ -369,6 +371,7 @@ namespace NCC.Extend.LqXhHyhk overtimeCoefficient = it.OvertimeCoefficient, originalSgfy = it.OriginalSgfy, overtimeSgfy = it.OvertimeSgfy, + appointmentId = it.AppointmentId, }) .MergeTable() .OrderBy($"{sidx} {sort}") @@ -517,101 +520,6 @@ namespace NCC.Extend.LqXhHyhk } #endregion - #region 获取会员耗卡列表(备份) - /// - /// 获取会员耗卡列表 - /// - /// 请求参数 - /// - [HttpGet("GetListBak")] - public async Task GetListBak([FromQuery] LqXhHyhkListQueryInput input) - { - var sidx = input.sidx == null ? "id" : input.sidx; - List queryHksj = input.hksj != null ? input.hksj.Split(',').ToObeject>() : null; - DateTime? startHksj = queryHksj != null ? Ext.GetDateTime(queryHksj.First()) : null; - DateTime? endHksj = queryHksj != null ? Ext.GetDateTime(queryHksj.Last()) : null; - var data = await _db.Queryable() - .WhereIF(!string.IsNullOrEmpty(input.keyword), p => p.Hymc.Contains(input.keyword) || p.Hyzh.Contains(input.keyword) || p.MemberPhone.Contains(input.keyword)) - .WhereIF(!string.IsNullOrEmpty(input.id), p => p.Id.Contains(input.id)) - .WhereIF(!string.IsNullOrEmpty(input.md), p => p.Md.Equals(input.md)) - .WhereIF(!string.IsNullOrEmpty(input.mdbh), p => p.Mdbh.Contains(input.mdbh)) - .WhereIF(!string.IsNullOrEmpty(input.mdmc), p => p.Mdmc.Contains(input.mdmc)) - .WhereIF(!string.IsNullOrEmpty(input.hy), p => p.Hy.Equals(input.hy)) - .WhereIF(!string.IsNullOrEmpty(input.hyzh), p => p.Hyzh.Contains(input.hyzh)) - .WhereIF(!string.IsNullOrEmpty(input.hymc), p => p.Hymc.Contains(input.hymc)) - .WhereIF(!string.IsNullOrEmpty(input.gklx), p => p.Gklx.Equals(input.gklx)) - .WhereIF(!string.IsNullOrEmpty(input.sfykjb), p => p.Sfykjb.Equals(input.sfykjb)) - .WhereIF(queryHksj != null, p => p.Hksj >= new DateTime(startHksj.ToDate().Year, startHksj.ToDate().Month, startHksj.ToDate().Day, 0, 0, 0)) - .WhereIF(queryHksj != null, p => p.Hksj <= new DateTime(endHksj.ToDate().Year, endHksj.ToDate().Month, endHksj.ToDate().Day, 23, 59, 59)) - .WhereIF(!string.IsNullOrEmpty(input.czry), p => p.Czry.Equals(input.czry)) - .WhereIF(input.isEffective != 0, p => p.IsEffective == input.isEffective) - .Select(it => new LqXhHyhkListOutput - { - id = it.Id, - md = it.Md, - mdbh = it.Mdbh, - mdmc = it.Mdmc, - hy = it.Hy, - hyzh = it.Hyzh, - hymc = SqlFunc.Subqueryable().Where(w => w.Id == it.Hy).Select(w => w.Khmc), - gklx = it.Gklx, - xfje = SqlFunc.ToString(it.Xfje), - sgfy = SqlFunc.ToString(it.Sgfy), - sfykjb = it.Sfykjb, - hksj = it.Hksj, - czry = it.Czry, - memberPhone = SqlFunc.Subqueryable().Where(w => w.Id == it.Hy).Select(w => w.Sjh), - isEffective = it.IsEffective, - }) - .MergeTable() - .OrderBy(sidx + " " + input.sort) - .ToPagedListAsync(input.currentPage, input.pageSize); - - // 获取当前页的耗卡记录ID列表 - var consumeIds = data.list.Select(x => x.id).ToList(); - - // 批量查询耗卡明细 - var consumeDetails = new List(); - if (consumeIds.Any()) - { - consumeDetails = await _db.Queryable() - .Where(x => consumeIds.Contains(x.ConsumeInfoId) && x.IsEffective == StatusEnum.有效.GetHashCode()) - .Select(x => new LqXhPxmxInfoOutput - { - id = x.Id, - consumeInfoId = x.ConsumeInfoId, - billingItemId = x.BillingItemId, - px = x.Px, - pxmc = x.Pxmc, - pxjg = x.Pxjg, - memberId = x.MemberId, - createTime = x.CreateTIme, - projectNumber = x.ProjectNumber, - originalProjectNumber = x.OriginalProjectNumber, - overtimeProjectNumber = x.OvertimeProjectNumber, - sourceType = x.SourceType, - totalPrice = x.TotalPrice, - isEffective = x.IsEffective, - }) - .ToListAsync(); - } - - // 按耗卡记录ID分组耗卡明细 - var consumeDetailsGrouped = consumeDetails.GroupBy(x => x.consumeInfoId) - .ToDictionary(g => g.Key, g => g.ToList()); - - // 为每个耗卡记录分配耗卡明细 - foreach (var item in data.list) - { - item.ConsumeDetails = consumeDetailsGrouped.ContainsKey(item.id) - ? consumeDetailsGrouped[item.id] - : new List(); - } - - return PageResult.SqlSugarPageResult(data); - } - #endregion - #region 根据健康师ID获取耗卡列表 /// /// 根据健康师ID获取耗卡列表 @@ -670,8 +578,7 @@ namespace NCC.Extend.LqXhHyhk } // 通过健康师业绩表关联查询耗卡记录 - var data = await _db.Queryable( - (jksyj, hyhk) => jksyj.Glkdbh == hyhk.Id) + var data = await _db.Queryable((jksyj, hyhk) => jksyj.Glkdbh == hyhk.Id) .Where((jksyj, hyhk) => jksyj.Jkszh == input.jksId) .WhereIF(input.isEffective != 0, (jksyj, hyhk) => jksyj.IsEffective == input.isEffective && hyhk.IsEffective == input.isEffective) .WhereIF(input.isEffective == 0, (jksyj, hyhk) => jksyj.IsEffective == StatusEnum.有效.GetHashCode() && hyhk.IsEffective == StatusEnum.有效.GetHashCode()) @@ -705,15 +612,41 @@ namespace NCC.Extend.LqXhHyhk .OrderBy($"{sidx} {sort}") .ToPagedListAsync(input.currentPage, input.pageSize); + + // 获取当前页的耗卡记录ID列表 var consumeIds = data.list.Select(x => x.id).ToList(); - + // 获取人次记录列表 + var personTimesRecordList = await _db.Queryable().Where(x => consumeIds.Contains(x.BusinessId) && x.IsEffective == StatusEnum.有效.GetHashCode()) + .Select(x => new LqPersonTimesRecordListOutput + { + id = x.Id, + businessId = x.BusinessId, + businessType = x.BusinessType, + personType = x.PersonType, + personId = x.PersonId, + personName = x.PersonName, + memberId = x.MemberId, + memberName = x.MemberName, + workDate = x.WorkDate, + workMonth = x.WorkMonth, + quantity = x.Quantity, + createTime = x.CreateTime, + isEffective = x.IsEffective, + }) + .ToListAsync(); + // 按耗卡记录ID分组人次记录 + var personTimesRecordGrouped = personTimesRecordList.GroupBy(x => x.businessId).ToDictionary(g => g.Key, g => g.ToList()); + // 为每个耗卡记录分配人次记录 + foreach (var item in data.list) + { + item.personTimesRecordList = personTimesRecordGrouped.ContainsKey(item.id) ? personTimesRecordGrouped[item.id] : new List(); + } // 批量查询耗卡明细 var consumeDetails = new List(); if (consumeIds.Any()) { - consumeDetails = await _db.Queryable() - .Where(x => consumeIds.Contains(x.ConsumeInfoId) && x.IsEffective == StatusEnum.有效.GetHashCode()) + consumeDetails = await _db.Queryable().Where(x => consumeIds.Contains(x.ConsumeInfoId) && x.IsEffective == StatusEnum.有效.GetHashCode()) .Select(x => new LqXhPxmxInfoOutput { id = x.Id, @@ -733,19 +666,13 @@ namespace NCC.Extend.LqXhHyhk }) .ToListAsync(); } - // 按耗卡记录ID分组耗卡明细 - var consumeDetailsGrouped = consumeDetails.GroupBy(x => x.consumeInfoId) - .ToDictionary(g => g.Key, g => g.ToList()); - + var consumeDetailsGrouped = consumeDetails.GroupBy(x => x.consumeInfoId).ToDictionary(g => g.Key, g => g.ToList()); // 为每个耗卡记录分配耗卡明细 foreach (var item in data.list) { - item.ConsumeDetails = consumeDetailsGrouped.ContainsKey(item.id) - ? consumeDetailsGrouped[item.id] - : new List(); + item.ConsumeDetails = consumeDetailsGrouped.ContainsKey(item.id) ? consumeDetailsGrouped[item.id] : new List(); } - return PageResult.SqlSugarPageResult(data); } catch (Exception ex) @@ -956,6 +883,7 @@ namespace NCC.Extend.LqXhHyhk entity.UpdateTime = DateTime.Now; entity.OvertimeCoefficient = input.overtimeCoefficient ?? 0; entity.OriginalSgfy = input.sgfy; + entity.AppointmentId = input.appointmentId; //加班手工费 = 原始手工费 * 加班系数 entity.OvertimeSgfy = entity.OriginalSgfy * entity.OvertimeCoefficient; //最终手工费 = 原始手工费 + 加班手工费 @@ -979,6 +907,7 @@ namespace NCC.Extend.LqXhHyhk var allPxmxEntities = new List(); var allJksyjEntities = new List(); var allKjbsyjEntities = new List(); + var allPersonTimesRecordEntities = new List(); // 处理品项明细列表 if (input.lqXhPxmxList != null && input.lqXhPxmxList.Any()) { @@ -1002,7 +931,7 @@ namespace NCC.Extend.LqXhHyhk Pxjg = item.pxjg, SourceType = item.sourceType, IsEffective = StatusEnum.有效.GetHashCode(), - + ItemCategory = await _db.Queryable().Where(x => x.Id == item.px).Select(x => x.Qt2).FirstAsync(), }; allPxmxEntities.Add(lqXhPxmxEntity); @@ -1074,6 +1003,57 @@ namespace NCC.Extend.LqXhHyhk } } } + //获取这次耗卡有多少个健康师 + var jksCount = allJksyjEntities.GroupBy(x => x.Jks).Count(); + //添加到人次表里面去 + foreach (var item in allJksyjEntities.Select(x => x.Jks).Distinct()) + { + LqPersonTimesRecordEntity personTimesRecordEntity = new LqPersonTimesRecordEntity + { + Id = YitIdHelper.NextId().ToString(), + BusinessId = newEntity.Id, + BusinessType = "耗卡", + PersonType = "健康师", + PersonId = item, + PersonName = allJksyjEntities.Where(x => x.Jks == item).Select(x => x.Jksxm).First(), + MemberId = entity.Hy, + MemberName = memberInfo.Khmc, + WorkDate = input.hksj, + WorkMonth = input.hksj.ToDate().ToString("yyyyMM"), + Quantity = 1 / (decimal)jksCount, + CreateTime = DateTime.Now, + IsEffective = StatusEnum.有效.GetHashCode(), + }; + allPersonTimesRecordEntities.Add(personTimesRecordEntity); + } + //获取这次耗卡有多少个科技部老师 + var kjbCount = allKjbsyjEntities.GroupBy(x => x.Kjbls).Count(); + //添加到人次表里面去 + foreach (var item in allKjbsyjEntities.Select(x => x.Kjbls).Distinct()) + { + LqPersonTimesRecordEntity personTimesRecordEntity = new LqPersonTimesRecordEntity + { + Id = YitIdHelper.NextId().ToString(), + BusinessId = newEntity.Id, + BusinessType = "耗卡", + PersonType = "科技部老师", + PersonId = item, + PersonName = allKjbsyjEntities.Where(x => x.Kjbls == item).Select(x => x.Kjblsxm).First(), + MemberId = entity.Hy, + MemberName = memberInfo.Khmc, + WorkDate = input.hksj, + WorkMonth = input.hksj.ToDate().ToString("yyyyMM"), + Quantity = 1 / (decimal)kjbCount, + CreateTime = DateTime.Now, + IsEffective = StatusEnum.有效.GetHashCode(), + }; + allPersonTimesRecordEntities.Add(personTimesRecordEntity); + } + // 批量插入人次记录 + if (allPersonTimesRecordEntities.Any()) + { + await _db.Insertable(allPersonTimesRecordEntities).ExecuteCommandAsync(); + } // 批量插入品项明细 if (allPxmxEntities.Any()) { @@ -1264,6 +1244,7 @@ namespace NCC.Extend.LqXhHyhk entity.OriginalSgfy = input.sgfy; entity.OvertimeSgfy = (decimal)(entity.OvertimeCoefficient * input.sgfy); entity.Sgfy = entity.OriginalSgfy + entity.OvertimeSgfy; + entity.AppointmentId = input.appointmentId; //更新会员耗卡记录 await _db.Updateable(entity).IgnoreColumns(ignoreAllNullColumns: true).ExecuteCommandAsync(); @@ -1280,10 +1261,12 @@ namespace NCC.Extend.LqXhHyhk await _db.Deleteable().Where(u => u.Glkdbh == id).ExecuteCommandAsync(); await _db.Deleteable().Where(u => u.Glkdbh == id).ExecuteCommandAsync(); await _db.Deleteable().Where(u => u.ConsumeInfoId == id).ExecuteCommandAsync(); + await _db.Deleteable().Where(u => u.BusinessId == id).ExecuteCommandAsync(); // 收集所有需要插入的实体,然后批量插入 var allPxmxEntities = new List(); var allJksyjEntities = new List(); var allKjbsyjEntities = new List(); + var allPersonTimesRecordEntities = new List(); // 处理品项明细列表 if (input.lqXhPxmxList != null && input.lqXhPxmxList.Any()) { @@ -1307,6 +1290,7 @@ namespace NCC.Extend.LqXhHyhk OriginalProjectNumber = item.projectNumber ?? 0, OvertimeProjectNumber = (decimal)(entity.OvertimeCoefficient * (item.projectNumber ?? 0)), ProjectNumber = (decimal)((item.projectNumber ?? 0) + (entity.OvertimeCoefficient * (item.projectNumber ?? 0))), + ItemCategory = await _db.Queryable().Where(x => x.Id == item.px).Select(x => x.Qt2).FirstAsync(), }; allPxmxEntities.Add(lqXhPxmxEntity); @@ -1376,6 +1360,57 @@ namespace NCC.Extend.LqXhHyhk } } } + //获取这次耗卡有多少个健康师 + var jksCount = allJksyjEntities.GroupBy(x => x.Jks).Count(); + //添加到人次表里面去 + foreach (var item in allJksyjEntities.Select(x => x.Jks).Distinct()) + { + LqPersonTimesRecordEntity personTimesRecordEntity = new LqPersonTimesRecordEntity + { + Id = YitIdHelper.NextId().ToString(), + BusinessId = input.id, + BusinessType = "耗卡", + PersonType = "健康师", + PersonId = item, + PersonName = allJksyjEntities.Where(x => x.Jks == item).Select(x => x.Jksxm).First(), + MemberId = entity.Hy, + MemberName = memberInfo.Khmc, + WorkDate = input.hksj, + WorkMonth = input.hksj.ToDate().ToString("yyyyMM"), + Quantity = 1 / (decimal)jksCount, + CreateTime = DateTime.Now, + IsEffective = StatusEnum.有效.GetHashCode(), + }; + allPersonTimesRecordEntities.Add(personTimesRecordEntity); + } + //获取这次耗卡有多少个科技部老师 + var kjbCount = allKjbsyjEntities.GroupBy(x => x.Kjbls).Count(); + //添加到人次表里面去 + foreach (var item in allKjbsyjEntities.Select(x => x.Kjbls).Distinct()) + { + LqPersonTimesRecordEntity personTimesRecordEntity = new LqPersonTimesRecordEntity + { + Id = YitIdHelper.NextId().ToString(), + BusinessId = input.id, + BusinessType = "耗卡", + PersonType = "科技部老师", + PersonId = item, + PersonName = allKjbsyjEntities.Where(x => x.Kjbls == item).Select(x => x.Kjblsxm).First(), + MemberId = entity.Hy, + MemberName = memberInfo.Khmc, + WorkDate = input.hksj, + WorkMonth = input.hksj.ToDate().ToString("yyyyMM"), + Quantity = 1 / (decimal)kjbCount, + CreateTime = DateTime.Now, + IsEffective = StatusEnum.有效.GetHashCode(), + }; + allPersonTimesRecordEntities.Add(personTimesRecordEntity); + } + // 批量插入人次记录 + if (allPersonTimesRecordEntities.Any()) + { + await _db.Insertable(allPersonTimesRecordEntities).ExecuteCommandAsync(); + } // 批量插入品项明细 if (allPxmxEntities.Any()) { @@ -1430,6 +1465,9 @@ namespace NCC.Extend.LqXhHyhk //清空子表数据 await _db.Deleteable().Where(u => u.ConsumeInfoId == id).ExecuteCommandAsync(); + //清空子表数据 + await _db.Deleteable().Where(u => u.BusinessId == id).ExecuteCommandAsync(); + //关闭事务 _db.CommitTran(); } @@ -1550,6 +1588,8 @@ namespace NCC.Extend.LqXhHyhk await _db.Updateable().SetColumns(it => new LqXhJksyjEntity { IsEffective = StatusEnum.无效.GetHashCode() }).Where(w => w.Glkdbh == id).ExecuteCommandAsync(); //更新科技部老师业绩表状态 await _db.Updateable().SetColumns(it => new LqXhKjbsyjEntity { IsEffective = StatusEnum.无效.GetHashCode() }).Where(w => w.Glkdbh == id).ExecuteCommandAsync(); + //更新人次记录表状态 + await _db.Updateable().SetColumns(it => new LqPersonTimesRecordEntity { IsEffective = StatusEnum.无效.GetHashCode() }).Where(w => w.BusinessId == id).ExecuteCommandAsync(); //关闭事务 _db.CommitTran(); return LqhyhkInfo; diff --git a/netcore/src/Modularity/Extend/NCC.Extend/LqYaoyjlService.cs b/netcore/src/Modularity/Extend/NCC.Extend/LqYaoyjlService.cs index dd1d95d..419c373 100644 --- a/netcore/src/Modularity/Extend/NCC.Extend/LqYaoyjlService.cs +++ b/netcore/src/Modularity/Extend/NCC.Extend/LqYaoyjlService.cs @@ -61,7 +61,7 @@ namespace NCC.Extend.LqYaoyjl { var entity = await _db.Queryable().FirstAsync(p => p.Id == id); var output = entity.Adapt(); - output.storeName = SqlFunc.Subqueryable().Where(u => u.Id == entity.StoreId).Select(u => u.Dm); + output.storeName = _db.Queryable().Where(u => u.Id == entity.StoreId).Select(u => u.Dm).First(); return output; } #endregion @@ -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..89daef9 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,23 @@ namespace NCC.Extend.LqYyjl throw NCCException.Oh(ErrorCode.COM1002); } #endregion + + #region 添加未成交说明 + /// + /// 添加未成交说明 + /// + /// 参数 + /// + [HttpPost("AddNoDealRemark")] + public async Task AddNoDealRemark([FromBody] LqYyjlAddNoDealRemarkInput input) + { + var entity = await _db.Queryable().FirstAsync(p => p.Id == input.id); + _ = entity ?? throw NCCException.Oh(ErrorCode.COM1005); + entity.NoDealRemark = input.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..0b4d133 --- /dev/null +++ b/sql/创建人次记录表.sql @@ -0,0 +1,48 @@ +-- ============================================ +-- 创建人次记录表(lq_person_times_record) +-- ============================================ +-- 说明:用于记录耗卡/开单时健康师或科技老师的工作人次 +-- 支持人头统计(按健康师+月份+客户去重累加)和人次统计(按健康师+日期+客户去重累加) +-- +-- 业务场景: +-- 1. 耗卡时记录健康师或科技老师的工作人次 +-- 2. 未来可能记录开单时的工作人次 +-- +-- 统计规则: +-- - 人头统计:按健康师+月份+客户去重,累加数量 +-- - 人次统计:按健康师+日期+客户去重,累加数量 +-- ============================================ + +CREATE TABLE IF NOT EXISTS `lq_person_times_record` ( + `F_Id` VARCHAR(50) NOT NULL COMMENT '主键ID', + `F_BusinessId` VARCHAR(50) NULL COMMENT '关联业务记录ID', + `F_BusinessType` VARCHAR(20) NULL COMMENT '业务类型(耗卡/开单)', + `F_PersonType` VARCHAR(20) NULL COMMENT '人员类型(健康师/科技老师)', + `F_PersonId` VARCHAR(50) NULL COMMENT '人员ID', + `F_PersonName` VARCHAR(100) NULL COMMENT '人员姓名', + `F_MemberId` VARCHAR(50) NULL COMMENT '客户ID', + `F_MemberName` VARCHAR(100) NULL COMMENT '客户姓名', + `F_WorkDate` DATE NULL COMMENT '工作日期(用于人次统计,格式:YYYY-MM-DD)', + `F_WorkMonth` VARCHAR(6) NULL COMMENT '工作月份(用于人头统计,格式:202511)', + `F_Quantity` DECIMAL(10,2) NULL COMMENT '数量', + `F_CreateTime` DATETIME NULL COMMENT '创建时间', + `F_IsEffective` INT NULL DEFAULT 1 COMMENT '是否有效', + PRIMARY KEY (`F_Id`), + INDEX `idx_person_month_member` (`F_PersonId`, `F_WorkMonth`, `F_MemberId`) COMMENT '人头统计索引(健康师+月份+客户)', + INDEX `idx_person_date_member` (`F_PersonId`, `F_WorkDate`, `F_MemberId`) COMMENT '人次统计索引(健康师+日期+客户)', + INDEX `idx_business` (`F_BusinessId`, `F_BusinessType`) COMMENT '业务查询索引' +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='人次记录表'; + +-- ============================================ +-- 验证表结构 +-- ============================================ +-- SELECT COLUMN_NAME, DATA_TYPE, IS_NULLABLE, COLUMN_KEY, COLUMN_DEFAULT, COLUMN_COMMENT +-- FROM INFORMATION_SCHEMA.COLUMNS +-- WHERE TABLE_NAME = 'lq_person_times_record' +-- ORDER BY ORDINAL_POSITION; + +-- ============================================ +-- 验证索引 +-- ============================================ +-- SHOW INDEX FROM lq_person_times_record; + 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..032f26b --- /dev/null +++ b/sql/添加品项分类字段.sql @@ -0,0 +1,68 @@ +-- ============================================ +-- 为品项明细表添加品项分类字段 +-- ============================================ +-- 说明:此脚本为品项明细相关表添加品项分类字段,用于存储品项的分类(医美、科美、生美) +-- +-- 字段说明: +-- F_ItemCategory:品项分类,用于存储"医美"、"科美"、"生美"等分类值 +-- +-- 业务含义: +-- - 品项分类用于区分不同类型的品项,便于统计和分析 +-- - 分类值来源于项目资料表(lq_xmzl)的 qt2 字段 +-- +-- 注意事项: +-- - 字段类型为VARCHAR(20),可存储"医美"、"科美"、"生美"等分类值 +-- - 所有字段允许为NULL,因为历史数据可能没有这些分类信息 +-- - 字段位置:放在品项相关字段(px、pxmc)之后 + +-- ============================================ +-- 1. lq_kd_pxmx(开单品项明细表) - 添加品项分类字段 +-- ============================================ +ALTER TABLE lq_kd_pxmx +ADD COLUMN F_ItemCategory VARCHAR(20) NULL COMMENT '品项分类(医美/科美/生美)' AFTER pxmc; + +-- ============================================ +-- 2. lq_kd_deductinfo(开单扣减信息表) - 添加品项分类字段 +-- ============================================ +ALTER TABLE lq_kd_deductinfo +ADD COLUMN F_ItemCategory VARCHAR(20) NULL COMMENT '品项分类(医美/科美/生美)' AFTER F_ItemName; + +-- ============================================ +-- 3. lq_xh_pxmx(耗卡品项明细表) - 添加品项分类字段 +-- ============================================ +ALTER TABLE lq_xh_pxmx +ADD COLUMN F_ItemCategory VARCHAR(20) NULL COMMENT '品项分类(医美/科美/生美)' AFTER pxmc; + +-- ============================================ +-- 4. lq_hytk_mx(会员退卡明细表) - 添加品项分类字段 +-- ============================================ +ALTER TABLE lq_hytk_mx +ADD COLUMN F_ItemCategory VARCHAR(20) NULL COMMENT '品项分类(医美/科美/生美)' AFTER pxmc; + +-- ============================================ +-- 5. 验证字段创建 +-- ============================================ +-- 验证 lq_kd_pxmx 表 +-- SELECT COLUMN_NAME, DATA_TYPE, IS_NULLABLE, COLUMN_COMMENT +-- FROM INFORMATION_SCHEMA.COLUMNS +-- WHERE TABLE_NAME = 'lq_kd_pxmx' +-- AND COLUMN_NAME = 'F_ItemCategory'; + +-- 验证 lq_kd_deductinfo 表 +-- SELECT COLUMN_NAME, DATA_TYPE, IS_NULLABLE, COLUMN_COMMENT +-- FROM INFORMATION_SCHEMA.COLUMNS +-- WHERE TABLE_NAME = 'lq_kd_deductinfo' +-- AND COLUMN_NAME = 'F_ItemCategory'; + +-- 验证 lq_xh_pxmx 表 +-- SELECT COLUMN_NAME, DATA_TYPE, IS_NULLABLE, COLUMN_COMMENT +-- FROM INFORMATION_SCHEMA.COLUMNS +-- WHERE TABLE_NAME = 'lq_xh_pxmx' +-- AND COLUMN_NAME = 'F_ItemCategory'; + +-- 验证 lq_hytk_mx 表 +-- SELECT COLUMN_NAME, DATA_TYPE, IS_NULLABLE, COLUMN_COMMENT +-- FROM INFORMATION_SCHEMA.COLUMNS +-- WHERE TABLE_NAME = 'lq_hytk_mx' +-- AND COLUMN_NAME = 'F_ItemCategory'; + 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'; +