sunpengfei
2025-06-06 92e704206a64f4256e9fd8e9f738d6d3b4c84155
feat:推广相关接口
9个文件已添加
7个文件已修改
1335 ■■■■■ 已修改文件
LifePayment/LifePayment.Application.Contracts/Promoter/ChannelConsultationDto.cs 180 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
LifePayment/LifePayment.Application.Contracts/Promoter/IPromoterService.cs 75 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
LifePayment/LifePayment.Application.Contracts/Promoter/PromoterDto.cs 89 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
LifePayment/LifePayment.Application/LifePaymentServicesApplicationModuleAutoMapperProfile.cs 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
LifePayment/LifePayment.Application/Promoter/PromoterService.cs 285 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
LifePayment/LifePayment.Domain.Shared/Enum/LifePay/LifePayChannelAgentType.cs 29 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
LifePayment/LifePayment.Domain.Shared/Enum/LifePay/LifePayChannelConsultationFollowupStatus.cs 31 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
LifePayment/LifePayment.Domain/LifePay/LifePayChannelConsultation.cs 95 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
LifePayment/LifePayment.Domain/LifePay/LifePayChannles.cs 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
LifePayment/LifePayment.Domain/LifePay/LifePayPromoter.cs 61 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
LifePayment/LifePayment.EntityFrameworkCore/LifePaymentServicesDbContext.cs 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
LifePayment/LifePayment.EntityFrameworkCore/ModelConfigure/ModelDbContextModelBuilderExtensions.cs 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
LifePayment/LifePayment.Host/LifePaymentService.HttpApi.xml 50 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
LifePayment/LifePayment.Host/LifePaymentServices.Application.Contracts.xml 275 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
LifePayment/LifePayment.HttpApi/LifePay/PromoterController.cs 124 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
LifePayment/LifePayment.HttpApi/LifePay/SyncController.cs 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
LifePayment/LifePayment.Application.Contracts/Promoter/ChannelConsultationDto.cs
New file
@@ -0,0 +1,180 @@
using LifePayment.Domain.Shared;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using ZeroD.Util;
namespace LifePayment.Application.Contracts
{
    public class GetChannelConsultationsInput : PageInput
    {
        /// <summary>
        /// 创建的开始时间
        /// </summary>
        public DateTime? StartDate { get; set; }
        /// <summary>
        /// 创建的结束时间
        /// </summary>
        public DateTime? EndDate { get; set; }
        /// <summary>
        /// 搜索关键词
        /// </summary>
        public string SearchKey { get; set; }
    }
    public class ChannelConsultationDto
    {
        /// <summary>
        /// Id
        /// </summary>
        public Guid Id { get; set; }
        /// <summary>
        /// 咨询时间
        /// </summary>
        public DateTime CreationTime { get; set; }
        /// <summary>
        /// 咨询人
        /// </summary>
        public string Name { get; set; }
        /// <summary>
        /// 代理类型
        /// </summary>
        public LifePayChannelAgentType AgentType { get; set; }
        /// <summary>
        /// 联系方式
        /// </summary>
        public string PhoneNumber { get; set; }
        /// <summary>
        /// 公司名称
        /// </summary>
        public string CompanyName { get; set; }
        /// <summary>
        /// 客户资源
        /// </summary>
        public string CustomerResources { get; set; }
        /// <summary>
        /// ID
        /// </summary>
        public string PromoterIdNumber { get; set; }
        /// <summary>
        /// 推广员
        /// </summary>
        public string PromoterName { get; set; }
        /// <summary>
        /// 联系方式
        /// </summary>
        public string PromoterPhoneNumber { get; set; }
        /// <summary>
        /// 回访状态
        /// </summary>
        public LifePayChannelConsultationFollowupStatus FollowupStatus { get; set; }
        /// <summary>
        /// 最近回访
        /// </summary>
        public DateTime? LastFollowupTime { get; set; }
        /// <summary>
        /// 回访记录
        /// </summary>
        public string FollowupRemark { get; set; }
    }
    public class CreateChannelConsultationInput
    {
        /// <summary>
        /// 客户端用户Id 如有
        /// </summary>
        public Guid? UserId { get; set; }
        /// <summary>
        /// 推广人Id
        /// </summary>
        public string IdNumber { get; set; }
        /// <summary>
        /// 咨询人
        /// </summary>
        public string Name { get; set; }
        /// <summary>
        /// 代理类型
        /// </summary>
        public LifePayChannelAgentType? AgentType { get; set; }
        /// <summary>
        /// 联系方式
        /// </summary>
        public string PhoneNumber { get; set; }
        /// <summary>
        /// 公司名称
        /// </summary>
        public string CompanyName { get; set; }
        /// <summary>
        /// 客户资源
        /// </summary>
        public string CustomerResources { get; set; }
    }
    public class CreateChannelConsultationFollowupInput
    {
        /// <summary>
        /// 渠道咨询Id
        /// </summary>
        public Guid ChannelConsultationId { get; set; }
        /// <summary>
        /// 回访状态
        /// </summary>
        public LifePayChannelConsultationFollowupStatus? FollowupStatus { get; set; }
        /// <summary>
        /// 回访记录
        /// </summary>
        public string FollowupRemark { get; set; }
    }
    public class ChannelConsultationFollowupDto
    {
        /// <summary>
        /// 回访人Id
        /// </summary>
        public Guid? CreatorId { get; set; }
        /// <summary>
        /// 回访人
        /// </summary>
        public string Creator { get; set; }
        /// <summary>
        /// 回访状态
        /// </summary>
        public LifePayChannelConsultationFollowupStatus? FollowupStatus { get; set; }
        /// <summary>
        /// 回访记录
        /// </summary>
        public string FollowupRemark { get; set; }
        /// <summary>
        /// 咨询时间
        /// </summary>
        public DateTime CreationTime { get; set; }
    }
}
LifePayment/LifePayment.Application.Contracts/Promoter/IPromoterService.cs
New file
@@ -0,0 +1,75 @@
using AutoMapper;
using LifePayment.Domain.Shared;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Volo.Abp.Application.Services;
using Volo.Abp.AutoMapper;
using Volo.Abp.Users;
using ZeroD.Util;
namespace LifePayment.Application.Contracts
{
    public interface IPromoterService : IApplicationService
    {
        #region 查询
        /// <summary>
        /// 获取推广员列表
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        Task<PageOutput<PromoterDto>> GetPromoters(GetPromotersInput input);
        /// <summary>
        /// 获取渠道咨询列表
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        Task<PageOutput<ChannelConsultationDto>> GetChannelConsultation(GetChannelConsultationsInput input);
        /// <summary>
        /// 获取渠道咨询回访记录
        /// </summary>
        /// <param name="id">渠道咨询Id</param>
        /// <returns></returns>
        Task<List<ChannelConsultationFollowupDto>> GetChannelConsultationFollowupList(Guid id);
        #endregion
        #region 写入
        /// <summary>
        /// 创建或更新推广员
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        /// <exception cref="FormatException"></exception>
        Task<Guid> CreateOrUpdatePromoter(CreateOrUpdatePromoterInput input);
        /// <summary>
        /// 点击数+1
        /// </summary>
        /// <param name="idnumber"></param>
        /// <returns></returns>
        Task SetClickCount(string idnumber);
        /// <summary>
        /// 申请渠道咨询
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        Task<Guid> CreateChannelConsultation(CreateChannelConsultationInput input);
        /// <summary>
        /// 新增回访
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        Task<Guid> CreateChannelConsultationFollowup(CreateChannelConsultationFollowupInput input);
        #endregion
    }
}
LifePayment/LifePayment.Application.Contracts/Promoter/PromoterDto.cs
New file
@@ -0,0 +1,89 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using ZeroD.Util;
namespace LifePayment.Application.Contracts
{
    public class GetPromotersInput : PageInput
    {
    }
    public class PromoterDto
    {
        /// <summary>
        /// Id
        /// </summary>
        public Guid Id { get; set; }
        /// <summary>
        /// 咨询时间
        /// </summary>
        public DateTime CreationTime { get; set; }
        /// <summary>
        /// ID
        /// </summary>
        public string IdNumber { get; set; }
        /// <summary>
        /// 推广员
        /// </summary>
        public string Name { get; set; }
        /// <summary>
        /// 联系方式
        /// </summary>
        public string PhoneNumber { get; set; }
        /// <summary>
        /// 点击数
        /// </summary>
        public int ClickCount { get; set; }
        /// <summary>
        /// 申请数
        /// </summary>
        public int ApplyCount { get; set; }
        /// <summary>
        /// 备注
        /// </summary>
        public string Remark { get; set; }
    }
    public class CreateOrUpdatePromoterInput
    {
        /// <summary>
        /// Id
        /// </summary>
        public Guid? Id { get; set; }
        /// <summary>
        /// 客户端用户Id 如有
        /// </summary>
        public Guid? UserId { get; set; }
        /// <summary>
        /// ID
        /// </summary>
        public string IdNumber { get; set; }
        /// <summary>
        /// 推广员
        /// </summary>
        public string Name { get; set; }
        /// <summary>
        /// 联系方式
        /// </summary>
        public string PhoneNumber { get; set; }
        /// <summary>
        /// 备注
        /// </summary>
        public string Remark { get; set; }
    }
}
LifePayment/LifePayment.Application/LifePaymentServicesApplicationModuleAutoMapperProfile.cs
@@ -2,6 +2,7 @@
using LifePayment.Application.Contracts;
using LifePayment.Application.Contracts.Sync;
using LifePayment.Domain;
using LifePayment.Domain.LifePay;
using LifePayment.Domain.Models;
namespace LifePayment.Application
@@ -27,6 +28,15 @@
            CreateMap<SyncLifePayChannlesRake, SyncLifePayChannlesRake>(MemberList.None);
            CreateMap<SyncLifePayConsumption, SyncLifePayConsumption>(MemberList.None);
            CreateMap<SyncLifePayExpensesReceipts, SyncLifePayExpensesReceipts>(MemberList.None);
            CreateMap<LifePayPromoter, PromoterDto>(MemberList.None);
            CreateMap<CreateOrUpdatePromoterInput, LifePayPromoter>(MemberList.None);
            CreateMap<LifePayChannelConsultation, ChannelConsultationDto>(MemberList.None);
            CreateMap<CreateChannelConsultationInput, LifePayChannelConsultation>(MemberList.None);
            CreateMap<CreateChannelConsultationFollowupInput, LifePayChannelConsultationFollowup>(MemberList.None);
        }
    }
}
LifePayment/LifePayment.Application/Promoter/PromoterService.cs
New file
@@ -0,0 +1,285 @@
using AutoMapper.QueryableExtensions;
using LifePayment.Application.Contracts;
using LifePayment.Domain;
using LifePayment.Domain.LifePay;
using LifePayment.Domain.Models;
using LifePayment.Domain.Shared;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using Nest;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Volo.Abp.Application.Services;
using Volo.Abp.AutoMapper;
using Volo.Abp.Domain.Repositories;
using ZeroD.Util;
namespace LifePayment.Application.Promoter
{
    /// <summary>
    /// 推广服务
    /// </summary>
    public class PromoterService : ApplicationService, IPromoterService
    {
        private readonly IMapperAccessor mapperAccessor;
        private readonly ILogger<PromoterService> logger;
        private readonly IRepository<LifePayPromoter, Guid> lifePayPromoterRepository;
        private readonly IRepository<LifePayChannelConsultation, Guid> lifePayChannelConsultationRepository;
        private readonly IRepository<LifePayChannelConsultationFollowup, Guid> lifePayChannelConsultationFollowupRepository;
        private readonly IRepository<User, Guid> userRepository;
        public PromoterService(
            IMapperAccessor mapperAccessor,
            ILogger<PromoterService> logger,
            IRepository<LifePayPromoter, Guid> lifePayPromoterRepository,
            IRepository<LifePayChannelConsultation, Guid> lifePayChannelConsultationRepository,
            IRepository<LifePayChannelConsultationFollowup, Guid> lifePayChannelConsultationFollowupRepository,
            IRepository<User, Guid> userRepository)
        {
            this.mapperAccessor = mapperAccessor;
            this.logger = logger;
            this.lifePayPromoterRepository = lifePayPromoterRepository;
            this.lifePayChannelConsultationRepository = lifePayChannelConsultationRepository;
            this.lifePayChannelConsultationFollowupRepository = lifePayChannelConsultationFollowupRepository;
            this.userRepository = userRepository;
        }
        #region 查询
        /// <summary>
        /// 获取推广员列表
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task<PageOutput<PromoterDto>> GetPromoters(GetPromotersInput input)
        {
            var query = lifePayPromoterRepository.Select(it => new PromoterDto
            {
                Id = it.Id,
                CreationTime = it.CreationTime,
                IdNumber = it.IdNumber,
                Name = it.Name,
                PhoneNumber = it.PhoneNumber,
                ClickCount = it.ClickCount,
                ApplyCount = it.ApplyCount,
                Remark = it.Remark,
            });
            var result = await query.GetPageResult(input.PageModel);
            return result;
        }
        /// <summary>
        /// 获取渠道咨询列表
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task<PageOutput<ChannelConsultationDto>> GetChannelConsultation(GetChannelConsultationsInput input)
        {
            var query = from cc in lifePayChannelConsultationRepository
                        join p in lifePayPromoterRepository on cc.PromoterId equals p.Id into pg
                        from pgd in pg.DefaultIfEmpty()
                        select new ChannelConsultationDto
                        {
                            Id = cc.Id,
                            CreationTime = cc.CreationTime,
                            Name = cc.Name,
                            AgentType = cc.AgentType,
                            PhoneNumber = cc.PhoneNumber,
                            CompanyName = cc.CompanyName,
                            CustomerResources = cc.CustomerResources,
                            PromoterIdNumber = pgd.IdNumber,
                            PromoterName = pgd.Name,
                            PromoterPhoneNumber = pgd.PhoneNumber,
                            FollowupStatus = cc.FollowupStatus,
                            LastFollowupTime = cc.LastFollowupTime,
                            FollowupRemark = cc.FollowupRemark,
                        };
            if (input.StartDate.HasValue)
            {
                query = query.Where(s => s.CreationTime >= input.StartDate);
            }
            if (input.EndDate.HasValue)
            {
                query = query.Where(s => s.CreationTime <= input.EndDate);
            }
            if (!string.IsNullOrEmpty(input.SearchKey))
            {
                query = query.Where(s =>
                    s.Name.Contains(input.SearchKey)
                    || s.PhoneNumber.Contains(input.SearchKey)
                    || s.Name.Contains(input.SearchKey)
                    || s.PhoneNumber.Contains(input.SearchKey));
            }
            var result = await query.GetPageResult(input.PageModel);
            return result;
        }
        /// <summary>
        /// 获取渠道咨询回访记录
        /// </summary>
        /// <param name="id">渠道咨询Id</param>
        /// <returns></returns>
        public async Task<List<ChannelConsultationFollowupDto>> GetChannelConsultationFollowupList(Guid id)
        {
            var query = from f in lifePayChannelConsultationFollowupRepository
                        join u in userRepository on f.CreatorId equals u.Id into ug
                        from ugd in ug.DefaultIfEmpty()
                        where f.ChannelConsultationId == id
                        select new ChannelConsultationFollowupDto
                        {
                            CreatorId = f.CreatorId,
                            Creator = ugd.Name,
                            FollowupStatus = f.FollowupStatus,
                            FollowupRemark = f.FollowupRemark,
                            CreationTime = f.CreationTime,
                        };
            var list = await query.ToListAsync();
            return list;
        }
        #endregion
        #region 写入
        /// <summary>
        /// 创建或更新推广员
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        /// <exception cref="FormatException"></exception>
        public async Task<Guid> CreateOrUpdatePromoter(CreateOrUpdatePromoterInput input)
        {
            CheckExtensions.IfTrueThrowUserFriendlyException(string.IsNullOrWhiteSpace(input.Name), "请输入推广人");
            CheckExtensions.IfTrueThrowUserFriendlyException(string.IsNullOrWhiteSpace(input.PhoneNumber), "请输入联系方式");
            if (string.IsNullOrEmpty(input.IdNumber))
            {
                input.IdNumber = BuildIdNumber();
            }
            else if (input.Id == null)
            {
                var exist = await lifePayPromoterRepository.FirstOrDefaultAsync(it => it.IdNumber == input.IdNumber || it.PhoneNumber == input.PhoneNumber);
                if (exist != null)
                {
                    if (exist.IdNumber == input.IdNumber)
                    {
                        throw new FormatException("该ID已存在");
                    }
                    if (exist.PhoneNumber == input.PhoneNumber)
                    {
                        throw new FormatException("该手机号已申请");
                    }
                }
            }
            if (input.Id == null)
            {
                var entity = new LifePayPromoter();
                ObjectMapper.Map(input, entity);
                await lifePayPromoterRepository.InsertAsync(entity);
                return entity.Id;
            }
            else
            {
                var entity = await lifePayPromoterRepository.FirstOrDefaultAsync(it => it.Id == input.Id);
                CheckExtensions.IfTrueThrowUserFriendlyException(entity == null, "该推广员不存在");
                ObjectMapper.Map(input, entity);
                await lifePayPromoterRepository.UpdateAsync(entity);
                return entity.Id;
            }
        }
        /// <summary>
        /// 点击数+1
        /// </summary>
        /// <param name="idnumber"></param>
        /// <returns></returns>
        public async Task SetClickCount(string idnumber)
        {
            var entity = await lifePayPromoterRepository.FirstOrDefaultAsync(it => it.IdNumber == idnumber);
            CheckExtensions.IfTrueThrowUserFriendlyException(entity == null, "该推广员不存在");
            entity.ClickCount++;
            await lifePayPromoterRepository.UpdateAsync(entity);
        }
        /// <summary>
        /// 申请渠道咨询
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task<Guid> CreateChannelConsultation(CreateChannelConsultationInput input)
        {
            CheckExtensions.IfTrueThrowUserFriendlyException(string.IsNullOrWhiteSpace(input.Name), "请输入姓名");
            CheckExtensions.IfTrueThrowUserFriendlyException(string.IsNullOrWhiteSpace(input.PhoneNumber), "请输入联系方式");
            CheckExtensions.IfTrueThrowUserFriendlyException(input.AgentType == null, "请选择代理类型");
            CheckExtensions.IfTrueThrowUserFriendlyException(string.IsNullOrWhiteSpace(input.CustomerResources), "请输入客户资源");
            var entity = new LifePayChannelConsultation();
            ObjectMapper.Map(input, entity);
            if (!string.IsNullOrWhiteSpace(input.IdNumber))
            {
                var promoter = await lifePayPromoterRepository.FirstOrDefaultAsync(it => it.IdNumber == input.IdNumber);
                if (promoter != null)
                {
                    entity.PromoterId = promoter.Id;
                    promoter.ApplyCount++;
                    await lifePayPromoterRepository.UpdateAsync(promoter);
                }
            }
            await lifePayChannelConsultationRepository.InsertAsync(entity);
            return entity.Id;
        }
        /// <summary>
        /// 新增回访
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task<Guid> CreateChannelConsultationFollowup(CreateChannelConsultationFollowupInput input)
        {
            CheckExtensions.IfTrueThrowUserFriendlyException(input.FollowupStatus == null, "请选择回访状态");
            CheckExtensions.IfTrueThrowUserFriendlyException(string.IsNullOrWhiteSpace(input.FollowupRemark), "请输入回访记录");
            var consultation = await lifePayChannelConsultationRepository.FirstOrDefaultAsync(it => it.Id == input.ChannelConsultationId);
            CheckExtensions.IfTrueThrowUserFriendlyException(consultation == null, "该渠道咨询不存在");
            var entity = new LifePayChannelConsultationFollowup();
            ObjectMapper.Map(input, entity);
            await lifePayChannelConsultationFollowupRepository.InsertAsync(entity);
            consultation.FollowupRemark = entity.FollowupRemark;
            consultation.FollowupStatus = entity.FollowupStatus;
            consultation.LastFollowupTime = entity.CreationTime;
            await lifePayChannelConsultationRepository.UpdateAsync(consultation);
            return entity.Id;
        }
        #endregion
        /// <summary>
        /// 生成Id
        /// </summary>
        /// <returns></returns>
        private string BuildIdNumber()
        {
            var num = DateTimeOffset.UtcNow.ToUnixTimeSeconds().ToString();
            var exist = lifePayPromoterRepository.Any(it => it.IdNumber == num);
            if (exist)
            {
                return BuildIdNumber();
            }
            return num;
        }
    }
}
LifePayment/LifePayment.Domain.Shared/Enum/LifePay/LifePayChannelAgentType.cs
New file
@@ -0,0 +1,29 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace LifePayment.Domain.Shared
{
    /// <summary>
    /// 代理类型
    /// </summary>
    public enum LifePayChannelAgentType
    {
        /// <summary>
        /// 零售代理
        /// </summary>
        RetailAgent = 1,
        /// <summary>
        /// 品牌代理
        /// </summary>
        BrandAgent = 2,
        /// <summary>
        /// 区域代理
        /// </summary>
        AreaAgent = 3
    }
}
LifePayment/LifePayment.Domain.Shared/Enum/LifePay/LifePayChannelConsultationFollowupStatus.cs
New file
@@ -0,0 +1,31 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace LifePayment.Domain.Shared
{
    public enum LifePayChannelConsultationFollowupStatus
    {
        /// <summary>
        /// 未回访
        /// </summary>
        None = 0,
        /// <summary>
        /// 跟进中
        /// </summary>
        Ing = 1,
        /// <summary>
        /// 已拒绝
        /// </summary>
        Refuse = 1,
        /// <summary>
        /// 已开通
        /// </summary>
        Open = 1,
    }
}
LifePayment/LifePayment.Domain/LifePay/LifePayChannelConsultation.cs
New file
@@ -0,0 +1,95 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Volo.Abp.Domain.Entities.Auditing;
using Volo.Abp;
using LifePayment.Domain.LifePay;
using LifePayment.Domain.Shared;
using LifePayment.Domain.Models;
namespace LifePayment.Domain
{
    /// <summary>
    /// 渠道咨询
    /// </summary>
    public class LifePayChannelConsultation : FullAuditedEntity<Guid>, IDataUserFilter
    {
        /// <summary>
        /// 用户Id
        /// </summary>
        public Guid? UserId { get; set; }
        /// <summary>
        /// 推广员
        /// </summary>
        public Guid? PromoterId { get; set; }
        /// <summary>
        /// 推广员
        /// </summary>
        public LifePayPromoter Promoter { get; set; }
        /// <summary>
        /// 咨询人
        /// </summary>
        public string Name { get; set; }
        /// <summary>
        /// 代理类型
        /// </summary>
        public LifePayChannelAgentType AgentType { get; set; }
        /// <summary>
        /// 联系方式
        /// </summary>
        public string PhoneNumber { get; set; }
        /// <summary>
        /// 公司名称
        /// </summary>
        public string CompanyName { get; set; }
        /// <summary>
        /// 客户资源
        /// </summary>
        public string CustomerResources { get; set; }
        /// <summary>
        /// 回访状态
        /// </summary>
        public LifePayChannelConsultationFollowupStatus FollowupStatus { get; set; }
        /// <summary>
        /// 最近回访
        /// </summary>
        public DateTime? LastFollowupTime { get; set; }
        /// <summary>
        /// 回访记录
        /// </summary>
        public string FollowupRemark { get; set; }
    }
    /// <summary>
    /// 渠道咨询回访
    /// </summary>
    public class LifePayChannelConsultationFollowup : FullAuditedEntity<Guid>, IDataUserFilter
    {
        /// <summary>
        /// 渠道咨询Id
        /// </summary>
        public Guid ChannelConsultationId { get; set; }
        /// <summary>
        /// 回访状态
        /// </summary>
        public LifePayChannelConsultationFollowupStatus FollowupStatus { get; set; }
        /// <summary>
        /// 回访记录
        /// </summary>
        public string FollowupRemark { get; set; }
    }
}
LifePayment/LifePayment.Domain/LifePay/LifePayChannles.cs
@@ -24,4 +24,24 @@
    public LifePayChannelsStatsEnum Status { get; set; }
    public LifePayChannlesTypeEnum ChannlesType { get; set; }
    /// <summary>
    /// 代理类型
    /// </summary>
    public LifePayChannelAgentType? AgentType { get; set; }
    /// <summary>
    /// 区域-省Id
    /// </summary>
    public int? AreaProvinceId { get; set; }
    /// <summary>
    /// 区域-市Id
    /// </summary>
    public int? AreaCityId { get; set; }
    /// <summary>
    /// 推广员Id
    /// </summary>
    public Guid? PromoterId { get; set; }
}
LifePayment/LifePayment.Domain/LifePay/LifePayPromoter.cs
New file
@@ -0,0 +1,61 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Volo.Abp.Domain.Entities.Auditing;
using Volo.Abp;
namespace LifePayment.Domain.LifePay
{
    /// <summary>
    /// 推广员
    /// </summary>
    public class LifePayPromoter : FullAuditedEntity<Guid>, IDataUserFilter
    {
        public LifePayPromoter()
        {
            ChannelConsultations = new HashSet<LifePayChannelConsultation>();
        }
        /// <summary>
        /// 用户Id
        /// </summary>
        public Guid? UserId { get; set; }
        /// <summary>
        /// ID
        /// </summary>
        public string IdNumber { get; set; }
        /// <summary>
        /// 推广员
        /// </summary>
        public string Name { get; set; }
        /// <summary>
        /// 联系方式
        /// </summary>
        public string PhoneNumber { get; set; }
        /// <summary>
        /// 点击数
        /// </summary>
        public int ClickCount { get; set; }
        /// <summary>
        /// 申请数
        /// </summary>
        public int ApplyCount { get; set; }
        /// <summary>
        /// 备注
        /// </summary>
        public string Remark { get; set; }
        /// <summary>
        /// 渠道咨询
        /// </summary>
        public ICollection<LifePayChannelConsultation> ChannelConsultations { get; set; }
    }
}
LifePayment/LifePayment.EntityFrameworkCore/LifePaymentServicesDbContext.cs
@@ -17,6 +17,12 @@
        {
        }
        public virtual DbSet<LifePayPromoter> LifePayPromoter { get; set; }
        public virtual DbSet<LifePayChannelConsultation> LifePayChannelConsultation { get; set; }
        public virtual DbSet<LifePayChannelConsultationFollowup> LifePayChannelConsultationFollowup { get; set; }
        public virtual DbSet<LifePayUser> LifePayUser { get; set; }
        public virtual DbSet<LifePayOrder> LifePayOrder { get; set; }
