[CLAUDE] Contract: K1 SP-002 danh muc loai HD - ContractCatalogEntries (Mig 70) + seed 86 + CQRS + FE kind-5 x2 app + 8 test
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 6m31s
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 6m31s
Gate: reviewer PASS-WITH-FLAGS 9f (sub-reviewer-gate-k1.md). Xu ly: F4 IncludeInactive mac-dinh-loai (spec K1.c) + test T5b; F7 comment 5-kind; F1 OG-6 doi nhan soat-SAU @PAUSE-2 (seeder skip-if-exists giu sua-tay CRUD qua restart - update-branch co y KHONG co); F3 authz mirror khuon Catalogs, gioi-han khai: 4 policy ContractCatalog.* sinh ra nhung chua endpoint nao tieu thu (display-layer khac API-layer, #82); F6 ten index IX_ giu EF-default (NIT). Suite 598/0 (45D+553I). Mig 70 ap SQL Server that OK. Drift DELTA: MenuKeys.All 55->56, policies 220->224, bang 96->97. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@ -0,0 +1,62 @@
|
||||
using MediatR;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using SolutionErp.Application.Master.Catalogs;
|
||||
|
||||
namespace SolutionErp.Api.Controllers;
|
||||
|
||||
// [K1 — S164, Mig 70] API "Danh mục Hợp đồng" (SOL-CCM-SP-002, 86 dòng × 8 nhóm duyệt).
|
||||
//
|
||||
// Route nằm DƯỚI `api/catalogs/` để đồng bộ với 4 catalog cũ (FE dùng chung trang
|
||||
// KIND_CONFIG theo `:kind` → kind mới = `contract-catalog`), nhưng tách CONTROLLER
|
||||
// riêng cho gọn (CatalogsController đã 4 kind × 4 verb).
|
||||
//
|
||||
// AUTHZ (QUYẾT-1 S164 — mirror y CatalogsController.cs:12-14, KHÔNG policy key mới):
|
||||
// - class `[Authorize]` = mọi user đăng nhập ĐỌC được → picker chọn hạng mục ở
|
||||
// màn tạo phiếu KHKK (K2) không bị 403 vì thiếu grant leaf (gotcha #44/#85).
|
||||
// - mọi action GHI `[Authorize(Roles = "Admin")]` — sửa danh mục là việc quản trị,
|
||||
// KHÔNG phải quyền của drafter phiếu.
|
||||
|
||||
[ApiController]
|
||||
[Route("api/catalogs/contract-catalog")]
|
||||
[Authorize]
|
||||
public class ContractCatalogController(IMediator mediator) : ControllerBase
|
||||
{
|
||||
[HttpGet]
|
||||
public async Task<List<ContractCatalogEntryDto>> List(
|
||||
[FromQuery] string? groupCode,
|
||||
[FromQuery] int? approvalGroup,
|
||||
[FromQuery] bool includeInactive,
|
||||
[FromQuery] string? q,
|
||||
CancellationToken ct)
|
||||
=> await mediator.Send(new ListContractCatalogQuery(groupCode, approvalGroup, includeInactive, q), ct);
|
||||
|
||||
[HttpGet("{id:guid}")]
|
||||
public async Task<ContractCatalogEntryDto> Get(Guid id, CancellationToken ct)
|
||||
=> await mediator.Send(new GetContractCatalogEntryQuery(id), ct);
|
||||
|
||||
[HttpPost]
|
||||
[Authorize(Roles = "Admin")]
|
||||
public async Task<IActionResult> Create([FromBody] CreateContractCatalogEntryCommand body, CancellationToken ct)
|
||||
{
|
||||
var id = await mediator.Send(body, ct);
|
||||
return CreatedAtAction(nameof(Get), new { id }, new { id });
|
||||
}
|
||||
|
||||
[HttpPut("{id:guid}")]
|
||||
[Authorize(Roles = "Admin")]
|
||||
public async Task<IActionResult> Update(Guid id, [FromBody] UpdateContractCatalogEntryCommand body, CancellationToken ct)
|
||||
{
|
||||
if (id != body.Id) return BadRequest("Id mismatch");
|
||||
await mediator.Send(body, ct);
|
||||
return NoContent();
|
||||
}
|
||||
|
||||
[HttpDelete("{id:guid}")]
|
||||
[Authorize(Roles = "Admin")]
|
||||
public async Task<IActionResult> Delete(Guid id, CancellationToken ct)
|
||||
{
|
||||
await mediator.Send(new DeleteContractCatalogEntryCommand(id), ct);
|
||||
return NoContent();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user