อัพโหลดเอกสารสร้างรอบสมัคร

This commit is contained in:
Kittapath 2023-04-07 11:10:15 +07:00
parent 9f115e3c72
commit c986fc1500
13 changed files with 2278 additions and 315 deletions

View file

@ -119,7 +119,7 @@ namespace BMA.EHR.Recurit.Exam.Service.Controllers
/// <response code="200">เมื่อทำการอ่านข้อมูลรอบการสมัครสอบ และ คนสมัครสอบในรอบสำเร็จ</response> /// <response code="200">เมื่อทำการอ่านข้อมูลรอบการสมัครสอบ และ คนสมัครสอบในรอบสำเร็จ</response>
/// <response code="401">ไม่ได้ Login เข้าระบบ</response> /// <response code="401">ไม่ได้ Login เข้าระบบ</response>
/// <response code="500">เมื่อเกิดข้อผิดพลาดในการทำงาน</response> /// <response code="500">เมื่อเกิดข้อผิดพลาดในการทำงาน</response>
[HttpPost] [HttpPost, DisableRequestSizeLimit]
[ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status401Unauthorized)] [ProducesResponseType(StatusCodes.Status401Unauthorized)]
[ProducesResponseType(StatusCodes.Status500InternalServerError)] [ProducesResponseType(StatusCodes.Status500InternalServerError)]
@ -127,7 +127,13 @@ namespace BMA.EHR.Recurit.Exam.Service.Controllers
{ {
try try
{ {
await _periodExamService.CreateAsync(item); if (Request.Form.Files == null || Request.Form.Files.Count == 0)
{
return Error(GlobalMessages.NoFileToUpload);
}
var files = Request.Form.Files;
await _periodExamService.CreateAsync(item, files);
return Success(); return Success();
} }
@ -146,7 +152,7 @@ namespace BMA.EHR.Recurit.Exam.Service.Controllers
/// <response code="200">เมื่อทำการอ่านข้อมูลรอบการสมัครสอบ และ คนสมัครสอบในรอบสำเร็จ</response> /// <response code="200">เมื่อทำการอ่านข้อมูลรอบการสมัครสอบ และ คนสมัครสอบในรอบสำเร็จ</response>
/// <response code="401">ไม่ได้ Login เข้าระบบ</response> /// <response code="401">ไม่ได้ Login เข้าระบบ</response>
/// <response code="500">เมื่อเกิดข้อผิดพลาดในการทำงาน</response> /// <response code="500">เมื่อเกิดข้อผิดพลาดในการทำงาน</response>
[HttpPut("{examId:length(36)}")] [HttpPut("{examId:length(36)}"), DisableRequestSizeLimit]
[ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status401Unauthorized)] [ProducesResponseType(StatusCodes.Status401Unauthorized)]
[ProducesResponseType(StatusCodes.Status500InternalServerError)] [ProducesResponseType(StatusCodes.Status500InternalServerError)]
@ -154,7 +160,14 @@ namespace BMA.EHR.Recurit.Exam.Service.Controllers
{ {
try try
{ {
await _periodExamService.UpdateAsync(examId, item); if (Request.Form.Files == null || Request.Form.Files.Count == 0)
{
return Error(GlobalMessages.NoFileToUpload);
}
var files = Request.Form.Files;
await _periodExamService.UpdateAsync(examId, item, files);
return Success(); return Success();
} }

View file

@ -40,8 +40,11 @@ namespace BMA.EHR.Recurit.Exam.Service.Data
public DbSet<Document> Documents { get; set; } public DbSet<Document> Documents { get; set; }
public DbSet<CandidateDocument> CandidateDocuments { get; set; } public DbSet<CandidateDocument> CandidateDocuments { get; set; }
public DbSet<PositionExam> PositionExams { get; set; } public DbSet<PositionExam> PositionExams { get; set; }
public DbSet<BankExam> BankExams { get; set; } public DbSet<BankExam> BankExams { get; set; }
public DbSet<PeriodExamDocument> PeriodExamDocuments { get; set; }
} }
} }

View file

