Add Certificate Report

This commit is contained in:
Suphonchai Phoonsawat 2023-04-17 21:24:52 +07:00
parent 5cfdd1561d
commit dfc9cb2e85
31 changed files with 3737 additions and 79 deletions

View file

@ -1,17 +1,60 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<UserSecretsId>dce859f2-cd46-4149-910b-bea19ed278b2</UserSecretsId>
<DockerDefaultTargetOS>Linux</DockerDefaultTargetOS>
</PropertyGroup>
<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<UserSecretsId>dce859f2-cd46-4149-910b-bea19ed278b2</UserSecretsId>
<DockerDefaultTargetOS>Linux</DockerDefaultTargetOS>
<GenerateDocumentationFile>True</GenerateDocumentationFile>
<RootNamespace>BMA.EHR.Report.Service</RootNamespace>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="7.0.5" />
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.17.2" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.4.0" />
</ItemGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<NoWarn>1701;1702;1591;0436;</NoWarn>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
<NoWarn>1701;1702;1591;0436;</NoWarn>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="BMA.EHR.Core" Version="1.0.0" />
<PackageReference Include="BMA.EHR.Extensions" Version="1.0.1" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="7.0.5" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="7.0.5" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Versioning" Version="5.0.0" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Versioning.ApiExplorer" Version="5.0.0" />
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="7.0.5" />
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.17.2" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="7.0.5" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="7.0.5" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="7.0.5">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.18.1" />
<PackageReference Include="MongoDB.Driver" Version="2.19.1" />
<PackageReference Include="MongoDB.Driver.GridFS" Version="2.19.1" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="Pomelo.EntityFrameworkCore.MySql" Version="7.0.0" />
<PackageReference Include="Pomelo.EntityFrameworkCore.MySql.Design" Version="1.1.2" />
<PackageReference Include="runtime.osx.10.10-x64.CoreCompat.System.Drawing" Version="6.0.5.128" />
<PackageReference Include="Sentry.AspNetCore" Version="3.30.0" />
<PackageReference Include="Serilog.AspNetCore" Version="6.1.0" />
<PackageReference Include="Serilog.Enrichers.Environment" Version="2.2.0" />
<PackageReference Include="Serilog.Exceptions" Version="8.4.0" />
<PackageReference Include="Serilog.Sinks.Console" Version="4.1.0" />
<PackageReference Include="Serilog.Sinks.Debug" Version="2.0.0" />
<PackageReference Include="Serilog.Sinks.Elasticsearch" Version="9.0.0" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.5.0" />
<PackageReference Include="Swashbuckle.AspNetCore.Annotations" Version="6.5.0" />
<PackageReference Include="WatchDog.NET" Version="1.4.6" />
<PackageReference Include="Telerik.Reporting" Version="17.0.23.315" />
</ItemGroup>
<ItemGroup>
<Folder Include="Report\Recruit\" />
</ItemGroup>
</Project>

View file

@ -0,0 +1,84 @@
using Microsoft.AspNetCore.Mvc.ApiExplorer;
using Microsoft.Extensions.Options;
using Microsoft.OpenApi.Models;
using Swashbuckle.AspNetCore.SwaggerGen;
using System.Reflection;
namespace BMA.EHR.Report.Service
{
public class ConfigureSwaggerOptions : IConfigureNamedOptions<SwaggerGenOptions>
{
private readonly IApiVersionDescriptionProvider _provider;
public ConfigureSwaggerOptions(
IApiVersionDescriptionProvider provider)
{
_provider = provider;
}
public void Configure(SwaggerGenOptions options)
{
// add swagger document for every API version discovered
foreach (var description in _provider.ApiVersionDescriptions)
{
options.EnableAnnotations();
options.SwaggerDoc(
description.GroupName,
CreateVersionInfo(description));
}
options.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
{
In = ParameterLocation.Header,
Description = "Please enter a valid token",
Name = "Authorization",
Type = SecuritySchemeType.Http,
BearerFormat = "JWT",
Scheme = "Bearer"
});
options.AddSecurityRequirement(new OpenApiSecurityRequirement
{
{
new OpenApiSecurityScheme
{
Reference = new OpenApiReference
{
Type = ReferenceType.SecurityScheme,
Id = "Bearer"
}
},
new string[]{}
}
});
// generate the XML docs that'll drive the swagger docs
var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);
options.IncludeXmlComments(xmlPath);
}
public void Configure(string name, SwaggerGenOptions options)
{
Configure(options);
}
private OpenApiInfo CreateVersionInfo(
ApiVersionDescription desc)
{
var info = new OpenApiInfo()
{
Title = "BMA EHR Report Service Document",
Version = desc.ApiVersion.ToString()
};
if (desc.IsDeprecated)
{
info.Description += " This API version has been deprecated. Please use one of the new APIs available from the explorer.";
}
return info;
}
}
}

