unit frm_FormatosPresentacionEditor;

interface

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

type
  TfrmFormatosPresentacionEditor = class(TfrmBase)
    lblId: TLabel;
    edtId: TEdit;
    lblDescripcion: TLabel;
    edtDescripcion: TEdit;
    chkActivo: TCheckBox;
    qDetail: TFDQuery;
    dsDetail: TDataSource;
    procedure FormShow(Sender: TObject);
    procedure btnSaveClick(Sender: TObject);
    procedure btnSalirClick(Sender: TObject);
    procedure btnAddMaterialClick(Sender: TObject);
    procedure btnDelMaterialClick(Sender: TObject);
    procedure btnDuplicarClick(Sender: TObject);
  protected
    procedure Loaded; override;
    procedure DoAnadir; override;
    procedure DoModificar; override;
    procedure DoPrimero; override;
    procedure DoAnterior; override;
    procedure DoSiguiente; override;
    procedure DoUltimo; override;
  private
    FPresentacionId: Integer;
    FParentForm: TForm;
    procedure LoadData;
  public
    property PresentacionId: Integer read FPresentacionId write FPresentacionId;
    property ParentForm: TForm read FParentForm write FParentForm;
  end;

var
  frmFormatosPresentacionEditor: TfrmFormatosPresentacionEditor;

implementation

uses
  dmg_Main, uDbErrorHandler, frm_FormatosPresentacion, frm_SelectMateriaPrima;

{$R *.dfm}

procedure TfrmFormatosPresentacionEditor.Loaded;
begin
  inherited Loaded;
  qDetail.SQL.Text := 
    'SELECT pm.*, m.descripcion AS materia_prima_descripcion ' +
    'FROM ge_formatos_presentacion_materiales pm ' +
    'LEFT JOIN ge_materias_primas m ON pm.id_materia_prima = m.id ' +
    'WHERE pm.id_formato_presentacion = :id_formato';
end;

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

  btnGuardar.OnClick := btnSaveClick;
  btnSalir.OnClick := btnSalirClick;
  btnNuevoArticulo.OnClick := btnAddMaterialClick;
  btnEliminaArticulo.OnClick := btnDelMaterialClick;
  
  btnDuplicar.Visible := True;
  btnDuplicar.OnClick := btnDuplicarClick;

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

  edtId.ReadOnly := True;
  edtId.Color := clBtnFace;

  dsDetail.DataSet := qDetail;
  dbgItems.DataSource := dsDetail;

  dbgItems.Columns.Clear;
  with dbgItems.Columns.Add do
  begin
    FieldName := 'materia_prima_descripcion';
    Title.Caption := 'Material de Presentación / Envase';
    Width := 350;
    ReadOnly := True;
  end;
  with dbgItems.Columns.Add do
  begin
    FieldName := 'cantidad';
    Title.Caption := 'Cant. Consumo';
    Width := 120;
    ReadOnly := False;
  end;

  if FPresentacionId <> 0 then
    LoadData
  else
    DoAnadir;
end;

procedure TfrmFormatosPresentacionEditor.LoadData;
begin
  if FPresentacionId = 0 then Exit;

  dmgMain.qryExec.Close;
  dmgMain.qryExec.SQL.Text := 'SELECT id, descripcion, activo FROM ge_formatos_presentacion WHERE id = :id';
  dmgMain.qryExec.ParamByName('id').AsInteger := FPresentacionId;
  dmgMain.qryExec.Open;
  
  if not dmgMain.qryExec.IsEmpty then
  begin
    edtId.Text := IntToStr(FPresentacionId);
    edtDescripcion.Text := dmgMain.qryExec.FieldByName('descripcion').AsString;
    chkActivo.Checked := dmgMain.qryExec.FieldByName('activo').AsInteger <> 0;
  end;
  dmgMain.qryExec.Close;

  qDetail.Close;
  qDetail.ParamByName('id_formato').AsInteger := FPresentacionId;
  qDetail.Open;
end;

procedure TfrmFormatosPresentacionEditor.DoAnadir;
begin
  FPresentacionId := 0;
  edtId.Text := '(Nuevo)';
  edtDescripcion.Clear;
  chkActivo.Checked := True;
  
  qDetail.Close;
  qDetail.ParamByName('id_formato').AsInteger := 0;
  qDetail.Open;
  
  edtDescripcion.SetFocus;
end;

procedure TfrmFormatosPresentacionEditor.DoModificar;
begin
  edtDescripcion.SetFocus;
end;

procedure TfrmFormatosPresentacionEditor.DoPrimero;
var
  LParent: TfrmFormatosPresentacion;
