{
===============================================================================
  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.1.7
  Fecha versión actual: 08-03-2004
===============================================================================
  Modificaciones:

    Fecha         Comentarios
    ---------------------------------------------------------------------------
    15-10-2001    Se ha eliminado el campo 'Descripcion' porque no se usa en
                  albaranes. En su lugar se han colocado los campos de importes
                  y se ha eliminado la etiqueta 'Importes'.

    15-10-2001    Se han añadido las comprobaciones para el campo 'IVA' y para
                  el campo 'Descuento' porque no estaban.

    27-10-2001    Se ha arreglado un fallo que al añadir un concepto estando
                  en la última fila lo hacia por encima del registro, no por
                  debajo.

    29-10-2001    Cuando se elimina un concepto con <CTRL+Supr> hay que
                  volver a recalcular el importe total del albarán.

    30-10-2001    Se ha utilizado una tabla de memoria para tratar la lista
                  de detalles del albarán.

    31-10-2001    Se han añadido los campos IMPORTEDESCUENTO e IMPORTEIVA.

    27-11-2001    Recuperar la unidad de medida del artículo.

    07-02-2002    Desactivada la opción de 'CancelOnExit' del grid.

    24-02-2002    En la ventana modal de artículos seleccionar, si es posible,
                  la fila con el último material seleccionado.

    02-03-2002    En el contenido se pueden añadir muchos materiales a la vez.

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

    09-04-2002    En las funciones 'CancelarAnadir', 'CancelarModificar',
                  'CancelarEliminar', 'AnadirDatos', 'ModificarDatos', y
                  'EliminarDatos' cerrar todas las tablas que se usen.

    09-04-2002    En el evento 'bCancelarClick' llamar a la función
                  'TratarCambios' en vez de 'DescartarOperacion'.

    05-05-2002    En el procedimiento 'SetCodigoArticulo' no se daba un mensaje
                  de error cuando el artículo no existía.

    06-05-2002    Adaptación al grid 'TdxDBGrid'.

    21-08-2002    P237. Revisar los botones de 'Eliminar' y 'Eliminar todo'
                  para que al pulsar 'Esc' cancele la operación y no la
                  ejecute como ahora.

    21-08-2002    P238. Revisar el grid de los detalles para que se pueda
                  borrar un código de artículo cuando ya se ha introducido.

    14-09-2002    P242. Sacar una ventana modal para editar el
                  texto de un concepto.

    24-09-2002    Se producía una excepción si el cursos estaba en el código
                  del albarán, se pulsaba la tecla 'Esc' y se elegía 'No'.
                  El frame estaba oculto pero saltaba el evento OnExit del
                  campo de código de factura.    

    21-12-2002    Se ha eliminado un error con el campo 'PROVINCIA'. Al estar
                  situado en ese campo y dar Esc para salir se puede producir
                  una excepción.
                  
    08-03-2003    Se han puesto componentes con calendario.

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

unit AlbaranCliente;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  RdxFrameAlbaranes, Grids, DBGrids, RdxBotones, RdxTitulos, StdCtrls,
  RdxMemo, RdxCampos, ExtCtrls, Tipos, RxMemDS,
  RdxComboBox, RdxPaneles, RdxBarras, RXDBCtrl, ComCtrls, Configuracion,
  dxCntner, dxEditor, dxExEdtr, dxEdLib, dxDBELib, Db, dxTL, dxDBCtrl,
  dxDBGrid, RdxPageControl, cxControls, cxContainer, cxEdit, cxTextEdit,
  cxMaskEdit, cxDropDownEdit, cxCalendar, cxDBEdit, cxButtonEdit;

type
  TfrAlbaranCliente = class(TRdxFrameAlbaranes)
    brSalir: TRdxBarraInferior;
    bSalir: TRdxBoton;
    brGuardar: TRdxBarraInferior;
    bGuardar: TRdxBoton;
    bCancelar: TRdxBoton;
    pnlScroll: TRdxScrollPanel;
    pnlAlbaran: TRdxPanel;
    cDatosAlbaran: TRdxCabecera;
    eCodigo: TLabel;
    Codigo: TRdxDBEdit;
    eFechaAlta: TLabel;
    eUsuario: TLabel;
    Usuario: TRdxDBEdit;
    pnlTitulo: TRdxPanelTituloOperacion;
    RdxPanel1: TRdxPanel;
    Paginas: TRdxPagesControl;
    pagCliente: TTabSheet;
    pnlCliente: TRdxPanel;
    eCodigoCliente: TLabel;
    eNIFCIF: TLabel;
    eNombre: TLabel;
    eDireccion: TLabel;
    eNumero: TLabel;
    ePiso: TLabel;
    ePoblacion: TLabel;
    eCodigoPostal: TLabel;
    eProvincia: TLabel;
    ePersona: TLabel;
    eTelefono1: TLabel;
    eFax: TLabel;
    NIF: TRdxDBEdit;
    Nombre: TRdxDBEdit;
    Calle: TRdxDBEdit;
    Numero: TRdxDBEdit;
    Piso: TRdxDBEdit;
    Poblacion: TRdxDBEdit;
    CodigoPostal: TRdxDBEdit;
    Provincia: TRdxDBEdit;
    PersonaContacto: TRdxDBEdit;
    Telefono: TRdxDBEdit;
    Fax: TRdxDBEdit;
    pagContenido: TTabSheet;
    pnlGridArticulos: TPanel;
    dsAlbaran: TDataSource;
    dsDetallesAlbaran: TDataSource;
    pnlBarraGrid: TRdxPanel;
    bAnadir: TRdxBoton;
    bEliminar: TRdxBoton;
    bEliminarTodo: TRdxBoton;
    pagImportes: TTabSheet;
    pnlImporteAlbaran: TRdxPanel;
    Label4: TLabel;
    eDto: TLabel;
    eIVA: TLabel;
    Label6: TLabel;
    Shape1: TShape;
    BaseImponible: TRdxDBEdit;
    Descuento: TRdxDBEdit;
    IVA: TRdxDBEdit;
    ImporteTotal: TRdxDBEdit;
    ImporteDescuento: TRdxDBEdit;
    ImporteIVA: TRdxDBEdit;
    gridDetalles: TdxDBGrid;
    FechaAlta: TcxDBDateEdit;
    CodCliente: TcxDBButtonEdit;
    procedure CodigoButtonClick(Sender: TObject);
    procedure CodigoExit(Sender: TObject);
    procedure ProvinciaButtonClick(Sender: TObject);
    procedure PoblacionButtonClick(Sender: TObject);
    procedure bAnadirClick(Sender: TObject);
    procedure bEliminarClick(Sender: TObject);
    procedure bEliminarTodoClick(Sender: TObject);
    procedure bSalirClick(Sender: TObject);
    procedure bGuardarClick(Sender: TObject);
    procedure bCancelarClick(Sender: TObject);
    procedure CodClientePropertiesValidate(Sender: TObject;
      var DisplayValue: Variant; var ErrorText: TCaption;
      var Error: Boolean);
    procedure CodClientePropertiesButtonClick(Sender: TObject;
      AButtonIndex: Integer);
  private
    FCodigoProvincia : Variant;
    FCodigoPoblacion : Variant;
    FCodigoCliente : Variant;
    FCodigoArticulo : Variant;
    FTablaDetallesMem : TRxMemoryData;
    procedure CalcularTotalDetalle;
    procedure CalcularTotalAlbaran;
    procedure ActivarEventosCampos;
    procedure BorrarDetalles;
    procedure BorrarDetallesIB;
    procedure SalvarDetalles;
    procedure CargarDetalles;
    procedure DetalleAfterDelete (DataSet: TDataSet);
    procedure IVASetText(Sender: TField; const Text: String);
    procedure DtoSetText(Sender: TField; const Text: String);
  protected
    procedure ActivarModoAnadir; override;
    procedure ActivarModoModificar; override;
    procedure ActivarModoConsultar; override;
    procedure ActivarModoEliminar; override;
    function AnadirDatos : Boolean; override;
    function ModificarDatos : Boolean; override;
    function EliminarDatos : Boolean; override;
    function CancelarAnadir : Boolean; override;
    function CancelarModificar : Boolean; override;
    function CancelarEliminar : Boolean; override;
    function ComprobarDatos : Boolean; override;
    procedure VerModal; override;
    procedure SetCodigoProvincia (Value : Variant); virtual;
    procedure SetCodigoPoblacion (Value : Variant); virtual;
    procedure SetCodigoCliente (Value : Variant);
    procedure SetCodigoArticulo (Value : Variant);
    procedure FreeContenido; override;
    procedure BuscarAlbaran; override;
  public
    property CodigoProvincia : Variant read FCodigoProvincia write SetCodigoProvincia;
    property CodigoPoblacion : Variant read FCodigoPoblacion write SetCodigoPoblacion;
    property CodigoCliente : Variant read FCodigoCliente write SetCodigoCliente;
    property CodigoArticulo : Variant read FCodigoArticulo write SetCodigoArticulo;
    constructor Create (AOwner : TComponent); override;
    destructor Destroy; override;
  published
    property TablaAlbaranes;
    property TablaDetallesAlbaranes;
    property TablaDetallesMem : TRxMemoryData read FTablaDetallesMem write FTablaDetallesMem;
    property CodigoAlbaran;
    procedure ProvinciaSetText(Sender: TField; const Text: String);
    procedure GridBotonCodigoArticuloClick(Sender: TObject);
    procedure CodigoArticuloDetalleSetText(Sender: TField; const Text: String);
    procedure DtoDetalleSetText(Sender: TField; const Text: String);
    procedure CantidadDetalleSetText(Sender: TField; const Text: String);
    procedure PrecioDetalleSetText(Sender: TField; const Text: String);
    procedure GridBotonDescripcionClick(Sender: TObject);    
  end;

var
  frAlbaranCliente: TfrAlbaranCliente;

implementation

{$R *.DFM}

uses
  TablaAlbaranesCliente, BaseDatos, IB, StrFunc, Mensajes, NumFunc, 
  TablaArticulos, TablaClientes, TablaProvincias, TablaPoblaciones,
  RdxFrameArticulos, RdxFrameClientes, RdxFrameProvincias, RdxFramePoblaciones,
  AlbaranesClientes, Articulos, IBCustomDataSet, Clientes, Provincias,
  Poblaciones, Excepciones, IBErrorCodes, dxDBTLCL, EditorDescripcion,
  RdxEmpresaActiva, Literales;

{ TfrAlbaranCliente }

procedure TfrAlbaranCliente.ActivarModoAnadir;
var
  CodNuevo : Variant;
begin
  dsAlbaran.AutoEdit := True;
  dsDetallesAlbaran.AutoEdit := True;
  Codigo.VerBoton := False;
  Codigo.ReadOnly := False;
  CodCliente.Properties.Buttons[0].Visible := True;
  CodCliente.Properties.OnValidate := CodClientePropertiesValidate;
  Provincia.VerBoton := True;
  Poblacion.VerBoton := True;

  ActivarEdicionGridDetalles(gridDetalles);

  (gridDetalles.ColumnByFieldName('CODIGOARTICULO')
    as TdxDBTreeListButtonColumn).OnEditButtonClick := GridBotonCodigoArticuloClick;

  (gridDetalles.ColumnByFieldName('DESCRIPCION')
    as TdxDBTreeListButtonColumn).OnEditButtonClick := GridBotonDescripcionClick;

  pnlBarraGrid.Visible := True;

  try
    { Antes de aplicar la caché hay que asegurarse de que la
      tabla está cerrada. }
    TablaAlbaranes.DisableControls;

    { Inicializar la tabla de albaranes }
    TablaAlbaranes.Close;
    CodNuevo := dmTablaAlbaranesCliente.DarNuevoCodigo;
    with TablaAlbaranes do
    begin
      CachedUpdates := True;
      Prepare;
      Open;
      FieldByName('PROVINCIA').OnSetText := ProvinciaSetText;      
      EnableControls;
      Insert;
      FieldByName('CODIGOEMPRESA').AsInteger := EmpresaActiva.Codigo;      
    end;

    Codigo.Field.asString := CodNuevo;
    FechaAlta.DataBinding.Field.AsString := DateToStr(Date);
    Usuario.Field.AsString := dmBaseDatos.Usuario;

    { Inicializar la tabla de detalles }
    with TablaDetallesAlbaranes do
    begin
      Close;
      ParamByName('CODIGOEMPRESA').AsInteger := EmpresaActiva.Codigo;
      ParamByName('CODIGOALBARAN').AsString := CodNuevo;
      Prepare;
      Open;
    end;

    with TablaDetallesMem do
    begin
      Close;
      Open;
      ActivarEventosCampos;
    end;

    dmTablaAlbaranesCliente.InicializarTablaAlbaranes(@TablaAlbaranes);
    dmTablaAlbaranesCliente.InicializarTablaDetalles(@TablaDetallesMem);
    Visible := True;
  except
    on E : EIBError do
      TratarExcepcion(E);
    on E : Exception do
      TratarExcepcion(E);
  end;
end;

procedure TfrAlbaranCliente.ActivarModoConsultar;
begin
  dsAlbaran.AutoEdit := False;
  dsDetallesAlbaran.AutoEdit := False;
  Codigo.VerBoton := True;
  CodCliente.Properties.Buttons[0].Visible := False;
  CodCliente.Properties.OnValidate := nil;
  Provincia.VerBoton := False;
  Poblacion.VerBoton := False;

  DesactivarEdicionGridDetalles(gridDetalles);

  (gridDetalles.ColumnByFieldName('CODIGOARTICULO')
    as TdxDBTreeListButtonColumn).OnEditButtonClick := NIL;

  (gridDetalles.ColumnByFieldName('DESCRIPCION')
    as TdxDBTreeListButtonColumn).OnEditButtonClick := NIL;

  pnlBarraGrid.Visible := False;

  try
    TablaAlbaranes.Prepare;
    TablaAlbaranes.Open;

    if TablaAlbaranes.RecordCount = 0 then
    begin
      VerMensajeFmt(msgAlbNoExisteAlb, [CodigoAlbaran]);
      CloseFrame;
      Exit;
    end;

    TablaAlbaranes.Cancel;

    with TablaDetallesAlbaranes do
    begin
      Close;
      ParamByName('CODIGOEMPRESA').AsInteger := EmpresaActiva.Codigo;
      Params.ByName('CODIGOALBARAN').AsString := CodigoAlbaran;
      Prepare;
      Open;
      Cancel;
    end;

    with TablaDetallesMem do
    begin
      Close;
      Open;
      Cancel;
      CargarDetalles;
    end;

    dmTablaAlbaranesCliente.InicializarTablaAlbaranes(@TablaAlbaranes);
    dmTablaAlbaranesCliente.InicializarTablaDetalles(@TablaDetallesMem);
    Visible := True;
  except
    on E : EIBError do
      TratarExcepcion(E);
    on E : Exception do
      TratarExcepcion(E);
  end;
end;

procedure TfrAlbaranCliente.ActivarModoEliminar;
begin
  dsAlbaran.AutoEdit := False;
  dsDetallesAlbaran.AutoEdit := False;
  Codigo.VerBoton := True;
  CodCliente.Properties.Buttons[0].Visible := False;
  CodCliente.Properties.OnValidate := nil;
  Provincia.VerBoton := False;
  Poblacion.VerBoton := False;

  DesactivarEdicionGridDetalles(gridDetalles);

  (gridDetalles.ColumnByFieldName('CODIGOARTICULO')
    as TdxDBTreeListButtonColumn).OnEditButtonClick := NIL;

  (gridDetalles.ColumnByFieldName('DESCRIPCION')
    as TdxDBTreeListButtonColumn).OnEditButtonClick := NIL;

  pnlBarraGrid.Visible := False;

  try
    TablaAlbaranes.Prepare;
    TablaAlbaranes.Open;

    if TablaAlbaranes.RecordCount = 0 then
    begin
      VerMensajeFmt(msgAlbNoExisteAlb, [CodigoAlbaran]);
      CancelarEliminar;
      CloseFrame;
      Exit;
    end;

    TablaAlbaranes.Cancel;

    with TablaDetallesAlbaranes do
    begin
      Close;
      ParamByName('CODIGOEMPRESA').AsInteger := EmpresaActiva.Codigo;
      Params.ByName('CODIGOALBARAN').AsString := CodigoAlbaran;
      Prepare;
      Open;
      Cancel;
    end;

    with TablaDetallesMem do
    begin
      Close;
      Open;
      Cancel;
      CargarDetalles;
    end;

    dmTablaAlbaranesCliente.InicializarTablaAlbaranes(@TablaAlbaranes);
    dmTablaAlbaranesCliente.InicializarTablaDetalles(@TablaDetallesMem);
    Visible := True;    
  except
    on E : EIBError do
      TratarExcepcion(E);
    on E : Exception do
      TratarExcepcion(E);
  end;
end;

procedure TfrAlbaranCliente.ActivarModoModificar;
begin
  dsAlbaran.AutoEdit := True;
  dsDetallesAlbaran.AutoEdit := True;
  Codigo.VerBoton := True;
  Codigo.ReadOnly := True;
  CodCliente.Properties.Buttons[0].Visible := True;
  CodCliente.Properties.OnValidate := CodClientePropertiesValidate;
  Provincia.VerBoton := True;
  Poblacion.VerBoton := True;

  ActivarEdicionGridDetalles(gridDetalles);

  (gridDetalles.ColumnByFieldName('CODIGOARTICULO')
    as TdxDBTreeListButtonColumn).OnEditButtonClick := GridBotonCodigoArticuloClick;

  (gridDetalles.ColumnByFieldName('DESCRIPCION')
    as TdxDBTreeListButtonColumn).OnEditButtonClick := GridBotonDescripcionClick;

  pnlBarraGrid.Visible := True;

  try
    { Antes de aplicar la caché hay que asegurarse de que la
      tabla está cerrada. }
    TablaAlbaranes.Prepare;
    TablaAlbaranes.Open;
    TablaAlbaranes.FieldByName('PROVINCIA').OnSetText := ProvinciaSetText;
    if TablaAlbaranes.RecordCount = 0 then
    begin
      VerMensajeFmt(msgAlbNoExisteAlb, [CodigoAlbaran]);
      CancelarModificar;
      CloseFrame;
      Exit;
    end;

    TablaAlbaranes.Edit;
    TablaAlbaranes.Post;
    TablaAlbaranes.Edit;

    with TablaDetallesAlbaranes do
    begin
      Close;
      ParamByName('CODIGOEMPRESA').AsInteger := EmpresaActiva.Codigo;
      Params.ByName('CODIGOALBARAN').AsString := CodigoAlbaran;
      Prepare;
      Open;
    end;
    
    with TablaDetallesMem do
    begin
      Close;
      Open;
      CargarDetalles;
      ActivarEventosCampos;
      CalcularTotalAlbaran;
    end;

    dmTablaAlbaranesCliente.InicializarTablaAlbaranes(@TablaAlbaranes);
    dmTablaAlbaranesCliente.InicializarTablaDetalles(@TablaDetallesMem);
    Visible := True;
  except
    on E : EIBError do
    begin
      case E.IBErrorCode of
        isc_lock_conflict : begin
                              VerMensajeFmt(msgAlbBloqueado, [CodigoAlbaran]);
                              CancelarModificar;
                              CloseFrame;
                              Exit;
                            end
        else
          TratarExcepcion(E);
      end;
    end;
    on E : Exception do
      TratarExcepcion(E);
  end;
end;

function TfrAlbaranCliente.AnadirDatos: Boolean;
var
  NumConcepto : Integer;
begin
  Result := False;
  try
    CalcularTotalAlbaran;
    NumConcepto := 0;
    TablaAlbaranes.Post;
    TablaAlbaranes.ApplyUpdates;

    BorrarDetallesIB;
    SalvarDetalles;

    dmTablaAlbaranesCliente.IncrementarCodigo;
    FCodigoAlbaran := TablaAlbaranes.FieldByName('CODIGO').AsString;
    Commit;
    TablaAlbaranes.Close;
    TablaDetallesAlbaranes.Close;
    TablaDetallesMem.Close;
    TablaAlbaranes.CachedUpdates := False;
    Result := True;
  except
    on E : EIBError do begin
      if E.IBErrorCode = isc_unique_key_violation then begin
        VerMensajeFmt(msgAlbCodAlbRepetido, [Codigo.Field.AsString]);
        TablaAlbaranes.Edit;
      end
      else
        TratarExcepcion(E);
    end;
    on E : Exception do
      TratarExcepcion(E);
  end;
end;

procedure TfrAlbaranCliente.BuscarAlbaran;
begin
  if Transaccion = NIL then
    exit;
  try
    TablaAlbaranes.DisableControls;
    TablaDetallesMem.DisableControls;

    TablaAlbaranes.Close;
    TablaDetallesAlbaranes.Close;

    // Buscar la fila a tratar si es necesario
    if not VarIsNull(FCodigoAlbaran) then
    begin
      TablaAlbaranes.ParamByName('CODIGOEMPRESA').AsInteger := EmpresaActiva.Codigo;
      TablaAlbaranes.ParamByName('CODIGO').AsString := FCodigoAlbaran;

      TablaDetallesAlbaranes.ParamByName('CODIGOEMPRESA').AsInteger := EmpresaActiva.Codigo;
      TablaDetallesAlbaranes.ParamByName('CODIGOALBARAN').AsString := FCodigoAlbaran;
    end;
    TablaAlbaranes.Prepare;
    TablaAlbaranes.Open;

    TablaDetallesAlbaranes.Prepare;
    TablaDetallesAlbaranes.Open;

    TablaDetallesMem.Close;
    TablaDetallesMem.Open;

    BorrarDetalles;
    CargarDetalles;

    dmTablaAlbaranesCliente.InicializarTablaAlbaranes(@TablaAlbaranes);
    dmTablaAlbaranesCliente.InicializarTablaDetalles(@TablaDetallesMem);

    TablaAlbaranes.EnableControls;
    TablaDetallesMem.EnableControls;
  except
    on E : EIBError do
      TratarExcepcion(E);
    on E : Exception do
      TratarExcepcion(E);
  end;
end;

procedure TfrAlbaranCliente.CalcularTotalAlbaran;
var
  BaseImponible,
  ImporteIVA,
  ImporteDto,
  ImporteTotal : Double;
  FDetallesBookmark : string;
begin
  BaseImponible := 0;
  ImporteTotal := 0;
  with TablaDetallesMem do
  begin
    DisableControls;
    FDetallesBookmark := Bookmark;
    try
      First;
      while not EOF do begin
        BaseImponible := BaseImponible + FieldByName('TOTAL').AsFloat;
        Next;
      end;

      ImporteDto := BaseImponible * (TablaAlbaranes.FieldByName('DESCUENTO').AsFloat/100);
      ImporteTotal := BaseImponible - ImporteDto;
      ImporteIVA := ImporteTotal * (TablaAlbaranes.FieldByName('IVA').AsFloat/100);
      ImporteTotal := ImporteTotal + ImporteIVA;

      TablaAlbaranes.FieldByName('BASEIMPONIBLE').AsFloat := BaseImponible;
      TablaAlbaranes.FieldByName('IMPORTEDESCUENTO').AsFloat := ImporteDto;
      TablaAlbaranes.FieldByName('IMPORTEIVA').AsFloat := ImporteIVA;
      TablaAlbaranes.FieldByName('IMPORTETOTAL').AsFloat := ImporteTotal;
    finally
      Bookmark := FDetallesBookmark;
      EnableControls;
    end;
  end;
end;

procedure TfrAlbaranCliente.CalcularTotalDetalle;
var
  auxCantidad,
  auxPrecio,
  auxTotal : double;
begin
  with TablaDetallesMem do
  begin
    auxCantidad := FieldByName('CANTIDAD').AsFloat;
    auxPrecio := FieldByName('PRECIOUNIDAD').AsFloat;
    auxTotal := auxCantidad * auxPrecio;
    FieldByName('TOTAL').AsFloat := auxTotal;
  end;
end;

function TfrAlbaranCliente.CancelarAnadir: Boolean;
begin
  Result := False;
  try
    TablaDetallesMem.Close;
    TablaAlbaranes.Close;
    TablaDetallesAlbaranes.Close;
    TablaAlbaranes.CancelUpdates;
    RollBack;
    TablaAlbaranes.CachedUpdates := False;
    Result := True;
  except
    on E : EIBError do
      TratarExcepcion(E);
    on E : Exception do
      TratarExcepcion(E);
  end;
end;

function TfrAlbaranCliente.CancelarEliminar: Boolean;
begin
  Result := False;
  try
    TablaDetallesMem.Close;
    TablaAlbaranes.Close;
    TablaDetallesAlbaranes.Close;
    RollBack;
    Result := True;
  except
    on E : EIBError do
      TratarExcepcion(E);
    on E : Exception do
      TratarExcepcion(E);
  end;
end;

function TfrAlbaranCliente.CancelarModificar: Boolean;
begin
  Result := False;
  try
    TablaDetallesMem.Close;
    TablaAlbaranes.Close;
    TablaDetallesAlbaranes.Close;
    RollBack;
    Result := True;
  except
    on E : EIBError do
      TratarExcepcion(E);
    on E : Exception do
      TratarExcepcion(E);
  end;
end;

procedure TfrAlbaranCliente.CantidadDetalleSetText(Sender: TField;
  const Text: String);
begin
  try
    if EsCadenaVacia(Text) then
      Sender.AsString := '1'
    else
      Sender.AsString := Text;
    CalcularTotalDetalle;
    CalcularTotalAlbaran;
  except
    on E : EConvertError do
      VerMensaje(msgCantidadNoValida);
    on E : EIBError do
      TratarExcepcion(E);
    on E : Exception do
      TratarExcepcion(E);
  end;
end;

procedure TfrAlbaranCliente.CodigoArticuloDetalleSetText(Sender: TField;
  const Text: String);
var
  Codigo : String;
begin
  if (EsCadenaVacia(Text)) then
  begin
     Sender.AsString := '';
     exit;
  end;
  
  Codigo := Trim(Text);
  if (dmTablaArticulos.validarCodigo(Codigo)) then
    Codigo := dmTablaArticulos.formatearCodigo(Codigo)
  else
    raise Exception.CreateFmt(msgArtCodArtIncorrecto, [Codigo]);

  Sender.AsString := Codigo;
  CodigoArticulo := Codigo;
end;

function TfrAlbaranCliente.ComprobarDatos: Boolean;
begin
  Result := False;

  if EsCadenaVacia(FechaAlta.DataBinding.Field.AsString) then
  begin
    VerMensaje(msgAlbFaltaFechaAlta);
    FechaAlta.SetFocus;
    Exit;
  end;

  if EsCadenaVacia(Nombre.Field.AsString) then
  begin
    VerMensaje(msgAlbFaltaNombreCli);
    Paginas.ActivePageIndex := 0;
    Nombre.SetFocus;
    Exit;
  end;

  if TablaDetallesMem.IsEmpty then
  begin
    VerMensaje(msgAlbFaltaArticulos);
    Paginas.ActivePageIndex := 1;
    gridDetalles.SetFocus;
    Exit
  end;

  Result := True;
end;

constructor TfrAlbaranCliente.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  FCodigoProvincia := NULL;
  FCodigoPoblacion := NULL;
  FCodigoCliente := NULL;
  FCodigoArticulo := NULL;

  Entidad := entAlbaranCliente;
  ConfigurarFrame(Self, Self.Entidad);
  BaseDatos := dmBaseDatos.BD;

  Transaccion := dmBaseDatos.Transaccion;
  Transaccion.DefaultDatabase := BaseDatos;

  TablaAlbaranes := TIBDataSet.Create(Self);
  TablaDetallesAlbaranes := TIBDataSet.Create(Self);
  TablaDetallesMem := TRxMemoryData.Create(Self);

  dsAlbaran.DataSet := TablaAlbaranes;
  dsDetallesAlbaran.DataSet := TablaDetallesMem;

  with TablaAlbaranes do
  begin
    Database := BaseDatos;
    Transaction := Transaccion;
    SelectSQL.Assign(dmTablaAlbaranesCliente.sqlConsultarAlbaran);
    InsertSQL.Assign(dmTablaAlbaranesCliente.sqlInsertarAlbaran);
    ModifySQL.Assign(dmTablaAlbaranesCliente.sqlModificarAlbaran);
    DeleteSQL.Assign(dmTablaAlbaranesCliente.sqlEliminarAlbaran);
  end;

  with TablaDetallesAlbaranes do
  begin
    Database := BaseDatos;
    Transaction := Transaccion;
    SelectSQL.Assign(dmTablaAlbaranesCliente.sqlConsultarGridDetalles);
    InsertSQL.Assign(dmTablaAlbaranesCliente.sqlInsertarDetalles);
    ModifySQL.Assign(dmTablaAlbaranesCliente.sqlModificarDetalles);
    DeleteSQL.Assign(dmTablaAlbaranesCliente.sqlEliminarDetalles);
  end;

  try
    TablaDetallesMem.CopyStructure(TablaDetallesAlbaranes);
    TablaDetallesMem.FieldByName('CODIGOEMPRESA').Required := False;    
    TablaDetallesMem.FieldByName('CODIGOALBARAN').Required := False;
    TablaDetallesMem.FieldByName('NUMCONCEPTO').Required := False;
  except
    on E : EIBError do
      TratarExcepcion(E);
    on E : Exception do
      TratarExcepcion(E);
  end;

  dmTablaAlbaranesCliente.InicializarGridDetalles(gridDetalles);
  Paginas.ActivePage := pagCliente;
end;

destructor TfrAlbaranCliente.Destroy;
begin
  gridDetalles.DataSource := NIL;

  TablaDetallesMem.Close;
  TablaDetallesMem.Free;

  TablaAlbaranes.Close;
  TablaAlbaranes.UnPrepare;
  TablaAlbaranes.Free;

  TablaDetallesAlbaranes.Close;
  TablaDetallesAlbaranes.Unprepare;
  TablaDetallesAlbaranes.Free;

  inherited;
end;

procedure TfrAlbaranCliente.DtoDetalleSetText(Sender: TField;
  const Text: String);
begin
  try
    if EsCadenaVacia(Text) then
      Sender.AsString := '0'
    else begin
      ValidarDto(Text);
      Sender.AsString := Text;
    end;
    CalcularTotalDetalle;
    CalcularTotalAlbaran;
  except
    on E : EConvertError do
      VerMensaje(msgDtoNoValido);
    on E : EIBError do
      TratarExcepcion(E);
    on E : Exception do
      TratarExcepcion(E);
  end;
end;

function TfrAlbaranCliente.EliminarDatos: Boolean;
begin
  Result := False;
  try
    TablaAlbaranes.Delete;
    Commit;
    BorrarDetalles;
    TablaAlbaranes.Close;
    TablaDetallesAlbaranes.Close;
    TablaDetallesMem.Close;
    Result := True;
  except
    on E : EIBError do
    begin
      case E.IBErrorCode of
        isc_lock_conflict : VerMensajeFmt(msgAlbBloqueado, [Codigo.Field.AsString]);
        else
          TratarExcepcion(E);
      end;
    end;
    on E : Exception do
      TratarExcepcion(E);
  end;
end;

procedure TfrAlbaranCliente.FreeContenido;
var
  Contador : integer;
  ListaCodigos : TStringList;
begin
  if (ContenidoModal is TRdxFrameAlbaranes) then begin
    CodigoAlbaran := (ContenidoModal as TRdxFrameAlbaranes).CodigoAlbaran;
    ActivarModo;
  end;
  if (ContenidoModal is TRdxFrameArticulos) then
  begin
    ListaCodigos := (ContenidoModal as TRdxFrameArticulos).ListaArticulos;
    for Contador := 0 to ListaCodigos.Count - 1 do
    begin
      CodigoArticulo := ListaCodigos.Strings[Contador];
      bAnadirClick(Self);
    end;
    TablaDetallesMem.Cancel;
  end;

  if (ContenidoModal is TfrEditorDescripcion) then
  begin
    TablaDetallesMem.FieldByName('DESCRIPCION').AsString := (ContenidoModal as TfrEditorDescripcion).Texto;
    TablaDetallesMem.Post;
    TablaDetallesMem.Edit;
  end;

  if (ContenidoModal is TRdxFrameClientes) then
    CodigoCliente := (ContenidoModal as TRdxFrameClientes).CodigoCliente;
  if (ContenidoModal is TRdxFrameProvincias) then
    CodigoProvincia := (ContenidoModal as TRdxFrameProvincias).CodigoProvincia;
  if (ContenidoModal is TRdxFramePoblaciones) then begin
    CodigoProvincia := (ContenidoModal as TRdxFramePoblaciones).CodigoProvincia;
    CodigoPoblacion := (ContenidoModal as TRdxFramePoblaciones).CodigoPoblacion;
  end;
  inherited FreeContenido;
end;

procedure TfrAlbaranCliente.GridBotonCodigoArticuloClick(Sender: TObject);
begin
  TablaDetallesMem.Edit;
  ContenidoModal := TfrArticulos.Create(Self);
end;

function TfrAlbaranCliente.ModificarDatos: Boolean;
begin
  Result := False;
  try
    CalcularTotalAlbaran;
    TablaAlbaranes.Post;
    BorrarDetallesIB;
    SalvarDetalles;
    Commit;
    TablaAlbaranes.Close;
    TablaDetallesAlbaranes.Close;
    TablaDetallesMem.Close;
    Result := True;
  except
    on E : EIBError do
      TratarExcepcion(E);
    on E : Exception do
      TratarExcepcion(E);
  end;
end;

procedure TfrAlbaranCliente.PrecioDetalleSetText(Sender: TField;
  const Text: String);
begin
  if EsCadenaVacia(Text) then
    Sender.AsString := '0'
  else
    Sender.AsString := Text;
  CalcularTotalDetalle;
  CalcularTotalAlbaran;
end;

procedure TfrAlbaranCliente.SetCodigoArticulo(Value: Variant);
var
  DatosArticulo : TDatosArticulo;
begin
  if VarIsNull(Value) then
    exit;
  if Value = '' then
    exit;
  DatosArticulo := TDatosArticulo.Create;
  DatosArticulo.Codigo := Value;
  try
    if dmTablaArticulos.darDatosArticulo(DatosArticulo) then
    begin
      with TablaDetallesMem do
      begin
        Edit;
        FieldByName('CODIGOARTICULO').AsString := DatosArticulo.Codigo;
        FieldByName('DESCRIPCION').AsString := DatosArticulo.Descripcion;
        FieldByName('CANTIDAD').AsString := '1';
        FieldByName('UNIDADESMEDIDA').AsString := DatosArticulo.Unidadesmedida;
        FieldByName('PRECIOUNIDAD').AsString := DatosArticulo.Precio;
        FieldByName('TOTAL').AsString := DatosArticulo.Precio;
        Post;
      end;
      FCodigoArticulo := Value;
      CalcularTotalAlbaran;
    end
    else
      raise Exception.CreateFmt(msgArtCodArtNoExiste, [Value]);
  finally
    DatosArticulo.Free;
  end;
end;

procedure TfrAlbaranCliente.SetCodigoCliente(Value: Variant);
var
  DatosCliente : TDatosCliente;
begin
  if VarIsNull(Value) then
    exit;

  FCodigoCliente := Value;
  DatosCliente := TDatosCliente.Create;
  try
    DatosCliente.Codigo := FCodigoCliente;
    dmTablaClientes.darDatosCliente(DatosCliente);
    CodCliente.DataBinding.Field.AsString := DatosCliente.Codigo;
    NIF.Field.AsString := DatosCliente.Nifcif;
    Nombre.Field.AsString := DatosCliente.Nombre;
    PersonaContacto.Field.AsString := DatosCliente.PersonaContacto;
    Telefono.Field.AsString := DatosCliente.Telefono1;
    Fax.Field.AsString := DatosCliente.Fax;
    Calle.Field.AsString := DatosCliente.Calle;
    Numero.Field.AsString := DatosCliente.Numero;
    Piso.Field.AsString := DatosCliente.Piso;
    CodigoPostal.Field.AsString := DatosCliente.CodigoPostal;
    Poblacion.Field.AsString := DatosCliente.Poblacion;
    Provincia.Field.AsString := DatosCliente.Provincia;
    IVA.Field.AsString := DatosCliente.IVA;
    Descuento.Field.AsString := DatosCliente.Descuento;
    FCodigoProvincia := dmTablaProvincias.darCodigoProvincia(DatosCliente.Provincia);
    CalcularTotalAlbaran;
  finally
    DatosCliente.Free;
  end;
end;

procedure TfrAlbaranCliente.SetCodigoPoblacion(Value: Variant);
begin
  if (not VarIsNull(FCodigoPoblacion)) and (FCodigoPoblacion = Value) then
    exit;

  if (not VarIsNull(Value)) then
  begin
    FCodigoPoblacion := Value;
    Poblacion.Field.AsString := dmTablaPoblaciones.darNombrePoblacion(FCodigoProvincia, FCodigoPoblacion);
  end;
end;

procedure TfrAlbaranCliente.SetCodigoProvincia(Value: Variant);
begin
  if (not VarIsNull(FCodigoProvincia)) and (FCodigoProvincia = Value) then
    exit;

  if (not VarIsNull(Value)) then
  begin
    FCodigoProvincia := Value;
    Provincia.Field.AsString := dmTablaProvincias.darNombreProvincia(FCodigoProvincia);
  end;
end;

procedure TfrAlbaranCliente.VerModal;
begin
  if (ContenidoModal is TRdxFramePoblaciones) then
    (ContenidoModal as TRdxFramePoblaciones).CodigoProvincia := CodigoProvincia;
  if (ContenidoModal is TRdxFrameArticulos) then
    (ContenidoModal as TRdxFrameArticulos).CodigoArticulo := CodigoArticulo;
  if (ContenidoModal is TfrEditorDescripcion) then
    (ContenidoModal as TfrEditorDescripcion).Texto := TablaDetallesMem.FieldByName('DESCRIPCION').AsString;
  inherited;
end;

procedure TfrAlbaranCliente.CodigoButtonClick(Sender: TObject);
begin
  if (TratarCambios = IDCANCEL) then
    exit;
  { Esto es porque en modo 'Modificar' hacemos un cambio y pulsamos
    este botón se cierra la tabla y si en el frame hijo (el del grid) damos
    a cancelar, FCodigoAlbaran es NULL y da error al activar modo porque
    no se inicializa los parámetros de la sql. Lo hace BuscarAlbaran. }
  if not TablaAlbaranes.Active then
    BuscarAlbaran;
  ContenidoModal := TfrAlbaranesClientes.Create(Self);
end;

procedure TfrAlbaranCliente.CodigoExit(Sender: TObject);
begin
  if (Modo <> Anadir) or (Visible = false) then
    Exit;
  if EsCadenaVacia(Codigo.Text) then
    Codigo.Field.AsString := dmTablaAlbaranesCliente.darNuevoCodigo;
  if (dmTablaAlbaranesCliente.validarCodigo(Codigo.Text)) then
  begin
    Codigo.Field.asString := dmTablaAlbaranesCliente.formatearCodigo(Codigo.Text);
    if (dmTablaAlbaranesCliente.ExisteCodigo(EmpresaActiva.Codigo, Codigo.Text)) then begin
      VerMensajeFmt(msgAlbCodAlbRepetido, [Codigo.Text]);
      Codigo.SetFocus;
    end;
  end
  else begin
    VerMensajeFmt(msgAlbCodAlbIncorrecto, [Codigo.Text]);
    Codigo.SetFocus;
  end;
end;

procedure TfrAlbaranCliente.ProvinciaButtonClick(Sender: TObject);
begin
  CaptionModal := 'Lista de provincias';
  WidthModal := 280;
  HeightModal := 460;
  ContenidoModal := TfrProvincias.Create(Self);
end;

procedure TfrAlbaranCliente.PoblacionButtonClick(Sender: TObject);
begin
  if (VarIsNull(CodigoProvincia)) then begin
    VerMensaje(msgSinProvincia);
    Paginas.ActivePageIndex := 0;
    Provincia.SetFocus;
    Exit;
  end;
  CaptionModal := Format(msgListaPoblaciones, [dmTablaProvincias.darNombreProvincia(CodigoProvincia)]);
  WidthModal := 280;
  HeightModal := 460;
  ContenidoModal := TfrPoblaciones.Create(Self);
end;

procedure TfrAlbaranCliente.bAnadirClick(Sender: TObject);
begin
  try
    with TablaDetallesMem do
    begin
      DisableControls;
      Next;
      if EOF then
        Append
      else
        Insert;
      EnableControls;
    end;
    Paginas.ActivePage := pagContenido;
    gridDetalles.SetFocus;
  except
    on E : EIBError do
      TratarExcepcion(E);
    on E : Exception do
      TratarExcepcion(E);
  end;
end;

procedure TfrAlbaranCliente.bEliminarClick(Sender: TObject);
begin
  if (VerMensajePregunta(msgDeseaBorrar) <> IDYES) then
    Exit;

  if TablaDetallesMem.RecordCount = 0 then begin
    { Hacemos un cancel de la tabla por si el registro actual estuviera
      recien creado }
    TablaDetallesMem.Cancel;
    Exit
  end;
  try
    TablaDetallesMem.Delete;
  except
    on E : EIBError do
      TratarExcepcion(E);
    on E : Exception do
      TratarExcepcion(E);
  end;
  CalcularTotalAlbaran;
end;

procedure TfrAlbaranCliente.bEliminarTodoClick(Sender: TObject);
begin
  if (VerMensajePregunta(msgDeseaBorrarTodo) <> IDYES) then
    Exit;
  BorrarDetalles;
  CalcularTotalAlbaran;
end;

procedure TfrAlbaranCliente.bSalirClick(Sender: TObject);
begin
  try
    Rollback;
    CloseFrame;
  except
    on E : EIBError do
      TratarExcepcion(E);
    on E : Exception do
      TratarExcepcion(E);
  end;
end;

procedure TfrAlbaranCliente.bGuardarClick(Sender: TObject);
begin
  if (RealizarOperacion) then
    CloseFrame;
end;

procedure TfrAlbaranCliente.bCancelarClick(Sender: TObject);
begin
  if (TratarCambios = IDOK) then
    CloseFrame;
end;

procedure TfrAlbaranCliente.ActivarEventosCampos;
begin
  with TablaAlbaranes do
  begin
    FieldByName('IVA').OnSetText := IVASetText;
    FieldByName('DESCUENTO').OnSetText := DtoSetText;
  end;

  with TablaDetallesMem do
  begin
    FieldByName('CODIGOARTICULO').OnSetText := CodigoArticuloDetalleSetText;
    FieldByName('CANTIDAD').OnSetText := CantidadDetalleSetText;
    FieldByName('PRECIOUNIDAD').OnSetText := PrecioDetalleSetText;
    AfterDelete := DetalleAfterDelete;
  end;
end;

procedure TfrAlbaranCliente.DetalleAfterDelete(DataSet: TDataSet);
begin
  CalcularTotalAlbaran;
end;

procedure TfrAlbaranCliente.BorrarDetalles;
begin
  with TablaDetallesMem do
  begin
    DisableControls;
    EmptyTable;
    EnableControls;
  end;
end;

procedure TfrAlbaranCliente.BorrarDetallesIB;
begin
  with TablaDetallesAlbaranes do
  begin
    if IsEmpty then
      Exit;
    DisableControls;
    Last;
    while not BOF do
    begin
      Delete;
      Prior;
    end;
    if not IsEmpty then
      Delete;
    EnableControls;
  end;
end;

procedure TfrAlbaranCliente.CargarDetalles;
var
  NumeroCampo : Integer;
begin
  with TablaDetallesMem do
  begin
    if TablaDetallesAlbaranes.IsEmpty then
      Exit;
    DisableControls;
    TablaDetallesAlbaranes.First;
    while not TablaDetallesAlbaranes.EOF do
    begin
      Append;
      for NumeroCampo := 0 to TablaDetallesAlbaranes.FieldCount-1 do
        Fields[NumeroCampo].AsString := TablaDetallesAlbaranes.Fields[NumeroCampo].AsString;
      Post;
      TablaDetallesAlbaranes.Next;
    end;
    EnableControls;
  end;
end;

procedure TfrAlbaranCliente.SalvarDetalles;
var
  NumeroCampo : Integer;
  NumConcepto : Integer;
begin
  try
    with TablaDetallesMem do
    begin
      if IsEmpty then
        Exit;
      NumConcepto := 0;
      DisableControls;
      First;
      while not EOF do
      begin
        TablaDetallesAlbaranes.Append;
        for NumeroCampo := 0 to FieldCount-1 do
        begin
          if Fields[NumeroCampo].FieldName = 'CODIGOEMPRESA' then
            TablaDetallesAlbaranes.Fields[NumeroCampo].AsInteger := EmpresaActiva.Codigo
          else begin
            if Fields[NumeroCampo].FieldName = 'CODIGOALBARAN' then
              TablaDetallesAlbaranes.Fields[NumeroCampo].AsString := Codigo.Field.AsString
            else
              if Fields[NumeroCampo].FieldName = 'NUMCONCEPTO' then
                TablaDetallesAlbaranes.Fields[NumeroCampo].AsInteger := NumConcepto
              else
                TablaDetallesAlbaranes.Fields[NumeroCampo].AsString := Fields[NumeroCampo].AsString;
          end;
        end;
        TablaDetallesAlbaranes.Post;
        Next;
        NumConcepto := NumConcepto + 1;
      end;
      EnableControls;
    end;
  except
    on E : EIBError do
      TratarExcepcion(E);
    on E : Exception do
      TratarExcepcion(E);
  end;
end;

procedure TfrAlbaranCliente.DtoSetText(Sender: TField; const Text: String);
begin
  if EsCadenaVacia(Text) then
    Sender.AsString := '0'
  else begin
    ValidarDto(Text);
    Sender.AsString := Text;
  end;
  CalcularTotalAlbaran;
end;

procedure TfrAlbaranCliente.IVASetText(Sender: TField; const Text: String);
begin
  if EsCadenaVacia(Text) then
    Sender.AsString := '0'
  else begin
    ValidarIVA(Text);
    Sender.AsString := Text;
  end;
  CalcularTotalAlbaran;
end;

procedure TfrAlbaranCliente.GridBotonDescripcionClick(Sender: TObject);
begin
  TablaDetallesMem.Edit;
  WidthModal := 420;
  HeightModal := 435;
  ModoModal := Modo;
  ContenidoModal := TfrEditorDescripcion.Create(Self);
end;

procedure TfrAlbaranCliente.ProvinciaSetText(Sender: TField;
  const Text: String);
begin
  FCodigoProvincia := dmTablaProvincias.darCodigoProvincia(Text);
  Sender.AsString := Text;
end;

procedure TfrAlbaranCliente.CodClientePropertiesValidate(Sender: TObject;
  var DisplayValue: Variant; var ErrorText: TCaption; var Error: Boolean);
begin
  if not (Modo in [Anadir, Modificar]) then
    Exit;

  if EsCadenaVacia(DisplayValue) then
    Exit;

  if (dmTablaClientes.ValidarCodigo(DisplayValue)) then begin
    //Comprueba que le numero es lo sufucientemente pequeño para ser un entero
    if not EsInteger(DisplayValue) then
    begin
      VerMensajeFmt(msgCliCodCliIncorrecto,[DisplayValue]);
      DisplayValue := '0';
      CodCliente.SetFocus;
    end
    else
    begin
      DisplayValue := dmTablaClientes.FormatearCodigo(DisplayValue);
      if (dmTablaClientes.ExisteCodigo(DisplayValue)) then
        CodigoCliente := DisplayValue
      else begin
        VerMensajeFmt(msgCliCodCliNoExiste, [DisplayValue]);
        Paginas.ActivePageIndex := 0;
        CodCliente.SetFocus;
      end;
    end;
  end
  else begin
    VerMensajeFmt(msgCliCodCliIncorrecto, [CodCliente.Text]);
    Paginas.ActivePageIndex := 0;
    CodCliente.SetFocus;
  end;
end;

procedure TfrAlbaranCliente.CodClientePropertiesButtonClick(
  Sender: TObject; AButtonIndex: Integer);
begin
  ContenidoModal := TfrClientes.Create(Self);
end;

end.