View file

@ -0,0 +1,90 @@
using BMA.EHR.Core;
using BMA.EHR.Report.Service.Responses;
using Microsoft.AspNetCore.Mvc;
namespace BMA.EHR.Profile.Service.Controllers
{
public class BaseController : ControllerBase
{
#region " Methods "
#region " Protected "
#region " IActionResult "
protected virtual ActionResult<ResponseObject> Success(string message, object? result = null)
{
if (result != null)
{
return Ok(new ResponseObject
{
Status = StatusCodes.Status200OK,
Message = message,
Result = result
});
}
else
{
return Ok(new ResponseObject
{
Status = StatusCodes.Status200OK,
Message = message
});
}
}
protected virtual ActionResult<ResponseObject> Success(object? result = null)
{
return Success(GlobalMessages.Success, result);
}
protected virtual ActionResult<ResponseObject> Error(string message, string result, int statusCode = StatusCodes.Status500InternalServerError)
{
return StatusCode((int)statusCode, new ResponseObject
{
Status = statusCode,
Message = message,
Result = result
});
}
protected virtual ActionResult<ResponseObject> Error(string message, int statusCode = StatusCodes.Status500InternalServerError)
{
return Error(message, message, statusCode);
}
protected virtual ActionResult<ResponseObject> Error(Exception exception, string message, int statusCode = StatusCodes.Status500InternalServerError)
{
var msg = exception.Message;
var inner = exception.InnerException;
while (inner != null)
{
msg += $" {inner.Message}\r\n";
inner = inner.InnerException;
}
return Error(message, msg, statusCode);
}
protected virtual ActionResult<ResponseObject> Error(Exception exception, int statusCode = StatusCodes.Status500InternalServerError)
{
var msg = exception.Message;
var inner = exception.InnerException;
while (inner != null)
{
msg += $" {inner.Message}\r\n";
inner = inner.InnerException;
}
return Error(msg, msg, statusCode);
}
#endregion
#endregion
#endregion
}
}

View file

@ -0,0 +1,121 @@
using BMA.EHR.Extensions;
using BMA.EHR.Profile.Service.Controllers;
using BMA.EHR.Report.Service.Data;
using BMA.EHR.Report.Service.Responses;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Swashbuckle.AspNetCore.Annotations;
using Telerik.Reporting;
using Telerik.Reporting.Processing;
namespace BMA.EHR.Report.Service.Controllers
{
[Route("api/v{version:apiVersion}/report/recruit")]
[ApiVersion("1.0")]
[ApiController]
[Produces("application/json")]
[Authorize]
[SwaggerTag("รายงานข้อมูลการสอบแข่งขัน")]
public class RecruitReportController : BaseController
{
#region " Fields "
private readonly ApplicationDbContext _context;
private readonly IWebHostEnvironment _hostingEnvironment;
private readonly IConfiguration _configuration;
private readonly string space = "";
#endregion
#region " Constructor and Destructor "
public RecruitReportController(ApplicationDbContext context,
IWebHostEnvironment hostingEnvironment,
IConfiguration configuration)
{
this._context = context;
this._hostingEnvironment = hostingEnvironment;
this._configuration = configuration;
}
#endregion
#region " Methods "
/// <summary>
/// แสดงหนังสือรับรอง
/// </summary>
/// <param name="id">รหัสรอบการสอบ</param>
/// <param name="examId">เลขประจำตัวผู้สมัครสอบ</param>
/// <returns></returns>
/// <response code="200">เมื่อแสดงรายงานสำเร็จ</response>
/// <response code="400">ค่าตัวแปรที่ส่งมาไม่ถูกต้อง</response>
/// <response code="401">ไม่ได้ Login เข้าระบบ</response>
/// <response code="500">เมื่อเกิดข้อผิดพลาดในการทำงาน</response>
[HttpGet("certificate/{id:length(36)}/{examId}")]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
[ProducesResponseType(StatusCodes.Status401Unauthorized)]
[ProducesResponseType(StatusCodes.Status500InternalServerError)]
public async Task<ActionResult<ResponseObject>> GetPeriodByIdAsync(Guid id, string examId)
{
try
{
var data = await _context.Recruits.AsQueryable()
.Include(x => x.RecruitImport)
.Where(x => x.RecruitImport.Id == id)
.Where(x => x.ExamId == examId)
.Join(_context.RecruitScores.AsQueryable()
.Include(x => x.ScoreImport),
rc => new { rc.RecruitImport.Year, rc.ExamId },
sc => new { sc.ScoreImport.Year, sc.ExamId },
(p, sr) => new
{
ExamID = p.ExamId,
p.CitizenId,
Order = p.RecruitImport.Order,
Year = p.RecruitImport.Year,
FullName = $"{p.Prefix}{p.FirstName} {p.LastName}",
ExamResult = sr == null ? "" : sr.ExamStatus,
EndDate = DateTime.Now.ToThaiShortDate2()
})
.FirstOrDefaultAsync();
var rptFile = Path.Combine(_hostingEnvironment.ContentRootPath, "Report", "Recruit", "rptCertificate.trdp");
ReportPackager reportPackager = new ReportPackager();
Telerik.Reporting.Report report = null;
using (var sourceStream = System.IO.File.OpenRead(rptFile))
{
report = (Telerik.Reporting.Report)reportPackager.UnpackageDocument(sourceStream);
}
report.DataSource = data;
System.Collections.Hashtable deviceInfo = new System.Collections.Hashtable();
InstanceReportSource instanceReportSource = new InstanceReportSource()
{
ReportDocument = report
};
ReportProcessor reportProcessor = new ReportProcessor(_configuration);
RenderingResult result = reportProcessor.RenderReport("PDF", instanceReportSource, deviceInfo);
var content = result.DocumentBytes;
return File(content, "application/pdf", $"หนังสือรับรอง_{data.CitizenId}_{data.FullName}.pdf");
}
catch (Exception ex)
{
return Error(ex, "เกิดข้อผิดพลาดในการแสดงรายงาน");
}
}
#endregion
}
}

