Skip to content

Productos y servicios

Andres Ramos edited this page May 26, 2024 · 7 revisions

Modelos

Producto

La clase Producto representa un modelo amigable de un producto o servicio. Se utiliza principalmente para la creación de productos y servicios.

public class Producto
{
    /// <summary>
    ///     Id del producto.
    /// </summary>
    public int Id { get; set; }

    /// <summary>
    ///     Codigo del producto.
    /// </summary>
    public string Codigo { get; set; } = string.Empty;

    /// <summary>
    ///     Nombre del producto.
    /// </summary>
    public string Nombre { get; set; } = string.Empty;

    /// <summary>
    ///     Tipo del producto.
    /// </summary>
    [JsonConverter(typeof(JsonStringEnumConverter))]
    public TipoProducto Tipo { get; set; } = TipoProducto.Producto;

    /// <summary>
    ///     Control de existencias del producto.
    /// </summary>
    [JsonConverter(typeof(JsonStringEnumConverter))]
    public ControlExistencias ControlExistencias { get; set; } = ControlExistencias.Ninguno;

    /// <summary>
    ///     Unidad de medida base del producto.
    /// </summary>
    public UnidadMedida? UnidadMedida { get; set; }

    /// <summary>
    ///     Clave SAT del producto.
    /// </summary>
    public string ClaveSat { get; set; } = string.Empty;

    /// <summary>
    ///     Datos extra del producto.
    /// </summary>
    public Dictionary<string, string> DatosExtra { get; set; } = new();
}

admProductos

La clase admProductos representa el modelo de SQL con el esquema completo de la tabla de productos en la base de datos. Se utiliza principalmente para consultar el catalogo de productos cuando se necesita obtener el esquema completo.

public partial class admProductos
{
    public int CIDPRODUCTO { get; set; }
    public string CCODIGOPRODUCTO { get; set; } = null!;
    public string CNOMBREPRODUCTO { get; set; } = null!;
    public int CTIPOPRODUCTO { get; set; }
    public DateTime CFECHAALTAPRODUCTO { get; set; }
    public int CCONTROLEXISTENCIA { get; set; }
    public int CIDFOTOPRODUCTO { get; set; }
    public string? CDESCRIPCIONPRODUCTO { get; set; }
    public int CMETODOCOSTEO { get; set; }
    public double CPESOPRODUCTO { get; set; }
    public double CCOMVENTAEXCEPPRODUCTO { get; set; }
    public double CCOMCOBROEXCEPPRODUCTO { get; set; }
    public double CCOSTOESTANDAR { get; set; }
    public double CMARGENUTILIDAD { get; set; }
    public int CSTATUSPRODUCTO { get; set; }
    public int CIDUNIDADBASE { get; set; }
    public int CIDUNIDADNOCONVERTIBLE { get; set; }
    public DateTime CFECHABAJA { get; set; }
    public double CIMPUESTO1 { get; set; }
    public double CIMPUESTO2 { get; set; }
    public double CIMPUESTO3 { get; set; }
    public double CRETENCION1 { get; set; }
    public double CRETENCION2 { get; set; }
    public int CIDPADRECARACTERISTICA1 { get; set; }
    public int CIDPADRECARACTERISTICA2 { get; set; }
    public int CIDPADRECARACTERISTICA3 { get; set; }
    public int CIDVALORCLASIFICACION1 { get; set; }
    public int CIDVALORCLASIFICACION2 { get; set; }
    public int CIDVALORCLASIFICACION3 { get; set; }
    public int CIDVALORCLASIFICACION4 { get; set; }
    public int CIDVALORCLASIFICACION5 { get; set; }
    public int CIDVALORCLASIFICACION6 { get; set; }
    public string CSEGCONTPRODUCTO1 { get; set; } = null!;
    public string CSEGCONTPRODUCTO2 { get; set; } = null!;
    public string CSEGCONTPRODUCTO3 { get; set; } = null!;
    public string CTEXTOEXTRA1 { get; set; } = null!;
    public string CTEXTOEXTRA2 { get; set; } = null!;
    public string CTEXTOEXTRA3 { get; set; } = null!;
    public DateTime CFECHAEXTRA { get; set; }
    public double CIMPORTEEXTRA1 { get; set; }
    public double CIMPORTEEXTRA2 { get; set; }
    public double CIMPORTEEXTRA3 { get; set; }
    public double CIMPORTEEXTRA4 { get; set; }
    public double CPRECIO1 { get; set; }
    public double CPRECIO2 { get; set; }
    public double CPRECIO3 { get; set; }
    public double CPRECIO4 { get; set; }
    public double CPRECIO5 { get; set; }
    public double CPRECIO6 { get; set; }
    public double CPRECIO7 { get; set; }
    public double CPRECIO8 { get; set; }
    public double CPRECIO9 { get; set; }
    public double CPRECIO10 { get; set; }
    public int CBANUNIDADES { get; set; }
    public int CBANCARACTERISTICAS { get; set; }
    public int CBANMETODOCOSTEO { get; set; }
    public int CBANMAXMIN { get; set; }
    public int CBANPRECIO { get; set; }
    public int CBANIMPUESTO { get; set; }
    public int CBANCODIGOBARRA { get; set; }
    public int CBANCOMPONENTE { get; set; }
    public string CTIMESTAMP { get; set; } = null!;
    public int CERRORCOSTO { get; set; }
    public DateTime CFECHAERRORCOSTO { get; set; }
    public double CPRECIOCALCULADO { get; set; }
    public int CESTADOPRECIO { get; set; }
    public int CBANUBICACION { get; set; }
    public int CESEXENTO { get; set; }
    public int CEXISTENCIANEGATIVA { get; set; }
    public double CCOSTOEXT1 { get; set; }
    public double CCOSTOEXT2 { get; set; }
    public double CCOSTOEXT3 { get; set; }
    public double CCOSTOEXT4 { get; set; }
    public double CCOSTOEXT5 { get; set; }
    public DateTime CFECCOSEX1 { get; set; }
    public DateTime CFECCOSEX2 { get; set; }
    public DateTime CFECCOSEX3 { get; set; }
    public DateTime CFECCOSEX4 { get; set; }
    public DateTime CFECCOSEX5 { get; set; }
    public int CMONCOSEX1 { get; set; }
    public int CMONCOSEX2 { get; set; }
    public int CMONCOSEX3 { get; set; }
    public int CMONCOSEX4 { get; set; }
    public int CMONCOSEX5 { get; set; }
    public int CBANCOSEX { get; set; }
    public int CESCUOTAI2 { get; set; }
    public int CESCUOTAI3 { get; set; }
    public int CIDUNIDADCOMPRA { get; set; }
    public int CIDUNIDADVENTA { get; set; }
    public int CSUBTIPO { get; set; }
    public string CCODALTERN { get; set; } = null!;
    public string CNOMALTERN { get; set; } = null!;
    public string CDESCCORTA { get; set; } = null!;
    public int CIDMONEDA { get; set; }
    public int CUSABASCU { get; set; }
    public int CTIPOPAQUE { get; set; }
    public int CPRECSELEC { get; set; }
    public int CDESGLOSAI2 { get; set; }
    public string CSEGCONTPRODUCTO4 { get; set; } = null!;
    public string CSEGCONTPRODUCTO5 { get; set; } = null!;
    public string CSEGCONTPRODUCTO6 { get; set; } = null!;
    public string CSEGCONTPRODUCTO7 { get; set; } = null!;
    public string CCTAPRED { get; set; } = null!;
    public int CNODESCOMP { get; set; }
    public int CIDUNIXML { get; set; }
    public string CCLAVESAT { get; set; } = null!;
    public double CCANTIDADFISCAL { get; set; }
}

