unit uRemesasClienteController;

interface


uses
  Classes, SysUtils, uDADataTable, uControllerBase, uEditorDBItem,
  uIDataModuleRemesasCliente, uBizRemesasCliente, uProveedoresController,
  uBizContactos, uRecibosClienteController;

type
  IRemesasClienteController = interface(IControllerBase)
  ['{F5D925C6-255C-4374-9A71-DFC0FBB7FA96}']
    function Buscar(const ID: Integer): IBizRemesaCliente;
    function BuscarTodos: IBizRemesaCliente; overload;
    procedure Ver(ARemesaCliente : IBizRemesaCliente);
    procedure VerTodos(ARemesasCliente: IBizRemesaCliente);
    function Nuevo : IBizRemesaCliente;
    procedure Anadir(ARemesaCliente : IBizRemesaCliente);
    function Eliminar(const ID : Integer): Boolean; overload;
    function Eliminar(ARemesaCliente : IBizRemesaCliente; AllItems: Boolean = false): Boolean; overload;
    function Guardar(ARemesaCliente : IBizRemesaCliente): Boolean;
    procedure DescartarCambios(ARemesaCliente : IBizRemesaCliente);
    function Existe(const ID: Integer) : Boolean;

    procedure Preview(ARemesaCliente : IBizRemesaCliente; AllItems: Boolean = false);
    function Print(ARemesaCliente : IBizRemesaCliente; AllItems: Boolean = false): Boolean;
    function EsModificable(ARemesaProveedor : IBizRemesaCliente): Boolean;
    function EsEliminable(ARemesaProveedor : IBizRemesaCliente): Boolean;

    function ElegirRecibosCliente(ARemesaCliente : IBizRemesaCliente; AListaRecibosIniciales: TStringList): Boolean;
    procedure EliminarReciboCliente(ARemesaCliente : IBizRemesaCliente);
    function GetRecibosClienteController: IRecibosClienteController;
    property RecibosClienteController: IRecibosClienteController read GetRecibosClienteController;

    procedure RecuperarRecibos(ARemesaCliente: IBizRemesaCliente);
    function ExtraerSeleccionados(ARemesasCliente: IBizRemesaCliente) : IBizRemesaCliente;

    function DarListaAnosRemesas: TStringList;
    procedure FiltrarAno(ARemesa: IBizRemesaCliente; ADynWhereDataTable: WideString; const Ano: String);
  end;

  TRemesasClienteController = class(TControllerBase, IRemesasClienteController)
  protected
    FDataModule : IDataModuleRemesasCliente;
    FRecibosClienteController: IRecibosClienteController;
    function GetRecibosClienteController: IRecibosClienteController;

    procedure RecibirAviso(ASujeto: ISujeto; ADataTable: IDAStronglyTypedDataTable); override;
    procedure AsignarID(ARemesaCliente: IBizRemesaCliente; const IDNuevo: Integer); virtual;
    function CreateEditor(const AName : String; const IID: TGUID; out Intf): Boolean;
    function _Vacio : IBizRemesaCliente;

    procedure FiltrarEmpresa(ARemesaCliente: IBizRemesaCliente);
    function ValidarRemesaCliente(ARemesaCliente: IBizRemesaCliente): Boolean; virtual;

    procedure RecuperarRecibos(ARemesaCliente: IBizRemesaCliente);
    procedure RecuperarObjetos(ARemesaCliente: IBizRemesaCliente); virtual;
    procedure AsignarDataModule; virtual;

  public
    property RecibosClienteController: IRecibosClienteController read GetRecibosClienteController;

    constructor Create; override;
    destructor Destroy; override;

    function Eliminar(const ID : Integer): Boolean; overload;
    function Eliminar(ARemesaCliente : IBizRemesaCliente; AllItems: Boolean = false): Boolean; overload;
    function Guardar(ARemesaCliente : IBizRemesaCliente): Boolean;
    procedure DescartarCambios(ARemesaCliente : IBizRemesaCliente); virtual;
    function Existe(const ID: Integer) : Boolean; virtual;
    procedure Anadir(ARemesaCliente : IBizRemesaCliente); virtual;
    function Buscar(const ID: Integer): IBizRemesaCliente; virtual;
    function BuscarTodos: IBizRemesaCliente; overload;
    function Nuevo : IBizRemesaCliente; virtual;
    procedure Ver(ARemesaCliente : IBizRemesaCliente); virtual;
    procedure VerTodos(ARemesasCliente: IBizRemesaCliente); virtual;

    procedure Preview(ARemesaCliente : IBizRemesaCliente; AllItems: Boolean = false); virtual;
    function Print(ARemesaCliente : IBizRemesaCliente; AllItems: Boolean = false): Boolean; virtual;
    function EsModificable(ARemesaProveedor : IBizRemesaCliente): Boolean;
    function EsEliminable(ARemesaProveedor : IBizRemesaCliente): Boolean;

    function ExtraerSeleccionados(ARemesasCliente: IBizRemesaCliente) : IBizRemesaCliente; virtual;
    function ElegirRecibosCliente(ARemesaCliente : IBizRemesaCliente; AListaRecibosIniciales: TStringList): Boolean;
    procedure EliminarReciboCliente(ARemesaCliente : IBizRemesaCliente);

    function DarListaAnosRemesas: TStringList;
    procedure FiltrarAno(ARemesa: IBizRemesaCliente; ADynWhereDataTable: WideString; const Ano: String);
  end;