View file

@ -1,33 +0,0 @@
using Microsoft.AspNetCore.Mvc;
namespace BMA.EHR.Report.Service.Controllers
{
[ApiController]
[Route("[controller]")]
public class WeatherForecastController : ControllerBase
{
private static readonly string[] Summaries = new[]
{
"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
};
private readonly ILogger<WeatherForecastController> _logger;
public WeatherForecastController(ILogger<WeatherForecastController> logger)
{
_logger = logger;
}
[HttpGet(Name = "GetWeatherForecast")]
public IEnumerable<WeatherForecast> Get()
{
return Enumerable.Range(1, 5).Select(index => new WeatherForecast
{
Date = DateOnly.FromDateTime(DateTime.Now.AddDays(index)),
TemperatureC = Random.Shared.Next(-20, 55),
Summary = Summaries[Random.Shared.Next(Summaries.Length)]
})
.ToArray();
}
}
}

View file

@ -0,0 +1,56 @@
using BMA.EHR.Recruit.Service.Models.Documents;
using BMA.EHR.Recruit.Service.Models.Recruits;
using Microsoft.EntityFrameworkCore;
namespace BMA.EHR.Report.Service.Data
{
public class ApplicationDbContext : DbContext
{
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
: base(options)
{
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
//base.OnModelCreating(modelBuilder);
//modelBuilder.Ignore<Document>();
//modelBuilder.Ignore<RecruitImport>();
//modelBuilder.Ignore<Recruit.Service.Models.Recruits.Recruit>();
//modelBuilder.Ignore<RecruitAddress>();
//modelBuilder.Ignore<RecruitOccupation>();
//modelBuilder.Ignore<RecruitCertificate>();
//modelBuilder.Ignore<RecruitEducation>();
//modelBuilder.Ignore<ScoreImport>();
//modelBuilder.Ignore<RecruitScore>();
//modelBuilder.Ignore<RecruitPayment>();
//modelBuilder.Ignore<RecruitDocument>();
//modelBuilder.Ignore<RecruitImportHistory>();
}
public DbSet<Document> Documents { get; set; }
public DbSet<RecruitImport> RecruitImports { get; set; }
public DbSet<Recruit.Service.Models.Recruits.Recruit> Recruits { get; set; }
public DbSet<RecruitAddress> RecruitAddresses { get; set; }
public DbSet<RecruitOccupation> RecruitOccupations { get; set; }
public DbSet<RecruitCertificate> RecruitCertificates { get; set; }
public DbSet<RecruitEducation> RecruitEducations { get; set; }
public DbSet<ScoreImport> ScoreImports { get; set; }
public DbSet<RecruitScore> RecruitScores { get; set; }
public DbSet<RecruitPayment> RecruitPayments { get; set; }
public DbSet<RecruitDocument> RecruitDocuments { get; set; }
public DbSet<RecruitImportHistory> RecruitImportHistories { get; set; }
}
}

