unit InformeEstadistico;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  RdxFrame, RdxDBFrame, RdxTitulos, RdxPaneles, dxDBTLCl, dxGrClms, dxTL,
  dxDBCtrl, dxDBGrid, Db, IBCustomDataSet, IBQuery, IBDatabase, dxCntner,
  ExtCtrls, RxMemDS, Tipos, StdCtrls, RdxComboBox, TeEngine, TeeFunci,
  Series, TeeProcs, Chart, DBChart, RdxBotones, RdxBarras;

type
  TfrInformeEstadistico = class(TRdxDBFrame)
    Titulo: TRdxPanelTituloOperacion;
    pnlScroll: TRdxScrollPanel;
    dsResumen1: TDataSource;
    pnlResumen: TRdxPanel;
    cResumen1: TRdxCabecera;
    pnlGeneral: TRdxPanel;
    dsIntervalo: TDataSource;
    dsAnoCom1: TDataSource;
    dsAnoCom2: TDataSource;
    dsComparativa: TDataSource;
    TMemIntervalo: TRxMemoryData;
    TMemAnoCom1: TRxMemoryData;
    TMemAnoCom2: TRxMemoryData;
    TMemComparativa: TRxMemoryData;
    cGeneral: TRdxCabecera;
    pnlDatosGen: TPanel;
    pnlTotales: TPanel;
    pnlTotalComparativa: TPanel;
    pnlTotalAnoCom2: TPanel;
    pnlTotalAnoCom1: TPanel;
    pnlTotalIntervalo: TPanel;
    pnlTitulos: TPanel;
    pnlTitulo4: TPanel;
    pnlTitulo3: TPanel;
    pnlTitulo2: TPanel;
    pnlTitulo1: TPanel;
    pnlFiltros: TPanel;
    pnlFiltro4: TPanel;
    pnlFiltro3: TPanel;
    cbxFiltro3: TRdxComboBox;
    pnlFiltro2: TPanel;
    cbxFiltro2: TRdxComboBox;
    pnlFiltro1: TPanel;
    cbxFiltro1: TRdxComboBox;
    pnlTablas: TPanel;
    pnl4: TPanel;
    pnl3: TPanel;
    pnl2: TPanel;
    pnl1: TPanel;
    gridIntervalo: TdxDBGrid;
    gridAnoCom1: TdxDBGrid;
    gridAnoCom2: TdxDBGrid;
    gridComparativa: TdxDBGrid;
    pnlDatosResumen: TPanel;
    pnlGrid: TPanel;
    pnlTitulosResumen: TPanel;
    TablaResumen1Mem: TRxMemoryData;
    gridResumen: TdxDBGrid;
    pnlGraficoGen: TPanel;
    TMemGraficoAno1: TRxMemoryData;
    TMemGraficoAno2: TRxMemoryData;
    brSimple: TRdxBarraInferior;
    bImprimir: TRdxBoton;
    bCancelar: TRdxBoton;

    procedure gridCustomDrawCell(Sender: TObject; ACanvas: TCanvas;
      ARect: TRect; ANode: TdxTreeListNode; AColumn: TdxTreeListColumn;
      ASelected, AFocused, ANewItemRow: Boolean; var AText: String;
      var AColor: TColor; AFont: TFont; var AAlignment: TAlignment;
      var ADone: Boolean); virtual;

    procedure pnl1Resize(Sender: TObject);
    procedure pnl2Resize(Sender: TObject);
    procedure pnl3Resize(Sender: TObject);
    procedure pnl4Resize(Sender: TObject);
    procedure cbxFiltro2Change(Sender: TObject);
    procedure cbxFiltro3Change(Sender: TObject);
    procedure cbxFiltro1Change(Sender: TObject);

  private
    FTopN: Integer;
    FIntervalo: TTipoIntervalo;
    FAnosMem: TStrings;
    FAno1: Variant;
    FAno2: Variant;

    procedure SetTopN(const Value: Integer);
    procedure SetIntervalo(const Value: TTipoIntervalo);
    procedure SetAnosMem(const Value: TStrings);
    procedure RellenarAno2;

    function RellenarIntervalos: Boolean;
    function DibujarGrafico: Boolean;
    function InicializarGeneral: Boolean;
    function RefrescarGeneral: Boolean;

  protected
    procedure SetAno1(const Value: Variant); virtual;
    procedure SetAno2(const Value: Variant); virtual;
    procedure setTamPaneles; virtual;
    function InicializarFiltros: Boolean; virtual;
    function InicializarGrids: Boolean; virtual;
    function InicializarCamposTMem: Boolean; virtual;
    function CalcularDatos: Boolean; virtual; abstract;
    function CalcularResta (const x1, x2: Integer): Integer; overload;
    function CalcularResta (const x1, x2: Double): Double; overload;
    function CalcularPorcentaje (const x1, x2: Double; Incremento: Boolean): Double;

    function InicializarResumenes: Boolean; virtual; abstract;
    function RefrescarResumenes: Boolean; virtual; abstract;
    function FinalizarResumenes: Boolean; virtual; abstract;

  public
    property TopN: Integer read FTopN write SetTopN;
    property Intervalo: TTipoIntervalo read FIntervalo write SetIntervalo;
    property AnosMem: TStrings read FAnosMem write SetAnosMem;
    property Ano1: Variant read FAno1 write SetAno1;
    property Ano2: Variant read FAno2 write SetAno2;

    constructor Create (AOwner : TComponent); override;
    destructor Destroy; override;
  end;

