Контакты, начало

This commit is contained in:
Olga Nemt 2023-10-09 12:20:00 +05:00
parent 01f04c7ea5
commit a48381f10f
13 changed files with 8978 additions and 33 deletions

View File

@ -36,11 +36,11 @@ namespace AsbCloudApp.Data
/// <summary>
/// DTO компании с пользователями
/// </summary>
public class CompanyWithUsersDto: CompanyDto
public class CompanyWithContactsDto: CompanyDto
{
/// <summary>
/// Пользователи компании
/// </summary>
public IEnumerable<UserContactDto> Users { get; set; } = Enumerable.Empty<UserContactDto>();
public IEnumerable<ContactDto> Contacts { get; set; } = Enumerable.Empty<ContactDto>();
}
}

View File

@ -1,14 +1,52 @@
namespace AsbCloudApp.Data.User
using System;
using System.ComponentModel.DataAnnotations;
namespace AsbCloudApp.Data.User
{
/// <summary>
/// Пользователь - контакт
/// Контакт
/// </summary>
public class UserContactDto : UserDto
public class ContactDto : IId
{
/// <inheritdoc/>
public int Id { get; set; }
/// <summary>
/// является ли пользователь контактом
/// ФИО
/// </summary>
public bool IsContact { get; set; }
[StringLength(260, MinimumLength = 0, ErrorMessage = "Допустимая длина ФИО от 1 до 260 символов")]
public string FIO { get; set; } = null!;
/// <summary>
/// Email
/// </summary>
[Required]
[StringLength(260, MinimumLength = 3, ErrorMessage = "Допустимая длина email от 3 до 260 символов")]
public string Email { get; set; } = null!;
/// <summary>
/// Phone
/// </summary>
[StringLength(50, MinimumLength = 1, ErrorMessage = "Допустимая длина телефона от 1 до 50 символов")]
public string? Phone { get; set; }
/// <summary>
/// Должность
/// </summary>
[StringLength(100, MinimumLength = 1, ErrorMessage = "Допустимая длина должности от 1 до 100 символов")]
public string? Position { get; set; }
/// <summary>
/// Id компании
/// </summary>
[Required]
public int IdCompany { get; set; }
/// <summary>
/// DTO компании
/// </summary>
public CompanyDto? Company { get; set; }
}
}

View File

@ -1,4 +1,5 @@
using AsbCloudApp.Data;
using AsbCloudApp.Data.User;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
@ -11,22 +12,30 @@ namespace AsbCloudApp.Services
public interface IWellContactService
{
/// <summary>
/// Полуение пользователей по ключу скважины и типу контакта
/// Получение пользователей по ключу скважины и типу контакта
/// </summary>
/// <param name="wellId">ключ скважины</param>
/// <param name="contactTypeId">тип контакта</param>
/// <param name="token"></param>
/// <returns></returns>
Task<IEnumerable<CompanyWithUsersDto>> GetAsync(int wellId, int contactTypeId, CancellationToken token);
Task<IEnumerable<CompanyWithContactsDto>> GetAsync(int wellId, int contactTypeId, CancellationToken token);
/// <summary>
/// Получение типов контаков
/// Получение типов контактов
/// </summary>
/// <param name="idWell">ключ скважины</param>
/// <param name="token"></param>
/// <returns></returns>
Task<IEnumerable<CompanyTypeDto>> GetTypesAsync(int idWell, CancellationToken token);
/// <summary>
/// Добавление контакта
/// </summary>
/// <param name="contactDto"></param>
/// <param name="token"></param>
/// <returns></returns>
Task<int> InsertAsync(ContactDto contactDto, CancellationToken token);
/// <summary>
/// Обновление контактов по ключу скважины, типу контакта и ключам пользователей
/// </summary>

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,48 @@
using Microsoft.EntityFrameworkCore.Migrations;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
#nullable disable
namespace AsbCloudDb.Migrations
{
public partial class Add_Contacts : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "t_contact",
columns: table => new
{
id = table.Column<int>(type: "integer", nullable: false)
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
id_company = table.Column<int>(type: "integer", nullable: false),
fio = table.Column<string>(type: "character varying(255)", maxLength: 255, nullable: false, comment: "ФИО"),
email = table.Column<string>(type: "character varying(255)", maxLength: 255, nullable: false, comment: "email"),
phone = table.Column<string>(type: "character varying(50)", maxLength: 50, nullable: true, comment: "номер телефона"),
position = table.Column<string>(type: "character varying(255)", maxLength: 255, nullable: true, comment: "должность")
},
constraints: table =>
{
table.PrimaryKey("PK_t_contact", x => x.id);
table.ForeignKey(
name: "FK_t_contact_t_company_id_company",
column: x => x.id_company,
principalTable: "t_company",
principalColumn: "id",
onDelete: ReferentialAction.Cascade);
},
comment: "Контакты");
migrationBuilder.CreateIndex(
name: "IX_t_contact_id_company",
table: "t_contact",
column: "id_company");
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "t_contact");
}
}
}

