unit PriceMarginBillsDm;

interface

uses
  SysUtils, Classes, sdDB, sdProvider, BillsTree, mDataRecord,
  GclBillsGatherModel, DB, CalcDecimal;

type
  TPriceMarginBillsData = class(TDataModule)
    sdmpGclBills: TsdMemoryProvider;
    sddGclBills: TsdDataSet;
    sdmpDetailGclBills: TsdMemoryProvider;
    sddDetailGclBills: TsdDataSet;
    sdvGclBills: TsdDataView;
    sdvDetailGclBills: TsdDataView;
    sdvDetailGL: TsdDataView;
    procedure sdvGclBillsCurrentChanged(ARecord: TsdDataRecord);
    procedure sdvDetailGclBillsFilterRecord(ARecord: TsdDataRecord;
      var Allow: Boolean);
    procedure sdvDetailGLFilterRecord(ARecord: TsdDataRecord;
      var Allow: Boolean);
    procedure sdvDetailGclBillsCurrentChanged(ARecord: TsdDataRecord);
    procedure sdvDetailGLAfterValueChanged(AValue: TsdValue);
    procedure sdvDetailGclBillsGetText(var Text: String;
      ARecord: TsdDataRecord; AValue: TsdValue; AColumn: TsdViewColumn;
      DisplayText: Boolean);
    procedure sdvDetailGLAfterDeleteRecord(ARecord: TsdDataRecord);
    procedure sdvGclBillsGetText(var Text: String; ARecord: TsdDataRecord;
      AValue: TsdValue; AColumn: TsdViewColumn; DisplayText: Boolean);
    procedure sdvDetailGLSetText(var Text: String; ARecord: TsdDataRecord;
      AValue: TsdValue; AColumn: TsdViewColumn; var Allow: Boolean);
  private
    FProjectData: TObject;
    procedure WriteGclBillsData(AGcls, AXmjs: TList);
    function GetMainBillsTree: TBillsIDTree;
    function GetDecimal: TCalcDecimal;
  public
    constructor Create(AProjectData: TObject);
    destructor Destroy; override;

    procedure RefreshBills;
    procedure AddDetailGLs(AGls: TList);

    procedure RefreshDetailBills(ABillsID: Integer);
    procedure RefreshAllDetailBills;

    property ProjectData: TObject read FProjectData;
    property MainBillsTree: TBillsIDTree read GetMainBillsTree;
    property Decimal: TCalcDecimal read GetDecimal;
  end;

implementation

uses
  ZhAPI, ProjectData, UtilMethods;

{$R *.dfm}

{ TPriceMarginBillsData }

constructor TPriceMarginBillsData.Create(AProjectData: TObject);
begin
  inherited Create(nil);
  FProjectData := AProjectData;

  sddGclBills.Open;
  if not Assigned(sddGclBills.FindIndex('idxIndexCode')) then
    sddGclBills.AddIndex('idxIndexCode', 'IndexCode');
  sdvGclBills.Open;
  sdvGclBills.IndexName := 'idxIndexCode';

  sddDetailGclBills.Open;
  if not Assigned(sddDetailGclBills.FindIndex('idxSerialNo')) then
    sddDetailGclBills.AddIndex('idxSerialNo', 'BillsID;TreeSerialNo');
  if not Assigned(sddDetailGclBills.FindIndex('idxRelaBills')) then
    sddDetailGclBills.AddIndex('idxRelaBills', 'RelaBillsID');
  sdvDetailGclBills.Open;
  sdvDetailGclBills.IndexName := 'idxSerialNo';

  sdvDetailGL.DataSet := TProjectData(FProjectData).DetailGLData.sddDetailGL;
  sdvDetailGL.IndexName := 'idxView';
  sdvDetailGL.Columns.FindColumn('Name').LookupDataSet := TProjectData(FProjectData).ProjectGLData.sddProjectGL;
  sdvDetailGL.Columns.FindColumn('Units').LookupDataSet := TProjectData(FProjectData).ProjectGLData.sddProjectGL;
end;

destructor TPriceMarginBillsData.Destroy;
begin
  inherited;
end;

procedure TPriceMarginBillsData.RefreshBills;
var
  vGather: TGclGatherModel;
