unit U_ReportForm;

interface

uses
  Windows, U_LNG, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, U_BaseCommon, U_BaseConstants, U_Common, U_SCSComponent, U_SCSLists, Math, ExtCtrls, RzPanel, RzButton,
  cxStyles, cxCustomData, cxGraphics, cxFilter, cxData, cxDataStorage,
  cxEdit, DB, cxDBData, cxGridLevel, cxClasses, cxControls,
  cxGridCustomView, cxGridCustomTableView, cxGridTableView,
  cxGridDBTableView, cxGrid, kbmMemTable, StdCtrls, Mask, RzEdit,
  cxCurrencyEdit, cxCheckBox, cxColorComboBox, cxSpinEdit, cxDropDownEdit,
  cxDBLookupComboBox, cxTextEdit, ActnList, ActnMan, Menus, ComCtrls,
  ToolWin, XPMenu, siComp, siLngLnk, cxMemo, cxImageComboBox, Buttons,
  cxLookAndFeels, cxLookAndFeelPainters, cxNavigator,
  PlatformDefaultStyleActnCtrls;

//const
  //Colmn Indexes
  //ciTransToUOM = 10;

type
  TF_ReportForm = class(TForm)
    RzGroupBox1: TRzGroupBox;
    gbOkCancel: TRzGroupBox;
    btOK: TRzBitBtn;
    btCancel: TRzBitBtn;
    RzPanel1: TRzPanel;
    GT_Resources: TcxGridDBTableView;
    GL_Resources: TcxGridLevel;
    gridResources: TcxGrid;
    mtResources: TkbmMemTable;
    dsrcResources: TDataSource;
    lbTotalCost: TLabel;
    neTotalCost: TRzNumericEdit;
    GT_ResourcesName: TcxGridDBColumn;
    GT_ResourcesArticulProducer: TcxGridDBColumn;
    GT_ResourcesArticulDistributor: TcxGridDBColumn;
    GT_ResourcesProducerName: TcxGridDBColumn;
    GT_ResourcesIzm: TcxGridDBColumn;
    GT_ResourcesKolvo: TcxGridDBColumn;
    GT_ResourcesPrice: TcxGridDBColumn;
    GT_ResourcesCost: TcxGridDBColumn;
    mtProducers: TkbmMemTable;
    dsrcProducers: TDataSource;
    Timer_DefineTotalCost: TTimer;
    Timer_PostResources: TTimer;
    ActionManager: TActionManager;
    Act_ReplaceComponent: TAction;
    PopupMenu: TPopupMenu;
    N1: TMenuItem;
    Act_DelComponent: TAction;
    ToolBar1: TToolBar;
    ToolButton1: TToolButton;
    ToolButton2: TToolButton;
    N2: TMenuItem;
    XPMenu1: TXPMenu;
    GT_ResourcesNpp: TcxGridDBColumn;
    btApply: TRzBitBtn;
    lng_Forms: TsiLangLinked;
    GT_ResourcesTransformToUOM: TcxGridDBColumn;
    GT_ResourcesIsResource: TcxGridDBColumn;
    GT_ResourcesGUIDNBCompon: TcxGridDBColumn;
    GT_ResourcesIcon: TcxGridDBColumn;
    GT_ResourcesPriceNB: TcxGridDBColumn;
    Act_LoadPricesFromNB: TAction;
    N3: TMenuItem;
    ToolButton3: TToolButton;
    ToolButton4: TToolButton;
    procedure gbOkCancelResize(Sender: TObject);
    procedure mtResourcesBeforeEdit(DataSet: TDataSet);
    procedure mtResourcesAfterEdit(DataSet: TDataSet);
    procedure FormCreate(Sender: TObject);
    procedure GT_ResourcesPricePropertiesValidate(Sender: TObject;
      var DisplayValue: Variant; var ErrorText: TCaption;
      var Error: Boolean);
    procedure GT_ResourcesCostPropertiesValidate(Sender: TObject;
      var DisplayValue: Variant; var ErrorText: TCaption;
      var Error: Boolean);
    procedure neTotalCostChange(Sender: TObject);
    procedure GT_ResourcesEditing(Sender: TcxCustomGridTableView;
      AItem: TcxCustomGridTableItem; var AAllow: Boolean);
    procedure GT_ResourcesEditValueChanged(Sender: TcxCustomGridTableView;
      AItem: TcxCustomGridTableItem);
    procedure Timer_DefineTotalCostTimer(Sender: TObject);
    procedure Timer_PostResourcesTimer(Sender: TObject);
    procedure Act_ReplaceComponentExecute(Sender: TObject);
    procedure Act_DelComponentExecute(Sender: TObject);
    procedure GT_ResourcesNppGetDisplayText(Sender: TcxCustomGridTableItem;
      ARecord: TcxCustomGridRecord; var AText: String);
    procedure btApplyClick(Sender: TObject);
    procedure GT_ResourcesIzmGetDisplayText(Sender: TcxCustomGridTableItem;
      ARecord: TcxCustomGridRecord; var AText: String);
    procedure GT_ResourcesPriceGetDisplayText(
      Sender: TcxCustomGridTableItem; ARecord: TcxCustomGridRecord;
      var AText: String);
    procedure GT_ResourcesInitEdit(Sender: TcxCustomGridTableView;
      AItem: TcxCustomGridTableItem; AEdit: TcxCustomEdit);
    procedure GT_ResourcesKolvoGetDisplayText(
      Sender: TcxCustomGridTableItem; ARecord: TcxCustomGridRecord;
      var AText: String);
    procedure GT_ResourcesFocusedRecordChanged(
      Sender: TcxCustomGridTableView; APrevFocusedRecord,
      AFocusedRecord: TcxCustomGridRecord;
      ANewItemRecordFocusingChanged: Boolean);
    procedure GT_ResourcesCustomDrawCell(Sender: TcxCustomGridTableView;
      ACanvas: TcxCanvas; AViewInfo: TcxGridTableDataCellViewInfo;
      var ADone: Boolean);
    procedure Act_LoadPricesFromNBExecute(Sender: TObject);
    procedure GT_ResourcesPriceNBPropertiesValidate(Sender: TObject;
      var DisplayValue: Variant; var ErrorText: TCaption;
      var Error: Boolean);
    procedure neTotalCostKeyPress(Sender: TObject; var Key: Char);
    procedure neTotalCostExit(Sender: TObject);
  private
    GForm: TForm;
    FCanHaveActiveComponents: Boolean;
    FCanHaveDismountAccount: Boolean;
    FComponsWithZeroPrice: Boolean;
    FFormMode: TResourceReportFormMode;
    FFolder: TSCSCatalog;
    FLastTotalCost: Double;
    FNormResources: TSCSNormsResources;
    FReportName: String;

    Edit: TcxCustomEdit;
    //Colmn Indexes
    FTransToUOMIdx: Integer;

    procedure DefineTotalCost;
    procedure PrepareForm;
    function OnPriceValidate(const aFieldName: String; var aDisplayValue: Variant): Double;
    procedure OnTotalCostChange;
    procedure SendPriceAndCostToCurrRecord(APrice, ACost: Double);
    procedure SendStringToCurrRecord(AFieldName, AValue: String);
    procedure SendFromMTToObjects;
    procedure SendProducersToMT;
    procedure SendResourcesToMT;
    procedure SetActions;
  public
    constructor Create(AOwner: TComponent; AForm: TForm); overload;
    destructor Destroy; override;

    function Execute(AFolder: TSCSCatalog; const AReportName: String;
              AFormMode: TResourceReportFormMode; ACanHaveActiveComponents, ACanHaveDismountAccount, AComponsWithZeroPrice: Boolean): Boolean;
  end;