implementation

uses
  cxControls, DB, uEditorRegistryUtils, schRemesasClienteClient_Intf, uFactuGES_App,
  schRecibosClienteClient_Intf, uIEditorRemesasCliente, uIEditorRemesaCliente,
  Dialogs, uDataModuleRemesasCliente, uDataModuleUsuarios, uDAInterfaces,
  uDataTableUtils, uDateUtils, uROTypes, DateUtils, Controls, Windows,
  uBizRecibosCliente, Variants, uRemesasClienteReportController, uIntegerListUtils;

{ TRemesasClienteController }

procedure TRemesasClienteController.Anadir(ARemesaCliente: IBizRemesaCliente);
begin
  ARemesaCliente.Insert;
end;

procedure TRemesasClienteController.EliminarReciboCliente(ARemesaCliente: IBizRemesaCliente);
var
  ARecibosRemesa : IBizRecibosCliente;
begin
  inherited;
  ARecibosRemesa := ARemesaCliente.Recibos;
  RecibosClienteController.QuitarRemesa(ARecibosRemesa);
  //Quitamos el recibo de la remesa sin que el servidor se entere para que no elimine el recibo
  DesconectarTabla(ARecibosRemesa.DataTable);
  ARecibosRemesa.DataTable.Delete;
  ConectarTabla(ARecibosRemesa.DataTable);
  ARecibosRemesa := Nil;
end;

function TRemesasClienteController.EsEliminable(ARemesaProveedor: IBizRemesaCliente): Boolean;
begin
  Result := True;
end;

function TRemesasClienteController.EsModificable(ARemesaProveedor: IBizRemesaCliente): Boolean;
begin
  Result := True;
end;

procedure TRemesasClienteController.AsignarDataModule;
begin
  FDataModule := TDataModuleRemesasCliente.Create(Nil);
  FRecibosClienteController := TRecibosClienteController.Create;
end;

procedure TRemesasClienteController.AsignarID(ARemesaCliente: IBizRemesaCliente; const IDNuevo: Integer);
begin
  if not Assigned(ARemesaCliente) then
    raise Exception.Create ('RemesaCliente no asignado');

  ARemesaCliente.Edit;
  ARemesaCliente.ID := IDNuevo;
  ARemesaCliente.Post;
end;

function TRemesasClienteController.Buscar(const ID: Integer): IBizRemesaCliente;
begin
  Result := (FDataModule as IDataModuleRemesasCliente).GetItem(ID);
  FiltrarEmpresa(Result);
end;

function TRemesasClienteController.BuscarTodos: IBizRemesaCliente;
begin
  Result := FDataModule.GetItems;
  FiltrarEmpresa(Result);
end;

constructor TRemesasClienteController.Create;
begin
  inherited;
  AsignarDataModule;
end;

function TRemesasClienteController.CreateEditor(const AName: String;
  const IID: TGUID; out Intf): Boolean;
begin
  Result := Supports(EditorRegistry.CreateEditor(AName), IID, Intf);
end;

function TRemesasClienteController.DarListaAnosRemesas: TStringList;
begin
  Result := FDataModule.GetAnosItems;
end;

