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.Models; using NejCommon.Utils; using Swashbuckle.AspNetCore.Annotations; namespace NejCommon.Controllers { public abstract class AutoController : AutoController where TType : class, new() where TRequest : IAutomappedAttribute, new() where TResponse : IAutomappedAttribute, new() { public AutoController(AppDbContext appDb, IServiceProvider providers) : base(appDb, providers) { } } public abstract class AutoController : AutoController where TType : class, new() where TRequest : IAutomappedAttribute, new() where TResponse : IAutomappedAttribute, new() { public AutoController(AppDbContext appDb, IServiceProvider providers) : base(appDb, providers) { } } /// /// /// /// The underyling type /// The request type /// The response type [ApiController] public abstract class AutoController : ControllerBase where TType : class, new() where TGetAllResponse : IAutomappedAttribute, new() where TCreateRequest : IAutomappedAttribute, new() where TCreateResponse : IAutomappedAttribute, new() where TGetResponse : IAutomappedAttribute, new() where TUpdateRequest : IAutomappedAttribute, new() where TUpdateResponse : IAutomappedAttribute, new() { protected readonly AppDbContext db; protected readonly IServiceProvider providers; public AutoController(AppDbContext appDb, IServiceProvider providers) : base() { db = appDb; this.providers = providers; } protected abstract IQueryable 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 ApplyDefaultOrdering(IQueryable query) { return query; } /// /// Get all the /// /// Success /// There was an error [HttpGet] public virtual async Task, Ok>>> GetAll(TOwner company, [FromQuery] Pagination pag) { var data = await ApplyDefaultOrdering(GetQuery(company)).AsNoTrackingWithIdentityResolution().ApplyPaginationRes(providers, pag); //Console.Writeline(data.Data); return TypedResults.Ok(data); } /// /// Creates the /// /// /// Success /// There was an error [HttpPost] public virtual async Task, CreatedAtRoute>> Create(TOwner company, [FromBody] TCreateRequest body) { var entity = db.Create(); entity = AssociateWithParent(entity, company); await db.AddAsync(entity); body.ApplyTo(providers, entity); return await db.ApiSaveChangesAsyncCreate(providers, entity); } /// /// Gets the /// /// /// Success /// There was an error [HttpGet] [Route("{id}/")] public virtual async Task>> Get([FromServices][ModelBinder(Name = "id")] TType entity) { var dat = new TGetResponse().ApplyFrom(providers, entity); return TypedResults.Ok(dat); } /// /// Delete company. /// /// /// Success /// There was an error [HttpDelete] [Route("{id}/")] public virtual async Task, Ok>> Delete([FromServices][ModelBinder(Name = "id")] TType entity) { db.Remove(entity!); return await db.ApiSaveChangesAsync(TypedResults.Ok()); } /// /// Update company. /// /// /// /// Success /// There was an error [HttpPut] [Route("{id}/")] public virtual async Task, Ok>> 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(providers, entity); //use the private constructor thru reflection var ctor = typeof(Results, Ok>).GetConstructors(BindingFlags.NonPublic | BindingFlags.Instance)[0]; return (Results, Ok>)ctor.Invoke(new object[] { res.Result }); } } }