var
  frInformeEstadistico: TfrInformeEstadistico;

implementation
{$R *.DFM}

uses BaseDatos, Entidades, RdxEmpresaActiva, Mensajes, Constantes, DateFunc,
Colores, IBSQL, IB, Excepciones, Literales;

function TfrInformeEstadistico.inicializarGeneral: Boolean;
begin
  InicializarGrids;
  InicializarCamposTMem;
end;

constructor TfrInformeEstadistico.Create(AOwner: TComponent);
begin
  inherited;
  FTopN := CTE_TOP;
  FIntervalo := tiMensual;
  FAnosMem := Nil;
  FAno1 := Null;
  FAno2 := Null;

  InicializarGeneral;
  InicializarResumenes;
  InicializarFiltros;  
end;

destructor TfrInformeEstadistico.Destroy;
begin
// finalizarGeneral;
  FinalizarResumenes;

  FAnosMem.Free;
  FAnosMem := Nil;
  inherited;
end;

procedure TfrInformeEstadistico.SetAno1(const Value: Variant);
var
  Bloqueo: Boolean;

begin
  if FAno1 <> Value then
  begin
    FAno1 := Value;

    Bloqueo := LockWindowUpdate(Application.MainForm.Handle);
    RellenarAno2;
    RefrescarGeneral;
    RefrescarResumenes;
    if Bloqueo then
       LockWindowUpdate(0);
  end
end;

procedure TfrInformeEstadistico.SetTopN(const Value: Integer);
var
  Bloqueo: Boolean;

begin
  if FTopN <> Value then
  begin
    FTopN := Value;
    Bloqueo := LockWindowUpdate(Application.MainForm.Handle);
    RefrescarResumenes;
    if Bloqueo then
       LockWindowUpdate(0);
  end;
end;

function TfrInformeEstadistico.inicializarGrids: Boolean;
var
  Columna : TdxDBTreeListColumn;

begin
  pnlGraficoGen.Height := 260;

  //INTERVALO
  Columna := gridIntervalo.CreateColumn(TdxDBTreeListColumn);
  Columna.FieldName := CTE_CAMPO1;
  Columna.Caption := 'Fila';
  Columna.Visible := False;

  Columna := gridIntervalo.CreateColumn(TdxDBTreeListColumn);
  Columna.FieldName := CTE_CAMPO2;
  Columna.Caption := 'Intervalo';
  Columna.Visible := True;

  //ANO1
  Columna := gridAnoCom1.CreateColumn(TdxDBTreeListColumn);
  Columna.FieldName := CTE_CAMPO1;
  Columna.Caption := 'Fila';
  Columna.Visible := False;

  //ANO2
  Columna := gridAnoCom2.CreateColumn(TdxDBTreeListColumn);
  Columna.FieldName := CTE_CAMPO1;
  Columna.Caption := 'Fila';
  Columna.Visible := False;

  //COMPARATIVA
  Columna := gridComparativa.CreateColumn(TdxDBTreeListColumn);
  Columna.FieldName := CTE_CAMPO1;
  Columna.Caption := 'Fila';
  Columna.Visible := False;