procedure TRemesasClienteController.DescartarCambios(ARemesaCliente: IBizRemesaCliente);
begin
  if not Assigned(ARemesaCliente) then
    raise Exception.Create ('RemesaCliente no asignado');

  ShowHourglassCursor;
  try
    if (ARemesaCliente.State in dsEditModes) then
      ARemesaCliente.Cancel;

    ARemesaCliente.DataTable.CancelUpdates;
  finally
    HideHourglassCursor;
  end;
end;

destructor TRemesasClienteController.Destroy;
begin
  FDataModule := Nil;
  FRecibosClienteController := Nil;  
  inherited;
end;

function TRemesasClienteController.ValidarRemesaCliente(ARemesaCliente: IBizRemesaCliente): Boolean;
begin
  Result := False;
  
  if not Assigned(ARemesaCliente) then
    raise Exception.Create ('Remesa no asignada');

  if (ARemesaCliente.DataTable.State in dsEditModes) then
      ARemesaCliente.DataTable.Post;

  if ARemesaCliente.DataTable.FieldByName(fld_RemesasClienteFECHA_REMESA).IsNull then
     raise Exception.Create('Debe indicar la fecha de esta remesa.');

  if ARemesaCliente.ID_DATOS_BANCO < 1 then
     raise Exception.Create('Debe la cuenta bancaria sobre la que realizará la remesa.');

  // Asegurarse de valores en campos "automáticos"
  ARemesaCliente.Edit;
  try
    ARemesaCliente.USUARIO := AppFactuGES.UsuarioActivo.UserName;

    Result := True;
  finally
    ARemesaCliente.Post;
  end;
end;

procedure TRemesasClienteController.Ver(ARemesaCliente: IBizRemesaCliente);
var
  AEditor : IEditorRemesaCliente;
begin
  AEditor := NIL;
  RecuperarObjetos(ARemesaCliente);

  CreateEditor('EditorRemesaCliente', IEditorRemesaCliente, AEditor);
  if Assigned(AEditor) then
    try
      AEditor.Controller := Self; //OJO ORDEN MUY IMPORTANTE
      AEditor.RemesaCliente := ARemesaCliente;

      //MODO CONSULTAR
      if not EsModificable(ARemesaCliente) then
      begin
         SetDataTableReadOnly(ARemesaCliente.DataTable, True);
         AEditor.ReadOnly := True;
      end;

      AEditor.ShowModal;

      //MODO CONSULTAR (Se deja la tabla como estaba)
      if AEditor.ReadOnly then
         SetDataTableReadOnly(ARemesaCliente.DataTable, False);
    finally
      AEditor.Release;
      AEditor := NIL;
    end;
end;

procedure TRemesasClienteController.VerTodos(ARemesasCliente: IBizRemesaCliente);
var
  AEditor : IEditorRemesasCliente;
begin
  AEditor := NIL;

  CreateEditor('EditorRemesasCliente', IEditorRemesasCliente, AEditor);
  if Assigned(AEditor) then
    with (AEditor as IEditorRemesasCliente) do
    begin
      Controller := Self; //OJO ORDEN MUY IMPORTANTE
      RemesasCliente := ARemesasCliente;
      MultiSelect := True;
      ShowEmbedded;
    end;
end;

function TRemesasClienteController._Vacio: IBizRemesaCliente;
begin
  Result := Buscar(ID_NULO);
end;

function TRemesasClienteController.Eliminar(const ID: Integer): Boolean;
var
  ARemesaCliente : IBizRemesaCliente;
begin
  ARemesaCliente := Buscar(ID);

  if not Assigned(ARemesaCliente) then
    raise Exception.Create(Format('No se ha encontrado la remesa con ID = %d', [ID]));

  Result := Eliminar(ARemesaCliente);
  ARemesaCliente := NIL;
end;

function TRemesasClienteController.ElegirRecibosCliente(ARemesaCliente: IBizRemesaCliente; AListaRecibosIniciales: TStringList): Boolean;
var
  ARecibosRemesa : IBizRecibosCliente;
  ARecibosSeleccionados : IBizRecibosCliente;
  ListaRecibosVisibles: TStringList;
  ListaRecibosNoVisibles: TStringList;
  i: Integer;