View file

@ -0,0 +1,26 @@
// <auto-generated />
using BMA.EHR.Report.Service.Data;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
#nullable disable
namespace BMA.EHR.Report.Service.Migrations
{
[DbContext(typeof(ApplicationDbContext))]
[Migration("20230417135602_Init")]
partial class Init
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "7.0.5")
.HasAnnotation("Relational:MaxIdentifierLength", 64);
#pragma warning restore 612, 618
}
}
}

View file

@ -0,0 +1,23 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace BMA.EHR.Report.Service.Migrations
{
/// <inheritdoc />
public partial class Init : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AlterDatabase()
.Annotation("MySql:CharSet", "utf8mb4");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
}
}
}

1284
Migrations/20230417141222_Init2.Designer.cs generated Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,22 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace BMA.EHR.Report.Service.Migrations
{
/// <inheritdoc />
public partial class Init2 : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
}
}
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,29 @@
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace BMA.EHR.Recruit.Service.Models.Documents
{
public class Document
{
[Key]
public Guid Id { get; set; }
[Required, MaxLength(255)]
public string FileName { get; set; } = string.Empty;
[Required]
public int FileSize { get; set; } = 0;
[Required, MaxLength(128)]
public string FileType { get; set; } = string.Empty;
[Column(TypeName = "text")]
public string Detail { get; set; } = string.Empty;
[Required]
public Guid ObjectRefId { get; set; }
[Required]
public DateTime CreatedDate { get; set; } = DateTime.Now;
}
}

32
Models/EntityBase.cs Normal file
View file

@ -0,0 +1,32 @@
using Microsoft.EntityFrameworkCore;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Text.Json.Serialization;
namespace BMA.EHR.Report.Service.Models
{
public class EntityBase
{
[Key, Column(Order = 0), Comment("PrimaryKey")]
[JsonPropertyName("id")]
public Guid Id { get; set; }
[Required, Column(Order = 100), Comment("สร้างข้อมูลเมื่อ")]
public DateTime CreatedAt { get; set; } = DateTime.Now;
[Column(Order = 101), Comment("User Id ที่สร้างข้อมูล"), MaxLength(40)]
public string CreatedUserId { get; set; } = string.Empty;
[Column(Order = 102), Comment("แก้ไขข้อมูลล่าสุดเมื่อ")]
public DateTime? LastUpdatedAt { get; set; }
[Column(Order = 103), Comment("User Id ที่แก้ไขข้อมูลล่าสุด"), MaxLength(40)]
public string LastUpdateUserId { get; set; } = string.Empty;
[Column(Order = 104), Comment("ชื่อ User ที่สร้างข้อมูล"), MaxLength(200)]
public string CreatedFullName { get; set; } = string.Empty;
[Column(Order = 105), Comment("ชื่อ User ที่แก้ไขข้อมูลล่าสุด"), MaxLength(200)]
public string LastUpdateFullName { get; set; } = string.Empty;
}
}

View file

@ -0,0 +1,80 @@
using BMA.EHR.Report.Service.Models;
using Microsoft.EntityFrameworkCore;
using System.ComponentModel.DataAnnotations;
namespace BMA.EHR.Recruit.Service.Models.Recruits
{
public class Recruit : EntityBase
{
[Required, MaxLength(13), Comment("เลขประจำตัวประชาชน")]
public string CitizenId { get; set; } = string.Empty;
[Required, MaxLength(50)]
public string ExamId { get; set; } = string.Empty;
[Required, MaxLength(50)]
public string Prefix { get; set; } = string.Empty;
[Required, MaxLength(150)]
public string FirstName { get; set; } = string.Empty;
[Required, MaxLength(150)]
public string LastName { get; set; } = string.Empty;
[MaxLength(20)]
public string Gendor { get; set; } = string.Empty;
[MaxLength(200)]
public string National { get; set; } = string.Empty;
[MaxLength(200)]
public string Race { get; set; } = string.Empty;
[MaxLength(200)]
public string Religion { get; set; } = string.Empty;
[Required]
public DateTime DateOfBirth { get; set; }
[MaxLength(20)]
public string Marry { get; set; } = string.Empty;
[MaxLength(1)]
public string Isspecial { get; set; } = "N";
[MaxLength(20)]
public string RefNo { get; set; } = string.Empty;
[MaxLength(200)]
public string CitizenCardIssuer { get; set; } = string.Empty;
public DateTime CitizenCardExpireDate { get; set; }
[MaxLength(200)]
public string Remark { get; set; } = string.Empty;
[MaxLength(1)]
public string Qualified { get; set; } = "Y";
public RecruitImport? RecruitImport { get; set; }
public virtual List<RecruitAddress> Addresses { get; set; } = new List<RecruitAddress>();
public virtual List<RecruitOccupation> Occupations { get; set; } = new List<RecruitOccupation>();
public virtual List<RecruitCertificate> Certificates { get; set; } = new List<RecruitCertificate>();
public virtual List<RecruitEducation> Educations { get; set; } = new List<RecruitEducation>();
public virtual List<RecruitPayment> Payments { get; set; } = new List<RecruitPayment>();
public virtual List<RecruitDocument> Documents { get; set; } = new List<RecruitDocument>();
public DateTime CreatedDate { get; set; } = DateTime.Now;
public DateTime ModifiedDate { get; set; }
public DateTime ApplyDate { get; set; }
}
}