end;

function TfrInformeEstadistico.InicializarCamposTMem: Boolean;
begin
  //INTERVALO
  TMemIntervalo.FieldDefs.Add(CTE_CAMPO1,ftInteger);
  TMemIntervalo.FieldDefs.Items[TMemIntervalo.FieldDefs.IndexOf(CTE_CAMPO1)].CreateField(Self);
  TMemIntervalo.FieldDefs.Add(CTE_CAMPO2,ftString,20);
  TMemIntervalo.FieldDefs.Items[TMemIntervalo.FieldDefs.IndexOf(CTE_CAMPO2)].CreateField(Self);

  //ANO1
  TMemAnoCom1.FieldDefs.Add(CTE_CAMPO1,ftInteger);
  TMemAnoCom1.FieldDefs.Items[TMemAnoCom1.FieldDefs.IndexOf(CTE_CAMPO1)].CreateField(Self);

  //ANO2
  TMemAnoCom2.FieldDefs.Add(CTE_CAMPO1,ftInteger);
  TMemAnoCom2.FieldDefs.Items[TMemAnoCom2.FieldDefs.IndexOf(CTE_CAMPO1)].CreateField(Self);

  //COMPARATIVA
  TMemComparativa.FieldDefs.Add(CTE_CAMPO1,ftInteger);
  TMemComparativa.FieldDefs.Items[TMemComparativa.FieldDefs.IndexOf(CTE_CAMPO1)].CreateField(Self);

  //GRAFICO
  TMemGraficoAno1.FieldDefs.Add(CTE_CAMPO1,ftInteger);
  TMemGraficoAno1.FieldDefs.Items[TMemGraficoAno1.FieldDefs.IndexOf(CTE_CAMPO1)].CreateField(Self);
  TMemGraficoAno1.FieldDefs.Add(CTE_CAMPO2,ftString,20);
  TMemGraficoAno1.FieldDefs.Items[TMemGraficoAno1.FieldDefs.IndexOf(CTE_CAMPO2)].CreateField(Self);
  TMemGraficoAno2.FieldDefs.Add(CTE_CAMPO1,ftInteger);
  TMemGraficoAno2.FieldDefs.Items[TMemGraficoAno2.FieldDefs.IndexOf(CTE_CAMPO1)].CreateField(Self);
  TMemGraficoAno2.FieldDefs.Add(CTE_CAMPO2,ftString,20);
  TMemGraficoAno2.FieldDefs.Items[TMemGraficoAno2.FieldDefs.IndexOf(CTE_CAMPO2)].CreateField(Self);
end;

procedure TfrInformeEstadistico.SetAno2(const Value: Variant);
begin
  if FAno2 <> Value then
  begin
    if Value <> 'Ninguno'
    then FAno2 := Value
    else FAno2 := Null;
    RefrescarGeneral;
  end
end;

procedure TfrInformeEstadistico.SetIntervalo(const Value: TTipoIntervalo);
begin
  if FIntervalo <> Value then
  begin
    FIntervalo := Value;
    RefrescarGeneral;
  end;
end;

function TfrInformeEstadistico.RellenarIntervalos: Boolean;
var
  Contador: Integer;
  i: Integer;

