{
===============================================================================
  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.2
  Fecha versión actual: 24-09-2002
===============================================================================
  Modificaciones:

    Fecha         Comentarios
    ---------------------------------------------------------------------------
    07-04-2002    Se ha adaptado a una unica transacción.

    24-09-2002    Se producía una excepción si el cursos estaba en el código
                  del artículo, 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.
===============================================================================
}

unit Articulo;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls, ExtCtrls, Db, IBCustomDataSet, Mask, DBCtrls, Buttons, ToolEdit,
  IB, IBDatabase, RdxBarras, RdxBotones,  RdxCampos, RdxMemo, RdxComboBox,
  RdxCheckBox, RdxTitulos, RdxPaneles, Colores, Mensajes, Tipos,
  RdxFrameArticulos, cxControls, cxContainer, cxEdit, cxTextEdit,
  cxMaskEdit, cxButtonEdit, cxDBEdit, dxCntner, dxTL, dxDBCtrl, dxDBGrid,
  cxDropDownEdit, cxLookupEdit, cxDBLookupEdit, cxDBLookupComboBox,
  cxSpinEdit, Grids, DBGrids, RxMemDS, cxCurrencyEdit, ActnList, cxCalendar;

type
  TfrArticulo = class(TRdxFrameArticulos)
    brDoble: TRdxBarraInferior;
    brSimple: TRdxBarraInferior;
    bAceptarSimple: TRdxBoton;
    bAceptar: TRdxBoton;
    bCancelar: TRdxBoton;
    dsFabricantes: TDataSource;
    Titulo: TRdxPanelTituloOperacion;
    pnlScroll: TRdxScrollPanel;
    pnlDatos: TRdxPanel;
    eUnidades: TLabel;
    cDatos: TRdxCabecera;
    eCodigo: TLabel;
    eDescripcion: TLabel;
    eFamilia: TLabel;
    ePrecioEuros: TLabel;
    eObservaciones: TLabel;
    cbxUnidadesMedida: TRdxDBComboBox;
    Descripcion: TRdxDBEdit;
    Precio: TRdxDBEdit;
    cbxFamilia: TRdxDBComboBox;
    Observaciones: TRdxDBMemo;
    Codigo: TcxDBButtonEdit;
    dsArticulo: TDataSource;
    dsArticulosFabPro: TDataSource;
    pnlFabPro: TRdxPanel;
    cFabPro: TRdxCabecera;
    pnlListaPrecios: TRdxPanel;
    Panel1: TPanel;
    Panel2: TPanel;
    bEliminar: TRdxBoton;
    bEliminarTodo: TRdxBoton;
    ActionList1: TActionList;
    actEliminar: TAction;
    actEliminarTodo: TAction;
    pnlCamposFabPro: TPanel;
    grpCamposFabPro: TGroupBox;
    eFabricante: TLabel;
    eProveedor: TLabel;
    ePrecioPro: TLabel;
    eCodFab: TLabel;
    eCodPro: TLabel;
    Fabricante: TcxLookupComboBox;
    Proveedor: TcxButtonEdit;
    PrecioPro: TcxCurrencyEdit;
    CodFab: TcxTextEdit;
    CodPro: TcxTextEdit;
    bAgregar: TRdxBoton;
    ePrecioFinal: TLabel;
    eDescuento: TLabel;
    Descuento: TcxCurrencyEdit;
    e2PrecioFinal: TLabel;
    PrecioFinal: TcxCurrencyEdit;
    Label1: TLabel;
    FechaPrecio: TcxDateEdit;
    gridDetalles: TdxDBGrid;

    procedure bSalirClick(Sender: TObject);
    procedure bCancelarGuardarClick(Sender: TObject);
    procedure bAceptarClick(Sender: TObject);
    procedure PrecioSetText(Sender: TField; const Text: String);    
    procedure CodigoPropertiesButtonClick(Sender: TObject;
      AButtonIndex: Integer);
    procedure CodigoPropertiesValidate(Sender: TObject;
      var DisplayValue: Variant; var ErrorText: TCaption;
      var Error: Boolean);

    procedure ProveedorPropertiesButtonClick(Sender: TObject;
      AButtonIndex: Integer);
    procedure bAgragarClick(Sender: TObject);
    procedure TablaArticulosFabProMemAfterPost(DataSet: TDataSet);
    procedure actEliminarExecute(Sender: TObject);
    procedure actEliminarTodoExecute(Sender: TObject);
    procedure actEliminarUpdate(Sender: TObject);
    procedure PrecioProExit(Sender: TObject);
    procedure DescuentoExit(Sender: TObject);
    procedure PrecioFinalPropertiesChange(Sender: TObject);

  private
    FCodigoProveedor: Variant;
    TablaFabricantes : TIBDataSet;
    TablaArticulosFabProMem: TRxMemoryData;

    procedure SetCodigoProveedor (Value : Variant);
    procedure salvarDetalles;
    procedure cargarDetalles;
    procedure borrarDetalles;
    procedure borrarDetallesIB;
    procedure calcularPrecioFinal;
    procedure calcularPrecioFinalDetalle;

  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;
    procedure FreeContenido; override;
    procedure BuscarArticulo; override;
    function ComprobarDatos: Boolean; override;
    procedure PrecioDetalleSetText(Sender: TField; const Text: String);
    procedure DtoDetalleSetText(Sender: TField; const Text: String);
    property CodigoProveedor: Variant read FCodigoProveedor write SetCodigoProveedor;
  public
    constructor Create (AOwner : TComponent); override;
    destructor Destroy; override;
  published
    property TablaArticulos;
    property TablaArticulosFabPro;
    property CodigoArticulo;
  end;