@ -972,6 +972,68 @@ namespace BMA.EHR.Recurit.Exam.Service.Data.Migrations
b.ToTable("PeriodExams"); b.ToTable("PeriodExams");
}); });
modelBuilder.Entity("BMA.EHR.Recurit.Exam.Service.Models.PeriodExamDocument", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("char(36)")
.HasColumnOrder(0)
.HasComment("PrimaryKey")
.HasAnnotation("Relational:JsonPropertyName", "id");
b.Property<DateTime>("CreatedAt")
.HasColumnType("datetime(6)")
.HasColumnOrder(100)
.HasComment("สร้างข้อมูลเมื่อ");
b.Property<string>("CreatedFullName")
.IsRequired()
.HasMaxLength(200)
.HasColumnType("varchar(200)")
.HasColumnOrder(104)
.HasComment("ชื่อ User ที่สร้างข้อมูล");
b.Property<string>("CreatedUserId")
.IsRequired()
.HasMaxLength(40)
.HasColumnType("varchar(40)")
.HasColumnOrder(101)
.HasComment("User Id ที่สร้างข้อมูล");
b.Property<Guid>("DocumentId")
.HasColumnType("char(36)");
b.Property<string>("LastUpdateFullName")
.IsRequired()
.HasMaxLength(200)
.HasColumnType("varchar(200)")
.HasColumnOrder(105)
.HasComment("ชื่อ User ที่แก้ไขข้อมูลล่าสุด");
b.Property<string>("LastUpdateUserId")
.IsRequired()
.HasMaxLength(40)
.HasColumnType("varchar(40)")
.HasColumnOrder(103)
.HasComment("User Id ที่แก้ไขข้อมูลล่าสุด");
b.Property<DateTime?>("LastUpdatedAt")
.HasColumnType("datetime(6)")
.HasColumnOrder(102)
.HasComment("แก้ไขข้อมูลล่าสุดเมื่อ");
b.Property<Guid>("PeriodExamId")
.HasColumnType("char(36)");
b.HasKey("Id");
b.HasIndex("DocumentId");
b.HasIndex("PeriodExamId");
b.ToTable("PeriodExamDocuments");
});
modelBuilder.Entity("BMA.EHR.Recurit.Exam.Service.Models.PositionExam", b => modelBuilder.Entity("BMA.EHR.Recurit.Exam.Service.Models.PositionExam", b =>
{ {
b.Property<Guid>("Id") b.Property<Guid>("Id")
@ -1553,6 +1615,25 @@ namespace BMA.EHR.Recurit.Exam.Service.Data.Migrations
b.Navigation("EducationLevel"); b.Navigation("EducationLevel");
}); });
modelBuilder.Entity("BMA.EHR.Recurit.Exam.Service.Models.PeriodExamDocument", b =>
{
b.HasOne("BMA.EHR.Recurit.Exam.Service.Models.Documents.Document", "Document")
.WithMany()
.HasForeignKey("DocumentId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("BMA.EHR.Recurit.Exam.Service.Models.PeriodExam", "PeriodExam")
.WithMany("PeriodExamDocuments")
.HasForeignKey("PeriodExamId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Document");
b.Navigation("PeriodExam");
});
modelBuilder.Entity("BMA.EHR.Recurit.Exam.Service.Models.PositionExam", b => modelBuilder.Entity("BMA.EHR.Recurit.Exam.Service.Models.PositionExam", b =>
{ {
b.HasOne("BMA.EHR.Recurit.Exam.Service.Models.PeriodExam", "PeriodExam") b.HasOne("BMA.EHR.Recurit.Exam.Service.Models.PeriodExam", "PeriodExam")
@ -1584,6 +1665,8 @@ namespace BMA.EHR.Recurit.Exam.Service.Data.Migrations
b.Navigation("Candidate"); b.Navigation("Candidate");
b.Navigation("PeriodExamDocuments");
b.Navigation("PositionExam"); b.Navigation("PositionExam");
}); });

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,68 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace BMA.EHR.Recurit.Exam.Service.Migrations
{
/// <inheritdoc />
public partial class Updatetableexamadddocument : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "PeriodExamDocuments",
columns: table => new
{
Id = table.Column<Guid>(type: "char(36)", nullable: false, comment: "PrimaryKey", collation: "ascii_general_ci"),
CreatedAt = table.Column<DateTime>(type: "datetime(6)", nullable: false, comment: "สร้างข้อมูลเมื่อ"),
CreatedUserId = table.Column<string>(type: "varchar(40)", maxLength: 40, nullable: false, comment: "User Id ที่สร้างข้อมูล")
.Annotation("MySql:CharSet", "utf8mb4"),
LastUpdatedAt = table.Column<DateTime>(type: "datetime(6)", nullable: true, comment: "แก้ไขข้อมูลล่าสุดเมื่อ"),
LastUpdateUserId = table.Column<string>(type: "varchar(40)", maxLength: 40, nullable: false, comment: "User Id ที่แก้ไขข้อมูลล่าสุด")
.Annotation("MySql:CharSet", "utf8mb4"),
CreatedFullName = table.Column<string>(type: "varchar(200)", maxLength: 200, nullable: false, comment: "ชื่อ User ที่สร้างข้อมูล")
.Annotation("MySql:CharSet", "utf8mb4"),
LastUpdateFullName = table.Column<string>(type: "varchar(200)", maxLength: 200, nullable: false, comment: "ชื่อ User ที่แก้ไขข้อมูลล่าสุด")
.Annotation("MySql:CharSet", "utf8mb4"),
PeriodExamId = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
DocumentId = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci")
},
constraints: table =>
{
table.PrimaryKey("PK_PeriodExamDocuments", x => x.Id);
table.ForeignKey(
name: "FK_PeriodExamDocuments_Documents_DocumentId",
column: x => x.DocumentId,
principalTable: "Documents",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_PeriodExamDocuments_PeriodExams_PeriodExamId",
column: x => x.PeriodExamId,
principalTable: "PeriodExams",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
})
.Annotation("MySql:CharSet", "utf8mb4");
migrationBuilder.CreateIndex(
name: "IX_PeriodExamDocuments_DocumentId",
table: "PeriodExamDocuments",
column: "DocumentId");
migrationBuilder.CreateIndex(
name: "IX_PeriodExamDocuments_PeriodExamId",
table: "PeriodExamDocuments",
column: "PeriodExamId");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "PeriodExamDocuments");
}
}
}

