unit CalcDecimal;

interface

uses
  Classes, sdDB;

type
  TDecimal = class
  private
    FDigit: Integer;
    FFormat: string;
    FLinkViewCols: TList;
    FRelaDecimal: TDecimal;
    FCompareValue: Double;
    procedure SetDigit(const Value: Integer);

    function GetDisplayFormat(ADigit: Integer): string;
    procedure SetRelaDecimal(const Value: TDecimal);
  public
    constructor Create;
    destructor Destroy; override;

    function RoundTo(AValue: Double): Double;
    function StrRoundTo(const AValue: string): string;
    function CheckSameNum(AValue1, AValue2: Double): Boolean;

    procedure ClearLinkViewCols;
    procedure AddLinkViewCol(ACol: TObject);

    procedure RefreshLinkViewColsFormat;

    property Digit: Integer read FDigit write SetDigit;
    property Format: string read FFormat;
    property CompareValue: Double read FCompareValue;

    property RelaDecimal: TDecimal read FRelaDecimal write SetRelaDecimal;
  end;

  TCalcDecimal = class
  private
    FQuantity: TDecimal;
    FTotalPrice: TDecimal;
    FPrice: TDecimal;
    FRelaCalcDecimal: TCalcDecimal;
    procedure SetRelaCalcDecimal(const Value: TCalcDecimal);
  public
    constructor Create;
    destructor Destroy; override;

    procedure RefreshLinkViewColumnsFormat;

    property Quantity: TDecimal read FQuantity;
    property TotalPrice: TDecimal read FTotalPrice;
    property Price: TDecimal read FPrice;

    property RelaCalcDecimal: TCalcDecimal read FRelaCalcDecimal write SetRelaCalcDecimal;
  end;

  TDecimalManager = class
  private
    FProjectData: TObject;
    FCommon: TCalcDecimal;
    FCompile: TCalcDecimal;
    FPriceMargin: TCalcDecimal;
    FDealPay: TCalcDecimal;
  public
    constructor Create(AProjectData: TObject);
    destructor Destroy; override;

    procedure ResetLinkViewColumns;

    property Common: TCalcDecimal read FCommon;
    property Compile: TCalcDecimal read FCompile;
    property PriceMargin: TCalcDecimal read FPriceMargin;
    property DealPay: TCalcDecimal read FDealPay;
  end;

implementation

uses
  ProjectData, UtilMethods, SysUtils, Math;

{ TDecimal }

procedure TDecimal.AddLinkViewCol(ACol: TObject);
begin
  FLinkViewCols.Add(ACol);
end;

function TDecimal.CheckSameNum(AValue1, AValue2: Double): Boolean;
begin
  Result := Abs(RoundTo(AValue1 - AValue2)) < CompareValue;
end;

procedure TDecimal.ClearLinkViewCols;
begin
  FLinkViewCols.Clear;
end;

constructor TDecimal.Create;
begin
  FLinkViewCols := TList.Create;
  FDigit := -1;
end;

destructor TDecimal.Destroy;
begin
  FLinkViewCols.Free;
  inherited;
end;

function TDecimal.GetDisplayFormat(ADigit: Integer): string;
begin
  case ADigit of
    0: Result := '0';
    1: Result := '0.#';
    2: Result := '0.##';
    3: Result := '0.###';
    4: Result := '0.####';
    5: Result := '0.#####';
    6: Result := '0.######';
    7: Result := '0.#######';
    8: Result := '0.########';
    9: Result := '0.#########';
  else
    Result := '0.##########';
  end;
end;

procedure TDecimal.RefreshLinkViewColsFormat;
var
  i: Integer;
  ViewCol: TsdViewColumn;
begin
  for i := 0 to FLinkViewCols.Count - 1 do
  begin
    ViewCol := TsdViewColumn(FLinkViewCols.Items[i]);
    if not Assigned(ViewCol) then Continue;
    if Assigned(RelaDecimal) then
    begin
      ViewCol.DisplayFormat := FRelaDecimal.FFormat;
      ViewCol.EditFormat := FRelaDecimal.FFormat;
    end
    else
    begin
      ViewCol.DisplayFormat := FFormat;
      ViewCol.EditFormat := FFormat;
    end;
  end;