ProductoDto

La clase ProductoDto representa un modelo de producto simplificado. Se utiliza principalmente para consultar el catalogo de productos cuando solo se necesitan algunas propiedades. Las propiedades de este modelo tienen los los mismos nombres que las propiedades del modelo de SQL para facilitar la asignacion de valores cuando se utiliza con los repositorios genericos de productos, como por ejemplo los que implementan IProductoRepository<T> de ProductoDto.

public class ProductoDto
{
    /// <summary>
    ///     Id del producto.
    /// </summary>
    public int CIDPRODUCTO { get; set; }

    /// <summary>
    ///     Código del producto.
    /// </summary>
    public string CCODIGOPRODUCTO { get; set; } = string.Empty;

    /// <summary>
    ///     Nombre del producto.
    /// </summary>
    public string CNOMBREPRODUCTO { get; set; } = string.Empty;

    /// <summary>
    ///     Tipo de producto: 1 = Producto, 2 = Paquete, 3 = Servicio
    /// </summary>
    public int CTIPOPRODUCTO { get; set; }

    /// <summary>
    ///     Clave SAT para identificar al producto o servicio.
    /// </summary>
    public string CCLAVESAT { get; set; } = string.Empty;
}

Comandos

Servicios

El servicio IProductoService define metodos para crear, actualizar y eliminar productos.

public interface IProductoService
{
    /// <summary>
    ///     Actualiza un producto por dato abstracto.
    /// </summary>
    /// <param name="codigoProducto">Código del producto a actualizar.</param>
    /// <param name="producto">Producto a actualizar.</param>
    void Actualizar(string codigoProducto, tProducto producto);