var
  frArticulo: TfrArticulo;

implementation

{$R *.DFM}
uses
  BaseDatos, TablaArticulos, TablaArticulosAlmacen, Articulos,
  TablaFamilias, TablaUnidadesMedida, StrFunc, Configuracion,
  TablaPedidosProveedor,Excepciones, IBErrorCodes, RdxEmpresaActiva,
  Literales, NumFunc, TablaFabricantes, TablaProveedores, RdxFrameProveedores,
  Proveedores, Constantes;

constructor TfrArticulo.Create (AOwner : TComponent);
begin
  inherited Create(AOwner);
  FCodigoProveedor:= Null;
  Entidad := entArticulo;
  ConfigurarFrame(Self, Self.Entidad);

  BaseDatos := dmBaseDatos.BD;
  Transaccion := dmBaseDatos.Transaccion;
  TablaArticulos := TIBDataSet.Create(Self);
  dsArticulo.DataSet := TablaArticulos;
  with TablaArticulos do
  begin
    Database := BaseDatos;
    Transaction := Transaccion;
    SelectSQL.Assign(dmTablaArticulos.sqlConsultar);
    InsertSQL.Assign(dmTablaArticulos.sqlInsertar);
    ModifySQL.Assign(dmTablaArticulos.sqlModificar);
    DeleteSQL.Assign(dmTablaArticulos.sqlEliminar);
    RefreshSQL.Assign(dmTablaArticulos.sqlConsultar);
  end;

  TablaArticulosFabPro := TIBDataSet.Create(Self);
  with TablaArticulosFabPro do
  begin
    Database := BaseDatos;
    Transaction := Transaccion;
    SelectSQL.Assign(dmTablaArticulos.sqlConsultarArtFabPro);
    InsertSQL.Assign(dmTablaArticulos.sqlInsertarArtFabPro);
    ModifySQL.Assign(dmTablaArticulos.sqlModificarArtFabPro);
    DeleteSQL.Assign(dmTablaArticulos.sqlEliminarArtFabPro);
    RefreshSQL.Assign(dmTablaArticulos.sqlConsultarArtFabPro);
  end;

  TablaArticulosFabProMem := TRxMemoryData.Create(Self);
  TablaArticulosFabProMem.CopyStructure(TablaArticulosFabPro);

  dmTablaArticulos.InicializarGridArticulosFabProDetalles(gridDetalles);
  dmTablaArticulos.InicializarTablaArticulosFabPro(@TablaArticulosFabProMem);
  dsArticulosFabPro.DataSet := TablaArticulosFabProMem;
  TablaArticulosFabProMem.Open;

  TablaFabricantes := TIBDataSet.Create(Self);
  dsFabricantes.DataSet := TablaFabricantes;
  with TablaFabricantes do
  begin
    Database := BaseDatos;
    Transaction := Transaccion;
    SelectSQL.Assign(dmTablaFabricantes.sqlConsultar);
    RefreshSQL.Assign(dmTablaFabricantes.sqlConsultar);
    Open;
  end;

  cbxFamilia.Items := dmTablaFamilias.darFamilias;
  cbxUnidadesMedida.Items := dmTablaUnidadesMedida.darUnidadesMedida;

  FechaPrecio.Date := dmBaseDatos.DarFecha;
  PrecioPro.Properties.DisplayFormat := DISPLAY_EUROS2;
  Descuento.Properties.DisplayFormat := DISPLAY_DTO;
  PrecioFinal.Properties.DisplayFormat := DISPLAY_EUROS2;  
