Add TaxSecction on QuoteCreate
All checks were successful
CI/CD Pipeline / Build and Deploy with Docker Compose (push) Successful in 5m31s

This commit is contained in:
Leandro Hernan Rojas 2025-05-06 15:58:35 -03:00
parent f1bc764bbf
commit b1ab76aa5a
18 changed files with 552 additions and 30 deletions

View File

@ -0,0 +1,14 @@
using Domain.Entities;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Core.Interfaces
{
public interface ITaxTypeDom
{
Task<IEnumerable<ETaxType>> GetAllActiveAsync();
}
}

View File

@ -0,0 +1,32 @@
using Core.Interfaces;
using Domain.Entities;
using Models.Interfaces;
using System.Reflection;
namespace Core.Services
{
public class TaxTypeService: ITaxTypeDom
{
#region Declaraciones y Constructor
private readonly IPhOhArcataxTypeRepository _repository;
public TaxTypeService(IPhOhArcataxTypeRepository repository)
{
_repository = repository ?? throw new ArgumentNullException(nameof(repository));
}
#endregion
#region Metodos de clases
public async Task<IEnumerable<ETaxType>> GetAllActiveAsync()
{
try
{
return await _repository.GetAllActiveAsync();
}
catch (Exception ex)
{
var method = MethodBase.GetCurrentMethod()?.Name ?? "UnknownMethod";
throw new Exception($"{method} Message: {ex.Message}", ex);
}
}
#endregion
}
}

View File

@ -0,0 +1,40 @@
namespace Domain.Entities
{
public class ETaxType
{
/// <summary>
/// Identificador único del impuesto.
/// </summary>
public int Id { get; set; }
/// <summary>
/// Código oficial del impuesto según ARCA.
/// </summary>
public int TaxCode { get; set; }
/// <summary>
/// Descripción del impuesto.
/// </summary>
public string Description { get; set; } = null!;
/// <summary>
/// Porcentaje de la alícuota aplicable al impuesto, expresado como un valor decimal. Una alícuota del 21%, se debe almacenar el valor 21.00
/// </summary>
public decimal Taxrate { get; set; }
/// <summary>
/// Indica si el impuesto está activo (1) o inactivo (0).
/// </summary>
public bool IsActive { get; set; }
/// <summary>
/// Fecha de creación del registro.
/// </summary>
public DateTime CreatedAt { get; set; }
/// <summary>
/// Fecha de última modificación del registro.
/// </summary>
public DateTime? ModifiedAt { get; set; }
}
}

View File

@ -7,7 +7,7 @@
<NuGetPackageRoot Condition=" '$(NuGetPackageRoot)' == '' ">$(UserProfile)\.nuget\packages\</NuGetPackageRoot> <NuGetPackageRoot Condition=" '$(NuGetPackageRoot)' == '' ">$(UserProfile)\.nuget\packages\</NuGetPackageRoot>
<NuGetPackageFolders Condition=" '$(NuGetPackageFolders)' == '' ">C:\Users\maski\.nuget\packages\;C:\Program Files (x86)\Microsoft Visual Studio\Shared\NuGetPackages</NuGetPackageFolders> <NuGetPackageFolders Condition=" '$(NuGetPackageFolders)' == '' ">C:\Users\maski\.nuget\packages\;C:\Program Files (x86)\Microsoft Visual Studio\Shared\NuGetPackages</NuGetPackageFolders>
<NuGetProjectStyle Condition=" '$(NuGetProjectStyle)' == '' ">PackageReference</NuGetProjectStyle> <NuGetProjectStyle Condition=" '$(NuGetProjectStyle)' == '' ">PackageReference</NuGetProjectStyle>
<NuGetToolVersion Condition=" '$(NuGetToolVersion)' == '' ">6.13.2</NuGetToolVersion> <NuGetToolVersion Condition=" '$(NuGetToolVersion)' == '' ">6.13.1</NuGetToolVersion>
</PropertyGroup> </PropertyGroup>
<ItemGroup Condition=" '$(ExcludeRestorePackageImports)' != 'true' "> <ItemGroup Condition=" '$(ExcludeRestorePackageImports)' != 'true' ">
<SourceRoot Include="C:\Users\maski\.nuget\packages\" /> <SourceRoot Include="C:\Users\maski\.nuget\packages\" />

View File

