апи для работы с маршрутами согласования #2

Merged
admin merged 38 commits from initial-api into main 2026-07-27 13:14:32 +00:00
20 changed files with 101 additions and 91 deletions
Showing only changes of commit 5e3ef814f3 - Show all commits
@@ -16,10 +16,10 @@ public sealed class RequestTypesController(RequestTypeService service) : Control
public async Task<IActionResult> List(CancellationToken ct) =>
(await service.ListAsync(ct)).ToActionResult();
[HttpGet("{id:guid}")]
[HttpGet("{id:int}")]
[ProducesResponseType(typeof(ApiResponse<RequestTypeDto>), StatusCodes.Status200OK)]
[ProducesResponseType(typeof(ApiError), StatusCodes.Status404NotFound)]
public async Task<IActionResult> Get(Guid id, CancellationToken ct) =>
public async Task<IActionResult> Get(int id, CancellationToken ct) =>
(await service.GetAsync(id, ct)).ToActionResult();
[HttpPost]
@@ -28,16 +28,16 @@ public sealed class RequestTypesController(RequestTypeService service) : Control
public async Task<IActionResult> Create(CreateRequestTypeRequest body, CancellationToken ct) =>
(await service.CreateAsync(body, ct)).ToActionResult();
[HttpPut("{id:guid}")]
[HttpPut("{id:int}")]
[ProducesResponseType(typeof(ApiResponse<RequestTypeDto>), StatusCodes.Status200OK)]
[ProducesResponseType(typeof(ApiError), StatusCodes.Status400BadRequest)]
[ProducesResponseType(typeof(ApiError), StatusCodes.Status404NotFound)]
public async Task<IActionResult> Update(Guid id, UpdateRequestTypeRequest body, CancellationToken ct) =>
public async Task<IActionResult> Update(int id, UpdateRequestTypeRequest body, CancellationToken ct) =>
(await service.UpdateAsync(id, body, ct)).ToActionResult();
[HttpDelete("{id:guid}")]
[HttpDelete("{id:int}")]
[ProducesResponseType(StatusCodes.Status204NoContent)]
[ProducesResponseType(typeof(ApiError), StatusCodes.Status404NotFound)]
public async Task<IActionResult> Delete(Guid id, CancellationToken ct) =>
public async Task<IActionResult> Delete(int id, CancellationToken ct) =>
(await service.DeleteAsync(id, ct)).ToActionResult();
}
@@ -7,38 +7,38 @@ namespace Tnsu.ApprovalRoute.Api.Controllers;
[ApiController]
[Authorize]
[Route("api/template-routes/{routeId:guid}/steps")]
[Route("api/template-routes/{routeId:int}/steps")]
[Produces("application/json")]
public sealed class TemplateRouteStepsController(TemplateRouteStepService service) : ControllerBase
{
[HttpGet]
[ProducesResponseType(typeof(ApiResponse<IReadOnlyList<TemplateRouteStepDto>>), StatusCodes.Status200OK)]
public async Task<IActionResult> List(Guid routeId, CancellationToken ct) =>
public async Task<IActionResult> List(int routeId, CancellationToken ct) =>
(await service.ListAsync(routeId, ct)).ToActionResult();
[HttpGet("{id:guid}")]
[HttpGet("{id:int}")]
[ProducesResponseType(typeof(ApiResponse<TemplateRouteStepDto>), StatusCodes.Status200OK)]
[ProducesResponseType(typeof(ApiError), StatusCodes.Status404NotFound)]
public async Task<IActionResult> Get(Guid routeId, Guid id, CancellationToken ct) =>
public async Task<IActionResult> Get(int routeId, int id, CancellationToken ct) =>
(await service.GetAsync(routeId, id, ct)).ToActionResult();
[HttpPost]
[ProducesResponseType(typeof(ApiResponse<TemplateRouteStepDto>), StatusCodes.Status200OK)]
[ProducesResponseType(typeof(ApiError), StatusCodes.Status400BadRequest)]
[ProducesResponseType(typeof(ApiError), StatusCodes.Status404NotFound)]
public async Task<IActionResult> Create(Guid routeId, CreateTemplateRouteStepRequest body, CancellationToken ct) =>
public async Task<IActionResult> Create(int routeId, CreateTemplateRouteStepRequest body, CancellationToken ct) =>
(await service.CreateAsync(routeId, body, ct)).ToActionResult();
[HttpPut("{id:guid}")]
[HttpPut("{id:int}")]
[ProducesResponseType(typeof(ApiResponse<TemplateRouteStepDto>), StatusCodes.Status200OK)]
[ProducesResponseType(typeof(ApiError), StatusCodes.Status400BadRequest)]
[ProducesResponseType(typeof(ApiError), StatusCodes.Status404NotFound)]
public async Task<IActionResult> Update(Guid routeId, Guid id, UpdateTemplateRouteStepRequest body, CancellationToken ct) =>
public async Task<IActionResult> Update(int routeId, int id, UpdateTemplateRouteStepRequest body, CancellationToken ct) =>
(await service.UpdateAsync(routeId, id, body, ct)).ToActionResult();
[HttpDelete("{id:guid}")]
[HttpDelete("{id:int}")]
[ProducesResponseType(StatusCodes.Status204NoContent)]
[ProducesResponseType(typeof(ApiError), StatusCodes.Status404NotFound)]
public async Task<IActionResult> Delete(Guid routeId, Guid id, CancellationToken ct) =>
public async Task<IActionResult> Delete(int routeId, int id, CancellationToken ct) =>
(await service.DeleteAsync(routeId, id, ct)).ToActionResult();
}
@@ -20,13 +20,13 @@ public sealed class TemplateRoutesController(TemplateRouteService service) : Con
[HttpGet]
[ProducesResponseType(typeof(ApiResponse<IReadOnlyList<TemplateRouteDto>>), StatusCodes.Status200OK)]
public async Task<IActionResult> List([FromQuery] Guid? requestTypeId, CancellationToken ct) =>
public async Task<IActionResult> List([FromQuery] int? requestTypeId, CancellationToken ct) =>
(await service.ListAsync(requestTypeId, ct)).ToActionResult();
[HttpGet("{id:guid}")]
[HttpGet("{id:int}")]
[ProducesResponseType(typeof(ApiResponse<TemplateRouteDto>), StatusCodes.Status200OK)]
[ProducesResponseType(typeof(ApiError), StatusCodes.Status404NotFound)]
public async Task<IActionResult> Get(Guid id, CancellationToken ct) =>
public async Task<IActionResult> Get(int id, CancellationToken ct) =>
(await service.GetAsync(id, ct)).ToActionResult();
[HttpPost]
@@ -37,17 +37,17 @@ public sealed class TemplateRoutesController(TemplateRouteService service) : Con
public async Task<IActionResult> Create(CreateTemplateRouteRequest body, CancellationToken ct) =>
(await service.CreateAsync(body, ct)).ToActionResult();
[HttpPut("{id:guid}")]
[HttpPut("{id:int}")]
[ProducesResponseType(typeof(ApiResponse<TemplateRouteDto>), StatusCodes.Status200OK)]
[ProducesResponseType(typeof(ApiError), StatusCodes.Status400BadRequest)]
[ProducesResponseType(typeof(ApiError), StatusCodes.Status404NotFound)]
[ProducesResponseType(typeof(ApiError), StatusCodes.Status409Conflict)]
public async Task<IActionResult> Update(Guid id, UpdateTemplateRouteRequest body, CancellationToken ct) =>
public async Task<IActionResult> Update(int id, UpdateTemplateRouteRequest body, CancellationToken ct) =>
(await service.UpdateAsync(id, body, ct)).ToActionResult();
[HttpDelete("{id:guid}")]
[HttpDelete("{id:int}")]
[ProducesResponseType(StatusCodes.Status204NoContent)]
[ProducesResponseType(typeof(ApiError), StatusCodes.Status404NotFound)]
public async Task<IActionResult> Delete(Guid id, CancellationToken ct) =>
public async Task<IActionResult> Delete(int id, CancellationToken ct) =>
(await service.DeleteAsync(id, ct)).ToActionResult();
}
@@ -2,7 +2,7 @@ using FluentResults;
namespace Tnsu.ApprovalRoute.Application.Common.Errors;
public sealed class NotFoundError(string entity, Guid id)
public sealed class NotFoundError(string entity, object id)
: Error($"{entity} с id {id} не найден.");
public sealed class ValidationError(string message) : Error(message);
@@ -1,6 +1,6 @@
namespace Tnsu.ApprovalRoute.Application.RequestTypes;
public sealed record RequestTypeDto(Guid Id, string Name, string PageUrl);
public sealed record RequestTypeDto(int Id, string Name, string PageUrl);
public sealed record CreateRequestTypeRequest(string Name, string PageUrl);
@@ -18,7 +18,7 @@ public sealed class RequestTypeService(ApprovalRouteDbContext db)
return Result.Ok<IReadOnlyList<RequestTypeDto>>(items);
}
public async Task<Result<RequestTypeDto>> GetAsync(Guid id, CancellationToken cancellationToken)
public async Task<Result<RequestTypeDto>> GetAsync(int id, CancellationToken cancellationToken)
{
var entity = await db.RequestTypes.AsNoTracking().FirstOrDefaultAsync(x => x.Id == id, cancellationToken);
@@ -36,7 +36,7 @@ public sealed class RequestTypeService(ApprovalRouteDbContext db)
return Result.Ok(ToDto(entity));
}
public async Task<Result<RequestTypeDto>> UpdateAsync(Guid id, UpdateRequestTypeRequest request, CancellationToken cancellationToken)
public async Task<Result<RequestTypeDto>> UpdateAsync(int id, UpdateRequestTypeRequest request, CancellationToken cancellationToken)
{
var entity = await db.RequestTypes.FirstOrDefaultAsync(x => x.Id == id, cancellationToken);
if (entity is null)
@@ -49,7 +49,7 @@ public sealed class RequestTypeService(ApprovalRouteDbContext db)
return Result.Ok(ToDto(entity));
}
public async Task<Result> DeleteAsync(Guid id, CancellationToken cancellationToken)
public async Task<Result> DeleteAsync(int id, CancellationToken cancellationToken)
{
var entity = await db.RequestTypes.FirstOrDefaultAsync(x => x.Id == id, cancellationToken);
if (entity is null)
@@ -3,14 +3,14 @@ using Tnsu.ApprovalRoute.Domain.Enums;
namespace Tnsu.ApprovalRoute.Application.TemplateRouteSteps;
public sealed record TemplateRouteStepDto(
Guid Id,
int Id,
int OrderNo,
string ExecutorEmail,
string Position,
ProjectRole ProjectRole,
HeadType HeadType,
RouteStepStatus Status,
Guid RouteId,
int RouteId,
bool AllowReassignToOtherApprovers);
public sealed record CreateTemplateRouteStepRequest(
@@ -9,7 +9,7 @@ namespace Tnsu.ApprovalRoute.Application.TemplateRouteSteps;
public sealed class TemplateRouteStepService(ApprovalRouteDbContext db)
{
public async Task<Result<IReadOnlyList<TemplateRouteStepDto>>> ListAsync(Guid routeId, CancellationToken cancellationToken)
public async Task<Result<IReadOnlyList<TemplateRouteStepDto>>> ListAsync(int routeId, CancellationToken cancellationToken)
{
var items = await db.TemplateRouteSteps.AsNoTracking()
.Where(x => x.RouteId == routeId)
@@ -21,7 +21,7 @@ public sealed class TemplateRouteStepService(ApprovalRouteDbContext db)
return Result.Ok<IReadOnlyList<TemplateRouteStepDto>>(items);
}
public async Task<Result<TemplateRouteStepDto>> GetAsync(Guid routeId, Guid id, CancellationToken cancellationToken)
public async Task<Result<TemplateRouteStepDto>> GetAsync(int routeId, int id, CancellationToken cancellationToken)
{
var entity = await db.TemplateRouteSteps.AsNoTracking()
.FirstOrDefaultAsync(x => x.Id == id && x.RouteId == routeId, cancellationToken);
@@ -31,7 +31,7 @@ public sealed class TemplateRouteStepService(ApprovalRouteDbContext db)
: Result.Ok(ToDto(entity));
}
public async Task<Result<TemplateRouteStepDto>> CreateAsync(Guid routeId, CreateTemplateRouteStepRequest r, CancellationToken cancellationToken)
public async Task<Result<TemplateRouteStepDto>> CreateAsync(int routeId, CreateTemplateRouteStepRequest r, CancellationToken cancellationToken)
{
var route = await db.TemplateRoutes.FirstOrDefaultAsync(x => x.Id == routeId, cancellationToken);
if (route is null)
@@ -60,7 +60,7 @@ public sealed class TemplateRouteStepService(ApprovalRouteDbContext db)
}
public async Task<Result<TemplateRouteStepDto>> UpdateAsync(
Guid routeId, Guid id, UpdateTemplateRouteStepRequest r, CancellationToken cancellationToken)
int routeId, int id, UpdateTemplateRouteStepRequest r, CancellationToken cancellationToken)
{
var route = await db.TemplateRoutes.FirstOrDefaultAsync(x => x.Id == routeId, cancellationToken);
if (route is null)
@@ -87,7 +87,7 @@ public sealed class TemplateRouteStepService(ApprovalRouteDbContext db)
return await AppendMissingProjectRoleWarningAsync(route, result, cancellationToken);
}
public async Task<Result> DeleteAsync(Guid routeId, Guid id, CancellationToken cancellationToken)
public async Task<Result> DeleteAsync(int routeId, int id, CancellationToken cancellationToken)
{
var entity = await db.TemplateRouteSteps.FirstOrDefaultAsync(x => x.Id == id && x.RouteId == routeId, cancellationToken);
if (entity is null)
@@ -3,7 +3,7 @@ using Tnsu.ApprovalRoute.Domain.Enums;
namespace Tnsu.ApprovalRoute.Application.TemplateRoutes;
public sealed record ResolvedRouteStepDto(
Guid Id,
int Id,
int OrderNo,
string ExecutorEmail,
string Position,
@@ -13,13 +13,13 @@ public sealed record ResolvedRouteStepDto(
bool AllowReassignToOtherApprovers);
public sealed record ResolveTemplateRouteResultDto(
Guid RouteId,
int RouteId,
RouteType RouteType,
bool RequiresControl,
IReadOnlyList<ResolvedRouteStepDto> Steps);
public sealed record ResolveTemplateRouteRequest(
Guid RequestTypeId,
int RequestTypeId,
string? UserEmail,
Guid? ProjectId,
RouteStepStatus Status);
@@ -3,9 +3,9 @@ using Tnsu.ApprovalRoute.Domain.Enums;
namespace Tnsu.ApprovalRoute.Application.TemplateRoutes;
public sealed record TemplateRouteDto(
Guid Id,
int Id,
RouteType RouteType,
Guid RequestTypeId,
int RequestTypeId,
string? Department,
string Company,
bool ByProject,
@@ -13,7 +13,7 @@ public sealed record TemplateRouteDto(
public sealed record CreateTemplateRouteRequest(
RouteType RouteType,
Guid RequestTypeId,
int RequestTypeId,
string? Department,
string Company,
bool ByProject,
@@ -14,7 +14,7 @@ public sealed class TemplateRouteService(
ITnsuPortalClient portalClient,
ICurrentUser currentUser)
{
public async Task<Result<IReadOnlyList<TemplateRouteDto>>> ListAsync(Guid? requestTypeId, CancellationToken cancellationToken)
public async Task<Result<IReadOnlyList<TemplateRouteDto>>> ListAsync(int? requestTypeId, CancellationToken cancellationToken)
{
var query = db.TemplateRoutes.AsNoTracking().AsQueryable();
if (requestTypeId is { } id)
@@ -28,7 +28,7 @@ public sealed class TemplateRouteService(
return Result.Ok<IReadOnlyList<TemplateRouteDto>>(items);
}
public async Task<Result<TemplateRouteDto>> GetAsync(Guid id, CancellationToken cancellationToken)
public async Task<Result<TemplateRouteDto>> GetAsync(int id, CancellationToken cancellationToken)
{
var entity = await db.TemplateRoutes.AsNoTracking().FirstOrDefaultAsync(x => x.Id == id, cancellationToken);
@@ -64,7 +64,7 @@ public sealed class TemplateRouteService(
return Result.Ok(ToDto(entity));
}
public async Task<Result<TemplateRouteDto>> UpdateAsync(Guid id, UpdateTemplateRouteRequest r, CancellationToken cancellationToken)
public async Task<Result<TemplateRouteDto>> UpdateAsync(int id, UpdateTemplateRouteRequest r, CancellationToken cancellationToken)
{
var entity = await db.TemplateRoutes.FirstOrDefaultAsync(x => x.Id == id, cancellationToken);
if (entity is null)
@@ -86,7 +86,7 @@ public sealed class TemplateRouteService(
return Result.Ok(ToDto(entity));
}
public async Task<Result> DeleteAsync(Guid id, CancellationToken cancellationToken)
public async Task<Result> DeleteAsync(int id, CancellationToken cancellationToken)
{
var entity = await db.TemplateRoutes.FirstOrDefaultAsync(x => x.Id == id, cancellationToken);
if (entity is null)
@@ -113,7 +113,7 @@ public sealed class TemplateRouteService(
var employee = await portalClient.GetEmployeeByEmailAsync(email, cancellationToken);
if (employee is null)
return Result.Fail<ResolveTemplateRouteResultDto>(
new NotFoundError("Сотрудник по email в справочнике api.tnsu.kz не найден", Guid.Empty));
new NotFoundError("Сотрудник в справочнике api.tnsu.kz по email", email));
var byProject = request.ProjectId is not null;
var department = Normalize(employee.Department);
@@ -154,7 +154,7 @@ public sealed class TemplateRouteService(
}
private Task<bool> HasDuplicateAsync(
Guid requestTypeId, string? department, string company, bool byProject, Guid? excludeId, CancellationToken cancellationToken) =>
int requestTypeId, string? department, string company, bool byProject, int? excludeId, CancellationToken cancellationToken) =>
db.TemplateRoutes.AnyAsync(x =>
x.Id != excludeId &&
x.RequestTypeId == requestTypeId &&
@@ -1,11 +1,8 @@
using System;
using System.Collections.Generic;
namespace Tnsu.ApprovalRoute.Domain.Entities;
public class RequestType
{
public Guid Id { get; set; } = Guid.NewGuid();
public int Id { get; set; }
public string Name { get; set; } = string.Empty;
public string PageUrl { get; set; } = string.Empty;
@@ -4,9 +4,9 @@ namespace Tnsu.ApprovalRoute.Domain.Entities;
public class TemplateRoute
{
public Guid Id { get; set; } = Guid.NewGuid();
public int Id { get; set; }
public RouteType RouteType { get; set; } = RouteType.Sequential;
public Guid RequestTypeId { get; set; }
public int RequestTypeId { get; set; }
// Компания и отдел инициатора — названия из справочника AD (api-tnsu-portal /Employee/ByEmail),
// хранятся строками без FK в этой БД. Отдел опционален, компания обязательна.
@@ -4,7 +4,7 @@ namespace Tnsu.ApprovalRoute.Domain.Entities;
public class TemplateRouteStep
{
public Guid Id { get; set; } = Guid.NewGuid();
public int Id { get; set; }
public int OrderNo { get; set; }
// Внешняя ссылка на пользователя (1С/ZUP) — без локальной таблицы Users.
@@ -14,7 +14,7 @@ public class TemplateRouteStep
public HeadType HeadType { get; set; } = HeadType.None;
public RouteStepStatus Status { get; set; } = RouteStepStatus.Approval;
public Guid RouteId { get; set; }
public int RouteId { get; set; }
public bool AllowReassignToOtherApprovers { get; set; }
public TemplateRoute? Route { get; set; }
@@ -1,5 +1,4 @@
// <auto-generated />
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
@@ -12,7 +11,7 @@ using Tnsu.ApprovalRoute.Infrastructure.Persistence;
namespace Tnsu.ApprovalRoute.Infrastructure.Persistence.Migrations
{
[DbContext(typeof(ApprovalRouteDbContext))]
[Migration("20260724071302_InitialCreate")]
[Migration("20260724085143_InitialCreate")]
partial class InitialCreate
{
/// <inheritdoc />
@@ -27,11 +26,13 @@ namespace Tnsu.ApprovalRoute.Infrastructure.Persistence.Migrations
modelBuilder.Entity("Tnsu.ApprovalRoute.Domain.Entities.RequestType", b =>
{
b.Property<Guid>("Id")
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid")
.HasColumnType("integer")
.HasColumnName("id");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(256)
@@ -52,11 +53,13 @@ namespace Tnsu.ApprovalRoute.Infrastructure.Persistence.Migrations
modelBuilder.Entity("Tnsu.ApprovalRoute.Domain.Entities.TemplateRoute", b =>
{
b.Property<Guid>("Id")
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid")
.HasColumnType("integer")
.HasColumnName("id");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<bool>("ByProject")
.HasColumnType("boolean")
.HasColumnName("by_project");
@@ -72,8 +75,8 @@ namespace Tnsu.ApprovalRoute.Infrastructure.Persistence.Migrations
.HasColumnType("character varying(256)")
.HasColumnName("department");
b.Property<Guid>("RequestTypeId")
.HasColumnType("uuid")
b.Property<int>("RequestTypeId")
.HasColumnType("integer")
.HasColumnName("request_type_id");
b.Property<bool>("RequiresControl")
@@ -98,11 +101,13 @@ namespace Tnsu.ApprovalRoute.Infrastructure.Persistence.Migrations
modelBuilder.Entity("Tnsu.ApprovalRoute.Domain.Entities.TemplateRouteStep", b =>
{
b.Property<Guid>("Id")
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid")
.HasColumnType("integer")
.HasColumnName("id");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<bool>("AllowReassignToOtherApprovers")
.HasColumnType("boolean")
.HasColumnName("allow_reassign_to_other_approvers");
@@ -135,8 +140,8 @@ namespace Tnsu.ApprovalRoute.Infrastructure.Persistence.Migrations
.HasColumnType("character varying(32)")
.HasColumnName("project_role");
b.Property<Guid>("RouteId")
.HasColumnType("uuid")
b.Property<int>("RouteId")
.HasColumnType("integer")
.HasColumnName("route_id");
b.Property<string>("Status")
@@ -1,5 +1,5 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Migrations;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
#nullable disable
@@ -15,7 +15,8 @@ namespace Tnsu.ApprovalRoute.Infrastructure.Persistence.Migrations
name: "request_types",
columns: table => new
{
id = table.Column<Guid>(type: "uuid", nullable: false),
id = table.Column<int>(type: "integer", nullable: false)
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
name = table.Column<string>(type: "character varying(256)", maxLength: 256, nullable: false),
page_url = table.Column<string>(type: "character varying(512)", maxLength: 512, nullable: false)
},
@@ -28,9 +29,10 @@ namespace Tnsu.ApprovalRoute.Infrastructure.Persistence.Migrations
name: "template_routes",
columns: table => new
{
id = table.Column<Guid>(type: "uuid", nullable: false),
id = table.Column<int>(type: "integer", nullable: false)
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
route_type = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false),
request_type_id = table.Column<Guid>(type: "uuid", nullable: false),
request_type_id = table.Column<int>(type: "integer", nullable: false),
department = table.Column<string>(type: "character varying(256)", maxLength: 256, nullable: true),
company = table.Column<string>(type: "character varying(256)", maxLength: 256, nullable: false),
by_project = table.Column<bool>(type: "boolean", nullable: false),
@@ -51,14 +53,15 @@ namespace Tnsu.ApprovalRoute.Infrastructure.Persistence.Migrations
name: "template_route_steps",
columns: table => new
{
id = table.Column<Guid>(type: "uuid", nullable: false),
id = table.Column<int>(type: "integer", nullable: false)
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
order_no = table.Column<int>(type: "integer", nullable: false),
executor_email = table.Column<string>(type: "character varying(256)", maxLength: 256, nullable: false),
position = table.Column<string>(type: "character varying(128)", maxLength: 128, nullable: false),
project_role = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false),
head_type = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false),
status = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false),
route_id = table.Column<Guid>(type: "uuid", nullable: false),
route_id = table.Column<int>(type: "integer", nullable: false),
allow_reassign_to_other_approvers = table.Column<bool>(type: "boolean", nullable: false)
},
constraints: table =>
@@ -1,5 +1,4 @@
// <auto-generated />
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
@@ -24,11 +23,13 @@ namespace Tnsu.ApprovalRoute.Infrastructure.Persistence.Migrations
modelBuilder.Entity("Tnsu.ApprovalRoute.Domain.Entities.RequestType", b =>
{
b.Property<Guid>("Id")
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid")
.HasColumnType("integer")
.HasColumnName("id");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(256)
@@ -49,11 +50,13 @@ namespace Tnsu.ApprovalRoute.Infrastructure.Persistence.Migrations
modelBuilder.Entity("Tnsu.ApprovalRoute.Domain.Entities.TemplateRoute", b =>
{
b.Property<Guid>("Id")
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid")
.HasColumnType("integer")
.HasColumnName("id");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<bool>("ByProject")
.HasColumnType("boolean")
.HasColumnName("by_project");
@@ -69,8 +72,8 @@ namespace Tnsu.ApprovalRoute.Infrastructure.Persistence.Migrations
.HasColumnType("character varying(256)")
.HasColumnName("department");
b.Property<Guid>("RequestTypeId")
.HasColumnType("uuid")
b.Property<int>("RequestTypeId")
.HasColumnType("integer")
.HasColumnName("request_type_id");
b.Property<bool>("RequiresControl")
@@ -95,11 +98,13 @@ namespace Tnsu.ApprovalRoute.Infrastructure.Persistence.Migrations
modelBuilder.Entity("Tnsu.ApprovalRoute.Domain.Entities.TemplateRouteStep", b =>
{
b.Property<Guid>("Id")
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid")
.HasColumnType("integer")
.HasColumnName("id");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<bool>("AllowReassignToOtherApprovers")
.HasColumnType("boolean")
.HasColumnName("allow_reassign_to_other_approvers");
@@ -132,8 +137,8 @@ namespace Tnsu.ApprovalRoute.Infrastructure.Persistence.Migrations
.HasColumnType("character varying(32)")
.HasColumnName("project_role");
b.Property<Guid>("RouteId")
.HasColumnType("uuid")
b.Property<int>("RouteId")
.HasColumnType("integer")
.HasColumnName("route_id");
b.Property<string>("Status")
@@ -33,7 +33,7 @@ public sealed class RequestTypeServiceTests(PostgresDatabaseFixture fixture) : I
public async Task GetAsync_UnknownId_ReturnsFailedResult()
{
// Action
var result = await _service.GetAsync(Guid.NewGuid(), CancellationToken.None);
var result = await _service.GetAsync(999999, CancellationToken.None);
// Assert
result.IsFailed.ShouldBeTrue();
@@ -60,7 +60,7 @@ public sealed class RequestTypeServiceTests(PostgresDatabaseFixture fixture) : I
{
// Action
var result = await _service.UpdateAsync(
Guid.NewGuid(), new UpdateRequestTypeRequest("X", "/x"), CancellationToken.None);
999999, new UpdateRequestTypeRequest("X", "/x"), CancellationToken.None);
// Assert
result.IsFailed.ShouldBeTrue();
@@ -34,7 +34,7 @@ public sealed class TemplateRouteServiceTests : IClassFixture<PostgresDatabaseFi
_requestTypeService = _services.GetRequiredService<RequestTypeService>();
}
private async Task<Guid> CreateRequestTypeAsync(string name) =>
private async Task<int> CreateRequestTypeAsync(string name) =>
(await _requestTypeService.CreateAsync(new CreateRequestTypeRequest(name, $"/{name}"), CancellationToken.None)).Value.Id;
[Fact(DisplayName = "Создание маршрута и получение его по Id возвращает сохранённые данные")]
@@ -62,7 +62,7 @@ public sealed class TemplateRouteServiceTests : IClassFixture<PostgresDatabaseFi
{
// Action
var result = await _service.CreateAsync(
new CreateTemplateRouteRequest(RouteType.Sequential, Guid.NewGuid(), Department, Company, ByProject: false, RequiresControl: false),
new CreateTemplateRouteRequest(RouteType.Sequential, 999999, Department, Company, ByProject: false, RequiresControl: false),
CancellationToken.None);
// Assert
@@ -202,7 +202,7 @@ public sealed class TemplateRouteServiceTests : IClassFixture<PostgresDatabaseFi
{
// Action
var resolved = await _service.ResolveAsync(
new ResolveTemplateRouteRequest(Guid.NewGuid(), "someone@tnsu.kz", null, RouteStepStatus.Approval),
new ResolveTemplateRouteRequest(999999, "someone@tnsu.kz", null, RouteStepStatus.Approval),
CancellationToken.None);
// Assert
@@ -24,7 +24,7 @@ public sealed class TemplateRouteStepServiceTests : IClassFixture<PostgresDataba
_requestTypeService = services.GetRequiredService<RequestTypeService>();
}
private async Task<Guid> CreateRouteAsync(string requestTypeName, bool byProject)
private async Task<int> CreateRouteAsync(string requestTypeName, bool byProject)
{
var requestTypeId = (await _requestTypeService.CreateAsync(
new CreateRequestTypeRequest(requestTypeName, $"/{requestTypeName}"), CancellationToken.None)).Value.Id;
@@ -41,7 +41,7 @@ public sealed class TemplateRouteStepServiceTests : IClassFixture<PostgresDataba
{
// Action
var result = await _service.CreateAsync(
Guid.NewGuid(),
999999,
new CreateTemplateRouteStepRequest(1, "a@b.kz", "Engineer", ProjectRole.None, HeadType.None, RouteStepStatus.Approval, false),
CancellationToken.None);