|
@@ -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;
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|