Add project files.

This commit is contained in:
Suphonchai Phoonsawat 2023-06-05 20:22:51 +07:00
parent cc6b248537
commit 717b0f0a8e
31 changed files with 1296 additions and 0 deletions

25
.dockerignore Normal file
View file

@ -0,0 +1,25 @@
**/.classpath
**/.dockerignore
**/.env
**/.git
**/.gitignore
**/.project
**/.settings
**/.toolstarget
**/.vs
**/.vscode
**/*.*proj.user
**/*.dbmdl
**/*.jfm
**/azds.yaml
**/bin
**/charts
**/docker-compose*
**/Dockerfile*
**/node_modules
**/npm-debug.log
**/obj
**/secrets.dev.yaml
**/values.dev.yaml
LICENSE
README.md

View file

@ -0,0 +1,16 @@
using BMA.EHR.Application.Repositories;
using Microsoft.Extensions.DependencyInjection;
namespace BMA.EHR.Application
{
public static class ApplicationServicesRegistration
{
public static IServiceCollection AddApplication(this IServiceCollection services)
{
services.AddTransient<PrefixRepository>();
services.AddTransient<BloodGroupRepository>();
return services;
}
}
}

View file

@ -0,0 +1,19 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="7.0.5" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="7.0.0" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\BMA.EHR.Domain\BMA.EHR.Domain.csproj" />
</ItemGroup>
</Project>

View file

@ -0,0 +1,14 @@
using BMA.EHR.Domain.Entities.MetaData;
using Microsoft.EntityFrameworkCore;
namespace BMA.EHR.Application.Common.Interfaces
{
public interface IApplicationDBContext
{
DbSet<PrefixEntity> Prefixes { get; set; }
DbSet<BloodGroupEntity> BloodGroups { get; set; }
Task<int> SaveChangesAsync();
}
}

View file

@ -0,0 +1,9 @@
namespace BMA.EHR.Application.Common.Interfaces
{
public interface IGenericRepository<S,T> where T : class
{
Task<T?> GetByIdAsync(S id);
Task<IReadOnlyList<T>> GetAllAsync();
}
}

View file

@ -0,0 +1,26 @@
using BMA.EHR.Application.Common.Interfaces;
using BMA.EHR.Domain.Entities.MetaData;
using Microsoft.EntityFrameworkCore;
namespace BMA.EHR.Application.Repositories
{
public class BloodGroupRepository : IGenericRepository<Guid, BloodGroupEntity>
{
private readonly IApplicationDBContext _dbContext;
public BloodGroupRepository(IApplicationDBContext dbContext)
{
_dbContext = dbContext;
}
public async Task<IReadOnlyList<BloodGroupEntity>> GetAllAsync()
{
return await _dbContext.BloodGroups.ToListAsync();
}
public async Task<BloodGroupEntity?> GetByIdAsync(Guid id)
{
return await _dbContext.BloodGroups.FirstOrDefaultAsync(x => x.Id == id);
}
}
}

View file

@ -0,0 +1,26 @@
using BMA.EHR.Application.Common.Interfaces;
using BMA.EHR.Domain.Entities.MetaData;
using Microsoft.EntityFrameworkCore;
namespace BMA.EHR.Application.Repositories
{
public class PrefixRepository : IGenericRepository<Guid, PrefixEntity>
{
private readonly IApplicationDBContext _dbContext;
public PrefixRepository(IApplicationDBContext dbContext)
{
_dbContext = dbContext;
}
public async Task<IReadOnlyList<PrefixEntity>> GetAllAsync()
{
return await _dbContext.Prefixes.ToListAsync();
}
public async Task<PrefixEntity?> GetByIdAsync(Guid id)
{
return await _dbContext.Prefixes.FirstOrDefaultAsync(x => x.Id == id);
}
}
}

View file

@ -0,0 +1,13 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore.Abstractions" Version="7.0.5" />
</ItemGroup>
</Project>

View file

