| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643 | unit BillsDm;interfaceuses  StandardBillsFme,  ZhAPI, StandardLib, StageDm, BillsTree, mDataRecord,  SysUtils, Classes, sdDB, sdProvider, ADODB, sdIDTree, Math;const  DealIndex = 0;  AddDealIndex = 1;  AddQcIndex = 2;  AddPcIndex = 3;  AddGatherIndex = 4;type  TRecChangeEvent = procedure (ARec: TsdDataRecord) of object;  TBillsData = class(TDataModule)    sdpBills: TsdADOProvider;    sddBills: TsdDataSet;    procedure sddBillsAfterAddRecord(ARecord: TsdDataRecord);    procedure sddBillsBeforeDeleteRecord(ARecord: TsdDataRecord;      var Allow: Boolean);    procedure sddBillsBeforeValueChange(AValue: TsdValue;      const NewValue: Variant; var Allow: Boolean);    procedure sddBillsGetRecordClass(var ARecordClass: TsdRecordClass);  private    FProjectData: TObject;    FCurPhaseIndex: Integer;    FBeforeChangeTotalPrice: Double;    FBeforeChangeParentID: Integer;    //procedure RecursiveCalculate(ABillsID: Integer);    function GetStageData: TStageData;    function GetBuildLoadInterest(AIndex: Integer): Double;    function GetFirstPart(AIndex: Integer): Double;    function GetOtherFee(AIndex: Integer): Double;    function GetOtherProjectFee(AIndex: Integer): Double;    function GetRecyclingFee(AIndex: Integer): Double;    function GetReservedFee(AIndex: Integer): Double;    function GetSecondPart(AIndex: Integer): Double;    function GetStageSettlement(AIndex: Integer): Double;    function GetThirdPart(AIndex: Integer): Double;  public    constructor Create(AProjectData: TObject);    destructor Destroy; override;    procedure Open(AConnection: TADOConnection);    procedure Close;    procedure Save;    procedure InitBills;    // 计算 -- 均采用增量汇总方式计算父项   {procedure Calculate(ABillsID: Integer);    procedure CalculateDeal(ABillsID: Integer);           // 合同计量    procedure CalculateQuantityChange(ABillsID: Integer); // 数量变更计量    procedure CalculatePriceChange(ABillsID: Integer);    // 单价变更计量}    // 上报审核批复过程 -- 锁定数据    procedure LockedBaseData;    // 解锁数据    procedure UnLockedBaseData;    procedure DisableEvents;    procedure EnableEvents;    function GetMaxBillsID: Integer;    function GetGatherTotalPrice(ABillsID, AIndex: Integer): Double;    procedure SyncSetOthersGatherZJJL(ANode: TBillsIDTreeNode; ATree: TBillsIDTree);    property ProjectData: TObject read FProjectData;    property StageData: TStageData read GetStageData;    {累计完成 可查数据}    // AIndex表示不同类型,取值如下:    // 0: 0号台账合同 1: 累计合同计量 2: 累计数量变更计量 3: 累计单价变更计量 4: 累计完成计量    // 第一部分    property FirstPart[AIndex: Integer]: Double read GetFirstPart;    // 第二部分    property SecondPart[AIndex: Integer]: Double read GetSecondPart;    // 第三部分    property ThirdPart[AIndex: Integer]: Double read GetThirdPart;    // 预留费用    property ReservedFee[AIndex: Integer]: Double read GetReservedFee;    // 其他费用项目    property OtherFee[AIndex: Integer]: Double read GetOtherFee;    // 建设期贷款利息    property BuildLoadInterest[AIndex: Integer]: Double read GetBuildLoadInterest;    // 回收金额    property RecyclingFee[AIndex: Integer]: Double read GetRecyclingFee;    // 公路工程以外的工程费用    property OtherProjectFee[AIndex: Integer]: Double read GetOtherProjectFee;    // 结算价    property Settlement[AIndex: Integer]: Double read GetStageSettlement;  end;implementationuses  Variants, UtilMethods, Globals, ProjectData, ExcelImport, BillsCommand,  PhaseData, BillsCompileDm, ConditionalDefines, FormulaCalc;{$R *.dfm}{ TBillsData }procedure TBillsData.Close;begin  sddBills.Close;end;constructor TBillsData.Create(AProjectData: TObject);begin  inherited Create(nil);  FProjectData := AProjectData;end;destructor TBillsData.Destroy;begin  inherited;end;procedure TBillsData.Open(AConnection: TADOConnection);begin  sdpBills.Connection := AConnection;  sddBills.Open;  if not Assigned(sddBills.IndexList.FindByName('idxID')) then    sddBills.AddIndex('idxID', 'ID');  if not Assigned(sddBills.IndexList.FindByName('idxSerialNo')) then    sddBills.AddIndex('idxSerialNo', 'SerialNo');      sddBills.FieldByName('OrgQuantity').ValidChars := sddBills.FieldByName('Quantity').ValidChars + ArithmeticCharSet;  sddBills.FieldByName('OrgTotalPrice').ValidChars := sddBills.FieldByName('OrgQuantity').ValidChars;  sddBills.FieldByName('MisQuantity').ValidChars := sddBills.FieldByName('OrgQuantity').ValidChars;  sddBills.FieldByName('MisTotalPrice').ValidChars := sddBills.FieldByName('OrgQuantity').ValidChars;  sddBills.FieldByName('OthQuantity').ValidChars := sddBills.FieldByName('OrgQuantity').ValidChars;  sddBills.FieldByName('OthTotalPrice').ValidChars := sddBills.FieldByName('OrgQuantity').ValidChars;end;procedure TBillsData.Save;  procedure ResolveCode(ARec: TBillsRecord);  var    sgs: TStrings;    i: Integer;    sXiangCode, sMuCode, sJieCode, sXiMuCode: string;  begin    sgs := TStringList.Create;    try      sgs.Delimiter := '-';      sgs.DelimitedText := ARec.Code.AsString;      case sgs.Count of        1: sXiangCode := '';        2: sXiangCode := ChinessNum(StrToIntDef(sgs[1], 0));        3: sMuCode := sgs[2];        4: sJieCode := sgs[3];        else        begin          for i := 4 to sgs.Count - 1 do            if sXiMuCode = '' then              sXiMuCode := sgs[i]            else              sXiMuCode := sXiMuCode + '-' + sgs[i];        end;      end;    finally      ARec.SetStrValue(ARec.XiangCode, sXiangCode);      ARec.SetStrValue(ARec.MuCode, sMuCode);      ARec.SetStrValue(ARec.JieCode, sJieCode);      ARec.SetStrValue(ARec.XimuCode, sXiMuCode);      sgs.Free;    end;  end;  function GetB_CodeChapter(const AB_Code: string): Integer;  var    iValue, iError: Integer;  begin    Result := -1;    Val(AB_Code, iValue, iError);    if iValue > 0 then      Result := iValue div 100;  end;  procedure SaveReportsRela;  var    iIndex: Integer;    stnNode: TBillsIDTreeNode;    iLeafXmjParentID, iChapterParentID: Integer;    sIndexCode: string;  begin    sddBills.BeginUpdate;    try      with TProjectData(FProjectData).BillsCompileData do        for iIndex := 0 to BillsCompileTree.Count - 1 do        begin          stnNode := TBillsIDTreeNode(BillsCompileTree.Items[iIndex]);          // 分项清单排序          if (stnNode.Rec.SerialNo.AsString = '') or              (stnNode.MajorIndex <> stnNode.Rec.SerialNo.AsInteger) then            stnNode.Rec.SerialNo.AsInteger := stnNode.MajorIndex;          // 叶子节点          stnNode.Rec.SetBoolValue(stnNode.Rec.IsLeaf, not stnNode.HasChildren);          // 最底项目节父节点ID          if (stnNode.Rec.B_Code.AsString <> '') then            iLeafXmjParentID := GetLeafXmjParentID(stnNode.ID)          else            iLeafXmjParentID := -1;          stnNode.Rec.SetIntValue(stnNode.Rec.LeafXmjParentID, iLeafXmjParentID);          stnNode.Rec.SetIntValue(stnNode.Rec.ChapterParentID, stnNode.ChapterParentID);          // 分解项目节编号为项、目、节、细目          if stnNode.Rec.Code.AsString <> '' then            ResolveCode(stnNode.Rec);          // 工程量清单排序Code          if (stnNode.Rec.B_Code.AsString <> '') then          begin            sIndexCode := B_CodeToIndexCode(stnNode.Rec.B_Code.AsString);            stnNode.Rec.SetStrValue(stnNode.Rec.IndexCode, sIndexCode);          end;          stnNode.Rec.SetIntValue(stnNode.Rec.NodeLevel, stnNode.Level);          // 工程量清单所属章级          stnNode.Rec.SetIntValue(stnNode.Rec.B_CodeChapter, GetB_CodeChapter(stnNode.Rec.B_Code.AsString));        end;    finally      sddBills.EndUpdate;    end;  end;begin  if TProjectData(FProjectData).BillsCompileData.Active then    SaveReportsRela; // 保存 SerialNo, IsLeaf, LeafXmjParentID, 分解Code  sddBills.Save;end;{procedure TBillsData.Calculate(ABillsID: Integer);var  stnNode: TsdIDTreeNode;  iChild: Integer;begin  stnNode := FBillsTree.FindNode(ABillsID);  if stnNode.HasChildren then  begin    for iChild := 0 to stnNode.ChildCount - 1 do      Calculate(stnNode.ChildNodes[iChild].ID);  end  else  begin    CalculateOrg(ABillsID);    CalculateDeal(ABillsID);    CalculateQuantityChange(ABillsID);    CalculatePriceChange(ABillsID);  end;end;procedure TBillsData.CalculateDeal(ABillsID: Integer);var  iIndex: Integer;  fQuantity, fTotalPrice: Double;  Rec: TsdDataRecord;begin  fQuantity := 0;  fTotalPrice := 0;  with TProjectData(FProjectData) do    for iIndex := 0 to PhaseCount - 1 do    begin      Rec := PhaseData[iIndex].PhaseRecord(ABillsID);      if not Assigned(Rec) then Continue;      fQuantity := fQuantity + Rec.ValueByName('DealQuantity').AsFloat;      fTotalPrice := fTotalPrice + Rec.ValueByName('DealTotalPrice').AsFloat;    end;  with FBillsTree.FindNode(ABillsID).Rec do    UpdateRecordDeal(ABillsID, fQuantity - ValueByName('AddDealQuantity').AsFloat,      fTotalPrice - ValueByName('AddDealTotalPrice').AsFloat);end;procedure TBillsData.CalculatePriceChange(ABillsID: Integer);var  iIndex: Integer;  fQuantity, fTotalPrice: Double;  Rec: TsdDataRecord;begin  fQuantity := 0;  fTotalPrice := 0;  with TProjectData(FProjectData) do    for iIndex := 0 to PhaseCount - 1 do    begin      Rec := PhaseData[iIndex].PhaseRecord(ABillsID);      if not Assigned(Rec) then Continue;      fQuantity := fQuantity + Rec.ValueByName('PcQuantity').AsFloat;      fTotalPrice := fTotalPrice + Rec.ValueByName('PcTotalPrice').AsFloat;    end;  with FBillsTree.FindNode(ABillsID).Rec do    UpdateRecordPc(ABillsID, fQuantity - ValueByName('AddPcQuantity').AsFloat,      fTotalPrice - ValueByName('AddPcTotalPrice').AsFloat);end;procedure TBillsData.CalculateQuantityChange(ABillsID: Integer);var  iIndex: Integer;  fQuantity, fTotalPrice: Double;  Rec: TsdDataRecord;begin  fQuantity := 0;  fTotalPrice := 0;  with TProjectData(FProjectData) do    for iIndex := 0 to PhaseCount - 1 do    begin      Rec := PhaseData[iIndex].PhaseRecord(ABillsID);      if not Assigned(Rec) then Continue;      fQuantity := fQuantity + Rec.ValueByName('QcQuantity').AsFloat;      fTotalPrice := fTotalPrice + Rec.ValueByName('QcTotalPrice').AsFloat;    end;  with FBillsTree.FindNode(ABillsID).Rec do    UpdateRecordQc(ABillsID, fQuantity - ValueByName('AddQcQuantity').AsFloat,      fTotalPrice - ValueByName('AddQcTotalPrice').AsFloat);end; }{procedure TBillsData.RecursiveCalculate(ABillsID: Integer);  procedure GatherChildValue(ANode: TsdIDTreeNode);  var    CacheRecord: TCacheRecord;    iChild: Integer;  begin    CacheRecord := TCacheRecord.Create;    try      for iChild := 0 to ANode.ChildCount - 1 do        with ANode.ChildNodes[iChild].Rec do        begin          CacheRecord.FTotalPrice := CacheRecord.FTotalPrice + ValueByName('TotalPrice').AsFloat;          CacheRecord.FDealQuantity := CacheRecord.FDealQuantity + ValueByName('AddDealQuantity').AsFloat;          CacheRecord.FDealTotalPrice := CacheRecord.FDealTotalPrice + ValueByName('AddDealTotalPrice').AsFloat;          CacheRecord.FQcQuantity := CacheRecord.FQcQuantity + ValueByName('AddQcQuantity').AsFloat;          CacheRecord.FQcTotalPrice := CacheRecord.FQcTotalPrice + ValueByName('AddQcTotalPrice').AsFloat;          CacheRecord.FPcQuantity := CacheRecord.FPcQuantity + ValueByName('AddPcQuantity').AsFloat;          CacheRecord.FPcTotalPrice := CacheRecord.FPcTotalPrice + ValueByName('AddPcTotalPrice').AsFloat;        end;    finally      CacheRecord.SetBillsRecord(ANode);      CacheRecord.Free;    end;  end;  procedure CalculateLeafNode(ANode: TsdIDTreeNode; ACacheRecord: TCacheRecord);  begin    with ANode.Rec do    begin      if ValueByName('QtyFlag').AsInteger = 1 then        ValueByName('Quantity').AsFloat := EvaluateExprs(ValueByName('QtyFormula').AsString);      if ValueByName('QtyFlag').AsInteger < 2 then        ACacheRecord.FTotalPrice := ValueByName('Quantity').AsFloat * ValueByName('Price').AsFloat      else      begin        FFormulaCalc.SetRecordText(ValueByName('QtyFormula').AsString);        ACacheRecord.FTotalPrice := FFormulaCalc.Value;      end;    end;  end;  procedure GatherPhaseValue(ANode: TsdIDTreeNode);  var    CacheRecord: TCacheRecord;    iIndex: Integer;    Rec: TsdDataRecord;  begin    CacheRecord := TCacheRecord.Create;    try      CalculateLeafNode(ANode, CacheRecord);      {with TProjectData(FProjectData) do        for iIndex := 0 to PhaseCount - 1 do        begin          PhaseData[iIndex].ReCalculate(ANode.ID);          Rec := PhaseData[iIndex].PhaseRecord(ANode.ID);          if not Assigned(Rec) then Continue;          CacheRecord.FDealQuantity := CacheRecord.FDealQuantity + Rec.ValueByName('DealQuantity').AsFloat;          CacheRecord.FDealTotalPrice := CacheRecord.FDealTotalPrice + Rec.ValueByName('DealTotalPrice').AsFloat;          CacheRecord.FQcQuantity := CacheRecord.FQcQuantity + Rec.ValueByName('QcQuantity').AsFloat;          CacheRecord.FQcTotalPrice := CacheRecord.FQcTotalPrice + Rec.ValueByName('QcTotalPrice').AsFloat;          CacheRecord.FPcQuantity := CacheRecord.FPcQuantity + Rec.ValueByName('PcQuantity').AsFloat;          CacheRecord.FPcTotalPrice := CacheRecord.FPcTotalPrice + Rec.ValueByName('PcTotalPrice').AsFloat;        end;}{    finally      CacheRecord.SetBillsRecord(ANode);      CacheRecord.Free;    end;  end;  procedure CalculateCurNode(ANode: TsdIDTreeNode);  begin    if ANode.HasChildren then      GatherChildValue(ANode)    else      GatherPhaseValue(ANode);  end;  procedure CalculateAllChildren(ANode: TsdIDTreeNode);  var    iChild: Integer;  begin    if ANode.HasChildren then      for iChild := 0 to ANode.ChildCount - 1 do        RecursiveCalculate(ANode.ChildNodes[iChild].ID);  end;var  stnNode: TsdIDTreeNode;begin  stnNode := FBillsTree.FindNode(ABillsID);  CalculateAllChildren(stnNode);  CalculateCurNode(stnNode);end;  }procedure TBillsData.InitBills;var  Import: TBillsExcelImport;begin  Import := TBillsExcelImport.Create(TProjectData(ProjectData));  try    Import.ImportFile(GetTemplateBillsFileName);  finally    Import.Free;  end;end;function TBillsData.GetStageData: TStageData;begin  Result := TProjectData(FProjectData).PhaseData.StageData;end;procedure TBillsData.LockedBaseData;var  iIndex: Integer;  Rec: TBillsRecord;begin  sddBills.BeginUpdate;  for iIndex := 0 to sddBills.RecordCount - 1 do  begin    Rec := TBillsRecord(sddBills.Records[iIndex]);    Rec.SetBoolValue(Rec.LockedLevel, True);    Rec.SetBoolValue(Rec.LockedInfo, True);    Rec.SetBoolValue(Rec.LockedNewPrice, Rec.NewPrice.AsFloat <> 0);  end;  sddBills.EndUpdate;end;procedure TBillsData.sddBillsAfterAddRecord(ARecord: TsdDataRecord);begin  ARecord.ValueByName('CreatePhaseID').AsInteger := TProjectData(FProjectData).PhaseIndex;end;function TBillsData.GetBuildLoadInterest(AIndex: Integer): Double;begin  Result := GetGatherTotalPrice(34, AIndex);end;function TBillsData.GetFirstPart(AIndex: Integer): Double;begin  Result := GetGatherTotalPrice(1, AIndex);end;function TBillsData.GetOtherFee(AIndex: Integer): Double;begin  Result := GetGatherTotalPrice(15, AIndex);end;function TBillsData.GetOtherProjectFee(AIndex: Integer): Double;begin  Result := GetGatherTotalPrice(9, AIndex);end;function TBillsData.GetRecyclingFee(AIndex: Integer): Double;begin  Result := GetGatherTotalPrice(16, AIndex);end;function TBillsData.GetReservedFee(AIndex: Integer): Double;begin  Result := GetGatherTotalPrice(7, AIndex);end;function TBillsData.GetSecondPart(AIndex: Integer): Double;begin  Result := GetGatherTotalPrice(2, AIndex);end;function TBillsData.GetStageSettlement(AIndex: Integer): Double;begin  // 全国  // 第一部分+第二部分+第三部分+预备费+新增加费用项目(其他费用_广东)-回收金额  Result := FirstPart[AIndex] + SecondPart[AIndex] + ThirdPart[AIndex]         + ReservedFee[AIndex] + OtherFee[AIndex] - RecyclingFee[AIndex];  // 广东  // 全国的基础上+建设期贷款利息+公路功能以外的项目  if _IsGuangDong then    Result := Result + BuildLoadInterest[AIndex] + OtherProjectFee[AIndex];end;function TBillsData.GetThirdPart(AIndex: Integer): Double;begin  Result := GetGatherTotalPrice(3, AIndex);end;function TBillsData.GetGatherTotalPrice(ABillsID, AIndex: Integer): Double;var  Rec: TsdDataRecord;begin  Result := 0;  Rec := sddBills.FindKey('idxID', ABillsID);  if Assigned(Rec) then  begin    case AIndex of      0: Result := Rec.ValueByName('TotalPrice').AsFloat;      1: Result := Rec.ValueByName('AddDealTotalPrice').AsFloat;      2: Result := Rec.ValueByName('AddQcTotalPrice').AsFloat;      3: Result := Rec.ValueByName('AddPcTotalPrice').AsFloat;      4: Result := Rec.ValueByName('AddGatherTotalPrice').AsFloat;    end;  end;end;procedure TBillsData.DisableEvents;begin  sddBills.BeforeValueChange := nil;end;procedure TBillsData.EnableEvents;begin  sddBills.BeforeValueChange := sddBillsBeforeValueChange;end;procedure TBillsData.UnLockedBaseData;var  iIndex: Integer;begin  for iIndex := 0 to sddBills.RecordCount - 1 do    sddBills.Records[iIndex].ValueByName('LockedInfo').AsBoolean := False;end;procedure TBillsData.sddBillsBeforeDeleteRecord(ARecord: TsdDataRecord;  var Allow: Boolean);begin  with TProjectData(FProjectData) do  begin    if ProjProperties.PhaseCount > 0 then      PhaseData.StageData.DeletePhaseRecord(ARecord.ValueByName('ID').AsInteger);  end;end;procedure TBillsData.sddBillsBeforeValueChange(AValue: TsdValue;  const NewValue: Variant; var Allow: Boolean);begin  if (Pos('DgnQuantity', AValue.FieldName) > 0) and     not (VarIsNull(NewValue) or (NewValue = 0)) then  begin    if AValue.Owner.ValueByName('B_Code').AsString <> '' then    begin      ErrorMessage('仅项目节可以输入设计数量!');      Allow := False;    end;  end;end;function TBillsData.GetMaxBillsID: Integer;var  Rec: TsdDataRecord;  i: Integer;begin  Result := 100;  for i := 0 to sddBills.RecordCount - 1 do  begin    Rec := sddBills.Records[i];    if Rec.ValueByName('ID').AsInteger > Result then      Result := Rec.ValueByName('ID').AsInteger;  end;end;procedure TBillsData.sddBillsGetRecordClass(  var ARecordClass: TsdRecordClass);begin  ARecordClass := TBillsRecord;end;procedure TBillsData.SyncSetOthersGatherZJJL(ANode: TBillsIDTreeNode;  ATree: TBillsIDTree);  procedure SetSibling;  var    vSibling: TBillsIDTreeNode;  begin    if Assigned(ANode.Parent) then      vSibling := TBillsIDTreeNode(ANode.Parent.FirstChild)    else      vSibling := TBillsIDTreeNode(ATree.FirstNode);    while Assigned(vSibling) do    begin      vSibling.Rec.IsGatherZJJL.AsBoolean := ANode.Rec.IsGatherZJJL.AsBoolean;      vSibling := TBillsIDTreeNode(vSibling.NextSibling);    end;  end;  procedure SetSameLevelXmj;  var    vParent, vChild: TBillsIDTreeNode;    iCount, iPosterity: Integer;  begin    if ANode.Level < 1 then Exit;    vParent := TBillsIDTreeNode(ANode.Parent);    while (vParent.Level > 1) do      vParent :=  TBillsIDTreeNode(vParent.Parent);    iCount := 0;    iPosterity := vParent.PosterityCount;    vChild := TBillsIDTreeNode(vParent.NextNode);    while (iCount < iPosterity) do    begin      if (vChild.Level = ANode.Level) and (vChild.Rec.B_Code.AsString = '') then        vChild.Rec.IsGatherZJJL.AsBoolean := ANode.Rec.IsGatherZJJL.AsBoolean;      vChild := TBillsIDTreeNode(vChild.NextNode);      Inc(iCount);    end;  end;begin  case SupportManager.ConfigInfo.GatherZJJLSelect of    1: SetSameLevelXmj;    2: SetSibling;  end;end;end.
 |