LifePayment/LifePayment.EntityFrameworkCore/ModelConfigure/ModelDbContextModelBuilderExtensions.cs
@@ -1,4 +1,6 @@
using LifePayment.Domain.Models;
using LifePayment.Domain;
using LifePayment.Domain.LifePay;
using LifePayment.Domain.Models;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
LifePayment/LifePayment.Host/LifePaymentService.HttpApi.xml
@@ -513,6 +513,56 @@
            <param name="input"></param>
            <returns></returns>
        </member>
        <member name="M:LifePayment.HttpApi.PromoterController.GetPromoters(LifePayment.Application.Contracts.GetPromotersInput)">
            <summary>
            获取推广员列表
            </summary>
            <param name="input"></param>
            <returns></returns>
        </member>
        <member name="M:LifePayment.HttpApi.PromoterController.GetChannelConsultation(LifePayment.Application.Contracts.GetChannelConsultationsInput)">
            <summary>
            获取渠道咨询列表
            </summary>
            <param name="input"></param>
            <returns></returns>
        </member>
        <member name="M:LifePayment.HttpApi.PromoterController.GetChannelConsultationFollowupList(System.Guid)">
            <summary>
            获取渠道咨询回访记录
            </summary>
            <param name="id">渠道咨询Id</param>
            <returns></returns>
        </member>
        <member name="M:LifePayment.HttpApi.PromoterController.CreateOrUpdatePromoter(LifePayment.Application.Contracts.CreateOrUpdatePromoterInput)">
            <summary>
            创建或更新推广员
            </summary>
            <param name="input"></param>
            <returns></returns>
            <exception cref="T:System.FormatException"></exception>
        </member>
        <member name="M:LifePayment.HttpApi.PromoterController.SetClickCount(System.String)">
            <summary>
            点击数+1
            </summary>
            <param name="idnumber"></param>
            <returns></returns>
        </member>
        <member name="M:LifePayment.HttpApi.PromoterController.CreateChannelConsultation(LifePayment.Application.Contracts.CreateChannelConsultationInput)">
            <summary>
            申请渠道咨询
            </summary>
            <param name="input"></param>
            <returns></returns>
        </member>
        <member name="M:LifePayment.HttpApi.PromoterController.CreateChannelConsultationFollowup(LifePayment.Application.Contracts.CreateChannelConsultationFollowupInput)">
            <summary>
            新增回访
            </summary>
            <param name="input"></param>
            <returns></returns>
        </member>
        <member name="M:LifePayment.HttpApi.SyncController.SyncFromTest">
            <summary>
            同步测试订单数据