end;

function TDecimal.RoundTo(AValue: Double): Double;
begin
  if Assigned(RelaDecimal) then
    Result := FRelaDecimal.RoundTo(AValue)
  else
    Result := CommonRoundTo(AValue, -Digit);
end;

procedure TDecimal.SetDigit(const Value: Integer);
begin
  if FDigit <> Value then
  begin
    FDigit := Value;
    FFormat := GetDisplayFormat(FDigit);
    FCompareValue := GetCompareDigitValue(FDigit);
    RefreshLinkViewColsFormat;
  end;
end;

procedure TDecimal.SetRelaDecimal(const Value: TDecimal);
begin
  FRelaDecimal := Value;
  RefreshLinkViewColsFormat;
end;

function TDecimal.StrRoundTo(const AValue: string): string;
begin
  if Assigned(FRelaDecimal) then
    Result := RelaDecimal.StrRoundTo(AValue)
  else
    Result := FloatToStr(RoundTo(StrToFloatDef(AValue, 0)));
end;

{ TCalcDecimal }

constructor TCalcDecimal.Create;
begin
  FQuantity := TDecimal.Create;
  FTotalPrice := TDecimal.Create;
  FPrice := TDecimal.Create;
end;

destructor TCalcDecimal.Destroy;
begin
  FPrice.Free;
  FTotalPrice.Free;
  FQuantity.Free;
  inherited;
end;

procedure TCalcDecimal.RefreshLinkViewColumnsFormat;
begin
  Quantity.RefreshLinkViewColsFormat;
  TotalPrice.RefreshLinkViewColsFormat;
  Price.RefreshLinkViewColsFormat;
end;

procedure TCalcDecimal.SetRelaCalcDecimal(const Value: TCalcDecimal);
begin
  FRelaCalcDecimal := Value;
  if Assigned(FRelaCalcDecimal) then
  begin
    Quantity.RelaDecimal := FRelaCalcDecimal.Quantity;
    TotalPrice.RelaDecimal := FRelaCalcDecimal.TotalPrice;
    Price.RelaDecimal := FRelaCalcDecimal.Price;
  end
  else
  begin
    Quantity.RelaDecimal := nil;
    TotalPrice.RelaDecimal := nil;
    Price.RelaDecimal := nil;
  end;
end;

{ TDecimalManager }

constructor TDecimalManager.Create(AProjectData: TObject);
begin
  FProjectData := AProjectData;
  FCommon := TCalcDecimal.Create;
  FCompile := TCalcDecimal.Create;
  FPriceMargin := TCalcDecimal.Create;
  FDealPay := TCalcDecimal.Create;
end;

destructor TDecimalManager.Destroy;
begin
  FDealPay.Free;
  FPriceMargin.Free;
  FCompile.Free;
  FCommon.Free;
  inherited;
end;

