API การลา 01-03
This commit is contained in:
parent
32686c3e0b
commit
cffb53c1f5
29 changed files with 6391 additions and 4 deletions
|
|
@ -1,5 +1,4 @@
|
|||
using Amazon.S3.Model;
|
||||
using BMA.EHR.Application.Repositories;
|
||||
using BMA.EHR.Application.Repositories;
|
||||
using BMA.EHR.Application.Repositories.Leaves.TimeAttendants;
|
||||
using BMA.EHR.Domain.Common;
|
||||
using BMA.EHR.Domain.Models.Leave.TimeAttendants;
|
||||
|
|
|
|||
348
BMA.EHR.Leave.Service/Controllers/LeaveRequestController.cs
Normal file
348
BMA.EHR.Leave.Service/Controllers/LeaveRequestController.cs
Normal file
|
|
@ -0,0 +1,348 @@
|
|||
using BMA.EHR.Application.Repositories;
|
||||
using BMA.EHR.Application.Repositories.Leaves.LeaveRequests;
|
||||
using BMA.EHR.Application.Repositories.MetaData;
|
||||
using BMA.EHR.Domain.Common;
|
||||
using BMA.EHR.Domain.Extensions;
|
||||
using BMA.EHR.Domain.Models.Leave.Requests;
|
||||
using BMA.EHR.Domain.Shared;
|
||||
using BMA.EHR.Infrastructure.Persistence;
|
||||
using BMA.EHR.Leave.Service.DTOs.LeaveRequest;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Swashbuckle.AspNetCore.Annotations;
|
||||
using System.Security.Claims;
|
||||
|
||||
namespace BMA.EHR.Leave.Service.Controllers
|
||||
{
|
||||
[Route("api/v{version:apiVersion}/leave")]
|
||||
[ApiVersion("1.0")]
|
||||
[ApiController]
|
||||
[Produces("application/json")]
|
||||
[Authorize]
|
||||
[SwaggerTag("API ระบบลงเวลาและการลา (การลา)")]
|
||||
public class LeaveRequestController : BaseController
|
||||
{
|
||||
#region " Fields "
|
||||
|
||||
private readonly LeaveDbContext _context;
|
||||
private readonly IHttpContextAccessor _httpContextAccessor;
|
||||
private readonly IWebHostEnvironment _hostingEnvironment;
|
||||
private readonly IConfiguration _configuration;
|
||||
private readonly UserProfileRepository _userProfileRepository;
|
||||
private readonly LeaveTypeRepository _leaveTypeRepository;
|
||||
private readonly LeaveRequestRepository _leaveRequestRepository;
|
||||
private readonly MinIOService _minIOService;
|
||||
private readonly HolidayRepository _holidayRepository;
|
||||
|
||||
#endregion
|
||||
|
||||
#region " Constuctor and Destructor "
|
||||
|
||||
public LeaveRequestController(LeaveDbContext context,
|
||||
IHttpContextAccessor httpContextAccessor,
|
||||
IWebHostEnvironment hostingEnvironment,
|
||||
IConfiguration configuration,
|
||||
UserProfileRepository userProfileRepository,
|
||||
LeaveTypeRepository leaveTypeRepository,
|
||||
LeaveRequestRepository leaveRequestRepository,
|
||||
MinIOService minIOService,
|
||||
HolidayRepository holidayRepository)
|
||||
{
|
||||
_context = context;
|
||||
_httpContextAccessor = httpContextAccessor;
|
||||
_hostingEnvironment = hostingEnvironment;
|
||||
_configuration = configuration;
|
||||
_userProfileRepository = userProfileRepository;
|
||||
_leaveTypeRepository = leaveTypeRepository;
|
||||
_leaveRequestRepository = leaveRequestRepository;
|
||||
_minIOService = minIOService;
|
||||
_holidayRepository = holidayRepository;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region " Properties "
|
||||
|
||||
private string? UserId => _httpContextAccessor?.HttpContext?.User?.FindFirst(ClaimTypes.NameIdentifier)?.Value;
|
||||
|
||||
private string? FullName => _httpContextAccessor?.HttpContext?.User?.FindFirst("name")?.Value;
|
||||
|
||||
private bool? PlacementAdmin => _httpContextAccessor?.HttpContext?.User?.IsInRole("placement1");
|
||||
|
||||
private Guid OcId
|
||||
{
|
||||
get
|
||||
{
|
||||
if (UserId != null || UserId != "")
|
||||
return _userProfileRepository.GetUserOCId(Guid.Parse(UserId!));
|
||||
else
|
||||
return Guid.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region " Methods "
|
||||
|
||||
/// <summary>
|
||||
/// LV2_001 - สร้างคำขอการลา (USER)
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// </returns>
|
||||
/// <response code="200">เมื่อทำรายการสำเร็จ</response>
|
||||
/// <response code="401">ไม่ได้ Login เข้าระบบ</response>
|
||||
/// <response code="500">เมื่อเกิดข้อผิดพลาดในการทำงาน</response>
|
||||
[HttpPost("user")]
|
||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(StatusCodes.Status401Unauthorized)]
|
||||
[ProducesResponseType(StatusCodes.Status500InternalServerError)]
|
||||
public async Task<ActionResult<ResponseObject>> CreateLeaveRequestAsync([FromForm] CreateLeaveRequestDto req)
|
||||
{
|
||||
var userId = UserId == null ? Guid.Empty : Guid.Parse(UserId);
|
||||
var thisYear = DateTime.Now.Year;
|
||||
|
||||
var profile = await _userProfileRepository.GetProfileByKeycloakIdAsync(userId);
|
||||
|
||||
if (profile == null)
|
||||
{
|
||||
return Error(GlobalMessages.DataNotFound, StatusCodes.Status404NotFound);
|
||||
}
|
||||
|
||||
var leaveType = await _leaveTypeRepository.GetByIdAsync(req.Type);
|
||||
if (leaveType == null)
|
||||
{
|
||||
return Error(GlobalMessages.DataNotFound, StatusCodes.Status404NotFound);
|
||||
}
|
||||
|
||||
var leaveRequest = new LeaveRequest
|
||||
{
|
||||
Type = leaveType,
|
||||
LeaveStartDate = req.LeaveStartDate,
|
||||
LeaveEndDate = req.LeaveEndDate,
|
||||
LeaveWrote = req.LeaveWrote ?? "",
|
||||
LeaveDetail = req.LeaveDetail ?? "",
|
||||
LeaveAddress = req.LeaveAddress ?? "",
|
||||
LeaveNumber = req.LeaveNumber ?? "",
|
||||
LeaveTotal = req.LeaveStartDate.DiffDay(req.LeaveEndDate),
|
||||
LeaveSalaryText = req.LeaveSalaryText ?? ""
|
||||
};
|
||||
|
||||
// get leave last
|
||||
leaveRequest.LeaveLast = await _leaveRequestRepository.GetLeaveLastByTypeForUserAsync(userId, req.Type);
|
||||
|
||||
// upload document
|
||||
if (req.LeaveDocument != null)
|
||||
{
|
||||
var doc = await _minIOService.UploadFileAsync(req.LeaveDocument);
|
||||
if (doc != null)
|
||||
{
|
||||
leaveRequest.LeaveDocument = doc;
|
||||
}
|
||||
}
|
||||
|
||||
// upload draft document
|
||||
if (req.LeaveDraftDocument != null)
|
||||
{
|
||||
var doc = await _minIOService.UploadFileAsync(req.LeaveDraftDocument);
|
||||
if (doc != null)
|
||||
{
|
||||
leaveRequest.LeaveDraftDocument = doc;
|
||||
}
|
||||
}
|
||||
|
||||
// switch from leave type
|
||||
switch (leaveType.Code.Trim().ToUpper())
|
||||
{
|
||||
case "LV-004":
|
||||
{
|
||||
leaveRequest.WifeDayName = req.WifeDayName ?? "";
|
||||
leaveRequest.WifeDayDateBorn = req.WifeDayDateBorn ?? "";
|
||||
}
|
||||
break;
|
||||
case "LV-005":
|
||||
{
|
||||
leaveRequest.RestDayOldTotal = await _leaveRequestRepository.GetRestDayTotalByYearForUserAsync(userId, thisYear - 1);
|
||||
leaveRequest.RestDayCurrentTotal = await _leaveRequestRepository.GetRestDayTotalByYearForUserAsync(userId, thisYear);
|
||||
}
|
||||
break;
|
||||
case "LV-006":
|
||||
{
|
||||
leaveRequest.OrdainDayStatus = req.OrdainDayStatus ?? false;
|
||||
leaveRequest.OrdainDayLocationName = req.OrdainDayLocationName ?? "";
|
||||
leaveRequest.OrdainDayLocationAddress = req.OrdainDayLocationAddress ?? "";
|
||||
leaveRequest.OrdainDayLocationNumber = req.OrdainDayLocationNumber ?? "";
|
||||
if (req.OrdainDayOrdination != null)
|
||||
leaveRequest.OrdainDayOrdination = req.OrdainDayOrdination.Value;
|
||||
|
||||
leaveRequest.OrdainDayBuddhistLentName = req.OrdainDayBuddhistLentName ?? "";
|
||||
|
||||
leaveRequest.OrdainDayBuddhistLentAddress = req.OrdainDayBuddhistLentAddress ?? "";
|
||||
|
||||
leaveRequest.LeaveBirthDate = profile.BirthDate;
|
||||
leaveRequest.LeaveGovernmentDate = profile.DateStart;
|
||||
|
||||
leaveRequest.HajjDayStatus = req.HajjDayStatus ?? false;
|
||||
|
||||
}
|
||||
break;
|
||||
case "LV-007":
|
||||
{
|
||||
leaveRequest.AbsentDayLocation = req.AbsentDayLocation ?? "";
|
||||
leaveRequest.AbsentDaySummon = req.AbsentDaySummon ?? "";
|
||||
if (req.AbsentDayRegistorDate != null)
|
||||
leaveRequest.AbsentDayRegistorDate = req.AbsentDayRegistorDate.Value;
|
||||
|
||||
leaveRequest.AbsentDayGetIn = req.AbsentDayGetIn ?? "";
|
||||
|
||||
leaveRequest.AbsentDayAt = req.AbsentDayAt ?? "";
|
||||
}
|
||||
break;
|
||||
case "LV-008":
|
||||
{
|
||||
var lastSalary = profile.Salaries.OrderByDescending(x => x.Order).FirstOrDefault();
|
||||
|
||||
leaveRequest.LeaveSalary = lastSalary == null ? 0 : (int)lastSalary.Amount.Value;
|
||||
leaveRequest.LeaveSalaryText = lastSalary == null ? "" : ((int)lastSalary.Amount.Value).ToThaiBahtText(false);
|
||||
leaveRequest.LeaveBirthDate = profile.BirthDate;
|
||||
leaveRequest.LeaveGovernmentDate = profile.DateStart;
|
||||
|
||||
leaveRequest.StudyDaySubject = req.StudyDaySubject ?? "";
|
||||
leaveRequest.StudyDayDegreeLevel = req.StudyDayDegreeLevel ?? "";
|
||||
leaveRequest.StudyDayUniversityName = req.StudyDayUniversityName ?? "";
|
||||
leaveRequest.StudyDayCountry = req.StudyDayCountry ?? "";
|
||||
leaveRequest.StudyDayScholarship = req.StudyDayScholarship ?? "";
|
||||
|
||||
leaveRequest.StudyDayTrainingSubject = req.StudyDayTrainingSubject ?? "";
|
||||
leaveRequest.StudyDayTrainingName = req.StudyDayTrainingName ?? "";
|
||||
|
||||
}
|
||||
break;
|
||||
case "LV-010":
|
||||
{
|
||||
var lastSalary = profile.Salaries.OrderByDescending(x => x.Order).FirstOrDefault();
|
||||
|
||||
leaveRequest.LeaveSalary = lastSalary == null ? 0 : (int)lastSalary.Amount.Value;
|
||||
leaveRequest.LeaveSalaryText = lastSalary == null ? "" : ((int)lastSalary.Amount.Value).ToThaiBahtText(false);
|
||||
|
||||
leaveRequest.CoupleDayName = req.CoupleDayName ?? "";
|
||||
leaveRequest.CoupleDayPosition = req.CoupleDayPosition ?? "";
|
||||
leaveRequest.CoupleDayLevel = req.CoupleDayLevel ?? "";
|
||||
leaveRequest.CoupleDayLevelCountry = req.CoupleDayLevelCountry ?? "";
|
||||
leaveRequest.CoupleDayCountryHistory = req.CoupleDayCountryHistory ?? "";
|
||||
leaveRequest.CoupleDayTotalHistory = req.CoupleDayTotalHistory ?? "";
|
||||
|
||||
if (req.CoupleDayStartDateHistory != null)
|
||||
leaveRequest.CoupleDayStartDateHistory = req.CoupleDayStartDateHistory.Value;
|
||||
|
||||
if (req.CoupleDayEndDateHistory != null)
|
||||
leaveRequest.CoupleDayEndDateHistory = req.CoupleDayEndDateHistory.Value;
|
||||
|
||||
leaveRequest.CoupleDaySumTotalHistory = req.CoupleDaySumTotalHistory ?? "";
|
||||
|
||||
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// save to database
|
||||
await _leaveRequestRepository.AddAsync(leaveRequest);
|
||||
|
||||
return Success();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// LV2_002 - ข้อมูลที่ user ขอยื่นลา (USER)
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// </returns>
|
||||
/// <response code="200">เมื่อทำรายการสำเร็จ</response>
|
||||
/// <response code="401">ไม่ได้ Login เข้าระบบ</response>
|
||||
/// <response code="500">เมื่อเกิดข้อผิดพลาดในการทำงาน</response>
|
||||
[HttpPost("user/profile")]
|
||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(StatusCodes.Status401Unauthorized)]
|
||||
[ProducesResponseType(StatusCodes.Status500InternalServerError)]
|
||||
public async Task<ActionResult<ResponseObject>> GetUserLeaveProfileAsync([FromBody] GetUserLeaveProfileDto req)
|
||||
{
|
||||
var userId = UserId == null ? Guid.Empty : Guid.Parse(UserId);
|
||||
var thisYear = DateTime.Now.Year;
|
||||
|
||||
var profile = await _userProfileRepository.GetProfileByKeycloakIdAsync(userId);
|
||||
if (profile == null)
|
||||
{
|
||||
return Error(GlobalMessages.DataNotFound, StatusCodes.Status404NotFound);
|
||||
}
|
||||
|
||||
var leaveType = await _leaveTypeRepository.GetByIdAsync(req.Type);
|
||||
if (leaveType == null)
|
||||
{
|
||||
return Error(GlobalMessages.DataNotFound, StatusCodes.Status404NotFound);
|
||||
}
|
||||
|
||||
var sumLeave = await _leaveRequestRepository.GetSumLeaveByTypeForUserAsync(userId, req.Type, thisYear);
|
||||
var restOldDay = await _leaveRequestRepository.GetRestDayTotalByYearForUserAsync(userId, thisYear - 1);
|
||||
|
||||
var lastSalary = profile.Salaries.OrderByDescending(x => x.Order).FirstOrDefault();
|
||||
|
||||
var result = new GetUserLeaveProfileResultDto
|
||||
{
|
||||
DateSendLeave = DateTime.Now.Date,
|
||||
LeaveTypeName = leaveType.Name,
|
||||
Dear = "นายณัฐพงษ์ ดิษยบุตร",
|
||||
FullName = $"{profile.Prefix.Name}{profile.FirstName} {profile.LastName}",
|
||||
PositionName = profile.Position.Name,
|
||||
PositionLevelName = profile.PositionEmployeeLevel.Name,
|
||||
OrganizationName = profile.Oc,
|
||||
LeaveLimit = leaveType.Limit,
|
||||
LeaveTotal = sumLeave,
|
||||
LeaveRemain = leaveType.Limit - sumLeave,
|
||||
RestDayTotalOld = restOldDay,
|
||||
BirthDate = profile.BirthDate.Date,
|
||||
DateAppoint = profile.DateAppoint.Value.Date,
|
||||
Salary = lastSalary == null ? 0 : (int)lastSalary.Amount.Value,
|
||||
SalaryText = lastSalary == null ? "" : ((int)lastSalary.Amount.Value).ToThaiBahtText(false),
|
||||
|
||||
};
|
||||
|
||||
return Success(result);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// LV2_003 - เช็คการยืนขอลา (USER)
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// </returns>
|
||||
/// <response code="200">เมื่อทำรายการสำเร็จ</response>
|
||||
/// <response code="401">ไม่ได้ Login เข้าระบบ</response>
|
||||
/// <response code="500">เมื่อเกิดข้อผิดพลาดในการทำงาน</response>
|
||||
[HttpPost("user/check")]
|
||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(StatusCodes.Status401Unauthorized)]
|
||||
[ProducesResponseType(StatusCodes.Status500InternalServerError)]
|
||||
public async Task<ActionResult<ResponseObject>> CheckUserLeaveAsync([FromBody] GetLeaveCheckDto req)
|
||||
{
|
||||
var userId = UserId == null ? Guid.Empty : Guid.Parse(UserId);
|
||||
var leaveType = await _leaveTypeRepository.GetByIdAsync(req.Type);
|
||||
if (leaveType == null)
|
||||
{
|
||||
return Error(GlobalMessages.DataNotFound, StatusCodes.Status404NotFound);
|
||||
}
|
||||
|
||||
var sumLeave = await _leaveRequestRepository.GetSumLeaveByTypeForUserAsync(userId, req.Type, req.StartLeaveDate.Year);
|
||||
var sumWorkDay = await _holidayRepository.GetHolidayCountAsync(req.StartLeaveDate, req.EndLeaveDate);
|
||||
var totalDay = req.StartLeaveDate.DiffDay(req.EndLeaveDate);
|
||||
var isLeave = sumLeave + (totalDay - sumWorkDay) <= leaveType.Limit;
|
||||
|
||||
var result = new GetLeaveCheckResultDto
|
||||
{
|
||||
IsLeave = isLeave,
|
||||
SumDateWork = sumWorkDay,
|
||||
TotalDate = totalDay,
|
||||
};
|
||||
|
||||
return Success(result);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
|
@ -26,5 +26,72 @@ namespace BMA.EHR.Leave.Service.DTOs.LeaveRequest
|
|||
public IFormFile? LeaveDraftDocument { get; set; }
|
||||
|
||||
public string? LeaveSalaryText { get; set; }
|
||||
|
||||
public string? WifeDayName { get; set; }
|
||||
|
||||
public string? WifeDayDateBorn { get; set; }
|
||||
|
||||
public int? RestDayOldTotal { get; set; }
|
||||
|
||||
public int? RestDayCurrentTotal { get; set; }
|
||||
|
||||
public bool? OrdainDayStatus { get; set; }
|
||||
|
||||
public string? OrdainDayLocationName { get; set; }
|
||||
|
||||
public string? OrdainDayLocationAddress { get; set; }
|
||||
|
||||
public string? OrdainDayLocationNumber { get; set; }
|
||||
|
||||
public DateTime? OrdainDayOrdination { get; set; }
|
||||
|
||||
public string? OrdainDayBuddhistLentName { get; set; }
|
||||
|
||||
public string? OrdainDayBuddhistLentAddress { get; set; }
|
||||
|
||||
public bool? HajjDayStatus { get; set; }
|
||||
|
||||
public string? AbsentDaySummon { get; set; }
|
||||
|
||||
public string? AbsentDayLocation { get; set; }
|
||||
|
||||
public DateTime? AbsentDayRegistorDate { get; set; }
|
||||
|
||||
public string? AbsentDayGetIn { get; set; }
|
||||
|
||||
public string? AbsentDayAt { get; set; }
|
||||
|
||||
public string? StudyDaySubject { get; set; }
|
||||
|
||||
public string? StudyDayDegreeLevel { get; set; }
|
||||
|
||||
public string? StudyDayUniversityName { get; set; }
|
||||
|
||||
public string? StudyDayTrainingSubject { get; set; }
|
||||
|
||||
public string? StudyDayTrainingName { get; set; }
|
||||
|
||||
public string? StudyDayCountry { get; set; }
|
||||
|
||||
public string? StudyDayScholarship { get; set; }
|
||||
|
||||
public string? CoupleDayName { get; set; }
|
||||
|
||||
public string? CoupleDayPosition { get; set; }
|
||||
|
||||
public string? CoupleDayLevel { get; set; }
|
||||
|
||||
public string? CoupleDayLevelCountry { get; set; }
|
||||
|
||||
public string? CoupleDayCountryHistory { get; set; }
|
||||
|
||||
public string? CoupleDayTotalHistory { get; set; }
|
||||
|
||||
public DateTime? CoupleDayStartDateHistory { get; set; }
|
||||
|
||||
public DateTime? CoupleDayEndDateHistory { get; set; }
|
||||
|
||||
public string? CoupleDaySumTotalHistory { get; set; }
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
16
BMA.EHR.Leave.Service/DTOs/LeaveRequest/GetLeaveCheckDto.cs
Normal file
16
BMA.EHR.Leave.Service/DTOs/LeaveRequest/GetLeaveCheckDto.cs
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace BMA.EHR.Leave.Service.DTOs.LeaveRequest
|
||||
{
|
||||
public class GetLeaveCheckDto
|
||||
{
|
||||
[Required]
|
||||
public Guid Type { get; set; } = Guid.Empty;
|
||||
|
||||
[Required]
|
||||
public DateTime StartLeaveDate { get; set; } = DateTime.MinValue;
|
||||
|
||||
[Required]
|
||||
public DateTime EndLeaveDate { get; set;} = DateTime.MinValue;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
namespace BMA.EHR.Leave.Service.DTOs.LeaveRequest
|
||||
{
|
||||
public class GetLeaveCheckResultDto
|
||||
{
|
||||
public bool IsLeave { get;set; } = false;
|
||||
|
||||
public double SumDateWork { get; set; } = 0;
|
||||
|
||||
public double TotalDate { get; set; } = 0;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace BMA.EHR.Leave.Service.DTOs.LeaveRequest
|
||||
{
|
||||
public class GetUserLeaveProfileDto
|
||||
{
|
||||
[Required]
|
||||
public Guid Type { get; set; } = Guid.Empty;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
namespace BMA.EHR.Leave.Service.DTOs.LeaveRequest
|
||||
{
|
||||
public class GetUserLeaveProfileResultDto
|
||||
{
|
||||
public DateTime DateSendLeave { get; set; }
|
||||
|
||||
public string LeaveTypeName { get; set; }
|
||||
|
||||
public string Dear { get; set; }
|
||||
|
||||
public string FullName { get; set; }
|
||||
|
||||
public string PositionName { get; set; }
|
||||
|
||||
public string PositionLevelName { get; set; }
|
||||
|
||||
public string OrganizationName { get; set; }
|
||||
|
||||
public double LeaveLimit { get; set; }
|
||||
|
||||
public double LeaveTotal { get; set; }
|
||||
|
||||
public double LeaveRemain { get; set; }
|
||||
|
||||
public double RestDayTotalOld { get; set; }
|
||||
|
||||
public DateTime BirthDate { get; set; }
|
||||
|
||||
public DateTime DateAppoint { get; set; }
|
||||
|
||||
public int Salary { get; set; }
|
||||
|
||||
public string SalaryText { get; set; }
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue