unit uGenerarFacturasCliAlbCliUtils; interface uses Windows, SysUtils, Classes, uBizAlbaranesCliente, uBizFacturasCliente, pngimage, JSDialog; type TdmGenerarFacturasCliAlbCli = class(TDataModule) JsListaFacturasGeneradas: TJSDialog; end; function GenerarFacturaCliAlb(const IDAlbaran : Integer; const CopiarDetalles: Boolean = True) : Boolean; overload; function GenerarFacturaCliAlb(AAlbaran : IBizAlbaranCliente; const CopiarDetalles: Boolean = True) : Boolean; overload; function GenerarFacturaCliAlb : Boolean; overload; function GenerarFacturas(AFacturas : IBizFacturaCliente; AListaAlbaranes : IBizAlbaranCliente; const CopiarDetalles: Boolean = True): Boolean; implementation {$R *.dfm} uses DB, uDialogUtils, uDADataTable, uControllerDetallesBase, uBizDetallesFacturaCliente, uBizDetallesAlbaranCliente, uAlbaranesClienteController, uDetallesFacturaClienteController, uFacturasClienteController, schFacturasClienteClient_Intf, schAlbaranesClienteClient_Intf; // , // , uProveedoresController, // , uControllerDetallesBase, // , uBizContactos, , // ; var dmGenerarFacturasCliAlbCli: TdmGenerarFacturasCliAlbCli; AFacturasClienteController : IFacturasClienteController; AAlbaranesClienteController : IAlbaranesClienteController; ADetallesAlbaranesClienteController : IDetallesFacturaClienteController; // AProveedoresController : IProveedoresController; { Métodos auxiliares } {procedure CopiarPedidoAAlbaran(AAlbaran: IBizPedidoCliente; AAlbaran : IBizAlbaranProveedor); begin if not Assigned(AAlbaran) then raise Exception.Create ('Albarán no asignado (CopiarPedidoAAlbaran)'); if not Assigned(AAlbaran) then raise Exception.Create ('Pedido no asignado (CopiarPedidoAAlbaran)'); if not AAlbaran.DataTable.Active then AAlbaran.DataTable.Active := True; // El albarán tiene que venir ya abierto y posicionado donde hay que copiar AAlbaran.ID_CLIENTE := AAlbaran.ID_CLIENTE; AAlbaran.ID_PEDIDO := AAlbaran.ID; AAlbaran.CALLE := AAlbaran.CALLE; AAlbaran.CODIGO_POSTAL := AAlbaran.CODIGO_POSTAL; AAlbaran.POBLACION := AAlbaran.POBLACION; AAlbaran.PROVINCIA := AAlbaran.PROVINCIA; AAlbaran.PERSONA_CONTACTO := AAlbaran.PERSONA_CONTACTO; AAlbaran.TELEFONO := AAlbaran.TELEFONO; AAlbaran.IMPORTE_NETO := AAlbaran.IMPORTE_NETO; AAlbaran.IMPORTE_PORTE := AAlbaran.IMPORTE_PORTE; AAlbaran.DESCUENTO := AAlbaran.DESCUENTO; AAlbaran.IMPORTE_DESCUENTO := AAlbaran.IMPORTE_DESCUENTO; AAlbaran.BASE_IMPONIBLE := AAlbaran.BASE_IMPONIBLE; AAlbaran.IVA := AAlbaran.IVA; AAlbaran.IMPORTE_IVA := AAlbaran.IMPORTE_IVA; AAlbaran.IMPORTE_TOTAL := AAlbaran.IMPORTE_TOTAL; AAlbaran.DataTable.FieldByName(fld_AlbaranesClienteOBSERVACIONES).AsVariant := AAlbaran.DataTable.FieldByName(fld_PedidosClienteOBSERVACIONES).AsVariant; AAlbaran.ID_FORMA_PAGO := AAlbaran.ID_FORMA_PAGO; end; procedure CopiarArticulosPendAAlbaran( AAlbaran: IBizPedidoCliente; AAlbaran: IBizAlbaranProveedor; AArticulosPendientes: IBizPedidoClienteArticulosPend); var i : integer; ADetalles : IBizDetallesFacturaClieedor; ADetallesController : IDetallesFacturaClieedorController; begin if not Assigned(AAlbaran) then raise Exception.Create ('Albarán no asignado (CopiarArticulosPendAAlbaran)'); if not Assigned(AAlbaran) then raise Exception.Create ('Pedido no asignado (CopiarArticulosPendAAlbaran)'); if not Assigned(AArticulosPendientes) then raise Exception.Create ('Artículos pendientes no asignado (CopiarArticulosPendAAlbaran)'); if not AArticulosPendientes.DataTable.Active then AArticulosPendientes.DataTable.Active := True; // El albarán tiene que venir ya abierto y posicionado donde hay que copiar ADetalles := AAlbaran.Detalles; ADetallesController := TDetallesFacturaClieedorController.Create; 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 ADetallesController.BeginUpdate(ADetalles); AArticulosPendientes.DataTable.First; for i := 0 to AArticulosPendientes.DataTable.RecordCount - 1 do begin AAlbaran.Detalles.First; if (AAlbaran.Detalles.Locate('ID_ARTICULO', AArticulosPendientes.ID_ARTICULO, [])) then if (AArticulosPendientes.CANTIDAD_PENDIENTE > 0) then begin ADetallesController.Add(ADetalles, TIPO_DETALLE_CONCEPTO); ADetalles.Edit; ADetalles.REFERENCIA := AAlbaran.Detalles.REFERENCIA; ADetalles.ID_ARTICULO := AAlbaran.Detalles.ID_ARTICULO; ADetalles.CONCEPTO := AAlbaran.Detalles.CONCEPTO; ADetalles.CANTIDAD := AArticulosPendientes.CANTIDAD_PENDIENTE; ADetalles.IMPORTE_UNIDAD := AAlbaran.Detalles.IMPORTE_UNIDAD; ADetalles.IMPORTE_TOTAL := AAlbaran.Detalles.IMPORTE_TOTAL; ADetalles.DESCUENTO := AAlbaran.Detalles.DESCUENTO; ADetalles.IMPORTE_PORTE := AAlbaran.Detalles.IMPORTE_PORTE; ADetalles.VISIBLE := AAlbaran.Detalles.VISIBLE; ADetalles.REFERENCIA_PROVEEDOR := AAlbaran.Detalles.REFERENCIA_PROVEEDOR; ADetalles.Post; AArticulosPendientes.Next; end; end; finally ADetallesController.EndUpdate(ADetalles); ADetallesController := NIL; end; end; } procedure CopiarArticulosAlbaran(AOrigen: IBizDetallesAlbaranCliente; ADestino : IBizDetallesFacturaCliente); var i : integer; ADetallesController : IDetallesFacturaClienteController; begin if not Assigned(AOrigen) then raise Exception.Create ('Origen no asignado (CopiarArticulosAlbaran)'); if not Assigned(ADestino) then raise Exception.Create ('Destino no asignado (CopiarArticulosAlbaran)'); if not AOrigen.DataTable.Active then AOrigen.DataTable.Active := True; if not ADestino.DataTable.Active then ADestino.DataTable.Active := True; ADetallesController := TDetallesFacturaClienteController.Create; 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 ADetallesController.BeginUpdate(ADestino); AOrigen.DataTable.First; for i := 0 to AOrigen.DataTable.RecordCount - 1 do begin ADetallesController.Add(ADestino, TIPO_DETALLE_CONCEPTO); ADestino.Edit; // ADestino.REFERENCIA := AOrigen.REFERENCIA; if AOrigen.ID_ARTICULO > 0 then ADestino.ID_ARTICULO := AOrigen.ID_ARTICULO; ADestino.CONCEPTO := AOrigen.CONCEPTO; ADestino.CANTIDAD := AOrigen.CANTIDAD; ADestino.IMPORTE_UNIDAD := AOrigen.IMPORTE_UNIDAD; ADestino.IMPORTE_TOTAL := AOrigen.IMPORTE_TOTAL; ADestino.DESCUENTO := AOrigen.DESCUENTO; ADestino.IMPORTE_PORTE := AOrigen.IMPORTE_PORTE; ADestino.VISIBLE := AOrigen.VISIBLE; // ADestino.REFERENCIA_PROVEEDOR := AOrigen.REFERENCIA_PROVEEDOR; ADestino.Post; AOrigen.Next; end; finally ADetallesController.EndUpdate(ADestino); ADetallesController := NIL; end; end; procedure Inicializar; begin dmGenerarFacturasCliAlbCli := TdmGenerarFacturasCliAlbCli.Create(nil); AFacturasClienteController := TFacturasClienteController.Create; AAlbaranesClienteController := TAlbaranesClienteController.Create; ADetallesAlbaranesClienteController := TDetallesFacturaClienteController.Create; // AProveedoresController := TProveedoresController.Create; end; procedure Finalizar; begin FreeAndNIL(dmGenerarFacturasCliAlbCli); AFacturasClienteController := nil; AAlbaranesClienteController := nil; ADetallesAlbaranesClienteController := nil; // AProveedoresController := nil; end; function GenerarFacturaCliAlb(const IDAlbaran : Integer; const CopiarDetalles: Boolean = True) : Boolean; overload; var AAlbaran : IBizAlbaranCliente; begin Result := False; try if not Assigned(AAlbaranesClienteController) then Inicializar; AAlbaran := AAlbaranesClienteController.Buscar(IDAlbaran); if Assigned(AAlbaran) then begin if (ShowConfirmMessage('Generar factura', Format('¿Desea copiar todos los conceptos del albaran seleccionados a su factura correspondiente?', [])) = IDYES) then Result := GenerarFacturaCliAlb(AAlbaran) else Result := GenerarFacturaCliAlb(AAlbaran, False); end; if Assigned(AAlbaranesClienteController) then Finalizar; finally AAlbaran := NIL; end; end; function GenerarFacturaCliAlb(AAlbaran : IBizAlbaranCliente; const CopiarDetalles: Boolean = True) : Boolean; overload; var AFacturasNuevas : IBizFacturaCliente; i: Integer; begin Result := False; if not Assigned(AAlbaran) then raise Exception.Create('Albarán de proveedor no asignado (GenerarFacturaCliAlb)'); if not AAlbaran.DataTable.Active then AAlbaran.DataTable.Active := True; if not Assigned(AAlbaranesClienteController) then Inicializar; try AFacturasNuevas := AFacturasClienteController.Nuevo(False); if GenerarFacturas(AFacturasNuevas, AAlbaran, CopiarDetalles) then begin if AFacturasNuevas.DataTable.RecordCount = 1 then begin if AFacturasNuevas.TIPO = CTE_TIPO_FACTURA then ShowInfoMessage('La factura se ha dado de alta con el código ' + AFacturasNuevas.REFERENCIA) else ShowInfoMessage('El abono se ha dado de alta con el código ' + AFacturasNuevas.REFERENCIA); end else begin with dmGenerarFacturasCliAlbCli.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; dmGenerarFacturasCliAlbCli.JsListaFacturasGeneradas.Execute; end; Result := True; end; finally AFacturasNuevas := NIL; if Assigned(AAlbaranesClienteController) then Finalizar; end; end; function GenerarFacturaCliAlb : Boolean; overload; var AAlbaranes : IBizAlbaranCliente; begin Result := False; try if not Assigned(AAlbaranesClienteController) then Inicializar; AAlbaranes := AAlbaranesClienteController.ElegirAlbaranes(AAlbaranesClienteController.BuscarSinFacturar, 'Elija el albarán o albaranes de cliente que desea utilizar para dar de alta la factura.' + #10#13 + 'Si elige albaranes de clientes diferentes se dará de alta una factura por cada uno de ellos.' , True); if Assigned(AAlbaranes) then begin if (ShowConfirmMessage('Generar factura', Format('¿Desea copiar todos los conceptos de/los albaran/es seleccionados a sus facturas correspondientes?', [])) = IDYES) then Result := GenerarFacturaCliAlb(AAlbaranes) else Result := GenerarFacturaCliAlb(AAlbaranes, False); end; if Assigned(AAlbaranesClienteController) then Finalizar; finally AAlbaranes := Nil; end; end; function GenerarFacturas(AFacturas : IBizFacturaCliente; AListaAlbaranes : IBizAlbaranCliente; const CopiarDetalles: Boolean = True): Boolean; var AFacturaActual : IBizFacturaCliente; AAlbaranesController : IAlbaranesClienteController; I: Integer; bEnEdicion : Boolean; begin // ATENCIÓN!!! AFacturas tiene que estar vacio para no pisar facturas // ya generadas. if not Assigned(AFacturas) then raise Exception.Create ('Factura no asignada (Anadir)'); if not Assigned(AListaAlbaranes) then raise Exception.Create ('Albaranes no asignados (Anadir)'); if not AFacturas.DataTable.Active then AFacturas.DataTable.Active := True; if not AListaAlbaranes.DataTable.Active then AListaAlbaranes.DataTable.Active := True; AAlbaranesController := TAlbaranesClienteController.Create; try // Ordenar por fecha de albaran AListaAlbaranes.DataTable.Sort([fld_AlbaranesClienteFECHA_ALBARAN], [uDADataTable.sdAscending]); AListaAlbaranes.First; for I := 0 to AListaAlbaranes.DataTable.RecordCount - 1 do begin AListaAlbaranes._Cliente := NIL; AFacturaActual := NIL; // Busco si hay alguna factura ya hecha de ese cliente AFacturas.DataTable.First; if AFacturas.DataTable.Locate(fld_FacturasClienteID_CLIENTE, AListaAlbaranes.ID_CLIENTE, []) then begin AFacturaActual := AFacturas; AFacturasClienteController.RecuperarCliente(AFacturaActual); AFacturaActual.Cliente.DataTable.Active := True; end else begin // No hay factura de ese cliente. Creo una nueva AFacturasClienteController.Anadir(AFacturas); AAlbaranesController.RecuperarCliente(AListaAlbaranes); AListaAlbaranes.Cliente.DataTable.Active := True; AFacturas.Cliente := AListaAlbaranes.Cliente; //Si el albaran es de tipo devolución hacemos la factura de tipo abono if (AListaAlbaranes.TIPO = CTE_TIPO_ALBARAN_DEV) then begin bEnEdicion := (AFacturas.DataTable.State in dsEditModes); if not bEnEdicion then AFacturas.Edit; AFacturas.TIPO := CTE_TIPO_ABONO; AFacturas.Post; if bEnEdicion then AFacturas.Edit; end; AFacturaActual := AFacturas; end; // Ya tengo la factura. Le añado los conceptos del albarán AFacturaActual.Detalles.DataTable.Last; //Se pone la referencia del pedido y el total y nos olvidamos de los detalles if not CopiarDetalles then begin AFacturasClienteController.DetallesController.Add(AFacturaActual.Detalles, TIPO_DETALLE_CONCEPTO); with AFacturaActual.Detalles do begin Edit; CONCEPTO := 'Albaran ' + AListaAlbaranes.REFERENCIA; CANTIDAD := 1; IMPORTE_UNIDAD := AListaAlbaranes.IMPORTE_TOTAL; //Tecsitel no utiliza el IVA en los pedidos por lo tanto el //importe total es lo que queremos (IMPORTE_NETO+IMPORTE_PORTE) Post; end; end //Se copian los detalles del pedido a la factura else begin // Añado el título AFacturasClienteController.DetallesController.Add(AFacturaActual.Detalles, TIPO_DETALLE_TITULO); with AFacturaActual.Detalles do begin Edit; CONCEPTO := 'Albarán ' + AListaAlbaranes.REFERENCIA + ' del ' + DateToStr(AListaAlbaranes.FECHA_ALBARAN); Post; end; // Añado el contenido del albarán CopiarArticulosAlbaran(AListaAlbaranes.Detalles, AFacturaActual.Detalles); AFacturasClienteController.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 AFacturasClienteController.DetallesController.Add(AFacturaActual.Detalles, TIPO_DETALLE_SUBTOTAL); with AFacturaActual.Detalles do begin Edit; CONCEPTO := 'Total del albarán ' + AListaAlbaranes.REFERENCIA; Post; end; end; // Añado una línea en blanco AFacturasClienteController.DetallesController.Add(AFacturaActual.Detalles, TIPO_DETALLE_CONCEPTO); with AFacturaActual.Detalles do begin Edit; CONCEPTO := ''; Post; end; // Guardo la factura que acabo de generar o editar AFacturaActual.CalcularImporteTotal; AFacturasClienteController.Guardar(AFacturaActual); // Asocio la factura con el albarán AListaAlbaranes.Edit; AListaAlbaranes.ID_FACTURA := AFacturaActual.ID; AListaAlbaranes.Post; AAlbaranesController.Guardar(AListaAlbaranes); AListaAlbaranes.Next; end; Result := True; finally AAlbaranesController := NIL; // HideHourglassCursor end; end; end.