{
===============================================================================
  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: 08-10-2004
===============================================================================
  Modificaciones:

    Fecha         Comentarios
    ---------------------------------------------------------------------------
    03-10-2001    Cambio de la mascara de formato de los euros a 4.

    18-01-2002    Ordenar por descripción el grid de materiales.

    25-01-2002    Cambio en 'DarNuevoCodigo': Se saca el siguiente
                  codigo mayor disponible.
                  Cambio en 'IncrementarCodigo': Se saca el siguiente
                  codigo mayor disponible y se le añade 1.

    02-03-2002    Se ha añadido la funcion 'DarListaArticulos' para devolver
                  una lista de codigos de material a partir de un bookmark
                  de filas seleccionadas de la tabla de articulos.

    07-04-2002    Cambio de todos los procedimientos en los que se utiliza
                  una transaccion nueva, por una unica transacción.

    09-05-2002    Cambio de grid en lugar de utilizar UltimDBGrid,
                  utilizaremos dxDBGrid.

    27-05-2002    Cambio a un objeto contador (TContadorCliente)

    16-11-2002    p250. Poner el número total de artículos dados de alta
                  en la inicialización del grid.

    06-03-2004    P272. Adaptación a multiempresa.

    08-10-2004    P289. Cambios varios, tener en cuenta los fabricantes y proveedores
                  para cada uno de los artículos.
===============================================================================
}

unit TablaArticulos;

interface

uses
  SysUtils, Windows, Messages, Classes, Graphics, Controls, Forms,
  Dialogs, DBTables, DB, IBCustomDataSet, IBSQL, BaseDatos, IBDatabase,
  dxDBGrid, dxDBCtrl, dbgrids, StrFunc, Mensajes, IB;

type
  TDatosArticulo = class(TPersistent)
  public
    Codigo : String;
    Familia : String;
    Descripcion : String;
    Unidadesmedida : String;
    Precio : String;
    Observaciones : String;
    Existencias : String;
    StockMin : String;
    StockMax : String;
    FechaRecepcion : String;
    PrecioRecepcion : String;
    CodigoAlmacen : Variant;
//Datos proveedor
    CodigoFabricante : String;
    CodigoProveedor : String;
    CodArtFabricante : String;
    CodArtProveedor : String;
    FechaPrecioPro : String;
    PrecioPro : String;
    DtoPro : String;
    PrecioFinal : String;
  end;

  TDatosArticuloAlmacen = class(TPersistent)
  public
    Codigo : String;
    Unidadesmedida : String;
    Precio : String;
    TipoOperacion : String;
    TipoMovimiento : String;
    Causa : String;
    Existencias : String;
    StockMin : String;
    StockMax : String;
    CodigoAlmacen : Variant;
    NombreCliente : String;
    FechaRecepcion : String;
    PrecioRecepcion : String;
  end;

  TdmTablaArticulos = class(TDataModule)
  private
    procedure IniciarSQL;
  public
    sqlInsertar : TStrings;
    sqlModificar : TStrings;
    sqlConsultar : TStrings;
    sqlEliminar : TStrings;
    sqlGrid : TStrings;

    sqlInsertarArtFabPro : TStrings;
    sqlModificarArtFabPro : TStrings;
    sqlConsultarArtFabPro : TStrings;
    sqlEliminarArtFabPro : TStrings;
    sqlGridArtFabPro : TStrings;

    constructor Create (AOwner : TComponent); override;
    destructor Destroy; override;

    //Metodos que llamaran a contador
    function DarNuevoCodigo : String;
    function IncrementarCodigo: boolean;
    function InsertarContador: boolean;
    function ValidarCodigo(Codigo : String) : Boolean;
    function FormatearCodigo(Codigo : String) : String;

    function ExisteArticulo(CodigoArticulo : String) : Boolean;
    function DarDatosArticulo(var Datos: TDatosArticulo): Boolean;
    function DarDatosArticuloPro(var Datos: TDatosArticulo): Boolean;
    function DarListaArticulos(Grid : TdxDBGrid; Tabla: TPTabla) : TStringList;

    function DarArticuloMin : String;
    function DarArticuloMax : String;

    procedure InicializarTablaArticulos(Tabla : TPTabla);
    procedure InicializarGridArticulos(var Grid: TdxDBGrid);

    procedure InicializarGridArticulosFabPro(var Grid: TdxDBGrid);
    procedure InicializarGridArticulosFabProDetalles(var Grid: TdxDBGrid);
    procedure InicializarTablaArticulosFabPro(Tabla : TPTabla);
  end;

