unit frm_SeriesEditor;

interface

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

type
  TfrmSeriesEditor = class(TfrmBase)
    lblSerie: TLabel;
    edtSerie: TEdit;
    lblSigAlbaran: TLabel;
    edtSigAlbaran: TEdit;
    lblSigFactura: TLabel;
    edtSigFactura: TEdit;
    lblSigPresupuesto: TLabel;
    edtSigPresupuesto: TEdit;
    lblFormularioImpresion: TLabel;
    edtFormularioImpresion: TEdit;
    chkActivo: TCheckBox;
    lblSerieFactusol: TLabel;
    edtSerieFactusol: TEdit;
    lblFechaInicio: TLabel;
    dtpFechaInicio: TDateTimePicker;
    lblFechaFin: TLabel;
    dtpFechaFin: TDateTimePicker;
    procedure FormShow(Sender: TObject);
    procedure btnSaveClick(Sender: TObject);
    procedure btnSalirClick(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
  protected
    procedure DoAnadir; override;
    procedure DoModificar; override;
    procedure DoPrimero; override;
    procedure DoAnterior; override;
    procedure DoSiguiente; override;
    procedure DoUltimo; override;
  private
    FSerieId: string;
    FParentForm: TForm;
    FWasDefault: Boolean;
    chkPorDefecto: TCheckBox;
    chkUsarFechaInicio: TCheckBox;
    chkUsarFechaFin: TCheckBox;
    procedure chkUsarFechaInicioClick(Sender: TObject);
    procedure chkUsarFechaFinClick(Sender: TObject);
    procedure LoadData;
  public
    property SerieId: string read FSerieId write FSerieId;
    property ParentForm: TForm read FParentForm write FParentForm;
  end;

var
  frmSeriesEditor: TfrmSeriesEditor;

implementation

uses
  dmg_Main, uDbErrorHandler, frm_Series;

{$R *.dfm}

procedure TfrmSeriesEditor.FormShow(Sender: TObject);
begin
  TAppTheme.ApplyToForm(Self);

  btnGuardar.OnClick := btnSaveClick;
  btnSalir.OnClick := btnSalirClick;

  pgcDetails.Visible := True;
  TsListado.TabVisible := False;
  pgcDetails.ActivePage := tsDatosEnvio;
  pnlSideToolbar.Visible := False;
  dbgItems.Visible := False;
  pnlFooter.Visible := False;

  dtpFechaInicio.ShowCheckbox := False;
  dtpFechaFin.ShowCheckbox := False;

  if not Assigned(chkPorDefecto) then
  begin
    chkPorDefecto := TCheckBox.Create(Self);
    chkPorDefecto.Parent := chkActivo.Parent;
    chkPorDefecto.Left := chkActivo.Left + 150;
    chkPorDefecto.Top := chkActivo.Top;
    chkPorDefecto.Width := 150;
    chkPorDefecto.Caption := 'Serie por defecto';
    chkPorDefecto.TabOrder := chkActivo.TabOrder + 1;
  end;

  if not Assigned(chkUsarFechaInicio) then
  begin
    chkUsarFechaInicio := TCheckBox.Create(Self);
    chkUsarFechaInicio.Parent := lblFechaInicio.Parent;
    chkUsarFechaInicio.Left := lblFechaInicio.Left;
    chkUsarFechaInicio.Top := lblFechaInicio.Top;
    chkUsarFechaInicio.Width := 160;
    chkUsarFechaInicio.Caption := 'Limitar Fecha Inicio';
    chkUsarFechaInicio.OnClick := chkUsarFechaInicioClick;
    lblFechaInicio.Visible := False;
  end;

  if not Assigned(chkUsarFechaFin) then
  begin
    chkUsarFechaFin := TCheckBox.Create(Self);
    chkUsarFechaFin.Parent := lblFechaFin.Parent;
    chkUsarFechaFin.Left := lblFechaFin.Left;
    chkUsarFechaFin.Top := lblFechaFin.Top;
    chkUsarFechaFin.Width := 160;
    chkUsarFechaFin.Caption := 'Limitar Fecha Fin';
    chkUsarFechaFin.OnClick := chkUsarFechaFinClick;
    lblFechaFin.Visible := False;
  end;

  if FSerieId <> '' then
    LoadData
  else
    DoAnadir;
end;

procedure TfrmSeriesEditor.chkUsarFechaInicioClick(Sender: TObject);
begin
  dtpFechaInicio.Enabled := chkUsarFechaInicio.Checked;
end;

procedure TfrmSeriesEditor.chkUsarFechaFinClick(Sender: TObject);
begin
  dtpFechaFin.Enabled := chkUsarFechaFin.Checked;
end;

procedure TfrmSeriesEditor.FormDestroy(Sender: TObject);
begin
  // No-op
end;

procedure TfrmSeriesEditor.LoadData;
begin
  if FSerieId = '' then Exit;

  dmgMain.qryExec.Close;
  dmgMain.qryExec.SQL.Text := 
    'SELECT id, serie, sig_numero_albaran, sig_numero_factura, sig_numero_presupuesto, ' +
    'formulario_impresion, activo, serie_factusol, fecha_inicio, fecha_fin, por_defecto ' +
    'FROM ge_series WHERE id = :id';
  dmgMain.qryExec.ParamByName('id').AsString := FSerieId;
  dmgMain.qryExec.Open;
  
  if not dmgMain.qryExec.IsEmpty then
  begin
    edtSerie.Text := dmgMain.qryExec.FieldByName('serie').AsString;
    edtSigAlbaran.Text := dmgMain.qryExec.FieldByName('sig_numero_albaran').AsString;
    edtSigFactura.Text := dmgMain.qryExec.FieldByName('sig_numero_factura').AsString;
    edtSigPresupuesto.Text := dmgMain.qryExec.FieldByName('sig_numero_presupuesto').AsString;
    edtFormularioImpresion.Text := dmgMain.qryExec.FieldByName('formulario_impresion').AsString;
    chkActivo.Checked := dmgMain.qryExec.FieldByName('activo').AsInteger <> 0;
    chkPorDefecto.Checked := dmgMain.qryExec.FieldByName('por_defecto').AsInteger <> 0;
    FWasDefault := chkPorDefecto.Checked;
    edtSerieFactusol.Text := dmgMain.qryExec.FieldByName('serie_factusol').AsString;
    
    if not dmgMain.qryExec.FieldByName('fecha_inicio').IsNull and (dmgMain.qryExec.FieldByName('fecha_inicio').AsDateTime > 0) then
    begin
      dtpFechaInicio.Date := dmgMain.qryExec.FieldByName('fecha_inicio').AsDateTime;
      chkUsarFechaInicio.Checked := True;
      dtpFechaInicio.Enabled := True;
    end
    else
    begin
      dtpFechaInicio.Date := Date;
      chkUsarFechaInicio.Checked := False;
      dtpFechaInicio.Enabled := False;
    end;
 
    if not dmgMain.qryExec.FieldByName('fecha_fin').IsNull and (dmgMain.qryExec.FieldByName('fecha_fin').AsDateTime > 0) then
    begin
      dtpFechaFin.Date := dmgMain.qryExec.FieldByName('fecha_fin').AsDateTime;
      chkUsarFechaFin.Checked := True;
      dtpFechaFin.Enabled := True;
    end
    else
    begin
      dtpFechaFin.Date := Date;
      chkUsarFechaFin.Checked := False;
      dtpFechaFin.Enabled := False;
    end;
  end;
  dmgMain.qryExec.Close;
end;

procedure TfrmSeriesEditor.DoAnadir;
begin
  FSerieId := '';
  edtSerie.Clear;
  edtSigAlbaran.Text := '1';
  edtSigFactura.Text := '1';
  edtSigPresupuesto.Text := '1';
  edtFormularioImpresion.Clear;
  chkActivo.Checked := True;
  chkPorDefecto.Checked := False;
  FWasDefault := False;
  edtSerieFactusol.Clear;
  dtpFechaInicio.Date := Date;
  chkUsarFechaInicio.Checked := False;
  dtpFechaInicio.Enabled := False;
  dtpFechaFin.Date := Date;
  chkUsarFechaFin.Checked := False;
  dtpFechaFin.Enabled := False;
  edtSerie.SetFocus;
end;

procedure TfrmSeriesEditor.DoModificar;
begin
  edtSerie.SetFocus;
end;

procedure TfrmSeriesEditor.DoPrimero;
var
  LParent: TfrmSeries;
begin
  LParent := nil;
  if Assigned(FParentForm) and (FParentForm is TfrmSeries) then
    LParent := TfrmSeries(FParentForm)
  else if Assigned(frmSeries) then
    LParent := frmSeries;

  if Assigned(LParent) and Assigned(LParent.QryMain) and not LParent.QryMain.IsEmpty then
  begin
    LParent.QryMain.First;
    FSerieId := LParent.QryMain.FieldByName('id').AsString;
    LoadData;
  end;
end;

procedure TfrmSeriesEditor.DoAnterior;
var
  LParent: TfrmSeries;
begin
  LParent := nil;
  if Assigned(FParentForm) and (FParentForm is TfrmSeries) then
    LParent := TfrmSeries(FParentForm)
  else if Assigned(frmSeries) then
    LParent := frmSeries;

  if Assigned(LParent) and Assigned(LParent.QryMain) and not LParent.QryMain.IsEmpty then
  begin
    LParent.QryMain.Prior;
    FSerieId := LParent.QryMain.FieldByName('id').AsString;
    LoadData;
  end;
end;

procedure TfrmSeriesEditor.DoSiguiente;
var
  LParent: TfrmSeries;
begin
  LParent := nil;
  if Assigned(FParentForm) and (FParentForm is TfrmSeries) then
    LParent := TfrmSeries(FParentForm)
  else if Assigned(frmSeries) then
    LParent := frmSeries;

  if Assigned(LParent) and Assigned(LParent.QryMain) and not LParent.QryMain.IsEmpty then
  begin
    LParent.QryMain.Next;
    FSerieId := LParent.QryMain.FieldByName('id').AsString;
    LoadData;
  end;
end;

procedure TfrmSeriesEditor.DoUltimo;
var
  LParent: TfrmSeries;
begin
  LParent := nil;
  if Assigned(FParentForm) and (FParentForm is TfrmSeries) then
    LParent := TfrmSeries(FParentForm)
  else if Assigned(frmSeries) then
    LParent := frmSeries;

  if Assigned(LParent) and Assigned(LParent.QryMain) and not LParent.QryMain.IsEmpty then
  begin
    LParent.QryMain.Last;
    FSerieId := LParent.QryMain.FieldByName('id').AsString;
    LoadData;
  end;
end;

procedure TfrmSeriesEditor.btnSalirClick(Sender: TObject);
begin
  Close;
end;

procedure TfrmSeriesEditor.btnSaveClick(Sender: TObject);
var
  LIsNew: Boolean;
  LSigAlbaran, LSigFactura, LSigPresupuesto: Integer;
  Qry: TFDQuery;
begin
  if Trim(edtSerie.Text) = '' then
  begin
    ShowMessage('Debe introducir un código de serie.');
    edtSerie.SetFocus;
    Exit;
  end;
 
  LSigAlbaran := StrToIntDef(edtSigAlbaran.Text, 1);
  LSigFactura := StrToIntDef(edtSigFactura.Text, 1);
  LSigPresupuesto := StrToIntDef(edtSigPresupuesto.Text, 1);
 
  LIsNew := (FSerieId = '');
  
  // Si el campo estaba a 1 y se pasa a 0 no debe permitirlo si no hay otra serie marcada a 1
  if not LIsNew and FWasDefault and not chkPorDefecto.Checked then
  begin
    Qry := TFDQuery.Create(nil);
    try
      Qry.Connection := dmgMain.dbConn;
      Qry.SQL.Text := 'SELECT COUNT(*) FROM ge_series WHERE empresa_id = :emp AND por_defecto = 1 AND id <> :id AND activo = 1';
      Qry.ParamByName('emp').AsString := dmgMain.CurrentCompanyId;
      Qry.ParamByName('id').AsString := FSerieId;
      Qry.Open;
      if Qry.Fields[0].AsInteger = 0 then
      begin
        ShowMessage('No se puede desmarcar esta serie como por defecto porque no hay otra serie marcada como por defecto.');
        Exit;
      end;
    finally
      Qry.Free;
    end;
  end;
  
  if LIsNew and not chkPorDefecto.Checked then
  begin
    // Si es la única serie de la empresa, forzar por defecto
    Qry := TFDQuery.Create(nil);
    try
      Qry.Connection := dmgMain.dbConn;
      Qry.SQL.Text := 'SELECT COUNT(*) FROM ge_series WHERE empresa_id = :emp AND activo = 1';
      Qry.ParamByName('emp').AsString := dmgMain.CurrentCompanyId;
      Qry.Open;
      if Qry.Fields[0].AsInteger = 0 then
        chkPorDefecto.Checked := True;
    finally
      Qry.Free;
    end;
  end;
 
  dmgMain.dbConn.StartTransaction;
  try
    // Si la modificamos para ponerla a 1 (por_defecto = 1), ponemos el resto a 0
    if chkPorDefecto.Checked then
    begin
      dmgMain.qryExec.Close;
      dmgMain.qryExec.SQL.Text := 'UPDATE ge_series SET por_defecto = 0 WHERE empresa_id = :emp AND id <> :id';
      dmgMain.qryExec.ParamByName('emp').AsString := dmgMain.CurrentCompanyId;
      dmgMain.qryExec.ParamByName('id').AsString := FSerieId;
      dmgMain.qryExec.ExecSQL;
    end;
 
    dmgMain.qryExec.Close;
    if LIsNew then
    begin
      dmgMain.qryExec.SQL.Text := 
        'INSERT INTO ge_series (empresa_id, serie, sig_numero_albaran, sig_numero_factura, sig_numero_presupuesto, ' +
        '  formulario_impresion, activo, serie_factusol, fecha_inicio, fecha_fin, por_defecto, id_user_creator, id_user_update) ' +
        'VALUES (:emp, :ser, :albar, :fact, :presu, :form, :act, :factusol, :fec_ini, :fec_fin, :pordef, :user, :user)';
    end
    else
    begin
      dmgMain.qryExec.SQL.Text := 
        'UPDATE ge_series SET serie = :ser, sig_numero_albaran = :albar, sig_numero_factura = :fact, ' +
        'sig_numero_presupuesto = :presu, formulario_impresion = :form, activo = :act, ' +
        'serie_factusol = :factusol, fecha_inicio = :fec_ini, fecha_fin = :fec_fin, por_defecto = :pordef, ' +
        'id_user_update = :user, updated_at = CURRENT_TIMESTAMP ' +
        'WHERE id = :id';
      dmgMain.qryExec.ParamByName('id').AsString := FSerieId;
    end;
    if LIsNew then
      dmgMain.qryExec.ParamByName('emp').AsString := dmgMain.CurrentCompanyId;
    dmgMain.qryExec.ParamByName('ser').AsString := Trim(edtSerie.Text);
    dmgMain.qryExec.ParamByName('albar').AsInteger := LSigAlbaran;
    dmgMain.qryExec.ParamByName('fact').AsInteger := LSigFactura;
    dmgMain.qryExec.ParamByName('presu').AsInteger := LSigPresupuesto;
    
    if Trim(edtFormularioImpresion.Text) <> '' then
      dmgMain.qryExec.ParamByName('form').AsString := Trim(edtFormularioImpresion.Text)
    else
    begin
      dmgMain.qryExec.ParamByName('form').DataType := ftString;
      dmgMain.qryExec.ParamByName('form').Clear;
    end;
      
    if chkActivo.Checked then
      dmgMain.qryExec.ParamByName('act').AsInteger := 1
    else
      dmgMain.qryExec.ParamByName('act').AsInteger := 0;
    
    if chkPorDefecto.Checked then
      dmgMain.qryExec.ParamByName('pordef').AsInteger := 1
    else
      dmgMain.qryExec.ParamByName('pordef').AsInteger := 0;
    
    if Trim(edtSerieFactusol.Text) <> '' then
      dmgMain.qryExec.ParamByName('factusol').AsString := Trim(edtSerieFactusol.Text)
    else
    begin
      dmgMain.qryExec.ParamByName('factusol').DataType := ftString;
      dmgMain.qryExec.ParamByName('factusol').Clear;
    end;

    if chkUsarFechaInicio.Checked then
      dmgMain.qryExec.ParamByName('fec_ini').AsDate := dtpFechaInicio.Date
    else
    begin
      dmgMain.qryExec.ParamByName('fec_ini').DataType := ftDate;
      dmgMain.qryExec.ParamByName('fec_ini').Clear;
    end;

    if chkUsarFechaFin.Checked then
      dmgMain.qryExec.ParamByName('fec_fin').AsDate := dtpFechaFin.Date
    else
    begin
      dmgMain.qryExec.ParamByName('fec_fin').DataType := ftDate;
      dmgMain.qryExec.ParamByName('fec_fin').Clear;
    end;

    dmgMain.qryExec.ParamByName('user').AsString := dmgMain.CurrentUserId;
    
    dmgMain.qryExec.ExecSQL;
    dmgMain.dbConn.Commit;
    
    if Assigned(FParentForm) and (FParentForm is TfrmSeries) then
      TfrmSeries(FParentForm).btnRefreshClick(nil);
      
    ResetChangeTracking;
    ShowMessage('Serie guardada correctamente.');
  except
    on E: Exception do
    begin
      dmgMain.dbConn.Rollback;
      TDbErrorHandler.HandleException(E, 'Error al guardar la serie');
    end;
  end;
end;

end.