//var
  //F_ReportForm: TF_ReportForm;

implementation
Uses U_Main, Unit_DM_SCS, U_DMCommon;
{$R *.dfm}

{ TF_ReportForm }

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

destructor TF_ReportForm.Destroy;
begin

  inherited;
end;

function TF_ReportForm.Execute(AFolder: TSCSCatalog; const AReportName: String;
  AFormMode: TResourceReportFormMode; ACanHaveActiveComponents, ACanHaveDismountAccount, AComponsWithZeroPrice: Boolean): Boolean;
begin
  Result := false;
  if AFolder <> nil then
  begin
    FFolder := AFolder;
    FFormMode := AFormMode;
    FCanHaveActiveComponents := ACanHaveActiveComponents;
    FCanHaveDismountAccount := ACanHaveDismountAccount;
    FComponsWithZeroPrice := AComponsWithZeroPrice;
    FReportName := AReportName;
    FLastTotalCost := -1;
    FNormResources := nil;

    mtProducers.Active := False;
    mtProducers.Active := True;

    mtResources.Active := False;
    mtResources.Active := True;

    PrepareForm;
    SendProducersToMT;
    SendResourcesToMT;

    try
      if ShowModal = mrOk then
      begin
        Result := true;
        SendFromMTToObjects;
      end;
    finally
      if FNormResources <> nil then
        FreeAndNil(FNormResources);
    end;
  end;
end;

procedure TF_ReportForm.gbOkCancelResize(Sender: TObject);
begin
  SetMiddleControlChilds(TControl(Sender), TControl(Self));
end;

procedure TF_ReportForm.FormCreate(Sender: TObject);
var
  i: Integer;
  Action: TAction;
  ImgCbProps: TcxImageComboBoxProperties;

  procedure AddItemToImgCbProps(AImageIndex: Integer);
  var
    ImgCbItem: TcxImageComboBoxItem; //}TCollectionItem;
  begin
    ImgCbItem := TcxImageComboBoxItem(ImgCbProps.Items.Add);
    ImgCbItem.Value := AImageIndex;
    ImgCbItem.ImageIndex := AImageIndex;
  end;

begin
  for i := 0 to ActionManager.ActionCount - 1 do
  begin
    Action := TAction(ActionManager.Actions[i]);
    Action.Hint := Action.Caption;
  end;

  mtResources.FieldDefs.Add(fnID, ftAutoInc);
  mtResources.FieldDefs.Add(fnGuid, ftString, 40);
  mtResources.FieldDefs.Add(fnIsResource, ftBoolean);
  mtResources.FieldDefs.Add(fnIsModified, ftBoolean);
  mtResources.FieldDefs.Add(fnObjectAddress, ftInteger);
  mtResources.FieldDefs.Add(fnTransToUOM, ftBoolean);
  mtResources.FieldDefs.Add(fnGuidNBComponent, ftString, 40);
  mtResources.FieldDefs.Add(fnIconType, ftInteger);

  mtResources.FieldDefs.Add(fnName, ftString, 255);
  mtResources.FieldDefs.Add(fnArticulProducer, ftString, 255);
  mtResources.FieldDefs.Add(fnArticulDistributor, ftString, 255);
  mtResources.FieldDefs.Add(fnGuidProducer, ftString, 255);
  mtResources.FieldDefs.Add(fnIzm, ftString, 50);
  mtResources.FieldDefs.Add(fnFirstKolvo, ftFloat);
  mtResources.FieldDefs.Add(fnFirstPrice, ftFloat);
  mtResources.FieldDefs.Add(fnKolvo, ftFloat);
  mtResources.FieldDefs.Add(fnPrice, ftFloat);
  mtResources.FieldDefs.Add(fnCost, ftFloat);
  mtResources.FieldDefs.Add(fnPriceNB, ftFloat);

  mtProducers.FieldDefs.Add(fnID, ftInteger);
  mtProducers.FieldDefs.Add(fnGuid, ftString, 40);
  mtProducers.FieldDefs.Add(fnName, ftString, 255);

  ImgCbProps := TcxImageComboBoxProperties(GT_ResourcesIcon.Properties);
  ImgCbProps.Images := TF_Main(GForm).DM.ImageList_Dir;
  ImgCbProps.LargeImages := TF_Main(GForm).DM.ImageList_Dir;
  AddItemToImgCbProps(tciiComponLine);
  AddItemToImgCbProps(tciiComponCon);
  AddItemToImgCbProps(tciiTemplateLine);
  AddItemToImgCbProps(tciiTemplateCon);

  if GReadOnlyMode then
  begin
    btOk.Enabled := False;
    btApply.Enabled := False;
    ToolBar1.Enabled := False;
  end;

end;


procedure TF_ReportForm.PrepareForm;
var
  CurrencyName: String;
