unit frm_MovimientosInternos;

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, uAppTheme, FireDAC.Stan.Param, FireDAC.Comp.Client,
  System.UITypes, frm_BaseList;

type
  TfrmMovimientosInternos = 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 dbGridMainDblClick(Sender: TObject);
  public
    { Public declarations }
  end;

var
  frmMovimientosInternos: TfrmMovimientosInternos;

implementation

uses
  dmg_Main, frm_MovimientoInternoEditor, uDbErrorHandler, frm_AlbaranesEditor, frm_ProvAlbaranesEditor;

{$R *.dfm}

procedure TfrmMovimientosInternos.FormShow(Sender: TObject);
begin
  inherited;
  frmMovimientosInternos := Self;
  OnDestroy := FormDestroy;
  pnlSearch.Visible := True;
  lblSearch.Caption := 'Buscar Movimiento:';
  dbGridMain.OnDblClick := dbGridMainDblClick;
  btnRefreshClick(nil);
end;

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

procedure TfrmMovimientosInternos.dbGridMainDblClick(Sender: TObject);
begin
  btnEditClick(nil);
end;

procedure TfrmMovimientosInternos.btnRefreshClick(Sender: TObject);
var
  LSql: string;
begin
  FQryMain.Close;
  LSql :=
    'SELECT m.id, m.fecha, ' +
    '  CONCAT(''['', m.tipo_origen, ''] '', ao.descripcion) AS origen_desc, ' +
    '  eo.nombre AS empresa_origen, ' +
    '  CONCAT(''['', m.tipo_destino, ''] '', ad.descripcion) AS destino_desc, ' +
    '  ed.nombre AS empresa_destino, ' +
    '  a.descripcion AS articulo_nombre, ' +
    '  COALESCE(l.codigo, ''-'') AS lote_codigo, ' +
    '  m.cantidad, m.precio_unitario, m.es_interempresa, ' +
    '  m.id_albaran_venta, m.id_albaran_compra, ' +
    '  CONCAT(COALESCE(av.serie, ''''), ''-'', COALESCE(av.numero, '''')) AS alb_venta_num, ' +
    '  COALESCE(ac.documento, ''-'') AS alb_compra_num, ' +
    '  m.observaciones ' +
    'FROM ge_movimientos_internos m ' +
    'LEFT JOIN ge_almacenes ao ON m.id_almacen_origen = ao.id ' +
    'LEFT JOIN ge_almacenes ad ON m.id_almacen_destino = ad.id ' +
    'LEFT JOIN ge_empresas eo ON m.id_empresa_origen = eo.id ' +
    'LEFT JOIN ge_empresas ed ON m.id_empresa_destino = ed.id ' +
    'LEFT JOIN ge_articulos a ON m.id_articulo = a.id ' +
    'LEFT JOIN ge_lotes l ON m.id_lote = l.id ' +
    'LEFT JOIN ge_albaranes av ON m.id_albaran_venta = av.id ' +
    'LEFT JOIN ge_prov_albaranes ac ON m.id_albaran_compra = ac.id ' +
    'WHERE (m.id_empresa_origen = :emp OR m.id_empresa_destino = :emp OR :emp = 0) ';

  if Trim(edtSearch.Text) <> '' then
  begin
    LSql := LSql +
      'AND (a.descripcion LIKE :search OR l.codigo LIKE :search OR ao.descripcion LIKE :search ' +
      '     OR ad.descripcion LIKE :search OR m.observaciones LIKE :search ' +
      '     OR eo.nombre LIKE :search OR ed.nombre LIKE :search) ';
  end;

  LSql := LSql + 'ORDER BY m.fecha DESC, m.id DESC LIMIT 300';

  FQryMain.SQL.Text := LSql;
  FQryMain.ParamByName('emp').AsInteger := StrToIntDef(dmgMain.CurrentCompanyId, 0);

  if Trim(edtSearch.Text) <> '' then
    FQryMain.ParamByName('search').AsString := '%' + Trim(edtSearch.Text) + '%';

  FQryMain.Open;

  dbGridMain.Columns.Clear;
  with dbGridMain.Columns.Add do
  begin
    FieldName := 'fecha';
    Title.Caption := 'Fecha / Hora';
    Width := 130;
  end;
  with dbGridMain.Columns.Add do
  begin
    FieldName := 'origen_desc';
    Title.Caption := 'Ubicación Origen';
    Width := 160;
  end;
  with dbGridMain.Columns.Add do
  begin
    FieldName := 'empresa_origen';
    Title.Caption := 'Empresa Origen';
    Width := 140;
  end;
  with dbGridMain.Columns.Add do
  begin
    FieldName := 'destino_desc';
    Title.Caption := 'Ubicación Destino';
    Width := 160;
  end;
  with dbGridMain.Columns.Add do
  begin
    FieldName := 'empresa_destino';
    Title.Caption := 'Empresa Destino';
    Width := 140;
  end;
  with dbGridMain.Columns.Add do
  begin
    FieldName := 'articulo_nombre';
    Title.Caption := 'Artículo';
    Width := 180;
  end;
  with dbGridMain.Columns.Add do
  begin
    FieldName := 'lote_codigo';
    Title.Caption := 'Lote';
    Width := 90;
  end;
  with dbGridMain.Columns.Add do
  begin
    FieldName := 'cantidad';
    Title.Caption := 'Cantidad';
    Width := 75;
  end;
  with dbGridMain.Columns.Add do
  begin
    FieldName := 'es_interempresa';
    Title.Caption := 'Interempresa';
    Width := 80;
  end;
  with dbGridMain.Columns.Add do
  begin
    FieldName := 'alb_venta_num';
    Title.Caption := 'Alb. Venta';
    Width := 85;
  end;
  with dbGridMain.Columns.Add do
  begin
    FieldName := 'alb_compra_num';
    Title.Caption := 'Alb. Compra';
    Width := 85;
  end;
  with dbGridMain.Columns.Add do
  begin
    FieldName := 'observaciones';
    Title.Caption := 'Observaciones';
    Width := 200;
  end;