@ -0,0 +1,34 @@
using BMA.EHR.Domain.Common.Interfaces;
using Microsoft.EntityFrameworkCore;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace BMA.EHR.Domain.Common
{
public abstract class BaseEntity<T> : IActivableEntity, IAuditableEntity
{
[Key, Column(Order = 0), Comment("คีย์หลัก")]
public virtual T Id { get; set; }
[Required, Column(Order = 990), Comment("สถานะการใช้งาน")]
public bool IsActive { get; set; } = true;
[Required, Column(Order = 991), Comment("User Id ที่สร้างข้อมูล")]
public Guid CreatedUserId { get; set; } = Guid.Empty;
[Required, Column(Order = 992), Comment("ชื่อ User ที่สร้างข้อมูล")]
public string CreatedUserFullName { get; set; } = string.Empty;
[Required, Column(Order = 993), Comment("สร้างข้อมูลเมื่อ")]
public DateTime CreatedDate { get; set; } = DateTime.Now;
[Column(Order = 994), Comment("User Id ที่แก้ไขข้อมูล")]
public Guid? ModifiedUserId { get; set; }
[Column(Order = 995), Comment("ชื่อ User ที่แก้ไจข้อมูล")]
public string? ModifiedUserFullName { get; set; }
[Column(Order = 996), Comment("แก้ไขข้อมูลเมื่อ")]
public DateTime? ModifiedDate { get; set; }
}
}

View file

@ -0,0 +1,7 @@
namespace BMA.EHR.Domain.Common.Interfaces
{
public interface IActivableEntity
{
bool IsActive { get; set; }
}
}

View file

@ -0,0 +1,17 @@
namespace BMA.EHR.Domain.Common.Interfaces
{
public interface IAuditableEntity
{
Guid CreatedUserId { get; set; }
string CreatedUserFullName { get; set; }
DateTime CreatedDate { get; set; }
Guid? ModifiedUserId { get; set; }
string? ModifiedUserFullName { get; set; }
DateTime? ModifiedDate { get; set; }
}
}

View file

@ -0,0 +1,13 @@
using BMA.EHR.Domain.Common;
using Microsoft.EntityFrameworkCore;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace BMA.EHR.Domain.Entities.MetaData
{
public class BloodGroupEntity : BaseEntity<Guid>
{
[Required, MaxLength(2), Column(Order = 1), Comment("ชื่อหมู่โลหิต")]
public string Name { get; set; } = string.Empty;
}
}

View file

@ -0,0 +1,13 @@
using BMA.EHR.Domain.Common;
using Microsoft.EntityFrameworkCore;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace BMA.EHR.Domain.Entities.MetaData
{
public class PrefixEntity : BaseEntity<Guid>
{
[Required, MaxLength(100), Column(Order = 1), Comment("รายละเอียดคำนำหน้า")]
public string Name { get; set; } = string.Empty;
}
}

View file

@ -0,0 +1,26 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="7.0.5">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="7.0.5">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="7.0.0" />
<PackageReference Include="Oracle.EntityFrameworkCore" Version="7.21.9" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\BMA.EHR.Application\BMA.EHR.Application.csproj" />
</ItemGroup>
</Project>

View file

@ -0,0 +1,23 @@
using BMA.EHR.Application.Common.Interfaces;
using BMA.EHR.Infrastructure.Persistence;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
namespace BMA.EHR.Infrastructure
{
public static class InfrastructureServiceRegistration
{
public static IServiceCollection AddPersistence(this IServiceCollection services,
IConfiguration configuration)
{
services.AddDbContext<ApplicationDBContext>(options =>
options.UseOracle(configuration.GetConnectionString("DefaultConnection"),
b => b.MigrationsAssembly(typeof(ApplicationDBContext).Assembly.FullName)), ServiceLifetime.Transient);
services.AddScoped<IApplicationDBContext>(provider => provider.GetService<ApplicationDBContext>());
return services;
}
}
}

View file