View file

@ -0,0 +1,64 @@
using System.ComponentModel.DataAnnotations;
using BMA.EHR.Report.Service.Models;
namespace BMA.EHR.Recruit.Service.Models.Recruits
{
public class RecruitAddress : EntityBase
{
[MaxLength(200)]
public string Address { get; set; }
[MaxLength(200)]
public string Moo { get; set; }
[MaxLength(200)]
public string Soi { get; set; }
[MaxLength(200)]
public string Road { get; set; }
[MaxLength(200)]
public string District { get; set; }
[MaxLength(200)]
public string Amphur { get; set; }
[MaxLength(200)]
public string Province { get; set; }
[MaxLength(5)]
public string ZipCode { get; set; }
[MaxLength(200)]
public string Telephone { get; set; }
[MaxLength(200)]
public string Mobile { get; set; }
[MaxLength(200)]
public string Address1 { get; set; }
[MaxLength(200)]
public string Moo1 { get; set; }
[MaxLength(200)]
public string Soi1 { get; set; }
[MaxLength(200)]
public string Road1 { get; set; }
[MaxLength(200)]
public string District1 { get; set; }
[MaxLength(200)]
public string Amphur1 { get; set; }
[MaxLength(200)]
public string Province1 { get; set; }
[MaxLength(5)]
public string ZipCode1 { get; set; }
public Recruit Recruit { get; set; }
}
}

View file

@ -0,0 +1,20 @@
using System.ComponentModel.DataAnnotations;
using BMA.EHR.Report.Service.Models;
namespace BMA.EHR.Recruit.Service.Models.Recruits
{
public class RecruitCertificate : EntityBase
{
[MaxLength(50)]
public string CertificateNo { get; set; }
[MaxLength(200)]
public string Description { get; set; }
public DateTime IssueDate { get; set; }
public DateTime ExpiredDate { get; set; }
public Recruit Recruit { get; set; }
}
}

View file

@ -0,0 +1,15 @@
using BMA.EHR.Recruit.Service.Models.Documents;
using BMA.EHR.Report.Service.Models;
using BMA.EHR.Report.Service.Models;
namespace BMA.EHR.Recruit.Service.Models.Recruits
{
public class RecruitDocument : EntityBase
{
public DateTime CreatedDate { get; set; }
public Document DocumentFile { get; set; }
public Recruit Recruit { get; set; }
}
}

View file

@ -0,0 +1,34 @@
using System.ComponentModel.DataAnnotations;
using BMA.EHR.Report.Service.Models;
namespace BMA.EHR.Recruit.Service.Models.Recruits
{
public class RecruitEducation : EntityBase
{
[MaxLength(200)]
public string Degree { get; set; }
[MaxLength(200)]
public string Major { get; set; }
[MaxLength(20)]
public string MajorGroupId { get; set; }
[MaxLength(200)]
public string MajorGroupName { get; set; }
[MaxLength(200)]
public string University { get; set; }
public double GPA { get; set; } = 0.0;
[MaxLength(1000)]
public string Specialist { get; set; }
[MaxLength(200)]
public string HighDegree { get; set; }
public DateTime BachelorDate { get; set; }
public Recruit Recruit { get; set; }
}
}

View file