@ -0,0 +1,14 @@
using Domain.Entities;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Models.Interfaces
{
public interface IPhOhArcataxTypeRepository
{
Task<IEnumerable<ETaxType>> GetAllActiveAsync();
}
}

View File

@ -23,6 +23,11 @@ public partial class PhOhArcataxType
/// </summary> /// </summary>
public string Description { get; set; } = null!; public string Description { get; set; } = null!;
/// <summary>
/// Porcentaje de la alícuota aplicable al impuesto, expresado como un valor decimal. Una alícuota del 21%, se debe almacenar el valor 21.00
/// </summary>
public decimal Taxrate { get; set; }
/// <summary> /// <summary>
/// Indica si el impuesto está activo (1) o inactivo (0). /// Indica si el impuesto está activo (1) o inactivo (0).
/// </summary> /// </summary>

View File

@ -141,6 +141,10 @@ public partial class PhronCareOperationsHubContext : DbContext
entity.Property(e => e.TaxCode) entity.Property(e => e.TaxCode)
.HasComment("Código oficial del impuesto según AFIP.") .HasComment("Código oficial del impuesto según AFIP.")
.HasColumnName("tax_code"); .HasColumnName("tax_code");
entity.Property(e => e.Taxrate)
.HasComment("Porcentaje de la alícuota aplicable al impuesto, expresado como un valor decimal. Una alícuota del 21%, se debe almacenar el valor 21.00")
.HasColumnType("decimal(18, 0)")
.HasColumnName("taxrate");
}); });
modelBuilder.Entity<PhOhTaxCondition>(entity => modelBuilder.Entity<PhOhTaxCondition>(entity =>

View File

@ -0,0 +1,33 @@
using Domain.Entities;
using Microsoft.EntityFrameworkCore;
using Models.Helpers;
using Models.Interfaces;
using Models.Models;
namespace Models.Repositories
{
public class PhOhArcataxTypeRepository (PhronCareOperationsHubContext context) : IPhOhArcataxTypeRepository
{
#region Declaraciones y Constructor
private readonly PhronCareOperationsHubContext _context = context;
#endregion
#region Metodos de clase
public async Task<IEnumerable<ETaxType>> GetAllActiveAsync()
{
var taxTypes= await _context.PhOhArcataxTypes
.Where(t => t.IsActive)
.Select(t => new PhOhArcataxType
{
Id = t.Id,
TaxCode = t.TaxCode,
Description = t.Description,
Taxrate=t.Taxrate,
IsActive=t.IsActive
})
.ToListAsync();
return taxTypes.Select(EntityMapper.MapEntity<PhOhArcataxType, ETaxType>);
}
#endregion
}
}

View File

@ -7,7 +7,7 @@
<NuGetPackageRoot Condition=" '$(NuGetPackageRoot)' == '' ">$(UserProfile)\.nuget\packages\</NuGetPackageRoot> <NuGetPackageRoot Condition=" '$(NuGetPackageRoot)' == '' ">$(UserProfile)\.nuget\packages\</NuGetPackageRoot>
<NuGetPackageFolders Condition=" '$(NuGetPackageFolders)' == '' ">C:\Users\maski\.nuget\packages\;C:\Program Files (x86)\Microsoft Visual Studio\Shared\NuGetPackages</NuGetPackageFolders> <NuGetPackageFolders Condition=" '$(NuGetPackageFolders)' == '' ">C:\Users\maski\.nuget\packages\;C:\Program Files (x86)\Microsoft Visual Studio\Shared\NuGetPackages</NuGetPackageFolders>
<NuGetProjectStyle Condition=" '$(NuGetProjectStyle)' == '' ">PackageReference</NuGetProjectStyle> <NuGetProjectStyle Condition=" '$(NuGetProjectStyle)' == '' ">PackageReference</NuGetProjectStyle>
<NuGetToolVersion Condition=" '$(NuGetToolVersion)' == '' ">6.13.2</NuGetToolVersion> <NuGetToolVersion Condition=" '$(NuGetToolVersion)' == '' ">6.13.1</NuGetToolVersion>
</PropertyGroup> </PropertyGroup>
<ItemGroup Condition=" '$(ExcludeRestorePackageImports)' != 'true' "> <ItemGroup Condition=" '$(ExcludeRestorePackageImports)' != 'true' ">
<SourceRoot Include="C:\Users\maski\.nuget\packages\" /> <SourceRoot Include="C:\Users\maski\.nuget\packages\" />

View File

@ -152,26 +152,6 @@ namespace phronCare.API.Controllers.Sales
#endregion #endregion
#region Exportación
[HttpPost("exportfiltered")]
public async Task<IActionResult> ExportFiltered([FromBody] QuoteSearchParams searchParams)
{
try
{
var file = await _quoteService.ExportFilteredQuotesToExcelAsync(searchParams);
return File(file,
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
"Presupuestos.xlsx");
}
catch (Exception ex)
{
return BadRequest(ex.Message);
}
}
#endregion
#region Impuestos (QuoteTaxes) #region Impuestos (QuoteTaxes)
[HttpGet("{quoteId:int}/taxes")] [HttpGet("{quoteId:int}/taxes")]
@ -241,5 +221,96 @@ namespace phronCare.API.Controllers.Sales
} }
#endregion #endregion
#region Ajustes Comerciales (QuoteAdjustments)
[HttpGet("{quoteId:int}/adjustments")]
public async Task<IActionResult> GetAdjustments(int quoteId)
{
try
{
var adjustments = await _quoteService.GetAdjustmentsByQuoteIdAsync(quoteId);
return Ok(adjustments);
}
catch (Exception ex)
{
var methodName = MethodBase.GetCurrentMethod()?.Name ?? "UnknownMethod";
return StatusCode(500, $"{methodName} Message: {ex.Message}");
}
}
[HttpPost("{quoteId:int}/adjustments")]
public async Task<IActionResult> AddAdjustment(int quoteId, [FromBody] EQuoteAdjustment adjustment)
{
try
{
if (adjustment == null || quoteId != adjustment.QuoteheaderId)
return BadRequest("Datos inválidos para el ajuste.");
var result = await _quoteService.AddAdjustmentAsync(adjustment);
return Ok(result);
}
catch (Exception ex)
{
var methodName = MethodBase.GetCurrentMethod()?.Name ?? "UnknownMethod";
return StatusCode(500, $"{methodName} Message: {ex.Message}");
}
}
[HttpPut("adjustments")]
public async Task<IActionResult> UpdateAdjustment([FromBody] EQuoteAdjustment adjustment)
{
try
{
if (adjustment == null || adjustment.Id <= 0)
return BadRequest("Datos inválidos para actualizar el ajuste.");
await _quoteService.UpdateAdjustmentAsync(adjustment);
return Ok("Ajuste actualizado correctamente.");
}
catch (Exception ex)
{
var methodName = MethodBase.GetCurrentMethod()?.Name ?? "UnknownMethod";
return StatusCode(500, $"{methodName} Message: {ex.Message}");
}
}
[HttpDelete("adjustments/{adjustmentId:int}")]
public async Task<IActionResult> DeleteAdjustment(int adjustmentId)
{
try
{
await _quoteService.DeleteAdjustmentAsync(adjustmentId);
return Ok("Ajuste eliminado correctamente.");
}
catch (Exception ex)
{
var methodName = MethodBase.GetCurrentMethod()?.Name ?? "UnknownMethod";
return StatusCode(500, $"{methodName} Message: {ex.Message}");
}
}
#endregion
#region Exportación
[HttpPost("exportfiltered")]
public async Task<IActionResult> ExportFiltered([FromBody] QuoteSearchParams searchParams)
{
try
{
var file = await _quoteService.ExportFilteredQuotesToExcelAsync(searchParams);
return File(file,
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
"Presupuestos.xlsx");
}
catch (Exception ex)
{
return BadRequest(ex.Message);
}
}
#endregion
} }
} }