begin
  Result := False;

  ListaRecibosVisibles := TStringList.Create;
  ListaRecibosNoVisibles := TStringList.Create;

  //Todos los recibos que tenga la remesa no deben de visualizarse en la lista de seleccion
  ARemesaCliente.Recibos.DataTable.First;
  while not ARemesaCliente.Recibos.DataTable.eof do
  begin
    ListaRecibosNoVisibles.Add(IntToStr(ARemesaCliente.Recibos.ID));
    ARemesaCliente.Recibos.DataTable.Next;
  end;
  ARemesaCliente.Recibos.DataTable.First;

  //Si de la lista inicial hay alguno que no se encuentre en la lista de recibos de la
  //remesa que tenemos en memoria dicho recibo debería verse por lo que lo añadimos a la lista de visibles
  for i := 0 to AListaRecibosIniciales.Count - 1 do
  begin
    ARemesaCliente.Recibos.DataTable.First;
    if not ARemesaCliente.Recibos.DataTable.Locate(fld_RecibosClienteID, AListaRecibosIniciales.strings[i], []) then
       ListaRecibosVisibles.Add(AListaRecibosIniciales.strings[i]);
  end;
  ARemesaCliente.Recibos.DataTable.First;

  ARecibosSeleccionados := (FRecibosClienteController.ElegirRecibos(FRecibosClienteController.BuscarRecibosARemesar(ListaRecibosVisibles, ListaRecibosNoVisibles), 'Elija uno o más recibos para incluirlos en esta remesa', True) as IBizRecibosCliente);
  if Assigned(ARecibosSeleccionados) then
  begin
     ShowHourglassCursor;
     try
       ARecibosRemesa := ARemesaCliente.Recibos;
       //Copia los recibos seleccionados a los recibos de la remesa sin que el servidor se entere de
       //las inserciones
       DuplicarRegistros(ARecibosSeleccionados.DataTable,ARecibosRemesa.DataTable, mdrTodos, True, False, True);
       FRecibosClienteController.SetSituacionCobrados(ARecibosRemesa);
       Result := True;
     finally
       HideHourglassCursor;
     end;
  end;

  ListaRecibosVisibles.Free;
  ListaRecibosNoVisibles.Free;
  ARecibosRemesa := Nil;
  ARecibosSeleccionados := Nil;
end;

function TRemesasClienteController.Eliminar(ARemesaCliente: IBizRemesaCliente; AllItems: Boolean = false): Boolean;
//En el caso de eliminar almenos un elemento del conjunto se devuelve true
var
  bEliminado: Boolean;
begin
  Result := False;
  bEliminado := False;

  if not Assigned(ARemesaCliente) then
    raise Exception.Create ('ARemesaCliente no asignada');

  ShowHourglassCursor;
  try
    if not ARemesaCliente.DataTable.Active then
      ARemesaCliente.DataTable.Active := True;

    if (ARemesaCliente.State in dsEditModes) then
      ARemesaCliente.Cancel;

    //Siempre eliminaremos el seleccionado
    if EsEliminable(ARemesaCliente) then
    begin
      //Si la llamada a eliminar es por el editor RemesasCliente, debo recuperar los recibos
      //de la remesa a eliminar, en caso de venir por el editor RemesaCliente ya los tengo
      if not Assigned(ARemesaCliente.Recibos) then
         RecuperarRecibos(ARemesaCliente);
      //Eliminaremos la remesa de los recibos asociados
      With ARemesaCliente.Recibos.DataTable do
      begin
        First;
        While not Eof do
        begin
          RecibosClienteController.QuitarRemesa(ARemesaCliente.Recibos);
          Next;
        end;
      end;

      //Como no están declarados como maestro-detalles debemos hacer el applyupdates nosotros
      ARemesaCliente.Recibos.DataTable.ApplyUpdates;

      ARemesaCliente.Delete;
      bEliminado := True;
    end;

    //En el caso de querer eliminar todos los items del objeto AAlbaran
    if AllItems then
    begin
       with ARemesaCliente.DataTable do
       begin
         First;
         while not EOF do
         begin
           if EsEliminable(ARemesaCliente) then
           begin
              //Si la llamada a eliminar es por el editor RemesasProveedor, debo recuperar los recibos
              //de la remesa a eliminar, en caso de venir por el editor RemesaCliente ya los tengo
              if not Assigned(ARemesaCliente.Recibos) then
                 RecuperarRecibos(ARemesaCliente);
              //Eliminaremos la remesa de los recibos asociados
              With ARemesaCliente.Recibos.DataTable do
              begin
                First;
                While not Eof do
                begin
                  RecibosClienteController.QuitarRemesa(ARemesaCliente.Recibos);
                  Next;
                end;
              end;

              //Como no están declarados como maestro-detalles debemos hacer el applyupdates nosotros
              ARemesaCliente.Recibos.DataTable.ApplyUpdates;

              ARemesaCliente.Delete;
              bEliminado := True
           end
           else Next;
         end;
       end;
    end;

    if bEliminado then
    begin
       ARemesaCliente.DataTable.ApplyUpdates;
       Result := True;
    end
    else
       Result := False;

    HideHourglassCursor;
  except
    //Hay algun recibo de la remesa que tiene movimientos (Cobros/Devoluciones) posteriores al cobro inicial de la remesa
    on E: Exception do
    begin
      ARemesaCliente.Recibos.DataTable.CancelUpdates;
      ARemesaCliente.DataTable.CancelUpdates;
      HideHourglassCursor;
      MessageBox(0, 'Exiten movimientos (Cobros/Devoluciones) en los recibos posteriores al cobro inicial de la remesa', 'Atención', MB_ICONWARNING or MB_OK);
    end;
  end;