var
  dmTablaArticulos: TdmTablaArticulos;

implementation
{$R *.DFM}

uses
    dxDBTLCL, Excepciones, Constantes, RdxGestorContadores, Contadores;

constructor TdmTablaArticulos.Create (AOwner : TComponent);
begin
  inherited;
  sqlInsertar := TStringList.Create;
  sqlModificar := TStringList.Create;
  sqlConsultar := TStringList.Create;
  sqlEliminar := TStringList.Create;
  sqlGrid := TStringList.Create;

  sqlInsertarArtFabPro := TStringList.Create;
  sqlModificarArtFabPro := TStringList.Create;
  sqlConsultarArtFabPro := TStringList.Create;
  sqlEliminarArtFabPro := TStringList.Create;
  sqlGridArtFabPro := TStringList.Create;

  IniciarSQL;
end;

destructor TdmTablaArticulos.Destroy;
begin
  sqlInsertar.Free;
  sqlModificar.Free;
  sqlConsultar.Free;
  sqlEliminar.Free;
  sqlGrid.Free;

  sqlInsertarArtFabPro.Free;
  sqlModificarArtFabPro.Free;
  sqlConsultarArtFabPro.Free;
  sqlEliminarArtFabPro.Free;
  sqlGridArtFabPro.Free;

  inherited;
end;

procedure TdmTablaArticulos.IniciarSQL;
begin
  with sqlInsertar do
  begin
    Add('insert into ARTICULOS ');
    Add('(CODIGO, FAMILIA, DESCRIPCION, UNIDADESMEDIDA, ');
    Add('PRECIO, OBSERVACIONES) ');
    Add('values (:CODIGO, :FAMILIA, :DESCRIPCION, :UNIDADESMEDIDA, ');
    Add(':PRECIO, :OBSERVACIONES)');
  end;

  with sqlModificar do
  begin
    Add('update ARTICULOS set ');
    Add('FAMILIA = :FAMILIA, ');
    Add('DESCRIPCION = :DESCRIPCION, ');
    Add('UNIDADESMEDIDA = :UNIDADESMEDIDA, ');
    Add('PRECIO = :PRECIO, ');
    Add('OBSERVACIONES = :OBSERVACIONES ');
    Add('where CODIGO = :CODIGO');
  end;

  with sqlEliminar do
  begin
    Add('delete from ARTICULOS ');
    Add('where CODIGO = :CODIGO');
  end;

  with sqlConsultar do
  begin
    Add('select * from ARTICULOS ');
    Add('where CODIGO = :CODIGO');
  end;

  with sqlGrid do
  begin
    Add('select CODIGO, FAMILIA, DESCRIPCION, UNIDADESMEDIDA, PRECIO ');
    Add('from ARTICULOS ');
    Add('order by DESCRIPCION');
  end;

  with sqlInsertarArtFabPro do
  begin
    Add('insert into ARTICULOSFABPRO ');
    Add('(CODIGOARTICULO, CODIGOFABRICANTE, CODIGOPROVEEDOR, ');
    Add('CODARTFABRICANTE, CODARTPROVEEDOR, FECHAPRECIO, PRECIO, DESCUENTO, PRECIOFINAL) ');
    Add('values (:CODIGOARTICULO, :CODIGOFABRICANTE, :CODIGOPROVEEDOR, ');
    Add(':CODARTFABRICANTE, :CODARTPROVEEDOR, :FECHAPRECIO, :PRECIO, :DESCUENTO, :PRECIOFINAL) ');
  end;

  with sqlConsultarArtFabPro do
  begin
    Add('select CODIGOARTICULO, CODIGOFABRICANTE, FABRICANTE, CODARTFABRICANTE,');
    Add('CODIGOPROVEEDOR, PROVEEDOR, CODARTPROVEEDOR, FECHAPRECIO, PRECIO, DESCUENTO, PRECIOFINAL');
    Add('from V_ARTICULOSFABPRO');
    Add('where CODIGOARTICULO = :CODIGOARTICULO');
    Add('order by CODIGOFABRICANTE');
  end;

  with sqlModificarArtFabPro do
  begin
    Add('update ARTICULOSFABPRO');
    Add('set FECHAPRECIO = :FECHAPRECIO,');
    Add('PRECIO = :PRECIO,');
    Add('DESCUENTO = :DESCUENTO,');
    Add('PRECIOFINAL = :PRECIOFINAL');
    Add('where CODIGOARTICULO = :CODIGOARTICULO');
    Add('and CODIGOFABRICANTE = :CODIGOFABRICANTE');
    Add('and CODIGOPROVEEDOR = :CODIGOPROVEEDOR');
  end;

  with sqlEliminarArtFabPro do
  begin
    Add('Delete from ARTICULOSFABPRO');
    Add('where CODIGOARTICULO = :CODIGOARTICULO');
    Add('and CODIGOFABRICANTE = :CODIGOFABRICANTE');
    Add('and CODIGOPROVEEDOR = :CODIGOPROVEEDOR');
  end;

  with sqlGridArtFabPro do
  begin
    Add('select ART.CODIGO, ART.FAMILIA, ART.DESCRIPCION, ART.UNIDADESMEDIDA, AFP.FABRICANTE, AFP.CODARTFABRICANTE,');
    Add('AFP.PROVEEDOR, AFP.CODARTPROVEEDOR, AFP.FECHAPRECIO, AFP.PRECIO, AFP.DESCUENTO, AFP.PRECIOFINAL');
    Add('from ARTICULOS ART right join V_ARTICULOSFABPRO AFP');
    Add('on ART.CODIGO = AFP.CODIGOARTICULO');
    Add('order by ART.DESCRIPCION');
  end;