end;

destructor TfrArticulo.Destroy;
begin
  TablaArticulos.Close;
  TablaArticulos.UnPrepare;
  TablaArticulos.Free;

  TablaArticulosFabPro.Close;
  TablaArticulosFabPro.UnPrepare;
  TablaArticulosFabPro.Free;

  TablaArticulosFabProMem.Close;
  TablaArticulosFabProMem.Free;

  TablaFabricantes.Close;
  TablaFabricantes.UnPrepare;
  TablaFabricantes.Free;

  inherited;
end;

procedure TfrArticulo.BuscarArticulo;
begin
  if Transaccion = NIL then
    exit;

  try
    TablaArticulos.Close;
    TablaArticulosFabPro.Close;
    TablaArticulosFabProMem.Close;

    // Buscar la fila a tratar si es necesario
    if not VarIsNull(CodigoArticulo) then begin
        TablaArticulos.Params.ByName('CODIGO').AsString := CodigoArticulo;
        TablaArticulosFabPro.Params.ByName('CODIGOARTICULO').AsString := CodigoArticulo;
    end;

    TablaArticulos.Prepare;
    TablaArticulos.Open;
    dmTablaArticulos.InicializarTablaArticulos(@TablaArticulos);

    TablaArticulosFabPro.Prepare;
    TablaArticulosFabPro.Open;
    dmTablaArticulos.InicializarTablaArticulosFabPro(@TablaArticulosFabPro);
    CodFab.Properties.MaxLength := TablaArticulosFabPro.FieldByName('CODARTFABRICANTE').Size;
    CodPro.Properties.MaxLength := TablaArticulosFabPro.FieldByName('CODARTPROVEEDOR').Size;

    TablaArticulosFabProMem.Open;
    cargarDetalles;

  except
    on E : EIBError do begin
      VerMensaje(E.Message);
    end;
    on E : EDatabaseError do begin
      VerMensaje(E.Message);
    end;
  end;
end;

procedure TfrArticulo.FreeContenido;
begin
  if (ContenidoModal is TRdxFrameArticulos) then
  begin
    CodigoArticulo := (ContenidoModal as TRdxFrameArticulos).CodigoArticulo;
    ActivarModo;
  end;

  if (ContenidoModal is TRdxFrameProveedores) then
  begin
    CodigoProveedor := (ContenidoModal as TRdxFrameProveedores).CodigoProveedor;
  end;

  inherited FreeContenido;
end;

function TfrArticulo.AnadirDatos : Boolean;
begin
  Result := False;
  try
    TablaArticulos.Post;
    TablaArticulos.ApplyUpdates;
    dmTablaArticulos.incrementarCodigo;
    FCodigoArticulo := TablaArticulos.FieldByName('CODIGO').AsString;

    salvarDetalles;
    Commit;

    TablaArticulos.CachedUpdates := False;
    TablaArticulos.Close;
    TablaArticulosFabPro.Close;
    TablaArticulosFabProMem.Close;

    Result := True;
  except
    on E : EIBError do begin
      if E.IBErrorCode = isc_unique_key_violation then begin
        VerMensajeFmt(msgArtCodArtRepetido, [Codigo.DataBinding.Field.AsString]);
        TablaArticulos.Edit;
      end
      else
        TratarExcepcion(E);
    end;
    on E : Exception do
      TratarExcepcion(E);
  end;