end;

procedure TRemesasClienteController.RecibirAviso(ASujeto: ISujeto; ADataTable: IDAStronglyTypedDataTable);
begin
  inherited;
//
end;

procedure TRemesasClienteController.RecuperarObjetos(ARemesaCliente: IBizRemesaCliente);
begin
  RecuperarRecibos(ARemesaCliente);
end;

procedure TRemesasClienteController.RecuperarRecibos(ARemesaCliente: IBizRemesaCliente);
begin
  ARemesaCliente.Recibos := RecibosClienteController.BuscarRecibosRemesa(ARemesaCliente.ID);
end;

function TRemesasClienteController.Existe(const ID: Integer): Boolean;
var
  ARemesaCliente : IBizRemesaCliente;
begin
  try
    ARemesaCliente := Buscar(ID);
    Result := Assigned(ARemesaCliente) and (ARemesaCliente.ID = ID);
  finally
    ARemesaCliente := NIL;
  end;
end;

function TRemesasClienteController.ExtraerSeleccionados(ARemesasCliente: IBizRemesaCliente): IBizRemesaCliente;
var
  ASeleccionados : IBizRemesaCliente;
begin
  ASeleccionados := (Self.Buscar(ID_NULO) as IBizRemesaCliente);
  CopyDataTableDA5(ARemesasCliente.DataTable, ASeleccionados.DataTable, True);
  Result := ASeleccionados;
end;

procedure TRemesasClienteController.FiltrarAno(ARemesa: IBizRemesaCliente; ADynWhereDataTable: WideString; const Ano: String);
var
  Condicion: TDAWhereExpression;
  FechaIni: String;
  FechaFin: String;

begin
  ARemesa.DataTable.DynamicWhere.Clear;
  ARemesa.DataTable.DynamicWhere.Xml := ADynWhereDataTable;

  if (Ano <> 'Todos') then
  begin
    // Filtrar las facturas actuales por empresa
    FechaIni := '01/01/' + Ano;
    FechaFin := '31/12/' + Ano;
    with ARemesa.DataTable.DynamicWhere do
    begin
      // (FECHA_INICIO between FECHA_FIN)
      Condicion := NewBinaryExpression(NewField('', fld_RemesasClienteFECHA_REMESA), NewConstant(FechaIni, datString), dboGreaterOrEqual);
      Condicion := NewBinaryExpression(NewBinaryExpression(NewField('', fld_RemesasClienteFECHA_REMESA), NewConstant(FechaFin, datString), dboLessOrEqual), Condicion, dboAnd);

      if IsEmpty then
         Expression := Condicion
      else
         Expression := NewBinaryExpression(Condicion, Expression, dboAnd);
    end;
  end;
end;

procedure TRemesasClienteController.FiltrarEmpresa(ARemesaCliente: IBizRemesaCliente);
var
  Condicion: TDAWhereExpression;