View File

@ -0,0 +1,29 @@
using Core.Interfaces;
using Microsoft.AspNetCore.Mvc;
namespace phronCare.API.Controllers.Sales
{
[Route("api/[controller]")]
[ApiController]
public class TaxTypeController : ControllerBase
{
private readonly ITaxTypeDom _taxTypeDom;
public TaxTypeController(ITaxTypeDom taxTypeDom)
{
_taxTypeDom = taxTypeDom ?? throw new ArgumentNullException(nameof(taxTypeDom));
}
[HttpGet("GetAll")]
public async Task<IActionResult> GetAll()
{
try
{
var result = await _taxTypeDom.GetAllActiveAsync();
return Ok(result);
}
catch (Exception ex)
{
return BadRequest(ex.Message);
}
}
}
}

View File

@ -239,7 +239,8 @@ static void RepositorysAndServices(WebApplicationBuilder builder)
builder.Services.AddScoped<IAdjustmentReasonDom, AdjustmentReasonService>(); builder.Services.AddScoped<IAdjustmentReasonDom, AdjustmentReasonService>();
builder.Services.AddScoped<IPhSAdjustmentReasonRepository, PhSAdjustmentReasonRepository>(); builder.Services.AddScoped<IPhSAdjustmentReasonRepository, PhSAdjustmentReasonRepository>();
builder.Services.AddScoped<ITaxTypeDom, TaxTypeService>();
builder.Services.AddScoped<IPhOhArcataxTypeRepository, PhOhArcataxTypeRepository>();
builder.Services.AddScoped<IQuoteDom, QuoteService>(); builder.Services.AddScoped<IQuoteDom, QuoteService>();
builder.Services.AddScoped<IPhSQuoteHeaderRepository, PhSQuoteHeaderRepository>(); builder.Services.AddScoped<IPhSQuoteHeaderRepository, PhSQuoteHeaderRepository>();

