unit uCountersFrame;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes,
  Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Data.DB, FireDAC.Stan.Intf,
  FireDAC.Stan.Option, FireDAC.Stan.Error, FireDAC.UI.Intf, FireDAC.Phys.Intf,
  FireDAC.Stan.Def, FireDAC.Stan.Pool, FireDAC.Stan.Async, FireDAC.Phys, FireDAC.Phys.MySQL,
  FireDAC.Phys.MySQLDef, FireDAC.VCLUI.Wait, FireDAC.Stan.Param, FireDAC.DatS,
  FireDAC.DApt.Intf, FireDAC.DApt, FireDAC.Comp.DataSet, FireDAC.Comp.Client,
  Vcl.StdCtrls, Vcl.DBCtrls, Vcl.ExtCtrls, Vcl.Grids, Vcl.DBGrids, Vcl.Buttons;

type
  TCountersFrame = class(TFrame)
    DBGrid: TDBGrid;
    FDConnectionTemp: TFDConnection;
    tbit: TPanel;
    qFlatNumbers: TFDQuery;
    qCounters: TFDQuery;
    qHouseNumbers: TFDQuery;
    qStreets: TFDQuery;
    bAdd: TBitBtn;
    bEdit: TBitBtn;
    bDelete: TBitBtn;
    DSCounters: TDataSource;
    pCountersToCheck: TPanel;
    cbStreets: TDBLookupComboBox;
    cbHouseNumbers: TDBLookupComboBox;
    lStreets: TLabel;
    lHouseNumbers: TLabel;
    bFilter: TButton;
    bFlushFilter: TButton;
    DSStreets: TDataSource;
    DSHouseNumbers: TDataSource;
    qCountersFilter: TFDQuery;
    bAddNewData: TBitBtn;
    procedure bAddClick(Sender: TObject);
    procedure bEditClick(Sender: TObject);
    procedure bDeleteClick(Sender: TObject);
    procedure cbStreetsCloseUp(Sender: TObject);
    procedure cbHouseNumbersCloseUp(Sender: TObject);
    procedure bFilterClick(Sender: TObject);
    procedure bFlushFilterClick(Sender: TObject);
    procedure bAddNewDataClick(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
    procedure Init();
  end;

implementation

{$R *.dfm}

uses
  uAddEditCounterForm, //
  uDB, //
  uCounter, //
  uCountersController, //
  uAddNewCounterData, //
  uCommon, //
  uFlatCounter, //
  uCountersUpdateHistory, uFlat; //

procedure TCountersFrame.bAddClick(Sender: TObject);
var
  f: TAddEditCounterForm;
  c: TCounter;
  fh: TFLatCounter;
  h: TCountersUpdateHistory;
begin
  f := TAddEditCounterForm.Create(Self);
  f.Init();
  c := TCounter.Create(Self);
  fh := TFLatCounter.Create(Self);
  h := TCountersUpdateHistory.Create(Self);
  try
    if f.ShowModal = mrOK then
    begin
      // updating model
      c.SerialNumber := f.eSerialNumber.Text;
      c.LastCheckDate := f.dtpLast.DateTime;
      c.NextCheckDate := f.dtpNext.DateTime;
      c.Id := TCountersController.InsertCounter(c); //
      // association to flat
      if f.cbIsAssociateToFlat.Checked then
      begin
        fh.Flat.Id := f.qFlatNumbers.FieldByName('id').AsInteger;
        fh.Counter.Id := c.Id;
        TCountersController.AssociateFlatToCounter(fh);
        // add history
        h.Counter := c;
        h.Flat.Id := f.qFlatNumbers.FieldByName('id').AsInteger;
        h.CounterOld.Id := -1; // no old counter
        TCountersController.LogAssociatonFlatToCounter(h);
      end;
      //updating dataset
      qCounters.Disconnect();
      qCounters.Open();
      DSCounters.DataSet := qCounters;
    end;
  finally
    f.Free();
    c.Free();
    fh.Free();
    h.Free();
  end;
end;

procedure TCountersFrame.bAddNewDataClick(Sender: TObject);
var
  f: TAddNewCounterData;
  newValue: double;
begin
  f := TAddNewCounterData.Create(Self);
  try
    f.CounterID := qCounters.FieldByName('id').AsInteger;
    f.Init();
    if f.ShowModal = mrOk then
    begin
      newValue := TCommon.GetDoubleFromIntAndFrac(f.seInt.Value, f.seFrac.Value);
       // insert new record
      if (not TCountersController.IsNewValueOk(f.CounterID, newValue)) then
      begin
        Application.MessageBox('Новое значение должно быть больше предыдущего', //
          'Сообщение системы', MB_OK + MB_ICONSTOP);
        exit;
      end;
      TCountersController.InsertCounterData(f.CounterID, newValue);
      qCounters.Disconnect();
      qCounters.Open();
    end;
  finally
    f.Free();
  end;
end;

procedure TCountersFrame.bDeleteClick(Sender: TObject);
var
  buttonSelected: Integer;
begin
  case Application.MessageBox('Удалить счетчик и все его данные?', 'Сообщение системы', MB_YESNO + MB_ICONQUESTION) of
    IDYES:
      begin
        TCountersController.Delete(qCounters.FieldByName('id').AsInteger);
        qCounters.Disconnect();
        qCounters.Open();
        DSCounters.DataSet := qCounters;
      end;
    IDNO:
      begin
        Exit();
      end;
  end;
end;

procedure TCountersFrame.bEditClick(Sender: TObject);
var
  counter: TCounter;
  anotherCounter: TCounter;
  f: TAddEditCounterForm;
  fc: TFLatCounter;
  fcAnother: TFLatCounter;
  h, h2: TCountersUpdateHistory;
  anotherCounterId: integer;
  counterId: Integer;
  flat: TFlat;
begin
  // current counterId
  counterId := qCounters.FieldByName('id').AsInteger;
  counter := TCountersController.GetCounter(counterId);
  flat := TFlat.Create(Self);

  f := TAddEditCounterForm.Create(Self);
  h := TCountersUpdateHistory.Create(Self);
  h2 := TCountersUpdateHistory.Create(Self);
  anotherCounter := nil;
  fc := nil;
  try
    f.Init();
    // проверяем ассоциацию счетчика с квартирой
    fc := TCountersController.GetAssociationToFlat(counter);

    if fc.IsAssociated then
    begin
      // Заполняем списки
      f.cbIsAssociateToFlat.Checked := true;
      f.cbStreets.KeyValue := fc.Street.Id;
      // дома
      f.LoadHouseNumbersInList(fc.Street.Id);
      f.cbHouseNumbers.KeyValue := fc.HouseNumber.Id;
      // квартиры
      f.LoadFlatsInList(fc.HouseNumber.Id);
      f.cbFlatNumbers.KeyValue := fc.Flat.Id;
      // для лога истрии
      h.Counter := counter; // new counter
    end;
    with f do
    begin
      // update view
      eSerialNumber.Text := counter.SerialNumber;
      dtpLast.DateTime := counter.LastCheckDate;
      dtpNext.DateTime := counter.NextCheckDate;
      if f.ShowModal = mrOk then
      begin
      // обновляем модель счетчика из представления
        counter.SerialNumber := eSerialNumber.Text;
        counter.LastCheckDate := dtpLast.DateTime;
        counter.NextCheckDate := dtpNext.DateTime;
        TCountersController.Update(counter, qCounters.FieldByName('id').AsInteger);

        flat.Id := f.qFlatNumbers.FieldByName('id').AsInteger;
        fcAnother := TCountersController.GetAssociationToCounter(flat);





       {
        //
        if f.qFlatNumbers.FieldByName('counters_id').IsNull then
        begin
          anotherCounter := nil;
          anotherCounterId := -1;
        end
        else
        begin
          anotherCounterId := f.qFlatNumbers.FieldByName('counters_id').AsInteger;
          anotherCounter := TCountersController.GetCounter(anotherCounterId);
        end;
        // Если выбрали другую квартиру - ассоциируем счетчик с новой выбранной
        // квартирой
        if ((anotherCounterId <> counter.id) and (f.cbIsAssociateToFlat.Checked)) then
        begin
          // updating association
         // Cлучаи
         // 1) Текущий Счетчик уже ассоциирован с квартирой, а в выбранной
         // квартире уже свой ассоциированный счетчик, тогда предложить
         // их поменять местами
          if (fc.IsAssociated) //
            and (TCountersController.IsFlatHasCounter(anotherFlatId)) then //
          begin
            case Application.MessageBox('В выбранной квартире уже есть другой счетчик. Поменять счетчики местами?', 'Сообщение системы', MB_YESNO + MB_ICONQUESTION) of
              IDYES:
                begin
                  // exchange counters in flats
                  TCountersController.ExchangeCountersInFlats(counter.id, anotherCounterId);
                  // Записываем историю замены одного счетчика
                  h.CounterOld := anotherCounter;
                  h.Flat.Id := f.qFlatNumbers.FieldByName('id').AsInteger;
                  TCountersController.LogAssociatonFlatToCounter(h);
                  // И теперь наоборот
                  h2.Counter := anotherCounter;
                  h2.CounterOld := counter;
                  h2.Flat.Id := fc.Flat.Id;
                  TCountersController.LogAssociatonFlatToCounter(h2);
                end;
              IDNO:
                begin
                  exit;
                end;
            end;
          end
          else
         // 2) Текущий счетчик не ассоциирован с квартирой,
         // В выбранной квартире уже есть счетчик, тогда предложить
         // перезаписать
if (not fc.IsAssociated) //
  and (TCountersController.IsFlatHasCounter(anotherFlatId)) then //
          begin
            case Application.MessageBox('В выбранной квартире уже есть счетчик, перезаписать счетчик?', 'Сообщение системы', MB_YESNO + MB_ICONQUESTION) of
              IDYES:
                begin
                  // rewrite counter un another flat
                  TCountersController.UpdateCounterInFlat(counter.Id, anotherFlatId);
                  // Записываем историю замены счетчиков
                  anotherCounter := TCountersController.GetCounter(anotherCounterId);
                  h.CounterOld := anotherCounter;
                  h.Counter := counter;
                  h.Flat.Id := f.qFlatNumbers.FieldByName('id').AsInteger;
                  TCountersController.LogAssociatonFlatToCounter(h);
                end;
              IDNO:
                begin
                  exit;
                end;
            end;

          end
          //3) Текущий счетчик не ассоциирован с квартирой,
          //В выбранной квартире нет счетчика, тогда просто записываем
          else if (not TCountersController.IsCounterAssociatedToFlat(counterId)) //
            and (not TCountersController.IsFlatHasCounter(fc.Flat.Id)) then //
          begin
            //TCountersController.AssociateFlatToCounter(fc);
            TCountersController.UpdateCounterInFlat(counter.Id, anotherFlatId);
          // Записываем историю замены счетчиков
            h.Counter := counter;
            if anotherCounterId = -1 then
              anotherCounter := nil
            else
              anotherCounter := TCountersController.GetCounter(anotherCounterId);
            h.CounterOld := anotherCounter;
            h.Flat.Id := f.qFlatNumbers.FieldByName('id').AsInteger;
            TCountersController.LogAssociatonFlatToCounter(h);
          end;
        end;
        }
      end;
      qCounters.Disconnect();
      qCounters.Open();
      DSCounters.DataSet := qCounters;
    end;
  finally
    counter.Free;
    flat.Free();
    f.Free();
    h.Free();
    if anotherCounter <> nil then
      anotherCounter.Free();
    if fc <> nil then
      fc.Free();
  end;
end;

procedure TCountersFrame.bFilterClick(Sender: TObject);
begin
  with qCountersFilter do
  begin
    Connection := Db.FDConnection;
    params.ParamValues['streetId'] := qStreets.FieldByName('id').AsInteger;
    params.ParamValues['houseNumberId'] := qHouseNumbers.FieldByName('id').AsInteger;
    Disconnect();
    Open();
    DSCounters.DataSet := qCountersFilter;
  end;
end;

procedure TCountersFrame.bFlushFilterClick(Sender: TObject);
begin
  with qCounters do
  begin
    Connection := Db.FDConnection;
    Disconnect();
    Open();
    DSCounters.DataSet := qCounters;
  end;
end;

procedure TCountersFrame.cbHouseNumbersCloseUp(Sender: TObject);
begin
  with qHouseNumbers do
  begin
    Connection := Db.FDConnection;
    CachedUpdates := true;
    params.ParamValues['streets_id'] := qStreets.FieldByName('id').AsInteger;
    Disconnect();
    Open();
    cbHouseNumbers.KeyValue := qHouseNumbers.FieldByName('id').AsInteger;
  end;

end;

procedure TCountersFrame.cbStreetsCloseUp(Sender: TObject);
begin
  with qHouseNumbers do
  begin
    Connection := Db.FDConnection;
    CachedUpdates := true;
    params.ParamValues['streets_id'] := qStreets.FieldByName('id').AsInteger;
    Disconnect();
    Open();
    cbHouseNumbers.KeyValue := qHouseNumbers.FieldByName('id').AsInteger;
  end;
end;

procedure TCountersFrame.Init;
begin
  FDConnectionTemp.Connected := false;
  with qCounters do
  begin
    Connection := Db.FDConnection;
    CachedUpdates := true;
    Disconnect();
    Open();
  end;
  with qStreets do
  begin
    Connection := Db.FDConnection;
    CachedUpdates := true;
    Disconnect();
    Open();
    cbStreets.KeyValue := qStreets.FieldByName('id').AsInteger;
  end;
  with qHouseNumbers do
  begin
    Connection := Db.FDConnection;
    CachedUpdates := true;
    params.ParamValues['streets_id'] := qStreets.FieldByName('id').AsInteger;
    Disconnect();
    Open();
    cbHouseNumbers.KeyValue := qHouseNumbers.FieldByName('id').AsInteger;
  end;
end;

end.