begin
  gbOkCancelResize(gbOkCancel);
  Caption := FReportName + ' - ' + FFolder.GetNameForVisible;

  CurrencyName := TF_Main(GForm).GCurrencyM.NameBrief;
  if CurrencyName <> '' then
    CurrencyName := ', ' + CurrencyName;

  FTransToUOMIdx := GT_ResourcesTransformToUOM.Index;
  SetCxCurrencyEditProperties(GT_ResourcesPrice.Properties); //29.08.2012 TcxCurrencyEditProperties(GT_ResourcesPrice.Properties).DisplayFormat := GetDisplayFormatForFloat;
  SetCxCurrencyEditProperties(GT_ResourcesCost.Properties); //29.08.2012 TcxCurrencyEditProperties(GT_ResourcesCost.Properties).DisplayFormat := GetDisplayFormatForFloat;
  SetCxCurrencyEditProperties(GT_ResourcesPriceNB.Properties); //29.08.2012 TcxCurrencyEditProperties(GT_ResourcesPriceNB.Properties).DisplayFormat := GetDisplayFormatForFloat;

  neTotalCost.DisplayFormat := GetDisplayFormatForFloat; //GetDisplayFormat(TF_Main(GForm).GCurrencyM.NameBrief);
  neTotalCost.IntegersOnly := false;

  GT_ResourcesPrice.Caption := cReportForm_Msg1 + CurrencyName;
  GT_ResourcesCost.Caption := cReportForm_Msg2 + CurrencyName;
  GT_ResourcesPriceNB.Caption := cReportForm_Msg1_2 + CurrencyName;
  lbTotalCost.Caption := cReportForm_Msg3 + CurrencyName;
end;

function TF_ReportForm.OnPriceValidate(const aFieldName: String; var aDisplayValue: Variant): Double;
var
  OldPrice: Double;
  NewPrice: Double;
begin
  OldPrice := mtResources.FieldByName(aFieldName).AsFloat;
  if aDisplayValue = '' then
  begin
    aDisplayValue := FloatToStr(OldPrice);
    Exit; ///// EXIT /////
  end;
  NewPrice := StrToFloat(aDisplayValue);
  // Преобразуем цену из TF_Main(GForm).FUOM на метр
  if mtResources.FieldByName(fnTransToUOM).AsBoolean then
  begin
    NewPrice := FloatInUOM(NewPrice, umMetr, TF_Main(GForm).FUOM);
    if NewPrice <> OldPrice then
    begin
      mtResources.Edit;
      mtResources.FieldByName(aFieldName).AsFloat := NewPrice;
      mtResources.Post;
    end;
  end;
  Result := NewPrice;
  if OldPrice = NewPrice then
    Exit; ///// EXIT /////

end;

procedure TF_ReportForm.OnTotalCostChange;
var
  NewValue: Double;
  PercentFromLast: Double;

  RecordCost: Double;
  RecordPrice: Double;

  RecNo: Integer;
  i: Integer;
begin
  NewValue := neTotalCost.Value;
  if NewValue = 0 then
  begin
    neTotalCost.OnChange := nil;
    try
      neTotalCost.Value := FLastTotalCost;
    finally
      neTotalCost.OnChange := neTotalCostChange;
    end;
    Exit; ///// EXIT /////
  end;
  // Tolik 28/12/2019 --
  if mtResources.RecordCount > 0 then
  begin
    PercentFromLast := RoundX((NewValue * 100) / FLastTotalCost, 20);
    RecNo := mtResources.RecNo;
    mtResources.DisableControls;
    try
      for i := 0 to mtResources.RecordCount - 1 do
      begin
        mtResources.RecNo := i+1;

        RecordCost := mtResources.FieldByName(fnCost).AsFloat;
        RecordCost := RecordCost * (PercentFromLast / 100);
        RecordPrice := RoundCP(RecordCost / mtResources.FieldByName(fnKolvo).AsFloat);

        SendPriceAndCostToCurrRecord(RecordPrice, RecordCost);
      end;
      mtResources.RecNo := RecNo;
    finally
      mtResources.EnableControls;
    end;
  end;
  FLastTotalCost := NewValue;
end;

procedure TF_ReportForm.mtResourcesBeforeEdit(DataSet: TDataSet);
begin
  //beep;
end;

procedure TF_ReportForm.mtResourcesAfterEdit(DataSet: TDataSet);
begin
  if DataSet.State <> dsBrowse then
    DataSet.FieldByName(fnIsModified).AsBoolean := true;
end;

procedure TF_ReportForm.SendStringToCurrRecord(AFieldName, AValue: String);
begin
  mtResources.Edit;
  mtResources.FieldByName(AFieldName).AsString := AValue;
  mtResources.Post;
end;

procedure TF_ReportForm.SendFromMTToObjects;
var
  ResourceGroup: TSCSResourceGroup;
  SCSComponent: TSCSComponent;
  PartComponent: TSCSComponent;

  ResourceRel: TSCSResourceRel;

  ChangedComponents: TSCSComponents;
  RecNo: Integer;
  i, j, k: Integer;
  IsRecalcTotal: Boolean;
