{
===============================================================================
  Copyright (©) 2002. 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: 03-11-2002
  Versión actual: 1.0.1
  Fecha versión actual: 14-02-2003
===============================================================================
  Modificaciones:

    Fecha         Comentarios
    ---------------------------------------------------------------------------
    14-02-2003    Se ha añadido la propiedad 'RutaBD'.
===============================================================================
}

unit BaseDatos;

interface

uses
  SysUtils, Windows, Messages, Classes, Graphics, Controls, Forms,
  Dialogs, DBTables, DB, IBDatabase, IBCustomDataSet, IBTable, IBSQLMonitor,
  IBSQL, IB, IBServices,
  cxGridDBCardView, cxGrid, cxGridCustomTableView,
  cxGridTableView, cxGridDBTableView,
  Variants, RdxEmpresaActiva,
  Entidades, Contadores, RdxGestorContadores;

Const
////////////////////////////////////////////////////////////////////////////////
// COMUNES
////////////////////////////////////////////////////////////////////////////////
  CBD_CODIGO = 'CODIGO';
  tamColCodigo = 78;

  CBD_FECHAALTA = 'FECHAALTA';
  tamColFecha = 65;

  CBD_USUARIO = 'USUARIO';
  tamColUsuario = 200;

  CBD_NIFCIF = 'NIFCIF';
  tamColNIFCIF = 65;

  CBD_NOMBRE ='NOMBRE';
  tamColNombre = 200;
  tamColNombreCorto = 140;

  CBD_CALLE = 'CALLE';
  tamColCalle = 200;

  CBD_NUMERO = 'NUMERO';
  tamColNumero = 35;

  CBD_PISO = 'PISO';
  tamColPiso = 35;

  CBD_PROVINCIA = 'PROVINCIA';
  tamColProvincia = 85;

  CBD_POBLACION = 'POBLACION';
  tamColPoblacion = 95;

  CBD_CODIGOPOSTAL = 'CODIGOPOSTAL';
  tamColCodigoPostal = 45;

  CBD_TELEFONO1 = 'TELEFONO1';
  CBD_TELEFONO2 = 'TELEFONO2';
  CBD_MOVIL1 = 'MOVIL1';
  CBD_MOVIL2 = 'MOVIL2';
  CBD_FAX = 'FAX';
  tamColTelefono = 60;

  CBD_CORREO = 'CORREO';
  tamColCorreo = 100;

  CBD_WEB = 'WEB';
  tamColWeb = 100;

  CBD_PERSONACONTACTO = 'PERSONACONTACTO';
  tamColPersonaContacto = 200;

  CBD_OBSERVACIONES = 'OBSERVACIONES';
  tamColObservaciones = 200;

  CBD_SERIE = 'SERIE';
  tamColSerie = 25;

  CBD_FORMAPAGO = 'FORMAPAGO';
  tamColFormaPago = 70;

////////////////////////////////////////////////////////////////////////////////
// ARTICULOS
////////////////////////////////////////////////////////////////////////////////
  CBD_FAMILIA = 'FAMILIA';
  tamColFamilia = 65;
  tamColReferencia = 65;

////////////////////////////////////////////////////////////////////////////////
// PRESUPUESTOS
////////////////////////////////////////////////////////////////////////////////
  tamColDocumentos = 85;
////////////////////////////////////////////////////////////////////////////////
// FACTURAS
////////////////////////////////////////////////////////////////////////////////
  CBD_CANTIDAD = 'CANTIDAD';
  tamColCantidad = 35;

  CBD_DESCRIPCION = 'DESCRIPCION';
  tamColDescripcion = 350;

  CBD_IMPORTEUNIDAD = 'IMPORTEUNIDAD';
  CBD_IMPORTETOTAL = 'IMPORTETOTAL';
  tamColImporte = 65;
  tamColImporteLargo = 80;

  CBD_DESCUENTO = 'DESCUENTO';
  tamColDescuento = 35;
  tamColPorcentaje = 35;

  CBD_SITUACION = 'SITUACION';
  tamColSituacion = 65;

////////////////////////////////////////////////////////////////////////////////
// LIBROS
////////////////////////////////////////////////////////////////////////////////
  tamColFechaEntrada = 60;
  tamColTipoEntrada = 50;
  tamColNumEntrada = 60;


