unit frm_ArticulosClientesEan;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, System.UITypes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.Buttons, Vcl.Grids, Vcl.DBGrids,
  Vcl.ExtCtrls, Vcl.ComCtrls, Data.DB, FireDAC.Comp.Client, FireDAC.Stan.Intf, FireDAC.Stan.Option,
  FireDAC.Stan.Param, FireDAC.Stan.Error, FireDAC.DatS, FireDAC.Phys.Intf, FireDAC.DApt.Intf,
  FireDAC.Stan.Async, FireDAC.DApt, uAppTheme, uRichEditHtmlHelper;

type
  TfrmArticulosClientesEan = class(TForm)
    pnlTop: TPanel;
    lblArticulo: TLabel;
    lblArticuloNombre: TLabel;
    pnlBottom: TPanel;
    btnCerrar: TBitBtn;
    pnlListContainer: TPanel;
    dbgClientesEan: TDBGrid;
    pnlListActions: TPanel;
    btnAnadir: TSpeedButton;
    btnEliminar: TSpeedButton;
    pnlFicha: TPanel;
    lblFichaTitulo: TLabel;
    lblFichaCliente: TLabel;
    chkFichaActivo: TCheckBox;
    lblFichaEan13: TLabel;
    edtFichaEan13: TEdit;
    lblFichaDun14: TLabel;
    edtFichaDun14: TEdit;
    lblFichaRefCli: TLabel;
    edtFichaRefCli: TEdit;
    lblFichaDescEtiqueta: TLabel;
    btnBoldDesc: TSpeedButton;
    btnUnderlineDesc: TSpeedButton;
    btnSourceDesc: TSpeedButton;
    lblTamanoDesc: TLabel;
    cbFontSizeDesc: TComboBox;
    btnCopiarDescArticulo: TBitBtn;
    redtFichaDescripcion: TRichEdit;
    lblFichaIngredientes: TLabel;
    btnBoldIngredientes: TSpeedButton;
    btnUnderlineIngredientes: TSpeedButton;
    btnSourceIngredientes: TSpeedButton;
    btnCopiarIngrArticulo: TBitBtn;
    redtFichaIngredientes: TRichEdit;
    btnGuardarFicha: TBitBtn;
    btnCancelarFicha: TBitBtn;
    dsClientesEan: TDataSource;
    qryClientesEan: TFDQuery;
    procedure FormShow(Sender: TObject);
    procedure btnCerrarClick(Sender: TObject);
    procedure btnAnadirClick(Sender: TObject);
    procedure btnEliminarClick(Sender: TObject);
    procedure dsClientesEanDataChange(Sender: TObject; Field: TField);
    procedure btnGuardarFichaClick(Sender: TObject);
    procedure btnCancelarFichaClick(Sender: TObject);
    procedure btnBoldDescClick(Sender: TObject);
    procedure btnUnderlineDescClick(Sender: TObject);
    procedure btnSourceDescClick(Sender: TObject);
    procedure cbFontSizeDescChange(Sender: TObject);
    procedure redtFichaDescripcionSelectionChange(Sender: TObject);
    procedure btnBoldIngredientesClick(Sender: TObject);
    procedure btnUnderlineIngredientesClick(Sender: TObject);
    procedure btnSourceIngredientesClick(Sender: TObject);
    procedure redtFichaIngredientesSelectionChange(Sender: TObject);
    procedure btnCopiarDescArticuloClick(Sender: TObject);
    procedure btnCopiarIngrArticuloClick(Sender: TObject);
  private
    FArticuloId: Integer;
    FArticuloDesc: string;
    FArticuloEan: string;
    FArticuloDescEtiqueta: string;
    FArticuloIngredientes: string;
    FLoadingFicha: Boolean;
    procedure LoadData(ASelectedId: Integer = 0);
    procedure CargarFichaDesdeRegistro;
    procedure LimpiarFicha;
  public
    property ArticuloId: Integer read FArticuloId write FArticuloId;
    property ArticuloDesc: string read FArticuloDesc write FArticuloDesc;
    property ArticuloEan: string read FArticuloEan write FArticuloEan;
    property ArticuloDescEtiqueta: string read FArticuloDescEtiqueta write FArticuloDescEtiqueta;
    property ArticuloIngredientes: string read FArticuloIngredientes write FArticuloIngredientes;
  end;