LifePayment/LifePayment.Host/LifePaymentServices.Application.Contracts.xml
@@ -2112,6 +2112,281 @@
            结算时间
            </summary>
        </member>
        <member name="P:LifePayment.Application.Contracts.GetChannelConsultationsInput.StartDate">
            <summary>
            创建的开始时间
            </summary>
        </member>
        <member name="P:LifePayment.Application.Contracts.GetChannelConsultationsInput.EndDate">
            <summary>
            创建的结束时间
            </summary>
        </member>
        <member name="P:LifePayment.Application.Contracts.GetChannelConsultationsInput.SearchKey">
            <summary>
            搜索关键词
            </summary>
        </member>
        <member name="P:LifePayment.Application.Contracts.ChannelConsultationDto.Id">
            <summary>
            Id
            </summary>
        </member>
        <member name="P:LifePayment.Application.Contracts.ChannelConsultationDto.CreationTime">
            <summary>
            咨询时间
            </summary>
        </member>
        <member name="P:LifePayment.Application.Contracts.ChannelConsultationDto.Name">
            <summary>
            咨询人
            </summary>
        </member>
        <member name="P:LifePayment.Application.Contracts.ChannelConsultationDto.AgentType">
            <summary>
            代理类型
            </summary>
        </member>
        <member name="P:LifePayment.Application.Contracts.ChannelConsultationDto.PhoneNumber">
            <summary>
            联系方式
            </summary>
        </member>
        <member name="P:LifePayment.Application.Contracts.ChannelConsultationDto.CompanyName">
            <summary>
            公司名称
            </summary>
        </member>
        <member name="P:LifePayment.Application.Contracts.ChannelConsultationDto.CustomerResources">
            <summary>
            客户资源
            </summary>
        </member>
        <member name="P:LifePayment.Application.Contracts.ChannelConsultationDto.PromoterIdNumber">
            <summary>
            ID
            </summary>
        </member>
        <member name="P:LifePayment.Application.Contracts.ChannelConsultationDto.PromoterName">
            <summary>
            推广员
            </summary>
        </member>
        <member name="P:LifePayment.Application.Contracts.ChannelConsultationDto.PromoterPhoneNumber">
            <summary>
            联系方式
            </summary>
        </member>
        <member name="P:LifePayment.Application.Contracts.ChannelConsultationDto.FollowupStatus">
            <summary>
            回访状态
            </summary>
        </member>
        <member name="P:LifePayment.Application.Contracts.ChannelConsultationDto.LastFollowupTime">
            <summary>
            最近回访
            </summary>
        </member>
        <member name="P:LifePayment.Application.Contracts.ChannelConsultationDto.FollowupRemark">
            <summary>
            回访记录
            </summary>
        </member>
        <member name="P:LifePayment.Application.Contracts.CreateChannelConsultationInput.UserId">
            <summary>
            客户端用户Id 如有
            </summary>
        </member>
        <member name="P:LifePayment.Application.Contracts.CreateChannelConsultationInput.IdNumber">
            <summary>
            推广人Id
            </summary>
        </member>
        <member name="P:LifePayment.Application.Contracts.CreateChannelConsultationInput.Name">
            <summary>
            咨询人
            </summary>
        </member>
        <member name="P:LifePayment.Application.Contracts.CreateChannelConsultationInput.AgentType">
            <summary>
            代理类型
            </summary>
        </member>
        <member name="P:LifePayment.Application.Contracts.CreateChannelConsultationInput.PhoneNumber">
            <summary>
            联系方式
            </summary>
        </member>
        <member name="P:LifePayment.Application.Contracts.CreateChannelConsultationInput.CompanyName">
            <summary>
            公司名称
            </summary>
        </member>
        <member name="P:LifePayment.Application.Contracts.CreateChannelConsultationInput.CustomerResources">
            <summary>
            客户资源
            </summary>
        </member>
        <member name="P:LifePayment.Application.Contracts.CreateChannelConsultationFollowupInput.ChannelConsultationId">
            <summary>
            渠道咨询Id
            </summary>
        </member>
        <member name="P:LifePayment.Application.Contracts.CreateChannelConsultationFollowupInput.FollowupStatus">
            <summary>
            回访状态
            </summary>
        </member>
        <member name="P:LifePayment.Application.Contracts.CreateChannelConsultationFollowupInput.FollowupRemark">
            <summary>
            回访记录
            </summary>
        </member>
        <member name="P:LifePayment.Application.Contracts.ChannelConsultationFollowupDto.CreatorId">
            <summary>
            回访人Id
            </summary>
        </member>
        <member name="P:LifePayment.Application.Contracts.ChannelConsultationFollowupDto.Creator">
            <summary>
            回访人
            </summary>
        </member>
        <member name="P:LifePayment.Application.Contracts.ChannelConsultationFollowupDto.FollowupStatus">
            <summary>
            回访状态
            </summary>
        </member>
        <member name="P:LifePayment.Application.Contracts.ChannelConsultationFollowupDto.FollowupRemark">
            <summary>
            回访记录
            </summary>
        </member>
        <member name="P:LifePayment.Application.Contracts.ChannelConsultationFollowupDto.CreationTime">
            <summary>
            咨询时间
            </summary>
        </member>
        <member name="M:LifePayment.Application.Contracts.IPromoterService.GetPromoters(LifePayment.Application.Contracts.GetPromotersInput)">
            <summary>
            获取推广员列表
            </summary>
            <param name="input"></param>
            <returns></returns>
        </member>
        <member name="M:LifePayment.Application.Contracts.IPromoterService.GetChannelConsultation(LifePayment.Application.Contracts.GetChannelConsultationsInput)">
            <summary>
            获取渠道咨询列表
            </summary>
            <param name="input"></param>
            <returns></returns>
        </member>
        <member name="M:LifePayment.Application.Contracts.IPromoterService.GetChannelConsultationFollowupList(System.Guid)">
            <summary>
            获取渠道咨询回访记录
            </summary>
            <param name="id">渠道咨询Id</param>
            <returns></returns>
        </member>
        <member name="M:LifePayment.Application.Contracts.IPromoterService.CreateOrUpdatePromoter(LifePayment.Application.Contracts.CreateOrUpdatePromoterInput)">
            <summary>
            创建或更新推广员
            </summary>
            <param name="input"></param>
            <returns></returns>
            <exception cref="T:System.FormatException"></exception>
        </member>
        <member name="M:LifePayment.Application.Contracts.IPromoterService.SetClickCount(System.String)">
            <summary>
            点击数+1
            </summary>
            <param name="idnumber"></param>
            <returns></returns>
        </member>
        <member name="M:LifePayment.Application.Contracts.IPromoterService.CreateChannelConsultation(LifePayment.Application.Contracts.CreateChannelConsultationInput)">
            <summary>
            申请渠道咨询
            </summary>
            <param name="input"></param>
            <returns></returns>
        </member>
        <member name="M:LifePayment.Application.Contracts.IPromoterService.CreateChannelConsultationFollowup(LifePayment.Application.Contracts.CreateChannelConsultationFollowupInput)">
            <summary>
            新增回访
            </summary>
            <param name="input"></param>
            <returns></returns>
        </member>
        <member name="P:LifePayment.Application.Contracts.PromoterDto.Id">
            <summary>
            Id
            </summary>
        </member>
        <member name="P:LifePayment.Application.Contracts.PromoterDto.CreationTime">
            <summary>
            咨询时间
            </summary>
        </member>
        <member name="P:LifePayment.Application.Contracts.PromoterDto.IdNumber">
            <summary>
            ID
            </summary>
        </member>
        <member name="P:LifePayment.Application.Contracts.PromoterDto.Name">
            <summary>
            推广员
            </summary>
        </member>
        <member name="P:LifePayment.Application.Contracts.PromoterDto.PhoneNumber">
            <summary>
            联系方式
            </summary>
        </member>
        <member name="P:LifePayment.Application.Contracts.PromoterDto.ClickCount">
            <summary>
            点击数
            </summary>
        </member>
        <member name="P:LifePayment.Application.Contracts.PromoterDto.ApplyCount">
            <summary>
            申请数
            </summary>
        </member>
        <member name="P:LifePayment.Application.Contracts.PromoterDto.Remark">
            <summary>
            备注
            </summary>
        </member>
        <member name="P:LifePayment.Application.Contracts.CreateOrUpdatePromoterInput.Id">
            <summary>
            Id
            </summary>
        </member>
        <member name="P:LifePayment.Application.Contracts.CreateOrUpdatePromoterInput.UserId">
            <summary>
            客户端用户Id 如有
            </summary>
        </member>
        <member name="P:LifePayment.Application.Contracts.CreateOrUpdatePromoterInput.IdNumber">
            <summary>
            ID
            </summary>
        </member>
        <member name="P:LifePayment.Application.Contracts.CreateOrUpdatePromoterInput.Name">
            <summary>
            推广员
            </summary>
        </member>
        <member name="P:LifePayment.Application.Contracts.CreateOrUpdatePromoterInput.PhoneNumber">
            <summary>
            联系方式
            </summary>
        </member>
        <member name="P:LifePayment.Application.Contracts.CreateOrUpdatePromoterInput.Remark">
            <summary>
            备注
            </summary>
        </member>
        <member name="P:LifePayment.Application.Contracts.RecordOperateHistoryEto.RelationId">
            <summary>
            关联关系ID