type

  TPTabla = ^TIBDataSet;

  TdmBaseDatos = class(TDataModule)
  private
    FBD : TIBDatabase;
    FTransaccionBD : TIBTransaction;
    FNombreBD : string;

    procedure IniciarTablasBackOffice;
    procedure IniciarTablas;

    function DarTransaccion: TIBTransaction;
    function DarUsuario : string;
    function GetRutaBD: String;
    function GetNombreServidor: String;
    function validarPrivilegios: Boolean;
  public
    procedure Commit;
    procedure Rollback;
    procedure Desconectar;
    procedure Conectar (RutaBD : String; Usuario : String; Clave : String); overload;
    procedure Conectar (RutaBD : String); overload;
    procedure Conectar; overload;
    constructor Create(AOwner : TComponent); override;
    destructor Destroy; override;
    function DarFecha : TDateTime;
    function DarHora : TTime;
    function DarAno : string;
    function DarMes : string;
    function DarSeriesFacturas : TStrings;
    function DarValorConfiguracion (Codigo : String):String;
    function DarSerieConfiguracion (VAR_CONFIG : String):String;

  published
    property BD : TIBDatabase read FBD;
    property Transaccion : TIBTransaction read FTransaccionBD;
    property Usuario : String read DarUsuario;
    property NombreBD : String read FNombreBD write FNombreBD;
    property RutaBD : String read GetRutaBD;
    property NombreServidor : String read GetNombreServidor;
  end;

  procedure ActivarEdicionGridDetalles(var vGrid: TcxGrid); overload;
  procedure ActivarEdicionGridDetalles(var vGrid: TcxGridDBTableView); overload;
  procedure DesactivarEdicionGridDetalles(var vGrid: TcxGrid); overload;
  procedure DesactivarEdicionGridDetalles(var Grid: TcxGridDBTableView); overload;

  procedure IntercambiarPropiedades(Tabla: TPTabla; NumIni, NumFin : Integer);
  procedure BorrarTabla(DataSet : TDataSet);

  procedure FiltrarGrid(var vGrid: TcxGrid; TextoFiltro : String);
var
  dmBaseDatos: TdmBaseDatos;

implementation

{$R *.DFM}

uses
  RxMemDS, Mensajes, Literales, Excepciones, IBQuery, IBBlob, StrUtils, StrFunc,
  cxFilter,
  //Empresas
  TablaEmpresas,
  //Datos
  TablaArticulos, TablaVendedores, TablaInstaladores, TablaFamilias, TablaProcedencias, TablaPropiedades,
  TablaFormasPago, TablaProvincias, TablaPoblaciones, TablaPropiedadesArticulo, TablaValores,
  //Proveedores
  TablaProveedores, TablaRepresentantesProveedor, TablaFacturasProveedor,
  TablaPagosProveedor,
  //Clientes
  TablaClientes, TablaSucursalesCliente, TablaPresupuestos, TablaContratos,
  TablaFacturasCliente, TablaPagosCliente, TablaFacturasProforma,
  TablaObras, TablaObrasPedidos, TablaObrasInstaladores, TablaObrasGastos, TablaTareas,
  TablaAlbaranesCliente,
  //Libros
  TablaLibros,
  // Trimestres
  TablaTrimestres,
  // Configuracion
  TablaDocumentos,
  Configuracion, TablaAgenda, TablaCitas;

constructor TdmBaseDatos.Create(AOwner: TComponent);
begin
  inherited;

  FBD := TIBDatabase.Create(Self);
  with FBD do
  begin
    SQLDialect := 3;
    LoginPrompt := False;
    TraceFlags := [tfQExecute, tfQFetch, tfStmt];
    Params.Add('lc_ctype=ISO8859_1');
  end;

  FTransaccionBD := TIBTransaction.Create(Self);
  with FTransaccionBD do
  begin
    DefaultAction := TARollbackRetaining;
    DefaultDatabase := FBD;
    Params.Add('read_committed');
    Params.Add('rec_version');
    Params.Add('nowait');
  end;
  FBD.DefaultTransaction := FTransaccionBD;
end;

