unit U_MakeCurrency;

interface

uses
  Windows, U_LNG, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, cxLookAndFeelPainters, StdCtrls, cxButtons, cxMaskEdit,
  cxSpinEdit, cxControls, cxContainer, cxEdit, cxTextEdit, cxCurrencyEdit, U_BaseCommon, U_BaseConstants,
  RzEdit, Mask, RzButton, ExtCtrls, RzPanel, RzSpnEdt, RzRadChk, siComp,
  siLngLnk, RzTabs, kbmMemTable;

type
  TF_MakeCurrency = class(TForm)
    RzGroupBox1: TRzGroupBox;
    Label1: TLabel;
    Label2: TLabel;
    Label3: TLabel;
    edName: TRzEdit;
    edNameBrief: TRzEdit;
    RzGroupBox2: TRzGroupBox;
    btOk: TRzBitBtn;
    btCancel: TRzBitBtn;
    Label4: TLabel;
    seKolvo: TRzSpinEdit;
    neRatio: TRzNumericEdit;
    lng_Forms: TsiLangLinked;
    gbMainKind: TRzGroupBox;
    rbSimple: TRzRadioButton;
    rbMain: TRzRadioButton;
    rbSecond: TRzRadioButton;
    cbIsCountry: TRzCheckBox;
    pnInfo: TRzPanel;
    procedure FormShow(Sender: TObject);
    procedure FormHide(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure neRatioChange(Sender: TObject);
  private
    { Private declarations }
    GForm: TForm;
    FChangedRatio: Boolean;
  public
    { Public declarations }
    GMakeEdit : TMakeEdit;
    GID: Integer;
    Constructor Create(AOwner: TComponent; AForm: TForm);
    Destructor Destroy; override;

    function Execute(AMakeEdit: TMakeEdit; AMemTable, AMTNorms, AMTResources: TkbmMemTable): Boolean;
    //23.08.2012 function ExecuteForObject(AMakeEdit: TMakeEdit; AObjectCurrency: PCurrency): Boolean;
  end;
 {
var
  F_MakeCurrency: TF_MakeCurrency; }

implementation
Uses Unit_DM_SCS, U_MAIN, DB, U_Common;
{$R *.dfm}

procedure TF_MakeCurrency.FormShow(Sender: TObject);
begin
  if TF_Main(GForm).GDBMode <> bkNormBase then
  begin
    pnInfo.Visible := false;
    Self.AutoSize := true;
    Self.AutoSize := false;
  end;

  {case GParam of
    tMake:  begin
            Caption := 'Создание валюты';
            Edit_Name.Text := '';
            Edit_Name_Brief.Text := '';
            CurrencyEdit_Ratio.Value := 0.1;
            end;
     tEdit: with TF_Main(GForm).DM.DataSet_CURRENCY do
              begin
                  Caption := 'Редактирование валюты';
                  Edit_Name.Text := FN('Name').AsString;
                  Edit_Name_Brief.Text := FN('Name_Brief').AsString;
                  CurrencyEdit_Ratio.Value := RoundX(FN('Ratio').AsFloat, 2);
              end;
  end;
  }
  edName.SetFocus;
end;

procedure TF_MakeCurrency.FormHide(Sender: TObject);
begin
    // ##### При Следующем вsзове, Отображать эту форму в средине Главной #####
    //F_MakeCurrency.Position := poMainFormCenter;
end;

constructor TF_MakeCurrency.Create(AOwner: TComponent; AForm: TForm);
begin
  GForm := AForm;
  inherited Create(AOwner);
end;

destructor TF_MakeCurrency.Destroy;
begin
  inherited;
end;

function TF_MakeCurrency.Execute(AMakeEdit: TMakeEdit; AMemTable, AMTNorms, AMTResources: TkbmMemTable): Boolean;
var
  OldCurrency: TCurrency;
  NewCurrency: TCurrency;
  CurrCurrency: TCurrency;

  OldCurrencyM: TCurrency;
  CurrencyS: TCurrency;
  ChangedCurrencyM: Boolean;
  PriceValue: Double;

  //BookmarkStr: String;
  BookmarkStr: TBookMark;
  PriceFields: TStringList;
  //Tolik
  NewRatio: Double;
begin
  Result := false;
  Caption := '';
  GID := -1;
  GMakeEdit := AMakeEdit;

  ZeroMemory(@OldCurrency, SizeOf(TCurrency));
  ZeroMemory(@OldCurrencyM, SizeOf(TCurrency));
  ZeroMemory(@NewCurrency, SizeOf(TCurrency));
  FChangedRatio := false;

  cbIsCountry.Enabled := true;

  rbSimple.Enabled := true;
  rbSimple.Checked := false;
  rbMain.Enabled := true;
  rbMain.Checked := false;
  rbSecond.Enabled := true;
  rbSecond.Checked := false;

  //gbMainKind.Visible := (AMemTable <> nil);

  case AMakeEdit of
    meMake:
      begin
        Caption := cMakeCurrency_Msg1_1;
        edName.Text := '';
        edNameBrief.Text := '';
        seKolvo.Value := 100;
        neRatio.Value := 0.1;
        cbIsCountry.Checked := false;
      end;
    meEdit:
      begin
        Caption := cMakeCurrency_Msg1_2;
        if AMemTable <> nil then
          OldCurrency := GetCurrencyFromMemTable(AMemTable)
        else
          OldCurrency := GetCurrencyFromDataSet(TF_Main(GForm).DM.DataSet_CURRENCY);

        edName.Text := OldCurrency.Name;
        edNameBrief.Text := OldCurrency.NameBrief;
        seKolvo.Value := OldCurrency.Kolvo;
        neRatio.OnChange := nil;
        try
          neRatio.Value := Round3(OldCurrency.Ratio);
        finally
          neRatio.OnChange := neRatioChange;
          // Tolik 12/06/2018 --
          if neRatio.Value = 0 then
          begin
            neRatio.Font.Color := clRed;
            neRatio.Refresh;
          end
          else
          begin
            neRatio.Font.Color := clBlack;
            neRatio.Refresh;
          end;
          //
        end;
        if OldCurrency.Main = ctSimple then
          rbSimple.Checked := true
        else
        begin
          rbSimple.Enabled := false;
          if OldCurrency.Main = ctMain then
            rbMain.Checked := true
          else
          if OldCurrency.Main = ctSecond then
            rbSecond.Checked := true;
        end;
        cbIsCountry.Checked := IntToBool(OldCurrency.IsCountry);

        //*** Запретить снятие валюты страны, если она здесь установлена
        cbIsCountry.Enabled := Not cbIsCountry.Checked;
      end;
  end;

  if ShowModal = mrOk then
  begin
    ChangedCurrencyM := false;
    NewCurrency := OldCurrency;
    NewCurrency.Kolvo := Round(seKolvo.Value);
    if FChangedRatio then
      NewCurrency.Ratio := neRatio.Value
    else
      NewCurrency.Ratio := OldCurrency.Ratio;

    NewCurrency.Main := -1;
    if rbSimple.Checked then
      NewCurrency.Main := ctSimple
    else
    if rbMain.Checked then
      NewCurrency.Main := ctMain
    else
    if rbSecond.Checked then
      NewCurrency.Main := ctSecond;
    //*** Изменилась главная валюта
    if (OldCurrency.Main <> -1) and (NewCurrency.Main <> -1) and (NewCurrency.Main <> OldCurrency.Main) then
      ChangedCurrencyM := true;


    if AMemTable <> nil then
    begin
      AMemTable.DisableControls;
      //BookmarkStr := AMemTable.Bookmark;
      BookmarkStr := AMemTable.getBookmark;
      try
        //*** Сбросить флаг IsCountry на всех записях
        //CurrentID := 0;
        if cbIsCountry.Checked then
        begin
          AMemTable.First;
          while Not AMemTable.Eof do
          begin
            if AMemTable.FieldByName(fnIsCountry).AsInteger = biTrue then
            begin
              AMemTable.Edit;
              AMemTable.FieldByName(fnIsCountry).AsInteger := biFalse;
              AMemTable.FieldByName(fnIsModified).AsBoolean := true;
              AMemTable.Post;
            end;
            AMemTable.Next;
          end;
        end;

        //*** Найти запись со значением NewCurrency.Main, и установить туда OldCurrency.Main
        if ChangedCurrencyM then
        begin
          if AMemTable.Locate(fnMain, NewCurrency.Main, []) then
          begin
            OldCurrencyM := GetCurrencyFromMemTable(AMemTable);
            WriteToMemTable(AMemTable, fnMain, OldCurrency.Main);
          end;
        end;
      finally
        //AMemTable.Bookmark := BookmarkStr;
        if BookmarkStr <> nil then
        begin
          AMemTable.GotoBookmark(BookmarkStr);
          AMemTable.FreeBookmark(BookmarkStr);
        end;
        AMemTable.EnableControls;
      end;

      case AMakeEdit of
        meMake:
          AMemTable.Append;
        meEdit:
          AMemTable.Edit;
      end;
      AMemTable.FieldByName(fnName).AsString := edName.Text;
      AMemTable.FieldByName(fnNameBrief).AsString := edNameBrief.Text;
      AMemTable.FieldByName(fnKolvo).AsInteger := NewCurrency.Kolvo;
      AMemTable.FieldByName(fnRatio).AsFloat := NewCurrency.Ratio;
      AMemTable.FieldByName(fnMain).AsInteger := NewCurrency.Main;
      AMemTable.FieldByName(fnIsCountry).AsInteger := BoolToInt(cbIsCountry.Checked);
      AMemTable.Post;

      //*** Изменить курсы вадют
      if ChangedCurrencyM and (OldCurrencyM.GUID <> '') then
      begin
        // Tolik
        // валюта становится главной
        if NewCurrency.Main = 1 then
          NewRatio := NewCurrency.Ratio
        else
        begin
          if OldCurrency.Main = 0 then
            NewRatio := NewCurrency.Ratio
          else
            NewRatio := OldCurrencyM.Ratio;
        end;
        //
        AMemTable.DisableControls;
        //BookmarkStr := AMemTable.Bookmark;
        BookmarkStr := AMemTable.getBookmark;
        try
          AMemTable.First;
          while Not AMemTable.Eof do
          begin
            CurrCurrency := GetCurrencyFromMemTable(AMemTable);
            AMemTable.Edit;
            // Tolik
            // Если не поменялась второстепенная валюта на проекте, то будут изменения
            if ((NewCurrency.Main = 2) and (OldCurrency.Main = 0)) then
            begin
              // второстепенная валюта не изменит курса, так как соотношения валют, по идее,
              // уже выставлены, поэтому пересчет не ведем, ведь практически ничего не изменится,
              // главная валюта есть
            end
            else
            // пересчет
              // Tolik -- 12/06/2018 -- для особо "умных", которые любят повыебываться и ставят нули
              if (CurrCurrency.Kolvo * NewRatio) <> 0 then
              //
                AMemTable.FieldByName(fnRatio).AsFloat := Roundx(CurrCurrency.Kolvo*((NewCurrency.Kolvo*CurrCurrency.Ratio)/(CurrCurrency.Kolvo * NewRatio)), valEpsilonCurrency);
            // AMemTable.FieldByName(fnRatio).AsFloat := GetPriceAfterChangeCurrency(CurrCurrency.Ratio, NewCurrency, OldCurrencyM, valEpsilonCurrency);
           // использщование функции просто закомментил, чтоб ее не ломать, так как используется неоднократно, нужно пересмотреть
           // ситуации вызова до того, как поломать
            AMemTable.Post;
            AMemTable.Next;
          end;
        finally
          //AMemTable.Bookmark := BookmarkStr;
          if BookmarkStr <> nil then
          begin
            AMemTable.GotoBookmark(BookmarkStr);
            AMemTable.FreeBookmark(BookmarkStr);
          end;
          AMemTable.EnableControls;
        end;

        //*** Поменять цены справочных ресурсов
        ////24.09.2010
//        if AMTResources <> nil then
//        begin
//          BookmarkStr := AMTResources.Bookmark;
//          AMTResources.DisableControls;
//          try
//            AMTResources.First;
//            while Not AMTResources.Eof do
//            begin
//              PriceValue := AMTResources.FieldByName(fnPrice).AsFloat;
//              if PriceValue > 0 then
//              begin
//                AMTResources.Edit;
//                AMTResources.FieldByName(fnPrice).AsFloat := GetPriceAfterChangeCurrency(PriceValue, OldCurrencyM, NewCurrency, valEpsilonCurrency);
//                AMTResources.Post;
//              end;
//              AMTResources.Next;
//            end;
//            AMTResources.Bookmark := BookmarkStr;
//          finally
//            AMTResources.EnableControls;
//          end;
//        end;

        PriceFields := TStringList.Create;
        PriceFields.Add(fnPrice);
        //*** Поменять цены справочных норм
        DefineMTPriceFields(AMTNorms, PriceFields, OldCurrencyM, NewCurrency);
        //*** Поменять цены справочных ресурсов
        DefineMTPriceFields(AMTResources, PriceFields, OldCurrencyM, NewCurrency);
        PriceFields.Free;
      end;
      Result := true;
    end
    else
    with TF_Main(GForm).DM do
    begin
      //*** Сбросить флаг IsCountry на всех записях
      //CurrentID := 0;
      if cbIsCountry.Checked then
      begin
        SetSQLToQuery(scsQOperat, 'UPDATE CURRENCY SET '+fnIsCountry+' = '''+IntToStr(biFalse)+'''');
        DataSet_CURRENCY.FullRefresh;
      end;

      case AMakeEdit of
        meMake:
          DataSet_CURRENCY.Append;
        meEdit:
          DataSet_CURRENCY.Edit;
      end;
      DataSet_CURRENCY.FN(fnName).AsString := edName.Text;
      DataSet_CURRENCY.FN(fnNameBrief).AsString := edNameBrief.Text;
      DataSet_CURRENCY.FN(fnKolvo).AsInteger := NewCurrency.Kolvo;
      DataSet_CURRENCY.FN(fnRatio).AsFloat := NewCurrency.Ratio;
      //DataSet_CURRENCY.FN(fnMain).AsInteger := NewCurrency.Main;
      DataSet_CURRENCY.FN(fnIsCountry).AsInteger := BoolToInt(cbIsCountry.Checked);
      DataSet_CURRENCY.Post;

      if AMakeEdit = meMake then
        GID := DataSet_CURRENCY.FN(fnID).AsInteger;

      // Смена главной/второй валюты НБ
      if ChangedCurrencyM then
      begin
        BeginProgress;
        try
          OldCurrencyM := U_BaseCommon.GetCurrencyByType(ctMain, TF_Main(GForm).DM.Query_Select);
          CurrencyS := U_BaseCommon.GetCurrencyByType(ctSecond, TF_Main(GForm).DM.Query_Select);
          // Если даная валюта стала главной
          if NewCurrency.Main = ctMain then
          begin
            //25.10.2011 if OldCurrencyM.GUID <> '' then
            begin
              if OldCurrencyM.Ratio <> 0 then
                ChengeCurrencyRatiosWithPrices(OldCurrencyM, NewCurrency, CurrencyS, Query_Select, Query_Operat);
              UpdateTableField(tnCurrency, fnMain, fnID, NewCurrency.ID, ctMain, qmPhisical);
              if (NewCurrency.ID = CurrencyS.ID) and (OldCurrencyM.ID <> 0) then
                UpdateTableField(tnCurrency, fnMain, fnID, OldCurrencyM.ID, ctSecond, qmPhisical);
            end;
          end
          // Если даная валюта была главной и стала не главной
          else if (OldCurrency.Main = ctMain) and (NewCurrency.Main <> ctMain) then
          begin
            ChengeCurrencyRatiosWithPrices(OldCurrencyM, CurrencyS, OldCurrency, Query_Select, Query_Operat);
          end
          // Если даная валюта стала второй
          else if NewCurrency.Main = ctSecond then
          begin
            //*** Очистить поле с второй валютой
            SetSQLToFIBQuery(TF_Main(GForm).DM.Query_Operat, GetSQLByParams(qtUpdate, tnCurrency,
              fnMain+' = '''+IntTostr(ctSecond)+'''', nil, fnMain), false);
            TF_Main(GForm).DM.Query_Operat.ParamByName(fnMain).AsInteger := ctSimple;
            TF_Main(GForm).DM.Query_Operat.ExecQuery;
            UpdateTableField(tnCurrency, fnMain, fnID, NewCurrency.ID, ctSecond, qmPhisical);
          end;
          TF_Main(GForm).GCurrencyM := U_BaseCommon.GetCurrencyByType(ctMain, TF_Main(GForm).DM.Query_Select);
          TF_Main(GForm).GCurrencyS := U_BaseCommon.GetCurrencyByType(ctSecond, TF_Main(GForm).DM.Query_Select);
          TF_Main(GForm).SetCurrencyBriefToControls;
          TF_Main(GForm).Tree_Catalog.OnChange(TF_Main(GForm).Tree_Catalog, TF_Main(GForm).Tree_Catalog.Selected);

          DataSet_CURRENCY.ReopenLocate(fnID);
        finally
          EndProgress;
          //TF_Main(GForm).RefreshNode(true); // Внтури BeginProgress/EndProgress работать не будет
        end;
      end;
      Result := true;
    end;
  end;
end;

{//23.08.2012 - Пока нигде не используется
function TF_MakeCurrency.ExecuteForObject(AMakeEdit: TMakeEdit; AObjectCurrency: PCurrency): Boolean;
begin
  Result := false;
  Caption := '';
  GID := -1;
  GMakeEdit := AMakeEdit;

  rbSimple.Enabled := true;
  rbSimple.Checked := false;
  rbMain.Enabled := true;
  rbMain.Checked := false;
  rbSecond.Enabled := true;
  rbSecond.Checked := false;
  case AMakeEdit of
    meMake:
      begin
        Caption := cMakeCurrency_Msg1_1;
        edName.Text := '';
        edNameBrief.Text := '';
        seKolvo.Value := 100;
        neRatio.Value := 0.1;
        cbIsCountry.Checked := false;
        rbSimple.Checked := true;
      end;
    meEdit:
      begin
        Caption := cMakeCurrency_Msg1_2;
        edName.Text := AObjectCurrency.Name;
        edNameBrief.Text := AObjectCurrency.NameBrief;
        seKolvo.Value := AObjectCurrency.Kolvo;
        neRatio.Value := Round3(AObjectCurrency.Ratio);
        if AObjectCurrency.Main = ctSimple then
          rbSimple.Checked := true
        else
        if AObjectCurrency.Main = ctMain then
        begin
          rbMain.Checked := true;
          rbSimple.Enabled := false;
          rbSecond.Enabled := false;
        end
        else
        if AObjectCurrency.Main = ctSecond then
        begin
          rbSecond.Checked := true;
          rbMain.Enabled := false;
          rbSimple.Enabled := false;
        end;

        neRatio.OnChange := nil;
        try
          neRatio.Value := Round3(AObjectCurrency.Ratio);
        finally
          neRatio.OnChange := neRatioChange;
        end;
        if AObjectCurrency.Main = ctSimple then
          rbSimple.Checked := true
        else
        if AObjectCurrency.Main = ctMain then
        begin
          rbMain.Checked := true;
          rbSimple.Enabled := false;
          //rbSecond.Enabled := false;
        end
        else
        if AObjectCurrency.Main = ctSecond then
        begin
          rbSecond.Checked := true;
          //rbMain.Enabled := false;
          rbSimple.Enabled := false;
        end;

        //cbIsCountry.Checked := (TF_Main(GForm).DM.DataSet_CURRENCY.FN(fnIsCountry).AsInteger = biTrue);
      end;
  end;

  if ShowModal = mrOk then
  begin
    AObjectCurrency.Name := edName.Text;
    AObjectCurrency.NameBrief := edNameBrief.Text;
    AObjectCurrency.Kolvo := Trunc(seKolvo.Value);
    AObjectCurrency.Ratio := Round3(neRatio.Value);
    if rbSimple.Checked then
      AObjectCurrency.Main := ctSimple
    else
    if rbMain.Checked then
      AObjectCurrency.Main := ctMain
    else
    if rbSecond.Checked then
      AObjectCurrency.Main := ctSecond;

    Result := true;
  end;
end;}

procedure TF_MakeCurrency.FormCreate(Sender: TObject);
begin
  // Tolik 01/11/2019 --
  seKolvo.Max := 10000000000;
  //
  neRatio.DisplayFormat := GetDisplayFormatForFloat;
end;

procedure TF_MakeCurrency.neRatioChange(Sender: TObject);
begin
  FChangedRatio := true;
  // Tolik 12/06/2018 - -
  if neRatio.Value = 0 then
  begin
    neRatio.Font.Color := clRed;
    neRatio.Refresh;
  end
  else
  begin
    neRatio.Font.Color := clBlack;
    neRatio.Refresh;
  end;
end;

end.