@ -0,0 +1,28 @@
using BMA.EHR.Recruit.Service.Models.Documents;
using Microsoft.EntityFrameworkCore;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using BMA.EHR.Report.Service.Models;
namespace BMA.EHR.Recruit.Service.Models.Recruits
{
public class RecruitImport : EntityBase
{
[Required, Comment("ปีที่จัดการสอบ"), Column(Order = 1)]
public int Year { get; set; }
[Required, MaxLength(250), Comment("ชื่อการสอบ"), Column(Order = 2)]
public string Name { get; set; } = string.Empty;
[Required, Comment("ครั้งที่"), Column(Order = 3)]
public int Order { get; set; } = 1;
public Document ImportFile { get; set; } = new Document();
public List<Recruit> Recruits { get; set; } = new List<Recruit>();
public ScoreImport ScoreImport { get; set; }
public List<RecruitImportHistory> ImportHostories { get; set; } = new List<RecruitImportHistory>();
}
}

View file

@ -0,0 +1,15 @@
using Microsoft.EntityFrameworkCore;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using BMA.EHR.Report.Service.Models;
namespace BMA.EHR.Recruit.Service.Models.Recruits
{
public class RecruitImportHistory : EntityBase
{
[Required, Comment("รายละเอียดการนำเข้า"), Column(Order = 1)]
public string Description { get; set; } = string.Empty;
public RecruitImport RecruitImport { get; set; }
}
}

View file

@ -0,0 +1,25 @@
using System.ComponentModel.DataAnnotations;
using BMA.EHR.Report.Service.Models;
namespace BMA.EHR.Recruit.Service.Models.Recruits
{
public class RecruitOccupation : EntityBase
{
[MaxLength(200)]
public string Occupation { get; set; }
[MaxLength(200)]
public string WorkAge { get; set; }
[MaxLength(200)]
public string Position { get; set; }
[MaxLength(200)]
public string Workplace { get; set; }
[MaxLength(200)]
public string Telephone { get; set; }
public Recruit Recruit { get; set; }
}
}

View file

@ -0,0 +1,57 @@
using System.ComponentModel.DataAnnotations;
using BMA.EHR.Report.Service.Models;
namespace BMA.EHR.Recruit.Service.Models.Recruits
{
public class RecruitPayment : EntityBase
{
[MaxLength(50)]
public string PaymentId { get; set; }
[MaxLength(50)]
public string CompanyCode { get; set; }
[MaxLength(50)]
public string TextFile { get; set; }
[MaxLength(50)]
public string BankCode { get; set; }
[MaxLength(50)]
public string AccountNumber { get; set; }
[MaxLength(50)]
public string TransDate { get; set; }
[MaxLength(50)]
public string TransTime { get; set; }
[MaxLength(200)]
public string CustomerName { get; set; }
[MaxLength(50)]
public string RefNo1 { get; set; }
[MaxLength(50)]
public string TermBranch { get; set; }
[MaxLength(50)]
public string TellerId { get; set; }
[MaxLength(50)]
public string CreditDebit { get; set; }
[MaxLength(50)]
public string PaymentType { get; set; }
[MaxLength(50)]
public string ChequeNo { get; set; }
public decimal Amount { get; set; }
[MaxLength(50)]
public string ChqueBankCode { get; set; }
public Recruit Recruit { get; set; }
}
}

View file

@ -0,0 +1,42 @@
using System.ComponentModel.DataAnnotations;
using BMA.EHR.Report.Service.Models;
namespace BMA.EHR.Recruit.Service.Models.Recruits
{
public class RecruitScore : EntityBase
{
[Required, MaxLength(50)]
public string ExamId { get; set; }
public int SumA { get; set; }
public int FullA { get; set; }
public double PercentageA { get; set; }
public int SumB { get; set; }
public int FullB { get; set; }
public double PercentageB { get; set; }
public int SumAB { get; set; }
[Required, MaxLength(50)]
public string ABStatus { get; set; }
public int SumC { get; set; }
public int FullC { get; set; }
public double PercentageC { get; set; }
[Required, MaxLength(50)]
public string ExamStatus { get; set; }
[MaxLength(200)]
public string Major { get; set; }
public ScoreImport ScoreImport { get; set; }
}
}

View file

@ -0,0 +1,20 @@
using BMA.EHR.Recruit.Service.Models.Documents;
using System.ComponentModel.DataAnnotations.Schema;
using BMA.EHR.Report.Service.Models;
namespace BMA.EHR.Recruit.Service.Models.Recruits
{
public class ScoreImport : EntityBase
{
public int Year { get; set; }
public Document ImportFile { get; set; } = new Document();
public virtual List<RecruitScore> Scores { get; set; } = new List<RecruitScore>();
[ForeignKey("FK_Score_Import_ID")]
public Guid RecruitImportId { get; set; }
public RecruitImport RecruitImport { get; set; }
}
}