destructor TdmBaseDatos.Destroy;
begin
  FBD.Close;
  FBD.DefaultTransaction := NIL;
  FBD.Free;
  FBD := NIL;

  FTransaccionBD.Free;
  FTransaccionBD := NIL;

  inherited;
end;

procedure TdmBaseDatos.IniciarTablas;
begin
  // Configuracion
  Application.CreateForm(TdmTablaDocumentos, dmTablaDocumentos);
  // Datos
  Application.CreateForm(TdmTablaFamilias, dmTablaFamilias);
  Application.CreateForm(TdmTablaProcedencias, dmTablaProcedencias);
  Application.CreateForm(TdmTablaPropiedades, dmTablaPropiedades);
  Application.CreateForm(TdmTablaValores, dmTablaValores);
  Application.CreateForm(TdmTablaPropiedadesArticulo, dmTablaPropiedadesArticulo);
  Application.CreateForm(TdmTablaArticulos, dmTablaArticulos);
  Application.CreateForm(TdmTablaFormasPago, dmTablaFormasPago);
  Application.CreateForm(TdmTablaVendedores, dmTablaVendedores);
  Application.CreateForm(TdmTablaInstaladores, dmTablaInstaladores);
  // Proveedores
  Application.CreateForm(TdmTablaProveedores, dmTablaProveedores);
  Application.CreateForm(TdmTablaRepresentantesProveedor, dmTablaRepresentantesProveedor);
  Application.CreateForm(TdmTablaFacturasProveedor, dmTablaFacturasProveedor);
  Application.CreateForm(TdmTablaPagosProveedor, dmTablaPagosProveedor);
  // Clientes
  Application.CreateForm(TdmTablaClientes, dmTablaClientes);
  Application.CreateForm(TdmTablaSucursalesCliente, dmTablaSucursalesCliente);
  Application.CreateForm(TdmTablaPresupuestos, dmTablaPresupuestos);
  Application.CreateForm(TdmTablaContratos, dmTablaContratos);
  Application.CreateForm(TdmTablaFacturasCliente, dmTablaFacturasCliente);
  Application.CreateForm(TdmTablaPagosCliente, dmTablaPagosCliente);
  Application.CreateForm(TdmTablaFacturasProforma, dmTablaFacturasProforma);
  Application.CreateForm(TdmTablaObras, dmTablaObras);
  Application.CreateForm(TdmTablaObrasPedidos, dmTablaObrasPedidos);
  Application.CreateForm(TdmTablaObrasInstaladores, dmTablaObrasInstaladores);
  Application.CreateForm(TdmTablaObrasGastos, dmTablaObrasGastos);
  Application.CreateForm(TdmTablaTareas, dmTablaTareas);
  Application.CreateForm(TdmTablaAlbaranesCliente, dmTablaAlbaranesCliente);  
  // Agenda
  Application.CreateForm(TdmTablaAgenda, dmTablaAgenda);
  Application.CreateForm(TdmTablaCitas, dmTablaCitas);  
end;

function TdmBaseDatos.DarTransaccion: TIBTransaction;
begin
  Result := FTransaccionBD;
end;

function TdmBaseDatos.DarAno : string;
var
  Ano, Mes, Dia : Word;
begin
  DecodeDate(darFecha, ano, mes, dia);
  Result := IntToStr(ano);
end;

function TdmBaseDatos.DarMes : string;
var
  Ano, Mes, Dia : Word;
begin
  DecodeDate(darFecha, ano, mes, dia);
  Result := IntToStr(mes);
end;

function TdmBaseDatos.DarUsuario: string;
begin
  Result := BD.Params.Values['user_name'];
end;

procedure ActivarEdicionGridDetalles(var vGrid: TcxGridDBTableView);
begin
  if vGrid = NIL then
    Exit;
  with (vGrid as TcxCustomGridTableView) do
  begin
    OptionsBehavior.FocusCellOnTab := True;
    OptionsBehavior.GoToNextCellOnEnter := True;
    OptionsBehavior.ImmediateEditor := True;
    OptionsBehavior.AlwaysShowEditor := False;

    OptionsSelection.CellSelect := True;
    OptionsSelection.InvertSelect := False;
    OptionsSelection.HideFocusRect := False;

    OptionsData.Appending := True;
    OptionsData.Inserting := True;
    OptionsData.Editing := True;
    { El borrado se debe controlar en cada pantalla para
      que no salga el mensaje en inglés. }
    OptionsData.Deleting := False;
    OptionsData.DeletingConfirmation := False;
  end