begin
  ChangedComponents := TSCSComponents.Create(false);

  if mtResources.RecordCount > 0 then // Tolik 28/12/2019 --
  begin
    RecNo := mtResources.RecNo;
    mtResources.DisableControls;
    try
      IsRecalcTotal := false;
      for i := 0 to mtResources.RecordCount - 1 do
      begin
        mtResources.RecNo := i+1;
        if GT_ResourcesPriceNB.Visible then
          if mtResources.FieldByName(fnPriceNB).Value <> null then
          begin
            mtResources.Edit;
            mtResources.FieldByName(fnPrice).AsFloat := mtResources.FieldByName(fnPriceNB).AsFloat;
            mtResources.FieldByName(fnCost).AsFloat := mtResources.FieldByName(fnPrice).AsFloat * mtResources.FieldByName(fnKolvo).AsFloat;
            mtResources.FieldByName(fnIsModified).AsBoolean := true;
            mtResources.Post;
            IsRecalcTotal := true;
          end;

        if mtResources.FieldByName(fnIsModified).AsBoolean then
        begin
          ResourceGroup := TSCSResourceGroup(mtResources.FieldByName(fnObjectAddress).AsInteger);
          if Assigned(ResourceGroup) then
            for j := 0 to ResourceGroup.ObjectList.Count - 1 do
            begin
              case ResourceGroup.ServIsResource of
                False:
                  begin
                    SCSComponent := TSCSComponent(ResourceGroup.ObjectList[j]);

                    SCSComponent.Name := mtResources.FieldByName(fnName).AsString;
                    SCSComponent.ArticulDistributor := mtResources.FieldByName(fnArticulDistributor).AsString;
                    SCSComponent.ArticulProducer := mtResources.FieldByName(fnArticulProducer).AsString;
                    SCSComponent.Izm := mtResources.FieldByName(fnIzm).AsString;
                    SCSComponent.Price := mtResources.FieldByName(fnPrice).AsFloat;
                    SCSComponent.GUIDProducer := mtResources.FieldByName(fnGuidProducer).AsString;
                    if SCSComponent.GUIDProducer <> '' then
                      SCSComponent.ID_Producer := TF_Main(GForm).FNormBase.DM.GetIntFromTableByGUID(tnProducers, fnID, SCSComponent.GUIDProducer, qmPhisical)
                    else
                      SCSComponent.ID_Producer := 0;

                    ChangedComponents.Add(SCSComponent);

                    if SCSComponent.IsLine = biTrue then
                    begin
                      SCSComponent.LoadWholeComponent(false);
                      for k := 0 to SCSComponent.WholeComponent.Count - 1 do
                      begin
                        PartComponent := TF_Main(GForm).GSCSBase.CurrProject.GetComponentFromReferences(SCSComponent.WholeComponent[k]);

                        if PartComponent <> SCSComponent then
                        begin
                          PartComponent.Name := SCSComponent.Name;
                          PartComponent.ArticulDistributor := SCSComponent.ArticulDistributor;
                          PartComponent.ArticulProducer := SCSComponent.ArticulProducer;
                          PartComponent.Izm := SCSComponent.Izm;
                          PartComponent.Price := SCSComponent.Price;
                          PartComponent.GUIDProducer := SCSComponent.GUIDProducer;
                          PartComponent.ID_Producer := SCSComponent.ID_Producer;

                          ChangedComponents.Add(PartComponent);
                        end;
                      end;
                    end;
                  end;
                True:
                  begin
                    ResourceRel := TSCSResourceRel(ResourceGroup.ObjectList[j]);

                    ResourceRel.Name := mtResources.FieldByName(fnName).AsString;
                    ResourceRel.Izm := mtResources.FieldByName(fnIzm).AsString;
                    ResourceRel.Price := mtResources.FieldByName(fnPrice).AsFloat;
                    ResourceRel.CalcCost;
                  end;
              end;
            end;
          mtResources.Edit;
          mtResources.FieldByName(fnIsModified).AsBoolean := False;
          mtResources.FieldByName(fnPriceNB).Value := null;
          mtResources.Post;
        end;
      end;

      for i := 0 to ChangedComponents.Count - 1 do
      begin
        SCSComponent := ChangedComponents[i];
        TF_Main(GForm).CalcPriceForParents(SCSComponent.ID);
      end;

      if IsRecalcTotal then
        Timer_DefineTotalCost.Enabled := true;
    finally
      mtResources.RecNo := RecNo;
      mtResources.EnableControls;
      FreeAndNil(ChangedComponents);
      //GT_ResourcesPriceNB.Visible := false;
    end;
  end;
end;

procedure TF_ReportForm.SendProducersToMT;
var
  //AllProducers: TList;
  //ptrProducer: PProducer;
  Spravochnik: TSpravochnik;
  SprProducer: TNBProducer;
  i: Integer;
begin
  //AllProducers := TF_Main(GForm).FNormBase.DM.GetAllProducers;
  try
    mtProducers.Active := false;
    mtProducers.Active := true;
    mtProducers.DisableControls;

    {mtProducers.Append;
    mtProducers.FieldByName(fnID).AsInteger := 0;
    mtProducers.FieldByName(fnGUID).AsString := '';
    mtProducers.FieldByName(fnName).AsString := '';
    mtProducers.Post;}

    Spravochnik := TF_Main(GForm).GSCSBase.CurrProject.Spravochnik;

    for i := 0 to Spravochnik.Producers.Count - 1 do
    begin
      SprProducer := TNBProducer(Spravochnik.Producers[i]);

      mtProducers.Append;
      mtProducers.FieldByName(fnID).AsInteger := SprProducer.ID;
      mtProducers.FieldByName(fnGUID).AsString := SprProducer.GUID;
      mtProducers.FieldByName(fnName).AsString := SprProducer.Name;
      mtProducers.Post;
    end;
  finally
    mtProducers.EnableControls;
    mtProducers.SortOn(fnName, []);
  end;
end;

procedure TF_ReportForm.SendResourcesToMT;
var
  ResourceRel: TSCSResourceGroup;
  ResourceCompon: TSCSComponent;
  ComponImageIndex: Integer;
  i: Integer;