    /// <summary>
    ///     Actualiza un producto por su Id. Los datos a actualizar se pasan en un diccionario donde la llave es el nombre de
    ///     la columna de la tabla de productos en la base de datos y el valor es un valor valido para la columna.
    /// </summary>
    /// <param name="idProducto">Id del producto a actualizar.</param>
    /// <param name="datosProducto">Datos del producto a actualizar.</param>
    void Actualizar(int idProducto, Dictionary<string, string> datosProducto);

    /// <summary>
    ///     Actualiza un producto por su código. Los datos a actualizar se pasan en un diccionario donde la llave es el nombre
    ///     de la columna de la tabla de productos en la base de datos y el valor es un valor valido para la columna.
    /// </summary>
    /// <param name="codigoProducto">Código del producto a actualizar.</param>
    /// <param name="datosProducto">Datos del producto a actualizar.</param>
    void Actualizar(string codigoProducto, Dictionary<string, string> datosProducto);

    /// <summary>
    ///     Crea un producto por dato abstracto.
    /// </summary>
    /// <param name="producto">Producto a crear.</param>
    /// <returns>Id del producto creado.</returns>
    int Crear(tProducto producto);

    /// <summary>
    ///     Crear un producto. Los datos del producto se pasan en un diccionario donde la llave es el nombre de la columna de
    ///     la tabla de productos en la base de datos y el valor es un valor valido para la columna.
    /// </summary>
    /// <param name="datosProducto">Datos del producto a crear.</param>
    /// <returns>Id del producto creado.</returns>
    int Crear(Dictionary<string, string> datosProducto);

    /// <summary>
    ///     Crea un producto.
    /// </summary>
    /// <param name="producto">Producto a crear.</param>
    /// <returns>Id del producto creado.</returns>
    int Crear(Producto producto);

    /// <summary>
    ///     Elimina un producto por su Id.
    /// </summary>
    /// <param name="idProducto">Id del producto a eliminar.</param>
    void Eliminar(int idProducto);

    /// <summary>
    ///     Elimina un producto por su código.
    /// </summary>
    /// <param name="codigoProducto">Código del producto a eliminar.</param>
    void Eliminar(string codigoProducto);
}

Crear Producto

public class CrearProducto
{
    private readonly IProductoService _productoService;

    public CrearProducto(IProductoService productoService)
    {
        _productoService = productoService;
    }

    public int Crear()
    {
        var producto = new Producto
        {
            Codigo = "PRUEBA", Nombre = "PRODUCTO DE PRUEBAS", Tipo = TipoProducto.Servicio, ClaveSat = "43231500"
        };

        producto.DatosExtra.Add(nameof(admProductos.CTEXTOEXTRA1), "Texto Extra 1");
        producto.DatosExtra.Add(nameof(admProductos.CTEXTOEXTRA2), "Texto Extra 2");

        return _productoService.Crear(producto);
    }
}

Editar Producto

public class EditarProducto
{
    private readonly IProductoService _productoService;

    public EditarProducto(IProductoService productoService)
    {
        _productoService = productoService;
    }

    public void Editar()
    {
        var codigoProducto = "PRUEBA";

        var datosProducto = new Dictionary<string, string>
        {
            { nameof(admProductos.CTEXTOEXTRA1), "Texto Extra 1" },
            { nameof(admProductos.CTEXTOEXTRA2), "Texto Extra 2" },
            { nameof(admProductos.CTEXTOEXTRA3), "Texto Extra 3" }
        };

        _productoService.Actualizar(codigoProducto, datosProducto);
    }
}

Eliminar Producto

public class EliminarProducto
{
    private readonly IProductoService _productoService;

    public EliminarProducto(IProductoService productoService)
    {
        _productoService = productoService;
    }

    public void Eliminar()
    {
        var codigoProducto = "PRUEBA";

        _productoService.Eliminar(codigoProducto);
    }
}

Consultas

Repositorios

El proyecto incluye repositorios que implementan la interfaz IProductoRepository<T> que proporciona metodos que puedes utilizar para consultar el catalogo de productos.

Los repositorios disponibles para SDK son:

  • ProductoSdkRepository<T> - Implementa IProductoRepository<T>.

El repositorio ProductoSdkRepository<T> utiliza reflection para buscar los valores de la propiedades del tipo T en el modelo de SQL admProductos por lo que debes asegurarte que las propiedades del tipo T tengan el mismo nombre que las columnas de la tabla admProductos en la base de datos. El proyecto ya incluye un tipo ProductoDto que cumple con este requisito.

Los repositorios disponibles para SQL son:

  • ProductoSqlRepository<T> - Implementa IProductoSqlRepository<T>. IProductoSqlRepository<T> hereda de IProductoRepository<T> y define las versiones asincronas de los metodos para beneficiarse del uso de Entity Framework Core.