end;

function TfrArticulo.ModificarDatos : Boolean;
begin
  Result := False;
  try
    TablaArticulos.Post;

    BorrarDetallesIB;
    SalvarDetalles;
    Commit;

    TablaArticulos.Close;
    TablaArticulosFabPro.Close;
    TablaArticulosFabProMem.Close;

    Result := True;
  except
    on E : EIBError do
      TratarExcepcion(E);
    on E : Exception do
      TratarExcepcion(E);
  end;
end;

function TfrArticulo.EliminarDatos : Boolean;
begin
  Result := False;
  try
    TablaArticulos.Delete;
    
    Commit;

    TablaArticulos.Close;
    TablaArticulosFabPro.Close;
    TablaArticulosFabProMem.Close;

    Result := True;
  except
    on E : EIBError do
    begin
      case E.IBErrorCode of
        isc_lock_conflict : VerMensajeFmt(msgArtBloqueado, [Codigo.DataBinding.Field.AsString]);
        else
          TratarExcepcion(E);
      end;
    end;
    on E : Exception do
      TratarExcepcion(E);
  end;
end;

procedure TfrArticulo.activarModoAnadir;
begin
  dsArticulo.AutoEdit := True;

  dsArticulosFabPro.AutoEdit := False;
  TablaArticulosFabProMem.FieldByName('DESCUENTO').OnSetText := Nil;
  TablaArticulosFabProMem.FieldByName('PRECIO').OnSetText := Nil;

  Codigo.Properties.Buttons[0].Visible := False;
  Codigo.Properties.ReadOnly := False;
  Codigo.Properties.OnValidate := CodigoPropertiesValidate;

  pnlCamposFabPro.Visible := True;

  try
    TablaArticulos.Close;
    TablaArticulos.CachedUpdates := True;
    TablaArticulos.Open;
    dmTablaArticulos.InicializarTablaArticulos(@TablaArticulos);
    TablaArticulos.FieldByName('PRECIO').OnSetText := PrecioSetText;

    TablaArticulosFabPro.Open;
    dmTablaArticulos.InicializarTablaArticulosFabPro(@TablaArticulosFabPro);
    CodFab.Properties.MaxLength := TablaArticulosFabPro.FieldByName('CODARTFABRICANTE').Size;
    CodPro.Properties.MaxLength := TablaArticulosFabPro.FieldByName('CODARTPROVEEDOR').Size;

    TablaArticulos.Insert;
    Codigo.DataBinding.Field.asString := dmTablaArticulos.DarNuevoCodigo;

    borrarDetalles;
    TablaArticulosFabProMem.AfterPost := TablaArticulosFabProMemAfterPost;

    Visible := True;
  except
    on E : EIBError do
      TratarExcepcion(E);
    on E : Exception do
      TratarExcepcion(E);
  end;
end;

procedure TfrArticulo.activarModoModificar;
begin
  dsArticulo.AutoEdit := True;

  dsArticulosFabPro.AutoEdit := True;
  TablaArticulosFabProMem.FieldByName('DESCUENTO').OnSetText := DtoDetalleSetText;
  TablaArticulosFabProMem.FieldByName('PRECIO').OnSetText := PrecioDetalleSetText;

  Codigo.Properties.Buttons[0].Visible := True;
  Codigo.Properties.ReadOnly := True;
  Codigo.Properties.OnValidate := nil;

  pnlCamposFabPro.Visible := True;

  try
    TablaArticulos.FieldByName('PRECIO').OnSetText := PrecioSetText;
    TablaArticulos.Open;
    if TablaArticulos.RecordCount = 0 then
    begin
      VerMensajeFmt(msgArtNoExisteArt, [CodigoArticulo]);
      CancelarModificar;
      CloseFrame;
      Exit;
    end;
    TablaArticulos.Edit;
    TablaArticulos.Post;
    TablaArticulos.Edit;

    TablaArticulosFabProMem.AfterPost := TablaArticulosFabProMemAfterPost;
    Visible := True;
  except
    on E : EIBError do
    begin
      case E.IBErrorCode of
        isc_lock_conflict : begin
                              VerMensajeFmt(msgArtBloqueado, [CodigoArticulo]);
                              CancelarModificar;
                              CloseFrame;
                              Exit;
                            end
        else
          TratarExcepcion(E);
      end;
    end;
    on E : Exception do
      TratarExcepcion(E);
  end;