begin
  LParent := nil;
  if Assigned(FParentForm) and (FParentForm is TfrmFormatosPresentacion) then
    LParent := TfrmFormatosPresentacion(FParentForm)
  else if Assigned(frmFormatosPresentacion) then
    LParent := frmFormatosPresentacion;

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

procedure TfrmFormatosPresentacionEditor.DoAnterior;
var
  LParent: TfrmFormatosPresentacion;
begin
  LParent := nil;
  if Assigned(FParentForm) and (FParentForm is TfrmFormatosPresentacion) then
    LParent := TfrmFormatosPresentacion(FParentForm)
  else if Assigned(frmFormatosPresentacion) then
    LParent := frmFormatosPresentacion;

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

procedure TfrmFormatosPresentacionEditor.DoSiguiente;
var
  LParent: TfrmFormatosPresentacion;
begin
  LParent := nil;
  if Assigned(FParentForm) and (FParentForm is TfrmFormatosPresentacion) then
    LParent := TfrmFormatosPresentacion(FParentForm)
  else if Assigned(frmFormatosPresentacion) then
    LParent := frmFormatosPresentacion;

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

procedure TfrmFormatosPresentacionEditor.DoUltimo;
var
  LParent: TfrmFormatosPresentacion;
begin
  LParent := nil;
  if Assigned(FParentForm) and (FParentForm is TfrmFormatosPresentacion) then
    LParent := TfrmFormatosPresentacion(FParentForm)
  else if Assigned(frmFormatosPresentacion) then
    LParent := frmFormatosPresentacion;

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

procedure TfrmFormatosPresentacionEditor.btnAddMaterialClick(Sender: TObject);
begin
  if not Assigned(frmSelectMateriaPrima) then
    Application.CreateForm(TfrmSelectMateriaPrima, frmSelectMateriaPrima);
  
  if frmSelectMateriaPrima.ShowModal = mrOk then
  begin
    if qDetail.Locate('id_materia_prima', frmSelectMateriaPrima.SelectedId, []) then
    begin
      ShowMessage('Este material ya ha sido añadido al formato.');
      Exit;
    end;

    qDetail.Append;
    qDetail.FieldByName('id_formato_presentacion').AsInteger := FPresentacionId;
    qDetail.FieldByName('id_materia_prima').AsString := frmSelectMateriaPrima.SelectedId;
    
    qDetail.FieldByName('materia_prima_descripcion').ReadOnly := False;
    try
      qDetail.FieldByName('materia_prima_descripcion').AsString := frmSelectMateriaPrima.SelectedDesc;
    finally
      qDetail.FieldByName('materia_prima_descripcion').ReadOnly := True;
    end;
    
    qDetail.FieldByName('cantidad').AsFloat := 1.0;
    qDetail.Post;
  end;
end;

procedure TfrmFormatosPresentacionEditor.btnDelMaterialClick(Sender: TObject);
begin
  if qDetail.Active and not qDetail.IsEmpty then
  begin
    if MessageDlg('¿Desea quitar el material seleccionado?', mtConfirmation, [mbYes, mbNo], 0) = mrYes then
      qDetail.Delete;
  end;
end;

procedure TfrmFormatosPresentacionEditor.btnDuplicarClick(Sender: TObject);
var
  LNewDesc: string;
  LNewId: Integer;
  LQry: TFDQuery;
begin
  if FPresentacionId = 0 then
  begin
    ShowMessage('Guarde o cargue un formato existente antes de duplicarlo.');
    Exit;
  end;

  LNewDesc := InputBox('Duplicar Formato de Presentación', 'Introduce el nombre del nuevo formato:', edtDescripcion.Text + ' (Copia)');
  if Trim(LNewDesc) = '' then Exit;

  if qDetail.State in [dsEdit, dsInsert] then
    qDetail.Post;

  LQry := TFDQuery.Create(nil);
  try
    LQry.Connection := dmgMain.dbConn;
    dmgMain.dbConn.StartTransaction;
    try
      LQry.SQL.Text := 
        'INSERT INTO ge_formatos_presentacion (descripcion, activo, id_user_creator, id_user_update) ' +
        'VALUES (:des, :act, :user, :user)';
      LQry.ParamByName('des').AsString := Trim(LNewDesc);
      LQry.ParamByName('act').AsInteger := 1;
      LQry.ParamByName('user').AsString := dmgMain.CurrentUserId;
      LQry.ExecSQL;

      LQry.SQL.Text := 'SELECT LAST_INSERT_ID()';
      LQry.Open;
      LNewId := LQry.Fields[0].AsInteger;
      LQry.Close;

      LQry.SQL.Text := 
        'INSERT INTO ge_formatos_presentacion_materiales (id_formato_presentacion, id_materia_prima, cantidad, id_user_creator) ' +
        'SELECT :new_id, id_materia_prima, cantidad, :user ' +
        'FROM ge_formatos_presentacion_materiales ' +
        'WHERE id_formato_presentacion = :old_id';
      LQry.ParamByName('new_id').AsInteger := LNewId;
      LQry.ParamByName('old_id').AsInteger := FPresentacionId;
      LQry.ParamByName('user').AsString := dmgMain.CurrentUserId;
      LQry.ExecSQL;

      dmgMain.dbConn.Commit;
      
      FPresentacionId := LNewId;
      LoadData;
      
      ShowMessage('Formato duplicado correctamente.');

      if Assigned(FParentForm) and (FParentForm is TfrmFormatosPresentacion) then
        TfrmFormatosPresentacion(FParentForm).btnRefreshClick(nil);
    except
      on E: Exception do
      begin
        dmgMain.dbConn.Rollback;
        TDbErrorHandler.HandleException(E, 'Error al duplicar el formato de presentación');
      end;
    end;
  finally
    LQry.Free;
  end;