View File

@ -1556,6 +1556,43 @@
} }
] ]
}, },
{
"ContainingType": "phronCare.API.Controllers.Sales.QuoteController",
"Method": "GetAdjustments",
"RelativePath": "api/Quote/{quoteId}/adjustments",
"HttpMethod": "GET",
"IsController": true,
"Order": 0,
"Parameters": [
{
"Name": "quoteId",
"Type": "System.Int32",
"IsRequired": true
}
],
"ReturnTypes": []
},
{
"ContainingType": "phronCare.API.Controllers.Sales.QuoteController",
"Method": "AddAdjustment",
"RelativePath": "api/Quote/{quoteId}/adjustments",
"HttpMethod": "POST",
"IsController": true,
"Order": 0,
"Parameters": [
{
"Name": "quoteId",
"Type": "System.Int32",
"IsRequired": true
},
{
"Name": "adjustment",
"Type": "Domain.Entities.EQuoteAdjustment",
"IsRequired": true
}
],
"ReturnTypes": []
},
{ {
"ContainingType": "phronCare.API.Controllers.Sales.QuoteController", "ContainingType": "phronCare.API.Controllers.Sales.QuoteController",
"Method": "GetTaxes", "Method": "GetTaxes",
@ -1593,6 +1630,38 @@
], ],
"ReturnTypes": [] "ReturnTypes": []
}, },
{
"ContainingType": "phronCare.API.Controllers.Sales.QuoteController",
"Method": "UpdateAdjustment",
"RelativePath": "api/Quote/adjustments",
"HttpMethod": "PUT",
"IsController": true,
"Order": 0,
"Parameters": [
{
"Name": "adjustment",
"Type": "Domain.Entities.EQuoteAdjustment",
"IsRequired": true
}
],
"ReturnTypes": []
},
{
"ContainingType": "phronCare.API.Controllers.Sales.QuoteController",
"Method": "DeleteAdjustment",
"RelativePath": "api/Quote/adjustments/{adjustmentId}",
"HttpMethod": "DELETE",
"IsController": true,
"Order": 0,
"Parameters": [
{
"Name": "adjustmentId",
"Type": "System.Int32",
"IsRequired": true
}
],
"ReturnTypes": []
},
{ {
"ContainingType": "phronCare.API.Controllers.Sales.QuoteController", "ContainingType": "phronCare.API.Controllers.Sales.QuoteController",
"Method": "GetAll", "Method": "GetAll",
@ -1802,6 +1871,16 @@
], ],
"ReturnTypes": [] "ReturnTypes": []
}, },
{
"ContainingType": "phronCare.API.Controllers.Sales.TaxTypeController",
"Method": "GetAll",
"RelativePath": "api/TaxType/GetAll",
"HttpMethod": "GET",
"IsController": true,
"Order": 0,
"Parameters": [],
"ReturnTypes": []
},
{ {
"ContainingType": "phronCare.API.Controllers.TestController", "ContainingType": "phronCare.API.Controllers.TestController",
"Method": "GetAdministradores", "Method": "GetAdministradores",

View File

@ -0,0 +1,123 @@
@using Blazored.Modal
@using Blazored.Modal.Services
@using Blazored.Typeahead
@using Domain.Entities
@inject Services.Lookups.ISalesLookupService SalesLookupService
<EditForm Model="_model" OnValidSubmit="HandleValidSubmit">
<DataAnnotationsValidator />
<ValidationSummary />
<div class="card" style="zoom:90%;">
<div class="card-header">
<h5 class="card-title mb-0">Agregar Impuesto</h5>
</div>
<div class="card-body">
<div class="mb-3">
<label class="form-label">Tipo de Impuesto *</label>
<BlazoredTypeahead TItem="ETaxType" TValue="ETaxType"
SearchMethod="SearchTaxTypes"
Value="_selectedTaxType"
ValueChanged="OnTaxTypeSelected"
ValueExpression="@(() => _selectedTaxType)"
TextProperty="Description"
Placeholder="Buscar tipo de impuesto...">
<ResultTemplate Context="item">
@item.Description (@item.Taxrate.ToString("0.#")%)
</ResultTemplate>
<SelectedTemplate Context="item">
@item.Description
</SelectedTemplate>
</BlazoredTypeahead>
</div>
<div class="mb-3">
<label class="form-label">Base Imponible *</label>
<InputNumber class="form-control"
Value="_model.TaxableAmount"
ValueChanged="(decimal val) => OnValueChanged(val, (m, v) => m.TaxableAmount = v)"
ValueExpression="@(() => _model.TaxableAmount)" />
</div>
<div class="mb-3">
<label class="form-label">Alícuota (%) *</label>
<InputNumber class="form-control"
Value="_model.Taxrate"
ValueChanged="(decimal val) => OnValueChanged(val, (m, v) => m.Taxrate = v)"
ValueExpression="@(() => _model.Taxrate)" />
</div>
<div class="mb-3">
<label class="form-label">Importe del impuesto</label>
<InputNumber class="form-control" @bind-Value="_model.Taxamount" readonly />
</div>
<div class="form-check form-switch">
<InputCheckbox class="form-check-input" @bind-Value="_model.IsIncludedInPrice" />
<label class="form-check-label ms-2">¿Incluido en precio?</label>
</div>
</div>
<div class="card-footer text-end">
<button type="submit" class="btn btn-success">Agregar</button>
<button type="button" class="btn btn-secondary ms-2" @onclick="Cancelar">Cancelar</button>
</div>
</div>
</EditForm>
@code {
[CascadingParameter] public BlazoredModalInstance ModalInstance { get; set; } = default!;
[Parameter] public decimal NetAmount { get; set; }
private ETaxType? _selectedTaxType;
private EQuoteTax _model = new();
private List<ETaxType> _taxTypes = new();
protected override async Task OnInitializedAsync()
{
_taxTypes = (await SalesLookupService.GetTaxTypesAsync()).ToList();
_model.TaxableAmount = NetAmount;
Recalculate();
}
private Task<IEnumerable<ETaxType>> SearchTaxTypes(string searchTerm)
{
var result = string.IsNullOrWhiteSpace(searchTerm)
? _taxTypes
: _taxTypes.Where(t => t.Description.Contains(searchTerm, StringComparison.OrdinalIgnoreCase));
return Task.FromResult(result);
}
private Task OnTaxTypeSelected(ETaxType selected)
{
_model.Taxname = selected.Description;
_model.Taxcode = selected.TaxCode.ToString();
_model.Taxrate = selected.Taxrate;
Recalculate();
return Task.CompletedTask;
}
private void OnValueChanged(decimal value, Action<EQuoteTax, decimal> setter)
{
setter(_model, value);
Recalculate();
}
private void Recalculate()
{
_model.Taxamount = Math.Round(_model.TaxableAmount * (_model.Taxrate / 100), 2);
}
private async Task HandleValidSubmit()
{
if (string.IsNullOrWhiteSpace(_model.Taxname))
{
return;
}
await ModalInstance.CloseAsync(ModalResult.Ok(_model));
}
private async Task Cancelar()
{
await ModalInstance.CancelAsync();
}
}

View File

@ -205,8 +205,12 @@
<!-- Totales + Ajustes --> <!-- Totales + Ajustes -->
<div class="row justify-content-end mt-3"> <div class="row justify-content-end mt-3">
<div class="col-md-4"> <div class="col-md-4">
<label class="form-label d-block">Ajustes comerciales</label> <label class="form-label d-flex justify-content-between align-items-center">
Ajustes comerciales
<button class="btn btn-sm btn-outline-success mt-2" @onclick="OpenAdjustmentModal">
<i class="fas fa-plus me-1"></i> Agregar
</button>
</label>
@if (_quoteModel.PhSQuoteAdjustments.Any()) @if (_quoteModel.PhSQuoteAdjustments.Any())
{ {
<div class="mb-2"> <div class="mb-2">
@ -226,11 +230,51 @@
<p class="text-muted">Sin ajustes.</p> <p class="text-muted">Sin ajustes.</p>
} }
<button class="btn btn-sm btn-outline-success mt-2" @onclick="OpenAdjustmentModal">
<i class="fas fa-plus me-1"></i> Agregar ajuste
</button>
</div> </div>
<!-- Impuestos -->
<div class="col-md-4"> <div class="col-md-4">
<label class="form-label d-flex justify-content-between align-items-center">
Impuestos
<button class="btn btn-sm btn-outline-success mt-2" @onclick="AddNewTax">
<i class="fas fa-percentage me-1"></i> Agregar
</button>
</label>
@if (_quoteModel.PhSQuoteTaxes.Any())
{
<div class="table-responsive">
<table class="table table-sm table-bordered mb-0">
<thead class="table-light">
<tr>
<th>Nombre</th>
<th class="text-end">%</th>
<th class="text-end">Importe</th>
<th style="width: 30px;"></th>
</tr>
</thead>
<tbody>
@foreach (var tax in _quoteModel.PhSQuoteTaxes)
{
<tr>
<td>@tax.Taxname</td>
<td class="text-end">@tax.Taxrate.ToString("0.##")%</td>
<td class="text-end">$@tax.Taxamount.ToString("N2")</td>
<td class="text-center">
<button class="btn btn-sm btn-danger" @onclick="() => RemoveTax(tax)">
<i class="fas fa-trash-alt"></i>
</button>
</td>
</tr>
}
</tbody>
</table>
</div>
}
else
{
<p class="text-muted"><em>No hay impuestos aplicados</em></p>
}
</div> </div>
<div class="col-md-4"> <div class="col-md-4">
<ul class="list-group"> <ul class="list-group">
@ -369,5 +413,30 @@
{ {
_quoteModel.PhSQuoteAdjustments.Remove(adj); _quoteModel.PhSQuoteAdjustments.Remove(adj);
} }
private async Task AddNewTax()
{
var parameters = new ModalParameters();
parameters.Add(nameof(QuoteTaxQuickAddModal.NetAmount), _netAmount);
var options = new ModalOptions
{
HideHeader = true,
Size = ModalSize.Small
};
var modal = Modal.Show<QuoteTaxQuickAddModal>("", parameters, options);
var result = await modal.Result;
if (!result.Cancelled && result.Data is EQuoteTax newTax)
{
_quoteModel.PhSQuoteTaxes.Add(newTax);
RecalculateTotals();
}
}
private void RemoveTax(EQuoteTax tax)
{
_quoteModel.PhSQuoteTaxes.Remove(tax);
RecalculateTotals();
}
} }