begin
  Case Intervalo of
    tiMensual    : Contador := CTE_MENSUAL;
    tiTrimestral : Contador := CTE_TRIMESTRAL;
    tiSemestral  : Contador := CTE_SEMESTRAL;
  end;

  TMemIntervalo.Close;
  TMemAnoCom1.Close;
  TMemAnoCom2.Close;
  TMemComparativa.Close;
  TMemGraficoAno1.Close;
  TMemGraficoAno2.Close;

  TMemIntervalo.Open;
  TMemAnoCom1.Open;
  TMemAnoCom2.Open;
  TMemComparativa.Open;
  TMemGraficoAno1.Open;
  TMemGraficoAno2.Open;

  for i:=1 to Contador do
  begin
    TMemIntervalo.Append;
    TMemAnoCom1.Append;
    TMemAnoCom2.Append;
    TMemComparativa.Append;
    TMemGraficoAno1.Append;
    TMemGraficoAno2.Append;

    TMemIntervalo.FieldByName(CTE_CAMPO1).AsInteger := i;
    TMemAnoCom1.FieldByName(CTE_CAMPO1).AsInteger := i;
    TMemAnoCom2.FieldByName(CTE_CAMPO1).AsInteger := i;
    TMemComparativa.FieldByName(CTE_CAMPO1).AsInteger := i;
    TMemGraficoAno1.FieldByName(CTE_CAMPO1).AsInteger := i;
    TMemGraficoAno2.FieldByName(CTE_CAMPO1).AsInteger := i;

    Case Intervalo of
      tiMensual    : begin
                       TMemIntervalo.FieldByName(CTE_CAMPO2).AsString := DarMes(i);
                       TMemGraficoAno1.FieldByName(CTE_CAMPO2).AsString := copy(TMemIntervalo.FieldByName(CTE_CAMPO2).AsString, 0, 3);
                       TMemGraficoAno2.FieldByName(CTE_CAMPO2).AsString := copy(TMemIntervalo.FieldByName(CTE_CAMPO2).AsString, 0, 3);
                     end;
      tiTrimestral : begin
                       TMemIntervalo.FieldByName(CTE_CAMPO2).AsString := IntToStr(i) + 'º Trimestre';
                       TMemGraficoAno1.FieldByName(CTE_CAMPO2).AsString := TMemIntervalo.FieldByName(CTE_CAMPO2).AsString;
                       TMemGraficoAno2.FieldByName(CTE_CAMPO2).AsString := TMemIntervalo.FieldByName(CTE_CAMPO2).AsString;
                     end;
      tiSemestral  : begin
                       TMemIntervalo.FieldByName(CTE_CAMPO2).AsString := IntToStr(i) + 'º Semestre';
                       TMemGraficoAno1.FieldByName(CTE_CAMPO2).AsString := TMemIntervalo.FieldByName(CTE_CAMPO2).AsString;
                       TMemGraficoAno2.FieldByName(CTE_CAMPO2).AsString := TMemIntervalo.FieldByName(CTE_CAMPO2).AsString;
                     end;
    end;

    TMemIntervalo.Post;
    TMemAnoCom1.Post;
    TMemAnoCom2.Post;
    TMemComparativa.Post;
    TMemGraficoAno1.Post;
    TMemGraficoAno2.Post;
  end;
end;

procedure TfrInformeEstadistico.setTamPaneles;
begin
  //Altura de panel general
  Case Intervalo of
    tiMensual: pnlTablas.Height := 210;
    tiTrimestral: pnlTablas.Height := 75;
    tiSemestral: pnlTablas.Height := 40;
  end;
end;

procedure TfrInformeEstadistico.pnl1Resize(Sender: TObject);
begin
  pnlFiltro1.Width := pnl1.Width;
  pnlTitulo1.Width := pnl1.Width;
  pnlTotalIntervalo.Width := pnl1.Width;
end;

procedure TfrInformeEstadistico.pnl2Resize(Sender: TObject);
begin
  pnlFiltro2.Width := pnl2.Width;
  pnlTitulo2.Width := pnl2.Width;
  pnlTotalAnoCom1.Width := pnl2.Width;
end;

procedure TfrInformeEstadistico.pnl3Resize(Sender: TObject);
begin
  pnlFiltro3.Width := pnl3.Width;
  pnlTitulo3.Width := pnl3.Width;
  pnlTotalAnoCom2.Width := pnl3.Width;
end;

procedure TfrInformeEstadistico.pnl4Resize(Sender: TObject);
begin
  pnlFiltro4.Width := pnl4.Width;
  pnlTitulo4.Width := pnl4.Width;
  pnlTotalComparativa.Width := pnl4.Width;
end;