end;

procedure ActivarEdicionGridDetalles(var vGrid: TcxGrid);
begin
  if vGrid = NIL then
    Exit;
  with (vGrid.ActiveView as TcxCustomGridTableView) do
  begin
    OptionsBehavior.FocusCellOnTab := True;
    OptionsBehavior.GoToNextCellOnEnter := True;
    OptionsBehavior.ImmediateEditor := True;
    OptionsBehavior.AlwaysShowEditor := False;

    OptionsSelection.CellSelect := True;
    OptionsSelection.InvertSelect := False;
    OptionsSelection.HideFocusRect := False;

    OptionsData.Appending := True;
    OptionsData.Inserting := True;
    OptionsData.Editing := True;
    { El borrado se debe controlar en cada pantalla para
      que no salga el mensaje en inglés. }
    OptionsData.Deleting := False;
    OptionsData.DeletingConfirmation := False;
  end
end;

procedure DesactivarEdicionGridDetalles(var Grid: TcxGridDBTableView);
begin
  if Grid = NIL then
    Exit;
  with (Grid as TcxCustomGridTableView) do
  begin
    OptionsBehavior.FocusCellOnTab := True;
    OptionsBehavior.GoToNextCellOnEnter := True;
    OptionsBehavior.ImmediateEditor := False;
    OptionsBehavior.AlwaysShowEditor := False;

    OptionsSelection.CellSelect := False;
    OptionsSelection.InvertSelect := False;
    OptionsSelection.HideFocusRect := True;

    OptionsData.Appending := False;
    OptionsData.Deleting := False;
    OptionsData.DeletingConfirmation := False;
    OptionsData.Editing := False;
    OptionsData.Inserting := False;
  end
end;

procedure DesactivarEdicionGridDetalles(var vGrid: TcxGrid); overload;
begin
  if vGrid = NIL then
    Exit;
  with (vGrid.ActiveView as TcxCustomGridTableView) do
  begin
    OptionsBehavior.FocusCellOnTab := True;
    OptionsBehavior.GoToNextCellOnEnter := True;
    OptionsBehavior.ImmediateEditor := False;
    OptionsBehavior.AlwaysShowEditor := False;

    OptionsSelection.CellSelect := False;
    OptionsSelection.InvertSelect := False;
    OptionsSelection.HideFocusRect := True;

    OptionsData.Appending := False;
    OptionsData.Deleting := False;
    OptionsData.DeletingConfirmation := False;
    OptionsData.Editing := False;
    OptionsData.Inserting := False;
  end
end;

procedure TdmBaseDatos.Commit;
begin
  if FTransaccionBD = NIL then
    Exit;
  if FTransaccionBD.InTransaction then
    FTransaccionBD.CommitRetaining;
end;

procedure TdmBaseDatos.Rollback;
begin
  if FTransaccionBD = NIL then
    exit;
  if FTransaccionBD.InTransaction then
    FTransaccionBD.RollbackRetaining;
end;

function TdmBaseDatos.DarSeriesFacturas: TStrings;
var
  oSQL : TIBSQL;
  Lista : TStringList;
begin
  Result := NIL;
  oSQL := TIBSQL.Create(Self);
  Lista := TStringList.Create;
  with oSQL do
  begin
    Database := dmBaseDatos.BD;
    Transaction := dmBaseDatos.Transaccion;
    SQL.Add('select DESCRIPCION from SERIES');
    try
      Prepare;
      ExecQuery;
      while not EOF do begin
        Lista.Append(Fields[0].AsString);
        Next;
      end;
      Result := Lista;
    finally
      Close;
      Transaction := NIL;
      Free;
    end;
  end;
end;

function TdmBaseDatos.DarFecha: TDateTime;
var
  oSQL : TIBSQL;
  Fecha : TDateTime;