View File

@ -12,5 +12,6 @@ namespace phronCare.UIBlazor.Services.Lookups
Task<IEnumerable<ELookUpItem>> SearchBussinessUnitsAsync(string filtro); Task<IEnumerable<ELookUpItem>> SearchBussinessUnitsAsync(string filtro);
Task<IEnumerable<EProductLookupItem>> SearchProductsAsync(string filtro); Task<IEnumerable<EProductLookupItem>> SearchProductsAsync(string filtro);
Task<IEnumerable<EAdjustmentReason>> GetAdjustmentReasonsAsync(); Task<IEnumerable<EAdjustmentReason>> GetAdjustmentReasonsAsync();
Task<IEnumerable<ETaxType>> GetTaxTypesAsync();
} }
} }

View File

@ -49,5 +49,12 @@ namespace phronCare.UIBlazor.Services.Lookups
var items = await _http.GetFromJsonAsync<EProductLookupItem[]>(url); var items = await _http.GetFromJsonAsync<EProductLookupItem[]>(url);
return items ?? Array.Empty<EProductLookupItem>(); return items ?? Array.Empty<EProductLookupItem>();
} }
public async Task<IEnumerable<ETaxType>> GetTaxTypesAsync()
{
var items = await _http.GetFromJsonAsync<ETaxType[]>("api/taxtype/getall");
return items ?? Array.Empty<ETaxType>();
}
} }
} }