var
  frmArticulosClientesEan: TfrmArticulosClientesEan;

implementation

uses
  dmg_Main, uDbErrorHandler, frm_SelectCliente, uDbParamsHelper;

{$R *.dfm}

procedure TfrmArticulosClientesEan.FormShow(Sender: TObject);
begin
  TAppTheme.ApplyToForm(Self);
  lblArticuloNombre.Caption := Format('[%d] %s', [FArticuloId, FArticuloDesc]);

  btnBoldDesc.Tag := 999;
  btnUnderlineDesc.Tag := 999;
  btnSourceDesc.Tag := 999;
  lblTamanoDesc.Tag := 999;
  cbFontSizeDesc.Tag := 999;
  btnCopiarDescArticulo.Tag := 999;
  btnBoldIngredientes.Tag := 999;
  btnUnderlineIngredientes.Tag := 999;
  btnSourceIngredientes.Tag := 999;
  btnCopiarIngrArticulo.Tag := 999;

  cbFontSizeDesc.Items.Clear;
  for var i := 5 to 30 do
    cbFontSizeDesc.Items.Add(IntToStr(i));
  cbFontSizeDesc.ItemIndex := cbFontSizeDesc.Items.IndexOf(IntToStr(redtFichaDescripcion.Font.Size));
  if cbFontSizeDesc.ItemIndex < 0 then
    cbFontSizeDesc.ItemIndex := cbFontSizeDesc.Items.IndexOf('10');

  qryClientesEan.Connection := dmgMain.dbConn;
  qryClientesEan.CachedUpdates := False;

  qryClientesEan.SQL.Text :=
    'SELECT ca.id, ca.ide, ca.id_cliente, ca.id_articulo, ' +
    '       COALESCE(NULLIF(c.nombre_comercial, ''''), c.nombre_fiscal) as cliente_nombre, ' +
    '       ca.ean13, ca.dun14, ca.codigo_articulo_cliente, ca.descripcion_cliente, ' +
    '       ca.ingredientes, ca.activo ' +
    'FROM ge_clientes_articulos ca ' +
    'LEFT JOIN ge_clientes c ON ca.id_cliente = c.id ' +
    'WHERE ca.id_articulo = :articulo_id ' +
    'ORDER BY cliente_nombre ASC';

  LoadData;

  dbgClientesEan.Columns.Clear;
  with dbgClientesEan.Columns.Add do
  begin
    FieldName := 'cliente_nombre';
    Title.Caption := 'Cliente / Distribuidor';
    Width := 260;
  end;
  with dbgClientesEan.Columns.Add do
  begin
    FieldName := 'ean13';
    Title.Caption := 'EAN-13 (Unidad)';
    Width := 130;
  end;
  with dbgClientesEan.Columns.Add do
  begin
    FieldName := 'dun14';
    Title.Caption := 'DUN-14 (Caja)';
    Width := 130;
  end;
  with dbgClientesEan.Columns.Add do
  begin
    FieldName := 'codigo_articulo_cliente';
    Title.Caption := 'Ref./Cód. Cliente';
    Width := 120;
  end;
  with dbgClientesEan.Columns.Add do
  begin
    FieldName := 'activo';
    Title.Caption := 'Activo';
    Width := 50;
    Alignment := taCenter;
  end;

  CargarFichaDesdeRegistro;
end;

procedure TfrmArticulosClientesEan.LoadData(ASelectedId: Integer = 0);
begin
  qryClientesEan.Close;
  qryClientesEan.ParamByName('articulo_id').AsInteger := FArticuloId;
  qryClientesEan.Open;

  if ASelectedId > 0 then
    qryClientesEan.Locate('id', ASelectedId, []);

  CargarFichaDesdeRegistro;
end;

procedure TfrmArticulosClientesEan.dsClientesEanDataChange(Sender: TObject; Field: TField);
begin
  if not FLoadingFicha then
    CargarFichaDesdeRegistro;
end;

procedure TfrmArticulosClientesEan.LimpiarFicha;
begin
  lblFichaCliente.Caption := '(Ningún cliente seleccionado)';
  chkFichaActivo.Checked := True;
  edtFichaEan13.Text := '';
  edtFichaDun14.Text := '';
  edtFichaRefCli.Text := '';
  redtFichaDescripcion.Clear;
  redtFichaIngredientes.Clear;
  btnBoldDesc.Down := False;
  btnUnderlineDesc.Down := False;
  btnSourceDesc.Down := False;
  btnBoldIngredientes.Down := False;
  btnUnderlineIngredientes.Down := False;
  btnSourceIngredientes.Down := False;
  btnBoldDesc.Enabled := True;
  btnUnderlineDesc.Enabled := True;
  cbFontSizeDesc.Enabled := True;
  btnBoldIngredientes.Enabled := True;
  btnUnderlineIngredientes.Enabled := True;
  pnlFicha.Enabled := False;
end;

procedure TfrmArticulosClientesEan.CargarFichaDesdeRegistro;
begin
  if (not qryClientesEan.Active) or qryClientesEan.IsEmpty then
  begin
    LimpiarFicha;
    Exit;
  end;

  pnlFicha.Enabled := True;
  FLoadingFicha := True;
  try
    lblFichaCliente.Caption := qryClientesEan.FieldByName('cliente_nombre').AsString;
    if not qryClientesEan.FieldByName('activo').IsNull then
      chkFichaActivo.Checked := qryClientesEan.FieldByName('activo').AsBoolean
    else
      chkFichaActivo.Checked := True;
    edtFichaEan13.Text := qryClientesEan.FieldByName('ean13').AsString;
    edtFichaDun14.Text := qryClientesEan.FieldByName('dun14').AsString;
    edtFichaRefCli.Text := qryClientesEan.FieldByName('codigo_articulo_cliente').AsString;

    LoadRichEditHtml(qryClientesEan.FieldByName('descripcion_cliente').AsString, redtFichaDescripcion, btnSourceDesc);
    LoadRichEditHtml(qryClientesEan.FieldByName('ingredientes').AsString, redtFichaIngredientes, btnSourceIngredientes);

    btnBoldDesc.Enabled := not btnSourceDesc.Down;
    btnUnderlineDesc.Enabled := not btnSourceDesc.Down;
    cbFontSizeDesc.Enabled := not btnSourceDesc.Down;
    btnBoldIngredientes.Enabled := not btnSourceIngredientes.Down;
    btnUnderlineIngredientes.Enabled := not btnSourceIngredientes.Down;

    UpdateRichEditToolbar(redtFichaDescripcion, btnBoldDesc, btnUnderlineDesc);
    UpdateRichEditToolbar(redtFichaIngredientes, btnBoldIngredientes, btnUnderlineIngredientes);
  finally
    FLoadingFicha := False;
  end;
end;

procedure TfrmArticulosClientesEan.btnGuardarFichaClick(Sender: TObject);
var
  LId: Integer;
  LActivoVal: Integer;
begin
  if (not qryClientesEan.Active) or qryClientesEan.IsEmpty then
    Exit;

  LId := qryClientesEan.FieldByName('id').AsInteger;
  if LId <= 0 then Exit;

  if chkFichaActivo.Checked then
    LActivoVal := 1
  else
    LActivoVal := 0;

  try
    dmgMain.qryExec.Close;
    dmgMain.qryExec.SQL.Text :=
      'UPDATE ge_clientes_articulos ' +
      'SET ean13 = :ean13, ' +
      '    dun14 = :dun14, ' +
      '    codigo_articulo_cliente = :cod_cli, ' +
      '    descripcion_cliente = :desc_cli, ' +
      '    ingredientes = :ingredientes, ' +
      '    activo = :activo, ' +
      '    updated_at = CURRENT_TIMESTAMP ' +
      'WHERE id = :id';
    SetParamInt(dmgMain.qryExec.ParamByName('id'), LId);
    SetParamString(dmgMain.qryExec.ParamByName('ean13'), Trim(edtFichaEan13.Text));
    SetParamString(dmgMain.qryExec.ParamByName('dun14'), Trim(edtFichaDun14.Text));
    SetParamString(dmgMain.qryExec.ParamByName('cod_cli'), Trim(edtFichaRefCli.Text));
    SetParamText(dmgMain.qryExec.ParamByName('desc_cli'), GetRichEditHtml(redtFichaDescripcion, btnSourceDesc));
    SetParamMemo(dmgMain.qryExec.ParamByName('ingredientes'), GetRichEditHtml(redtFichaIngredientes, btnSourceIngredientes));
    SetParamInt(dmgMain.qryExec.ParamByName('activo'), LActivoVal);
    dmgMain.qryExec.ExecSQL;

    LoadData(LId);
    ShowMessage('Ficha de cliente guardada correctamente.');
  except
    on E: Exception do
      TDbErrorHandler.HandleException(E, 'Error al guardar la ficha del cliente');
  end;
end;

procedure TfrmArticulosClientesEan.btnCancelarFichaClick(Sender: TObject);
begin
  CargarFichaDesdeRegistro;
end;

procedure TfrmArticulosClientesEan.btnCerrarClick(Sender: TObject);
begin
  Close;
end;

procedure TfrmArticulosClientesEan.btnAnadirClick(Sender: TObject);
var
  LFrmSelect: TfrmSelectCliente;
  LClienteId: Integer;
  LNewId: Integer;
  LQryCheck: TFDQuery;
  LInitDesc: string;
begin
  LFrmSelect := TfrmSelectCliente.Create(nil);
  try
    if LFrmSelect.ShowModal = mrOk then
    begin
      LClienteId := StrToIntDef(LFrmSelect.SelectedId, 0);
      if LClienteId <= 0 then Exit;

      // Comprobar si ya existe para este artículo y cliente
      LQryCheck := TFDQuery.Create(nil);
      try
        LQryCheck.Connection := dmgMain.dbConn;
        LQryCheck.SQL.Text :=
          'SELECT id FROM ge_clientes_articulos WHERE id_articulo = :art AND id_cliente = :cli';
        LQryCheck.ParamByName('art').AsInteger := FArticuloId;
        LQryCheck.ParamByName('cli').AsInteger := LClienteId;
        LQryCheck.Open;

        if not LQryCheck.IsEmpty then
        begin
          LNewId := LQryCheck.FieldByName('id').AsInteger;
          MessageDlg('Este cliente ya está configurado para este artículo.', mtInformation, [mbOK], 0);
          LoadData(LNewId);
          Exit;
        end;
      finally
        LQryCheck.Free;
      end;

      if FArticuloDescEtiqueta <> '' then
        LInitDesc := FArticuloDescEtiqueta
      else
        LInitDesc := FArticuloDesc;

      // Insertar nuevo registro con valores iniciales
      try
        dmgMain.qryExec.Close;
        dmgMain.qryExec.SQL.Text :=
          'INSERT INTO ge_clientes_articulos ' +
          '  (ide, id_cliente, id_articulo, ean13, dun14, codigo_articulo_cliente, descripcion_cliente, ingredientes, activo) ' +
          'VALUES ' +
          '  (1, :cli, :art, :ean13, :dun14, :ref_cli, :desc_cli, :ingredientes, 1)';
        SetParamInt(dmgMain.qryExec.ParamByName('cli'), LClienteId);
        SetParamInt(dmgMain.qryExec.ParamByName('art'), FArticuloId);
        SetParamString(dmgMain.qryExec.ParamByName('ean13'), Trim(FArticuloEan));
        SetParamString(dmgMain.qryExec.ParamByName('dun14'), '');
        SetParamString(dmgMain.qryExec.ParamByName('ref_cli'), '');
        SetParamText(dmgMain.qryExec.ParamByName('desc_cli'), Trim(LInitDesc));
        SetParamMemo(dmgMain.qryExec.ParamByName('ingredientes'), Trim(FArticuloIngredientes));
        dmgMain.qryExec.ExecSQL;

        // Obtener ID insertado
        dmgMain.qryExec.Close;
        dmgMain.qryExec.SQL.Text := 'SELECT LAST_INSERT_ID() as new_id';
        dmgMain.qryExec.Open;
        LNewId := dmgMain.qryExec.FieldByName('new_id').AsInteger;

        LoadData(LNewId);
      except
        on E: Exception do
          TDbErrorHandler.HandleException(E, 'Error al asociar el cliente con el artículo');
      end;
    end;
  finally
    LFrmSelect.Free;
  end;
end;

procedure TfrmArticulosClientesEan.btnEliminarClick(Sender: TObject);
var
  LId: Integer;
begin
  if (not qryClientesEan.Active) or qryClientesEan.IsEmpty then Exit;

  LId := qryClientesEan.FieldByName('id').AsInteger;
  if MessageDlg('¿Desea eliminar la configuración de EANs y ficha para el cliente seleccionado?',
                mtConfirmation, [mbYes, mbNo], 0) = mrYes then
  begin
    try
      dmgMain.qryExec.Close;
      dmgMain.qryExec.SQL.Text := 'DELETE FROM ge_clientes_articulos WHERE id = :id';
      dmgMain.qryExec.ParamByName('id').AsInteger := LId;
      dmgMain.qryExec.ExecSQL;

      LoadData;
    except
      on E: Exception do
        TDbErrorHandler.HandleException(E, 'Error al eliminar el registro');
    end;
  end;
end;

procedure TfrmArticulosClientesEan.btnBoldDescClick(Sender: TObject);
begin
  ToggleRichEditBold(redtFichaDescripcion, btnBoldDesc);
end;

procedure TfrmArticulosClientesEan.btnUnderlineDescClick(Sender: TObject);
begin
  ToggleRichEditUnderline(redtFichaDescripcion, btnUnderlineDesc);
end;

procedure TfrmArticulosClientesEan.btnSourceDescClick(Sender: TObject);
begin
  ToggleRichEditSourceView(redtFichaDescripcion, btnSourceDesc);
  btnBoldDesc.Enabled := not btnSourceDesc.Down;
  btnUnderlineDesc.Enabled := not btnSourceDesc.Down;
  cbFontSizeDesc.Enabled := not btnSourceDesc.Down;
end;

procedure TfrmArticulosClientesEan.cbFontSizeDescChange(Sender: TObject);
var
  LSize: Integer;
begin
  if cbFontSizeDesc.ItemIndex >= 0 then
  begin
    LSize := StrToIntDef(cbFontSizeDesc.Items[cbFontSizeDesc.ItemIndex], 0);
    if LSize > 0 then
      redtFichaDescripcion.SelAttributes.Size := LSize;
  end;
  redtFichaDescripcion.SetFocus;
end;

procedure TfrmArticulosClientesEan.redtFichaDescripcionSelectionChange(Sender: TObject);
var
  LSize: Integer;
  LIdx: Integer;
begin
  UpdateRichEditToolbar(redtFichaDescripcion, btnBoldDesc, btnUnderlineDesc);
  LSize := redtFichaDescripcion.SelAttributes.Size;
  if LSize > 0 then
  begin
    LIdx := cbFontSizeDesc.Items.IndexOf(IntToStr(LSize));
    if LIdx >= 0 then
      cbFontSizeDesc.ItemIndex := LIdx;
  end;
end;

procedure TfrmArticulosClientesEan.btnBoldIngredientesClick(Sender: TObject);
begin
  ToggleRichEditBold(redtFichaIngredientes, btnBoldIngredientes);
end;

procedure TfrmArticulosClientesEan.btnUnderlineIngredientesClick(Sender: TObject);
begin
  ToggleRichEditUnderline(redtFichaIngredientes, btnUnderlineIngredientes);
end;

procedure TfrmArticulosClientesEan.btnSourceIngredientesClick(Sender: TObject);
begin
  ToggleRichEditSourceView(redtFichaIngredientes, btnSourceIngredientes);
  btnBoldIngredientes.Enabled := not btnSourceIngredientes.Down;
  btnUnderlineIngredientes.Enabled := not btnSourceIngredientes.Down;
end;

procedure TfrmArticulosClientesEan.redtFichaIngredientesSelectionChange(Sender: TObject);
begin
  UpdateRichEditToolbar(redtFichaIngredientes, btnBoldIngredientes, btnUnderlineIngredientes);
end;

procedure TfrmArticulosClientesEan.btnCopiarDescArticuloClick(Sender: TObject);
begin
  if FArticuloDescEtiqueta <> '' then
    LoadRichEditHtml(FArticuloDescEtiqueta, redtFichaDescripcion, btnSourceDesc)
  else
    LoadRichEditHtml(FArticuloDesc, redtFichaDescripcion, btnSourceDesc);
end;

procedure TfrmArticulosClientesEan.btnCopiarIngrArticuloClick(Sender: TObject);
begin
  LoadRichEditHtml(FArticuloIngredientes, redtFichaIngredientes, btnSourceIngredientes);
end;

end.