end;

procedure TfrArticulo.activarModoConsultar;
begin
  dsArticulo.AutoEdit := False;

  dsArticulosFabPro.AutoEdit := False;
  TablaArticulosFabProMem.FieldByName('DESCUENTO').OnSetText := Nil;
  TablaArticulosFabProMem.FieldByName('PRECIO').OnSetText := Nil;

  Codigo.Properties.Buttons[0].Visible := True;
  Codigo.Properties.OnValidate := nil;

  pnlCamposFabPro.Visible := False;

  try
    TablaArticulos.Open;
    if TablaArticulos.RecordCount = 0 then
    begin
      VerMensajeFmt(msgArtNoExisteArt, [CodigoArticulo]);
      CloseFrame;
      Exit;
    end;
    TablaArticulos.Cancel;

    TablaArticulosFabProMem.AfterPost := Nil;
    Visible := True;
  except
    on E : EIBError do
      TratarExcepcion(E);
    on E : Exception do
      TratarExcepcion(E);
  end;
end;

procedure TfrArticulo.activarModoEliminar;
begin
  dsArticulo.AutoEdit := False;

  dsArticulosFabPro.AutoEdit := False;
  TablaArticulosFabProMem.FieldByName('DESCUENTO').OnSetText := Nil;
  TablaArticulosFabProMem.FieldByName('PRECIO').OnSetText := Nil;

  Codigo.Properties.Buttons[0].Visible := True;
  Codigo.Properties.OnValidate := nil;

  pnlCamposFabPro.Visible := False;

  try
    TablaArticulos.Open;
    if TablaArticulos.RecordCount = 0 then
    begin
      VerMensajeFmt(msgArtNoExisteArt, [CodigoArticulo]);
      CancelarEliminar;
      CloseFrame;
      Exit;
    end;
    TablaArticulos.Cancel;

    TablaArticulosFabProMem.AfterPost := Nil;
    Visible := True;
  except
    on E : EIBError do
      TratarExcepcion(E);
    on E : Exception do
      TratarExcepcion(E);
  end;
end;

procedure TfrArticulo.bAceptarClick(Sender: TObject);
begin
  if (RealizarOperacion) then
    CloseFrame;
end;

function TfrArticulo.CancelarAnadir: Boolean;
begin
  Result := False;
  try
    TablaArticulos.CancelUpdates;
    RollBack;

    TablaArticulos.CachedUpdates := False;
    TablaArticulos.Close;
    TablaArticulosFabPro.Close;
    TablaArticulosFabProMem.Close;

    Result := True;
  except
    on E : EIBError do
      TratarExcepcion(E);
    on E : Exception do
      TratarExcepcion(E);
  end;
end;

function TfrArticulo.CancelarEliminar: Boolean;
begin
  Result := False;
  try
    RollBack;

    TablaArticulos.Close;
    TablaArticulosFabPro.Close;
    TablaArticulosFabProMem.Close;

    Result := True;
  except
    on E : EIBError do
      TratarExcepcion(E);
    on E : Exception do
      TratarExcepcion(E);
  end;
end;

function TfrArticulo.CancelarModificar: Boolean;
begin
  Result := False;
  try
    RollBack;

    TablaArticulos.Close;
    TablaArticulosFabPro.Close;
    TablaArticulosFabProMem.Close;

    Result := True;
  except
    on E : EIBError do
      TratarExcepcion(E);
    on E : Exception do
      TratarExcepcion(E);
  end;