end;

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

procedure TfrmFormatosPresentacionEditor.btnSaveClick(Sender: TObject);
var
  LIsNew: Boolean;
  LDetailQry: TFDQuery;
begin
  if Trim(edtDescripcion.Text) = '' then
  begin
    ShowMessage('Debe introducir la descripción del formato.');
    edtDescripcion.SetFocus;
    Exit;
  end;

  if qDetail.State in [dsEdit, dsInsert] then
    qDetail.Post;

  LIsNew := (FPresentacionId = 0);
  
  LDetailQry := TFDQuery.Create(nil);
  try
    LDetailQry.Connection := dmgMain.dbConn;
    dmgMain.dbConn.StartTransaction;
    try
      dmgMain.qryExec.Close;
      if LIsNew then
      begin
        dmgMain.qryExec.SQL.Text := 
          'INSERT INTO ge_formatos_presentacion (descripcion, activo, id_user_creator, id_user_update) ' +
          'VALUES (:des, :act, :user, :user)';
      end
      else
      begin
        dmgMain.qryExec.SQL.Text := 
          'UPDATE ge_formatos_presentacion SET descripcion = :des, activo = :act, ' +
          'id_user_update = :user, updated_at = CURRENT_TIMESTAMP ' +
          'WHERE id = :id';
        dmgMain.qryExec.ParamByName('id').AsInteger := FPresentacionId;
      end;

      dmgMain.qryExec.ParamByName('des').AsString := Trim(edtDescripcion.Text);
      dmgMain.qryExec.ParamByName('act').AsBoolean := chkActivo.Checked;
      dmgMain.qryExec.ParamByName('user').AsString := dmgMain.CurrentUserId;
      dmgMain.qryExec.ExecSQL;

      if LIsNew then
      begin
        dmgMain.qryExec.SQL.Text := 'SELECT LAST_INSERT_ID()';
        dmgMain.qryExec.Open;
        FPresentacionId := dmgMain.qryExec.Fields[0].AsInteger;
        dmgMain.qryExec.Close;
      end;

      LDetailQry.SQL.Text := 'DELETE FROM ge_formatos_presentacion_materiales WHERE id_formato_presentacion = :id_formato';
      LDetailQry.ParamByName('id_formato').AsInteger := FPresentacionId;
      LDetailQry.ExecSQL;

      qDetail.First;
      while not qDetail.Eof do
      begin
        LDetailQry.SQL.Text := 
          'INSERT INTO ge_formatos_presentacion_materiales (id_formato_presentacion, id_materia_prima, cantidad, id_user_creator) ' +
          'VALUES (:id_formato, :id_mp, :cant, :user)';
        LDetailQry.ParamByName('id_formato').AsInteger := FPresentacionId;
        LDetailQry.ParamByName('id_mp').AsInteger := qDetail.FieldByName('id_materia_prima').AsInteger;
        LDetailQry.ParamByName('cant').AsFloat := qDetail.FieldByName('cantidad').AsFloat;
        LDetailQry.ParamByName('user').AsString := dmgMain.CurrentUserId;
        LDetailQry.ExecSQL;

        qDetail.Next;
      end;

      dmgMain.dbConn.Commit;
      ResetChangeTracking;
      ShowMessage('Formato de presentación guardado correctamente.');

      if Assigned(FParentForm) and (FParentForm is TfrmFormatosPresentacion) then
      begin
        TfrmFormatosPresentacion(FParentForm).btnRefreshClick(nil);
        TfrmFormatosPresentacion(FParentForm).QryMain.Locate('id', FPresentacionId, []);
      end;
    except
      on E: Exception do
      begin
        dmgMain.dbConn.Rollback;
        TDbErrorHandler.HandleException(E, 'Error al guardar el formato de presentación');
      end;
    end;
  finally
    LDetailQry.Free;
  end;
end;

end.
