{
===============================================================================
  Copyright (©) 2001. Rodax Software.
===============================================================================
  Los contenidos de este fichero son propiedad de Rodax Software titular del
  copyright. Este fichero sólo podrá ser copiado, distribuido y utilizado,
  en su totalidad o en parte, con el permiso escrito de Rodax Software, o de
  acuerdo con los términos y condiciones establecidas en el acuerdo/contrato
  bajo el que se suministra.
  -----------------------------------------------------------------------------
  Web:  www.rodax-software.com
===============================================================================
  Fecha primera versión: 01-10-2001
  Versión actual: 1.0.9
  Fecha versión actual: 30-07-2004
===============================================================================
  Modificaciones:

    Fecha         Comentarios
    ---------------------------------------------------------------------------
    27-10-2001    Se ha eliminado el apartado 'Notas'.

    27-10-2001    Se ha añadido el CIF del cliente junto con el resto de sus
                  datos.

    27-10-2001    Se ha eliminado la persona de contacto del cliente y se ha
                  reemplazado por el literal 'Departamento de contabilidad'.

    30-10-2001    Debe aparecer el importe del IVA y del descuento.

    30-10-2001    Si la factura no tiene descuento, no debe aparecer en el
                  informe.

    27-11-2001    Se han añadido las unidades de medida.

    15-01-2002    Imprimir la provincia del cliente junto con el resto
                  de la dirección.

    17-02-2002    Al final de cada capítulo de aparecer su importe total.

    07-04-2002    Se ha adaptado para la transacción única.

    08-03-2004    p272. Adaptación a multiempresa.

    30-07-2004    p284. Se han añadido los datos de inscripción del Registro
                  Mercantil a la tabla de empresas.

    01-03-2006    Se ha añadido el campo BaseImponible2 que nos aclara la base
                  imponible sobre la que se aplica el IVA

===============================================================================
}

unit InformeFacturaCliente;

interface

uses
  classes, AHWord97, IB, IBCustomDataSet, Ibdatabase, Mensajes,
  Word2000;

type
  TInformeFacturaCliente = class(TComponent)
  private
    sqlCabeceraFactura : TStrings;
    sqlDetallesFactura : TStrings;
    FPlantilla : string;
    FWordApp : TWordApp;
    FDocumento : TWordDoc;
    FTransaccion : TIBTransaction;
    FBaseDatos : TIBDatabase;
    FNumCapitulos : Integer;
    FCodigoFactura : string;
    FTabla : TIBDataSet;
    FNombreFichero : String;
    SentenciaSQL : TStrings;
    function DarNumCapitulos : Integer;
    procedure InsertarConceptos(Tabla : Table);
    function Generar (Codigo : string) : Boolean;
    procedure InicializarSQLInforme; virtual;
    procedure InicializarParametrosSQL; virtual;
    function InicializarTabla : boolean;
    function RellenarCabecera : boolean; virtual;
    function RellenarInforme : boolean; virtual;
  public
    constructor Create (AOwner : TComponent); override;
    destructor Destroy; override;
    function Exportar(Codigo, Fichero : String): Boolean;
    function Imprimir(Codigo : String): Boolean;
  end;

implementation

{ TInformeFacturaCliente }

uses
  BaseDatos, TablaFacturasCliente, DB, Sysutils, Controls, Constantes,
  Configuracion, Forms, StrFunc, RdxUtilidades, RdxEmpresaActiva,
  Literales, SysFunc;

constructor TInformeFacturaCliente.Create(AOwner: TComponent);
begin
  inherited;
  FDocumento := NIL;
  SentenciaSQL := TStringList.Create;
  FNumCapitulos := 0;

  sqlCabeceraFactura := TStringList.Create;
  sqlDetallesFactura := TStringList.Create;

  FBaseDatos := dmBaseDatos.BD;
  FTransaccion := dmBaseDatos.Transaccion;
  FPlantilla := ExtractFileDir(ParamStr(0))+ '\informes\' + IntToStr(EmpresaActiva.ModeloInforme) + '\FacturaCliente.rdx';