begin
  Result := Date;
  oSQL := TIBSQL.Create(Self);
  with oSQL do
  begin
    Database := BD;
    Transaction := DarTransaccion;
    SQL.Add('select CURRENT_DATE from RDB$DATABASE');
    try
      Prepare;
      ExecQuery;
      Fecha := Fields[0].AsDateTime;
      Result := Fecha;
    finally
      Close;
      Transaction := NIL;
      Free;
    end;
  end;
end;

procedure TdmBaseDatos.Conectar(RutaBD, Usuario, Clave: String);
begin
  with BD do
  begin
    DatabaseName := RutaBD;
    Params.Clear;
    Params.Add('user_name=' + LowerCase(Usuario));
    Params.Add('password=' + LowerCase(Clave));
    Params.Add('lc_ctype=ISO8859_1');
    Params.Add('sql_role_name=usuarios');
    try
      Screen.Cursor := crHourGlass;
      Connected := True;
      FTransaccionBD.StartTransaction;
      if (ValidarPrivilegios) then
      begin
        GestorContadores.BD := FBD;
        GestorContadores.Transaccion := FTransaccionBD;

        //Asignamos empresa como variable de entorno
        IniciarTablasBackOffice;
        IniciarTablas;
      end
      else
      begin
        Rollback;
        Connected := False;
        raise EIBError.Create(msgUsuarioInc);
      end;
    finally
      Screen.Cursor := crDefault;
    end;
  end;
end;

function TdmBaseDatos.GetRutaBD: String;
begin
  Result := Copy(BD.DatabaseName, Pos(':', BD.DatabaseName) + 1, MaxInt);
end;

function TdmBaseDatos.GetNombreServidor: String;
begin
  Result := LeftStr(BD.DatabaseName, Pos(':', BD.DatabaseName) - 1);
end;

procedure TdmBaseDatos.Desconectar;
begin
  with BD do
  begin
    try
      Screen.Cursor := crHourGlass;
      Connected := False;
    finally
      Screen.Cursor := crDefault;
    end;
  end;
end;

procedure TdmBaseDatos.Conectar;
begin
  with BD do
  begin
    try
      Screen.Cursor := crHourGlass;
      Connected := True;
      FTransaccionBD.StartTransaction;
    finally
      Screen.Cursor := crDefault;
    end;
  end;
end;

procedure TdmBaseDatos.Conectar(RutaBD: String);
begin
  with BD do
  begin
    DatabaseName := RutaBD;
    Params.Clear;
    Params.Add('user_name=' + LowerCase('FACTUGES'));
    Params.Add('password=' + LowerCase('FACTUGES'));
    Params.Add('lc_ctype=ISO8859_1');
    Params.Add('sql_role_name=usuarios');
    try
      Screen.Cursor := crHourGlass;
      Connected := True;
      FTransaccionBD.StartTransaction;

      IniciarTablasBackOffice;
      IniciarTablas;
    finally
      Screen.Cursor := crDefault;
    end;
  end;
end;

function TdmBaseDatos.validarPrivilegios: Boolean;
begin
//Por si en un futuro se desea establecer una politica de privilegios de usuario
//para cada EmpresaActiva.
  Result := True;
end;

procedure TdmBaseDatos.IniciarTablasBackOffice;
begin
  Application.CreateForm(TdmTablaProvincias, dmTablaProvincias);
  Application.CreateForm(TdmTablaPoblaciones, dmTablaPoblaciones);

  // Empresas
  Application.CreateForm(TdmTablaEmpresas, dmTablaEmpresas);
  // Trimestres
  Application.CreateForm(TdmTablaTrimestres, dmTablaTrimestres);
  // Libros
  Application.CreateForm(TdmTablaLibros, dmTablaLibros);
end;

procedure IntercambiarPropiedades(Tabla: TPTabla; NumIni, NumFin : Integer);
begin
  with Tabla^ do
  begin
    try
      DisableControls;
      First;
      if Locate('NUMPROPIEDAD', NumIni, []) then
      begin
        Edit;
        FieldByName('NUMPROPIEDAD').AsInteger := -1;
        Post;

        First;
        Locate('NUMPROPIEDAD', NumFin, []);
        Edit;
        FieldByName('NUMPROPIEDAD').AsInteger := NumIni;
        Post;

        First;
        Locate('NUMPROPIEDAD', -1, []);
        Edit;
        FieldByName('NUMPROPIEDAD').AsInteger := NumFin;
        Post;
      end;
    finally
      Locate('NUMPROPIEDAD', NumFin, []);
      EnableControls;
    end;
  end;
