unit uBizFechasObra;

interface

uses
  uDAInterfaces, uDADataTable;

const
  TIPODETALLE_CONCEPTO = 'Concepto';
  TIPODETALLE_SUBTOTAL = 'S';
  TIPODETALLE_COMENTARIO = 'Comentario';
  fld_POSICION = 'POSICION';
  fld_TIPODETALLE = 'TIPO';
  fld_IMPORTETOTAL = 'IMPORTETOTAL';
  fld_CANTIDAD = 'CANTIDAD';
  fld_IMPORTEUNIDAD = 'IMPORTEUNIDAD';

type

  TBizFechaIniFieldRules = class(TDAFieldRules)
  protected
    procedure OnChange(Sender: TDACustomField); override;
  end;

  TBizFechaFinFieldRules = class(TDAFieldRules)
  protected
    procedure OnChange(Sender: TDACustomField); override;
  end;



{function DarMaximaPosicion(aDataTable : TDADataTable): integer;
procedure ReasignarPosiciones(aDataTable : TDADataTable);
procedure AsignarPosicion(aDataTable : TDADataTable; IsAppend : Boolean);

function DarTotalDetalles(aDataTable : TDADataTable; TieneSubtotales : Boolean) : Currency;
procedure IntercambiarPosiciones(aDataTable : TDADataTable; Pos1, Pos2 : Integer);
}

implementation