end;

function TInformeFacturaCliente.DarNumCapitulos: Integer;
var
  AuxNumCapitulos : integer;
begin
  AuxNumCapitulos := 0;
  FTabla.First;
  while not FTabla.Eof do
  begin
    if FTabla.FieldByName('TIPO').AsString = 'TIT' then
      AuxNumCapitulos := AuxNumCapitulos + 1;
    FTabla.Next;
  end;
  FTabla.First;
  Result := AuxNumCapitulos;
end;

destructor TInformeFacturaCliente.Destroy;
begin
  FTabla.Close;
  FTabla.Free;
  FTabla := NIL;
  
  if FDocumento <> NIL then
    FDocumento.Free;
  FDocumento := NIL;

  FTransaccion := NIL;

  FBaseDatos := NIL;

  sqlCabeceraFactura.Free;
  sqlDetallesFactura.Free;

  inherited;
end;

function TInformeFacturaCliente.Exportar(Codigo, Fichero: String): Boolean;
begin
  if EsCadenaVacia(Fichero) then
  begin
    Result := False;
    raise Exception.Create(msgInfFaltaFicheroListado);
  end;

  FNombreFichero := Fichero;
  Result := Generar(Codigo);
end;

function TInformeFacturaCliente.Generar (Codigo : string) : Boolean;
var
  Aux : OleVariant;
begin
  if EsCadenaVacia(Codigo) then
    raise Exception.Create(msgInfFaltaCodFac);

  FCodigoFactura := Codigo;
  Screen.Cursor := crHourglass;

  FWordApp := TWordApp.Create (False, False);
  with FWordApp do
  begin
    Visible := False;
    ScreenUpdating := False;
  end;

  FDocumento := TWordDoc.CreateNewDoc(FWordApp, FPlantilla);
  FWordApp.ScreenUpdating := False;
  try
    InicializarSQLInforme;
    SentenciaSQL := sqlCabeceraFactura;
    InicializarTabla;
    InicializarParametrosSQL;

    if not RellenarCabecera then
    begin
      VerMensaje(msgInfFalloRellenarCabecera);
      Exit;
    end;

    SentenciaSQL := sqlDetallesFactura;
    InicializarTabla;
    InicializarParametrosSQL;

    if not RellenarInforme then
    begin
      VerMensaje(msgInfFalloRellenarInforme);
      Exit;
    end;
    FDocumento.SaveAs(FNombreFichero);
    FWordApp.CloseApp(wdDoNotSaveChanges);
    Result := True;
  finally
    FDocumento := NIL;
    FWordApp := NIL;
    Screen.Cursor := crArrow;
  end;
end;

function TInformeFacturaCliente.Imprimir(Codigo: String): Boolean;
begin
  FNombreFichero := DarFicheroTemporal;
  if not Generar(Codigo) then
  begin
    Result := False;
    Exit;
  end;
  Result := ImprimirDoc(FNombreFichero);
  DeleteFile(FNombreFichero);
end;

procedure TInformeFacturaCliente.InicializarParametrosSQL;
begin
  FTabla.ParamByName('CODIGOEMPRESA').AsInteger := EmpresaActiva.Codigo;
  FTabla.ParamByName('CODIGOFACTURA').AsString := FCodigoFactura;
end;

procedure TInformeFacturaCliente.InicializarSQLInforme;
begin
  with sqlCabeceraFactura do
  begin