View file

@ -1,25 +1,164 @@
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Mvc.Versioning;
using Microsoft.AspNetCore.Mvc;
using Microsoft.IdentityModel.Logging;
using Microsoft.IdentityModel.Tokens;
using System.Text;
using Microsoft.EntityFrameworkCore;
using MongoDB.Bson.Serialization.Serializers;
using Serilog;
using Serilog.Exceptions;
using Serilog.Sinks.Elasticsearch;
using System.Reflection;
using BMA.EHR.Report.Service.Data;
using MongoDB.Bson;
using MongoDB.Bson.Serialization;
using BMA.EHR.Report.Service;
using Microsoft.AspNetCore.Mvc.ApiExplorer;
var builder = WebApplication.CreateBuilder(args);
var issuer = builder.Configuration["Jwt:Issuer"];
var key = builder.Configuration["Jwt:Key"];
IdentityModelEventSource.ShowPII = true;
builder.Services.AddHttpContextAccessor();
builder.Services.AddApiVersioning(opt =>
{
opt.DefaultApiVersion = new ApiVersion(1, 0);
opt.AssumeDefaultVersionWhenUnspecified = true;
opt.ReportApiVersions = true;
opt.ApiVersionReader = ApiVersionReader.Combine(new UrlSegmentApiVersionReader(),
new HeaderApiVersionReader("x-api-version"),
new MediaTypeApiVersionReader("x-api-version"));
});
builder.Services.AddVersionedApiExplorer(setup =>
{
setup.GroupNameFormat = "'v'VVV";
setup.SubstituteApiVersionInUrl = true;
});
builder.Services.AddEndpointsApiExplorer();
// Authorization
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme).AddJwtBearer(opt =>
{
opt.RequireHttpsMetadata = false; //false for dev
opt.Authority = issuer;
opt.TokenValidationParameters = new()
{
ValidateIssuer = true,
ValidateAudience = false,
ValidateLifetime = true,
ValidateIssuerSigningKey = true,
ValidIssuer = issuer,
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(key))
};
});
builder.Services.AddAuthorization();
// use serilog
ConfigureLogs();
builder.Host.UseSerilog();
BsonSerializer.RegisterSerializer(new GuidSerializer(BsonType.String));
BsonSerializer.RegisterSerializer(new DateTimeSerializer(BsonType.String));
// Register DbContext
var recruitConnection = builder.Configuration.GetConnectionString("RecruitConnection");
builder.Services.AddDbContext<ApplicationDbContext>(options =>
options.UseMySql(recruitConnection, ServerVersion.AutoDetect(recruitConnection), o => o.MigrationsHistoryTable("__ReportMigrationsHistory"))
);
// Add config CORS
builder.Services.AddCors(options => options.AddDefaultPolicy(builder =>
{
builder
.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader()
.SetIsOriginAllowedToAllowWildcardSubdomains();
}));
// Register Service
//builder.Services.AddTransient<ProfileService>();
//builder.Services.AddTransient<MinIOService>();
// Add services to the container.
builder.Services.AddControllers(options =>
{
options.SuppressAsyncSuffixInActionNames = false;
})
.AddNewtonsoftJson(x => x.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore);
builder.Services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
builder.Services.ConfigureOptions<ConfigureSwaggerOptions>();
builder.Services.AddHealthChecks();
var app = builder.Build();
// Configure the HTTP request pipeline.
var apiVersionDescriptionProvider = app.Services.GetRequiredService<IApiVersionDescriptionProvider>();
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
app.UseSwaggerUI(options =>
{
foreach (var description in apiVersionDescriptionProvider.ApiVersionDescriptions)
{
options.SwaggerEndpoint($"/swagger/{description.GroupName}/swagger.json",
description.GroupName.ToUpperInvariant());
}
});
}
app.MapHealthChecks("/health");
app.UseHttpsRedirection();
app.UseCors();
app.UseAuthentication();
app.UseAuthorization();
app.UseDefaultFiles();
app.UseStaticFiles();
app.MapControllers();
// apply migrations
await using var scope = app.Services.CreateAsyncScope();
await using var db = scope.ServiceProvider.GetRequiredService<ApplicationDbContext>();
await db.Database.MigrateAsync();
app.Run();
void ConfigureLogs()
{
var environment = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT");
var configuration = new ConfigurationBuilder()
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
.AddJsonFile(
$"appsettings.{Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT")}.json",
optional: true)
.Build();
Log.Logger = new LoggerConfiguration()
.Enrich.FromLogContext()
// .WriteTo.Debug()
.MinimumLevel.Error()
.WriteTo.Console()
.Enrich.WithExceptionDetails()
// .Enrich.WithEnvironmentUserName()
.WriteTo.Elasticsearch(ConfigureElasticSink(configuration, environment ?? ""))
.Enrich.WithProperty("Environment", environment)
.ReadFrom.Configuration(configuration)
.CreateLogger();
}
ElasticsearchSinkOptions ConfigureElasticSink(IConfigurationRoot configuration, string environment)
{
return new ElasticsearchSinkOptions(new Uri(configuration["ElasticConfiguration:Uri"] ?? ""))
{
AutoRegisterTemplate = true,
IndexFormat = $"{Assembly.GetExecutingAssembly()?.GetName()?.Name?.ToLower().Replace(".", "-")}-{environment?.ToLower().Replace(".", "-")}"
};
}