begin
  BeginProgress(pcPreparingReport);
  try
    FNormResources := FFolder.GetAllNormsResources([nrResources, nrAccessories, nrComponents],
                          false, FCanHaveActiveComponents, FCanHaveDismountAccount, FComponsWithZeroPrice);
    //mtResources.AfterPost := nil;
    mtResources.DisableControls;
    try
      mtResources.Active := false;
      mtResources.Active := true;

      for i := 0 to FNormResources.Resources.Count - 1 do
      begin
        ResourceRel := TSCSResourceGroup(FNormResources.Resources[i]);
        ComponImageIndex := -1;

        mtResources.Append;
        mtResources.FieldByName(fnGuid).AsString := ResourceRel.GuidNB;
        mtResources.FieldByName(fnIsResource).AsBoolean := ResourceRel.ServIsResource;
        mtResources.FieldByName(fnIsModified).AsBoolean := false;
        mtResources.FieldByName(fnObjectAddress).AsInteger := Integer(ResourceRel);
        if ResourceRel.ServIsResource then
          mtResources.FieldByName(fnTransToUOM).AsBoolean := false
        else
        if ResourceRel.ObjectList.Count > 0 then
        begin
          ResourceCompon := TSCSComponent(ResourceRel.ObjectList[0]);
          if CheckPriceTransformToUOMByCompType(@ResourceCompon.ComponentType) then//26.05.2009 if CheckPriceTransformToUOMByCompType(@TSCSComponent(ResourceRel.ObjectList[0]).ComponentType) then
            mtResources.FieldByName(fnTransToUOM).AsBoolean := true;

          // Иконка компонента
          case ResourceCompon.IsLine of
            biTrue:
              if ResourceCompon.IsTemplate = biTrue then
                ComponImageIndex := tciiTemplateLine
              else
                ComponImageIndex := tciiComponLine;
            biFalse:
              if ResourceCompon.IsTemplate = biTrue then
                ComponImageIndex := tciiTemplateCon
              else
                ComponImageIndex := tciiComponCon;
          end;
        end;
        mtResources.FieldByName(fnGuidNBComponent).AsString := ResourceRel.GUIDNBComponent;
        if Not ResourceRel.ServIsResource then
          mtResources.FieldByName(fnGuidNBComponent).AsString := ResourceRel.GuidNB;
        mtResources.FieldByName(fnIconType).AsInteger := ComponImageIndex;

        mtResources.FieldByName(fnName).AsString := ResourceRel.Name;
        mtResources.FieldByName(fnArticulProducer).AsString := ResourceRel.ArtProducer;
        mtResources.FieldByName(fnArticulDistributor).AsString := ResourceRel.ArtDistributor;
        mtResources.FieldByName(fnGuidProducer).AsString := ResourceRel.GUIDProducer; //}TF_Main(GForm).FNormBase.DM.GetStringFromTableByGUID(tnProducers, fnName, ResourceRel.GUIDProducer, qmPhisical);
        mtResources.FieldByName(fnIzm).AsString := ResourceRel.Izm;
        mtResources.FieldByName(fnFirstKolvo).AsFloat := Round3(ResourceRel.Kolvo);
        mtResources.FieldByName(fnFirstPrice).AsFloat := Round3(ResourceRel.Price);
        mtResources.FieldByName(fnKolvo).AsFloat := Round3(ResourceRel.Kolvo);
        mtResources.FieldByName(fnPrice).AsFloat := Round3(ResourceRel.Price);
        mtResources.FieldByName(fnCost).AsFloat := Round3(ResourceRel.Cost);
        mtResources.Post;

        //TotalCost := TotalCost + ResourceRel.Cost;
      end;
      mtResources.SortOn(fnName, []);
    finally
      mtResources.EnableControls;
      //mtResources.AfterPost := mtResourcesAfterPost;
      if mtResources.RecordCount > 0 then
        mtResources.First;
    end;
  finally
    EndProgress;
  end;
  DefineTotalCost;
  SetActions;
end;

procedure TF_ReportForm.SetActions;
begin
  Act_ReplaceComponent.Enabled := mtResources.RecordCount > 0;
  Act_DelComponent.Enabled := mtResources.RecordCount > 0;
end;

procedure TF_ReportForm.DefineTotalCost;
var
  RecNo: Integer;
  i: Integer;
  CurrCost: Double;

  SavedOnChange: TNotifyevent;
begin
  CurrCost := 0;

  if mtResources.RecordCount > 0 then
  begin
    RecNo := mtResources.RecNo;
    mtResources.DisableControls;
    try
      for i := 0 to mtResources.RecordCount - 1 do
      begin
        mtResources.RecNo := i+1;
        CurrCost := CurrCost + mtResources.FieldByName(fnCost).AsFloat;
      end;
    finally
      mtResources.EnableControls;
      mtResources.RecNo := RecNo;
    end;
  end;
  FLastTotalCost := CurrCost;

  SavedOnChange := neTotalCost.OnChange;
  neTotalCost.OnChange := nil;
  try
    neTotalCost.Value := CurrCost;
  finally
    neTotalCost.OnChange := SavedOnChange;
  end;
end;

procedure TF_ReportForm.GT_ResourcesPricePropertiesValidate(
  Sender: TObject; var DisplayValue: Variant; var ErrorText: TCaption;
  var Error: Boolean);
var
  //OldPrice: Double;
  NewPrice: Double;
  NewCost: Double;