//    Add('select * ');
//    Add('from FACTURASCLIENTE ');
//    Add('where (CODIGO = :CODIGOFACTURA)');
//    Add('and (CODIGOEMPRESA = :CODIGOEMPRESA)');

      Add('select CODIGOEMPRESA, CODIGO, FECHAALTA, FECHAVENCIMIENTO, FORMAPAGO,');
      Add('SITUACION, USUARIO, DESCRIPCION, CODIGOCLIENTE, NIFCIF, NOMBRE,');
      Add('CALLE, NUMERO, PISO, CODIGOPOSTAL, POBLACION, PROVINCIA, PERSONACONTACTO,');
      Add('TELEFONO, FAX, CODIGOPRESUPUESTOALBARAN, BASEIMPONIBLE, DESCUENTO, IVA,');
      Add('IMPORTETOTAL, BANCO, NOTAS, CODIGOCLIENTEFINAL, NOMBRECLIENTEFINAL, IMPORTEDESCUENTO * (-1) as IMPORTEDESCUENTO,');
      Add('IMPORTEIVA, CLASEFACTURA, CODIGOCARGO, (BASEIMPONIBLE-IMPORTEDESCUENTO) as BASEIMPONIBLE2');
      Add('from FACTURASCLIENTE');
      Add('where (CODIGO = :CODIGOFACTURA)');
      Add('and (CODIGOEMPRESA = :CODIGOEMPRESA)');
  end;

  with sqlDetallesFactura do
  begin
    Add('select * ');
    Add('from DETALLESFACTURASCLIENTE ');
    Add('where (CODIGOFACTURA = :CODIGOFACTURA) ');
    Add('and (CODIGOEMPRESA = :CODIGOEMPRESA)');
    Add('order by NUMCONCEPTO');
  end;
end;

function TInformeFacturaCliente.InicializarTabla: boolean;
begin
  Result := True;
  FTabla := TIBDataSet.Create(Self);
  try
    FTabla.Database := FBaseDatos;
    FTabla.Transaction := FTransaccion;
    FTabla.SelectSQL.Assign(SentenciaSQL);
  except
    on E : EIBError do begin
      VerMensaje(E.Message);
      Result := False;
    end;
  end;
end;

procedure TInformeFacturaCliente.InsertarConceptos(Tabla : Table);
var
  numRows, numCols, mergeSplit, shiftCells : OleVariant;
  iContador : Integer;
  TotalConceptos : Double;
begin
  numRows := 2;
  numCols := 1;
  mergeSplit := False;
  shiftCells := False;
  iContador := 2; // Empezar en la 2ª fila de celdas. La primera es la
                  // cabecera de la tabla.

  with Tabla, FTabla do
  begin
    while not EOF do
    begin
      if FieldByName('TIPO').AsString <> 'CON' then
        Break;
      // Partir la celda actual en 2 filas de 1 columna.
      Rows.Item(iContador).Cells.Split (numRows, numCols, mergesplit);
      Cell(iContador, 1).Range.Text := FieldByName('DESCRIPCION').AsString;
      Cell(iContador, 2).Range.Text := FieldByName('CANTIDAD').AsString;
      Cell(iContador, 3).Range.Text := FieldByName('PRECIO').DisplayText;
      Cell(iContador, 4).Range.Text := FieldByName('TOTAL').DisplayText;
      TotalConceptos := TotalConceptos + FieldByName('TOTAL').AsFloat;
      Next;
      Inc (iContador);
    end;
    // Borrar la fila vacía que sobra
    Rows.Item(iContador).Cells.Delete(shiftCells);
    Cell(iContador, 1).Range.Text := 'Total: ' + FormatFloat(DISPLAY_EUROS2, TotalConceptos);
    AutoFitBehavior(wdAutoFitWindow);
  end;
end;

function TInformeFacturaCliente.RellenarCabecera: boolean;
var
  NombreFichero,
  Texto,
  FicheroTemporal : String;
  LinkToFile, SaveWithDocument, _Range : OleVariant;
  Imagen : InlineShape;
  _ShiftCells : OleVariant;

