using System; using System.Collections.Generic; using System.IdentityModel.Tokens.Jwt; using System.Linq; using System.Security.Claims; using System.Text; using FMSAdmin.Data; using FMSAdmin.Helpers; using FMSAdmin.Entities; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using Microsoft.IdentityModel.Tokens; using FMSAdmin.Models; using System.Transactions; namespace FMSApp.Repositories { public class WorkRequestRepository { private readonly ILogger _logger; private readonly FMSContext _context; private readonly AppSettings _appSettings; private readonly StorageHelper _storage; private readonly WorkConfigRepository _workConfigRepository; private readonly HolidayRepository _holidayRepository; public WorkRequestRepository( ILogger logger, FMSContext context, IOptions appSettings, StorageHelper storage, WorkConfigRepository workConfigRepository, HolidayRepository holidayRepository ) { _logger = logger; _context = context; _appSettings = appSettings.Value; _storage = storage; _workConfigRepository = workConfigRepository; _holidayRepository = holidayRepository; } public void CreateFromWorkSchedules() { var today = DateTime.Now.Date; var seekStartDate = today.AddDays(-31); using (var trans = new TransactionScope()) { var query = from schedule in _context.FmsWorkSchedule where schedule.IsUse == true && schedule.WorkDueDate >= seekStartDate && _context.FmsWorkRequest.Where( request => request.SiteId == schedule.SiteId && request.WorkScheduleId == schedule.WorkScheduleId && request.StartWorkDate == schedule.WorkDueDate ).Any() == false select schedule; foreach (var schedule in query) { CreateFromWorkSchedule(schedule); } trans.Complete(); } } public bool IsCreatedRequest(FmsWorkSchedule schedule) { return _context.FmsWorkRequest.Any( x => x.SiteId == schedule.SiteId && x.WorkScheduleId == schedule.WorkScheduleId && x.StartWorkDate == schedule.WorkDueDate ); } public void CreateAllRequestFromWorkSchedule(FmsWorkSchedule schedule, bool bTran = false) { var today = DateTime.Now.Date; TransactionScope trans = null; if (bTran) trans = new TransactionScope(); try { if (schedule.WorkExpireDate == null) throw new ServiceException("작업만료일을 선택하세요."); DateTime startWorkDate = schedule.WorkDueDate; DateTime? endWorkDate = schedule.WorkEndDate; DateTime expireDate = schedule.WorkExpireDate.Value; var weekend = _holidayRepository.GetHolidayWeekend(schedule.SiteId); var holidays = _holidayRepository.GetHolidays(schedule.SiteId); var workrequestFileCategory = _context.CmFileCategory.First(x => x.Name == "workrequest"); var workscheduleFileCategory = _context.CmFileCategory.First(x => x.Name == "workschedule"); if (schedule.CmFile != null && schedule.CmFile.IsUpload) { _logger.LogError("<<<<<<<<<<<<<<<<<< schedule.CmFile IS NOT NULL >>>>>>>>>>>>>>>>"); schedule.CmFile.SiteId = schedule.SiteId; schedule.CmFile.FileCategoryId = workscheduleFileCategory.FileCategoryId; schedule.CmFile.FileCategory = workscheduleFileCategory; schedule.CmFile.CreatedDate = DateTime.Now; } else { schedule.CmFile = null; } schedule.IsNotProcess = true; schedule.IsUse = true; _context.FmsWorkSchedule.Add(schedule); _context.SaveChanges(); while (true) { var request = new FmsWorkRequest(); request.CmFile = schedule.CmFile != null ? (new CmFile() { SiteId = schedule.CmFile.SiteId, FileCategoryId = workrequestFileCategory.FileCategoryId, FileCategory = workrequestFileCategory, Name = schedule.CmFile.Name, FileSize = schedule.CmFile.FileSize, CreatedDate = schedule.CmFile.CreatedDate, ContentType = schedule.CmFile.ContentType, IsUpload = schedule.CmFile.IsUpload, IsDelete = schedule.CmFile.IsDelete, Url = schedule.CmFile.Url, Path = schedule.CmFile.Path }) : null; request.FmsWorkSchedule = schedule; request.SiteId = schedule.SiteId; request.WorkTypeId = schedule.WorkTypeId; request.BusinessFieldId = schedule.BusinessFieldId; request.WorkProgressId = 1; // 작업계획 request.Title = schedule.Name; request.Content = schedule.Content; request.RequestUserId = schedule.UpdateUserId; request.RequestDate = today; request.InspectionAgencyId = schedule.InspectionAgencyId; request.StartWorkDate = startWorkDate; request.WorkEndDate = endWorkDate; request.WorkPartnerId = schedule.WorkPartnerId; request.WorkPrice = schedule.WorkPrice; foreach (var facility in schedule.FmsWorkScheduleToFacility) { request.FmsWorkRequestToFacility.Add(new FmsWorkRequestToFacility() { SiteId = schedule.SiteId, FacilityCode = facility.FacilityCode }); } _context.FmsWorkRequest.Add(request); _context.SaveChanges(); // 자동지시 (일자가 도래해야 자동지시처리.) if (_workConfigRepository.IsAutoOrder(true) || schedule.IsAutoOrder) { if (request.StartWorkDate.Date <= today) { this.WorkToOrder(request.SiteId, request.WorkRequestId, request.RequestUserId, ""); } } if (request.CmFile != null && request.CmFile.IsUpload) { _storage.CopyEntity(request.CmFile.Path, request.CmFile); } startWorkDate = this.GetNextDueDate(schedule, startWorkDate, weekend, holidays); if (!Util.IsNullOrEmpty(endWorkDate)) endWorkDate = this.GetNextDueDate(schedule, endWorkDate.Value, weekend, holidays); if (startWorkDate > expireDate) { break; } } if (schedule.CmFile != null && schedule.CmFile.IsUpload) { _storage.CopyEntity(schedule.CmFile.Path, schedule.CmFile); } if (trans != null) trans.Complete(); } finally { if (trans != null) trans.Dispose(); } } public void CreateFromWorkSchedule(FmsWorkSchedule schedule, bool bTran = false) { if (schedule.IsNotProcess) return; var today = DateTime.Now.Date; TransactionScope trans = null; if (bTran) trans = new TransactionScope(); try { var request = new FmsWorkRequest(); request.SiteId = schedule.SiteId; request.WorkTypeId = schedule.WorkTypeId; request.BusinessFieldId = schedule.BusinessFieldId; request.WorkScheduleId = schedule.WorkScheduleId; request.WorkProgressId = 1; // 작업계획 request.Title = schedule.Name; request.Content = schedule.Content; request.RequestUserId = schedule.UpdateUserId; request.RequestDate = today; request.InspectionAgencyId = schedule.InspectionAgencyId; request.StartWorkDate = schedule.WorkDueDate; request.WorkPartnerName = schedule.WorkPartnerName; request.WorkPrice = schedule.WorkPrice; //request.WorkItem = schedule.WorkItem; foreach (var facility in schedule.FmsWorkScheduleToFacility) { request.FmsWorkRequestToFacility.Add(new FmsWorkRequestToFacility() { SiteId = schedule.SiteId, FacilityCode = facility.FacilityCode }); } _context.FmsWorkRequest.Add(request); _context.SaveChanges(); // 자동지시 (일자가 도래해야 자동지시처리.) if (_workConfigRepository.IsAutoOrder(true) || schedule.IsAutoOrder) { if (request.StartWorkDate.Date <= today) { this.WorkToOrder(request.SiteId, request.WorkRequestId, request.RequestUserId, ""); } } if (trans != null) trans.Complete(); } finally { if (trans != null) trans.Dispose(); } } public void UpdateFromWorkSchedule(FmsWorkSchedule schedule) { // 작업계획(1) : 수정한다. // 작업반려(2) : 수정하지 않는다. // 작업대기(3) : 수정한다. // 작업진행(4) : 수정한다. // 작업완료(5) : 수정시 오류메시지 표시한다. // 작업승인(6) : 수정하지 않는다. // (승인시 차기작업이 생성되었을것이므로, 생성된 작업계획~작업진행 상태의 데이터에 대한 수정이 가해질 것임) // (차기작업을 생성하지 않았을경우 수정할 데이터가 없다.) // 작업보류(7) : 수정한다. var request = _context.FmsWorkRequest.Where( x => x.SiteId == schedule.SiteId && x.WorkScheduleId == schedule.WorkScheduleId && (new int[] { 1, 3, 4, 7 }).Contains(x.WorkProgressId) ).OrderByDescending(x => x.WorkRequestId).FirstOrDefault(); if (request == null) { var completeCount = _context.FmsWorkRequest.Where( x => x.SiteId == schedule.SiteId && x.WorkScheduleId == schedule.WorkScheduleId && x.WorkProgressId == 5 ).Count(); if (completeCount > 0) { throw new ServiceException("작업완료처리된 작업은 계획수정이 불가능합니다. 작업승인 이후에 계획 수정이 가능합니다."); } else { // 계획, 대기, 진행, 완료, 보류 건이 없는상태 // 작업이력관리에서 해당 계획의 작업이 삭제된 경우이다. // 이 경우 기존 계획으로 새로 생성해야한다. CreateFromWorkSchedule(schedule); } return; } // Request 정보 수정 request.Title = schedule.Name; request.StartWorkDate = schedule.WorkDueDate.Date; request.InspectionAgencyId = schedule.InspectionAgencyId; request.Content = schedule.Content; //request.RequestUserId = schedule.UpdateUserId; //request.RequestDate = today; _context.FmsWorkRequest.Update(request); _context.SaveChanges(); request.FmsWorkRequestToFacility.Clear(); _context.SaveChanges(); foreach (var facility in schedule.FmsWorkScheduleToFacility) { _context.FmsWorkRequestToFacility.Add(new FmsWorkRequestToFacility() { SiteId = facility.SiteId, WorkRequestId = request.WorkRequestId, FacilityCode = facility.FacilityCode }); } _context.SaveChanges(); // Order 정보 수정 var order = request.FmsWorkOrder; if (order != null) { order.Title = request.Title; order.StartWorkDate = request.StartWorkDate; order.Content = request.Content; _context.FmsWorkOrder.Update(order); _context.SaveChanges(); order.FmsWorkOrderToFacility.Clear(); _context.SaveChanges(); foreach (var facility in schedule.FmsWorkScheduleToFacility) { _context.FmsWorkOrderToFacility.Add(new FmsWorkOrderToFacility() { SiteId = facility.SiteId, WorkRequestId = request.WorkRequestId, FacilityCode = facility.FacilityCode }); } _context.SaveChanges(); } // Result 정보 수정 var result = request.FmsWorkResult; if (result != null) { result.StartDate = request.StartWorkDate; result.EndDate = request.StartWorkDate; result.Content = request.Content; _context.FmsWorkOrder.Update(order); _context.SaveChanges(); result.FmsWorkResultToFacility.Clear(); _context.SaveChanges(); foreach (var facility in schedule.FmsWorkScheduleToFacility) { _context.FmsWorkResultToFacility.Add(new FmsWorkResultToFacility() { SiteId = facility.SiteId, WorkRequestId = request.WorkRequestId, FacilityCode = facility.FacilityCode }); } _context.SaveChanges(); } } // 자동지시 public void WorkToOrders() { _logger.LogInformation($"============================================================================================="); _logger.LogInformation($"작업시작일이 지나거나 당일인 실행계획 데이터를 작업지시 처리 (처리일 : {DateTime.Now})"); int processCount = 0; if (_workConfigRepository.IsAutoOrder(true)) { _logger.LogInformation($"자동지시 전역설정 TRUE"); // 전역설정이 자동지시로 되어있을때는 모든 실행계획 자동지시(정기,법정,교육,수시,공사) var query = from request in _context.FmsWorkRequest where request.StartWorkDate < DateTime.Now.AddDays(1).Date && request.WorkProgressId == 1 && _context.FmsWorkOrder.Where(x => x.SiteId == request.SiteId && x.WorkRequestId == request.WorkRequestId && x.Title == request.Title).Any() == false select request; foreach (var request in query.ToList()) { WorkToOrder(request.SiteId, request.WorkRequestId, request.RequestUserId, "", true); processCount++; } } else { _logger.LogInformation($"자동지시 전역설정 FALSE"); // 전역설정이 자동지시로 되어있지 않을때는 정기점검,법정검사,법정교육 (FmsWorkSchedule 등록되어있는 실행계획) 만 자동지시 // 기초계획에 자동지시여부가 true 인것만 자동지시 var query = from schedule in _context.FmsWorkSchedule join request in _context.FmsWorkRequest on schedule.WorkScheduleId equals request.WorkScheduleId where schedule.IsUse == true && request.WorkProgressId == 1 && schedule.IsAutoOrder == true && (request.StartWorkDate < DateTime.Now.AddDays(1).Date) && _context.FmsWorkOrder.Where(x => x.SiteId == request.SiteId && x.WorkRequestId == request.WorkRequestId && x.Title == request.Title).Any() == false select request; foreach (var request in query.ToList()) { WorkToOrder(request.SiteId, request.WorkRequestId, request.RequestUserId, "", true); processCount++; } } _logger.LogInformation($"처리완료 : {processCount}건"); _logger.LogInformation($"============================================================================================="); } // 자동수행 public void WorkToResults() { _logger.LogInformation($"============================================================================================="); _logger.LogInformation($"작업수행 처리되지 않은 작업대기 목록 자동수행 (처리일시 : {DateTime.Now})"); int processCount = 0; if (_workConfigRepository.IsAutoResult(true)) { _logger.LogInformation($"자동수행 전역설정 TRUE"); var query = from order in _context.FmsWorkOrder join request in _context.FmsWorkRequest on order.WorkRequestId equals request.WorkRequestId where request.WorkProgressId == 3 && _context.FmsWorkResult.Where(x => x.SiteId == order.SiteId && x.WorkRequestId == order.WorkRequestId).Any() == false select order; foreach (var order in query.ToList()) { WorkToResult(order, new FmsWorkResult { StartDate = order.StartWorkDate.Date, EndDate = order.StartWorkDate.Date, Content = "", WorkerUserId = order.OrderUserId, }, true); processCount++; } } else { _logger.LogInformation($"자동수행 전역설정 FALSE => 자동수행 안함."); } _logger.LogInformation($"처리완료 : {processCount}건"); _logger.LogInformation($"============================================================================================="); } public void WorkToOrder(int siteId, int workRequestId, string orderUserId, string orderContent, bool bTran = false) { TransactionScope trans = null; if (bTran) trans = new TransactionScope(); try { var persist = _context.FmsWorkRequest.FirstOrDefault( x => x.SiteId == siteId && x.WorkRequestId == workRequestId ); if (persist == null) throw new ServiceException("존재하지 않는 데이터 입니다."); if (persist.WorkProgressId == 2) { throw new ServiceException("반려된 작업은 작업지시 처리할 수 없습니다."); } if (persist.WorkProgressId != 1) { throw new ServiceException("이미 작업지시 처리된 데이터입니다."); } // WorkRequest.WorkProgressId = 3 persist.WorkProgressId = 3; _context.FmsWorkRequest.Update(persist); _context.SaveChanges(); // WorkOrder 생성 var order = new FmsWorkOrder(); order.SiteId = persist.SiteId; order.WorkRequestId = persist.WorkRequestId; order.BusinessFieldId = persist.BusinessFieldId; order.Title = persist.Title; order.StartWorkDate = persist.StartWorkDate; order.OrderUserId = orderUserId; order.OrderDate = DateTime.Now; order.Content = orderContent; _context.FmsWorkOrder.Add(order); _context.SaveChanges(); // 기존 WorkOrderToFacility 삭제 var facilities = _context.FmsWorkOrderToFacility.Where( x => x.SiteId == persist.SiteId && x.WorkRequestId == persist.WorkRequestId ); _context.FmsWorkOrderToFacility.RemoveRange(facilities); _context.SaveChanges(); // 신규 WorkOrderToFacility 생성 From FmsWorkRequestToFacility foreach (var facility in persist.FmsWorkRequestToFacility.ToList()) { _context.FmsWorkOrderToFacility.Add(new FmsWorkOrderToFacility() { SiteId = facility.SiteId, WorkRequestId = facility.WorkRequestId, FacilityCode = facility.FacilityCode, }); } _context.SaveChanges(); // 자동진행 if (_workConfigRepository.IsAutoResult(true)) { this.WorkToResult(order, new FmsWorkResult() { StartDate = order.StartWorkDate.Date, EndDate = order.StartWorkDate.Date, Content = "", WorkerUserId = order.OrderUserId, }); } if (trans != null) trans.Complete(); } catch (Exception ex) { _logger.LogError(ex, ""); throw ex; } finally { if (trans != null) trans.Dispose(); } } public void WorkToResult(FmsWorkOrder order, FmsWorkResult data, bool bTran = false) { TransactionScope trans = null; if (bTran) trans = new TransactionScope(); try { if (order.FmsWorkRequest.WorkProgressId != 3) { throw new ServiceException("작업 대기상태의 데이터만 작업진행 가능합니다."); } // WorkRequest 의 ProgressId 변경 order.FmsWorkRequest.WorkProgressId = 4; _context.FmsWorkRequest.Update(order.FmsWorkRequest); _context.SaveChanges(); // WorkOrder 의 StartWorkDate 변경 order.StartWorkDate = data.StartDate.Date; _context.FmsWorkOrder.Update(order); _context.SaveChanges(); // WorkResult 생성 var result = new FmsWorkResult() { SiteId = order.SiteId, WorkRequestId = order.WorkRequestId, StartDate = data.StartDate.Date, EndDate = data.EndDate.Date, Content = data.Content, IsConfirmed = false, WorkerUserId = data.WorkerUserId, }; _context.FmsWorkResult.Add(result); _context.SaveChanges(); // 기존 FmsWorkResultToFacility 삭제 var facilities = _context.FmsWorkResultToFacility.Where( x => x.SiteId == order.SiteId && x.WorkRequestId == order.WorkRequestId ); _context.FmsWorkResultToFacility.RemoveRange(facilities); _context.SaveChanges(); // 신규 FmsWorkResultToFacility 생성 From FmsWorkOrderToFacility foreach (var facility in order.FmsWorkOrderToFacility.ToList()) { _context.FmsWorkResultToFacility.Add(new FmsWorkResultToFacility() { SiteId = facility.SiteId, WorkRequestId = facility.WorkRequestId, FacilityCode = facility.FacilityCode, }); } _context.SaveChanges(); if (trans != null) trans.Complete(); } catch (Exception ex) { _logger.LogError(ex, ""); throw ex; } finally { if (trans != null) trans.Dispose(); } } public void WorkToResult(int siteId, int workRequestId, FmsWorkResult data, bool bTran = false) { TransactionScope trans = null; if (bTran) trans = new TransactionScope(); try { var persist = _context.FmsWorkOrder.FirstOrDefault( x => x.SiteId == siteId && x.WorkRequestId == workRequestId ); if (persist == null) throw new ServiceException("존재하지 않는 데이터 입니다."); this.WorkToResult(persist, data); if (trans != null) trans.Complete(); } finally { if (trans != null) trans.Dispose(); } } public DateTime GetNextDueDate(FmsWorkSchedule schedule, DateTime date, CmHolidayWeekend weekend, IList holidays) { DateTime WorkDueDate = date; DateTime EndDate = date; switch (schedule.CycleUnitId) { case 1: WorkDueDate = EndDate.AddDays(schedule.CycleSize); break; case 2: WorkDueDate = EndDate.AddDays(schedule.CycleSize * 7); break; case 3: WorkDueDate = EndDate.AddMonths(schedule.CycleSize); break; case 4: WorkDueDate = EndDate.AddMonths(schedule.CycleSize * 3); break; case 5: WorkDueDate = EndDate.AddMonths(schedule.CycleSize * 6); break; case 6: WorkDueDate = EndDate.AddYears(schedule.CycleSize); break; } if (schedule.HolidayWorkTypeId == 0) return WorkDueDate; bool isHoliday = _holidayRepository.IsHoliday(WorkDueDate, weekend, holidays); if (schedule.HolidayWorkTypeId == 1) { while (!isHoliday) { WorkDueDate = WorkDueDate.AddDays(1); isHoliday = _holidayRepository.IsHoliday(WorkDueDate, weekend, holidays); } return WorkDueDate; } if (schedule.HolidayWorkTypeId == 2) { while (isHoliday) { WorkDueDate = WorkDueDate.AddDays(1); isHoliday = _holidayRepository.IsHoliday(WorkDueDate, weekend, holidays); } return WorkDueDate; } return WorkDueDate; } } }