begin
  vGather := TGclGatherModel.Create(FProjectData);
  try
    vGather.WriteGatherData := WriteGclBillsData;
    vGather.Execute;
  finally
    vGather.Free;
  end;
end;

procedure TPriceMarginBillsData.WriteGclBillsData(AGcls, AXmjs: TList);

  procedure BeforeWrite;
  begin
    sdvDetailGclBills.Filtered := False;
    sdvDetailGL.Filtered := False;

    sddGclBills.DisableControls;
    sddGclBills.BeginUpdate;
    sddGclBills.DeleteAll;

    sddDetailGclBills.DisableControls;
    sddDetailGclBills.BeginUpdate;
    sddDetailGclBills.DeleteAll;
  end;

  procedure AfterWrite;
  var
    idx: TsdIndex;
  begin
    sddDetailGclBills.EndUpdate;
    sddDetailGclBills.EnableControls;

    sddGclBills.EndUpdate;
    sddGclBills.EnableControls;

    if not sdvDetailGL.Active then
      sdvDetailGL.Open;

    idx := sddGclBills.FindIndex('idxIndexCode');
    sdvGclBills.LocateInControl(sdvGclBills.Records[0]);
    sdvDetailGclBills.Filtered := True;
    sdvDetailGclBills.LocateInControl(sdvDetailGclBills.Records[0]);
    sdvDetailGL.Filtered := True;

    sdvDetailGclBills.LocateInControl(sdvDetailGclBills.Records[0]);
  end;

  procedure WriteDetailGclNode(AGclNode: TGclNode);
  var
    iDetailGcl: Integer;
    vDetailGcl: TDetailGclNode;
    Rec: TsdDataRecord;
  begin
    for iDetailGcl := 0 to AGclNode.DetailGclCount -1 do
    begin
      vDetailGcl := AGclNode.DetailGcl[iDetailGcl];
      Rec := sddDetailGclBills.Add;
      Rec.ValueByName('ID').AsInteger := vDetailGcl.ID;
      Rec.ValueByName('BillsID').AsInteger := AGclNode.ID;
      Rec.ValueByName('TreeSerialNo').AsInteger := vDetailGcl.TreeSerialNo;
      Rec.ValueByName('RelaBillsID').AsInteger := vDetailGcl.BillsID;

      if Assigned(vDetailGcl.LeafXmj) then
      begin
        Rec.ValueByName('LeafXmjID').AsInteger := vDetailGcl.LeafXmj.ID;
        Rec.ValueByName('XmjCode').AsString := vDetailGcl.LeafXmj.XmjCode;
        Rec.ValueByName('XmjName').AsString := vDetailGcl.LeafXmj.XmjName;
        Rec.ValueByName('XmjUnits').AsString := vDetailGcl.LeafXmj.XmjUnits;
        Rec.ValueByName('NameDanWei').AsString := vDetailGcl.LeafXmj.NameDanWei;
        Rec.ValueByName('NameFenXiang').AsString := vDetailGcl.LeafXmj.NameFenXiang;
        Rec.ValueByName('NameFenBu').AsString := vDetailGcl.LeafXmj.NameFenBu;
        Rec.ValueByName('NameUnit').AsString := vDetailGcl.LeafXmj.NameUnit;
        Rec.ValueByName('Peg').AsString := vDetailGcl.LeafXmj.Peg;
        Rec.ValueByName('Position').AsString := vDetailGcl.LeafXmj.Position;
        Rec.ValueByName('DrawingCode').AsString := vDetailGcl.LeafXmj.DrawingCode;
      end;

      Rec.ValueByName('CurDealQuantity').AsFloat := vDetailGcl.CurDealQuantity;
      Rec.ValueByName('CurQcQuantity').AsFloat := vDetailGcl.CurQcQuantity;
      Rec.ValueByName('CurGatherQuantity').AsFloat := vDetailGcl.CurGatherQuantity;

      Rec.ValueByName('PM_PreTotalPrice').AsFloat := vDetailGcl.PM_PreTotalPrice;
      Rec.ValueByName('PM_TotalPrice').AsFloat := vDetailGcl.PM_TotalPrice;
    end;
  end;

  procedure WriteGclNode(AGclNode: TGclNode);
  var
    Rec: TsdDataRecord;
  begin
    Rec := sddGclBills.Add;
    Rec.ValueByName('ID').AsInteger := AGclNode.ID;
    Rec.ValueByName('B_Code').AsString := AGclNode.B_Code;
    Rec.ValueByName('IndexCode').AsString := AGclNode.IndexCode;
    Rec.ValueByName('Name').AsString := AGclNode.Name;
    Rec.ValueByName('Units').AsString := AGclNode.Units;
    Rec.ValueByName('Price').AsFloat := AGclNode.Price;

    Rec.ValueByName('CurDealQuantity').AsFloat := AGclNode.CurDealQuantity;
    Rec.ValueByName('CurQcQuantity').AsFloat := AGclNode.CurQcQuantity;
    Rec.ValueByName('CurGatherQuantity').AsFloat := AGclNode.CurGatherQuantity;
    WriteDetailGclNode(AGclNode);
  end;