begin
  TcxCurrencyEditProperties(GT_ResourcesPrice.Properties).OnValidate := nil;
  try
    {//28.08.2012
    OldPrice := mtResources.FieldByName(fnPrice).AsFloat;
    if DisplayValue = '' then
    begin
      DisplayValue := FloatToStr(OldPrice);
      Exit; ///// EXIT /////
    end;
    NewPrice := StrToFloat(DisplayValue);
    // Преобразуем цену из TF_Main(GForm).FUOM на метр
    if mtResources.FieldByName(fnTransToUOM).AsBoolean then
    begin
      NewPrice := FloatInUOM(NewPrice, umMetr, TF_Main(GForm).FUOM);
      if NewPrice <> OldPrice then
      begin
        mtResources.Edit;
        mtResources.FieldByName(fnPrice).AsFloat := NewPrice;
        mtResources.Post;
      end;
    end;
    if OldPrice = NewPrice then
      Exit; ///// EXIT /////}
    NewPrice := OnPriceValidate(fnPrice, DisplayValue);

    NewCost := NewPrice * mtResources.FieldByName(fnKolvo).AsFloat;
    SendPriceAndCostToCurrRecord(NewPrice, NewCost);
    Timer_DefineTotalCost.Enabled := true;
  finally
    TcxCurrencyEditProperties(GT_ResourcesPrice.Properties).OnValidate := GT_ResourcesPricePropertiesValidate;
  end;
end;

procedure TF_ReportForm.GT_ResourcesPriceNBPropertiesValidate(
  Sender: TObject; var DisplayValue: Variant; var ErrorText: TCaption;
  var Error: Boolean);
begin
  TcxCurrencyEditProperties(GT_ResourcesPriceNB.Properties).OnValidate := nil;
  try
    OnPriceValidate(fnPriceNB, DisplayValue);
  finally
    TcxCurrencyEditProperties(GT_ResourcesPriceNB.Properties).OnValidate := GT_ResourcesPricePropertiesValidate;
  end;
end;


procedure TF_ReportForm.GT_ResourcesCostPropertiesValidate(Sender: TObject;
  var DisplayValue: Variant; var ErrorText: TCaption; var Error: Boolean);
var
  OldCost: Double;
  NewPrice: Double;
  NewCost: Double;
begin
  TcxCurrencyEditProperties(GT_ResourcesCost.Properties).OnValidate := nil;
  try
    OldCost := mtResources.FieldByName(fnCost).AsFloat;
    if DisplayValue = '' then
    begin
      DisplayValue := FloatToStr(OldCost);
      Exit; ///// EXIT /////
    end;
    NewCost := StrToFloat(DisplayValue);
    if OldCost = NewCost then
      Exit; ///// EXIT /////

    NewPrice := RoundCP(NewCost / mtResources.FieldByName(fnKolvo).AsFloat);
    SendPriceAndCostToCurrRecord(NewPrice, NewCost);
    Timer_DefineTotalCost.Enabled := true;
  finally
    TcxCurrencyEditProperties(GT_ResourcesCost.Properties).OnValidate := GT_ResourcesCostPropertiesValidate;
  end;
end;

procedure TF_ReportForm.SendPriceAndCostToCurrRecord(APrice,
  ACost: Double);
begin
  mtResources.Edit;
  mtResources.FieldByName(fnPrice).AsFloat := APrice;
  mtResources.FieldByName(fnCost).AsFloat := ACost;
  mtResources.FieldByName(fnIsModified).AsBoolean := true;
  mtResources.Post;
end;

procedure TF_ReportForm.neTotalCostChange(Sender: TObject);
begin
  OnTotalCostChange;
end;

procedure TF_ReportForm.GT_ResourcesEditing(Sender: TcxCustomGridTableView;
  AItem: TcxCustomGridTableItem; var AAllow: Boolean);
begin
  //mtResources.Edit;
  //mtResources.FieldByName(fnIsModified).AsBoolean := true;
  //mtResources.Post;
end;

procedure TF_ReportForm.GT_ResourcesEditValueChanged(
  Sender: TcxCustomGridTableView; AItem: TcxCustomGridTableItem);
begin
  if (Sender.DataController.IsEditing) and (mtResources.State <> dsBrowse) then
  begin
    Timer_PostResources.Enabled := true;
  end;
end;

procedure TF_ReportForm.Timer_DefineTotalCostTimer(Sender: TObject);
begin
  TTimer(Sender).Enabled := false;
  DefineTotalCost;
end;

procedure TF_ReportForm.Timer_PostResourcesTimer(Sender: TObject);
begin
  TTimer(Sender).Enabled := false;
  if mtResources.State <> dsBrowse then
  begin
    GT_Resources.DataController.Post;
  end;
end;


procedure TF_ReportForm.Act_ReplaceComponentExecute(Sender: TObject);
var
  GroupResource: TSCSResourceGroup;
  ComponentList: TSCSComponents;
  SCSComponent: TSCSComponent;

  NBComponent: TSCSComponent;
  ReplacedComponent: TSCSComponent;
  FirstReplacedComponent: TSCSComponent;
  ComponentIndex: Integer;

  CanReplaceIndexes: TIntList;
  CanReplaceCount: Integer;

  strText: String;
  strWarning: String;

  SelectedRecord: Boolean;

  i: Integer;
  CmpDelta: Double;
begin
  try
    TF_Main(GForm).CreateFConnectComplWith;

    CmpDelta := 1 / Power(10, FloatPrecision);
    GroupResource := nil;
    GroupResource := TSCSResourceGroup(mtResources.FieldByName(fnObjectAddress).AsInteger);
    if GroupResource <> nil then
    begin
      if Not GroupResource.ServIsResource then
      begin
        if GroupResource.ObjectList.Count > 0 then
        begin
          ComponentList := TSCSComponents.Create(false);
          CanReplaceIndexes := TIntList.Create;
          CanReplaceCount := 0;

          try
            for i := 0 to GroupResource.ObjectList.Count - 1 do
              ComponentList.Add(TSCSComponent(GroupResource.ObjectList[i]));

            NBComponent := TF_Main(GForm).CreateFConnectComplWith.DefineReplaceComponent(ComponentList, ComponentIndex, true);
            if NBComponent <> nil then
            begin
              //*** Анализ всех на подкл.
              BeginProgress;
              try
                for i := 0 to ComponentList.Count - 1 do
                begin
                  SCSComponent := ComponentList[i];
                  CanReplaceIndexes.Add(biNone);

                  if (SCSComponent.IsLine = biTrue) or
                     (SCSComponent.Parent is TSCSCatalog) or
                     (TF_Main(GForm).CreateFConnectComplWith.cbApplyForComplects.Checked) then
                  begin
                    if SCSComponent.CanReplaceWithNBCompon(NBComponent, TF_Main(GForm).CreateFConnectComplWith.cbLeaveComplectsInTarget.Checked) = [crcrSuccessful] then
                    begin
                      Inc(CanReplaceCount);
                      CanReplaceIndexes[i] := biTrue;
                    end
                    else
                      CanReplaceIndexes[i] := biFalse;
                  end;
                end;
              finally
                EndProgress;
              end;

              strText := '';
              strWarning := cReportForm_Msg4;
              if CanReplaceIndexes.Count <> CanReplaceCount then
              begin
                strText := cReportForm_Msg5+#13+#10+#13+#10+ strWarning;
              end
              else
                strText := strText + strWarning + #13+#10+ cReportForm_Msg6;


              if MessageModal(strText, ApplicationName, MB_ICONQUESTION or MB_YESNO) = IDYES then
              begin
                ProcessMessagesEx;
                BeginProgress;
                try
                  mtResources.DisableControls;
                  try
                    //if FFolder is TSCSList then
                    //  OpenNoExistsListInCAD(FFolder);

                    FirstReplacedComponent := nil;
                    //*** Заменить компоненты
                    for i := 0 to CanReplaceIndexes.Count - 1 do
                      if CanReplaceIndexes[i] = biTrue then
                      begin
                        SCSComponent := ComponentList[i];
                        //ReplacedComponent := SCSComponent.ReplaceWithNBCompon(NBComponent, TF_Main(GForm).F_ConnectComplWith.cbLeaveComplectsInTarget.Checked);
                        ReplacedComponent := ReplacePMComponFromNB(SCSComponent, NBComponent, TF_Main(GForm).CreateFConnectComplWith.cbLeaveComplectsInTarget.Checked);
                        if (FirstReplacedComponent = nil) and (ReplacedComponent <> nil) then
                          FirstReplacedComponent := ReplacedComponent;
                      end;

                    //*** Обновить ведомость ресурсов
                    if FNormResources <> nil then
                      FreeAndNil(FNormResources);
                    SendResourcesToMT;

                    //*** Выделить позицию с замененной компонентой
                    SelectedRecord := false;
                    if FirstReplacedComponent <> nil then
                      for i := 0 to mtResources.RecordCount - 1 do
                      begin
                        mtResources.RecNo := i+1;
                        if (mtResources.FieldByName(fnIsResource).AsBoolean = false) and
                           (mtResources.FieldByName(fnGuid).AsString = FirstReplacedComponent.GuidNB) and
                           (mtResources.FieldByName(fnName).AsString = FirstReplacedComponent.Name) and
                           (mtResources.FieldByName(fnArticulProducer).AsString = FirstReplacedComponent.ArticulProducer) and
                           (mtResources.FieldByName(fnArticulDistributor).AsString = FirstReplacedComponent.ArticulDistributor) and
                           (mtResources.FieldByName(fnGuidProducer).AsString = FirstReplacedComponent.GUIDProducer) and
                           (mtResources.FieldByName(fnIzm).AsString = FirstReplacedComponent.Izm) and
                           (Abs(mtResources.FieldByName(fnPrice).AsFloat - Round3(FirstReplacedComponent.Price)) < CmpDelta) then
                        begin
                          SelectedRecord := true;
                          Break; //// BREAK ////
                        end;
                      end;
                    if Not SelectedRecord then
                      if mtResources.RecordCount > 0 then
                        mtResources.First;
                  finally
                    mtResources.EnableControls;
                  end;
                finally
                  EndProgress;
                end;
              end;
            end;
          finally
            FreeAndNil(ComponentList);
            FreeAndNil(CanReplaceIndexes);
          end;
        end;
      end
      else
        MessageModal(cReportForm_Msg7,
          ApplicationName, MB_ICONINFORMATION or MB_OK);
    end;
  except
    on E: Exception do AddExceptionToLog('TF_ReportForm.Act_ReplaceComponentExecute: '+E.Message);
  end;
end;

procedure TF_ReportForm.Act_DelComponentExecute(Sender: TObject);
var
  GroupResource: TSCSResourceGroup;
  SCSComponent: TSCSComponent;
  WholeComponent: TSCSComponents;
  PartComponent: TSCSComponent;

  CanDeleteComponents: TSCSComponents;
  CanDelete: Boolean;
  strText: String;
  msgStyle: Integer;
  msgResult: Integer;

  i: Integer;
  RecNo: Integer;
begin
  try
    GroupResource := nil;
    GroupResource := TSCSResourceGroup(mtResources.FieldByName(fnObjectAddress).AsInteger);
    if GroupResource <> nil then
    begin
      if (Not GroupResource.ServIsResource) and (GroupResource.ObjectList.Count > 0) then
      begin
        CanDeleteComponents := TSCSComponents.Create(false);
        try
          //*** Анализ на удаление не подключенных компонент
          for i := 0 to GroupResource.ObjectList.Count - 1 do
          begin
            SCSComponent := TSCSComponent(GroupResource.ObjectList[i]);

            case SCSComponent.IsLine of
              biFalse:
                if Not CheckJoinedComponToIsLine(SCSComponent, biTrue, true) or
                  (SCSComponent.ComponentType.SysName = ctsnCableChannelElement) then
                  CanDeleteComponents.Add(SCSComponent);
              biTrue:
                if ((SCSComponent.FirstIDConnectedConnCompon = 0) and (SCSComponent.LastIDConnectedConnCompon = 0)) or
                   (SCSComponent.ComponentType.SysName = ctsnCableChannel) then
                  CanDeleteComponents.Add(SCSComponent);
            end;
          end;

          strText := '';
          msgStyle := MB_ICONQUESTION or MB_YESNO;

          CanDelete := true;
          if (CanDeleteComponents.Count <> GroupResource.ObjectList.Count) then
          begin
            if CanDeleteComponents.Count = 0 then
            begin
              strText := cReportForm_Msg9;
              msgStyle := MB_ICONINFORMATION or MB_OK;
              CanDelete := false;
            end
            else
              strText := cReportForm_Msg10;
          end
          else
            strText := cReportForm_Msg8; //strText := strText + strWarning + #13+#10+ cReportForm_Msg11;
          msgResult := MessageModal(strText, ApplicationName, msgStyle);

          if CanDelete and (msgResult = IDYES) then
          begin
            //if FFolder is TSCSList then
            //  OpenNoExistsListInCAD(FFolder);

            TF_Main(GForm).DelComponentsFromList(TSCSList(FFolder), CanDeleteComponents, true);

            BeginProgress;
            try
              RecNo := mtResources.RecNo;

              {
              //*** Удаление компонент
              while CanDeleteComponents.Count > 0 do
              begin
                SCSComponent := CanDeleteComponents[0];
                CanDeleteComponents.Delete(0);

                if SCSComponent.IsLine = biTrue then
                begin
                  if SCSComponent.ChildComplects.Count > 0 then
                  begin
                    SCSComponent.TreeViewNode := TF_Main(GForm).FindComponOrDirInTree(SCSComponent.ID, true);
                    TF_Main(GForm).MoveComponComplectsToUp(SCSComponent.TreeViewNode);
                  end;
                  WholeComponent := FFolder.GetComponentsByWholeID(SCSComponent.Whole_ID);
                  for i := 0 to WholeComponent.Count - 1 do
                  begin
                    PartComponent := WholeComponent[i];
                    //PartComponent.DisConnectFromParent;
                    TF_Main(GForm).DelCompon(PartComponent, PartComponent.TreeViewNode, true, true, true, false);
                  end;
                end
                else
                begin
                  //SCSComponent.DisConnectFromParent;
                  TF_Main(GForm).DelCompon(SCSComponent, SCSComponent.TreeViewNode, true, true, true, false);
                end;
              end;
              }

              //*** Обновить ведомость ресурсов
              if FNormResources <> nil then
                FreeAndNil(FNormResources);
              SendResourcesToMT;

              //*** Стать на позицию перед удаляемой
              if mtResources.RecordCount > 0 then
              begin
                if RecNo > mtResources.RecordCount + 1 then
                  RecNo := mtResources.RecordCount + 1;
                if RecNo > -1 then // Tolik 28/12/2019 --
                  mtResources.RecNo := RecNo;
              end;
            finally
              EndProgress;
            end;
          end;
        finally
          FreeAndNil(CanDeleteComponents);
        end;
      end
      else
        MessageModal(cReportForm_Msg12,
          ApplicationName, MB_ICONINFORMATION or MB_OK);
    end;
    SetActions;
  except
    on E: Exception do AddExceptionToLog('TF_ReportForm.Act_DelComponentExecute: '+E.Message);
  end;
end;

procedure TF_ReportForm.GT_ResourcesNppGetDisplayText(
  Sender: TcxCustomGridTableItem; ARecord: TcxCustomGridRecord;
  var AText: String);
begin
  AText := IntToStr(ARecord.Index + 1);
end;

procedure TF_ReportForm.btApplyClick(Sender: TObject);
begin
  SendFromMTToObjects;
end;

procedure TF_ReportForm.GT_ResourcesIzmGetDisplayText(
  Sender: TcxCustomGridTableItem; ARecord: TcxCustomGridRecord;
  var AText: String);
begin
  try
    if ARecord.Values[FTransToUOMIdx] <> null then
      if ARecord.Values[FTransToUOMIdx] = true then
        AText := GetNameUOM(TF_Main(GForm).FUOM, true);
  except
  end;
end;

procedure TF_ReportForm.GT_ResourcesKolvoGetDisplayText(
  Sender: TcxCustomGridTableItem; ARecord: TcxCustomGridRecord;
  var AText: String);
var
  ValueFloat: Double;
begin
  try
    if ARecord.Values[FTransToUOMIdx] <> null then
      if ARecord.Values[FTransToUOMIdx] = true then
      begin
        ValueFloat := StrToFloat(AText);
        ValueFloat := FloatInUOM(ValueFloat, umMetr, TF_Main(GForm).FUOM);
        AText := FloatToStr(RoundCP(ValueFloat));
      end;
  except
  end;
end;

procedure TF_ReportForm.GT_ResourcesPriceGetDisplayText(
  Sender: TcxCustomGridTableItem; ARecord: TcxCustomGridRecord;
  var AText: String);
begin
  try
    if ARecord.Values[FTransToUOMIdx] <> null then
      if ARecord.Values[FTransToUOMIdx] = true then
        AText := GetDisplayTextToNORMExpenseForLength(AText, TF_Main(GForm).FUOM);
  except
  end;
end;

procedure TF_ReportForm.GT_ResourcesInitEdit(
  Sender: TcxCustomGridTableView; AItem: TcxCustomGridTableItem;
  AEdit: TcxCustomEdit);
begin
  if (AItem = GT_ResourcesPrice) or (AItem = GT_ResourcesPriceNB) then
    if mtResources.Active then
      if mtResources.FieldByName(fnTransToUOM).AsBoolean then
        AEdit.EditValue := GetDisplayTextToNORMExpenseForLength(AEdit.EditValue, TF_Main(GForm).FUOM);
  Edit := AEdit;
end;

procedure TF_ReportForm.GT_ResourcesFocusedRecordChanged(
  Sender: TcxCustomGridTableView; APrevFocusedRecord,
  AFocusedRecord: TcxCustomGridRecord;
  ANewItemRecordFocusingChanged: Boolean);
var
  CanEditIzm: Boolean;
begin
  CanEditIzm := true;
  if mtResources.Active then
    if mtResources.FieldByName(fnTransToUOM).AsBoolean then
      CanEditIzm := false;
  GT_ResourcesIzm.Options.Editing := CanEditIzm;
end;

procedure TF_ReportForm.GT_ResourcesCustomDrawCell(
  Sender: TcxCustomGridTableView; ACanvas: TcxCanvas;
  AViewInfo: TcxGridTableDataCellViewInfo; var ADone: Boolean);
begin
  OnNormsResourcesCustomDrawCell(ACanvas, AViewInfo, GT_ResourcesIsResource.Index, GT_ResourcesGUIDNBCompon.Index, -1, false);
end;

procedure TF_ReportForm.Act_LoadPricesFromNBExecute(Sender: TObject);
var
  i: Integer;
  GUIDCompon: String;
  IDCompon: Integer;
  NBPrice: Double;
  Compon: TSCSComponent;
  //BookMark: String;
  BookMark: TBookMark;
begin
  GT_ResourcesPriceNB.Visible := true;

  //BookMark := mtResources.Bookmark;
  BookMark := mtResources.GetBookmark;
  try
    Compon := TSCSComponent.Create(F_NormBase);
    for i := 0 to GT_Resources.Controller.SelectedRecordCount - 1 do
    begin
      //GT_Resources.Controller.SelectedRows[i].
      GUIDCompon := GT_Resources.Controller.SelectedRecords[i].Values[GT_ResourcesGUIDNBCompon.Index];
      IDCompon := F_NormBase.DM.GetIntFromTableByGUID(tnComponent, fnID, GUIDCompon, qmPhisical);
      if IDCompon <> 0 then
      begin
        Compon.Clear;
        Compon.LoadComponentByID(IDCompon, false);
        DefineComponPriceOnCopyToOtherBase(Compon, nil, F_ProjMan.GSCSBase.CurrProject, F_NormBase, F_ProjMan);
        //GT_Resources.Controller.SelectedRecords[i].Values[GT_ResourcesPriceNB.Index] := Compon.Price;
        //GT_Resources.DataController.Values[GT_Resources.Controller.SelectedRecords[i].Index, GT_ResourcesPriceNB.Index] := Compon.Price;
        if mtResources.Locate(fnGuidNBComponent, GUIDCompon, []) then
        begin
          mtResources.Edit;
          mtResources.FieldByName(fnPriceNB).AsFloat := RoundCP(Compon.Price);
          mtResources.Post;
        end;
      end;
    end;
    Compon.Free;
  finally
    //mtResources.Bookmark := BookMark;
    mtResources.GOTOBookmark(BookMark);
    mtResources.FreeBookmark(BookMark);

  end;
end;


procedure TF_ReportForm.neTotalCostKeyPress(Sender: TObject;
  var Key: Char);
begin
  CorrectMaskKeyPress(Key);
  //if Key = #13 then
  //  OnTotalCostChange;
end;

procedure TF_ReportForm.neTotalCostExit(Sender: TObject);
begin
  //OnTotalCostChange;
end;

end.