end;

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

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

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

  if EsCadenaVacia(Descripcion.Text) then
  begin
    VerMensaje(msgArtFaltaDesArt);
    Descripcion.SetFocus;
    Exit;
  end;

  if Modo = Eliminar then
  begin
    if dmTablaArticulosAlmacen.ExisteArticuloEnAlmacen(EmpresaActiva.Codigo, CodigoArticulo) then
    begin
      VerMensaje(msgArtExisteArtEnAlm);
      Exit;
    end;
    if dmTablaPedidosProveedor.existeArticuloEnPedido(EmpresaActiva.Codigo, CodigoArticulo) then
    begin
      VerMensaje(msgArtExisteArtEnPed);
      Exit;
    end;
  end;
  Result := True;
end;

procedure TfrArticulo.CodigoPropertiesButtonClick(Sender: TObject;
  AButtonIndex: Integer);
begin
  inherited;
  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, FCodigoArticulo es NULL y da error al activar modo porque
    no se inicializa los parámetros de la sql. Lo hace BuscarArticulo. }
  if not TablaArticulos.Active then
    BuscarArticulo;

  ContenidoModal := TfrArticulos.Create(Self);
end;

procedure TfrArticulo.CodigoPropertiesValidate(Sender: TObject;
  var DisplayValue: Variant; var ErrorText: TCaption; var Error: Boolean);
begin
  if (Modo <> Anadir) or (Visible = false) then
    exit;

  if EsCadenaVacia(DisplayValue) then
    DisplayValue := dmTablaArticulos.darNuevoCodigo;

  if (dmTablaArticulos.validarCodigo(DisplayValue)) then begin
    //Comprueba que le numero es lo sufucientemente pequeño para ser un entero
    if not EsInteger(DisplayValue) then
    begin
      VerMensajeFmt(msgArtCodArtIncorrecto,[DisplayValue]);
      Codigo.SetFocus;
    end
    else
    begin
      DisplayValue := dmTablaArticulos.formatearCodigo(DisplayValue);
      if (dmTablaArticulos.existeArticulo(DisplayValue)) then begin
        VerMensajeFmt(msgArtCodArtRepetido, [DisplayValue]);
        Codigo.SetFocus;
      end;
    end;
  end
  else begin
    VerMensajeFmt(msgArtCodArtIncorrecto, [DisplayValue]);
    Codigo.SetFocus;
  end;
end;

procedure TfrArticulo.bAgragarClick(Sender: TObject);
var
prueba: String;
begin
    if esCadenaVacia(Fabricante.Text)
      or esCadenaVacia(CodFab.Text)
      or esCadenaVacia(Proveedor.Text)
      or esCadenaVacia(CodPro.Text)
      or esCadenaVacia(PrecioPro.Text) then
    begin
      VerMensaje('Debe rellenar todos los campos para poder agregar un nuevo precio');
      Exit;
    end;

    TablaArticulosFabProMem.Insert;
    TablaArticulosFabProMem.FieldByName('CODIGOARTICULO').AsString := Codigo.Text;
    TablaArticulosFabProMem.FieldByName('CODIGOFABRICANTE').AsString := Fabricante.EditValue;
    TablaArticulosFabProMem.FieldByName('FABRICANTE').AsString := Fabricante.Text;
    TablaArticulosFabProMem.FieldByName('CODIGOPROVEEDOR').AsString := CodigoProveedor;
    TablaArticulosFabProMem.FieldByName('PROVEEDOR').AsString := Proveedor.Text;
    TablaArticulosFabProMem.FieldByName('CODARTFABRICANTE').AsString := CodFab.Text;
    TablaArticulosFabProMem.FieldByName('CODARTPROVEEDOR').AsString := CodPro.Text;
    TablaArticulosFabProMem.FieldByName('FECHAPRECIO').AsDateTime := FechaPrecio.Date;
    TablaArticulosFabProMem.FieldByName('PRECIO').AsFloat := PrecioPro.Value;
    TablaArticulosFabProMem.FieldByName('DESCUENTO').AsFloat := Descuento.Value;
    TablaArticulosFabProMem.FieldByName('PRECIOFINAL').AsFloat := PrecioFinal.Value;
    TablaArticulosFabProMem.Post;

    Fabricante.Text := '';
    Proveedor.Text := '';
    CodFab.Text := '';
    CodPro.Text := '';
    PrecioPro.Value := 0;
    Descuento.Value := 0;
    PrecioFinal.Value := 0;    
    CodigoProveedor := '';

    TablaArticulos.Edit;
    //Para que se trague siempre que ha habido cambios
    TablaArticulos.FieldByName('CODIGO').AsString := TablaArticulos.FieldByName('CODIGO').AsString;