var
  iGcl: Integer;
  vGclNode: TGclNode;
begin
  BeforeWrite;
  try
    for iGcl := 0 to AGcls.Count - 1 do
    begin
      vGclNode := TGclNode(AGcls.Items[iGcl]);
      WriteGclNode(vGclNode);
    end;
  finally
    AfterWrite;
  end;
end;

procedure TPriceMarginBillsData.sdvGclBillsCurrentChanged(
  ARecord: TsdDataRecord);
begin
  sdvDetailGclBills.RefreshFilter;
  sdvDetailGclBills.LocateInControl(sdvDetailGclBills.Records[0]);
end;

procedure TPriceMarginBillsData.sdvDetailGclBillsFilterRecord(
  ARecord: TsdDataRecord; var Allow: Boolean);
begin
  if Assigned(sdvGclBills.Current) and Assigned(ARecord) then
    Allow := ARecord.ValueByName('BillsID').AsInteger = sdvGclBills.Current.ValueByName('ID').AsInteger
  else
    Allow := False;
end;

procedure TPriceMarginBillsData.sdvDetailGLFilterRecord(
  ARecord: TsdDataRecord; var Allow: Boolean);
begin
  if Assigned(sdvDetailGclBills.Current) and Assigned(ARecord) then
    Allow := ARecord.ValueByName('BillsID').AsInteger = sdvDetailGclBills.Current.ValueByName('RelaBillsID').AsInteger
  else
    Allow := False;
end;

function TPriceMarginBillsData.GetMainBillsTree: TBillsIDTree;
begin
  Result := TProjectData(FProjectData).BillsMeasureData.BillsMeasureTree;
end;

procedure TPriceMarginBillsData.AddDetailGLs(AGls: TList);
begin
  TProjectData(FProjectData).DetailGLData.AddDetailGLs(
      sdvDetailGclBills.Current.ValueByName('RelaBillsID').AsInteger, AGls);
  sdvDetailGL.RefreshFilter;
end;

procedure TPriceMarginBillsData.sdvDetailGclBillsCurrentChanged(
  ARecord: TsdDataRecord);
begin
  sdvDetailGL.RefreshFilter;
end;

procedure TPriceMarginBillsData.RefreshDetailBills(ABillsID: Integer);
var
  Rec: TsdDataRecord;
  StageRec: TStageRecord;
begin
  Rec := sddDetailGclBills.FindKey('idxRelaBills', ABillsID);
  if not Assigned(Rec) then Exit;

  StageRec := TProjectData(FProjectData).PhaseData.StageData.StageRecord(ABillsID);
  if Assigned(StageRec) then
    Rec.ValueByName('PM_TotalPrice').AsFloat := StageRec.PM_TotalPrice.AsFloat
  else
    Rec.ValueByName('PM_TotalPrice').AsFloat := 0;
end;

procedure TPriceMarginBillsData.sdvDetailGLAfterValueChanged(
  AValue: TsdValue);
var
  ARec: TDetailGLRecord;