function TfrInformeEstadistico.RefrescarGeneral: Boolean;
begin
  setTamPaneles;
  RellenarIntervalos;
  CalcularDatos;
  DibujarGrafico;
end;

procedure TfrInformeEstadistico.gridCustomDrawCell(Sender: TObject;
  ACanvas: TCanvas; ARect: TRect; ANode: TdxTreeListNode;
  AColumn: TdxTreeListColumn; ASelected, AFocused, ANewItemRow: Boolean;
  var AText: String; var AColor: TColor; AFont: TFont;
  var AAlignment: TAlignment; var ADone: Boolean);
var
  IndiceCol: Integer;

begin
  IndiceCol := (Sender as TdxDBGrid).ColumnByFieldName(CTE_CAMPO1).Index;
  if ANode.Strings[IndiceCol] <> '' then
     if (StrToInt(ANode.Strings[IndiceCol]) mod 2) <> 0 then
        AColor := rdxSepiaAmarillo;
end;

function TfrInformeEstadistico.CalcularPorcentaje(const x1, x2: Double; Incremento: Boolean): Double;
var
  Aux: Double;
begin
//Formula
//x1 --- 100
//x2 --- X
// X = (x2*100)/x1

  Aux := x2 * 100;
  if (x1 = 0)
  then Aux := Aux
  else Aux := (Aux / x1);

//Si queremos el incremento del primero sobre el segundo 100 - Aux
  if Incremento then
    Aux := 100 - Aux;

  Result:= Aux;
end;

function TfrInformeEstadistico.InicializarFiltros: Boolean;
begin
  cbxFiltro1.Items.Append(CaptionsIntervalos[tiMensual]);
  cbxFiltro1.Items.Append(CaptionsIntervalos[tiTrimestral]);
  cbxFiltro1.Items.Append(CaptionsIntervalos[tiSemestral]);

  cbxFiltro1.ItemIndex := 1;
  FIntervalo := tiTrimestral;
end;

procedure TfrInformeEstadistico.cbxFiltro2Change(Sender: TObject);
begin
  Ano1 := cbxFiltro2.Text;
end;

procedure TfrInformeEstadistico.cbxFiltro3Change(Sender: TObject);
begin
  Ano2 := cbxFiltro3.Text;
end;

procedure TfrInformeEstadistico.cbxFiltro1Change(Sender: TObject);
begin
  if (cbxFiltro1.Text = CaptionsIntervalos[tiMensual]) then
     Intervalo := tiMensual
  else if (cbxFiltro1.Text = CaptionsIntervalos[tiTrimestral]) then
     Intervalo := tiTrimestral
  else if (cbxFiltro1.Text = CaptionsIntervalos[tiSemestral]) then
     Intervalo := tiSemestral;
end;

function TfrInformeEstadistico.DibujarGrafico: Boolean;
begin
//
end;

function TfrInformeEstadistico.CalcularResta(const x1, x2: Integer): Integer;
begin
  Result:= x1 - x2;
end;

procedure TfrInformeEstadistico.SetAnosMem(const Value: TStrings);
begin
  FAnosMem := Value;
  cbxFiltro2.Items := AnosMem;
  //Activo la propiedad para hacer el primer calculo
  cbxFiltro2.ItemIndex := 0;
  Ano1 := cbxFiltro2.Text;
end;

procedure TfrInformeEstadistico.RellenarAno2;
var
  i: Integer;

begin
  cbxFiltro3.Items.Clear;
  cbxFiltro3.Items.Add('Ninguno');

  i:=0;
  while cbxFiltro2.Items.Strings[i] <> cbxFiltro2.Text do
    i:= i+1;

  i:= i+1;
  while i < cbxFiltro2.Items.Count do
  begin
    cbxFiltro3.Items.Add(cbxFiltro2.Items.Strings[i]);
    i:= i+1;
  end;
  
  //Activamos el primero por defecto
  cbxFiltro3.ItemIndex := 0;
  Ano2 := cbxFiltro3.Text;
end;

function TfrInformeEstadistico.CalcularResta(const x1, x2: Double): Double;
begin
  if x2 < 0
  then Result:= x1 + x2
  else Result:= x1 - x2;
end;

end.
