diff --git a/BMA.EHR.Application/Repositories/Commands/CommandReportRepository.cs b/BMA.EHR.Application/Repositories/Commands/CommandReportRepository.cs index 4a8cf792..b67be682 100644 --- a/BMA.EHR.Application/Repositories/Commands/CommandReportRepository.cs +++ b/BMA.EHR.Application/Repositories/Commands/CommandReportRepository.cs @@ -620,7 +620,7 @@ namespace BMA.EHR.Application.Repositories.Commands PositionNumber = pf.PosNo == null ? "" : pf.PosNo.Name.ToThaiNumber(), Salary = r.Amount == null ? "" : r.Amount.Value.ToNumericNoDecimalText().ToThaiNumber(), //Salary = pf.Salaries == null || pf.Salaries.Count == 0 ? "" : pf.Salaries.OrderByDescending(x => x.Order).FirstOrDefault().Amount.Value.ToNumericNoDecimalText().ToThaiNumber(), - ActiveDate = "", + ActiveDate = p.Date == null ? "" : p.Date.Value.ToThaiShortDate2().ToThaiNumber(), ReceiveOrganizationName = r.Command!.ReceiveOrganizationName }) .ToList(); @@ -706,6 +706,7 @@ namespace BMA.EHR.Application.Repositories.Commands Organization = p.Organization, StartDate = p.DateStart == null ? "" : p.DateStart.Value.ToThaiShortDate2().ToThaiNumber(), EndDate = p.DateEnd == null ? "" : p.DateEnd.Value.ToThaiShortDate2().ToThaiNumber(), + Reason = p.Reason == null ? "" : p.Reason.ToThaiNumber() }) .ToList(); @@ -801,11 +802,11 @@ namespace BMA.EHR.Application.Repositories.Commands PositionNumber = p.PositionNumberOld.ToThaiNumber(), Salary = r.Amount == null ? "" : r.Amount.Value.ToNumericNoDecimalText().ToThaiNumber(), //Salary = p.Profile.Salaries == null || p.Profile.Salaries.Count == 0 ? "" : p.Profile.Salaries.OrderByDescending(x => x.Order).FirstOrDefault().Amount.Value.ToNumericNoDecimalText().ToThaiNumber(), - Fault = r.Command.Fault, - GuiltyBasis = r.Command.GuiltyBasis, + Fault = r.Command.Fault.ToThaiNumber(), + GuiltyBasis = r.Command.GuiltyBasis.ToThaiNumber(), ConclusionFireNo = r.Command!.ConclusionFireNo.ToThaiNumber(), ConclusionFireDate = r.Command.ConclusionFireDate == null ? "" : r.Command.ConclusionFireDate.Value.ToThaiFullDate3().ToThaiNumber(), - ConclusionFireResolution = r.Command.ConclusionFireResolution + ConclusionFireResolution = r.Command.ConclusionFireResolution.ToThaiNumber() }) .ToList(); @@ -855,11 +856,11 @@ namespace BMA.EHR.Application.Repositories.Commands PositionNumber = p.PositionNumberOld.ToThaiNumber(), Salary = r.Amount == null ? "" : r.Amount.Value.ToNumericNoDecimalText().ToThaiNumber(), //Salary = p.Profile.Salaries == null || p.Profile.Salaries.Count == 0 ? "" : p.Profile.Salaries.OrderByDescending(x => x.Order).FirstOrDefault().Amount.Value.ToNumericNoDecimalText().ToThaiNumber(), - Fault = r.Command.Fault, - GuiltyBasis = r.Command.GuiltyBasis, + Fault = r.Command.Fault.ToThaiNumber(), + GuiltyBasis = r.Command.GuiltyBasis.ToThaiNumber(), ConclusionFireNo = r.Command!.ConclusionFireNo.ToThaiNumber(), ConclusionFireDate = r.Command.ConclusionFireDate == null ? "" : r.Command.ConclusionFireDate.Value.ToThaiFullDate3().ToThaiNumber(), - ConclusionFireResolution = r.Command.ConclusionFireResolution + ConclusionFireResolution = r.Command.ConclusionFireResolution.ToThaiNumber() }) .ToList(); @@ -908,11 +909,11 @@ namespace BMA.EHR.Application.Repositories.Commands PositionNumber = p.PositionNumberOld.ToThaiNumber(), Salary = r.Amount == null ? "" : r.Amount.Value.ToNumericNoDecimalText().ToThaiNumber(), //Salary = p.Profile.Salaries == null || p.Profile.Salaries.Count == 0 ? "" : p.Profile.Salaries.OrderByDescending(x => x.Order).FirstOrDefault().Amount.Value.ToNumericNoDecimalText().ToThaiNumber(), - Fault = r.Command.Fault, - GuiltyBasis = r.Command.GuiltyBasis, + Fault = r.Command.Fault.ToThaiNumber(), + GuiltyBasis = r.Command.GuiltyBasis.ToThaiNumber(), ConclusionFireNo = r.Command!.ConclusionFireNo.ToThaiNumber(), ConclusionFireDate = r.Command.ConclusionFireDate == null ? "" : r.Command.ConclusionFireDate.Value.ToThaiFullDate3().ToThaiNumber(), - ConclusionFireResolution = r.Command.ConclusionFireResolution + ConclusionFireResolution = r.Command.ConclusionFireResolution.ToThaiNumber() }) .ToList(); diff --git a/BMA.EHR.Application/Repositories/Commands/CommandRepository.cs b/BMA.EHR.Application/Repositories/Commands/CommandRepository.cs index f440f37e..c583cb3d 100644 --- a/BMA.EHR.Application/Repositories/Commands/CommandRepository.cs +++ b/BMA.EHR.Application/Repositories/Commands/CommandRepository.cs @@ -16,7 +16,9 @@ using Microsoft.AspNetCore.Http; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Configuration; using Newtonsoft.Json; +using System.Linq; using System.Net.Http.Headers; +using System.Text; using Command = BMA.EHR.Domain.Models.Commands.Core.Command; using Profile = BMA.EHR.Domain.Models.HR.Profile; @@ -6033,6 +6035,23 @@ namespace BMA.EHR.Application.Repositories.Commands var seq = 1; foreach (var item in ap) { + + PlacementSalaryResponse salary = new(); + // ให้ Update Salary เฉพาะของ Command 01-04 + switch (command.CommandType.CommandCode.ToUpper()) + { + case "C-PM-01": + case "C-PM-02": + case "C-PM-03": + case "c-PM-04": + salary = await GetPlacementSalaryAsync(item.RefPlacementProfileId.Value); + break; + default: + salary = await GetCommandReceiverSalary(item.RefPlacementProfileId.Value); + break; + } + + var receiver = new CommandReceiver { Sequence = seq, @@ -6040,7 +6059,10 @@ namespace BMA.EHR.Application.Repositories.Commands Prefix = item.Prefix, FirstName = item.FirstName!, LastName = item.LastName!, - RefPlacementProfileId = item.RefPlacementProfileId + RefPlacementProfileId = item.RefPlacementProfileId, + Amount = salary == null ? 0 : salary.SalaryAmount, + MouthSalaryAmount = salary == null ? 0 : salary.MonthSalaryAmount, + PositionSalaryAmount = salary == null ? 0 : salary.PositionSalaryAmount }; seq++; @@ -6217,6 +6239,80 @@ namespace BMA.EHR.Application.Repositories.Commands #endregion + public async Task GetReceiverPositionByCommandIdAsync(Guid id) + { + try + { + var ret = string.Empty; + + var data = await (from r in _dbContext.Set() + .Include(x => x.Command) + join pf in _dbContext.Set() + .Include(x => x.PositionPath) + on r.RefPlacementProfileId equals pf.Id + where r.Command.Id == id + select new + { + r.RefPlacementProfileId, + Position = pf.PositionPath!.Name + }).ToListAsync(); + + if (data.Count > 0) + { + foreach (var d in data) + { + if (!ret.Contains($"{d.Position},")) + ret += $"{d.Position},"; + } + + ret = ret.Substring(0, ret.Length - 1); + } + + return ret; + } + catch + { + throw; + } + } + + public async Task GetReceiverPosition2ByCommandIdAsync(Guid id) + { + try + { + var ret = string.Empty; + + var data = await (from r in _dbContext.Set() + .Include(x => x.Command) + join pf in _dbContext.Set() + .Include(x => x.PositionPath) + on r.RefPlacementProfileId equals pf.Id + where r.Command.Id == id + select new + { + r.RefPlacementProfileId, + Position = pf.PositionPath!.Name + }).ToListAsync(); + + if (data.Count > 0) + { + foreach (var d in data) + { + if (!ret.Contains($"{d.Position},")) + ret += $"{d.Position},"; + } + + ret = ret.Substring(0, ret.Length - 1); + } + + return ret; + } + catch + { + throw; + } + } + public async Task> GetDeploymentByCommandIdAsync(Guid id) { try @@ -6550,12 +6646,12 @@ namespace BMA.EHR.Application.Repositories.Commands if (profile != null && profile.Salaries.Count() > 0) { - SalaryAmount = cmdReceiver.Amount == null ? profile.Salaries == null ? 0 : - profile.Salaries.OrderByDescending(x => x.Order).FirstOrDefault().Amount != null ? profile.Salaries.OrderByDescending(x => x.Order).FirstOrDefault().Amount.Value : 0 : 0; + SalaryAmount = cmdReceiver.Amount == null ? profile.Salaries == null ? 0 : + profile.Salaries.OrderByDescending(x => x.Order).FirstOrDefault().Amount != null ? profile.Salaries.OrderByDescending(x => x.Order).FirstOrDefault().Amount.Value : 0 : 0; PositionSalaryAmount = cmdReceiver.PositionSalaryAmount == null ? profile.Salaries == null ? 0 : - profile.Salaries.OrderByDescending(x => x.Order).FirstOrDefault().PositionSalaryAmount != null ? profile.Salaries.OrderByDescending(x => x.Order).FirstOrDefault().PositionSalaryAmount.Value : 0 : 0; + profile.Salaries.OrderByDescending(x => x.Order).FirstOrDefault().PositionSalaryAmount != null ? profile.Salaries.OrderByDescending(x => x.Order).FirstOrDefault().PositionSalaryAmount.Value : 0 : 0; MonthSalaryAmount = cmdReceiver.MouthSalaryAmount == null ? profile.Salaries == null ? 0 : - profile.Salaries.OrderByDescending(x => x.Order).FirstOrDefault().MouthSalaryAmount != null ?profile.Salaries.OrderByDescending(x => x.Order).FirstOrDefault().MouthSalaryAmount.Value : 0 : 0; + profile.Salaries.OrderByDescending(x => x.Order).FirstOrDefault().MouthSalaryAmount != null ? profile.Salaries.OrderByDescending(x => x.Order).FirstOrDefault().MouthSalaryAmount.Value : 0 : 0; } return new PlacementSalaryResponse diff --git a/BMA.EHR.Application/Responses/Reports/CommandType15Response.cs b/BMA.EHR.Application/Responses/Reports/CommandType15Response.cs index 352014a1..702b7113 100644 --- a/BMA.EHR.Application/Responses/Reports/CommandType15Response.cs +++ b/BMA.EHR.Application/Responses/Reports/CommandType15Response.cs @@ -15,5 +15,7 @@ public string StartDate { get; set; } = string.Empty; public string EndDate { get; set; } = string.Empty; + + public string Reason { get; set; } = string.Empty; } } diff --git a/BMA.EHR.Report.Service/Controllers/CommandReportController.cs b/BMA.EHR.Report.Service/Controllers/CommandReportController.cs index b1488588..3ece403e 100644 --- a/BMA.EHR.Report.Service/Controllers/CommandReportController.cs +++ b/BMA.EHR.Report.Service/Controllers/CommandReportController.cs @@ -62,7 +62,7 @@ namespace BMA.EHR.Report.Service.Controllers } //var recvId = raw_data.Receivers.Select(x => x.RefPlacementProfileId).ToList(); - //var positionList = string.Empty; + var positionList = await _repository.GetReceiverPositionByCommandIdAsync(commandId); var command = new { @@ -73,7 +73,7 @@ namespace BMA.EHR.Report.Service.Controllers ConclusionRegisterDate = raw_data.ConclusionRegisterDate == null ? "" : raw_data.ConclusionRegisterDate.Value.ToThaiFullDate3().ToThaiNumber(), ConclusionResultNo = raw_data.ConclusionResultNo.ToThaiNumber(), ConclusionResultDate = raw_data.ConclusionResultDate == null ? "" : raw_data.ConclusionResultDate.Value.ToThaiFullDate3().ToThaiNumber(), - PositionList = "", + PositionList = positionList, Count = raw_data.Receivers.Count.ToString().ToThaiNumber(), CommandAffectDate = raw_data.CommandAffectDate == null ? "" : raw_data.CommandAffectDate.Value.ToThaiFullDate3().ToThaiNumber(), AuthorizedUserFullName = raw_data.AuthorizedUserFullName, @@ -180,7 +180,7 @@ namespace BMA.EHR.Report.Service.Controllers } //var recvId = raw_data.Receivers.Select(x => x.RefPlacementProfileId).ToList(); - //var positionList = string.Empty; + var positionList = await _repository.GetReceiverPositionByCommandIdAsync(commandId); var command = new { @@ -191,7 +191,7 @@ namespace BMA.EHR.Report.Service.Controllers ConclusionRegisterDate = raw_data.ConclusionRegisterDate == null ? "" : raw_data.ConclusionRegisterDate.Value.ToThaiFullDate3().ToThaiNumber(), ConclusionResultNo = raw_data.ConclusionResultNo.ToThaiNumber(), ConclusionResultDate = raw_data.ConclusionResultDate == null ? "" : raw_data.ConclusionResultDate.Value.ToThaiFullDate3().ToThaiNumber(), - PositionList = "", + PositionList = positionList, Count = raw_data.Receivers.Count.ToString().ToThaiNumber(), CommandAffectDate = raw_data.CommandAffectDate == null ? "" : raw_data.CommandAffectDate.Value.ToThaiFullDate3().ToThaiNumber(), AuthorizedUserFullName = raw_data.AuthorizedUserFullName, @@ -298,7 +298,7 @@ namespace BMA.EHR.Report.Service.Controllers } //var recvId = raw_data.Receivers.Select(x => x.RefPlacementProfileId).ToList(); - //var positionList = string.Empty; + var positionList = await _repository.GetReceiverPositionByCommandIdAsync(commandId); var command = new { @@ -309,7 +309,7 @@ namespace BMA.EHR.Report.Service.Controllers ConclusionRegisterDate = raw_data.ConclusionRegisterDate == null ? "" : raw_data.ConclusionRegisterDate.Value.ToThaiFullDate3().ToThaiNumber(), ConclusionResultNo = raw_data.ConclusionResultNo.ToThaiNumber(), ConclusionResultDate = raw_data.ConclusionResultDate == null ? "" : raw_data.ConclusionResultDate.Value.ToThaiFullDate3().ToThaiNumber(), - PositionList = "", + PositionList = positionList, Count = raw_data.Receivers.Count.ToString().ToThaiNumber(), CommandAffectDate = raw_data.CommandAffectDate == null ? "" : raw_data.CommandAffectDate.Value.ToThaiFullDate3().ToThaiNumber(), AuthorizedUserFullName = raw_data.AuthorizedUserFullName, @@ -416,7 +416,7 @@ namespace BMA.EHR.Report.Service.Controllers } //var recvId = raw_data.Receivers.Select(x => x.RefPlacementProfileId).ToList(); - //var positionList = string.Empty; + var positionList = await _repository.GetReceiverPositionByCommandIdAsync(commandId); var command = new { @@ -427,7 +427,7 @@ namespace BMA.EHR.Report.Service.Controllers ConclusionRegisterDate = raw_data.ConclusionRegisterDate == null ? "" : raw_data.ConclusionRegisterDate.Value.ToThaiFullDate3().ToThaiNumber(), ConclusionResultNo = raw_data.ConclusionResultNo.ToThaiNumber(), ConclusionResultDate = raw_data.ConclusionResultDate == null ? "" : raw_data.ConclusionResultDate.Value.ToThaiFullDate3().ToThaiNumber(), - PositionList = "", + PositionList = positionList, Count = raw_data.Receivers.Count.ToString().ToThaiNumber(), CommandAffectDate = raw_data.CommandAffectDate == null ? "" : raw_data.CommandAffectDate.Value.ToThaiFullDate3().ToThaiNumber(), AuthorizedUserFullName = raw_data.AuthorizedUserFullName, @@ -533,7 +533,7 @@ namespace BMA.EHR.Report.Service.Controllers } //var recvId = raw_data.Receivers.Select(x => x.RefPlacementProfileId).ToList(); - //var positionList = string.Empty; + var positionList = await _repository.GetReceiverPosition2ByCommandIdAsync(commandId); var command = new { @@ -544,7 +544,7 @@ namespace BMA.EHR.Report.Service.Controllers ConclusionRegisterDate = raw_data.ConclusionRegisterDate == null ? "" : raw_data.ConclusionRegisterDate.Value.ToThaiFullDate3().ToThaiNumber(), ConclusionResultNo = raw_data.ConclusionResultNo.ToThaiNumber(), ConclusionResultDate = raw_data.ConclusionResultDate == null ? "" : raw_data.ConclusionResultDate.Value.ToThaiFullDate3().ToThaiNumber(), - PositionList = "", + PositionList = positionList, Count = raw_data.Receivers.Count.ToString().ToThaiNumber(), CommandAffectDate = raw_data.CommandAffectDate == null ? "" : raw_data.CommandAffectDate.Value.ToThaiFullDate3().ToThaiNumber(), AuthorizedUserFullName = raw_data.AuthorizedUserFullName, @@ -651,7 +651,7 @@ namespace BMA.EHR.Report.Service.Controllers } //var recvId = raw_data.Receivers.Select(x => x.RefPlacementProfileId).ToList(); - //var positionList = string.Empty; + var positionList = await _repository.GetReceiverPosition2ByCommandIdAsync(commandId); var command = new { @@ -662,11 +662,13 @@ namespace BMA.EHR.Report.Service.Controllers ConclusionRegisterDate = raw_data.ConclusionRegisterDate == null ? "" : raw_data.ConclusionRegisterDate.Value.ToThaiFullDate3().ToThaiNumber(), ConclusionResultNo = raw_data.ConclusionResultNo.ToThaiNumber(), ConclusionResultDate = raw_data.ConclusionResultDate == null ? "" : raw_data.ConclusionResultDate.Value.ToThaiFullDate3().ToThaiNumber(), - PositionList = "", + PositionList = positionList, Count = raw_data.Receivers.Count.ToString().ToThaiNumber(), CommandAffectDate = raw_data.CommandAffectDate == null ? "" : raw_data.CommandAffectDate.Value.ToThaiFullDate3().ToThaiNumber(), AuthorizedUserFullName = raw_data.AuthorizedUserFullName, AuthorizedPosition = raw_data.AuthorizedPosition, + ConclusionMeetingNo = raw_data.ConclusionMeetingNo.ToThaiNumber(), + ConclusionMeetingDate = raw_data.ConclusionMeetingDate == null ? "" : raw_data.ConclusionMeetingDate.Value.ToThaiFullDate3().ToThaiNumber() }; var rptFile = Path.Combine(_hostingEnvironment.ContentRootPath, "Reports", $"05-06-คำสั่งแต่งตั้ง-คำสั่งเลื่อน.trdp"); @@ -769,7 +771,7 @@ namespace BMA.EHR.Report.Service.Controllers } //var recvId = raw_data.Receivers.Select(x => x.RefPlacementProfileId).ToList(); - //var positionList = string.Empty; + var positionList = await _repository.GetReceiverPosition2ByCommandIdAsync(commandId); var command = new { @@ -780,7 +782,7 @@ namespace BMA.EHR.Report.Service.Controllers ConclusionRegisterDate = raw_data.ConclusionRegisterDate == null ? "" : raw_data.ConclusionRegisterDate.Value.ToThaiFullDate3().ToThaiNumber(), ConclusionResultNo = raw_data.ConclusionResultNo.ToThaiNumber(), ConclusionResultDate = raw_data.ConclusionResultDate == null ? "" : raw_data.ConclusionResultDate.Value.ToThaiFullDate3().ToThaiNumber(), - PositionList = "", + PositionList = positionList, Count = raw_data.Receivers.Count.ToString().ToThaiNumber(), CommandAffectDate = raw_data.CommandAffectDate == null ? "" : raw_data.CommandAffectDate.Value.ToThaiFullDate3().ToThaiNumber(), AuthorizedUserFullName = raw_data.AuthorizedUserFullName, diff --git a/BMA.EHR.Report.Service/Reports/08-คำสั่งบรรจุและแต่งตั้งข้าราชการฯกลับเข้ารับราชการ-5.trdp b/BMA.EHR.Report.Service/Reports/08-คำสั่งบรรจุและแต่งตั้งข้าราชการฯกลับเข้ารับราชการ-5.trdp index c9fe2deb..902f253a 100644 Binary files a/BMA.EHR.Report.Service/Reports/08-คำสั่งบรรจุและแต่งตั้งข้าราชการฯกลับเข้ารับราชการ-5.trdp and b/BMA.EHR.Report.Service/Reports/08-คำสั่งบรรจุและแต่งตั้งข้าราชการฯกลับเข้ารับราชการ-5.trdp differ diff --git a/BMA.EHR.Report.Service/Reports/09-คำสั่งบรรจุและแต่งตั้งผู้ออกไปรับราชการทหารกลับเข้ารับราชการ-7.trdp b/BMA.EHR.Report.Service/Reports/09-คำสั่งบรรจุและแต่งตั้งผู้ออกไปรับราชการทหารกลับเข้ารับราชการ-7.trdp index 09f65185..bb3519ff 100644 Binary files a/BMA.EHR.Report.Service/Reports/09-คำสั่งบรรจุและแต่งตั้งผู้ออกไปรับราชการทหารกลับเข้ารับราชการ-7.trdp and b/BMA.EHR.Report.Service/Reports/09-คำสั่งบรรจุและแต่งตั้งผู้ออกไปรับราชการทหารกลับเข้ารับราชการ-7.trdp differ diff --git a/BMA.EHR.Report.Service/Reports/28-คำสั่งรับโอนข้าราชการกรุงเทพมหานครสามัญ-5.trdp b/BMA.EHR.Report.Service/Reports/28-คำสั่งรับโอนข้าราชการกรุงเทพมหานครสามัญ-5.trdp index 2930bd50..29281b9f 100644 Binary files a/BMA.EHR.Report.Service/Reports/28-คำสั่งรับโอนข้าราชการกรุงเทพมหานครสามัญ-5.trdp and b/BMA.EHR.Report.Service/Reports/28-คำสั่งรับโอนข้าราชการกรุงเทพมหานครสามัญ-5.trdp differ diff --git a/BMA.EHR.Report.Service/Reports/29-คำสั่งให้ช่วยราชการ-2.trdp b/BMA.EHR.Report.Service/Reports/29-คำสั่งให้ช่วยราชการ-2.trdp index fc55d13e..baefe7c6 100644 Binary files a/BMA.EHR.Report.Service/Reports/29-คำสั่งให้ช่วยราชการ-2.trdp and b/BMA.EHR.Report.Service/Reports/29-คำสั่งให้ช่วยราชการ-2.trdp differ diff --git a/BMA.EHR.Report.Service/Reports/37-คำสั่งปลดออกจากราชการ.trdp b/BMA.EHR.Report.Service/Reports/37-คำสั่งปลดออกจากราชการ.trdp index 18eb8427..bca96026 100644 Binary files a/BMA.EHR.Report.Service/Reports/37-คำสั่งปลดออกจากราชการ.trdp and b/BMA.EHR.Report.Service/Reports/37-คำสั่งปลดออกจากราชการ.trdp differ diff --git a/BMA.EHR.Report.Service/Reports/37-คำสั่งให้ออกจากราชการ.trdp b/BMA.EHR.Report.Service/Reports/37-คำสั่งให้ออกจากราชการ.trdp index ba337f53..bb8c9a1c 100644 Binary files a/BMA.EHR.Report.Service/Reports/37-คำสั่งให้ออกจากราชการ.trdp and b/BMA.EHR.Report.Service/Reports/37-คำสั่งให้ออกจากราชการ.trdp differ diff --git a/BMA.EHR.Report.Service/Reports/38-คำสั่งลงโทษไล่ข้าราชการออกจากราชการ.trdp b/BMA.EHR.Report.Service/Reports/38-คำสั่งลงโทษไล่ข้าราชการออกจากราชการ.trdp index e779ff45..2563ee69 100644 Binary files a/BMA.EHR.Report.Service/Reports/38-คำสั่งลงโทษไล่ข้าราชการออกจากราชการ.trdp and b/BMA.EHR.Report.Service/Reports/38-คำสั่งลงโทษไล่ข้าราชการออกจากราชการ.trdp differ