@ -0,0 +1,142 @@
// <auto-generated />
using System;
using BMA.EHR.Infrastructure.Persistence;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Oracle.EntityFrameworkCore.Metadata;
#nullable disable
namespace BMA.EHR.Infrastructure.Migrations
{
[DbContext(typeof(ApplicationDBContext))]
[Migration("20230605123842_Initial Database")]
partial class InitialDatabase
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "7.0.5")
.HasAnnotation("Relational:MaxIdentifierLength", 128);
OracleModelBuilderExtensions.UseIdentityColumns(modelBuilder);
modelBuilder.Entity("BMA.EHR.Domain.Entities.MetaData.BloodGroupEntity", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("RAW(16)")
.HasColumnOrder(0)
.HasComment("คีย์หลัก");
b.Property<DateTime>("CreatedDate")
.HasColumnType("TIMESTAMP(7)")
.HasColumnOrder(993)
.HasComment("สร้างข้อมูลเมื่อ");
b.Property<string>("CreatedUserFullName")
.IsRequired()
.HasColumnType("NVARCHAR2(2000)")
.HasColumnOrder(992)
.HasComment("ชื่อ User ที่สร้างข้อมูล");
b.Property<Guid>("CreatedUserId")
.HasColumnType("RAW(16)")
.HasColumnOrder(991)
.HasComment("User Id ที่สร้างข้อมูล");
b.Property<bool>("IsActivable")
.HasColumnType("NUMBER(1)")
.HasColumnOrder(990)
.HasComment("สถานะการใช้งาน");
b.Property<DateTime?>("ModifiedDate")
.HasColumnType("TIMESTAMP(7)")
.HasColumnOrder(996)
.HasComment("แก้ไขข้อมูลเมื่อ");
b.Property<string>("ModifiedUserFullName")
.HasColumnType("NVARCHAR2(2000)")
.HasColumnOrder(995)
.HasComment("ชื่อ User ที่แก้ไจข้อมูล");
b.Property<Guid?>("ModifiedUserId")
.HasColumnType("RAW(16)")
.HasColumnOrder(994)
.HasComment("User Id ที่แก้ไขข้อมูล");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(2)
.HasColumnType("NVARCHAR2(2)")
.HasColumnOrder(1)
.HasComment("ชื่อหมู่โลหิต");
b.HasKey("Id");
b.ToTable("BloodGroups");
});
modelBuilder.Entity("BMA.EHR.Domain.Entities.MetaData.PrefixEntity", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("RAW(16)")
.HasColumnOrder(0)
.HasComment("คีย์หลัก");
b.Property<DateTime>("CreatedDate")
.HasColumnType("TIMESTAMP(7)")
.HasColumnOrder(993)
.HasComment("สร้างข้อมูลเมื่อ");
b.Property<string>("CreatedUserFullName")
.IsRequired()
.HasColumnType("NVARCHAR2(2000)")
.HasColumnOrder(992)
.HasComment("ชื่อ User ที่สร้างข้อมูล");
b.Property<Guid>("CreatedUserId")
.HasColumnType("RAW(16)")
.HasColumnOrder(991)
.HasComment("User Id ที่สร้างข้อมูล");
b.Property<bool>("IsActivable")
.HasColumnType("NUMBER(1)")
.HasColumnOrder(990)
.HasComment("สถานะการใช้งาน");
b.Property<DateTime?>("ModifiedDate")
.HasColumnType("TIMESTAMP(7)")
.HasColumnOrder(996)
.HasComment("แก้ไขข้อมูลเมื่อ");
b.Property<string>("ModifiedUserFullName")
.HasColumnType("NVARCHAR2(2000)")
.HasColumnOrder(995)
.HasComment("ชื่อ User ที่แก้ไจข้อมูล");
b.Property<Guid?>("ModifiedUserId")
.HasColumnType("RAW(16)")
.HasColumnOrder(994)
.HasComment("User Id ที่แก้ไขข้อมูล");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("NVARCHAR2(100)")
.HasColumnOrder(1)
.HasComment("รายละเอียดคำนำหน้า");
b.HasKey("Id");
b.ToTable("Prefixes");
});
#pragma warning restore 612, 618
}
}
}

View file

