|  | @@ -0,0 +1,276 @@
 | 
	
		
			
				|  |  | +using NPOI.SS.Formula.PTG;
 | 
	
		
			
				|  |  | +using System;
 | 
	
		
			
				|  |  | +using System.Collections.Generic;
 | 
	
		
			
				|  |  | +using System.Linq;
 | 
	
		
			
				|  |  | +using System.Text;
 | 
	
		
			
				|  |  | +using System.Threading.Tasks;
 | 
	
		
			
				|  |  | +using ZhonTai.Admin.Core.Consts;
 | 
	
		
			
				|  |  | +using ZhonTai.Admin.Services.ProjectLink;
 | 
	
		
			
				|  |  | +using ZhonTai.DynamicApi.Attributes;
 | 
	
		
			
				|  |  | +using ZhonTai.DynamicApi;
 | 
	
		
			
				|  |  | +using ZhonTai.Admin.Domain.Project;
 | 
	
		
			
				|  |  | +using Microsoft.AspNetCore.Mvc;
 | 
	
		
			
				|  |  | +using ZhonTai.Admin.Core.Dto;
 | 
	
		
			
				|  |  | +using ZhonTai.Admin.Services.ProjectStat.Dto;
 | 
	
		
			
				|  |  | +using ZhonTai.Admin.Domain.Org;
 | 
	
		
			
				|  |  | +using System.ComponentModel.DataAnnotations;
 | 
	
		
			
				|  |  | +using Microsoft.AspNetCore.Http;
 | 
	
		
			
				|  |  | +using ZhonTai.Admin.Core.Configs;
 | 
	
		
			
				|  |  | +using Microsoft.Extensions.Options;
 | 
	
		
			
				|  |  | +using System.IO;
 | 
	
		
			
				|  |  | +using ZhonTai.Common.Files;
 | 
	
		
			
				|  |  | +using ZhonTai.Admin.Core.Helpers;
 | 
	
		
			
				|  |  | +using Microsoft.AspNetCore.Hosting;
 | 
	
		
			
				|  |  | +using System.Data;
 | 
	
		
			
				|  |  | +using ZhonTai.Admin.Domain.ProjectLink;
 | 
	
		
			
				|  |  | +using ZhonTai.Common.Extensions;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +namespace ZhonTai.Admin.Services.ProjectStat
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +    /// <summary>
 | 
	
		
			
				|  |  | +    /// 项目统计服务
 | 
	
		
			
				|  |  | +    /// </summary>
 | 
	
		
			
				|  |  | +    [Order(10)]
 | 
	
		
			
				|  |  | +    [DynamicApi(Area = AdminConsts.AreaName)]
 | 
	
		
			
				|  |  | +    public class ProjectStatService : BaseService, IProjectStatService, IDynamicApi
 | 
	
		
			
				|  |  | +    {
 | 
	
		
			
				|  |  | +        private IProjectStatRepository _projectStatRepository => LazyGetRequiredService<IProjectStatRepository>();
 | 
	
		
			
				|  |  | +        private IProjectRepository _projectRepository => LazyGetRequiredService<IProjectRepository>();
 | 
	
		
			
				|  |  | +        private IProjectPriceRepository _projectPriceRepository => LazyGetRequiredService<IProjectPriceRepository>();
 | 
	
		
			
				|  |  | +        private IOrgRepository _orgRepository => LazyGetRequiredService<IOrgRepository>();
 | 
	
		
			
				|  |  | +        private OSSConfig _oSSConfig => LazyGetRequiredService<IOptions<OSSConfig>>().Value;
 | 
	
		
			
				|  |  | +        private IHttpContextAccessor _httpContextAccessor => LazyGetRequiredService<IHttpContextAccessor>();
 | 
	
		
			
				|  |  | +        private IProjectLinkRepository _projectLinkRepository => LazyGetRequiredService<IProjectLinkRepository>();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        public ProjectStatService()
 | 
	
		
			
				|  |  | +        {
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        /// <summary>
 | 
	
		
			
				|  |  | +        /// 查询统计管理分页
 | 
	
		
			
				|  |  | +        /// </summary>
 | 
	
		
			
				|  |  | +        /// <param name="input"></param>
 | 
	
		
			
				|  |  | +        /// <returns></returns>
 | 
	
		
			
				|  |  | +        [HttpPost]
 | 
	
		
			
				|  |  | +        public async Task<PageOutput<ProjectStatManagePageOutput>> GetManagePageAsync(PageInput<ProjectStatManagePageInput> input)
 | 
	
		
			
				|  |  | +        {
 | 
	
		
			
				|  |  | +            var ProjectId = input.Filter?.ProjectId;
 | 
	
		
			
				|  |  | +            var TenantId = input.Filter?.TenantId;
 | 
	
		
			
				|  |  | +            var IsSettele = input.Filter?.IsSettele;
 | 
	
		
			
				|  |  | +            var EffectDate = input.Filter?.EffectDate;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            var list = _projectStatRepository.Select.DisableGlobalFilter(FilterNames.Tenant)
 | 
	
		
			
				|  |  | +                .WhereIf(ProjectId.HasValue && ProjectId.Value > 0, a => a.ProjectId == ProjectId)
 | 
	
		
			
				|  |  | +                .WhereIf(TenantId.HasValue && TenantId.Value > 0, a => a.TenantId == TenantId)
 | 
	
		
			
				|  |  | +                .WhereIf(IsSettele.HasValue, a => a.IsSettle == IsSettele)
 | 
	
		
			
				|  |  | +                .WhereIf(EffectDate.HasValue, a => a.EffectDate == EffectDate)
 | 
	
		
			
				|  |  | +                .GroupBy(m => new { m.ProjectId, m.TenantId, m.EffectDate })
 | 
	
		
			
				|  |  | +            .Count(out var total)
 | 
	
		
			
				|  |  | +            .Page(input.CurrentPage, input.PageSize)
 | 
	
		
			
				|  |  | +            .ToList(m => new ProjectStatManagePageOutput()
 | 
	
		
			
				|  |  | +            {
 | 
	
		
			
				|  |  | +                ProjectId = m.Key.ProjectId,
 | 
	
		
			
				|  |  | +                TenantId = m.Key.TenantId.Value,
 | 
	
		
			
				|  |  | +                EffectDate = m.Key.EffectDate,
 | 
	
		
			
				|  |  | +                VaildCount = m.Sum(m.Value.ValidCount),
 | 
	
		
			
				|  |  | +                Count = m.Sum(m.Value.ValidCount),
 | 
	
		
			
				|  |  | +                IsSettle = m.Sum(m.Value.IsSettle) > 0 ? 1 : 0,
 | 
	
		
			
				|  |  | +                ProjectName = "",
 | 
	
		
			
				|  |  | +                OrgName = "",
 | 
	
		
			
				|  |  | +                TotalCommission = m.Sum(m.Value.CommissionPrice * m.Value.ValidCount),
 | 
	
		
			
				|  |  | +            });
 | 
	
		
			
				|  |  | +            //项目名称
 | 
	
		
			
				|  |  | +            var listProjectId = list.Select(m => m.ProjectId).Distinct().ToList();
 | 
	
		
			
				|  |  | +            if (listProjectId.Count() > 0)
 | 
	
		
			
				|  |  | +            {
 | 
	
		
			
				|  |  | +                var listProject = await _projectRepository.Select.DisableGlobalFilter(FilterNames.Tenant).Where(m => listProjectId.Contains(m.Id)).ToListAsync(m => new
 | 
	
		
			
				|  |  | +                {
 | 
	
		
			
				|  |  | +                    m.Id,
 | 
	
		
			
				|  |  | +                    m.Name
 | 
	
		
			
				|  |  | +                });
 | 
	
		
			
				|  |  | +                foreach (var item in list)
 | 
	
		
			
				|  |  | +                {
 | 
	
		
			
				|  |  | +                    var project = listProject.FirstOrDefault(m => m.Id == item.ProjectId);
 | 
	
		
			
				|  |  | +                    if (project != null)
 | 
	
		
			
				|  |  | +                        item.ProjectName = project.Name;
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +            //平台
 | 
	
		
			
				|  |  | +            var listTenantId = list.Select(m => m.TenantId).Distinct().ToList();
 | 
	
		
			
				|  |  | +            if (listTenantId.Count() > 0)
 | 
	
		
			
				|  |  | +            {
 | 
	
		
			
				|  |  | +                var listTenant = await _orgRepository.Select.DisableGlobalFilter(FilterNames.Tenant).Where(m => listTenantId.Contains(m.TenantId.Value)).ToListAsync(m => new
 | 
	
		
			
				|  |  | +                {
 | 
	
		
			
				|  |  | +                    m.TenantId,
 | 
	
		
			
				|  |  | +                    m.Name
 | 
	
		
			
				|  |  | +                });
 | 
	
		
			
				|  |  | +                foreach (var item in list)
 | 
	
		
			
				|  |  | +                {
 | 
	
		
			
				|  |  | +                    var model = listTenant.FirstOrDefault(m => m.TenantId == item.TenantId);
 | 
	
		
			
				|  |  | +                    if (model != null)
 | 
	
		
			
				|  |  | +                        item.OrgName = model.Name;
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +            var data = new PageOutput<ProjectStatManagePageOutput>()
 | 
	
		
			
				|  |  | +            {
 | 
	
		
			
				|  |  | +                List = list,
 | 
	
		
			
				|  |  | +                Total = total
 | 
	
		
			
				|  |  | +            };
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            return data;
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        private static object locker = new object();//创建锁
 | 
	
		
			
				|  |  | +        private static List<long> ProjectIds = new List<long>();//项目
 | 
	
		
			
				|  |  | +        /// <summary>
 | 
	
		
			
				|  |  | +        /// 上传统计文件
 | 
	
		
			
				|  |  | +        /// </summary>
 | 
	
		
			
				|  |  | +        /// <param name="file">文件</param>
 | 
	
		
			
				|  |  | +        /// <param name="ProjectId">文件目录</param>      
 | 
	
		
			
				|  |  | +        /// <returns></returns>            
 | 
	
		
			
				|  |  | +        public async Task UploadAsync([Required] IFormFile file, [Required] long ProjectId)
 | 
	
		
			
				|  |  | +        {
 | 
	
		
			
				|  |  | +            try
 | 
	
		
			
				|  |  | +            {
 | 
	
		
			
				|  |  | +                lock (locker)//加锁
 | 
	
		
			
				|  |  | +                {
 | 
	
		
			
				|  |  | +                    if (ProjectIds.Contains(ProjectId))
 | 
	
		
			
				|  |  | +                    {
 | 
	
		
			
				|  |  | +                        throw new Exception("该项目统计数据正在上传,请稍后");
 | 
	
		
			
				|  |  | +                    }
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +                var localUploadConfig = _oSSConfig.LocalUploadConfig;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                var extention = Path.GetExtension(file.FileName).ToLower();
 | 
	
		
			
				|  |  | +                if (extention != ".xlsx")
 | 
	
		
			
				|  |  | +                {
 | 
	
		
			
				|  |  | +                    throw new Exception($"请上传.xlsx格式文件");
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +                var fileLenth = file.Length;
 | 
	
		
			
				|  |  | +                if (fileLenth <= 0)
 | 
	
		
			
				|  |  | +                {
 | 
	
		
			
				|  |  | +                    throw new Exception("文件不能为空");
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +                if (fileLenth > localUploadConfig.MaxSize)
 | 
	
		
			
				|  |  | +                {
 | 
	
		
			
				|  |  | +                    throw new Exception($"文件大小不能超过{new FileSize(localUploadConfig.MaxSize)}");
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +                if (ProjectId <= 0)
 | 
	
		
			
				|  |  | +                {
 | 
	
		
			
				|  |  | +                    throw new Exception($"请输入有效项目Id");
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                string fileDirectory = "stat";
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                string SaveFileName = FreeUtil.NewMongodbId().ToString();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                var filePath = Path.Combine(fileDirectory, SaveFileName + extention).ToPath();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                var uploadHelper = LazyGetRequiredService<UploadHelper>();
 | 
	
		
			
				|  |  | +                var env = LazyGetRequiredService<IWebHostEnvironment>();
 | 
	
		
			
				|  |  | +                fileDirectory = Path.Combine(env.WebRootPath, fileDirectory).ToPath();
 | 
	
		
			
				|  |  | +                if (!Directory.Exists(fileDirectory))
 | 
	
		
			
				|  |  | +                {
 | 
	
		
			
				|  |  | +                    Directory.CreateDirectory(fileDirectory);
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +                filePath = Path.Combine(env.WebRootPath, filePath).ToPath();
 | 
	
		
			
				|  |  | +                await uploadHelper.SaveAsync(file, filePath);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                //导入数据
 | 
	
		
			
				|  |  | +                var datatable = NOPIHelper.ReadExcel(filePath);
 | 
	
		
			
				|  |  | +                if (datatable == null || datatable.Rows.Count <= 0)
 | 
	
		
			
				|  |  | +                {
 | 
	
		
			
				|  |  | +                    throw new Exception($"文件不能为空");
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +                var listPrice = await _projectPriceRepository.Select.DisableGlobalFilter(FilterNames.Tenant).Where(m => m.ProjectId == ProjectId).ToListAsync();
 | 
	
		
			
				|  |  | +                if (listPrice.Count() <= 0)
 | 
	
		
			
				|  |  | +                {
 | 
	
		
			
				|  |  | +                    throw new Exception($"项目不存在");
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +                bool IsComplete = true; //标准是否完整 true完整 false不完整
 | 
	
		
			
				|  |  | +                foreach (var item in listPrice)
 | 
	
		
			
				|  |  | +                {
 | 
	
		
			
				|  |  | +                    if (datatable.Columns[item.Name] == null)
 | 
	
		
			
				|  |  | +                    {
 | 
	
		
			
				|  |  | +                        IsComplete = false;
 | 
	
		
			
				|  |  | +                        break;
 | 
	
		
			
				|  |  | +                    }
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +                if (datatable.Columns["二维码编号"] == null || datatable.Columns["作业日期"] == null|| !IsComplete)
 | 
	
		
			
				|  |  | +                {
 | 
	
		
			
				|  |  | +                    throw new Exception($"导入格式不正确");
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +                List<string> listDate = (from d in datatable.AsEnumerable() select d.Field<string>("作业日期")).ToList();
 | 
	
		
			
				|  |  | +                var listDateInt = listDate.Select(m => int.Parse(m.Replace("-", "")));
 | 
	
		
			
				|  |  | +                //已结算数据是否存在
 | 
	
		
			
				|  |  | +                var count = await _projectStatRepository.Select.DisableGlobalFilter(FilterNames.Tenant).Where(m => m.ProjectId == ProjectId && listDateInt.Contains(m.EffectDateNum) && m.IsSettle == 1).CountAsync();
 | 
	
		
			
				|  |  | +                if (count > 0)
 | 
	
		
			
				|  |  | +                {
 | 
	
		
			
				|  |  | +                    throw new Exception($"请删除作业时间已结算的数据");
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +                //是否有覆盖数据存在
 | 
	
		
			
				|  |  | +                var listFuGai = await _projectStatRepository.Select.DisableGlobalFilter(FilterNames.Tenant).Where(m => m.ProjectId == ProjectId && listDateInt.Contains(m.EffectDateNum) && m.IsSettle == 0).ToListAsync(m=>m.EffectDateNum);
 | 
	
		
			
				|  |  | +                if (listFuGai.Count() > 0)
 | 
	
		
			
				|  |  | +                {
 | 
	
		
			
				|  |  | +                     listFuGai = listFuGai.Distinct().ToList();
 | 
	
		
			
				|  |  | +                     await _projectStatRepository.UpdateDiy.Set(m=>m.IsDeleted,true).Where(m => listFuGai.Contains(m.EffectDateNum)).ExecuteUpdatedAsync();
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +                List<ProjectStatEntity> list = new List<ProjectStatEntity>();
 | 
	
		
			
				|  |  | +                foreach (DataRow row in datatable.Rows)
 | 
	
		
			
				|  |  | +                {
 | 
	
		
			
				|  |  | +                    string num = row["二维码编号"]?.ToString();
 | 
	
		
			
				|  |  | +                    DateTime EffectDate = row["作业日期"].ToDateTime();
 | 
	
		
			
				|  |  | +                    int EffectDateNum = EffectDate.ToString("yyyyMMdd").ToInt();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                    var link = await _projectLinkRepository.Select.DisableGlobalFilter(FilterNames.Tenant).Where(m => m.ProjectId == ProjectId && m.Num==num ).ToOneAsync();                    
 | 
	
		
			
				|  |  | +                    foreach (var price in listPrice)
 | 
	
		
			
				|  |  | +                    {
 | 
	
		
			
				|  |  | +                        var model=new ProjectStatEntity()
 | 
	
		
			
				|  |  | +                        {
 | 
	
		
			
				|  |  | +                            Num = num,
 | 
	
		
			
				|  |  | +                            EffectDate = EffectDate,
 | 
	
		
			
				|  |  | +                            EffectDateNum = EffectDateNum,
 | 
	
		
			
				|  |  | +                            ProjectPriceId = price.Id,
 | 
	
		
			
				|  |  | +                            ProjectId = price.ProjectId,
 | 
	
		
			
				|  |  | +                            ValidCount = row[price.Name].ToInt(),
 | 
	
		
			
				|  |  | +                            Name = price.Name,
 | 
	
		
			
				|  |  | +                            CommissionPrice = 0,
 | 
	
		
			
				|  |  | +                            IsSettle = 0,
 | 
	
		
			
				|  |  | +                            TenantId = link?.TenantId,
 | 
	
		
			
				|  |  | +                        };
 | 
	
		
			
				|  |  | +                        list.Add(model);
 | 
	
		
			
				|  |  | +                    }
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +                await _projectStatRepository.InsertAsync(list);
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +            catch (Exception ex)
 | 
	
		
			
				|  |  | +            {
 | 
	
		
			
				|  |  | +                throw new Exception($"导入项目统计异常");
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +            finally
 | 
	
		
			
				|  |  | +            {
 | 
	
		
			
				|  |  | +                ProjectIds.Remove(ProjectId);
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        /// <summary>
 | 
	
		
			
				|  |  | +        /// 下载项目统计模板
 | 
	
		
			
				|  |  | +        /// </summary>        
 | 
	
		
			
				|  |  | +        /// <returns></returns>        
 | 
	
		
			
				|  |  | +        [HttpGet]
 | 
	
		
			
				|  |  | +        public string DownLinkCodeAsync()
 | 
	
		
			
				|  |  | +        {
 | 
	
		
			
				|  |  | +            string fileDirectory = "stat";
 | 
	
		
			
				|  |  | +            var filePath = Path.Combine(fileDirectory, "statcode.xlsx").ToPath();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            var env = LazyGetRequiredService<IWebHostEnvironment>();
 | 
	
		
			
				|  |  | +            var file = Path.Combine(env.WebRootPath, filePath).ToPath();
 | 
	
		
			
				|  |  | +            if (!System.IO.File.Exists(file))
 | 
	
		
			
				|  |  | +            {
 | 
	
		
			
				|  |  | +                throw new Exception($"项目统计模板文件不存在");
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            var linkUrl = $"{_httpContextAccessor.HttpContext.Request.Scheme}://{_httpContextAccessor.HttpContext.Request.Host.Value}/{filePath}";
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            return linkUrl;
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +}
 |