uses
  SysUtils, DB, Controls, Forms, Dialogs, schObrasClient_Intf, uBizObra;
{
procedure IntercambiarPosiciones(aDataTable : TDADataTable; Pos1, Pos2 : Integer);
var
  ABookmark : Pointer;
  AField : TDAField;
  AFieldTipo : TDAField;
  ACursor: TCursor;
  bRecalcular : Boolean;
begin
  if not Assigned(aDataTable) then
    raise Exception.Create('Tabla no asignada (IntercambiarPosicion)');

  AField := aDataTable.FindField(fld_POSICION);
  if not Assigned(AField) then
    raise Exception.Create('Campo POSICION no encontrado (IntercambiarPosicion)');

  // No importa si el TIPO no está en la lista de columnas
  AFieldTipo := aDataTable.FindField(fld_TIPODETALLE);

  bRecalcular := False;
  ACursor := Screen.Cursor;
  Screen.Cursor := crHourGlass;
  aDataTable.DisableEventHandlers;
  aDataTable.DisableControls;
  ABookmark := aDataTable.GetBookMark;
  try
    aDataTable.First;
    if aDataTable.Locate(fld_POSICION, Pos1, []) then
    begin
      // Si alguna de las dos filas es un subtotal, hay que recalcular todo
      if Assigned(AFieldTipo) and (AFieldTipo.AsString = TIPODETALLE_SUBTOTAL) then
        bRecalcular := True;

      aDataTable.Edit;
      AField.AsInteger := -1;
      aDataTable.Post;

      aDataTable.First;
      if aDataTable.Locate(fld_POSICION, Pos2, []) then
      begin
        // Si alguna de las dos filas es un subtotal, hay que recalcular todo
        if Assigned(AFieldTipo) and (AFieldTipo.AsString = TIPODETALLE_SUBTOTAL) then
          bRecalcular := True;

        aDataTable.Edit;
        AField.AsInteger := Pos1;
        aDataTable.Post;

        aDataTable.First;
        aDataTable.Locate(fld_POSICION, -1, []);
        aDataTable.Edit;
        AField.AsInteger := Pos2;
        aDataTable.Post;
      end
      else
        raise Exception.Create('No se ha encontrado posición 2 (IntercambiarPosicion)');
    end
    else
      raise Exception.Create('No se ha encontrado posición 1 (IntercambiarPosicion)');
  finally
    aDataTable.GotoBookmark(ABookmark);
    aDataTable.EnableControls;
    aDataTable.EnableEventHandlers;
    if bRecalcular then
      DarTotalDetalles(aDataTable, True);
    Screen.Cursor := ACursor;
  end;
end;

{function DarMaximaPosicion(aDataTable : TDADataTable): integer;
var
  ABookmark : Pointer;
  AField : TDAField;
  ACursor: TCursor;
begin
  //Sort(['ForeignKeyFieldofMasterDetailRelation','YourSortField'],[sdAscending, NeededOrder ]);
  Result := 0;

  if not Assigned(aDataTable) then
    raise Exception.Create('Tabla no asignada (DarMaximaPosicion)');

  AField := aDataTable.FindField(fld_POSICION);
  if not Assigned(AField) then
    raise Exception.Create('Campo POSICION no encontrado (DarMaximaPosicion)');

  ACursor := Screen.Cursor;
  Screen.Cursor := crHourGlass;
  ABookmark := aDataTable.GetBookMark;
  try
    aDataTable.DisableControls;
    aDataTable.First;
    while not aDataTable.Eof do
    begin
      if AField.AsInteger > Result then
        Result := AField.AsInteger;
      aDataTable.Next;
    end;
  finally
    aDataTable.GotoBookmark(ABookmark);
    aDataTable.EnableControls;
    Screen.Cursor := ACursor;
  end;
end;}

{procedure ReasignarPosiciones(aDataTable : TDADataTable);
var
  AField : TDAField;
  ABookmark : Pointer;
  Contador : Integer;
  NumCon : Integer;
  TotalConceptos : Integer;
  DetallesEditados : Integer;
  ACursor: TCursor;
begin
  if not Assigned(aDataTable) then
    raise Exception.Create('Tabla no asignada (ReasignarNumConceptos)');

  AField := aDataTable.FindField(fld_POSICION);
  if not Assigned(AField) then
    raise Exception.Create('Campo POSICION no encontrado (ReasignarNumConceptos)');

  Contador := 1;
  NumCon := 1;
  TotalConceptos := aDataTable.RecordCount;
  DetallesEditados := 0;

  ACursor := Screen.Cursor;
  Screen.Cursor := crHourGlass;
  ABookmark := aDataTable.GetBookMark;
  aDataTable.DisableControls;
  try
    aDataTable.First;
    while DetallesEditados < TotalConceptos do
    begin
      if aDataTable.Locate(fld_POSICION, Contador, []) then
      begin
        aDataTable.Edit;
        AField.Value := NumCon;
        Inc(NumCon);
        aDataTable.Post;
        Inc(DetallesEditados);
        aDataTable.First;
      end;
      Inc(Contador);
    end;
  finally
    aDataTable.EnableControls;
    aDataTable.GotoBookmark(ABookmark);
    Screen.Cursor := ACursor;
  end;
end;

procedure AsignarPosicion(aDataTable : TDADataTable; IsAppend : Boolean);
var
  AField : TDAField;
  ABookmark : Pointer;
  NumPosicion : Integer;
  MaxPosicion : Integer;
  ACursor: TCursor;
begin
  if not Assigned(aDataTable) then
    raise Exception.Create('Tabla no asignada (AsignarPosicion)');

  AField := aDataTable.FindField(fld_POSICION);
  if not Assigned(AField) then
    raise Exception.Create('Campo POSICION no encontrado (AsignarPosicion)');

  if not IsAppend then
  begin
    if not aDataTable.IsEmpty then
    begin
      ACursor := Screen.Cursor;
      Screen.Cursor := crHourGlass;
      // Mover las filas que están por debajo de la actual
      MaxPosicion := DarMaximaPosicion(aDataTable);
      NumPosicion := (AField.AsInteger * (-1));
      ABookmark := aDataTable.GetBookMark;
      try
        aDataTable.First;
        while aDataTable.Locate(fld_POSICION, MaxPosicion, []) do
        begin
          aDataTable.Edit;
          AField.Value := MaxPosicion + 1;
          aDataTable.Post;
          aDataTable.First;
          if MaxPosicion = NumPosicion then
            Break
          else
            Dec(MaxPosicion);
        end
      finally
        aDataTable.GotoBookmark(ABookmark);
        Screen.Cursor := ACursor;
      end;
    end;
    NumPosicion := (AField.AsInteger * (-1));
  end
  else begin
    if aDataTable.RecordCount > 1 then
      NumPosicion := DarMaximaPosicion(aDataTable) + 1
    else
      // Sólo hay una fila en toda la tabla
      NumPosicion := (AField.AsInteger * (-1));
  end;

  // Asignar posición a la nueva fila
  aDataTable.Edit;
  AField.Value := NumPosicion;
  aDataTable.Post;
end;

procedure CalcularImportesLinea(aDataTable : TDADataTable; TieneSubtotales : Boolean);
var
  ACabecera : IBizImportesCabecera;
  TipoField : TDAField;
  TotalField : TDAField;
  CantidadField : TDAField;
  ImporteUnidadField : TDAField;
begin
  if not Assigned(aDataTable) then
    raise Exception.Create('Tabla no asignada (CalcularImportesLinea)');

  TotalField := aDataTable.FindField(fld_IMPORTETOTAL);
  if not Assigned(TotalField) then
    raise Exception.Create('Campo IMPORTETOTAL no encontrado (CalcularImportesLinea)');

  CantidadField := aDataTable.FindField(fld_CANTIDAD);
  if not Assigned(CantidadField) then
    raise Exception.Create('Campo CANTIDAD no encontrado (CalcularImportesLinea)');

  ImporteUnidadField := aDataTable.FindField(fld_IMPORTEUNIDAD);
  if not Assigned(ImporteUnidadField) then
    raise Exception.Create('Campo IMPORTEUNIDAD no encontrado (CalcularImportesLinea)');

  if TieneSubtotales then
  begin
    TipoField := aDataTable.FindField(fld_TIPODETALLE);
    if not Assigned(TipoField) then
      raise Exception.Create('Campo TIPO no encontrado (CalcularImportesLinea)');

    if TipoField.AsString = TIPODETALLE_SUBTOTAL then
      Exit;
  end;

  aDataTable.Edit;
  TotalField.Value := CantidadField.AsCurrency * ImporteUnidadField.AsCurrency;
  aDataTable.Post;

  if Assigned(aDataTable.MasterSource) and
     Supports(aDataTable.MasterSource.DataTable, IBizImportesCabecera, ACabecera) then
     ACabecera.CalcularImportes;
end;

function DarTotalDetalles(aDataTable : TDADataTable; TieneSubtotales : Boolean) : Currency;
var
  ABookmark : Pointer;
  APosicion : Integer;
  MaxPos : Integer;
  Total : Currency;
  Subtotal : Currency;
  TipoField : TDAField;
  TotalField : TDAField;
  ACursor: TCursor;
begin
  Result := 0;

  if not Assigned(aDataTable) then
    raise Exception.Create('Tabla no asignada (DarTotalDetalles)');

  if TieneSubtotales then
  begin
    TipoField := aDataTable.FindField(fld_TIPODETALLE);
    if not Assigned(TipoField) then
      raise Exception.Create('Campo TIPO no encontrado (DarTotalDetalles)');

{    if TipoField.AsString = TIPODETALLE_SUBTOTAL then
      Exit;}
{  end;

  TotalField := aDataTable.FindField(fld_IMPORTETOTAL);
  if not Assigned(TotalField) then
    raise Exception.Create('Campo IMPORTETOTAL no encontrado (DarTotalDetalles)');


  ABookmark := aDataTable.GetBookMark;
  ACursor := Screen.Cursor;
  Screen.Cursor := crHourGlass;
  aDataTable.DisableControls;

  APosicion := 1;
  Total := 0;
  Subtotal := 0;
  try
    MaxPos := DarMaximaPosicion(aDataTable);
    while (APosicion <= MaxPos) do
    begin
      aDataTable.First;
      if aDataTable.Locate(fld_POSICION, APosicion, []) then
      begin
        if TieneSubtotales and
           (TipoField.AsString = TIPODETALLE_SUBTOTAL) then
        begin
          aDataTable.Edit;
          TotalField.Value := SubTotal;
          aDataTable.Post;
          Total := Total + SubTotal;
          Subtotal := 0;
        end
        else begin
          Subtotal := Subtotal + TotalField.AsCurrency;
          if (APosicion = MaxPos) then
            Total := Total + SubTotal;
        end;
        Inc(APosicion);
      end
      else
        Break;
    end;
  finally
    Result := Total;
    aDataTable.GotoBookmark(ABookmark);
    aDataTable.EnableControls;
    Screen.Cursor := ACursor;
  end;
end;
}



{ TBizCantidadFieldRules }

procedure TBizFechaIniFieldRules.OnChange(Sender: TDACustomField);
//var
//  aDetalle : IBizImportesDetalle;
begin
  inherited;
  showmessage('Hola Ini');
//  if Supports(DataTable, IBizImportesDetalle, aDetalle) then
//    CalcularImportesLinea(aDetalle.DataTable, True);
end;

procedure TBizFechaFinFieldRules.OnChange(Sender: TDACustomField);
var
  AObj : IBizFechasObra;
  AFechaIni: TDAField;
  AFechaFin: TDAField;
begin
  inherited;
//  showmessage('Hola Fin');

//Sender.AsDateTime
//  ComprobarFecha
  if Supports(DataTable, IBizFechasObra, AObj) then
  begin
     AFechaIni := AObj.DataTable.FindField(fld_ObrasFECHAINIOBR);
     AFechaFin := AObj.DataTable.FindField(fld_ObrasFECHAFINOBR);
     case ComprobarFecha(AFechaIni.AsDateTime, AFechaFin.AsDateTime) of
     0: showmessage('son Iguales');
     1: showmessage('FechaIni es una fecha posterior a fechaFin');
     2: showmessage('FechaFin es una fecha posterior a fechaIni');
     end;
  end;
//    CalcularImportesLinea(aDetalle.DataTable, True);
end;

initialization
  RegisterFieldRules('Client.Field.FechaIni', TBizFechaIniFieldRules);
  RegisterFieldRules('Client.Field.FechaFin', TBizFechaFinFieldRules);

finalization

end.