El repositorio ProductoSqlRepository<T> utiliza AutoMapper para proyectar el modelo de SQL admProductos al tipo del parametro T por lo debes crear una configuracion de mapeo con AutoMapper para que funcione. El proyecto ya incluye una configuracion de mapeo para el tipo ProductoDto.

IProductoRepository<T>

public interface IProductoRepository<T> where T : class, new()
{
    /// <summary>
    ///     Busca un producto por código.
    /// </summary>
    /// <param name="codigoProducto">
    ///     Código del producto a buscar.
    /// </param>
    /// <returns>
    ///     Un producto, o <see langword="null" /> si no existe un producto con el código proporcionado.
    /// </returns>
    T? BuscarPorCodigo(string codigoProducto);

    /// <summary>
    ///     Busca un producto por id.
    /// </summary>
    /// <param name="idProducto">
    ///     Id del producto a buscar.
    /// </param>
    /// <returns>
    ///     Un producto, o <see langword="null" /> si no existe un producto con el id proporcionado.
    /// </returns>
    T? BuscarPorId(int idProducto);

    /// <summary>
    ///     Busca productos por tipo.
    /// </summary>
    /// <param name="tipoProducto">
    ///     Tipo de los producto a buscar.
    /// </param>
    /// <returns>
    ///     Lista de productos.
    /// </returns>
    List<T> TraerPorTipo(TipoProducto tipoProducto);

    /// <summary>
    ///     Busca todos los productos.
    /// </summary>
    /// <returns>
    ///     Lista de productos.
    /// </returns>
    List<T> TraerTodo();
}

IProductoSqlRepository<T>

/// <inheritdoc cref="IProductoRepository{T}" />
public interface IProductoSqlRepository<T> : IProductoRepository<T> where T : class, new()
{
    /// <summary>
    ///     Busca un producto por código.
    /// </summary>
    /// <param name="codigoProducto">
    ///     Código del producto a buscar.
    /// </param>
    /// <param name="cancellationToken">
    ///     Token de cancelación.
    /// </param>
    /// <returns>
    ///     Un producto, o <see langword="null" /> si no existe un producto con el código proporcionado.
    /// </returns>
    Task<T?> BuscarPorCodigoAsync(string codigoProducto, CancellationToken cancellationToken);

    /// <summary>
    ///     Busca un producto por id.
    /// </summary>
    /// <param name="idProducto">
    ///     Id del producto a buscar.
    /// </param>
    /// <param name="cancellationToken">
    ///     Token de cancelación.
    /// </param>
    /// <returns>
    ///     Un producto, o <see langword="null" /> si no existe un producto con el id proporcionado.
    /// </returns>
    Task<T?> BuscarPorIdAsync(int idProducto, CancellationToken cancellationToken);

    /// <summary>
    ///     Busca productos por tipo.
    /// </summary>
    /// <param name="tipoProducto">
    ///     Tipo de los producto a buscar.
    /// </param>
    /// <param name="cancellationToken">
    ///     Token de cancelación.
    /// </param>
    /// <returns>
    ///     Lista de productos.
    /// </returns>
    Task<List<T>> TraerPorTipoAsync(TipoProducto tipoProducto, CancellationToken cancellationToken);

    /// <summary>
    ///     Busca todos los productos.
    /// </summary>
    /// <param name="cancellationToken">
    ///     Token de cancelación.
    /// </param>
    /// <returns>
    ///     Lista de productos.
    /// </returns>
    Task<List<T>> TraerTodoAsync(CancellationToken cancellationToken);
}

Dependency Injection

public sealed class BuscarProductosConRepositorio
{
    private readonly IProductoRepository<admProductos> _productoRepository;
    // private readonly IProductoRepository<ProductoDto> _productoRepository;
    // private readonly IProductoRepository<TuModelo> _productoRepository;

    public BuscarProductosConRepositorio(IProductoRepository<admProductos> productoRepository)
    {
        _productoRepository = productoRepository;
    }
}

Buscar Por Codigo

public void BuscarPorCodigo()
{
    var codigoProducto = "PRUEBA";

    admProductos? producto = _productoRepository.BuscarPorCodigo(codigoProducto);

    _logger.LogInformation("{@Producto}", producto);
}

Buscar Por Id

public void BuscarPorId()
{
    var idProducto = 1;

    admProductos? producto = _productoRepository.BuscarPorId(idProducto);

    _logger.LogInformation("{@Producto}", producto);
}

Traer Por Tipo

public void TraerPorTipo()
{
    var tipoProducto = TipoProducto.Servicio;

    List<admProductos> productos = _productoRepository.TraerPorTipo(tipoProducto);

    _logger.LogInformation("{@Productos}", productos);
}

Traer Todo

public void TraerTodo()
{
    List<admProductos> productos = _productoRepository.TraerTodo();

    _logger.LogInformation("{@Productos}", productos);
}