unit frm_FormatosEnvioEditor;

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;

type
  TfrmFormatosEnvioEditor = class(TfrmBase)
    lblId: TLabel;
    edtId: TEdit;
    lblDescripcion: TLabel;
    edtDescripcion: TEdit;
    lblCapacidad: TLabel;
    edtCapacidad: 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
    FEnvioId: Integer;
    FParentForm: TForm;
    procedure LoadData;
  public
    property EnvioId: Integer read FEnvioId write FEnvioId;
    property ParentForm: TForm read FParentForm write FParentForm;
  end;

var
  frmFormatosEnvioEditor: TfrmFormatosEnvioEditor;

implementation

uses
  dmg_Main, uDbErrorHandler, frm_FormatosEnvio, frm_SelectMateriaPrima;

{$R *.dfm}

procedure TfrmFormatosEnvioEditor.Loaded;
begin
  inherited Loaded;
  qDetail.SQL.Text := 
    'SELECT em.*, m.descripcion AS materia_prima_descripcion ' +
    'FROM ge_formatos_envio_materiales em ' +
    'LEFT JOIN ge_materias_primas m ON em.id_materia_prima = m.id ' +
    'WHERE em.id_embalaje_final = :id_formato';
end;

procedure TfrmFormatosEnvioEditor.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 Embalaje';
    Width := 350;
    ReadOnly := True;
  end;
  with dbgItems.Columns.Add do
  begin
    FieldName := 'cantidad';
    Title.Caption := 'Cant. Consumo';
    Width := 120;
    ReadOnly := False;
  end;

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

procedure TfrmFormatosEnvioEditor.LoadData;
begin
  if FEnvioId = 0 then Exit;

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

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

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

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

procedure TfrmFormatosEnvioEditor.DoPrimero;
var
  LParent: TfrmFormatosEnvio;
begin
  LParent := nil;
  if Assigned(FParentForm) and (FParentForm is TfrmFormatosEnvio) then
    LParent := TfrmFormatosEnvio(FParentForm)
  else if Assigned(frmFormatosEnvio) then
    LParent := frmFormatosEnvio;

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

procedure TfrmFormatosEnvioEditor.DoAnterior;
var
  LParent: TfrmFormatosEnvio;
begin
  LParent := nil;
  if Assigned(FParentForm) and (FParentForm is TfrmFormatosEnvio) then
    LParent := TfrmFormatosEnvio(FParentForm)
  else if Assigned(frmFormatosEnvio) then
    LParent := frmFormatosEnvio;

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

procedure TfrmFormatosEnvioEditor.DoSiguiente;
var
  LParent: TfrmFormatosEnvio;
begin
  LParent := nil;
  if Assigned(FParentForm) and (FParentForm is TfrmFormatosEnvio) then
    LParent := TfrmFormatosEnvio(FParentForm)
  else if Assigned(frmFormatosEnvio) then
    LParent := frmFormatosEnvio;

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

procedure TfrmFormatosEnvioEditor.DoUltimo;
var
  LParent: TfrmFormatosEnvio;
begin
  LParent := nil;
  if Assigned(FParentForm) and (FParentForm is TfrmFormatosEnvio) then
    LParent := TfrmFormatosEnvio(FParentForm)
  else if Assigned(frmFormatosEnvio) then
    LParent := frmFormatosEnvio;

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

procedure TfrmFormatosEnvioEditor.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_embalaje_final').AsInteger := FEnvioId;
    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 TfrmFormatosEnvioEditor.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 TfrmFormatosEnvioEditor.btnDuplicarClick(Sender: TObject);
var
  LNewDesc: string;
  LNewId: Integer;
  LQry: TFDQuery;
begin
  if FEnvioId = 0 then
  begin
    ShowMessage('Guarde o cargue un formato existente antes de duplicarlo.');
    Exit;
  end;

  LNewDesc := InputBox('Duplicar Formato de Envío', '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_envio (descripcion, capacidad_unidades, activo, id_user_creator, id_user_update) ' +
        'VALUES (:des, :cap, :act, :user, :user)';
      LQry.ParamByName('des').AsString := Trim(LNewDesc);
      LQry.ParamByName('cap').AsInteger := StrToIntDef(edtCapacidad.Text, 1);
      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_envio_materiales (id_embalaje_final, id_materia_prima, cantidad, id_user_creator) ' +
        'SELECT :new_id, id_materia_prima, cantidad, :user ' +
        'FROM ge_formatos_envio_materiales ' +
        'WHERE id_embalaje_final = :old_id';
      LQry.ParamByName('new_id').AsInteger := LNewId;
      LQry.ParamByName('old_id').AsInteger := FEnvioId;
      LQry.ParamByName('user').AsString := dmgMain.CurrentUserId;
      LQry.ExecSQL;

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

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

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

procedure TfrmFormatosEnvioEditor.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 := (FEnvioId = 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_envio (descripcion, capacidad_unidades, activo, id_user_creator, id_user_update) ' +
          'VALUES (:des, :cap, :act, :user, :user)';
      end
      else
      begin
        dmgMain.qryExec.SQL.Text := 
          'UPDATE ge_formatos_envio SET descripcion = :des, capacidad_unidades = :cap, activo = :act, ' +
          'id_user_update = :user, updated_at = CURRENT_TIMESTAMP ' +
          'WHERE id = :id';
        dmgMain.qryExec.ParamByName('id').AsInteger := FEnvioId;
      end;

      dmgMain.qryExec.ParamByName('des').AsString := Trim(edtDescripcion.Text);
      dmgMain.qryExec.ParamByName('cap').AsInteger := StrToIntDef(edtCapacidad.Text, 1);
      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;
        FEnvioId := dmgMain.qryExec.Fields[0].AsInteger;
        dmgMain.qryExec.Close;
      end;

      LDetailQry.SQL.Text := 'DELETE FROM ge_formatos_envio_materiales WHERE id_embalaje_final = :id_formato';
      LDetailQry.ParamByName('id_formato').AsInteger := FEnvioId;
      LDetailQry.ExecSQL;

      qDetail.First;
      while not qDetail.Eof do
      begin
        LDetailQry.SQL.Text := 
          'INSERT INTO ge_formatos_envio_materiales (id_embalaje_final, id_materia_prima, cantidad, id_user_creator) ' +
          'VALUES (:id_formato, :id_mp, :cant, :user)';
        LDetailQry.ParamByName('id_formato').AsInteger := FEnvioId;
        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 envío guardado correctamente.');

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

end.