View File

@ -154,6 +154,54 @@ namespace AsbCloudDb.Migrations
});
});
modelBuilder.Entity("AsbCloudDb.Model.Contact", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer")
.HasColumnName("id");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<string>("Email")
.IsRequired()
.HasMaxLength(255)
.HasColumnType("character varying(255)")
.HasColumnName("email")
.HasComment("email");
b.Property<string>("FIO")
.IsRequired()
.HasMaxLength(255)
.HasColumnType("character varying(255)")
.HasColumnName("fio")
.HasComment("ФИО");
b.Property<int>("IdCompany")
.HasColumnType("integer")
.HasColumnName("id_company");
b.Property<string>("Phone")
.HasMaxLength(50)
.HasColumnType("character varying(50)")
.HasColumnName("phone")
.HasComment("номер телефона");
b.Property<string>("Position")
.HasMaxLength(255)
.HasColumnType("character varying(255)")
.HasColumnName("position")
.HasComment("должность");
b.HasKey("Id");
b.HasIndex("IdCompany");
b.ToTable("t_contact");
b.HasComment("Контакты");
});
modelBuilder.Entity("AsbCloudDb.Model.DailyReport.DailyReport", b =>
{
b.Property<int>("IdWell")
@ -7719,6 +7767,17 @@ namespace AsbCloudDb.Migrations
b.Navigation("CompanyType");
});
modelBuilder.Entity("AsbCloudDb.Model.Contact", b =>
{
b.HasOne("AsbCloudDb.Model.Company", "Company")
.WithMany("Contacts")
.HasForeignKey("IdCompany")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Company");
});
modelBuilder.Entity("AsbCloudDb.Model.DailyReport.DailyReport", b =>
{
b.HasOne("AsbCloudDb.Model.Well", "Well")
@ -8538,6 +8597,8 @@ namespace AsbCloudDb.Migrations
modelBuilder.Entity("AsbCloudDb.Model.Company", b =>
{
b.Navigation("Contacts");
b.Navigation("RelationCompaniesWells");
b.Navigation("Users");

View File

@ -81,7 +81,7 @@ namespace AsbCloudDb.Model
public DbSet<NotificationCategory> NotificationCategories => Set<NotificationCategory>();
public DbSet<Manual> Manuals => Set<Manual>();
public DbSet<ManualDirectory> ManualDirectories => Set<ManualDirectory>();
public DbSet<Contact> Contacts => Set<Contact>();
public AsbCloudDbContext() : base()
{

View File

@ -29,5 +29,8 @@ namespace AsbCloudDb.Model
[InverseProperty(nameof(RelationCompanyWell.Company))]
public virtual ICollection<RelationCompanyWell> RelationCompaniesWells { get; set; } = null!;
[InverseProperty(nameof(Contact.Company))]
public virtual ICollection<Contact> Contacts { get; set; } = null!;
}
}

View File

@ -0,0 +1,38 @@
using Microsoft.EntityFrameworkCore;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace AsbCloudDb.Model
{
[Table("t_contact"), Comment("Контакты")]
public partial class Contact : IId
{
[Key]
[Column("id")]
public int Id { get; set; }
[Column("id_company")]
public int IdCompany { get; set; }
[Column("fio"), Comment("ФИО")]
[StringLength(255)]
public string FIO { get; set; } = string.Empty;
[Column("email"), Comment("email")]
[StringLength(255)]
public string Email { get; set; } = string.Empty;
[Column("phone"), Comment("номер телефона")]
[StringLength(50)]
public string? Phone { get; set; }
[Column("position"), Comment("должность")]
[StringLength(255)]
public string? Position { get; set; }
[ForeignKey(nameof(IdCompany))]
[InverseProperty(nameof(Model.Company.Contacts))]
public virtual Company Company { get; set; } = null!;
}
}

View File

@ -74,6 +74,7 @@ namespace AsbCloudDb.Model
DbSet<NotificationCategory> NotificationCategories { get; }
DbSet<Manual> Manuals { get; }
DbSet<ManualDirectory> ManualDirectories { get; }
DbSet<Contact> Contacts { get; }
DatabaseFacade Database { get; }
Task<int> RefreshMaterializedViewAsync(string mwName, CancellationToken token);

View File

@ -4,6 +4,7 @@ using AsbCloudApp.Services;
using AsbCloudDb.Model;
using Mapster;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
@ -20,30 +21,18 @@ namespace AsbCloudInfrastructure.Services
this.db = db;
}
public async Task<IEnumerable<CompanyWithUsersDto>> GetAsync(int wellId, int contactTypeId, CancellationToken token)
public async Task<IEnumerable<CompanyWithContactsDto>> GetAsync(int wellId, int contactTypeId, CancellationToken token)
{
var query = db.Companies
.Where(c => c.IdCompanyType == contactTypeId)
.Where(c => c.RelationCompaniesWells.Any(rc => rc.IdWell == wellId))
.Select(c => new CompanyWithUsersDto()
.Select(c => new CompanyWithContactsDto()
{
Caption = c.Caption,
Id = c.Id,
Users = c.Users
.Where(u => u.IdState == 1)
.OrderBy(u => u.Surname)
.Select(u => new UserContactDto()
{
Id = u.Id,
Name = u.Name,
Patronymic = u.Patronymic,
Surname = u.Surname,
Company = u.Company.Adapt<CompanyDto>(),
Email = u.Email,
Phone = u.Phone,
Position = u.Position,
IsContact = u.RelationContactsWells.Any(rel => rel.IdWell == wellId)
})
Contacts = c.Contacts
.OrderBy(u => u.FIO)
.Select(u => u.Adapt<ContactDto>())
});
var entities = await query.AsNoTracking()
@ -69,6 +58,23 @@ namespace AsbCloudInfrastructure.Services
return dtos;
}
public async Task<int> InsertAsync(ContactDto contactDto, CancellationToken token)
{
var entity = contactDto.Adapt<Contact>();
//var entity = new Contact()
//{
// Email = contactDto.Email,
// FIO = contactDto.FIO,
// IdCompany = contactDto.IdCompany,
// Phone = contactDto.Phone,
// Position = contactDto.Position
//};
db.Contacts.Add(entity);
await db.SaveChangesAsync(token).ConfigureAwait(false);
return entity.Id;
}
public async Task<int> UpdateRangeAsync(int idWell, int contactTypeId, IEnumerable<int> userIds, CancellationToken token)
{
var items = db.RelationContactsWells

View File

@ -1,5 +1,7 @@
using AsbCloudApp.Data;
using AsbCloudApp.Data.User;
using AsbCloudApp.Services;
using AsbCloudInfrastructure.Repository;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using System;
@ -14,6 +16,7 @@ namespace AsbCloudWebApi.Controllers
/// контроллер с контактной информацией по скважине
/// </summary>
[ApiController]
[Route("api/[controller]")]
[Authorize]
public class WellContactController : ControllerBase
{
@ -48,7 +51,7 @@ namespace AsbCloudWebApi.Controllers
/// <param name="token"></param>
/// <returns></returns>
[HttpGet("api/well/{idWell}/contactType/{contactTypeId}")]
[ProducesResponseType(typeof(IEnumerable<CompanyWithUsersDto>), (int)System.Net.HttpStatusCode.OK)]
[ProducesResponseType(typeof(IEnumerable<CompanyWithContactsDto>), (int)System.Net.HttpStatusCode.OK)]
public async Task<IActionResult> GetAsync(int idWell, int contactTypeId, CancellationToken token)
{
if (!await CanUserAccessToWellAsync(idWell, token).ConfigureAwait(false))
@ -58,6 +61,24 @@ namespace AsbCloudWebApi.Controllers
return Ok(result);
}
/// <summary>
/// добавление нового контакта
/// </summary>
/// <param name="contactDto">контакт</param>
/// <param name="token"></param>
/// <returns></returns>
[HttpPost]
[ProducesResponseType(typeof(ContactDto), (int)System.Net.HttpStatusCode.OK)]
public async Task<IActionResult> InsertAsync(
[FromBody] ContactDto contactDto,
CancellationToken token)
{
var result = await wellContactsRepository.InsertAsync(contactDto, token)
.ConfigureAwait(false);
return Ok(result);
}
/// <summary>
/// Создание контактов по ключу скважины, типу контакта и ключам пользователей

View File

@ -7,10 +7,10 @@
}
},
"ConnectionStrings": {
"DefaultConnection": "Host=localhost;Database=postgres;Username=postgres;Password=q;Persist Security Info=True",
"DebugConnection": "Host=localhost;Database=postgres;Username=postgres;Password=q;Persist Security Info=True;Include Error Detail=True",
"ServerConnection": "Host=192.168.1.70;Database=postgres;Username=postgres;Password=q;Persist Security Info=True",
"LocalConnection": "Host=localhost;Database=postgres;Username=postgres;Password=q;Persist Security Info=True"
"DefaultConnection": "Host=localhost;Database=postgres2;Username=postgres;Password=q;Persist Security Info=True",
"DebugConnection": "Host=localhost;Database=postgres2;Username=postgres;Password=q;Persist Security Info=True;Include Error Detail=True",
"ServerConnection": "Host=192.168.1.70;Database=postgres2;Username=postgres;Password=q;Persist Security Info=True",
"LocalConnection": "Host=localhost;Database=postgres2;Username=postgres;Password=q;Persist Security Info=True"
},
"AllowedHosts": "*",
//"userLimits": {