View file

@ -77,5 +77,8 @@ namespace BMA.EHR.Recurit.Exam.Service.Models
[Comment("ช่องทางชำระเงิน")] [Comment("ช่องทางชำระเงิน")]
public List<BankExam> BankExam { get; set; } = new List<BankExam>(); public List<BankExam> BankExam { get; set; } = new List<BankExam>();
[Comment("เอกสารอื่นๆ")]
public virtual List<PeriodExamDocument> PeriodExamDocuments { get; set; } = new();
} }
} }

View file

@ -0,0 +1,15 @@
using Microsoft.EntityFrameworkCore;
using System.ComponentModel.DataAnnotations.Schema;
using System.ComponentModel.DataAnnotations;
using BMA.EHR.Recurit.Exam.Service.Models.Documents;
namespace BMA.EHR.Recurit.Exam.Service.Models
{
public class PeriodExamDocument : EntityBase
{
[Required, Comment("Id รอบสมัครสอบ")]
public virtual PeriodExam? PeriodExam { get; set; }
[Required, Comment("Id ไฟล์เอกสาร")]
public virtual Document? Document { get; set; }
}
}

View file

@ -8,6 +8,7 @@ namespace BMA.EHR.Recurit.Exam.Service.Request
public bool Consend { get; set; } public bool Consend { get; set; }
public bool Position { get; set; } public bool Position { get; set; }
public bool Bank { get; set; } public bool Bank { get; set; }
public bool Payment { get; set; }
public string? Status { get; set; } public string? Status { get; set; }
public PositionExam? PositionExam { get; set; } public PositionExam? PositionExam { get; set; }
} }

View file