procedure TDecimalManager.ResetLinkViewColumns;

  procedure ResetCommonLink;
  begin
    FCommon.Quantity.ClearLinkViewCols;
    FCommon.TotalPrice.ClearLinkViewCols;
    FCommon.Price.ClearLinkViewCols;
    with TProjectData(FProjectData).BillsCompileData.sdvBillsCompile do
    begin
      // Quantity
      FCommon.Quantity.AddLinkViewCol(Columns.FindColumn('OrgQuantity'));
      FCommon.Quantity.AddLinkViewCol(Columns.FindColumn('MisQuantity'));
      FCommon.Quantity.AddLinkViewCol(Columns.FindColumn('OthQuantity'));
      FCommon.Quantity.AddLinkViewCol(Columns.FindColumn('Quantity'));
      FCommon.Quantity.AddLinkViewCol(Columns.FindColumn('DgnQuantity1'));
      FCommon.Quantity.AddLinkViewCol(Columns.FindColumn('DgnQuantity2'));
      // TotalPrice
      FCommon.TotalPrice.AddLinkViewCol(Columns.FindColumn('OrgTotalPrice'));
      FCommon.TotalPrice.AddLinkViewCol(Columns.FindColumn('MisTotalPrice'));
      FCommon.TotalPrice.AddLinkViewCol(Columns.FindColumn('OthTotalPrice'));
      FCommon.TotalPrice.AddLinkViewCol(Columns.FindColumn('TotalPrice'));
      // Price
      FCommon.Price.AddLinkViewCol(Columns.FindColumn('Price'));
      FCommon.Price.AddLinkViewCol(Columns.FindColumn('NewPrice'));
    end;
    with TProjectData(FProjectData).BillsMeasureData.sdvBillsMeasure do
    begin
      // Quantity
      FCommon.Quantity.AddLinkViewCol(Columns.FindColumn('Quantity'));

      FCommon.Quantity.AddLinkViewCol(Columns.FindColumn('CurDealQuantity'));
      FCommon.Quantity.AddLinkViewCol(Columns.FindColumn('CurQcQuantity'));
      FCommon.Quantity.AddLinkViewCol(Columns.FindColumn('CurPcQuantity'));
      FCommon.Quantity.AddLinkViewCol(Columns.FindColumn('CurGatherQuantity'));

      FCommon.Quantity.AddLinkViewCol(Columns.FindColumn('EndDealQuantity'));
      FCommon.Quantity.AddLinkViewCol(Columns.FindColumn('EndQcQuantity'));
      FCommon.Quantity.AddLinkViewCol(Columns.FindColumn('EndPcQuantity'));
      FCommon.Quantity.AddLinkViewCol(Columns.FindColumn('EndGahterQuantity'));

      FCommon.Quantity.AddLinkViewCol(Columns.FindColumn('AddDealQuantity'));
      FCommon.Quantity.AddLinkViewCol(Columns.FindColumn('AddQcQuantity'));
      FCommon.Quantity.AddLinkViewCol(Columns.FindColumn('AddPcQuantity'));
      FCommon.Quantity.AddLinkViewCol(Columns.FindColumn('AddGahterQuantity'));

      FCommon.Quantity.AddLinkViewCol(Columns.FindColumn('DealDgnQuantity1'));
      FCommon.Quantity.AddLinkViewCol(Columns.FindColumn('DealDgnQuantity2'));
      FCommon.Quantity.AddLinkViewCol(Columns.FindColumn('CDgnQuantity1'));
      FCommon.Quantity.AddLinkViewCol(Columns.FindColumn('CDgnQuantity2'));
      // TotalPrice
      FCommon.TotalPrice.AddLinkViewCol(Columns.FindColumn('TotalPrice'));

      FCommon.TotalPrice.AddLinkViewCol(Columns.FindColumn('CurDealTotalPrice'));
      FCommon.TotalPrice.AddLinkViewCol(Columns.FindColumn('CurQcTotalPrice'));
      FCommon.TotalPrice.AddLinkViewCol(Columns.FindColumn('CurPcTotalPrice'));
      FCommon.TotalPrice.AddLinkViewCol(Columns.FindColumn('CurGatherTotalPrice'));

      FCommon.TotalPrice.AddLinkViewCol(Columns.FindColumn('EndDealTotalPrice'));
      FCommon.TotalPrice.AddLinkViewCol(Columns.FindColumn('EndQcTotalPrice'));
      FCommon.TotalPrice.AddLinkViewCol(Columns.FindColumn('EndPcTotalPrice'));
      FCommon.TotalPrice.AddLinkViewCol(Columns.FindColumn('EndGahterTotalPrice'));

      FCommon.TotalPrice.AddLinkViewCol(Columns.FindColumn('AddDealTotalPrice'));
      FCommon.TotalPrice.AddLinkViewCol(Columns.FindColumn('AddQcTotalPrice'));
      FCommon.TotalPrice.AddLinkViewCol(Columns.FindColumn('AddPcTotalPrice'));
      FCommon.TotalPrice.AddLinkViewCol(Columns.FindColumn('AddGahterTotalPrice'));
      // Price
      FCommon.Price.AddLinkViewCol(Columns.FindColumn('Price'));
      FCommon.Price.AddLinkViewCol(Columns.FindColumn('NewPrice'));
    end;
  end;

  procedure ResetComplieLink;
  begin

  end;

  procedure ResetPriceMarginLink;
  begin
    FPriceMargin.Price.ClearLinkViewCols;
    with TProjectData(FProjectData).ProjectGLData.sdvProjectGL do
    begin
      FPriceMargin.Price.AddLinkViewCol(Columns.FindColumn('BasePrice'));
      FPriceMargin.Price.AddLinkViewCol(Columns.FindColumn('InfoPrice'));
      FPriceMargin.Price.AddLinkViewCol(Columns.FindColumn('DeltaPrice'));
      FPriceMargin.Price.AddLinkViewCol(Columns.FindColumn('ValidDeltaPrice'));

      FPriceMargin.Quantity.AddLinkViewCol(Columns.FindColumn('PM_Quantity'));
      FPriceMargin.Quantity.AddLinkViewCol(Columns.FindColumn('UsedQuantity'));
      FPriceMargin.Quantity.AddLinkViewCol(Columns.FindColumn('PAL_UsedQuantity'));

      FPriceMargin.TotalPrice.AddLinkViewCol(Columns.FindColumn('PM_TotalPrice'));
      FPriceMargin.TotalPrice.AddLinkViewCol(Columns.FindColumn('UsedTotalPrice'));
      FPriceMargin.TotalPrice.AddLinkViewCol(Columns.FindColumn('PAL_UsedTotalPrice'));
      FPriceMargin.TotalPrice.AddLinkViewCol(Columns.FindColumn('PAL_UsedTotalPrice'));
      FPriceMargin.TotalPrice.AddLinkViewCol(Columns.FindColumn('PAL_DeltaPrice'));
      FPriceMargin.TotalPrice.AddLinkViewCol(Columns.FindColumn('PAL_Total'));
    end;

    with TProjectData(FProjectData).ProjectGLData.sdvGather do
    begin
      FPriceMargin.TotalPrice.AddLinkViewCol(Columns.FindColumn('CurTotalPrice'));
      FPriceMargin.TotalPrice.AddLinkViewCol(Columns.FindColumn('PreTotalPrice'));
      FPriceMargin.TotalPrice.AddLinkViewCol(Columns.FindColumn('EndTotalPrice'));
      FPriceMargin.TotalPrice.AddLinkViewCol(Columns.FindColumn('AddTotalPrice'));
    end;

    with TProjectData(FProjectData).PriceMarginBillsData.sdvDetailGclBills do
    begin
      FPriceMargin.TotalPrice.AddLinkViewCol(Columns.FindColumn('PM_TotalPrice'));
    end;

    with TProjectData(FProjectData).PriceMarginBillsData.sdvDetailGL do
    begin
      FPriceMargin.Quantity.AddLinkViewCol(Columns.FindColumn('Quantity'));

      FPriceMargin.TotalPrice.AddLinkViewCol(Columns.FindColumn('PM_PreTotalPrice'));
      FPriceMargin.TotalPrice.AddLinkViewCol(Columns.FindColumn('PM_CurTotalPrice'));
      FPriceMargin.TotalPrice.AddLinkViewCol(Columns.FindColumn('PM_EndTotalPrice'));
    end;
  end;

  procedure ResetDealPayLink;
  begin
    with TProjectData(FProjectData).DealPaymentData.sdvDealPayment do
    begin
      FDealPay.TotalPrice.AddLinkViewCol(Columns.FindColumn('CurTotalPrice'));
      FDealPay.TotalPrice.AddLinkViewCol(Columns.FindColumn('TotalPrice'));
      FDealPay.TotalPrice.AddLinkViewCol(Columns.FindColumn('StartPrice'));
      FDealPay.TotalPrice.AddLinkViewCol(Columns.FindColumn('RangePrice'));
    end;
  end;

begin
  {ResetCommonLink;
  FCommon.RefreshLinkViewColumnsFormat;
  ResetComplieLink;
  FCompile.RefreshLinkViewColumnsFormat;}
  ResetPriceMarginLink;
  FPriceMargin.RefreshLinkViewColumnsFormat;
  ResetDealPayLink;
  FDealPay.RefreshLinkViewColumnsFormat;
end;

end.
