﻿unit dlgduplicar;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Data.DB, ZAbstractRODataset,
  ZAbstractDataset, ZDataset, Vcl.StdCtrls, Vcl.Mask, Vcl.DBCtrls;

type
  Tfdlgduplicar = class(TForm)
    comboserie: TDBLookupComboBox;
    Label1: TLabel;
    Label4: TLabel;
    Label5: TLabel;
    Label2: TLabel;
    Button1: TButton;
    dsqseries: TDataSource;
    qseries: TZQuery;
    qaux: TZQuery;
    qserieside: TIntegerField;
    qseriesid: TWideStringField;
    qseriesfechainicio: TDateField;
    qseriesfechafin: TDateField;
    qseriesnum_pedcliente: TIntegerField;
    qseriesnum_albaran: TIntegerField;
    qseriesnum_factura: TIntegerField;
    qseriesnum_expedicion: TIntegerField;
    qseriesnum_pedproveedor: TIntegerField;
    qseriesimp_albaran: TWideStringField;
    qseriesimp_factura: TWideStringField;
    qseriesactivo: TIntegerField;
    qseriesnum_presupuesto: TIntegerField;
    Edit1: TEdit;
    qseriesseriecontable: TWideStringField;
    MaskEdit1: TMaskEdit;
    procedure Button1Click(Sender: TObject);
    procedure FormShow(Sender: TObject);
    procedure dsqseriesDataChange(Sender: TObject; Field: TField);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  fdlgduplicar: Tfdlgduplicar;
  idserie,idalbaran,fecha,idempresa:string;
  desdepedidos:integer;

implementation

{$R *.dfm}

uses falbaranes, datos;


procedure Tfdlgduplicar.Button1Click(Sender: TObject);
var
  newserie, newnumalbaran, newfecha: string;
  LFecha: TDateTime;
  LColsHeader, LValsHeader: string;
  LColsDetail, LValsDetail: string;
  FName: string;
  i: Integer;