end;

procedure TfrmMovimientosInternos.btnNewClick(Sender: TObject);
var
  LFrm: TfrmMovimientoInternoEditor;
begin
  LFrm := TfrmMovimientoInternoEditor.Create(Self);
  try
    if LFrm.ShowModal = mrOk then
      btnRefreshClick(nil);
  finally
    LFrm.Free;
  end;
end;

procedure TfrmMovimientosInternos.btnEditClick(Sender: TObject);
var
  LAlbVentaId, LAlbCompraId: Integer;
  LFrmAlb: TfrmAlbaranesEditor;
begin
  if FQryMain.IsEmpty then Exit;

  LAlbVentaId := FQryMain.FieldByName('id_albaran_venta').AsInteger;
  LAlbCompraId := FQryMain.FieldByName('id_albaran_compra').AsInteger;

  if (LAlbVentaId > 0) or (LAlbCompraId > 0) then
  begin
    if MessageDlg(Format('Este movimiento interempresa generó documentos oficiales:'#13#10 +
      '• Albarán de Venta: %s'#13#10 +
      '• Albarán de Compra: %s'#13#10#13#10 +
      '¿Desea abrir el Albarán de Venta para consultar su detalle?',
      [FQryMain.FieldByName('alb_venta_num').AsString,
       FQryMain.FieldByName('alb_compra_num').AsString]),
      mtInformation, [mbYes, mbNo], 0) = mrYes then
    begin
      LFrmAlb := TfrmAlbaranesEditor.Create(Self);
      try
        LFrmAlb.AlbaranId := IntToStr(LAlbVentaId);
        LFrmAlb.ShowModal;
      finally
        LFrmAlb.Free;
      end;
    end;
  end
  else
  begin
    ShowMessage(Format('Detalles del Movimiento Interno (ID %d):'#13#10 +
      '• Fecha: %s'#13#10 +
      '• Origen: %s (%s)'#13#10 +
      '• Destino: %s (%s)'#13#10 +
      '• Artículo: %s (Lote: %s)'#13#10 +
      '• Cantidad: %.2f uds'#13#10 +
      '• Observaciones: %s',
      [FQryMain.FieldByName('id').AsInteger,
       FQryMain.FieldByName('fecha').AsString,
       FQryMain.FieldByName('origen_desc').AsString,
       FQryMain.FieldByName('empresa_origen').AsString,
       FQryMain.FieldByName('destino_desc').AsString,
       FQryMain.FieldByName('empresa_destino').AsString,
       FQryMain.FieldByName('articulo_nombre').AsString,
       FQryMain.FieldByName('lote_codigo').AsString,
       FQryMain.FieldByName('cantidad').AsFloat,
       FQryMain.FieldByName('observaciones').AsString]));
  end;
end;

procedure TfrmMovimientosInternos.btnDeleteClick(Sender: TObject);
begin
  ShowMessage('Por motivos de trazabilidad y auditoría de inventario, los registros históricos de traspaso no pueden eliminarse directamente. Para corregir discrepancias, realice un nuevo movimiento de ajuste o inventario.');
end;

end.