begin
  if SameText(AValue.FieldName, 'Quantity') then
  begin
    ARec := TDetailGLRecord(AValue.Owner);
    // 更新调差工料--本期价差
    with TProjectData(FProjectData).ProjectGLData do
      CalculateGL_PM(ARec.GLID.AsInteger);
    // 更新清单调差数据，材料调差节点数据
    with TProjectData(FProjectData).PhaseData.StageData do
    begin
      CalculatePriceMargin(ARec.BillsID.AsInteger);
      //CalculatePriceMarginNode;
    end;
    // 更新价差清单内存表信息
    with TProjectData(FProjectData).PriceMarginBillsData do
      RefreshDetailBills(ARec.BillsID.AsInteger);
    // 更新合同支付
    //TProjectData(FProjectData).PhaseData.PhasePayData.CalculateAll;
    // 更新合计值
    TProjectData(FProjectData).ProjectGLData.RefreshGatherData;
  end;
end;

procedure TPriceMarginBillsData.sdvDetailGclBillsGetText(var Text: String;
  ARecord: TsdDataRecord; AValue: TsdValue; AColumn: TsdViewColumn;
  DisplayText: Boolean);

  procedure GetDisplayText;
  begin
    if ((Pos('Price', AColumn.FieldName) > 0) or
        (Pos('Quantity', AColumn.FieldName) > 0)) then
    begin
      if AValue.AsFloat = 0 then
        Text := '';
    end;
  end;

begin
  if DisplayText then
    GetDisplayText;
end;

procedure TPriceMarginBillsData.sdvDetailGLAfterDeleteRecord(
  ARecord: TsdDataRecord);
var
  ARec: TDetailGLRecord;
begin
  if ARecord.ValueByName('Quantity').AsFloat <> 0 then
  begin
    ARec := TDetailGLRecord(ARecord);
    // 更新调差工料--本期价差
    with TProjectData(FProjectData).ProjectGLData do
      CalculateGL_PM(ARec.GLID.AsInteger);
    // 更新清单调差数据，材料调差节点数据
    with TProjectData(FProjectData).PhaseData.StageData do
    begin
      CalculatePriceMargin(ARec.BillsID.AsInteger);
      //CalculatePriceMarginNode;
    end;
    // 更新价差清单内存表信息
    with TProjectData(FProjectData).PriceMarginBillsData do
      RefreshDetailBills(ARec.BillsID.AsInteger);
    // 更新合同支付
    //TProjectData(FProjectData).PhaseData.PhasePayData.CalculateAll;
    // 更新合计值
    TProjectData(FProjectData).ProjectGLData.RefreshGatherData;
  end;
end;

procedure TPriceMarginBillsData.sdvGclBillsGetText(var Text: String;
  ARecord: TsdDataRecord; AValue: TsdValue; AColumn: TsdViewColumn;
  DisplayText: Boolean);

  procedure GetDisplayText;
  begin
    if ((Pos('Price', AColumn.FieldName) > 0) or
        (Pos('Quantity', AColumn.FieldName) > 0)) then
    begin
      if AValue.AsFloat = 0 then
        Text := '';
    end;
  end;

begin
  if DisplayText then
    GetDisplayText;
end;

procedure TPriceMarginBillsData.RefreshAllDetailBills;
var
  i: Integer;
  Rec: TsdDataRecord;
  StageRec: TStageRecord;
begin
  for i := 0 to sddDetailGclBills.RecordCount - 1 do
  begin
    Rec := sddDetailGclBills.Records[i];

    with TProjectData(FProjectData).PhaseData.StageData do
      StageRec := StageRecord(Rec.ValueByName('RelaBillsID').AsInteger);
    if Assigned(StageRec) then
      Rec.ValueByName('PM_TotalPrice').AsFloat := StageRec.PM_TotalPrice.AsFloat
    else
      Rec. ValueByName('PM_TotalPrice').AsFloat := 0;
  end;
end;

procedure TPriceMarginBillsData.sdvDetailGLSetText(var Text: String;
  ARecord: TsdDataRecord; AValue: TsdValue; AColumn: TsdViewColumn;
  var Allow: Boolean);
begin
  if AValue.DataType in [ftInteger, ftFloat] then
    if not CheckNumeric(Text) then
      Text := '';

  if SameText(AValue.FieldName, 'Quantity') then
    Text := Decimal.Quantity.StrRoundTo(Text);
end;

function TPriceMarginBillsData.GetDecimal: TCalcDecimal;
begin
  Result := TProjectData(FProjectData).ProjProperties.DecimalManager.PriceMargin;
end;

end.
