unit frm_TrabajadoresGrupos;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes,
  Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.ExtCtrls, Vcl.StdCtrls,
  Vcl.Grids, Vcl.DBGrids, Data.DB, Vcl.Buttons, FireDAC.Comp.Client, FireDAC.Stan.Param,
  frm_BaseList, uAppTheme, System.UITypes;

type
  TfrmTrabajadoresGrupos = class(TfrmBaseList)
    procedure FormShow(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure btnRefreshClick(Sender: TObject); override;
    procedure btnNewClick(Sender: TObject); override;
    procedure btnEditClick(Sender: TObject); override;
    procedure btnDeleteClick(Sender: TObject); override;
  private
    procedure dbGridMainCellClick(Column: TColumn);
    procedure dbGridMainDblClick(Sender: TObject);
    procedure dbGridMainKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
    procedure dbGridMainDrawColumnCellCustom(Sender: TObject; const Rect: TRect;
      DataCol: Integer; Column: TColumn; State: TGridDrawState);
    procedure ToggleEstadoActivo;
  public
    { Public declarations }
  end;

var
  frmTrabajadoresGrupos: TfrmTrabajadoresGrupos;

implementation

uses
  dmg_Main, frm_TrabajadoresGruposEditor, uDbErrorHandler;

{$R *.dfm}

procedure TfrmTrabajadoresGrupos.FormShow(Sender: TObject);
begin
  AlphaFilterField := 'nombre';
  StatusFilterField := 'activo';
  StatusValues.Clear;
  StatusValues.Add('Activo');
  StatusValues.Add('Inactivo');

  inherited;

  frmTrabajadoresGrupos := Self;
  OnDestroy := FormDestroy;

  pnlSearch.Visible := True;
  lblSearch.Caption := 'Buscar Grupo:';

  dbGridMain.Options := dbGridMain.Options + [dgEditing] - [dgRowSelect, dgMultiSelect];
  dbGridMain.OnCellClick := dbGridMainCellClick;
  dbGridMain.OnDblClick := dbGridMainDblClick;
  dbGridMain.OnKeyDown := dbGridMainKeyDown;
  dbGridMain.OnDrawColumnCell := dbGridMainDrawColumnCellCustom;
end;

procedure TfrmTrabajadoresGrupos.FormDestroy(Sender: TObject);
begin
  if frmTrabajadoresGrupos = Self then
    frmTrabajadoresGrupos := nil;
end;

procedure TfrmTrabajadoresGrupos.btnRefreshClick(Sender: TObject);
var
  LSql: string;
  LSearch: string;
begin
  FQryMain.Close;

  LSql :=
    'SELECT ' +
    '  g.id, ' +
    '  g.codigo, ' +
    '  g.nombre, ' +
    '  g.activo, ' +
    '  (SELECT COUNT(*) FROM ge_trabajadores_empresas te WHERE te.id_grupo = g.id AND te.activo = 1) AS num_trabajadores ' +
    'FROM ge_trabajadores_grupos g ';

  LSearch := Trim(edtSearch.Text);
  if LSearch <> '' then
    LSql := LSql + 'WHERE (g.nombre LIKE :search OR CAST(g.codigo AS CHAR) LIKE :search) ';

  LSql := LSql + 'ORDER BY g.codigo ASC';

  FQryMain.SQL.Text := LSql;
  if LSearch <> '' then
    FQryMain.ParamByName('search').AsString := '%' + LSearch + '%';

  FQryMain.Open;

  ApplyAllFilters;

  dbGridMain.Columns.Clear;

  with dbGridMain.Columns.Add do
  begin
    FieldName := 'codigo';
    Title.Caption := 'Código';
    Width := 80;
    Alignment := taCenter;
    Title.Alignment := taCenter;
    ReadOnly := True;
  end;

  with dbGridMain.Columns.Add do
  begin
    FieldName := 'nombre';
    Title.Caption := 'Nombre del Grupo';
    Width := 280;
    Alignment := taLeftJustify;
    Title.Alignment := taLeftJustify;
    ReadOnly := True;
  end;

  with dbGridMain.Columns.Add do
  begin
    FieldName := 'num_trabajadores';
    Title.Caption := 'Trabajadores Activos';
    Width := 140;
    Alignment := taCenter;
    Title.Alignment := taCenter;
    ReadOnly := True;
  end;

  with dbGridMain.Columns.Add do
  begin
    FieldName := 'activo';
    Title.Caption := 'Activo';
    Width := 70;
    Alignment := taCenter;
    Title.Alignment := taCenter;
    ReadOnly := True;
  end;

  dbGridMain.Options := dbGridMain.Options + [dgEditing] - [dgRowSelect, dgMultiSelect];
end;

procedure TfrmTrabajadoresGrupos.btnNewClick(Sender: TObject);
var
  LEditor: TfrmTrabajadoresGruposEditor;
  LNewId: Integer;
begin
  LEditor := TfrmTrabajadoresGruposEditor.Create(Self);
  try
    LEditor.GrupoId := 0;
    if LEditor.ShowModal = mrOk then
    begin
      LNewId := LEditor.GrupoId;
      btnRefreshClick(nil);
      if LNewId > 0 then
        FQryMain.Locate('id', LNewId, []);
    end;
  finally
    LEditor.Free;
  end;
end;

procedure TfrmTrabajadoresGrupos.btnEditClick(Sender: TObject);
var
  LEditor: TfrmTrabajadoresGruposEditor;
  LId: Integer;
begin
  if FQryMain.IsEmpty then Exit;

  LId := FQryMain.FieldByName('id').AsInteger;
  LEditor := TfrmTrabajadoresGruposEditor.Create(Self);
  try
    LEditor.GrupoId := LId;
    if LEditor.ShowModal = mrOk then
    begin
      btnRefreshClick(nil);
      FQryMain.Locate('id', LId, []);
    end;
  finally
    LEditor.Free;
  end;
end;

procedure TfrmTrabajadoresGrupos.btnDeleteClick(Sender: TObject);
var
  LId: Integer;
  LNombre: string;
  LNumTrab: Integer;
  LQryDel: TFDQuery;
begin
  if FQryMain.IsEmpty then Exit;

  LId := FQryMain.FieldByName('id').AsInteger;
  LNombre := FQryMain.FieldByName('nombre').AsString;
  LNumTrab := FQryMain.FieldByName('num_trabajadores').AsInteger;

  if LNumTrab > 0 then
  begin
    MessageDlg(
      Format('No se puede eliminar el grupo "%s" porque tiene %d trabajador(es) asignado(s) en activo.' + sLineBreak +
             'Por favor, reasigne los trabajadores a otro grupo antes de eliminarlo.', [LNombre, LNumTrab]),
      mtWarning, [mbOk], 0);
    Exit;
  end;

  if MessageDlg(Format('¿Está seguro de que desea eliminar el grupo "%s"?', [LNombre]),
                mtConfirmation, [mbYes, mbNo], 0) = mrYes then
  begin
    LQryDel := TFDQuery.Create(nil);
    try
      try
        LQryDel.Connection := dmgMain.dbConn;
        LQryDel.SQL.Text := 'DELETE FROM ge_trabajadores_grupos WHERE id = :id';
        LQryDel.ParamByName('id').AsInteger := LId;
        LQryDel.ExecSQL;

        btnRefreshClick(nil);
      except
        on E: Exception do
          TDbErrorHandler.HandleException(E, 'Error al eliminar el grupo de trabajadores');
      end;
    finally
      LQryDel.Free;
    end;
  end;
end;

procedure TfrmTrabajadoresGrupos.ToggleEstadoActivo;
var
  LId: Integer;
  LActivoActual: Integer;
  LNuevoActivo: Integer;
  LQryUpd: TFDQuery;
begin
  if FQryMain.IsEmpty then Exit;

  LId := FQryMain.FieldByName('id').AsInteger;
  LActivoActual := FQryMain.FieldByName('activo').AsInteger;

  if LActivoActual = 1 then
    LNuevoActivo := 0
  else
    LNuevoActivo := 1;

  LQryUpd := TFDQuery.Create(nil);
  try
    try
      LQryUpd.Connection := dmgMain.dbConn;
      LQryUpd.SQL.Text := 'UPDATE ge_trabajadores_grupos SET activo = :act WHERE id = :id';
      LQryUpd.ParamByName('act').AsInteger := LNuevoActivo;
      LQryUpd.ParamByName('id').AsInteger := LId;
      LQryUpd.ExecSQL;

      btnRefreshClick(nil);
      FQryMain.Locate('id', LId, []);
    except
      on E: Exception do
        TDbErrorHandler.HandleException(E, 'Error al actualizar el estado del grupo');
    end;
  finally
    LQryUpd.Free;
  end;
end;

procedure TfrmTrabajadoresGrupos.dbGridMainCellClick(Column: TColumn);
begin
  if (Column <> nil) and SameText(Column.FieldName, 'activo') then
    ToggleEstadoActivo;
end;

procedure TfrmTrabajadoresGrupos.dbGridMainDblClick(Sender: TObject);
var
  LCol: TColumn;
begin
  if dbGridMain.SelectedIndex >= 0 then
    LCol := dbGridMain.Columns[dbGridMain.SelectedIndex]
  else
    LCol := nil;

  if (LCol <> nil) and SameText(LCol.FieldName, 'activo') then
    Exit;

  btnEditClick(Sender);
end;

procedure TfrmTrabajadoresGrupos.dbGridMainKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
var
  LCol: TColumn;
begin
  if dbGridMain.SelectedIndex >= 0 then
    LCol := dbGridMain.Columns[dbGridMain.SelectedIndex]
  else
    LCol := nil;

  if (Key = VK_SPACE) and (LCol <> nil) and SameText(LCol.FieldName, 'activo') then
  begin
    ToggleEstadoActivo;
    Key := 0;
  end
  else if (Key = VK_RETURN) then
  begin
    btnEditClick(Sender);
    Key := 0;
  end;
end;

procedure TfrmTrabajadoresGrupos.dbGridMainDrawColumnCellCustom(Sender: TObject;
  const Rect: TRect; DataCol: Integer; Column: TColumn; State: TGridDrawState);
var
  LFlags: Cardinal;
  R: TRect;
begin
  if SameText(Column.FieldName, 'activo') then
  begin
    dbGridMain.Canvas.FillRect(Rect);
    LFlags := DFCS_BUTTONCHECK;
    if Column.Field.AsInteger = 1 then
      LFlags := LFlags or DFCS_CHECKED;

    R := Rect;
    InflateRect(R, -((Rect.Right - Rect.Left - 14) div 2), -((Rect.Bottom - Rect.Top - 14) div 2));
    DrawFrameControl(dbGridMain.Canvas.Handle, R, DFC_BUTTON, LFlags);
  end
  else
    dbGridMainDrawColumnCell(Sender, Rect, DataCol, Column, State);
end;

end.