begin

  //PARA DIBUJAR EL LOGOTIPO MULTIEMPRESA
  if (EmpresaActiva.Logotipo <> Nil) then
  begin
    //Activamos cabecera
    FWordApp.Application.ActiveWindow.ActivePane.View.SeekView := wdSeekCurrentPageHeader;
    LinkToFile := False;
    SaveWithDocument := True;
    _Range := EmptyParam;
    FicheroTemporal := DarFicheroTemporal;
    EmpresaActiva.Logotipo.SaveToFile (FicheroTemporal);
    Imagen := FWordApp.Application.ActiveWindow.ActivePane.Selection.InlineShapes.AddPicture(ficherotemporal, LinkToFile, SaveWithDocument, _Range);

    //Formateamos imagen
    if ((Imagen.Get_Width > ANCHO_LOGO_INF)) then
    begin
      Imagen.Set_Height(((ANCHO_LOGO_INF * Imagen.Get_Height) /Imagen.Get_Width));
      Imagen.Set_Width(ANCHO_LOGO_INF);
    end;
  end;

  with FDocumento, FTabla do
  begin
    Prepare;
    Open;
    dmTablaFacturasCliente.InicializarTablaFacturas(@FTabla);
    ReplaceBookmark('CodigoFacturaCab', FCodigoFactura);
    ReplaceBookmark('FechaFacturaCab', FieldByName('FECHAALTA').AsString);
    ReplaceBookmark('VencimientoCab', FieldByName('FECHAVENCIMIENTO').AsString);
    ReplaceBookmark('FormaPagoCab', FieldByName('FORMAPAGO').AsString);
    ReplaceBookmark('BancoCab', FieldByName('BANCO').AsString);

    ReplaceBookmark('NombreClienteCab', FieldByName('NOMBRE').AsString);
    ReplaceBookmark('CIFClienteCab', FieldByName('NIFCIF').AsString);

    ReplaceBookmark('DireccionClienteCab',
       FieldByName('CALLE').AsString + ', ' + FieldByName('NUMERO').AsString +
       ' ' + FieldByName('PISO').AsString);
    ReplaceBookmark('PoblacionClienteCab',
       FieldByName('CODIGOPOSTAL').AsString + ' ' +
       FieldByName('POBLACION').AsString + ' ' + FieldByName('PROVINCIA').AsString);

    ReplaceBookmark('BaseImponible', FieldByName('BASEIMPONIBLE').DisplayText);
    ReplaceBookmark('BaseImponible2', FieldByName('BASEIMPONIBLE2').DisplayText);    

    if (FieldByName('DESCUENTO').AsInteger = 0) then
    begin
      ReplaceBookmark('BaseImponibleTexto', 'Base imponible');
      FWordApp.GotoBookmark('CeldasDescuento');
      _ShiftCells := wdDeleteCellsShiftLeft;
      FWordApp.Application.Selection.Cells.Delete(_ShiftCells);
    end
    else begin
      ReplaceBookmark('Descuento', FieldByName('DESCUENTO').DisplayText);
      ReplaceBookmark('ImporteDto', FieldByName('IMPORTEDESCUENTO').DisplayText);
    end;
    if EsCadenaVacia(FieldByName('IVA').DisplayText) then
      ReplaceBookmark('IVA', '0')
    else
      ReplaceBookmark('IVA', FieldByName('IVA').DisplayText);
    ReplaceBookmark('ImporteIVA', FieldByName('IMPORTEIVA').DisplayText);
    ReplaceBookmark('ImporteTotal', FieldByName('IMPORTETOTAL').DisplayText);

    Texto := FieldByName('DESCRIPCION').AsString;
    if not EsCadenaVacia(Texto) then
    begin
      NombreFichero := DarFicheroTemporal;
      EscribirEnFichero(NombreFichero, Texto);
      FWordApp.InsertFile(NombreFichero, 'Descripcion');
      DeleteFile(NombreFichero);
    end;

    ReplaceBookmark('NombreEmpresa', EmpresaActiva.Nombre);
    ReplaceBookmark('CifEmpresa', EmpresaActiva.NifCif);  // Aparece oculto en Word
    ReplaceBookmark('DireccionEmpresa',
      Format('%s, %s. %s %s', [EmpresaActiva.Calle, EmpresaActiva.Numero,
      EmpresaActiva.CodigoPostal, EmpresaActiva.Poblacion]));
    ReplaceBookmark('TelefonoEmpresa', EmpresaActiva.Telefono);
    ReplaceBookmark('FaxEmpresa', EmpresaActiva.Fax);
    ReplaceBookmark('CorreoEmpresa', EmpresaActiva.Correo);

    ReplaceBookmark('DatosRegistroMercantil', EmpresaActiva.RegistroMercantil);
    Close;
  end;
  Result := True;