begin
  if desdepedidos = 1 then
  begin
    Exit;
  end;

  // 1. Validar y formatear fecha
  if not TryStrToDate(MaskEdit1.Text, LFecha) then
  begin
    ShowMessage('La fecha introducida no es válida.');
    MaskEdit1.SetFocus;
    Exit;
  end;
  newfecha := FormatDateTime('yyyy-mm-dd', LFecha);

  // 2. Determinar nueva serie y número de albarán
  newserie := Trim(qseriesid.AsString);
  if Trim(Edit1.Text) <> '' then
    newnumalbaran := Trim(Edit1.Text)
  else
    newnumalbaran := Trim(qseriesnum_albaran.AsString);

  if (newserie = '') or (newnumalbaran = '') or (StrToIntDef(newnumalbaran, 0) <= 0) then
  begin
    ShowMessage('Debe especificar una serie y un número de albarán válidos.');
    Exit;
  end;

  // 3. Comprobar si ya existe un albarán con la misma serie y número en la empresa
  qaux.Close;
  qaux.SQL.Clear;
  qaux.SQL.Add('select count(*) as cnt from albaranes where id = ' + QuotedStr(newnumalbaran) +
               ' and serie = ' + QuotedStr(newserie) +
               ' and idempresa = ' + idempresa);
  qaux.Open;
  if qaux.FieldByName('cnt').AsInteger > 0 then
  begin
    qaux.Close;
    ShowMessage('Ya existe un albarán con la serie ' + newserie + ' y número ' + newnumalbaran + ' para esta empresa.');
    Exit;
  end;
  qaux.Close;

  // 4. Construir dinámicamente columnas para albaranes (cabecera)
  qaux.SQL.Text := 'SELECT * FROM albaranes WHERE 1=0';
  qaux.Open;
  LColsHeader := '';
  LValsHeader := '';
  for i := 0 to qaux.FieldCount - 1 do
  begin
    FName := qaux.Fields[i].FieldName;

    if LColsHeader <> '' then
    begin
      LColsHeader := LColsHeader + ', ';
      LValsHeader := LValsHeader + ', ';
    end;

    LColsHeader := LColsHeader + '`' + FName + '`';

    if SameText(FName, 'id') then
      LValsHeader := LValsHeader + QuotedStr(newnumalbaran)
    else if SameText(FName, 'serie') then
      LValsHeader := LValsHeader + QuotedStr(newserie)
    else if SameText(FName, 'fecha') then
      LValsHeader := LValsHeader + QuotedStr(newfecha)
    else if SameText(FName, 'facturado') then
      LValsHeader := LValsHeader + '0'
    else if SameText(FName, 'idfactura') then
      LValsHeader := LValsHeader + 'NULL'
    else if SameText(FName, 'observaciones') then
      LValsHeader := LValsHeader + 'NULL'
    else
      LValsHeader := LValsHeader + '`' + FName + '`';
  end;
  qaux.Close;

  // 5. Construir dinámicamente columnas para albaranes_detalles (líneas)
  qaux.SQL.Text := 'SELECT * FROM albaranes_detalles WHERE 1=0';
  qaux.Open;
  LColsDetail := '';
  LValsDetail := '';
  for i := 0 to qaux.FieldCount - 1 do
  begin
    FName := qaux.Fields[i].FieldName;

    // Omitir la clave primaria AUTO_INCREMENT `id` para que MySQL genere nuevos correlativos
    if SameText(FName, 'id') then
      Continue;

    if LColsDetail <> '' then
    begin
      LColsDetail := LColsDetail + ', ';
      LValsDetail := LValsDetail + ', ';
    end;

    LColsDetail := LColsDetail + '`' + FName + '`';

    if SameText(FName, 'idalbaran') then
      LValsDetail := LValsDetail + QuotedStr(newnumalbaran)
    else if SameText(FName, 'serie') then
      LValsDetail := LValsDetail + QuotedStr(newserie)
    else if SameText(FName, 'idfactura') then
      LValsDetail := LValsDetail + 'NULL'
    else
      LValsDetail := LValsDetail + '`' + FName + '`';
  end;
  qaux.Close;

  // 6. Ejecutar inserciones dentro de transacción
  if (qseries.Connection <> nil) and (not qseries.Connection.InTransaction) then
    qseries.Connection.StartTransaction;
  try
    // Inserción de cabecera
    qaux.SQL.Text := 'INSERT INTO albaranes (' + LColsHeader + ') ' +
                     'SELECT ' + LValsHeader + ' FROM albaranes ' +
                     'WHERE id = ' + QuotedStr(idalbaran) + ' ' +
                     'AND serie = ' + QuotedStr(idserie) + ' ' +
                     'AND idempresa = ' + idempresa;
    qaux.ExecSQL;

    // Inserción de detalles (si existen líneas)
    if LColsDetail <> '' then
    begin
      qaux.SQL.Text := 'INSERT INTO albaranes_detalles (' + LColsDetail + ') ' +
                       'SELECT ' + LValsDetail + ' FROM albaranes_detalles ' +
                       'WHERE idalbaran = ' + QuotedStr(idalbaran) + ' ' +
                       'AND serie = ' + QuotedStr(idserie) + ' ' +
                       'AND idempresa = ' + idempresa + ' ' +
                       'ORDER BY id';
      qaux.ExecSQL;
    end;

    if (qseries.Connection <> nil) and qseries.Connection.InTransaction then
      qseries.Connection.Commit;
  except
    on E: Exception do
    begin
      if (qseries.Connection <> nil) and qseries.Connection.InTransaction then
        qseries.Connection.Rollback;
      raise Exception.Create('Error al duplicar el albarán: ' + E.Message);
    end;
  end;

  // 7. Actualizar contador correlativo en la serie numérica si procede
  if qseries.Active and not qseries.IsEmpty then
  begin
    qseries.Edit;
    if StrToIntDef(newnumalbaran, 0) >= qseriesnum_albaran.AsInteger then
      qseriesnum_albaran.Value := StrToInt(newnumalbaran) + 1;
    qseries.Post;
  end;

  idserie := newserie;
  idalbaran := newnumalbaran;
  Close;
end;

procedure Tfdlgduplicar.dsqseriesDataChange(Sender: TObject; Field: TField);
begin
  edit1.Text := qseriesnum_albaran.AsString;
end;

procedure Tfdlgduplicar.FormShow(Sender: TObject);
begin
  qseries.Open;
  if idserie <> '' then
    qseries.Locate('id', idserie, [loCaseInsensitive]);
  edit1.Text := qseriesnum_albaran.AsString;
  maskedit1.Text := DateToStr(Date());
end;

end.