end;

procedure TfrArticulo.ProveedorPropertiesButtonClick(Sender: TObject;
  AButtonIndex: Integer);
begin
  ContenidoModal := TfrProveedores.Create(Self);
end;

procedure TfrArticulo.SetCodigoProveedor(Value: Variant);
var
  lsProveedor : TDatosProveedor;
begin
  if varIsNull(Value) then
     exit;

  if (FCodigoProveedor <> Value) then
  begin
        FCodigoProveedor := Value;
        lsProveedor := TDatosProveedor.Create;
        lsProveedor.Codigo := FCodigoProveedor;
        dmTablaProveedores.DarDatosProveedor(lsProveedor);
        Proveedor.Text := lsProveedor.Nombre;
        lsProveedor.Free;
  end;
end;

procedure TfrArticulo.salvarDetalles;
var
  NumeroCampo : Integer;
begin
  try
    with TablaArticulosFabProMem do
    begin
      if IsEmpty then
        Exit;

      DisableControls;
      First;
      while not EOF do
      begin
        TablaArticulosFabPro.Append;
        for NumeroCampo := 0 to FieldCount-1 do
        begin
          if Fields[NumeroCampo].FieldName = 'CODIGOARTICULO' then
            TablaArticulosFabPro.Fields[NumeroCampo].AsString := TablaArticulos.FieldByName('CODIGO').AsString
          else
            TablaArticulosFabPro.Fields[NumeroCampo].AsString := Fields[NumeroCampo].AsString;
        end;
        TablaArticulosFabPro.Post;
        Next;
      end;
      EnableControls;
    end
  except
    on E : EIBError do begin
      if E.IBErrorCode = isc_unique_key_violation then
      begin
        TablaArticulosFabPro.Delete;
        TablaArticulosFabProMem.EnableControls;
      end;
      raise EIBError.Create(E.SQLCode, E.IBErrorCode, E.Message);
    end;
  end;
end;

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

procedure TfrArticulo.borrarDetallesIB;
begin
  with TablaArticulosFabPro 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 TfrArticulo.borrarDetalles;
begin
  with TablaArticulosFabProMem do
  begin
    DisableControls;
    EmptyTable;
    EnableControls;
  end;
end;

procedure TfrArticulo.TablaArticulosFabProMemAfterPost(DataSet: TDataSet);
var
    lsCodigoArt, lsCodigoFab, lsCodigoPro : Variant;
    FBookmarkAux : string;
    lbSemaforo: Boolean;
begin
  lsCodigoArt := TablaArticulosFabProMem.FieldByName('CODIGOARTICULO').AsString;
  lsCodigoFab := TablaArticulosFabProMem.FieldByName('CODIGOFABRICANTE').AsString;
  lsCodigoPro := TablaArticulosFabProMem.FieldByName('CODIGOPROVEEDOR').AsString;

  with TablaArticulosFabProMem do
  begin
    if IsEmpty then
      Exit;

    DisableControls;
    FBookmarkAux := Bookmark;
    lbSemaforo := False;
    First;
    while not EOF do
    begin
      if  (FieldByName('CODIGOARTICULO').AsString = lsCodigoArt)
      and (FieldByName('CODIGOFABRICANTE').AsString = lsCodigoFab)
      and (FieldByName('CODIGOPROVEEDOR').AsString = lsCodigoPro)
      and (FBookmarkAux <> Bookmark) then
      begin
          verMensaje('Ya ha introducido un precio de ese proveedor para este artículo');
          lbSemaforo := True;
          Break;
      end;
      Next;
    end;
    Bookmark := FBookmarkAux;
    if lbSemaforo then
       Delete;
    EnableControls;
  end;