end;

procedure BorrarTabla(DataSet : TDataSet);
begin
  with DataSet do
  begin
    if not Active then
      raise EDatabaseError.Create('La tabla está cerrada.');
    if IsEmpty then
      Exit;
    DisableControls;
    try
      if DataSet is TRxMemoryData then
        (DataSet as TRxMemoryData).EmptyTable
      else begin
        Last;
        while not BOF do
        begin
          Delete;
          Prior;
        end;
        if not IsEmpty then
          Delete;
      end;
    finally
      EnableControls;
    end;
  end;
end;


function TdmBaseDatos.DarHora: TTime;
var
  oSQL : TIBSQL;
begin
  Result := Time;
  oSQL := TIBSQL.Create(Self);
  with oSQL do
  begin
    Database := BD;
    Transaction := DarTransaccion;
    SQL.Add('select CURRENT_TIME from RDB$DATABASE');
    try
      Prepare;
      ExecQuery;
      Result := Fields[0].AsTime;
    finally
      Close;
      Transaction := NIL;
      Free;
    end;
  end;
end;

procedure FiltrarGrid(var vGrid: TcxGrid; TextoFiltro : String);
var
  Columna : TcxGridDBColumn;
  Texto : String;
  i : Integer;
  AItemList: TcxFilterCriteriaItemList;
  AItemList2 : TcxFilterCriteriaItemList;
begin
  with vGrid.ActiveView.DataController.Filter do
  begin
    BeginUpdate;
    try
      Options := [fcoCaseInsensitive, fcoSoftCompare];
      Root.Clear;
      if Length(TextoFiltro) > 0 then
      begin
        for i:=0 to (vGrid.ActiveView as TcxGridDBTableView).ColumnCount - 1 do
        begin
          Columna := (vGrid.ActiveView as TcxGridDBTableView).Columns[i];
          if i = 0 then
          begin
            Root.BoolOperatorKind := fboOr;
            Root.AddItem(Columna, foLike, '%'+TextoFiltro+'%', IntToStr(i));
            AItemList := Root;
          end
          else begin
            AItemList2 := AItemList.AddItemList(fboOr);
            AItemList2.AddItem(Columna, foLike, '%'+TextoFiltro+'%', IntToStr(i));
            AItemList := AItemList2;
          end;
        end;
        Active := True;
      end
      else
        Active := False;
    finally
      EndUpdate;
    end;
  end;
end;

function TdmBaseDatos.DarValorConfiguracion(Codigo: String): String;
var
  oSQL : TIBSQL;
begin
  Result := '';
  oSQL := TIBSQL.Create(Self);
  with oSQL do
  begin
    Database := dmBaseDatos.BD;
    Transaction := dmBaseDatos.Transaccion;
    SQL.Add('select VALOR from CONFIGURACION ');
    SQL.Add('where upper(CODIGO) = upper(:CODIGO) ');
    ParamByName('CODIGO').AsString := Codigo;
    try
      Prepare;
      ExecQuery;
      if not EOF then
        Result := Fields[0].AsString;
    finally
      Close;
      Transaction := NIL;
      Free;
    end;
  end;
end;

function TdmBaseDatos.DarSerieConfiguracion(VAR_CONFIG: String): String;
var
  oSQL : TIBSQL;
begin
  Result := '';
  oSQL := TIBSQL.Create(Self);
  with oSQL do
  begin
    Database := dmBaseDatos.BD;
    Transaction := dmBaseDatos.Transaccion;
    SQL.Add('SELECT ' + VAR_CONFIG);
    SQL.Add('FROM EMPRESAS ');
    SQL.Add('WHERE CODIGO = :CODIGOEMPRESA');
    ParamByName('CODIGOEMPRESA').AsInteger := EmpresaActiva.Codigo;
    try
      Prepare;
      ExecQuery;
      if not EOF then
        Result := Fields[0].AsString;
    finally
      Close;
      Transaction := NIL;
      Free;
    end;
  end;
end;

end.