end;

function TdmTablaArticulos.darNuevoCodigo : String;
begin
  Result := GestorContadores.DarNuevoCodigo(contArticulos);
end;

function TdmTablaArticulos.IncrementarCodigo: boolean;
begin
  Result := GestorContadores.IncrementarValor(contArticulos);
end;

function TdmTablaArticulos.validarCodigo(Codigo : String) : Boolean;
begin
  Result := GestorContadores.ValidarCodigo(contArticulos, Codigo);
end;

function TdmTablaArticulos.formatearCodigo(Codigo : String) : String;
begin
  Result := GestorContadores.FormatearCodigo(contArticulos, Codigo);
end;

function TdmTablaArticulos.insertarContador: boolean;
begin
  Result := GestorContadores.InsertarContador(contArticulos);
end;

function TdmTablaArticulos.existeArticulo(CodigoArticulo: String): Boolean;
var
  oSQL : TIBSQL;
  Codigo : String;
begin
  Result := False;

  if Length(Trim(CodigoArticulo)) = 0 then
    Exit;

  oSQL := TIBSQL.Create(Self);
  with oSQL do
  begin
    Database := dmBaseDatos.BD;
    Transaction := dmBaseDatos.Transaccion;
    SQL.Add('select CODIGO ');
    SQL.Add('from ARTICULOS ');
    SQL.Add('where CODIGO = :CODIGO ');

  try
    ParamByName('CODIGO').AsString := CodigoArticulo;
    Prepare;
    ExecQuery;

    Codigo := FieldByName('CODIGO').AsString;
    Result := (CodigoArticulo = Codigo);
  finally
    Close;
    Transaction := NIL;
    Free;
  end;
  end;
end;

function TdmTablaArticulos.DarDatosArticulo(var Datos: TDatosArticulo): Boolean;
var
  oSQL : TIBSQL;
