ИНН и описание
This commit is contained in:
@@ -41,6 +41,16 @@ public record RegisterUserCommand : IRequest<Guid>
|
||||
/// </summary>
|
||||
public string? CompanyName { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// ИНН (необязательно).
|
||||
/// </summary>
|
||||
public string? Inn { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Описание исполнителя или компании (необязательно, максимум 2048 символов).
|
||||
/// </summary>
|
||||
public string? Description { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Роль (по умолчанию User).
|
||||
/// </summary>
|
||||
@@ -68,26 +78,28 @@ public class RegisterUserCommandHandler : IRequestHandler<RegisterUserCommand, G
|
||||
|
||||
var passwordHash = _passwordHasher.HashPassword(request.Password);
|
||||
var account = Account.Create(request.Phone, passwordHash);
|
||||
|
||||
|
||||
// Добавляем роль, если она отличается от User
|
||||
if (request.Role != Role.User && request.Role != Role.Admin)
|
||||
if (request.Role != Role.User && request.Role != Role.Admin)
|
||||
{
|
||||
// Здесь можно добавить логику проверки прав, но для MVP разрешим
|
||||
account.Roles.Add(request.Role);
|
||||
}
|
||||
|
||||
var profile = UserProfile.Create(
|
||||
account.Id,
|
||||
request.FirstName,
|
||||
request.LastName,
|
||||
request.Patronymic,
|
||||
request.CompanyName);
|
||||
account.Id,
|
||||
request.FirstName,
|
||||
request.LastName,
|
||||
request.Patronymic,
|
||||
request.CompanyName,
|
||||
request.Inn,
|
||||
request.Description);
|
||||
|
||||
account.SetProfile(profile);
|
||||
|
||||
|
||||
await _accountRepository.AddAsync(account, cancellationToken);
|
||||
// Предполагаем, что AccountRepository.AddAsync сохранит всё дерево сущностей
|
||||
|
||||
|
||||
return account.Id;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,6 +10,8 @@ public record UpdateProfileCommand : IRequest
|
||||
public string LastName { get; init; } = default!;
|
||||
public string? Patronymic { get; init; }
|
||||
public string? CompanyName { get; init; }
|
||||
public string? Inn { get; init; }
|
||||
public string? Description { get; init; }
|
||||
}
|
||||
|
||||
public class UpdateProfileCommandHandler : IRequestHandler<UpdateProfileCommand>
|
||||
@@ -46,7 +48,9 @@ public class UpdateProfileCommandHandler : IRequestHandler<UpdateProfileCommand>
|
||||
request.FirstName,
|
||||
request.LastName,
|
||||
request.Patronymic,
|
||||
request.CompanyName);
|
||||
request.CompanyName,
|
||||
request.Inn,
|
||||
request.Description);
|
||||
|
||||
await _accountRepository.UpdateAsync(account, cancellationToken);
|
||||
}
|
||||
|
||||
@@ -7,13 +7,15 @@ namespace Nashel.Modules.Identity.Application.Queries.GetProfile;
|
||||
public record GetProfileQuery : IRequest<ProfileResponse>;
|
||||
|
||||
public record ProfileResponse(
|
||||
Guid Id,
|
||||
string Phone,
|
||||
Guid Id,
|
||||
string Phone,
|
||||
List<string> Roles,
|
||||
string FirstName,
|
||||
string LastName,
|
||||
string? Patronymic,
|
||||
string? CompanyName,
|
||||
string? Inn,
|
||||
string? Description,
|
||||
string FullName,
|
||||
string? AvatarUrl,
|
||||
List<string> Competencies);
|
||||
@@ -50,13 +52,15 @@ public class GetProfileQueryHandler : IRequestHandler<GetProfileQuery, ProfileRe
|
||||
}
|
||||
|
||||
return new ProfileResponse(
|
||||
account.Id,
|
||||
account.Phone,
|
||||
account.Id,
|
||||
account.Phone,
|
||||
account.Roles.Select(r => r.ToString()).ToList(),
|
||||
account.Profile.FirstName,
|
||||
account.Profile.LastName,
|
||||
account.Profile.Patronymic,
|
||||
account.Profile.CompanyName,
|
||||
account.Profile.Inn,
|
||||
account.Profile.Description,
|
||||
fullName,
|
||||
account.Profile.AvatarUrl,
|
||||
account.Profile.Competencies.Select(c => c.Name).ToList());
|
||||
|
||||
@@ -27,5 +27,12 @@ public class RegisterUserCommandValidator : AbstractValidator<RegisterUserComman
|
||||
RuleFor(x => x.CompanyName)
|
||||
.NotEmpty().WithMessage("Название компании обязательно для юридических лиц")
|
||||
.When(x => x.Role == Role.Company);
|
||||
|
||||
RuleFor(x => x.Inn)
|
||||
.Length(10).WithMessage("ИНН должен содержать 10 цифр")
|
||||
.When(x => x.Role == Role.Company);
|
||||
|
||||
RuleFor(x => x.Description)
|
||||
.MaximumLength(2048).WithMessage("Описание не может превышать 2048 символов");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,5 +14,8 @@ public class UpdateProfileCommandValidator : AbstractValidator<UpdateProfileComm
|
||||
RuleFor(x => x.LastName)
|
||||
.NotEmpty().WithMessage("Фамилия обязательна")
|
||||
.MinimumLength(2).WithMessage("Фамилия должна содержать минимум 2 символа");
|
||||
|
||||
RuleFor(x => x.Description)
|
||||
.MaximumLength(2048).WithMessage("Описание не может превышать 2048 символов");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,38 +6,51 @@ namespace Nashel.Modules.Identity.Domain.Aggregates;
|
||||
public class UserProfile : Entity<Guid>
|
||||
{
|
||||
private const int MaxCompetencies = 50;
|
||||
private const int MaxDescriptionLength = 2048;
|
||||
private readonly List<Competency> _competencies = new();
|
||||
|
||||
public string FirstName { get; private set; }
|
||||
public string LastName { get; private set; }
|
||||
public string? Patronymic { get; private set; }
|
||||
public string? CompanyName { get; private set; }
|
||||
public string? Inn { get; private set; }
|
||||
public string? Description { get; private set; }
|
||||
public string? AvatarUrl { get; private set; }
|
||||
public IReadOnlyCollection<Competency> Competencies => _competencies.AsReadOnly();
|
||||
|
||||
// EF Core constructor
|
||||
private UserProfile() { }
|
||||
|
||||
private UserProfile(Guid id, string firstName, string lastName, string? patronymic, string? companyName)
|
||||
private UserProfile(Guid id, string firstName, string lastName, string? patronymic, string? companyName, string? inn, string? description)
|
||||
{
|
||||
Id = id;
|
||||
FirstName = firstName;
|
||||
LastName = lastName;
|
||||
Patronymic = patronymic;
|
||||
CompanyName = companyName;
|
||||
Inn = inn;
|
||||
Description = description;
|
||||
}
|
||||
|
||||
public static UserProfile Create(Guid id, string firstName, string lastName, string? patronymic, string? companyName)
|
||||
public static UserProfile Create(Guid id, string firstName, string lastName, string? patronymic, string? companyName, string? inn, string? description)
|
||||
{
|
||||
return new UserProfile(id, firstName, lastName, patronymic, companyName);
|
||||
if (!string.IsNullOrEmpty(description) && description.Length > MaxDescriptionLength)
|
||||
throw new ArgumentException($"Описание не может превышать {MaxDescriptionLength} символов", nameof(description));
|
||||
|
||||
return new UserProfile(id, firstName, lastName, patronymic, companyName, inn, description);
|
||||
}
|
||||
|
||||
public void Update(string firstName, string lastName, string? patronymic, string? companyName)
|
||||
public void Update(string firstName, string lastName, string? patronymic, string? companyName, string? inn, string? description)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(description) && description.Length > MaxDescriptionLength)
|
||||
throw new ArgumentException($"Описание не может превышать {MaxDescriptionLength} символов", nameof(description));
|
||||
|
||||
FirstName = firstName;
|
||||
LastName = lastName;
|
||||
Patronymic = patronymic;
|
||||
CompanyName = companyName;
|
||||
Inn = inn;
|
||||
Description = description;
|
||||
}
|
||||
|
||||
public void UpdateAvatar(string? avatarUrl)
|
||||
@@ -48,7 +61,7 @@ public class UserProfile : Entity<Guid>
|
||||
public void UpdateCompetencies(IEnumerable<Competency> competencies)
|
||||
{
|
||||
var competencyList = competencies.ToList();
|
||||
|
||||
|
||||
if (competencyList.Count > MaxCompetencies)
|
||||
throw new InvalidOperationException($"Нельзя добавить больше {MaxCompetencies} компетенций");
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ using System.Text.Json;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||
using Nashel.Modules.Identity.Domain.Aggregates;
|
||||
using Nashel.Modules.Identity.Domain.Entities;
|
||||
using Nashel.Modules.Identity.Domain.Enums;
|
||||
|
||||
namespace Nashel.Modules.Identity.Infrastructure.Persistence.Configurations;
|
||||
@@ -30,5 +31,11 @@ public class AccountConfiguration : IEntityTypeConfiguration<Account>
|
||||
v => JsonSerializer.Serialize(v, (JsonSerializerOptions?)null),
|
||||
v => JsonSerializer.Deserialize<List<Role>>(v, (JsonSerializerOptions?)null) ?? new List<Role>())
|
||||
.HasColumnType("jsonb");
|
||||
|
||||
// Настройка связи с UserProfile (один-к-одному)
|
||||
builder.HasOne(x => x.Profile)
|
||||
.WithOne()
|
||||
.HasForeignKey<UserProfile>(p => p.Id)
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,6 +28,12 @@ public class UserProfileConfiguration : IEntityTypeConfiguration<UserProfile>
|
||||
builder.Property(x => x.CompanyName)
|
||||
.HasMaxLength(200);
|
||||
|
||||
builder.Property(x => x.Inn)
|
||||
.HasMaxLength(10);
|
||||
|
||||
builder.Property(x => x.Description)
|
||||
.HasMaxLength(2048);
|
||||
|
||||
builder.Property(x => x.AvatarUrl)
|
||||
.HasMaxLength(500);
|
||||
|
||||
|
||||
@@ -0,0 +1,158 @@
|
||||
// <auto-generated />
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
using Nashel.Modules.Identity.Infrastructure.Persistence;
|
||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Nashel.Modules.Identity.Infrastructure.Persistence.Migrations
|
||||
{
|
||||
[DbContext(typeof(IdentityDbContext))]
|
||||
[Migration("20260215191454_AddDescriptionToUserProfile")]
|
||||
partial class AddDescriptionToUserProfile
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder
|
||||
.HasAnnotation("ProductVersion", "10.0.2")
|
||||
.HasAnnotation("Relational:MaxIdentifierLength", 63);
|
||||
|
||||
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
|
||||
|
||||
modelBuilder.Entity("Nashel.Modules.Identity.Domain.Aggregates.Account", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<string>("PasswordHash")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("Phone")
|
||||
.IsRequired()
|
||||
.HasMaxLength(20)
|
||||
.HasColumnType("character varying(20)");
|
||||
|
||||
b.Property<string>("Roles")
|
||||
.IsRequired()
|
||||
.HasColumnType("jsonb");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("Phone")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("Accounts", "identity");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Nashel.Modules.Identity.Domain.Aggregates.UserProfile", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<string>("AvatarUrl")
|
||||
.HasMaxLength(500)
|
||||
.HasColumnType("character varying(500)");
|
||||
|
||||
b.Property<string>("CompanyName")
|
||||
.HasMaxLength(200)
|
||||
.HasColumnType("character varying(200)");
|
||||
|
||||
b.Property<string>("Description")
|
||||
.HasMaxLength(2048)
|
||||
.HasColumnType("character varying(2048)");
|
||||
|
||||
b.Property<string>("FirstName")
|
||||
.IsRequired()
|
||||
.HasMaxLength(100)
|
||||
.HasColumnType("character varying(100)");
|
||||
|
||||
b.Property<string>("LastName")
|
||||
.IsRequired()
|
||||
.HasMaxLength(100)
|
||||
.HasColumnType("character varying(100)");
|
||||
|
||||
b.Property<string>("Patronymic")
|
||||
.HasMaxLength(100)
|
||||
.HasColumnType("character varying(100)");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("UserProfiles", "identity");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Nashel.Modules.Identity.Domain.Entities.Competency", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasMaxLength(100)
|
||||
.HasColumnType("character varying(100)");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("Name")
|
||||
.IsUnique()
|
||||
.HasDatabaseName("IX_Competencies_Name");
|
||||
|
||||
b.ToTable("Competencies", "identity");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("UserProfileCompetencies", b =>
|
||||
{
|
||||
b.Property<Guid>("UserProfileId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<Guid>("CompetencyId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.HasKey("UserProfileId", "CompetencyId");
|
||||
|
||||
b.HasIndex("CompetencyId");
|
||||
|
||||
b.ToTable("UserProfileCompetencies", "identity");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Nashel.Modules.Identity.Domain.Aggregates.UserProfile", b =>
|
||||
{
|
||||
b.HasOne("Nashel.Modules.Identity.Domain.Aggregates.Account", null)
|
||||
.WithOne("Profile")
|
||||
.HasForeignKey("Nashel.Modules.Identity.Domain.Aggregates.UserProfile", "Id")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("UserProfileCompetencies", b =>
|
||||
{
|
||||
b.HasOne("Nashel.Modules.Identity.Domain.Entities.Competency", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("CompetencyId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("Nashel.Modules.Identity.Domain.Aggregates.UserProfile", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("UserProfileId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Nashel.Modules.Identity.Domain.Aggregates.Account", b =>
|
||||
{
|
||||
b.Navigation("Profile")
|
||||
.IsRequired();
|
||||
});
|
||||
#pragma warning restore 612, 618
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Nashel.Modules.Identity.Infrastructure.Persistence.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class AddDescriptionToUserProfile : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "Description",
|
||||
schema: "identity",
|
||||
table: "UserProfiles",
|
||||
type: "character varying(2048)",
|
||||
maxLength: 2048,
|
||||
nullable: true);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropColumn(
|
||||
name: "Description",
|
||||
schema: "identity",
|
||||
table: "UserProfiles");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,162 @@
|
||||
// <auto-generated />
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
using Nashel.Modules.Identity.Infrastructure.Persistence;
|
||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Nashel.Modules.Identity.Infrastructure.Persistence.Migrations
|
||||
{
|
||||
[DbContext(typeof(IdentityDbContext))]
|
||||
[Migration("20260215200327_AddInnToUserProfile")]
|
||||
partial class AddInnToUserProfile
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder
|
||||
.HasAnnotation("ProductVersion", "10.0.2")
|
||||
.HasAnnotation("Relational:MaxIdentifierLength", 63);
|
||||
|
||||
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
|
||||
|
||||
modelBuilder.Entity("Nashel.Modules.Identity.Domain.Aggregates.Account", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<string>("PasswordHash")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("Phone")
|
||||
.IsRequired()
|
||||
.HasMaxLength(20)
|
||||
.HasColumnType("character varying(20)");
|
||||
|
||||
b.Property<string>("Roles")
|
||||
.IsRequired()
|
||||
.HasColumnType("jsonb");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("Phone")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("Accounts", "identity");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Nashel.Modules.Identity.Domain.Aggregates.UserProfile", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<string>("AvatarUrl")
|
||||
.HasMaxLength(500)
|
||||
.HasColumnType("character varying(500)");
|
||||
|
||||
b.Property<string>("CompanyName")
|
||||
.HasMaxLength(200)
|
||||
.HasColumnType("character varying(200)");
|
||||
|
||||
b.Property<string>("Description")
|
||||
.HasMaxLength(2048)
|
||||
.HasColumnType("character varying(2048)");
|
||||
|
||||
b.Property<string>("FirstName")
|
||||
.IsRequired()
|
||||
.HasMaxLength(100)
|
||||
.HasColumnType("character varying(100)");
|
||||
|
||||
b.Property<string>("Inn")
|
||||
.HasMaxLength(10)
|
||||
.HasColumnType("character varying(10)");
|
||||
|
||||
b.Property<string>("LastName")
|
||||
.IsRequired()
|
||||
.HasMaxLength(100)
|
||||
.HasColumnType("character varying(100)");
|
||||
|
||||
b.Property<string>("Patronymic")
|
||||
.HasMaxLength(100)
|
||||
.HasColumnType("character varying(100)");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("UserProfiles", "identity");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Nashel.Modules.Identity.Domain.Entities.Competency", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasMaxLength(100)
|
||||
.HasColumnType("character varying(100)");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("Name")
|
||||
.IsUnique()
|
||||
.HasDatabaseName("IX_Competencies_Name");
|
||||
|
||||
b.ToTable("Competencies", "identity");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("UserProfileCompetencies", b =>
|
||||
{
|
||||
b.Property<Guid>("UserProfileId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<Guid>("CompetencyId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.HasKey("UserProfileId", "CompetencyId");
|
||||
|
||||
b.HasIndex("CompetencyId");
|
||||
|
||||
b.ToTable("UserProfileCompetencies", "identity");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Nashel.Modules.Identity.Domain.Aggregates.UserProfile", b =>
|
||||
{
|
||||
b.HasOne("Nashel.Modules.Identity.Domain.Aggregates.Account", null)
|
||||
.WithOne("Profile")
|
||||
.HasForeignKey("Nashel.Modules.Identity.Domain.Aggregates.UserProfile", "Id")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("UserProfileCompetencies", b =>
|
||||
{
|
||||
b.HasOne("Nashel.Modules.Identity.Domain.Entities.Competency", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("CompetencyId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("Nashel.Modules.Identity.Domain.Aggregates.UserProfile", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("UserProfileId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Nashel.Modules.Identity.Domain.Aggregates.Account", b =>
|
||||
{
|
||||
b.Navigation("Profile")
|
||||
.IsRequired();
|
||||
});
|
||||
#pragma warning restore 612, 618
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Nashel.Modules.Identity.Infrastructure.Persistence.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class AddInnToUserProfile : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "Inn",
|
||||
schema: "identity",
|
||||
table: "UserProfiles",
|
||||
type: "character varying(10)",
|
||||
maxLength: 10,
|
||||
nullable: true);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropColumn(
|
||||
name: "Inn",
|
||||
schema: "identity",
|
||||
table: "UserProfiles");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,162 @@
|
||||
// <auto-generated />
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
using Nashel.Modules.Identity.Infrastructure.Persistence;
|
||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Nashel.Modules.Identity.Infrastructure.Persistence.Migrations
|
||||
{
|
||||
[DbContext(typeof(IdentityDbContext))]
|
||||
[Migration("20260215202659_FixAccountProfileRelation")]
|
||||
partial class FixAccountProfileRelation
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder
|
||||
.HasAnnotation("ProductVersion", "10.0.2")
|
||||
.HasAnnotation("Relational:MaxIdentifierLength", 63);
|
||||
|
||||
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
|
||||
|
||||
modelBuilder.Entity("Nashel.Modules.Identity.Domain.Aggregates.Account", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<string>("PasswordHash")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("Phone")
|
||||
.IsRequired()
|
||||
.HasMaxLength(20)
|
||||
.HasColumnType("character varying(20)");
|
||||
|
||||
b.Property<string>("Roles")
|
||||
.IsRequired()
|
||||
.HasColumnType("jsonb");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("Phone")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("Accounts", "identity");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Nashel.Modules.Identity.Domain.Aggregates.UserProfile", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<string>("AvatarUrl")
|
||||
.HasMaxLength(500)
|
||||
.HasColumnType("character varying(500)");
|
||||
|
||||
b.Property<string>("CompanyName")
|
||||
.HasMaxLength(200)
|
||||
.HasColumnType("character varying(200)");
|
||||
|
||||
b.Property<string>("Description")
|
||||
.HasMaxLength(2048)
|
||||
.HasColumnType("character varying(2048)");
|
||||
|
||||
b.Property<string>("FirstName")
|
||||
.IsRequired()
|
||||
.HasMaxLength(100)
|
||||
.HasColumnType("character varying(100)");
|
||||
|
||||
b.Property<string>("Inn")
|
||||
.HasMaxLength(10)
|
||||
.HasColumnType("character varying(10)");
|
||||
|
||||
b.Property<string>("LastName")
|
||||
.IsRequired()
|
||||
.HasMaxLength(100)
|
||||
.HasColumnType("character varying(100)");
|
||||
|
||||
b.Property<string>("Patronymic")
|
||||
.HasMaxLength(100)
|
||||
.HasColumnType("character varying(100)");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("UserProfiles", "identity");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Nashel.Modules.Identity.Domain.Entities.Competency", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasMaxLength(100)
|
||||
.HasColumnType("character varying(100)");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("Name")
|
||||
.IsUnique()
|
||||
.HasDatabaseName("IX_Competencies_Name");
|
||||
|
||||
b.ToTable("Competencies", "identity");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("UserProfileCompetencies", b =>
|
||||
{
|
||||
b.Property<Guid>("UserProfileId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<Guid>("CompetencyId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.HasKey("UserProfileId", "CompetencyId");
|
||||
|
||||
b.HasIndex("CompetencyId");
|
||||
|
||||
b.ToTable("UserProfileCompetencies", "identity");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Nashel.Modules.Identity.Domain.Aggregates.UserProfile", b =>
|
||||
{
|
||||
b.HasOne("Nashel.Modules.Identity.Domain.Aggregates.Account", null)
|
||||
.WithOne("Profile")
|
||||
.HasForeignKey("Nashel.Modules.Identity.Domain.Aggregates.UserProfile", "Id")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("UserProfileCompetencies", b =>
|
||||
{
|
||||
b.HasOne("Nashel.Modules.Identity.Domain.Entities.Competency", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("CompetencyId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("Nashel.Modules.Identity.Domain.Aggregates.UserProfile", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("UserProfileId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Nashel.Modules.Identity.Domain.Aggregates.Account", b =>
|
||||
{
|
||||
b.Navigation("Profile")
|
||||
.IsRequired();
|
||||
});
|
||||
#pragma warning restore 612, 618
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Nashel.Modules.Identity.Infrastructure.Persistence.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class FixAccountProfileRelation : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -62,11 +62,19 @@ namespace Nashel.Modules.Identity.Infrastructure.Persistence.Migrations
|
||||
.HasMaxLength(200)
|
||||
.HasColumnType("character varying(200)");
|
||||
|
||||
b.Property<string>("Description")
|
||||
.HasMaxLength(2048)
|
||||
.HasColumnType("character varying(2048)");
|
||||
|
||||
b.Property<string>("FirstName")
|
||||
.IsRequired()
|
||||
.HasMaxLength(100)
|
||||
.HasColumnType("character varying(100)");
|
||||
|
||||
b.Property<string>("Inn")
|
||||
.HasMaxLength(10)
|
||||
.HasColumnType("character varying(10)");
|
||||
|
||||
b.Property<string>("LastName")
|
||||
.IsRequired()
|
||||
.HasMaxLength(100)
|
||||
|
||||
@@ -16,6 +16,11 @@ public class AccountRepository : IAccountRepository
|
||||
|
||||
public async Task AddAsync(Account account, CancellationToken cancellationToken)
|
||||
{
|
||||
// Явно добавляем профиль, чтобы EF Core сохранил его в таблицу UserProfiles
|
||||
if (account.Profile != null)
|
||||
{
|
||||
await _context.UserProfiles.AddAsync(account.Profile, cancellationToken);
|
||||
}
|
||||
await _context.Accounts.AddAsync(account, cancellationToken);
|
||||
await _context.SaveChangesAsync(cancellationToken);
|
||||
}
|
||||
@@ -37,6 +42,11 @@ public class AccountRepository : IAccountRepository
|
||||
|
||||
public async Task UpdateAsync(Account account, CancellationToken cancellationToken)
|
||||
{
|
||||
// Явно обновляем профиль, чтобы EF Core сохранил изменения в таблицу UserProfiles
|
||||
if (account.Profile != null)
|
||||
{
|
||||
_context.UserProfiles.Update(account.Profile);
|
||||
}
|
||||
_context.Accounts.Update(account);
|
||||
await _context.SaveChangesAsync(cancellationToken);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user