end;

procedure TfrArticulo.actEliminarExecute(Sender: TObject);
begin
    TablaArticulosFabProMem.Delete;
    TablaArticulosFabPro.Edit;

    TablaArticulos.Edit;
    //Para que se trague siempre que ha habido cambios
    TablaArticulos.FieldByName('CODIGO').AsString := TablaArticulos.FieldByName('CODIGO').AsString;
end;

procedure TfrArticulo.actEliminarTodoExecute(Sender: TObject);
begin
  with TablaArticulosFabProMem do
  begin
    if IsEmpty then
      Exit;
    DisableControls;
    Last;
    while not BOF do
    begin
      Delete;
      Prior;
    end;
    if not IsEmpty then
      Delete;
    EnableControls;
  end;

  TablaArticulos.Edit;
  //Para que se trague siempre que ha habido cambios
  TablaArticulos.FieldByName('CODIGO').AsString := TablaArticulos.FieldByName('CODIGO').AsString;
end;

procedure TfrArticulo.actEliminarUpdate(Sender: TObject);
begin
    (Sender as TAction).Enabled := (Modo in [Anadir, Modificar]);
end;

procedure TfrArticulo.calcularPrecioFinal;
var
  liPrecioFinal: Double;
begin
  liPrecioFinal := PrecioPro.Value - ((PrecioPro.Value * Descuento.Value) / 100);
  PrecioFinal.Value := liPrecioFinal;
end;

procedure TfrArticulo.PrecioProExit(Sender: TObject);
begin
  calcularPrecioFinal;
end;

procedure TfrArticulo.DescuentoExit(Sender: TObject);
begin
  calcularPrecioFinal;
end;

procedure TfrArticulo.DtoDetalleSetText(Sender: TField;
  const Text: String);
begin
  try
    if Length(Text) = 0 then
    begin
      Sender.AsString := '0';
      Exit;
    end;

    if (StrToFloat(Text) < 0) or (StrToFloat(Text) > 100) then
      raise Exception.Create(msgDtoNoValido);

    Sender.AsString := Text;
    calcularPrecioFinalDetalle;

  except
    on E : EConvertError do
      VerMensaje(msgDtoNoValido);
    on E : EDataBaseError do
      VerMensaje(msgDtoNoValido);
  end;
end;

procedure TfrArticulo.calcularPrecioFinalDetalle;
var
  liPrecioFinal: Double;
  liDescuento: Double;
begin
  liPrecioFinal:= TablaArticulosFabProMem.FieldByName('PRECIO').AsFloat;
  liDescuento := TablaArticulosFabProMem.FieldByName('DESCUENTO').AsFloat;

  liPrecioFinal := liPrecioFinal - ((liPrecioFinal * liDescuento) / 100);
  TablaArticulosFabProMem.FieldByName('PRECIOFINAL').AsFloat := liPrecioFinal;
end;

procedure TfrArticulo.PrecioDetalleSetText(Sender: TField;
  const Text: String);
begin
  try
    if Length(Text) = 0 then
    begin
      Sender.AsString := '0';
      Exit;
    end;

    Sender.AsString := Text;
    calcularPrecioFinalDetalle;

  except
    on E : EConvertError do
      VerMensaje(msgPrecioNoValido);
    on E : EDataBaseError do
      VerMensaje(msgPrecioNoValido);
  end;
end;

procedure TfrArticulo.PrecioSetText(Sender: TField; const Text: String);
begin
  try
    if Length(Text) = 0 then
    begin
      Sender.AsString := '0';
      Exit;
    end;

    Sender.AsString := Text
  except
    on E : EConvertError do
      VerMensaje(msgPrecioNoValido);
    on E : EDataBaseError do
      VerMensaje(msgPrecioNoValido);
  end;
end;

procedure TfrArticulo.PrecioFinalPropertiesChange(Sender: TObject);
begin
  e2PrecioFinal.Caption := PrecioFinal.Text;
end;

end.