begin
  Result := False;

  if EsCadenaVacia(Datos.Codigo) then
    Exit;

  oSQL := TIBSQL.Create(Self);
  with oSQL do
  begin
    Database := dmBaseDatos.BD;
    Transaction := dmBaseDatos.Transaccion;
    SQL.Add('select * from ARTICULOS ');
    SQL.Add('where CODIGO = :CODIGO');

  try
    ParamByName('CODIGO').AsString := Datos.Codigo;
    Prepare;
    ExecQuery;

    if (RecordCount > 0) then
    begin
      with Datos do
      begin
        Familia := FieldByName('FAMILIA').AsString;
        Descripcion := FieldByName('DESCRIPCION').AsString;
        Unidadesmedida := FieldByName('UNIDADESMEDIDA').AsString;
        Precio := FieldByName('PRECIO').AsString;
        Observaciones := FieldByName('OBSERVACIONES').AsString;
        //Inicializamos el resto de campos
        Existencias := '0';
        StockMin := '0';
        StockMax := '1000';
        Result := True;
      end;
    end;
  finally
    Close;
    Transaction := NIL;
    Free;
  end;
  end;
end;

procedure TdmTablaArticulos.InicializarGridArticulos(var Grid: TdxDBGrid);
var
  Columna : TdxDBTreeListColumn;
begin
  with Grid do begin
    DestroyColumns;
    ShowSummaryFooter := True;
    {Columna CODIGO}
    Columna := CreateColumn(TdxDBTreeListColumn);
    Columna.FieldName := 'CODIGO';
    Columna.Caption := 'Código';
    Columna.Width := tamColCodigo;
    Columna.SummaryFooterType := cstCount;
    Columna.SummaryFooterFormat := 'Total: 0 artículos';
    {Columna FAMILIA}
    Columna := CreateColumn(TdxDBTreeListColumn);
    Columna.FieldName := 'FAMILIA';
    Columna.Caption := 'Familia';
    Columna.Width := tamColFamilias;
    Columna.Visible := False;
    {Columna DESCRIPCION}
    Columna := CreateColumn(TdxDBTreeListColumn);
    Columna.FieldName := 'DESCRIPCION';
    Columna.Caption := 'Descripción';
    Columna.Width := tamColDescripcion;
    {Columna UNIDADESMEDIDA}
    Columna := CreateColumn(TdxDBTreeListColumn);
    Columna.FieldName := 'UNIDADESMEDIDA';
    Columna.Caption := 'Unid. medida';
    Columna.Width := tamColUnidadesMedida;
    {Columna PRECIO}
    Columna := CreateColumn(TdxDBTreeListColumn);
    Columna.FieldName := 'PRECIO';
    Columna.Caption := 'Precio unidad';
    Columna.Width := tamColPrecio;
  end;
end;

procedure TdmTablaArticulos.InicializarTablaArticulos(Tabla : TPTabla);
begin
  with Tabla^.Fields do
  begin
    with (FieldByName('PRECIO') as TFloatField) do begin
      DisplayFormat := DISPLAY_EUROS2;
      EditFormat := EDIT_EUROS2;
    end;
  end;
end;

function TdmTablaArticulos.DarListaArticulos(Grid : TdxDBGrid; Tabla: TPTabla): TStringList;
var
  i: integer;
  ListaArticulos : TStringList;
begin
  ListaArticulos := Nil;

  if Grid.SelectedCount = 0 then
  begin
    Result := ListaArticulos;
    exit
  end;

  ListaArticulos := TStringList.Create;
  Tabla^.DisableControls;
  for i:=0 to Grid.SelectedCount-1 do
  begin
    Tabla^.GotoBookmark(Pointer(Grid.SelectedRows[i]));
    ListaArticulos.Add(Tabla^.FieldByName('CODIGO').AsString);
  end;
  Tabla^.EnableControls;
  Result := ListaArticulos;
end;

function TdmTablaArticulos.DarArticuloMax: String;
var
  oSQL : TIBSQL;
begin
  Result := '';

  oSQL := TIBSQL.Create(Self);
  with oSQL do
  begin
    Database := dmBaseDatos.BD;
    Transaction := dmBaseDatos.Transaccion;
    SQL.Add('select max(DESCRIPCION) from ARTICULOS ');
    try
      Prepare;
      ExecQuery;
      Result := Fields[0].AsString;
    finally
      Close;
      Transaction := NIL;
      Free;
    end;
  end;
end;


function TdmTablaArticulos.DarArticuloMin: String;
var
  oSQL : TIBSQL;
