AbetoDesign_FactuGES2/Source/Modulos/Relaciones/Pedidos de proveedor - Facturas de proveedor/uGenerarFacturasProvPedProvUtils.pas
2025-07-23 12:19:05 +02:00

354 lines
13 KiB
ObjectPascal

unit uGenerarFacturasProvPedProvUtils;
interface
uses
Windows, SysUtils, Classes, uBizPedidosProveedor, uBizFacturasProveedor, pngimage, JSDialog;
type
TdmGenerarFacturasProv = class(TDataModule)
JsListaFacturasGeneradas: TJSDialog;
end;
function GenerarFacturaProv(const IDPedido : Integer) : Boolean; overload;
function GenerarFacturasProv : Boolean; overload;
function GenerarFacturasProv(APedidos : IBizPedidoProveedor) : Boolean; overload;
function GenerarFacturasdeListaPedidos(AFacturas: IBizFacturaProveedor; AListaPedidos: IBizPedidoProveedor): Boolean;
implementation
{$R *.dfm}
uses
uDialogUtils, uControllerDetallesBase, DB, uDADataTable, schFacturasProveedorClient_Intf,
uBizDetallesPedidoProveedor, schPedidosProveedorClient_Intf,
uPedidosProveedorController, uDetallesPedidoProveedorController,
uFacturasProveedorController, uBizDetallesFacturaProveedor;
var
dmGenerarFacturasProv: TdmGenerarFacturasProv;
APedidosProveedorController : IPedidosProveedorController;
ADetallesPedidosProveedorController : IDetallesPedidoProveedorController;
AFacturasProveedorController : IFacturasProveedorController;
{ Métodos auxiliares }
procedure CopiarPedidoAFactura(APedido: IBizPedidoProveedor; AFactura : IBizFacturaProveedor);
begin
if not Assigned(AFactura) then
raise Exception.Create ('Albarán no asignado (CopiarPedidoAAlbaran)');
if not Assigned(APedido) then
raise Exception.Create ('Pedido no asignado (CopiarPedidoAAlbaran)');
if not APedido.DataTable.Active then
APedido.DataTable.Active := True;
APedidosProveedorController.RecuperarProveedor(APedido);
if not APedido.Proveedor.DataTable.Active then
APedido.Proveedor.DataTable.active := true;
// La factura tiene que venir ya abierta y posicionado donde hay que copiar
AFactura.ID_PROVEEDOR := APedido.ID_PROVEEDOR;
AFactura.CALLE := APedido.CALLE;
AFactura.CODIGO_POSTAL := APedido.CODIGO_POSTAL;
AFactura.POBLACION := APedido.POBLACION;
AFactura.PROVINCIA := APedido.PROVINCIA;
AFactura.IMPORTE_NETO := APedido.IMPORTE_NETO;
AFactura.IMPORTE_PORTE := APedido.IMPORTE_PORTE;
AFactura.DESCUENTO := APedido.DESCUENTO;
AFactura.IMPORTE_DESCUENTO := APedido.IMPORTE_DESCUENTO;
AFactura.BASE_IMPONIBLE := APedido.BASE_IMPONIBLE;
AFactura.IVA := APedido.IVA;
AFactura.IMPORTE_IVA := APedido.IMPORTE_IVA;
AFactura.IMPORTE_TOTAL := APedido.IMPORTE_TOTAL;
AFactura.DataTable.FieldByName(fld_FacturasProveedorOBSERVACIONES).AsVariant := APedido.DataTable.FieldByName(fld_PedidosProveedorOBSERVACIONES).AsVariant;
AFactura.NIF_CIF := APedido.Proveedor.NIF_CIF;
AFactura.NOMBRE_COMERCIAL_PROVEEDOR := APedido.Proveedor.NOMBRE_COMERCIAL;
AFactura.ID_FORMA_PAGO := APedido.Proveedor.ID_FORMA_PAGO;
end;
procedure CopiarArticulosAFactura(APedido: IBizPedidoProveedor; AFactura: IBizFacturaProveedor);
var
i : integer;
ADetalles : IBizDetallesFacturaProveedor;
begin
if not Assigned(AFactura) then
raise Exception.Create ('Factura no asignada (CopiarArticulosAFactura)');
if not Assigned(APedido) then
raise Exception.Create ('Factura no asignada (CopiarArticulosAFactura)');
// La factura tiene que venir ya abierta y posicionada donde hay que copiar
ADetalles := AFactura.Detalles;
try
//OJO IMPORTANTE
//Siempre que vayamos a trabajar con los detalles debemos hacer un beginupdate de los mismos y un endupdate para
//obligarle siempre a recalcular los detalles una sola vez
AFacturasProveedorController.DetallesController.BeginUpdate(ADetalles);
APedido.Detalles.DataTable.First;
for i := 0 to APedido.Detalles.DataTable.RecordCount - 1 do
begin
AFacturasProveedorController.DetallesController.Add(ADetalles, TIPO_DETALLE_CONCEPTO);
ADetalles.Edit;
ADetalles.REFERENCIA := APedido.Detalles.REFERENCIA;
ADetalles.ID_ARTICULO := APedido.Detalles.ID_ARTICULO;
ADetalles.CONCEPTO := APedido.Detalles.CONCEPTO;
ADetalles.IMPORTE_UNIDAD := APedido.Detalles.IMPORTE_UNIDAD;
ADetalles.DESCUENTO := APedido.Detalles.DESCUENTO;
ADetalles.IMPORTE_PORTE := APedido.Detalles.IMPORTE_PORTE;
ADetalles.CANTIDAD := APedido.Detalles.CANTIDAD;
ADetalles.IMPORTE_TOTAL := APedido.Detalles.IMPORTE_TOTAL;
ADetalles.REFERENCIA_PROVEEDOR := APedido.Detalles.REFERENCIA_PROVEEDOR;
ADetalles.Post;
APedido.Detalles.Next;
end;
finally
AFacturasProveedorController.DetallesController.EndUpdate(ADetalles);
// AFacturasProveedorController.DetallesController.ActualizarTotales(ADetalles);
end;
end;
procedure Inicializar;
begin
dmGenerarFacturasProv := TdmGenerarFacturasProv.Create(nil);
APedidosProveedorController := TPedidosProveedorController.Create;
ADetallesPedidosProveedorController := TDetallesPedidoProveedorController.Create;
AFacturasProveedorController := TFacturasProveedorController.Create;
// AProveedoresController := TProveedoresController.Create;
end;
procedure Finalizar;
begin
FreeAndNIL(dmGenerarFacturasProv);
APedidosProveedorController := nil;
ADetallesPedidosProveedorController := nil;
AFacturasProveedorController := nil;
// AProveedoresController := nil;
end;
function GenerarFacturaProv(const IDPedido : Integer) : Boolean; overload;
var
APedido : IBizPedidoProveedor;
begin
Result := False;
if not Assigned(APedidosProveedorController) then
Inicializar;
APedido := APedidosProveedorController.Buscar(IDPedido);
Result := GenerarFacturasProv(APedido);
if Assigned(APedidosProveedorController) then
Finalizar;
end;
function GenerarFacturasProv : Boolean; overload;
var
APedidos : IBizPedidoProveedor;
begin
Result := False;
if not Assigned(APedidosProveedorController) then
Inicializar;
APedidos := APedidosProveedorController.ElegirPedidos(APedidosProveedorController.BuscarSinFacturar,
'Elija el pedido/s de proveedor que desea utilizar para dar de alta la factura.'
+ #10#13 + 'Si elige Pedidos de proveedores diferentes se dará de alta una factura por cada uno de ellos.' , True);
if Assigned(APedidos) then
Result := GenerarFacturasProv(APedidos);
if Assigned(APedidosProveedorController) then
Finalizar;
end;
function GenerarFacturasProv(APedidos : IBizPedidoProveedor) : Boolean; overload;
var
AFacturasNuevas : IBizFacturaProveedor;
i: Integer;
ARespuesta : Integer;
begin
Result := False;
if not Assigned(APedidosProveedorController) then
Inicializar;
if not Assigned(APedidos) then
raise Exception.Create('Pedidos de proveedor no asignado (GenerarFacturasProv)');
if not APedidos.DataTable.Active then
APedidos.DataTable.Active := True;
try
AFacturasNuevas := AFacturasProveedorController.Nuevo(False);
if GenerarFacturasdeListaPedidos(AFacturasNuevas, APedidos) then
begin
if AFacturasNuevas.DataTable.RecordCount = 1 then
begin
with dmGenerarFacturasProv.JsListaFacturasGeneradas do
begin
Content.Clear;
Content.Add(Format('Se ha generado correctamente la factura %s a partir del pedido de proveedor' + #10#13, [AFacturasNuevas.REFERENCIA]));
end;
end
else begin
dmGenerarFacturasProv.JsListaFacturasGeneradas.CustomButtons[1].Destroy;
with dmGenerarFacturasProv.JsListaFacturasGeneradas.Content do
begin
Clear;
AFacturasNuevas.DataTable.Last;
for i := 0 to AFacturasNuevas.DataTable.RecordCount - 1 do
begin
if Length(AFacturasNuevas.REFERENCIA) > 0 then
Add(AFacturasNuevas.REFERENCIA + ': ' + AFacturasNuevas.NOMBRE);
AFacturasNuevas.DataTable.Prior;
end;
end;
end;
dmGenerarFacturasProv.JsListaFacturasGeneradas.Execute;
ARespuesta := dmGenerarFacturasProv.JsListaFacturasGeneradas.CustomButtonResult;
case ARespuesta of
100 : begin
// Ver la factura
AFacturasProveedorController.Ver(AFacturasNuevas);
end;
200 : // Continuar;
end;
end;
finally
AFacturasNuevas := NIL;
end;
end;
function GenerarFacturasdeListaPedidos(AFacturas: IBizFacturaProveedor; AListaPedidos: IBizPedidoProveedor): Boolean;
var
AFacturaActual : IBizFacturaProveedor;
APedidosController : IPedidosProveedorController;
AArticulosPendientes : IBizDetallesPedidoProveedorPend;
I: Integer;
bEnEdicion : Boolean;
begin
Result := False;
// ATENCIÓN!!! AFacturas tiene que estar vacio para no pisar facturas
// ya generados.
if not Assigned(AFacturas) then
raise Exception.Create ('Facturas no asignado (Anadir)');
if not Assigned(AListaPedidos) then
raise Exception.Create ('Pedidos no asignados (Anadir)');
if not AFacturas.DataTable.Active then
AFacturas.DataTable.Active := True;
if not AListaPedidos.DataTable.Active then
AListaPedidos.DataTable.Active := True;
APedidosController := TPedidosProveedorController.Create;
try
// Ordenar por fecha de pedido
AListaPedidos.DataTable.Sort([fld_PedidosProveedorFECHA_PEDIDO], [uDADataTable.sdAscending]);
AListaPedidos.First;
for I := 0 to AListaPedidos.DataTable.RecordCount - 1 do
begin
AListaPedidos._Proveedor := NIL;
AFacturaActual := NIL;
// Busco si hay alguna factura ya hecha de ese Proveedor
AFacturas.DataTable.First;
if AFacturas.DataTable.Locate(fld_FacturasProveedorID_Proveedor, AListaPedidos.ID_Proveedor, []) then
AFacturaActual := AFacturas
else
begin
// No hay factura de ese proveedor. Creo una nueva
AFacturasProveedorController.Anadir(AFacturas);
AFacturaActual := AFacturas;
end;
//Asignamos el proveedor del pedido en la factura siempre
APedidosController.RecuperarProveedor(AListaPedidos);
AFacturaActual.Proveedor := AListaPedidos.Proveedor;
//Tanto si es nueva como ya existe añadimos la referencia del pedido a añadir
bEnEdicion := (AFacturaActual.DataTable.State in dsEditModes);
if not bEnEdicion then
AFacturaActual.Edit;
//Por cada pedido a añadir lo asignamos al campo manual de referencias de pedidos asociados REF_PEDIDOS_PROV
AFacturaActual.REF_PEDIDOS_PROV := AFacturaActual.REF_PEDIDOS_PROV + ' ' + AListaPedidos.REFERENCIA;
AFacturaActual.Post;
if bEnEdicion then
AFacturaActual.Edit;
AFacturaActual.Detalles.DataTable.Last;
// Añado el título
AFacturasProveedorController.DetallesController.Add(AFacturaActual.Detalles, TIPO_DETALLE_TITULO);
with AFacturaActual.Detalles do
begin
Edit;
CONCEPTO := 'Pedido ' + AListaPedidos.REFERENCIA + ' del ' + DateToStr(AListaPedidos.FECHA_PEDIDO);
Post;
end;
// Añado el contenido del pedido
CopiarArticulosAFactura(AListaPedidos, AFacturaActual);
{En los albaranes a proveedor el porte es a nivel del artículo
Self.DetallesController.Add(AFacturaActual.Detalles, TIPO_DETALLE_CONCEPTO);
with AFacturaActual.Detalles do
begin
Edit;
CONCEPTO := 'Porte del albarán';
CANTIDAD := 1;
IMPORTE_UNIDAD := AListaAlbaranes.IMPORTE_PORTE;
Post;
end;
}
// Añado el resumen
AFacturasProveedorController.DetallesController.Add(AFacturaActual.Detalles, TIPO_DETALLE_SUBTOTAL);
with AFacturaActual.Detalles do
begin
Edit;
CONCEPTO := 'Total del pedido ' + AListaPedidos.REFERENCIA;
Post;
end;
// Añado una línea en blanco
AFacturasProveedorController.DetallesController.Add(AFacturaActual.Detalles, TIPO_DETALLE_CONCEPTO);
with AFacturaActual.Detalles do
begin
Edit;
CONCEPTO := '';
Post;
end;
// Guardo el albaran que acabo de generar o editar
AFacturaActual.CalcularImporteTotal;
AFacturasProveedorController.Guardar(AFacturaActual);
// No se asocia la factura al pedido ya que un pedido, solo puede estar asociado a una factura y una factura puede tener asociados varios pedidos
//09/06/2025 ahora Stefy nos dice que puede venir un pedido en varias facturas diferentes por lo que no podemos asociar la factura al pedido
AListaPedidos.Edit;
AListaPedidos.ID_FACTURA := AFacturaActual.ID;
AListaPedidos.REF_FACTURA := AFacturaActual.REFERENCIA;
AListaPedidos.Post;
APedidosController.Guardar(AListaPedidos);
AListaPedidos.Next;
end;
Result := True;
finally
APedidosController := NIL;
end;
end;
end.