@ -0,0 +1,63 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace BMA.EHR.Infrastructure.Migrations
{
/// <inheritdoc />
public partial class InitialDatabase : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "BloodGroups",
columns: table => new
{
Id = table.Column<Guid>(type: "RAW(16)", nullable: false, comment: "คีย์หลัก"),
Name = table.Column<string>(type: "NVARCHAR2(2)", maxLength: 2, nullable: false, comment: "ชื่อหมู่โลหิต"),
IsActivable = table.Column<bool>(type: "NUMBER(1)", nullable: false, comment: "สถานะการใช้งาน"),
CreatedUserId = table.Column<Guid>(type: "RAW(16)", nullable: false, comment: "User Id ที่สร้างข้อมูล"),
CreatedUserFullName = table.Column<string>(type: "NVARCHAR2(2000)", nullable: false, comment: "ชื่อ User ที่สร้างข้อมูล"),
CreatedDate = table.Column<DateTime>(type: "TIMESTAMP(7)", nullable: false, comment: "สร้างข้อมูลเมื่อ"),
ModifiedUserId = table.Column<Guid>(type: "RAW(16)", nullable: true, comment: "User Id ที่แก้ไขข้อมูล"),
ModifiedUserFullName = table.Column<string>(type: "NVARCHAR2(2000)", nullable: true, comment: "ชื่อ User ที่แก้ไจข้อมูล"),
ModifiedDate = table.Column<DateTime>(type: "TIMESTAMP(7)", nullable: true, comment: "แก้ไขข้อมูลเมื่อ")
},
constraints: table =>
{
table.PrimaryKey("PK_BloodGroups", x => x.Id);
});
migrationBuilder.CreateTable(
name: "Prefixes",
columns: table => new
{
Id = table.Column<Guid>(type: "RAW(16)", nullable: false, comment: "คีย์หลัก"),
Name = table.Column<string>(type: "NVARCHAR2(100)", maxLength: 100, nullable: false, comment: "รายละเอียดคำนำหน้า"),
IsActivable = table.Column<bool>(type: "NUMBER(1)", nullable: false, comment: "สถานะการใช้งาน"),
CreatedUserId = table.Column<Guid>(type: "RAW(16)", nullable: false, comment: "User Id ที่สร้างข้อมูล"),
CreatedUserFullName = table.Column<string>(type: "NVARCHAR2(2000)", nullable: false, comment: "ชื่อ User ที่สร้างข้อมูล"),
CreatedDate = table.Column<DateTime>(type: "TIMESTAMP(7)", nullable: false, comment: "สร้างข้อมูลเมื่อ"),
ModifiedUserId = table.Column<Guid>(type: "RAW(16)", nullable: true, comment: "User Id ที่แก้ไขข้อมูล"),
ModifiedUserFullName = table.Column<string>(type: "NVARCHAR2(2000)", nullable: true, comment: "ชื่อ User ที่แก้ไจข้อมูล"),
ModifiedDate = table.Column<DateTime>(type: "TIMESTAMP(7)", nullable: true, comment: "แก้ไขข้อมูลเมื่อ")
},
constraints: table =>
{
table.PrimaryKey("PK_Prefixes", x => x.Id);
});
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "BloodGroups");
migrationBuilder.DropTable(
name: "Prefixes");
}
}
}

View file