begin
  Result := '';

  oSQL := TIBSQL.Create(Self);
  with oSQL do
  begin
    Database := dmBaseDatos.BD;
    Transaction := dmBaseDatos.Transaccion;
    SQL.Add('select min(DESCRIPCION) from ARTICULOS ');
    try
      Prepare;
      ExecQuery;
      Result := Fields[0].AsString;
    finally
      Close;
      Transaction := NIL;
      Free;
    end;
  end;
end;

procedure TdmTablaArticulos.InicializarGridArticulosFabPro(
  var Grid: TdxDBGrid);
var
  Columna : TdxDBTreeListColumn;
begin
  with Grid do begin
    DestroyColumns;
    ShowSummaryFooter := True;
    {Columna CODIGO}
    Columna := CreateColumn(TdxDBTreeListColumn);
    Columna.FieldName := 'CODIGO';
    Columna.Caption := 'Código';
    Columna.Width := tamColCodigo4;
    Columna.SummaryFooterType := cstCount;
    Columna.SummaryFooterFormat := 'Total: 0 artículos';
    {Columna FAMILIA}
    Columna := CreateColumn(TdxDBTreeListColumn);
    Columna.FieldName := 'FAMILIA';
    Columna.Caption := 'Familia';
    Columna.Width := tamColFamilias;
    Columna.Visible := False;
    {Columna PROVEEDOR}
    Columna := CreateColumn(TdxDBTreeListColumn);
    Columna.FieldName := 'PROVEEDOR';
    Columna.Caption := 'Proveedor';
    Columna.Width := tamColProveedor2;
    {Columna CODARTPROVEEDOR}
    Columna := CreateColumn(TdxDBTreeListColumn);
    Columna.FieldName := 'CODARTPROVEEDOR';
    Columna.Caption := 'Cod.Proveedor';
    Columna.Width := tamColCodProveedor;
    {Columna DESCRIPCION}
    Columna := CreateColumn(TdxDBTreeListColumn);
    Columna.FieldName := 'DESCRIPCION';
    Columna.Caption := 'Descripción';
    Columna.Width := tamColDescripcion2;
    {Columna UNIDADESMEDIDA}
    Columna := CreateColumn(TdxDBTreeListColumn);
    Columna.FieldName := 'UNIDADESMEDIDA';
    Columna.Caption := 'Unid. medida';
    Columna.Width := tamColUnidadesMedida2;
    {Columna FABRICANTE}
    Columna := CreateColumn(TdxDBTreeListColumn);
    Columna.FieldName := 'FABRICANTE';
    Columna.Caption := 'Fabricante';
    Columna.Width := tamColFabricante;
    {Columna CODARTFABRICANTE}
    Columna := CreateColumn(TdxDBTreeListColumn);
    Columna.FieldName := 'CODARTFABRICANTE';
    Columna.Caption := 'Cod. Fabricante';
    Columna.Width := tamColCodFabricante;
    {Columna FECHAPRECIO}
    Columna := CreateColumn(TdxDBTreeListColumn);
    Columna.FieldName := 'FECHAPRECIO';
    Columna.Caption := 'Fecha precio';
    Columna.Width := tamColFecha;
    {Columna PRECIO}
    Columna := CreateColumn(TdxDBTreeListColumn);
    Columna.FieldName := 'PRECIO';
    Columna.Caption := 'Precio';
    Columna.Width := tamColPrecio6;
    {Columna DESCUENTO}
    Columna := CreateColumn(TdxDBTreeListColumn);
    Columna.FieldName := 'DESCUENTO';
    Columna.Caption := 'Dto.';
    Columna.Width := tamColPorcentaje;
    {Columna PRECIOFINAL}
    Columna := CreateColumn(TdxDBTreeListColumn);
    Columna.FieldName := 'PRECIOFINAL';
    Columna.Caption := 'Precio final';
    Columna.Width := tamColPrecio6;
  end;
end;

procedure TdmTablaArticulos.InicializarTablaArticulosFabPro(
  Tabla: TPTabla);
begin
  with Tabla^.Fields do
  begin
    with (FieldByName('PRECIO') as TFloatField) do begin
      DisplayFormat := DISPLAY_EUROS2;
      EditFormat := EDIT_EUROS2;
    end;
    with (FieldByName('DESCUENTO') as TFloatField) do begin
      DisplayFormat := DISPLAY_DTO;
      EditFormat := DISPLAY_DTO;
    end;
    with (FieldByName('PRECIOFINAL') as TNumericField) do begin
      DisplayFormat := DISPLAY_EUROS2;
      EditFormat := EDIT_EUROS2;
    end;
  end;
