Add Update API UI Customers CRUD
All checks were successful
CI/CD Pipeline / Build and Deploy with Docker Compose (push) Successful in 5m16s
All checks were successful
CI/CD Pipeline / Build and Deploy with Docker Compose (push) Successful in 5m16s
This commit is contained in:
parent
0177366fc9
commit
d5722495ae
@ -1,21 +1,17 @@
|
||||
using Domain.Entities;
|
||||
using Domain.Generics;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Core.Interfaces
|
||||
{
|
||||
public interface ICustomerDom
|
||||
{
|
||||
Task<ECustomer> CreateAsync(ECustomer entity);
|
||||
Task<bool> DeleteAsync(int id);
|
||||
Task<bool> UpdateAsync(ECustomer entity);
|
||||
Task<PagedResult<ECustomer>> GetAllAsync(int page = 1, int pageSize = 50);
|
||||
Task<ECustomer?> GetByIdAsync(int id);
|
||||
Task<PagedResult<ECustomer>> SearchAsync(string? name, string? email, string? document, int page = 1, int pageSize = 50);
|
||||
Task<bool> UpdateAsync(ECustomer entity);
|
||||
Task<byte[]> ExportFilteredCustomersToExcelAsync(CustomerSearchParams searchParams);
|
||||
Task<bool> DeleteAsync(int id);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1,14 +1,9 @@
|
||||
using System.Drawing.Printing;
|
||||
using System.Reflection;
|
||||
using Azure;
|
||||
using System.Reflection.Metadata;
|
||||
using Core.Interfaces;
|
||||
using Core.Interfaces;
|
||||
using Domain.Entities;
|
||||
using Domain.Generics;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Models.Helpers;
|
||||
using Models.Interfaces;
|
||||
using Models.Models;
|
||||
using System.Reflection;
|
||||
using Transversal.Services;
|
||||
|
||||
namespace Core.Services
|
||||
{
|
||||
@ -21,6 +16,7 @@ namespace Core.Services
|
||||
_repository = customerRepository ?? throw new ArgumentNullException(nameof(customerRepository));
|
||||
}
|
||||
#endregion
|
||||
#region Metodos
|
||||
public async Task<PagedResult<ECustomer>> GetAllAsync(int page = 1, int pageSize = 50)
|
||||
{
|
||||
try
|
||||
@ -72,7 +68,6 @@ namespace Core.Services
|
||||
throw new Exception($"{methodName} Message: {ex.Message}", ex);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<bool> UpdateAsync(ECustomer entity)
|
||||
{
|
||||
if (entity is null)
|
||||
@ -90,5 +85,49 @@ namespace Core.Services
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
public async Task<byte[]> ExportFilteredCustomersToExcelAsync(CustomerSearchParams searchParams)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Realiza la búsqueda de clientes con los parámetros proporcionados
|
||||
var searchResult = await SearchAsync(
|
||||
searchParams.Name,
|
||||
searchParams.Email,
|
||||
searchParams.Document,
|
||||
searchParams.Page,
|
||||
searchParams.PageSize
|
||||
);
|
||||
// Verifica que se hayan encontrado resultados
|
||||
if (searchResult?.Items is null || !searchResult.Items.Any())
|
||||
{
|
||||
throw new Exception("No se encontraron clientes para exportar.");
|
||||
}
|
||||
// Llamamos a un método que exporta los datos a Excel
|
||||
var stream = new XLSXExportBase();
|
||||
// Convertimos los resultados de la búsqueda a un formato adecuado para el exportador
|
||||
var customersData = searchResult.Items.Select(c => new
|
||||
{
|
||||
c.Id,
|
||||
c.Name,
|
||||
c.BusinessName,
|
||||
c.Active,
|
||||
c.HasCreditAccount,
|
||||
c.CreditLimit,
|
||||
Address = c.PhSCustomerAddresses.FirstOrDefault()?.Streetaddress1,
|
||||
Email = c.PhSCustomerAddresses.FirstOrDefault()?.Email,
|
||||
Document = c.PhSCustomerDocuments.FirstOrDefault()?.DocumentNumber
|
||||
}).ToList();
|
||||
// Genera el archivo Excel
|
||||
var excelFile = stream.ExportExcel(customersData);
|
||||
// Devuelve el archivo Excel como un array de bytes
|
||||
return excelFile;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
var methodName = MethodBase.GetCurrentMethod()?.Name ?? "UnknownMethod";
|
||||
throw new Exception($"{ex.Message}", ex);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@ -1,23 +1,11 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Domain.Entities
|
||||
namespace Domain.Entities
|
||||
{
|
||||
public class EAccountType
|
||||
{
|
||||
public int Id { get; set; }
|
||||
|
||||
public string Name { get; set; } = null!;
|
||||
|
||||
public string? Description { get; set; }
|
||||
|
||||
public decimal? CreditLimit { get; set; }
|
||||
|
||||
public DateTime? CreationDate { get; set; }
|
||||
|
||||
//public virtual ICollection<ECustomer> Customers { get; set; } = new List<ECustomer>();
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,10 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
namespace Domain.Entities
|
||||
{
|
||||
public class ECustomer
|
||||
@ -18,20 +12,12 @@ namespace Domain.Entities
|
||||
public int? AccounttypesId { get; set; }
|
||||
[Required(ErrorMessage = "Debe seleccionar un condicion.")]
|
||||
public int? TaxConditionId { get; set; }
|
||||
|
||||
public bool HasCreditAccount { get; set; }
|
||||
|
||||
public decimal CreditLimit { get; set; }
|
||||
|
||||
public bool Active { get; set; }
|
||||
|
||||
public string? ExternalCode { get; set; }
|
||||
|
||||
public virtual EAccountType? Accounttypes { get; set; }
|
||||
|
||||
public virtual ICollection<ECustomerAddress> PhSCustomerAddresses { get; set; } = new List<ECustomerAddress>();
|
||||
|
||||
public virtual ICollection<ECustomerDocument> PhSCustomerDocuments { get; set; } = new List<ECustomerDocument>();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,10 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
namespace Domain.Entities
|
||||
{
|
||||
public class ECustomerAddress
|
||||
@ -26,5 +20,4 @@ namespace Domain.Entities
|
||||
public string? Email { get; set; }
|
||||
public string? Notes { get; set; }
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,10 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
namespace Domain.Entities
|
||||
{
|
||||
public class ECustomerDocument
|
||||
@ -15,9 +9,7 @@ namespace Domain.Entities
|
||||
public int DocumenttypesId { get; set; }
|
||||
[Required(ErrorMessage = "Debe seleccionar un numero documento.")]
|
||||
public string DocumentNumber { get; set; } = null!;
|
||||
|
||||
public DateOnly? IssueDate { get; set; }
|
||||
|
||||
public DateOnly? ExpiryDate { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@ -3,11 +3,8 @@
|
||||
public class EDocumentType
|
||||
{
|
||||
public int Id { get; set; }
|
||||
|
||||
public string? Code { get; set; }
|
||||
|
||||
public string Name { get; set; } = null!;
|
||||
|
||||
public string? Description { get; set; }
|
||||
}
|
||||
}
|
||||
@ -1,5 +1,4 @@
|
||||
|
||||
namespace Domain.Entities
|
||||
namespace Domain.Entities
|
||||
{
|
||||
public class ETicket
|
||||
{
|
||||
|
||||
9
Domain/Generics/CustomerSearchParams.cs
Normal file
9
Domain/Generics/CustomerSearchParams.cs
Normal file
@ -0,0 +1,9 @@
|
||||
namespace Domain.Generics
|
||||
{
|
||||
public class CustomerSearchParams : PagedRequest
|
||||
{
|
||||
public string? Name { get; set; }
|
||||
public string? Email { get; set; }
|
||||
public string? Document { get; set; }
|
||||
}
|
||||
}
|
||||
@ -1,10 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Domain.Generics
|
||||
namespace Domain.Generics
|
||||
{
|
||||
public class PagedRequest
|
||||
{
|
||||
|
||||
@ -6,7 +6,6 @@
|
||||
public int TotalItems { get; set; }
|
||||
public int Page { get; set; }
|
||||
public int PageSize { get; set; }
|
||||
|
||||
public int TotalPages => (int)Math.Ceiling((double)TotalItems / PageSize);
|
||||
}
|
||||
}
|
||||
|
||||
@ -15,7 +15,6 @@ namespace Models.Helpers
|
||||
.Skip((page - 1) * pageSize)
|
||||
.Take(pageSize)
|
||||
.ToListAsync();
|
||||
|
||||
return new PagedResult<T>
|
||||
{
|
||||
Items = items,
|
||||
|
||||
@ -1,11 +1,5 @@
|
||||
using Domain.Entities;
|
||||
using Domain.Generics;
|
||||
using Models.Models;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Models.Interfaces
|
||||
{
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
using Core.Interfaces;
|
||||
using Domain.Entities;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Domain.Generics;
|
||||
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using System.Reflection;
|
||||
|
||||
@ -50,6 +51,7 @@ namespace phronCare.API.Controllers.Sales
|
||||
return StatusCode(500, $"{methodName} Message: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
[HttpGet("{id:int}")]
|
||||
public async Task<ActionResult<ECustomer>> GetById(int id)
|
||||
{
|
||||
@ -66,6 +68,7 @@ namespace phronCare.API.Controllers.Sales
|
||||
return StatusCode(500, $"Error: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
[HttpPost("create")]
|
||||
public async Task<IActionResult> Create([FromBody] ECustomer customer)
|
||||
{
|
||||
@ -91,6 +94,7 @@ namespace phronCare.API.Controllers.Sales
|
||||
return StatusCode(500, $"{methodName} Message: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
[HttpPut("update")]
|
||||
public async Task<IActionResult> Update([FromBody] ECustomer customer)
|
||||
{
|
||||
@ -112,5 +116,20 @@ namespace phronCare.API.Controllers.Sales
|
||||
return StatusCode(500, $"{methodName} Message: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
[HttpPost("exportfiltered")]
|
||||
public async Task<IActionResult> ExportFiltered([FromBody] CustomerSearchParams searchParams)
|
||||
{
|
||||
try {
|
||||
var file = await _customerService.ExportFilteredCustomersToExcelAsync(searchParams);
|
||||
return File(file,
|
||||
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
|
||||
"Clientes.xlsx");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return BadRequest(ex.Message);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -367,6 +367,22 @@
|
||||
],
|
||||
"ReturnTypes": []
|
||||
},
|
||||
{
|
||||
"ContainingType": "phronCare.API.Controllers.Sales.CustomerController",
|
||||
"Method": "ExportFiltered",
|
||||
"RelativePath": "api/Customer/exportfiltered",
|
||||
"HttpMethod": "POST",
|
||||
"IsController": true,
|
||||
"Order": 0,
|
||||
"Parameters": [
|
||||
{
|
||||
"Name": "searchParams",
|
||||
"Type": "Domain.Generics.CustomerSearchParams",
|
||||
"IsRequired": true
|
||||
}
|
||||
],
|
||||
"ReturnTypes": []
|
||||
},
|
||||
{
|
||||
"ContainingType": "phronCare.API.Controllers.Sales.CustomerController",
|
||||
"Method": "Search",
|
||||
|
||||
@ -4,16 +4,16 @@
|
||||
@using phronCare.UIBlazor.Pages.Shared.Modals
|
||||
@using phronCare.UIBlazor.Services.Sales
|
||||
@inject IModalService Modal
|
||||
@inject IToastService toastService
|
||||
@inject HttpClient _httpClient
|
||||
@inject NavigationManager Navigation
|
||||
@inject IToastService toastService
|
||||
@inject AuthenticationStateProvider authenticationStateProvider
|
||||
@inject AccountTypeService accountTypeService
|
||||
@inject TaxConditionService taxConditionService
|
||||
|
||||
<div class="card " style="zoom:70%">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">Formulario: cliente</h3>
|
||||
<div class="card" style="zoom:80%">
|
||||
<div class="card-header d-flex justify-content-center align-items-center">
|
||||
<h3 class="card-title m-0">Información del cliente</h3>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<EditForm Model="@customer" OnValidSubmit="@HandleValidSubmit">
|
||||
@ -231,21 +231,17 @@
|
||||
@code {
|
||||
[Parameter]
|
||||
public int? CustomerId { get; set; }
|
||||
|
||||
private ECustomer customer { get; set; } = new();
|
||||
private List<EAccountType> accountTypes = new();
|
||||
private List<ETaxCondition> taxConditions = new();
|
||||
private List<EDocumentType> documentTypes = new();
|
||||
private ECustomerDocument documentFormModel = new();
|
||||
private bool isSaving = false;
|
||||
|
||||
private string returnUrl = "/sales/customers";
|
||||
|
||||
private List<string> countries = new() {
|
||||
"Argentina", "Brasil", "Chile", "Uruguay", "Paraguay", "Estados Unidos", "Canadá",
|
||||
"México", "Alemania", "Reino Unido", "Francia", "Italia", "España"
|
||||
};
|
||||
|
||||
private Dictionary<string, List<string>> provincesByCountry = new()
|
||||
{
|
||||
{
|
||||
@ -258,17 +254,14 @@
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private ECustomerAddress editingAddress = new();
|
||||
private int editingIndex = -1;
|
||||
|
||||
private void OnCountryChanged(ChangeEventArgs e)
|
||||
{
|
||||
var selectedCountry = e.Value?.ToString();
|
||||
editingAddress.Country = selectedCountry;
|
||||
editingAddress.Stateprovince = string.Empty; // Resetear la provincia si cambia el país
|
||||
}
|
||||
|
||||
private void AddOrUpdateAddress()
|
||||
{
|
||||
var context = new ValidationContext(editingAddress, null, null);
|
||||
@ -292,7 +285,6 @@
|
||||
{
|
||||
// Actualizar dirección existente
|
||||
var existing = customer.PhSCustomerAddresses.ElementAt(editingIndex);
|
||||
|
||||
existing.BusinessName = editingAddress.BusinessName;
|
||||
existing.Streetaddress1 = editingAddress.Streetaddress1;
|
||||
existing.Streetaddress2 = editingAddress.Streetaddress2;
|
||||
@ -306,10 +298,8 @@
|
||||
existing.Email = editingAddress.Email;
|
||||
existing.Notes = editingAddress.Notes;
|
||||
}
|
||||
|
||||
ResetAddressForm();
|
||||
}
|
||||
|
||||
private void EditAddress(int index)
|
||||
{
|
||||
var addr = customer.PhSCustomerAddresses.ElementAt(index);
|
||||
@ -333,26 +323,21 @@
|
||||
|
||||
editingIndex = index;
|
||||
}
|
||||
|
||||
private void RemoveAddress(int index)
|
||||
{
|
||||
var itemToRemove = customer.PhSCustomerAddresses.ElementAt(index);
|
||||
customer.PhSCustomerAddresses.Remove(itemToRemove);
|
||||
ResetAddressForm();
|
||||
}
|
||||
|
||||
|
||||
private void CancelAddressEdit()
|
||||
{
|
||||
ResetAddressForm();
|
||||
}
|
||||
|
||||
private void ResetAddressForm()
|
||||
{
|
||||
editingAddress = new();
|
||||
editingIndex = -1;
|
||||
}
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
await LoadAccountTypes();
|
||||
@ -365,7 +350,6 @@
|
||||
customer = await _httpClient.GetFromJsonAsync<ECustomer>($"/api/Customer/{CustomerId.Value}") ?? new();
|
||||
}
|
||||
}
|
||||
|
||||
private async Task LoadAccountTypes()
|
||||
{
|
||||
accountTypes = await accountTypeService.GetAllAsync();
|
||||
@ -379,7 +363,6 @@
|
||||
var result = await _httpClient.GetFromJsonAsync<List<EDocumentType>>("/api/DocumentType/GetAll");
|
||||
documentTypes = result ?? new();
|
||||
}
|
||||
|
||||
private void AddCustomerDocument()
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(documentFormModel.DocumentNumber))
|
||||
@ -396,21 +379,17 @@
|
||||
{
|
||||
customer.PhSCustomerAddresses.Remove(address);
|
||||
}
|
||||
|
||||
private async Task HandleValidSubmit()
|
||||
{
|
||||
var parameters = new ModalParameters();
|
||||
parameters.Add("Message", "¿Desea guardar los cambios del cliente?");
|
||||
|
||||
var modal = Modal.Show<ConfirmModal>("Confirmacion", parameters);
|
||||
var result = await modal.Result;
|
||||
|
||||
if (result.Cancelled)
|
||||
return;
|
||||
try
|
||||
{
|
||||
HttpResponseMessage response;
|
||||
|
||||
if (CustomerId.HasValue)
|
||||
{
|
||||
response = await _httpClient.PutAsJsonAsync("/api/Customer/Update", customer);
|
||||
@ -435,7 +414,6 @@
|
||||
toastService.ShowError($"Error: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
private void Cancel()
|
||||
{
|
||||
Navigation.NavigateTo(returnUrl);
|
||||
|
||||
@ -3,21 +3,34 @@
|
||||
@using phronCare.UIBlazor.Data
|
||||
@using Domain.Entities
|
||||
@using Domain.Generics
|
||||
@inject IToastService toastService
|
||||
@inject NavigationManager Navigation
|
||||
@inject CustomerService customerService
|
||||
|
||||
<div class="card " style="zoom:90%">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">Listado de clientes</h3> @* wtf? *@
|
||||
<div class="card">
|
||||
<div class="card-header d-flex justify-content-center align-items-center" style="zoom:80%;">
|
||||
<h3 class="card-title m-0">Administración de clientes</h3> @* wtf? *@
|
||||
</div>
|
||||
<div class="card-body" style="zoom:70%;">
|
||||
<div class="mb-4 space-y-2">
|
||||
<div class="card-body" style="zoom:80%;">
|
||||
<div class="mb-4 space-y-2" >
|
||||
<input @bind="SearchParams.Name" placeholder="Nombre" class="border rounded p-1 w-full" />
|
||||
<input @bind="SearchParams.Email" placeholder="Email" class="border rounded p-1 w-full" />
|
||||
<input @bind="SearchParams.Document" placeholder="Documento" class="border rounded p-1 w-full" />
|
||||
<button class="btn btn-primary" @onclick="BuscarClientes">Buscar</button>
|
||||
<button class="btn btn-primary rounded-pill" @onclick="BuscarClientes">
|
||||
<i class="fas fa-binoculars me-1"></i> Buscar
|
||||
</button>
|
||||
<button class="btn btn-success rounded-pill" @onclick="NuevoCliente">
|
||||
<i class="fas fa-plus me-1"></i> Nuevo
|
||||
</button>
|
||||
<button class="btn btn-success rounded-pill" @onclick="ExportarExcel">
|
||||
<i class="fas fa-file-excel me-1"></i> Excel
|
||||
</button>
|
||||
<button class="btn btn-secondary rounded-pill" @onclick="Cancel">
|
||||
<i class="fas fa-arrow-left me-1"></i> Volver
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
<div>
|
||||
@if (TablaClientes != null && TablaClientes.Any())
|
||||
{
|
||||
<PhTable Columns="TableColumns"
|
||||
@ -30,30 +43,62 @@
|
||||
RenderSelect="false"
|
||||
/>
|
||||
|
||||
<div class="mt-4 flex justify-between items-center">
|
||||
<button class="btn btn-secondary" @onclick="AnteriorPagina" disabled="@(!PuedeRetroceder)">Anterior</button>
|
||||
<span> Página @SearchParams.Page de @TotalPaginas </span>
|
||||
<button class="btn btn-secondary" @onclick="SiguientePagina" disabled="@(!PuedeAvanzar)">Siguiente</button>
|
||||
</div>
|
||||
}
|
||||
else
|
||||
{
|
||||
<p>No hay resultados.</p>
|
||||
}
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-footer">
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<button type="button" class="btn btn-success" @onclick="XSLXExportar">
|
||||
<i class="fas fa-file-excel"></i> Exportar a Excel
|
||||
<div class="card-footer d-flex justify-content-center align-items-center" style="zoom:80%;">
|
||||
<div class="d-flex align-items-center gap-3">
|
||||
<button class="btn btn-secondary rounded-pill" @onclick="PrimeraPagina" disabled="@(SearchParams.Page == 1)">
|
||||
<i class="fas fa-angle-double-left me-1"></i> Primera
|
||||
</button>
|
||||
<button class="btn btn-secondary rounded-pill" @onclick="AnteriorPagina" disabled="@(!PuedeRetroceder)">
|
||||
<i class="fas fa-chevron-left me-1"></i> Anterior
|
||||
</button>
|
||||
<span class="mx-2">
|
||||
Página <strong>@SearchParams.Page</strong> de <strong>@TotalPaginas</strong>
|
||||
</span>
|
||||
<button class="btn btn-secondary rounded-pill" @onclick="SiguientePagina" disabled="@(!PuedeAvanzar)">
|
||||
Siguiente <i class="fas fa-chevron-right ms-1"></i>
|
||||
</button>
|
||||
<button class="btn btn-secondary rounded-pill" @onclick="UltimaPagina" disabled="@(SearchParams.Page == TotalPaginas)">
|
||||
Última <i class="fas fa-angle-double-right ms-1"></i>
|
||||
</button>
|
||||
<div class="d-flex align-items-center ms-3">
|
||||
<input type="number" class="form-control form-control-sm rounded" style="width: 80px;" min="1" max="@TotalPaginas" @bind="PaginaDeseada" />
|
||||
<button class="btn btn-outline-primary btn-sm ms-2 rounded-pill" @onclick="IrAPagina">
|
||||
<i class="fas fa-arrow-right-to-bracket me-1"></i> Ir
|
||||
</button>
|
||||
<button type="button" class="btn btn-secondary" @onclick="Cancel">Volver</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
@code {
|
||||
protected override void OnInitialized()
|
||||
{
|
||||
botones = new List<PhTable.ButtonOptions>
|
||||
{
|
||||
new PhTable.ButtonOptions
|
||||
{
|
||||
Caption = "Editar",
|
||||
ElementClass = "btn btn-primary btn-sm",
|
||||
UrlAction = "/sales/customers/edit/",
|
||||
OnClickAction = async (id) =>
|
||||
{
|
||||
if (int.TryParse(id, out var customerId))
|
||||
{
|
||||
Navigation.NavigateTo($"/sales/customerform/{customerId}");
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
private CustomerSearchParams SearchParams = new();
|
||||
private PagedResult<ECustomer>? PagedResult;
|
||||
private List<Dictionary<string, object>> TablaClientes = new();
|
||||
@ -62,13 +107,34 @@
|
||||
"Id", "Nombre", "Activo", "Crédito", "Límite",
|
||||
"Email", "Teléfono", "Dirección", "Documento"
|
||||
};
|
||||
private int PaginaDeseada = 1;
|
||||
|
||||
private async Task BuscarClientes()
|
||||
private async Task PrimeraPagina()
|
||||
{
|
||||
SearchParams.Page = 1;
|
||||
await BuscarClientes();
|
||||
}
|
||||
private async Task UltimaPagina()
|
||||
{
|
||||
SearchParams.Page = TotalPaginas;
|
||||
await BuscarClientes();
|
||||
}
|
||||
private async Task IrAPagina()
|
||||
{
|
||||
if (PaginaDeseada >= 1 && PaginaDeseada <= TotalPaginas)
|
||||
{
|
||||
SearchParams.Page = PaginaDeseada;
|
||||
await BuscarClientes();
|
||||
}
|
||||
else
|
||||
{
|
||||
toastService.ShowWarning("Número de página fuera de rango.");
|
||||
}
|
||||
}
|
||||
private async Task BuscarClientes()
|
||||
{
|
||||
await CargarClientes();
|
||||
}
|
||||
|
||||
private async Task CargarClientes()
|
||||
{
|
||||
PagedResult = await customerService.SearchCustomersAsync(SearchParams);
|
||||
@ -107,45 +173,39 @@
|
||||
await CargarClientes();
|
||||
}
|
||||
}
|
||||
|
||||
private async Task XSLXExportar()
|
||||
private async Task ExportarExcel()
|
||||
{
|
||||
// string endpoint = "/api/Ticket/ExportDashboardDetail";
|
||||
// var response = await _httpClient.PostAsJsonAsync(endpoint, new { Param1 = Group, Param2 = "ASC" });
|
||||
// response.EnsureSuccessStatusCode();
|
||||
// var fileBytes = await response.Content.ReadAsByteArrayAsync();
|
||||
// var currentDate = DateTime.Now.ToString("ddMMyyyyhhmmss");
|
||||
// var filename = $"Tickets_{Group}_{currentDate}.xlsx";
|
||||
// await js.InvokeAsync<object>("saveAsFile", filename, Convert.ToBase64String(fileBytes));
|
||||
}
|
||||
|
||||
List<PhTable.ButtonOptions> botones = new();
|
||||
protected override void OnInitialized()
|
||||
{
|
||||
botones = new List<PhTable.ButtonOptions>
|
||||
{
|
||||
new PhTable.ButtonOptions
|
||||
// Crea el objeto de parámetros para la búsqueda
|
||||
var searchParams = new CustomerSearchParams
|
||||
{
|
||||
Caption = "Editar",
|
||||
ElementClass = "btn btn-primary btn-sm",
|
||||
UrlAction = "/sales/customers/edit/",
|
||||
OnClickAction = async (id) =>
|
||||
{
|
||||
if (int.TryParse(id, out var customerId))
|
||||
{
|
||||
Navigation.NavigateTo($"/sales/customerform/{customerId}");
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
Name = SearchParams.Name, // Aquí podés obtener los filtros de los campos en el formulario
|
||||
Email = SearchParams.Email,
|
||||
Document = SearchParams.Document,
|
||||
Page = 1,
|
||||
PageSize = int.MaxValue // Puedes ajustar el tamaño de la página para exportar todos los registros
|
||||
};
|
||||
try
|
||||
{
|
||||
await customerService.ExportFilteredAsync(searchParams);
|
||||
toastService.ShowSuccess("Exportación completada exitosamente.");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
toastService.ShowError($"{ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
private bool PuedeRetroceder => PagedResult != null && SearchParams.Page > 1;
|
||||
private bool PuedeAvanzar => PagedResult != null && SearchParams.Page < TotalPaginas;
|
||||
private int TotalPaginas => PagedResult is null ? 1 :
|
||||
(int)Math.Ceiling((double)(PagedResult.TotalItems) / SearchParams.PageSize);
|
||||
private bool PuedeAvanzar => PagedResult != null && SearchParams.Page < TotalPaginas;
|
||||
private bool PuedeRetroceder => PagedResult != null && SearchParams.Page > 1;
|
||||
|
||||
private void NuevoCliente()
|
||||
{
|
||||
Navigation.NavigateTo("/sales/customerform/");
|
||||
}
|
||||
public void Cancel()
|
||||
{
|
||||
Navigation.NavigateTo("/DashboardPanel");
|
||||
}
|
||||
List<PhTable.ButtonOptions> botones = new();
|
||||
}
|
||||
@ -1,14 +1,22 @@
|
||||
using Domain.Entities;
|
||||
using Domain.Generics;
|
||||
using System.Net.Http.Json;
|
||||
using System.Text.Json;
|
||||
using System.Text;
|
||||
using Microsoft.JSInterop;
|
||||
using System.Reflection;
|
||||
|
||||
|
||||
namespace phronCare.UIBlazor.Services.Sales
|
||||
{
|
||||
public class CustomerService
|
||||
{
|
||||
private readonly HttpClient _http;
|
||||
public CustomerService(HttpClient http)
|
||||
private readonly IJSRuntime _js;
|
||||
public CustomerService(HttpClient http, IJSRuntime js)
|
||||
{
|
||||
_http = http;
|
||||
_js = js;
|
||||
}
|
||||
public async Task<PagedResult<ECustomer>?> SearchCustomersAsync(CustomerSearchParams searchParams)
|
||||
{
|
||||
@ -20,13 +28,40 @@ namespace phronCare.UIBlazor.Services.Sales
|
||||
$"pageSize={searchParams.PageSize}";
|
||||
return await _http.GetFromJsonAsync<PagedResult<ECustomer>>(url);
|
||||
}
|
||||
public async Task ExportFilteredAsync(CustomerSearchParams searchParams)
|
||||
{
|
||||
try
|
||||
{
|
||||
var content = new StringContent(JsonSerializer.Serialize(searchParams), Encoding.UTF8, "application/json");
|
||||
var response = await _http.PostAsync("api/Customer/exportfiltered", content);
|
||||
|
||||
//response.EnsureSuccessStatusCode();
|
||||
if (!response.IsSuccessStatusCode)
|
||||
{
|
||||
var errorContent = await response.Content.ReadAsStringAsync();
|
||||
throw new Exception(errorContent);
|
||||
}
|
||||
var bytes = await response.Content.ReadAsByteArrayAsync();
|
||||
var base64 = Convert.ToBase64String(bytes);
|
||||
var timestamp = DateTime.Now.ToString("yyyyMMddHHmm");
|
||||
var fileName = $"{timestamp}_clientes.xlsx";
|
||||
await _js.InvokeVoidAsync("saveAsFile", fileName, base64);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
var methodName = MethodBase.GetCurrentMethod()?.Name ?? "UnknownMethod";
|
||||
var message = ex.Message ?? "No message provided";
|
||||
throw new Exception($"{message}", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
public class CustomerSearchParams
|
||||
{
|
||||
public string? Name { get; set; }
|
||||
public string? Email { get; set; }
|
||||
public string? Document { get; set; }
|
||||
public int Page { get; set; } = 1;
|
||||
public int PageSize { get; set; } = 10;
|
||||
}
|
||||
|
||||
//public class CustomerSearchParams
|
||||
//{
|
||||
// public string? Name { get; set; }
|
||||
// public string? Email { get; set; }
|
||||
// public string? Document { get; set; }
|
||||
// public int Page { get; set; } = 1;
|
||||
// public int PageSize { get; set; } = 10;
|
||||
//}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user