begin
  if ARemesaCliente.DataTable.Active then
     ARemesaCliente.DataTable.Active := False;

  // Filtrar las remesas actuales por empresa
  with ARemesaCliente.DataTable.DynamicWhere do
  begin
    // (ID_EMPRESA >= ID)
    Condicion := NewBinaryExpression(NewField('', fld_RemesasClienteID_EMPRESA), NewConstant(AppFactuGES.EmpresaActiva.ID, datInteger), dboEqual);

    if IsEmpty then
       Expression := Condicion
    else
       Expression := NewBinaryExpression(Expression, Condicion, dboAnd);
  end;
end;

function TRemesasClienteController.GetRecibosClienteController: IRecibosClienteController;
begin
  Result := FRecibosClienteController;
end;

function TRemesasClienteController.Guardar(ARemesaCliente: IBizRemesaCliente): Boolean;
var
  bEsNuevo: Boolean;
begin
  Result := False;

  if ValidarRemesaCliente(ARemesaCliente) then
  begin
    ShowHourglassCursor;
    try
      bEsNuevo := ARemesaCliente.EsNuevo;

      //Si es nuevo debemos hacer el applyupdates por la integridad referencial de BD
      if bEsNuevo then
         ARemesaCliente.DataTable.ApplyUpdates;

      //Si todo ha ido bien, asignamos la remesa a los recibos asociados
      //Como no están declarados como maestro-detalles debemos hacer el applyupdates nosotros
      RecibosClienteController.AsignarRemesa(ARemesaCliente.Recibos, ARemesaCliente.ID);
      ARemesaCliente.Recibos.DataTable.ApplyUpdates; //En este applyupdates tambien se realizarán todos los cambios acumulados sobre los recibos asociados (EliminarReciboCliente/ ElegirRecibosCliente)

      //Es necesario ya que no se refrescan bien los deltas y despues del applyupdates siguen
      //existiendo deltas, de esta forma los limpiamos
      if ARemesaCliente.Recibos.DataTable.HasDelta then
         ARemesaCliente.Recibos.DataTable.Refresh;

      ARemesaCliente.DataTable.ApplyUpdates;
      
      Result := True;
    finally
      HideHourglassCursor;
    end;
  end;
end;

function TRemesasClienteController.Nuevo: IBizRemesaCliente;
var
  ARemesaCliente : IBizRemesaCliente;
begin
  ARemesaCliente := FDataModule.NewItem;
  FiltrarEmpresa(ARemesaCliente);
  ARemesaCliente.DataTable.Active := True;
  ARemesaCliente.Insert;
  Result := ARemesaCliente;
end;

procedure TRemesasClienteController.Preview(ARemesaCliente: IBizRemesaCliente; AllItems: Boolean = false);
var
  AReportController : IRemesasClienteReportController;
  ID_Remesas: TIntegerList;

begin
  AReportController := TRemesasClienteReportController.Create;
  ID_Remesas := TIntegerList.Create;

  try
   //Si deseamos previsualizar todos los items del objeto albaran
   if AllItems then
   begin
     with ARemesaCliente.DataTable do
     begin
       First;
       while not EOF do
       begin
         ID_Remesas.Add(ARemesaCliente.ID);
         Next;
       end;
     end;
   end
   //Solo previsualizamos el item seleccionado
   else
     ID_Remesas.Add(ARemesaCliente.ID);

    AReportController.Preview(ID_Remesas);

  finally
    AReportController := NIL;
    FreeANDNil(ID_Remesas);
  end;
end;

function TRemesasClienteController.Print(ARemesaCliente: IBizRemesaCliente; AllItems: Boolean = false): Boolean;
var
  AReportController : IRemesasClienteReportController;
  ID_Remesas: TIntegerList;

begin
  Result := False;
  AReportController := TRemesasClienteReportController.Create;
   ID_Remesas := TIntegerList.Create;

  try
   //Si deseamos previsualizar todos los items del objeto albaran
   if AllItems then
   begin
     with ARemesaCliente.DataTable do
     begin
       First;
       while not EOF do
       begin
         ID_Remesas.Add(ARemesaCliente.ID);
         Next;
       end;
     end;
   end
   //Solo previsualizamos el item seleccionado
   else
     ID_Remesas.Add(ARemesaCliente.ID);

    Result := AReportController.Print(ID_Remesas);

  finally
    AReportController := NIL;
    FreeAndNil(ID_Remesas);
  end;
end;

end.