@ -4,10 +4,10 @@
{ {
public string? Id { get; set; } public string? Id { get; set; }
public string FileName { get; set; } = string.Empty; public string? FileName { get; set; } = string.Empty;
public string FileType { get; set; } = string.Empty; public string? FileType { get; set; } = string.Empty;
public int FileSize { get; set; } public int? FileSize { get; set; }
} }
} }

View file

@ -0,0 +1,35 @@

using BMA.EHR.Recurit.Exam.Service.Responses.Document;
namespace BMA.EHR.Recurit.Exam.Service.Response
{
public class PeriodExamCandidateResponseItem
{
public Guid Id { get; set; }
public string? Name { get; set; }
public bool CheckDocument { get; set; }
public bool CheckDisability { get; set; }
public int? Round { get; set; }
public int? Year { get; set; }
public float? Fee { get; set; }
public DateTime RegisterStartDate { get; set; }
public DateTime RegisterEndDate { get; set; }
public DateTime PaymentStartDate { get; set; }
public DateTime PaymentEndDate { get; set; }
public DateTime AnnouncementStartDate { get; set; }
public DateTime AnnouncementEndDate { get; set; }
public Guid? OrganizationCodeId { get; set; }
public string? OrganizationCodeName { get; set; }
public Guid? OrganizationId { get; set; }
public string? OrganizationName { get; set; }
public string? PaymentKrungThai { get; set; }
public string? Detail { get; set; }
public string? Note { get; set; }
public bool IsActive { get; set; }
public bool SetSeat { get; set; }
public List<Models.Candidate> Candidate { get; set; } = new List<Models.Candidate>();
public List<Models.PositionExam> PositionExam { get; set; } = new List<Models.PositionExam>();
public List<Models.BankExam> BankExam { get; set; } = new List<Models.BankExam>();
public List<FileListResponse> Documents { get; set; } = new List<FileListResponse>();
}
}

View file

@ -542,6 +542,7 @@ namespace BMA.EHR.Recurit.Exam.Service.Services
Status = candidate == null ? null : candidate.Status, Status = candidate == null ? null : candidate.Status,
PositionExam = candidatePosition?.PositionExam, PositionExam = candidatePosition?.PositionExam,
Bank = exam.BankExam.Count() > 0, Bank = exam.BankExam.Count() > 0,
Payment = exam.Fee > 0,
Position = candidatePosition == null ? false : true Position = candidatePosition == null ? false : true
}; };
} }

View file