@ -0,0 +1,142 @@
// <auto-generated />
using System;
using BMA.EHR.Infrastructure.Persistence;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Oracle.EntityFrameworkCore.Metadata;
#nullable disable
namespace BMA.EHR.Infrastructure.Migrations
{
[DbContext(typeof(ApplicationDBContext))]
[Migration("20230605131808_Change Field Name")]
partial class ChangeFieldName
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "7.0.5")
.HasAnnotation("Relational:MaxIdentifierLength", 128);
OracleModelBuilderExtensions.UseIdentityColumns(modelBuilder);
modelBuilder.Entity("BMA.EHR.Domain.Entities.MetaData.BloodGroupEntity", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("RAW(16)")
.HasColumnOrder(0)
.HasComment("คีย์หลัก");
b.Property<DateTime>("CreatedDate")
.HasColumnType("TIMESTAMP(7)")
.HasColumnOrder(993)
.HasComment("สร้างข้อมูลเมื่อ");
b.Property<string>("CreatedUserFullName")
.IsRequired()
.HasColumnType("NVARCHAR2(2000)")
.HasColumnOrder(992)
.HasComment("ชื่อ User ที่สร้างข้อมูล");
b.Property<Guid>("CreatedUserId")
.HasColumnType("RAW(16)")
.HasColumnOrder(991)
.HasComment("User Id ที่สร้างข้อมูล");
b.Property<bool>("IsActive")
.HasColumnType("NUMBER(1)")
.HasColumnOrder(990)
.HasComment("สถานะการใช้งาน");
b.Property<DateTime?>("ModifiedDate")
.HasColumnType("TIMESTAMP(7)")
.HasColumnOrder(996)
.HasComment("แก้ไขข้อมูลเมื่อ");
b.Property<string>("ModifiedUserFullName")
.HasColumnType("NVARCHAR2(2000)")
.HasColumnOrder(995)
.HasComment("ชื่อ User ที่แก้ไจข้อมูล");
b.Property<Guid?>("ModifiedUserId")
.HasColumnType("RAW(16)")
.HasColumnOrder(994)
.HasComment("User Id ที่แก้ไขข้อมูล");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(2)
.HasColumnType("NVARCHAR2(2)")
.HasColumnOrder(1)
.HasComment("ชื่อหมู่โลหิต");
b.HasKey("Id");
b.ToTable("BloodGroups");
});
modelBuilder.Entity("BMA.EHR.Domain.Entities.MetaData.PrefixEntity", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("RAW(16)")
.HasColumnOrder(0)
.HasComment("คีย์หลัก");
b.Property<DateTime>("CreatedDate")
.HasColumnType("TIMESTAMP(7)")
.HasColumnOrder(993)
.HasComment("สร้างข้อมูลเมื่อ");
b.Property<string>("CreatedUserFullName")
.IsRequired()
.HasColumnType("NVARCHAR2(2000)")
.HasColumnOrder(992)
.HasComment("ชื่อ User ที่สร้างข้อมูล");
b.Property<Guid>("CreatedUserId")
.HasColumnType("RAW(16)")
.HasColumnOrder(991)
.HasComment("User Id ที่สร้างข้อมูล");
b.Property<bool>("IsActive")
.HasColumnType("NUMBER(1)")
.HasColumnOrder(990)
.HasComment("สถานะการใช้งาน");
b.Property<DateTime?>("ModifiedDate")
.HasColumnType("TIMESTAMP(7)")
.HasColumnOrder(996)
.HasComment("แก้ไขข้อมูลเมื่อ");
b.Property<string>("ModifiedUserFullName")
.HasColumnType("NVARCHAR2(2000)")
.HasColumnOrder(995)
.HasComment("ชื่อ User ที่แก้ไจข้อมูล");
b.Property<Guid?>("ModifiedUserId")
.HasColumnType("RAW(16)")
.HasColumnOrder(994)
.HasComment("User Id ที่แก้ไขข้อมูล");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("NVARCHAR2(100)")
.HasColumnOrder(1)
.HasComment("รายละเอียดคำนำหน้า");
b.HasKey("Id");
b.ToTable("Prefixes");
});
#pragma warning restore 612, 618
}
}
}

View file

@ -0,0 +1,38 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace BMA.EHR.Infrastructure.Migrations
{
/// <inheritdoc />
public partial class ChangeFieldName : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.RenameColumn(
name: "IsActivable",
table: "Prefixes",
newName: "IsActive");
migrationBuilder.RenameColumn(
name: "IsActivable",
table: "BloodGroups",
newName: "IsActive");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.RenameColumn(
name: "IsActive",
table: "Prefixes",
newName: "IsActivable");
migrationBuilder.RenameColumn(
name: "IsActive",
table: "BloodGroups",
newName: "IsActivable");
}
}
}

View file