end;

function TInformeFacturaCliente.RellenarInforme : boolean;
var
  numRows, numCols, mergesplit : OleVariant;
  iRowCount : Integer;
  TipoConAnterior : String;
  Seleccion : TWordRange;
  TotalCapitulo : Double;
  EsCapitulo : Boolean;
begin
  Result := False;
  iRowCount := 2;
  numrows := 2;
  numcols := 1;
  mergeSplit := False;
  TipoConAnterior := '';
  TotalCapitulo := 0;
  EsCapitulo := False;

  with FDocumento.Document.Tables.Item(1), FTabla do
  begin
    Prepare;
    Open;
    dmTablaFacturasCliente.InicializarTablaDetalles(@FTabla);
    First;
    while not FTabla.EOF do
    begin
        if (TipoConAnterior = 'CON') and (FieldByName('TIPO').AsString = 'TIT') then
        begin
          Rows.Item (iRowCount).Cells.Split (numRows, numCols, mergesplit);
          if EsCapitulo then
          begin
            Rows.Item (iRowCount).Cells.Split (numRows, numCols, mergesplit);
            Cell(iRowCount, 2).Range.Text := 'TOTAL DEL CAPÍTULO';
            Cell(iRowCount, 5).Range.Text := FormatFloat(DISPLAY_EUROS2, TotalCapitulo);
            TotalCapitulo := 0;
            Inc (iRowCount);
          end;
          Inc (iRowCount);
        end;
        Rows.Item (iRowCount).Cells.Split (numRows, numCols, mergesplit);
        if FieldByName('TIPO').AsString = 'TIT' then
        begin
          Cell(iRowCount, 2).Range.Text := FieldByName('DESCRIPCION').AsString;
          Rows.Item(iRowCount).Select;
          Seleccion := FDocumento.AddRangeFromSelection;
          Seleccion.Bold := True;
          TotalCapitulo := 0;
          EsCapitulo := True;
        end
        else begin
          Cell(iRowCount, 1).Range.Text := FieldByName('CODIGOARTICULO').AsString;
          Cell(iRowCount, 2).Range.Text := FieldByName('DESCRIPCION').AsString;
          Cell(iRowCount, 3).Range.Text := FieldByName('CANTIDAD').AsString + ' ' +
                                           FieldByName('UNIDADESMEDIDA').AsString; 
          Cell(iRowCount, 4).Range.Text := FieldByName('PRECIOUNIDAD').DisplayText;
          Cell(iRowCount, 5).Range.Text := FieldByName('TOTAL').DisplayText;
          TotalCapitulo := TotalCapitulo + FieldByName('TOTAL').AsFloat;
        end;
        TipoConAnterior := FieldByName('TIPO').AsString;
        Next;
        Inc (iRowCount);
    end;
    if EsCapitulo then
    begin
      Rows.Item (iRowCount).Cells.Split (numRows, numCols, mergesplit);
      Cell(iRowCount, 2).Range.Text := 'TOTAL DEL CAPÍTULO';
      Cell(iRowCount, 5).Range.Text := FormatFloat(DISPLAY_EUROS2, TotalCapitulo);
      TotalCapitulo := 0;
    end;
    Close;
  end;
  Result := True;
end;

end.
