NejCommon.NET/Controllers/AutoController.cs
honzapatCZ 77a536ee79 init
2024-09-02 17:30:42 +02:00

173 lines
7.0 KiB
C#

using System.Linq.Expressions;
using System.Reflection;
using ApiSourceGeneratorHelper;
using AutoMapPropertyHelper;
using EntityFrameworkCore.Projectables;
using EntityFrameworkCore.Projectables.Extensions;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.HttpResults;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using NejAccountingAPI.Controllers;
using NejAccountingAPI.Models;
using NejCommon.Utils;
using Swashbuckle.AspNetCore.Annotations;
namespace NejCommon.Controllers
{
public abstract class AutoController<TType, TRequest, TResponse> : AutoController<Company, TType, TRequest, TResponse> where TType : class, new() where TRequest : IAutomappedAttribute<TType, TRequest>, new() where TResponse : IAutomappedAttribute<TType, TResponse>, new()
{
public AutoController(AppDbContext appDb, IServiceProvider providers) : base(appDb, providers)
{
}
}
public abstract class AutoController<TOwner, TType, TRequest, TResponse> : AutoController<TOwner, TType, TResponse, TRequest, TResponse, TResponse, TRequest, TResponse>
where TType : class, new()
where TRequest : IAutomappedAttribute<TType, TRequest>, new()
where TResponse : IAutomappedAttribute<TType, TResponse>, new()
{
public AutoController(AppDbContext appDb, IServiceProvider providers) : base(appDb, providers)
{
}
}
/// <summary>
///
/// </summary>
/// <typeparam name="TType">The underyling type</typeparam>
/// <typeparam name="TRequest">The request type</typeparam>
/// <typeparam name="TResponse">The response type</typeparam>
[ApiController]
public abstract class AutoController<TOwner, TType, TGetAllResponse, TCreateRequest, TCreateResponse, TGetResponse, TUpdateRequest, TUpdateResponse> : ControllerBase
where TType : class, new()
where TGetAllResponse : IAutomappedAttribute<TType, TGetAllResponse>, new()
where TCreateRequest : IAutomappedAttribute<TType, TCreateRequest>, new()
where TCreateResponse : IAutomappedAttribute<TType, TCreateResponse>, new()
where TGetResponse : IAutomappedAttribute<TType, TGetResponse>, new()
where TUpdateRequest : IAutomappedAttribute<TType, TUpdateRequest>, new()
where TUpdateResponse : IAutomappedAttribute<TType, TUpdateResponse>, new()
{
protected readonly AppDbContext db;
protected readonly IServiceProvider providers;
public AutoController(AppDbContext appDb, IServiceProvider providers) : base()
{
db = appDb;
this.providers = providers;
}
protected abstract IQueryable<TType> GetQuery(TOwner comp);
protected virtual TType AssociateWithParent(TType entity, TOwner comp)
{
if (typeof(TOwner) != typeof(Company))
{
throw new NotImplementedException("Special parent association not implemented");
}
var props = typeof(TType).GetProperty("Company");
if (props == null)
{
//not implemented
throw new NotImplementedException("Special parent association not implemented");
}
props.SetValue(entity, comp);
return entity;
}
protected virtual IQueryable<TType> ApplyDefaultOrdering(IQueryable<TType> query)
{
return query;
}
/// <summary>
/// Get all the <typeparamref name="TType"/>
/// </summary>
/// <response code="200">Success</response>
/// <response code="0">There was an error</response>
[HttpGet]
public virtual async Task<Results<BadRequest<Error>, Ok<PaginationResponse<TGetAllResponse>>>> GetAll(TOwner company, [FromQuery] Pagination pag)
{
var data = await ApplyDefaultOrdering(GetQuery(company)).AsNoTrackingWithIdentityResolution().ApplyPaginationRes<TType, TGetAllResponse>(providers, pag);
//Console.Writeline(data.Data);
return TypedResults.Ok(data);
}
/// <summary>
/// Creates the <typeparamref name="TType"/>
/// </summary>
/// <param name="body"></param>
/// <response code="201">Success</response>
/// <response code="0">There was an error</response>
[HttpPost]
public virtual async Task<Results<BadRequest<Error>, CreatedAtRoute<TCreateResponse>>> Create(TOwner company, [FromBody] TCreateRequest body)
{
var entity = db.Create<TType>();
entity = AssociateWithParent(entity, company);
await db.AddAsync(entity);
body.ApplyTo(providers, entity);
return await db.ApiSaveChangesAsyncCreate<TType, TCreateResponse>(providers, entity);
}
/// <summary>
/// Gets the <typeparamref name="TType"/>
/// </summary>
/// <param name="entity"></param>
/// <response code="200">Success</response>
/// <response code="0">There was an error</response>
[HttpGet]
[Route("{id}/")]
public virtual async Task<Results<NotFound, Ok<TGetResponse>>> Get([FromServices][ModelBinder(Name = "id")] TType entity)
{
var dat = new TGetResponse().ApplyFrom(providers, entity);
return TypedResults.Ok(dat);
}
/// <summary>
/// Delete company.
/// </summary>
/// <param name="entity"></param>
/// <response code="200">Success</response>
/// <response code="0">There was an error</response>
[HttpDelete]
[Route("{id}/")]
public virtual async Task<Results<BadRequest<Error>, Ok>> Delete([FromServices][ModelBinder(Name = "id")] TType entity)
{
db.Remove(entity!);
return await db.ApiSaveChangesAsync(TypedResults.Ok());
}
/// <summary>
/// Update company.
/// </summary>
/// <param name="entity"></param>
/// <param name="body"></param>
/// <response code="200">Success</response>
/// <response code="0">There was an error</response>
[HttpPut]
[Route("{id}/")]
public virtual async Task<Results<NotFound, BadRequest<Error>, Ok<TUpdateResponse>>> Update([FromServices][ModelBinder(Name = "id")] TType entity, [FromBody] TUpdateRequest body)
{/*
if(entity is InvoiceBase inv){
//Console.Writeline(inv.InvoiceItems.Count);
}*/
body.ApplyTo(providers, entity);
var dat = new TUpdateResponse().ApplyFrom(providers, entity);
var res = await db.ApiSaveChangesAsyncOk<TType, TUpdateResponse>(providers, entity);
//use the private constructor thru reflection
var ctor = typeof(Results<NotFound, BadRequest<Error>, Ok<TUpdateResponse>>).GetConstructors(BindingFlags.NonPublic | BindingFlags.Instance)[0];
return (Results<NotFound, BadRequest<Error>, Ok<TUpdateResponse>>)ctor.Invoke(new object[] { res.Result });
}
}
}