@ -0,0 +1,139 @@
// <auto-generated />
using System;
using BMA.EHR.Infrastructure.Persistence;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Oracle.EntityFrameworkCore.Metadata;
#nullable disable
namespace BMA.EHR.Infrastructure.Migrations
{
[DbContext(typeof(ApplicationDBContext))]
partial class ApplicationDBContextModelSnapshot : ModelSnapshot
{
protected override void BuildModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "7.0.5")
.HasAnnotation("Relational:MaxIdentifierLength", 128);
OracleModelBuilderExtensions.UseIdentityColumns(modelBuilder);
modelBuilder.Entity("BMA.EHR.Domain.Entities.MetaData.BloodGroupEntity", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("RAW(16)")
.HasColumnOrder(0)
.HasComment("คีย์หลัก");
b.Property<DateTime>("CreatedDate")
.HasColumnType("TIMESTAMP(7)")
.HasColumnOrder(993)
.HasComment("สร้างข้อมูลเมื่อ");
b.Property<string>("CreatedUserFullName")
.IsRequired()
.HasColumnType("NVARCHAR2(2000)")
.HasColumnOrder(992)
.HasComment("ชื่อ User ที่สร้างข้อมูล");
b.Property<Guid>("CreatedUserId")
.HasColumnType("RAW(16)")
.HasColumnOrder(991)
.HasComment("User Id ที่สร้างข้อมูล");
b.Property<bool>("IsActive")
.HasColumnType("NUMBER(1)")
.HasColumnOrder(990)
.HasComment("สถานะการใช้งาน");
b.Property<DateTime?>("ModifiedDate")
.HasColumnType("TIMESTAMP(7)")
.HasColumnOrder(996)
.HasComment("แก้ไขข้อมูลเมื่อ");
b.Property<string>("ModifiedUserFullName")
.HasColumnType("NVARCHAR2(2000)")
.HasColumnOrder(995)
.HasComment("ชื่อ User ที่แก้ไจข้อมูล");
b.Property<Guid?>("ModifiedUserId")
.HasColumnType("RAW(16)")
.HasColumnOrder(994)
.HasComment("User Id ที่แก้ไขข้อมูล");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(2)
.HasColumnType("NVARCHAR2(2)")
.HasColumnOrder(1)
.HasComment("ชื่อหมู่โลหิต");
b.HasKey("Id");
b.ToTable("BloodGroups");
});
modelBuilder.Entity("BMA.EHR.Domain.Entities.MetaData.PrefixEntity", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("RAW(16)")
.HasColumnOrder(0)
.HasComment("คีย์หลัก");
b.Property<DateTime>("CreatedDate")
.HasColumnType("TIMESTAMP(7)")
.HasColumnOrder(993)
.HasComment("สร้างข้อมูลเมื่อ");
b.Property<string>("CreatedUserFullName")
.IsRequired()
.HasColumnType("NVARCHAR2(2000)")
.HasColumnOrder(992)
.HasComment("ชื่อ User ที่สร้างข้อมูล");
b.Property<Guid>("CreatedUserId")
.HasColumnType("RAW(16)")
.HasColumnOrder(991)
.HasComment("User Id ที่สร้างข้อมูล");
b.Property<bool>("IsActive")
.HasColumnType("NUMBER(1)")
.HasColumnOrder(990)
.HasComment("สถานะการใช้งาน");
b.Property<DateTime?>("ModifiedDate")
.HasColumnType("TIMESTAMP(7)")
.HasColumnOrder(996)
.HasComment("แก้ไขข้อมูลเมื่อ");
b.Property<string>("ModifiedUserFullName")
.HasColumnType("NVARCHAR2(2000)")
.HasColumnOrder(995)
.HasComment("ชื่อ User ที่แก้ไจข้อมูล");
b.Property<Guid?>("ModifiedUserId")
.HasColumnType("RAW(16)")
.HasColumnOrder(994)
.HasComment("User Id ที่แก้ไขข้อมูล");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("NVARCHAR2(100)")
.HasColumnOrder(1)
.HasComment("รายละเอียดคำนำหน้า");
b.HasKey("Id");
b.ToTable("Prefixes");
});
#pragma warning restore 612, 618
}
}
}

View file

@ -0,0 +1,22 @@
using BMA.EHR.Application.Common.Interfaces;
using BMA.EHR.Domain.Entities.MetaData;
using Microsoft.EntityFrameworkCore;
namespace BMA.EHR.Infrastructure.Persistence
{
public class ApplicationDBContext : DbContext, IApplicationDBContext
{
public ApplicationDBContext(DbContextOptions<ApplicationDBContext> options)
: base(options)
{
}
public DbSet<PrefixEntity> Prefixes { get; set; }
public DbSet<BloodGroupEntity> BloodGroups { get; set; }
public Task<int> SaveChangesAsync()
{
return base.SaveChangesAsync();
}
}
}

View file