@ -3,8 +3,10 @@ using System.Text.Json;
using BMA.EHR.Recurit.Exam.Service.Core; using BMA.EHR.Recurit.Exam.Service.Core;
using BMA.EHR.Recurit.Exam.Service.Data; using BMA.EHR.Recurit.Exam.Service.Data;
using BMA.EHR.Recurit.Exam.Service.Models; using BMA.EHR.Recurit.Exam.Service.Models;
using BMA.EHR.Recurit.Exam.Service.Models.Documents;
using BMA.EHR.Recurit.Exam.Service.Request; using BMA.EHR.Recurit.Exam.Service.Request;
using BMA.EHR.Recurit.Exam.Service.Response; using BMA.EHR.Recurit.Exam.Service.Response;
using BMA.EHR.Recurit.Exam.Service.Responses.Document;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Newtonsoft.Json.Linq; using Newtonsoft.Json.Linq;
using OfficeOpenXml; using OfficeOpenXml;
@ -17,16 +19,19 @@ namespace BMA.EHR.Recurit.Exam.Service.Services
private readonly ApplicationDbContext _context; private readonly ApplicationDbContext _context;
private readonly IHttpContextAccessor _httpContextAccessor; private readonly IHttpContextAccessor _httpContextAccessor;
private readonly MinIOService _minioService;
#endregion #endregion
#region " Constructor and Destructor " #region " Constructor and Destructor "
public PeriodExamService(ApplicationDbContext context, public PeriodExamService(ApplicationDbContext context,
IHttpContextAccessor httpContextAccessor) IHttpContextAccessor httpContextAccessor,
MinIOService minioService)
{ {
_context = context; _context = context;
_httpContextAccessor = httpContextAccessor; _httpContextAccessor = httpContextAccessor;
_minioService = minioService;
} }
#endregion #endregion
@ -41,61 +46,61 @@ namespace BMA.EHR.Recurit.Exam.Service.Services
#region " Methods " #region " Methods "
public async Task<IEnumerable<PeriodExam>> GetsAsync(bool showAll = true) public async Task<IEnumerable<PeriodExamCandidateResponseItem>> GetsAsync(bool showAll = true)
{ {
if (showAll) return await _context.PeriodExams.AsQueryable()
return await _context.PeriodExams.AsQueryable() .Include(x => x.PositionExam)
.Include(x => x.PositionExam) .Include(x => x.BankExam)
.Include(x => x.BankExam) .Where(p => p.IsActive)
.OrderBy(d => d.Name) .OrderBy(d => d.Name)
.ToListAsync(); .Select(x => new PeriodExamCandidateResponseItem
else {
return await _context.PeriodExams.AsQueryable() AnnouncementEndDate = x.AnnouncementEndDate,
.Include(x => x.PositionExam) AnnouncementStartDate = x.AnnouncementStartDate,
.Include(x => x.BankExam) CheckDisability = x.CheckDisability,
.Where(p => p.IsActive) CheckDocument = x.CheckDocument,
.OrderBy(d => d.Name) Detail = x.Detail,
.Select(x => new PeriodExam Fee = x.Fee,
Id = x.Id,
IsActive = x.IsActive,
Name = x.Name,
Note = x.Note,
OrganizationCodeId = x.OrganizationCodeId,
OrganizationCodeName = x.OrganizationCodeName,
OrganizationId = x.OrganizationId,
OrganizationName = x.OrganizationName,
PaymentEndDate = x.PaymentEndDate,
PaymentKrungThai = x.PaymentKrungThai,
PaymentStartDate = x.PaymentStartDate,
RegisterEndDate = x.RegisterEndDate,
RegisterStartDate = x.RegisterStartDate,
Round = x.Round,
SetSeat = x.SetSeat,
Year = x.Year,
BankExam = x.BankExam.OrderBy(o => o.CreatedAt).Select(b => new BankExam
{ {
AnnouncementEndDate = x.AnnouncementEndDate, Id = b.Id,
AnnouncementStartDate = x.AnnouncementStartDate, AccountName = b.AccountName,
CheckDisability = x.CheckDisability, AccountNumber = b.AccountNumber,
CheckDocument = x.CheckDocument, BankName = b.BankName,
Detail = x.Detail, }).ToList(),
Fee = x.Fee, PositionExam = x.PositionExam.OrderBy(o => o.CreatedAt).Select(b => new PositionExam
Id = x.Id, {
IsActive = x.IsActive, Id = b.Id,
Name = x.Name, TypeId = b.TypeId,
Note = x.Note, TypeName = b.TypeName,
OrganizationCodeId = x.OrganizationCodeId, PositionId = b.PositionId,
OrganizationCodeName = x.OrganizationCodeName, PositionName = b.PositionName,
OrganizationId = x.OrganizationId, }).ToList(),
OrganizationName = x.OrganizationName, Documents = x.PeriodExamDocuments.OrderBy(o => o.CreatedAt).Select(b => new FileListResponse
PaymentEndDate = x.PaymentEndDate, {
PaymentKrungThai = x.PaymentKrungThai, Id = b.Document == null ? "" : b.Document.Id.ToString(),
PaymentStartDate = x.PaymentStartDate, FileName = b.Document == null ? "" : b.Document.FileName,
RegisterEndDate = x.RegisterEndDate, FileSize = b.Document == null ? 0 : b.Document.FileSize,
RegisterStartDate = x.RegisterStartDate, FileType = b.Document == null ? "" : b.Document.FileType,
Round = x.Round, }).ToList(),
SetSeat = x.SetSeat, })
Year = x.Year, .ToListAsync();
BankExam = x.BankExam.OrderBy(o => o.CreatedAt).Select(b => new BankExam
{
Id = b.Id,
AccountName = b.AccountName,
AccountNumber = b.AccountNumber,
BankName = b.BankName,
}).ToList(),
PositionExam = x.PositionExam.OrderBy(o => o.CreatedAt).Select(b => new PositionExam
{
Id = b.Id,
TypeId = b.TypeId,
TypeName = b.TypeName,
PositionId = b.PositionId,
PositionName = b.PositionName,
}).ToList(),
})
.ToListAsync();
} }
public async Task<PeriodExam?> GetsExamAndCandidateAsync(string examId, bool showAll = true) public async Task<PeriodExam?> GetsExamAndCandidateAsync(string examId, bool showAll = true)
@ -152,7 +157,7 @@ namespace BMA.EHR.Recurit.Exam.Service.Services
} }
} }
public async Task CreateAsync(RequestPeriodExam inserted) public async Task CreateAsync(RequestPeriodExam inserted, IFormFileCollection files)
{ {
var periodExam = new PeriodExam var periodExam = new PeriodExam
{ {
@ -220,16 +225,37 @@ namespace BMA.EHR.Recurit.Exam.Service.Services
await _context.PositionExams.AddAsync(positionExam); await _context.PositionExams.AddAsync(positionExam);
} }
foreach (var file in files)
{
var doc = await _minioService.UploadFileAsync(file);
var document = await _context.Documents.AsQueryable()
.FirstOrDefaultAsync(x => x.Id == doc.Id);
if (document == null)
throw new Exception(GlobalMessages.NoFileToUpload);
var periodExamDocument = new PeriodExamDocument
{
PeriodExam = periodExam,
Document = document,
};
await _context.PeriodExamDocuments.AddAsync(periodExamDocument);
}
await _context.PeriodExams.AddAsync(periodExam); await _context.PeriodExams.AddAsync(periodExam);
await _context.SaveChangesAsync(); await _context.SaveChangesAsync();
} }
public async Task UpdateAsync(string examId, RequestPeriodExam updated) public async Task UpdateAsync(string examId, RequestPeriodExam updated, IFormFileCollection files)
{ {
var periodExam = await _context.PeriodExams.AsQueryable() var periodExam = await _context.PeriodExams.AsQueryable()
.Include(x => x.BankExam) .Include(x => x.BankExam)
.Include(x => x.PositionExam) .Include(x => x.PositionExam)
.Include(x => x.PeriodExamDocuments)
.ThenInclude(x => x.Document)
.FirstOrDefaultAsync(x => x.Id == Guid.Parse(examId)); .FirstOrDefaultAsync(x => x.Id == Guid.Parse(examId));
if (periodExam == null) if (periodExam == null)
@ -348,9 +374,41 @@ namespace BMA.EHR.Recurit.Exam.Service.Services
await _context.PositionExams.AddAsync(positionExam); await _context.PositionExams.AddAsync(positionExam);
} }
foreach (var doc in periodExam.PeriodExamDocuments)
{
if (doc.Id != null)
{
await DeleteAsyncDocument(doc.Id.ToString());
}
}
foreach (var file in files)
{
var doc = await _minioService.UploadFileAsync(file);
var document = await _context.Documents.AsQueryable()
.FirstOrDefaultAsync(x => x.Id == doc.Id);
if (document == null)
throw new Exception(GlobalMessages.NoFileToUpload);
var periodExamDocument = new PeriodExamDocument
{
PeriodExam = periodExam,
Document = document,
};
await _context.PeriodExamDocuments.AddAsync(periodExamDocument);
}
await _context.SaveChangesAsync(); await _context.SaveChangesAsync();
} }
public async Task DeleteAsyncDocument(string documentId)
{
await _minioService.DeleteFileAsync(Guid.Parse(documentId));
}
public async Task DeleteAsync(string examId) public async Task DeleteAsync(string examId)
{ {
var periodExam = await _context.PeriodExams.AsQueryable() var periodExam = await _context.PeriodExams.AsQueryable()

File diff suppressed because it is too large Load diff