end;

procedure TdmTablaArticulos.InicializarGridArticulosFabProDetalles(
  var Grid: TdxDBGrid);
var
  Columna : TdxDBTreeListColumn;
  
begin
  with Grid do begin
    DestroyColumns;
    {Columna CODIGOARTICULO}
    Columna := CreateColumn(TdxDBTreeListColumn);
    Columna.FieldName := 'CODIGOARTICULO';
    Columna.Caption := 'Cod.Artículo';
    Columna.Width := tamColCodigo;
    Columna.Visible := False;
    {Columna FABRICANTE}
    Columna := CreateColumn(TdxDBTreeListColumn);
    Columna.FieldName := 'FABRICANTE';
    Columna.Caption := 'Fabricante';
    Columna.Width := tamColFabricante;
    Columna.DisableEditor := True;    
    {Columna CODARTFABRICANTE}
    Columna := CreateColumn(TdxDBTreeListColumn);
    Columna.FieldName := 'CODARTFABRICANTE';
    Columna.Caption := 'Cod. Fabricante';
    Columna.Width := tamColCodigo;
    {Columna PROVEEDOR}
    Columna := CreateColumn(TdxDBTreeListColumn);
    Columna.FieldName := 'PROVEEDOR';
    Columna.Caption := 'Proveedor';
    Columna.Width := tamColNombreProveedor;
    Columna.DisableEditor := True;
    {Columna CODARTPROVEEDOR}
    Columna := CreateColumn(TdxDBTreeListColumn);
    Columna.FieldName := 'CODARTPROVEEDOR';
    Columna.Caption := 'Cod.Proveedor';
    Columna.Width := tamColCodigo;
    {Columna FECHAPRECIO}
    Columna := CreateColumn(TdxDBTreeListDateColumn);
    Columna.FieldName := 'FECHAPRECIO';
    Columna.Caption := 'Fecha';
    Columna.Width := tamColFecha;
    {Columna PRECIO}
    Columna := CreateColumn(TdxDBTreeListColumn);
    Columna.FieldName := 'PRECIO';
    Columna.Caption := 'Precio';
    Columna.Width := tamColPrecio;
    {Columna DESCUENTO}
    Columna := CreateColumn(TdxDBTreeListColumn);
    Columna.FieldName := 'DESCUENTO';
    Columna.Caption := 'Dto.';
    Columna.Width := tamColPorcentaje3;
    {Columna PRECIOFINAL}
    Columna := CreateColumn(TdxDBTreeListColumn);
    Columna.FieldName := 'PRECIOFINAL';
    Columna.Caption := 'Precio final';
    Columna.Width := tamColPrecio;
    Columna.DisableEditor := True;
  end;
end;

function TdmTablaArticulos.DarDatosArticuloPro(
  var Datos: TDatosArticulo): Boolean;
var
  oSQL : TIBSQL;
begin
  Result := False;

  if EsCadenaVacia(Datos.Codigo) then
    Exit;

  oSQL := TIBSQL.Create(Self);
  with oSQL do
  begin
    Database := dmBaseDatos.BD;
    Transaction := dmBaseDatos.Transaccion;
    SQL.Add('select * from ARTICULOS ');
    SQL.Add('where CODIGO = :CODIGO');

  try
    ParamByName('CODIGO').AsString := Datos.Codigo;
    Prepare;
    ExecQuery;

    if (RecordCount > 0) then
    begin
      with Datos do
      begin
        Familia := FieldByName('FAMILIA').AsString;
        Descripcion := FieldByName('DESCRIPCION').AsString;
        Unidadesmedida := FieldByName('UNIDADESMEDIDA').AsString;
        Precio := FieldByName('PRECIO').AsString;
        Observaciones := FieldByName('OBSERVACIONES').AsString;
        //Inicializamos el resto de campos
        Existencias := '0';
        StockMin := '0';
        StockMax := '1000';
        Result := True;
      end;
    end;
  finally
    Close;
    Transaction := NIL;
    Free;
  end;
  end;
end;

end.