@ -0,0 +1,44 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<UserSecretsId>aba35659-832c-421f-a7c1-80acb6ab6f0c</UserSecretsId>
<DockerDefaultTargetOS>Linux</DockerDefaultTargetOS>
<GenerateDocumentationFile>True</GenerateDocumentationFile>
<DockerfileContext>.</DockerfileContext>
<RootNamespace>BMA.EHR.MetaData.Service</RootNamespace>
</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.1.0" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Versioning.ApiExplorer" Version="5.1.0" />
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="7.0.5" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="7.0.5">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.IdentityModel.Logging" Version="6.30.1" />
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.18.1" />
<PackageReference Include="runtime.osx.10.10-x64.CoreCompat.System.Drawing" Version="6.0.5.128" />
<PackageReference Include="Serilog.AspNetCore" Version="6.1.0" />
<PackageReference Include="Serilog.Sinks.Console" Version="4.1.0" />
<PackageReference Include="Sentry.AspNetCore" Version="3.24.0" />
<PackageReference Include="Serilog.Enrichers.Environment" Version="2.2.0" />
<PackageReference Include="Serilog.Exceptions" Version="8.4.0" />
<PackageReference Include="Serilog.Sinks.Debug" Version="2.0.0" />
<PackageReference Include="Serilog.Sinks.Elasticsearch" Version="8.4.1" />
<PackageReference Include="Swashbuckle.AspNetCore.Annotations" Version="6.4.0" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.4.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\BMA.EHR.Infrastructure\BMA.EHR.Infrastructure.csproj" />
</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.MetaData.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 Metadata 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,26 @@
using BMA.EHR.Application.Repositories;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
namespace BMA.EHR.MetaData.Service.Controllers
{
[Route("api/prefix")]
[ApiController]
public class PrefixController : ControllerBase
{
private readonly PrefixRepository _prefixRepository;
public PrefixController(PrefixRepository prefixRepository)
{
_prefixRepository = prefixRepository;
}
[HttpGet]
public async Task<IActionResult> GetAllAsync()
{
var data = await _prefixRepository.GetAllAsync();
return Ok(data);
}
}
}

View file

@ -0,0 +1,22 @@
#See https://aka.ms/customizecontainer to learn how to customize your debug container and how Visual Studio uses this Dockerfile to build your images for faster debugging.
FROM mcr.microsoft.com/dotnet/aspnet:7.0 AS base
WORKDIR /app
EXPOSE 80
EXPOSE 443
FROM mcr.microsoft.com/dotnet/sdk:7.0 AS build
WORKDIR /src
COPY ["BMA.EHR.MetaData.Service/BMA.EHR.MetaData.Service.csproj", "BMA.EHR.MetaData.Service/"]
RUN dotnet restore "BMA.EHR.MetaData.Service/BMA.EHR.MetaData.Service.csproj"
COPY . .
WORKDIR "/src/BMA.EHR.MetaData.Service"
RUN dotnet build "BMA.EHR.MetaData.Service.csproj" -c Release -o /app/build
FROM build AS publish
RUN dotnet publish "BMA.EHR.MetaData.Service.csproj" -c Release -o /app/publish /p:UseAppHost=false
FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "BMA.EHR.MetaData.Service.dll"]

View file

@ -0,0 +1,158 @@
using BMA.EHR.Application;
using BMA.EHR.Infrastructure;
using Microsoft.AspNetCore.Mvc.Versioning;
using Microsoft.AspNetCore.Mvc;
using Microsoft.IdentityModel.Logging;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.IdentityModel.Tokens;
using System.Text;
using Serilog.Sinks.Elasticsearch;
using Serilog;
using System.Reflection;
using Serilog.Exceptions;
using BMA.EHR.MetaData.Service;
using Microsoft.AspNetCore.Mvc.ApiExplorer;
using BMA.EHR.Infrastructure.Persistence;
using Microsoft.EntityFrameworkCore;
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 = false, //false for dev
ValidateAudience = false, //false for dev
ValidateLifetime = false, //false for dev
ValidateIssuerSigningKey = true,
ValidIssuer = issuer,
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(key))
};
});
builder.Services.AddAuthorization();
// use serilog
ConfigureLogs();
builder.Host.UseSerilog();
// Add config CORS
builder.Services.AddCors(options => options.AddDefaultPolicy(builder =>
{
builder
.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader()
.SetIsOriginAllowedToAllowWildcardSubdomains();
}));
// Add services to the container.
builder.Services.AddApplication();
builder.Services.AddPersistence(builder.Configuration);
builder.Services.AddControllers(options =>
{
options.SuppressAsyncSuffixInActionNames = false;
})
.AddNewtonsoftJson(x => x.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore);
builder.Services.AddSwaggerGen();
builder.Services.ConfigureOptions<ConfigureSwaggerOptions>();
builder.Services.AddHealthChecks();
}
var app = builder.Build();
{
var apiVersionDescriptionProvider = app.Services.GetRequiredService<IApiVersionDescriptionProvider>();
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
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()
.MinimumLevel.Error()
.WriteTo.Console()
.Enrich.WithExceptionDetails()
.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(".", "-")}"
};
}