LifePayment/LifePayment.HttpApi/LifePay/PromoterController.cs
New file
@@ -0,0 +1,124 @@
using AutoMapper;
using LifePayment.Application.Contracts;
using LifePayment.Domain.LifePay;
using LifePayment.Domain.Shared;
using LifePayment.Domain;
using System.Collections.Generic;
using System.Threading.Tasks;
using System;
using Volo.Abp.AutoMapper;
using Volo.Abp.Users;
using ZeroD.Util;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Volo.Abp.AspNetCore.Mvc;
using ZeroD.Util.Fadd;
using Volo.Abp.Uow;
using Nest;
namespace LifePayment.HttpApi
{
    [Route("api/[controller]/[action]")]
    [ApiController]
    [Authorize]
    public class PromoterController : AbpController
    {
        private readonly IPromoterService promoterService;
        public PromoterController(IPromoterService promoterService)
        {
            this.promoterService = promoterService;
        }
        #region 查询
        /// <summary>
        /// 获取推广员列表
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<PageOutput<PromoterDto>> GetPromoters(GetPromotersInput input)
        {
            return await promoterService.GetPromoters(input);
        }
        /// <summary>
        /// 获取渠道咨询列表
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<PageOutput<ChannelConsultationDto>> GetChannelConsultation(GetChannelConsultationsInput input)
        {
            return await promoterService.GetChannelConsultation(input);
        }
        /// <summary>
        /// 获取渠道咨询回访记录
        /// </summary>
        /// <param name="id">渠道咨询Id</param>
        /// <returns></returns>
        [HttpGet]
        public async Task<List<ChannelConsultationFollowupDto>> GetChannelConsultationFollowupList(Guid id)
        {
            return await promoterService.GetChannelConsultationFollowupList(id);
        }
        #endregion
        #region 写入
        /// <summary>
        /// 创建或更新推广员
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        /// <exception cref="FormatException"></exception>
        [HttpPost]
        [AllowAnonymous]
        public async Task<Guid> CreateOrUpdatePromoter(CreateOrUpdatePromoterInput input)
        {
            return await promoterService.CreateOrUpdatePromoter(input);
        }
        /// <summary>
        /// 点击数+1
        /// </summary>
        /// <param name="idnumber"></param>
        /// <returns></returns>
        [HttpPost]
        [AllowAnonymous]
        public async Task SetClickCount(string idnumber)
        {
            await promoterService.SetClickCount(idnumber);
        }
        /// <summary>
        /// 申请渠道咨询
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [HttpPost]
        [UnitOfWork]
        [AllowAnonymous]
        public async Task<Guid> CreateChannelConsultation(CreateChannelConsultationInput input)
        {
            return await promoterService.CreateChannelConsultation(input);
        }
        /// <summary>
        /// 新增回访
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [HttpPost]
        [UnitOfWork]
        public async Task<Guid> CreateChannelConsultationFollowup(CreateChannelConsultationFollowupInput input)
        {
            return await promoterService.CreateChannelConsultationFollowup(input);
        }
        #endregion
    }
}
LifePayment/LifePayment.HttpApi/LifePay/SyncController.cs
@@ -24,7 +24,6 @@
        /// </summary>
        /// <returns></returns>
        [HttpPost]
        [AllowAnonymous]
        public Task<List<string>> SyncFromTest()
        {
            return syncService.SyncFromTest();