Binary file not shown.

View file

@ -0,0 +1,13 @@
using System.Net;
namespace BMA.EHR.Report.Service.Responses
{
public class ResponseObject
{
public int Status { get; set; }
public string? Message { get; set; }
public object? Result { get; set; }
}
}

View file

@ -1,13 +0,0 @@
namespace BMA.EHR.Report.Service
{
public class WeatherForecast
{
public DateOnly Date { get; set; }
public int TemperatureC { get; set; }
public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
public string? Summary { get; set; }
}
}

View file

@ -1,8 +1,34 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
"Serilog": {
"MinimumLevel": {
"Default": "Information",
"Override": {
"Microsoft": "Information",
"System": "Warning"
}
}
},
"ElasticConfiguration": {
"Uri": "http://localhost:9200"
},
"AllowedHosts": "*",
"ConnectionStrings": {
"MongoConnection": "mongodb://admin:adminVM123@127.0.0.1:27017",
"RecruitConnection": "server=127.0.0.1;user=root;password=P@ssw0rd;port=3308;database=bma_recruit;Convert Zero Datetime=True;Allow User Variables=true;Pooling=True;"
},
"Jwt": {
"Key": "HP-FnQMUj9msHMSD3T9HtdEnphAKoCJLEl85CIqROFI",
"Issuer": "https://identity.frappet.com/realms/bma-ehr"
},
"EPPlus": {
"ExcelPackage": {
"LicenseContext": "NonCommercial"
}
},
"MinIO": {
"Endpoint": "http://127.0.0.1:9000",
"AccessKey": "XCiP1ubSyuGS5yDT",
"SecretKey": "LFnSRyk144oJERvump8UDxPcjjEyzgum",
"BucketName": "bma-recruit"
}
}
}
}

View file

@ -1,9 +1,34 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
"Serilog": {
"MinimumLevel": {
"Default": "Information",
"Override": {
"Microsoft": "Information",
"System": "Warning"
}
}
},
"ElasticConfiguration": {
"Uri": "http://localhost:9200"
},
"AllowedHosts": "*",
"ConnectionStrings": {
"MongoConnection": "mongodb://admin:adminVM123@127.0.0.1:27017",
"RecruitConnection": "server=127.0.0.1;user=root;password=P@ssw0rd;port=3308;database=bma_recruit;Convert Zero Datetime=True;Allow User Variables=true;Pooling=True;"
},
"Jwt": {
"Key": "HP-FnQMUj9msHMSD3T9HtdEnphAKoCJLEl85CIqROFI",
"Issuer": "https://identity.frappet.com/realms/bma-ehr"
},
"EPPlus": {
"ExcelPackage": {
"LicenseContext": "NonCommercial"
}
},
"MinIO": {
"Endpoint": "http://127.0.0.1:9000",
"AccessKey": "XCiP1ubSyuGS5yDT",
"SecretKey": "LFnSRyk144oJERvump8UDxPcjjEyzgum",
"BucketName": "bma-recruit"
}
},
"AllowedHosts": "*"
}
}

10
nuget.config Normal file
View file

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<packageSources>
<!--To inherit the global NuGet package sources remove the <clear/> line below -->
<clear />
<add key="nuget" value="https://api.nuget.org/v3/index.json" />
<add key="private_nuget" value="https://nuget.frappet.synology.me/v3/index.json" />
<add key="Components" value="./Components" />
</packageSources>
</configuration>