View file

@ -0,0 +1,48 @@
{
"profiles": {
"http": {
"commandName": "Project",
"launchBrowser": true,
"launchUrl": "swagger",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
},
"dotnetRunMessages": true,
"applicationUrl": "http://localhost:5243"
},
"https": {
"commandName": "Project",
"launchBrowser": true,
"launchUrl": "swagger",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
},
"dotnetRunMessages": true,
"applicationUrl": "https://localhost:7168;http://localhost:5243"
},
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"launchUrl": "swagger",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"Docker": {
"commandName": "Docker",
"launchBrowser": true,
"launchUrl": "{Scheme}://{ServiceHost}:{ServicePort}/swagger",
"publishAllPorts": true,
"useSSL": true
}
},
"$schema": "https://json.schemastore.org/launchsettings.json",
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:6604",
"sslPort": 44319
}
}
}

View file

@ -0,0 +1,8 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
}
}

View file

@ -0,0 +1,27 @@
{
"Serilog": {
"MinimumLevel": {
"Default": "Information",
"Override": {
"Microsoft": "Information",
"System": "Warning"
}
}
},
"ElasticConfiguration": {
"Uri": "http://localhost:9200"
},
"AllowedHosts": "*",
"ConnectionStrings": {
"DefaultConnection": "User Id=system;Password=P@ssw0rd;Data Source=localhost:1521/ORCLCDB"
},
"Jwt": {
"Key": "HP-FnQMUj9msHMSD3T9HtdEnphAKoCJLEl85CIqROFI",
"Issuer": "https://identity.frappet.com/realms/bma-ehr"
},
"EPPlus": {
"ExcelPackage": {
"LicenseContext": "NonCommercial"
}
}
}

View file

@ -0,0 +1,9 @@
<?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" />
</packageSources>
</configuration>

43
BMA.EHR.Solution.sln Normal file
View file

@ -0,0 +1,43 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.6.33723.286
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BMA.EHR.Domain", "BMA.EHR.Domain\BMA.EHR.Domain.csproj", "{9CA80F00-2D6E-4A0B-9C4B-80CE3EDFAB96}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BMA.EHR.Application", "BMA.EHR.Application\BMA.EHR.Application.csproj", "{C9656B6D-D24B-40AD-929E-CDED3FE53DCE}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BMA.EHR.Infrastructure", "BMA.EHR.Infrastructure\BMA.EHR.Infrastructure.csproj", "{F83D3633-4A7A-432A-9E47-29378F4D175F}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BMA.EHR.MetaData.Service", "BMA.EHR.MetaData.Service\BMA.EHR.MetaData.Service.csproj", "{939DD34A-C7AE-406E-B557-33F69AC64127}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{9CA80F00-2D6E-4A0B-9C4B-80CE3EDFAB96}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{9CA80F00-2D6E-4A0B-9C4B-80CE3EDFAB96}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9CA80F00-2D6E-4A0B-9C4B-80CE3EDFAB96}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9CA80F00-2D6E-4A0B-9C4B-80CE3EDFAB96}.Release|Any CPU.Build.0 = Release|Any CPU
{C9656B6D-D24B-40AD-929E-CDED3FE53DCE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C9656B6D-D24B-40AD-929E-CDED3FE53DCE}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C9656B6D-D24B-40AD-929E-CDED3FE53DCE}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C9656B6D-D24B-40AD-929E-CDED3FE53DCE}.Release|Any CPU.Build.0 = Release|Any CPU
{F83D3633-4A7A-432A-9E47-29378F4D175F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F83D3633-4A7A-432A-9E47-29378F4D175F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F83D3633-4A7A-432A-9E47-29378F4D175F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F83D3633-4A7A-432A-9E47-29378F4D175F}.Release|Any CPU.Build.0 = Release|Any CPU
{939DD34A-C7AE-406E-B557-33F69AC64127}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{939DD34A-C7AE-406E-B557-33F69AC64127}.Debug|Any CPU.Build.0 = Debug|Any CPU
{939DD34A-C7AE-406E-B557-33F69AC64127}.Release|Any CPU.ActiveCfg = Release|Any CPU
{939DD34A-C7AE-406E-B557-33F69AC64127}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {3111A492-1818-4438-B718-75199D8E779A}
EndGlobalSection
EndGlobal