BillsMeasureDm.pas 36 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088
  1. unit BillsMeasureDm;
  2. interface
  3. uses
  4. BillsDm, BillsTree, FormulaCalc, sdIDTree, StageDm,
  5. SysUtils, Classes, sdDB, DB;
  6. type
  7. TLocateZJJLEvent = procedure (ABillsID: Integer) of object;
  8. TBillsMeasureData = class(TDataModule)
  9. sdvBillsMeasure: TsdDataView;
  10. procedure sdvBillsMeasureAfterOpen(Sender: TObject);
  11. procedure sdvBillsMeasureAfterAddRecord(ARecord: TsdDataRecord);
  12. procedure sdvBillsMeasureGetText(var Text: String;
  13. ARecord: TsdDataRecord; AValue: TsdValue; AColumn: TsdViewColumn;
  14. DisplayText: Boolean);
  15. procedure sdvBillsMeasureSetText(var Text: String;
  16. ARecord: TsdDataRecord; AValue: TsdValue; AColumn: TsdViewColumn;
  17. var Allow: Boolean);
  18. procedure sdvBillsMeasureNeedLookupRecord(ARecord: TsdDataRecord;
  19. AColumn: TsdViewColumn; ANewText: String);
  20. procedure sdvBillsMeasureAfterClose(Sender: TObject);
  21. procedure sdvBillsMeasureAfterValueChanged(AValue: TsdValue);
  22. procedure sdvBillsMeasureCurrentChanged(ARecord: TsdDataRecord);
  23. private
  24. FProjectData: TObject;
  25. FBillsData: TBillsData;
  26. FBillsMeasureTree: TMeasureBillsIDTree;
  27. FFormulaCalc: TFormulaCalc;
  28. FShowParentData: Boolean;
  29. FOnRecChange: TRecChangeEvent;
  30. function OnGetCardinalNum(const ACardinalNum: string): Double;
  31. procedure CalcAddCompleteRate(ANode: TsdIDTreeNode);
  32. procedure CalcAddDgnPrice(ANode: TsdIDTreeNode);
  33. function SelectAndUpdateBGL(ABillsID: Integer; ARec: TsdDataRecord;
  34. ANewValue: Double; const AType: string): Boolean;
  35. procedure CalculateNode(ANode: TMeasureBillsIDTreeNode);
  36. procedure UpdateRecordGather(ANode: TsdIDTreeNode; AQuantity, ATotalPrice: Double);
  37. function GetStageData: TStageData;
  38. procedure SetOnRecChange(const Value: TRecChangeEvent);
  39. public
  40. constructor Create(AProjectData: TObject);
  41. destructor Destroy; override;
  42. procedure Open;
  43. procedure Close;
  44. procedure ReConnectTree;
  45. procedure CalculateAll;
  46. procedure ResetPhaseStageLink;
  47. procedure ResetTreeNodeStageRec;
  48. procedure FreeTreeNodeStageRec;
  49. procedure ExpandNodeTo(ALevel: Integer);
  50. procedure ExpandXmjNode;
  51. procedure ExpandCurPhase;
  52. function GatherRelaBGL(ANode: TsdIDTreeNode): string;
  53. function FindNodeWithZJJL(ANode: TsdIDTreeNode): TsdIDTreeNode;
  54. // 计算 修改各期原报审核数据时,需对累计数据做增量
  55. procedure UpdateRecordDeal(ABillsID: Integer; AQuantity, ATotalPrice: Double);
  56. procedure UpdateRecordQc(ABillsID: Integer; AQuantity, ATotalPrice: Double);
  57. procedure UpdateRecordPc(ABillsID: Integer; AQuantity, ATotalPrice: Double);
  58. procedure UpdateRecordPM(ABillsID: Integer; ADiffer: Double);
  59. procedure UpdateGather(ABillsID: Integer; ADiffer: Double);
  60. procedure UpdateBGLInfo(ABillsID: Integer; ARec: TsdDataRecord; const AType: string);
  61. property ProjectData: TObject read FProjectData;
  62. property BillsData: TBillsData read FBillsData;
  63. property BillsMeasureTree: TMeasureBillsIDTree read FBillsMeasureTree;
  64. property StageData: TStageData read GetStageData;
  65. property ShowParentData: Boolean read FShowParentData write FShowParentData;
  66. property OnRecChange: TRecChangeEvent read FOnRecChange write SetOnRecChange;
  67. end;
  68. implementation
  69. uses
  70. ProjectData, PhaseData, Math, ZhAPI, BillsCommand, BGLSelectFrm,
  71. BGLDm, UtilMethods, mDataRecord, ConstUnit, Variants;
  72. {$R *.dfm}
  73. { TBillsMeasureData }
  74. constructor TBillsMeasureData.Create(AProjectData: TObject);
  75. begin
  76. inherited Create(nil);
  77. FProjectData := AProjectData;
  78. FBillsData := TProjectData(FProjectData).BillsData;
  79. FBillsMeasureTree := TMeasureBillsIDTree.Create;
  80. FBillsMeasureTree.KeyFieldName := 'ID';
  81. FBillsMeasureTree.ParentFieldName := 'ParentID';
  82. FBillsMeasureTree.NextSiblingFieldName := 'NextSiblingID';
  83. FBillsMeasureTree.AutoCreateKeyID := True;
  84. FBillsMeasureTree.AutoExpand := True;
  85. FBillsMeasureTree.DataView := sdvBillsMeasure;
  86. FBillsMeasureTree.SeedID := Max(FBillsMeasureTree.SeedID, 100);
  87. FBillsMeasureTree.Link(TProjectData(FProjectData).BillsCompileData.BillsCompileTree, True);
  88. FBillsMeasureTree.CompileTree := TProjectData(FProjectData).BillsCompileData.BillsCompileTree;
  89. FFormulaCalc := TFormulaCalc.Create(FBillsMeasureTree);
  90. FFormulaCalc.OnGetValue := OnGetCardinalNum;
  91. end;
  92. destructor TBillsMeasureData.Destroy;
  93. begin
  94. FFormulaCalc.Free;
  95. FBillsMeasureTree.Free;
  96. inherited;
  97. end;
  98. procedure TBillsMeasureData.Open;
  99. begin
  100. sdvBillsMeasure.DataSet := TProjectData(FProjectData).BillsData.sddBills;
  101. sdvBillsMeasure.Open;
  102. end;
  103. procedure TBillsMeasureData.ReConnectTree;
  104. begin
  105. FBillsMeasureTree.DataView := nil;
  106. FBillsMeasureTree.DataView := sdvBillsMeasure;
  107. FBillsMeasureTree.Link(TProjectData(FProjectData).BillsCompileData.BillsCompileTree, True);
  108. end;
  109. procedure TBillsMeasureData.ResetPhaseStageLink;
  110. begin
  111. with TProjectData(FProjectData).PhaseData do
  112. begin
  113. sdvBillsMeasure.Columns.FindColumn('CurDealQuantity').LookupDataSet := StageData.sddStage;
  114. sdvBillsMeasure.Columns.FindColumn('CurDealTotalPrice').LookupDataSet := StageData.sddStage;
  115. sdvBillsMeasure.Columns.FindColumn('CurQcQuantity').LookupDataSet := StageData.sddStage;
  116. sdvBillsMeasure.Columns.FindColumn('CurQcTotalPrice').LookupDataSet := StageData.sddStage;
  117. sdvBillsMeasure.Columns.FindColumn('CurQcBGLCode').LookupDataSet := StageData.sddStage;
  118. sdvBillsMeasure.Columns.FindColumn('CurPcQuantity').LookupDataSet := StageData.sddStage;
  119. sdvBillsMeasure.Columns.FindColumn('CurPcTotalPrice').LookupDataSet := StageData.sddStage;
  120. sdvBillsMeasure.Columns.FindColumn('CurPcBGLCode').LookupDataSet := StageData.sddStage;
  121. sdvBillsMeasure.Columns.FindColumn('CurGatherQuantity').LookupDataSet := StageData.sddStage;
  122. sdvBillsMeasure.Columns.FindColumn('CurGatherTotalPrice').LookupDataSet := StageData.sddStage;
  123. sdvBillsMeasure.Columns.FindColumn('EndDealQuantity').LookupDataSet := StageData.sddStage;
  124. sdvBillsMeasure.Columns.FindColumn('EndDealTotalPrice').LookupDataSet := StageData.sddStage;
  125. sdvBillsMeasure.Columns.FindColumn('EndQcQuantity').LookupDataSet := StageData.sddStage;
  126. sdvBillsMeasure.Columns.FindColumn('EndQcTotalPrice').LookupDataSet := StageData.sddStage;
  127. sdvBillsMeasure.Columns.FindColumn('EndPcQuantity').LookupDataSet := StageData.sddStage;
  128. sdvBillsMeasure.Columns.FindColumn('EndPcTotalPrice').LookupDataSet := StageData.sddStage;
  129. sdvBillsMeasure.Columns.FindColumn('EndGatherQuantity').LookupDataSet := StageData.sddStage;
  130. sdvBillsMeasure.Columns.FindColumn('EndGatherTotalPrice').LookupDataSet := StageData.sddStage;
  131. sdvBillsMeasure.Columns.FindColumn('PM_PreTotalPrice').LookupDataSet := StageData.sddStage;
  132. sdvBillsMeasure.Columns.FindColumn('PM_TotalPrice').LookupDataSet := StageData.sddStage;
  133. end;
  134. end;
  135. procedure TBillsMeasureData.sdvBillsMeasureAfterOpen(Sender: TObject);
  136. begin
  137. FBillsMeasureTree.Active := True;
  138. end;
  139. procedure TBillsMeasureData.sdvBillsMeasureAfterAddRecord(
  140. ARecord: TsdDataRecord);
  141. begin
  142. if TProjectData(FProjectData).PhaseData.Active then
  143. ARecord.ValueByName('IsMeasureAdd').AsBoolean := True;
  144. end;
  145. procedure TBillsMeasureData.sdvBillsMeasureGetText(var Text: String;
  146. ARecord: TsdDataRecord; AValue: TsdValue; AColumn: TsdViewColumn;
  147. DisplayText: Boolean);
  148. function GetQuantityValueOrFormula(const AQtyType: string): string;
  149. begin
  150. with AValue.Owner do
  151. begin
  152. if ValueByName(AQtyType + 'Flag').AsInteger = 1 then
  153. Result := ValueByName(AQtyType + 'Formula').AsString
  154. else
  155. Result := Text;
  156. end;
  157. end;
  158. function GetTotalPriceValueOrFormula(const AQtyType: string): string;
  159. begin
  160. with AValue.Owner do
  161. begin
  162. if ValueByName(AQtyType + 'Formula').AsString <> '' then
  163. Result := ValueByName(AQtyType + 'Formula').AsString
  164. else
  165. Result := Text;
  166. end;
  167. end;
  168. procedure GetDisplayText(var AText: string; AValue: TsdValue;
  169. AColumn: TsdViewColumn);
  170. var
  171. stnNode: TsdIDTreeNode;
  172. begin
  173. if Assigned(AValue) and (AValue.DataType = ftFloat) and (AValue.AsFloat = 0) then
  174. begin
  175. Text := '';
  176. Exit;
  177. end;
  178. // 所有本期数据,当节点为父节点时,不显示值(实际上需要计算其中的金额值,但又不能显示)
  179. // 有病。每天都在变。
  180. if not ShowParentData and (Pos('Cur', AColumn.FieldName) > 0) and (Pos('Gather', AColumn.FieldName) = 0) then
  181. begin
  182. stnNode := BillsMeasureTree.FindNode(AValue.Owner.ValueByName('BillsID').AsInteger);
  183. if stnNode.HasChildren then
  184. Text := '';
  185. end;
  186. end;
  187. procedure GetEditText(var AText: string; AValue: TsdValue;
  188. AColumn: TsdViewColumn);
  189. begin
  190. if SameText(AColumn.FieldName, 'Quantity') then
  191. Text := GetQuantityValueOrFormula('Qty')
  192. else if SameText(AColumn.FieldName, 'CurDealQuantity') then
  193. Text := GetQuantityValueOrFormula('Deal')
  194. else if SameText(AColumn.FieldName, 'CurQcQuantity') then
  195. Text := GetQuantityValueOrFormula('Qc')
  196. else if SameText(AColumn.FieldName, 'CurPcQuantity') then
  197. Text := GetQuantityValueOrFormula('Pc')
  198. else if SameText(AColumn.FieldName, 'CurDealTotalPrice') then
  199. Text := GetTotalPriceValueOrFormula('Deal')
  200. else if SameText(AColumn.FieldName, 'CurQcTotalPrice') then
  201. Text := GetTotalPriceValueOrFormula('Qc')
  202. else if SameText(AColumn.FieldName, 'CurPcTotalPrice') then
  203. Text := GetTotalPriceValueOrFormula('Pc');
  204. end;
  205. var
  206. fPercent: Double;
  207. begin
  208. if not Assigned(AValue) then Exit;
  209. if DisplayText then
  210. GetDisplayText(Text, AValue, AColumn)
  211. else
  212. GetEditText(Text, AValue, AColumn);
  213. end;
  214. procedure TBillsMeasureData.sdvBillsMeasureSetText(var Text: String;
  215. ARecord: TsdDataRecord; AValue: TsdValue; AColumn: TsdViewColumn;
  216. var Allow: Boolean);
  217. function GetBillsID: Integer;
  218. begin
  219. if Pos('Cur', AColumn.FieldName) = 1 then
  220. Result := AValue.Owner.ValueByName('BillsID').AsInteger
  221. else
  222. Result := ARecord.ValueByName('ID').AsInteger;
  223. end;
  224. procedure CheckLockedData;
  225. begin
  226. if SameText(AColumn.FieldName, 'Code') or
  227. SameText(AColumn.FieldName, 'B_Code') or
  228. SameText(AColumn.FieldName, 'Name') or
  229. SameText(AColumn.FieldName, 'Units') or
  230. SameText(AColumn.FieldName, 'Price') then
  231. if ARecord.ValueByName('LockedInfo').AsBoolean then
  232. DataSetErrorMessage(Allow, '清单信息已被锁定,不允许修改编号、名称、单位、清单单价!');
  233. if not Allow then Exit;
  234. if SameText(AColumn.FieldName, 'NewPrice') then
  235. if ARecord.ValueByName('LockedNewPrice').AsBoolean then
  236. DataSetErrorMessage(Allow, '变更单价已被锁定,不允许修改!');
  237. end;
  238. procedure CheckNodeWritable(ANode: TBillsIDTreeNode);
  239. var
  240. iCreatePhase: Integer;
  241. begin
  242. iCreatePhase := ANode.Rec.ValueByName('CreatePhaseID').AsInteger;
  243. {if ANode.ID = iPriceMarginID then
  244. DataSetErrorMessage(Allow, sBills_PMHint);}
  245. if SameText('B_Code', AColumn.FieldName) or
  246. SameText('Name', AColumn.FieldName) or
  247. SameText('Units', AColumn.FieldName) then
  248. if ANode.Rec.ValueByName('AddQcQuantity').AsFloat <> 0 then
  249. DataSetErrorMessage(Allow, '该清单已进行过变更,不可修改清单编号、名称、单位!');
  250. if not Allow then Exit;
  251. if SameText('Price', AColumn.FieldName) then
  252. if ANode.Rec.ValueByName('AddGatherTotalPrice').AsFloat <> 0 then
  253. DataSetErrorMessage(Allow, '该清单已经计量,不可修改清单单价!');
  254. if not Allow then Exit;
  255. if SameText('NewPrice', AColumn.FieldName) then
  256. if ANode.Rec.ValueByName('AddPcTotalPrice').AsFloat <> 0 then
  257. DataSetErrorMessage(Allow, '该清单已经计量,不可修改清单变更单价!');
  258. if not Allow then Exit;
  259. if ANode.HasChildren then
  260. begin
  261. if Text = '' then
  262. Exit
  263. else if ((Pos('Quantity', AColumn.FieldName) > 0) and (Pos('Dgn', AColumn.FieldName) <=0)) or
  264. (Pos('TotalPrice', AColumn.FieldName) > 0) then
  265. DataSetErrorMessage(Allow, '该清单有子计算项,不能直接修改!')
  266. else if (Pos('Price', AColumn.FieldName) > 0) then
  267. DataSetErrorMessage(Allow, '仅最底层清单可输入单价!');
  268. end
  269. else
  270. begin
  271. // 目前仅允许本期合同计量,可直接输入金额
  272. if SameText('CurDealTotalPrice', AColumn.FieldName) then
  273. begin
  274. if not ANode.TotalPriceEnable then
  275. DataSetErrorMessage(Allow, '该清单不可直接输入金额,如需直接输入金额,请先清空所有数量、单价!');
  276. end
  277. else if SameText('CurDealQuantity', AColumn.FieldName) or
  278. SameText('CurQcQuantity', AColumn.FieldName) or
  279. SameText('CurPcQuantity', AColumn.FieldName) or
  280. SameText('Price', AColumn.FieldName) then
  281. begin
  282. if not ANode.CountPriceEnable then
  283. DataSetErrorMessage(Allow, '该清单不可输入数量单价,如需使用数量×单价计算,请先清空所有直接输入的金额!');
  284. end;
  285. end;
  286. if not Allow then Exit;
  287. // 变更清单允许填写本期合同计量,按超计论
  288. {if vNode.Rec.ValueByName('IsMeasureAdd').AsBoolean and (iCreatePhase > 0) and
  289. (SameText('CurDealQuantity', AColumn.FieldName) or
  290. SameText('CurDealTotalPrice', AColumn.FieldName)) then
  291. DataSetErrorMessage(Allow, Format('该清单为第%d期新增清单,不可填写本期合同计量数据!', [iCreatePhase]));}
  292. end;
  293. procedure SetQuantity(ANode: TBillsIDTreeNode; const AField: string);
  294. var
  295. vNode: TBillsIDTreeNode;
  296. begin
  297. // 变更应选择变更令
  298. if SameText(AField , 'Qc') or SameText(AField , 'Pc') then
  299. Allow := SelectAndUpdateBGL(GetBillsID, AValue.Owner, StrToFloatDef(Text, 0), AField);
  300. if not Allow then Exit;
  301. if CheckStringNull(Text) or CheckNumeric(Text) then
  302. begin
  303. AValue.Owner.ValueByName(AField + 'Flag').AsInteger := 0;
  304. AValue.Owner.ValueByName(AField + 'Formula').AsString := '';
  305. Text := FloatToStr(QuantityRoundTo(StrToFloatDef(Text, 0)));
  306. end
  307. else
  308. begin
  309. AValue.Owner.ValueByName(AField + 'Flag').AsInteger := 1;
  310. AValue.Owner.ValueByName(AField + 'Formula').AsString := Text;
  311. Text := FloatToStr(QuantityRoundTo(EvaluateExprs(Text)));
  312. end;
  313. ANode.Rec.SetIntValue(ANode.Rec.CalcType, 0);
  314. end;
  315. procedure SetTotalPrice(ANode: TBillsIDTreeNode; const AField: string);
  316. begin
  317. // 变更应选择变更令
  318. if SameText(AField , 'Qc') or SameText(AField , 'Pc') then
  319. Allow := SelectAndUpdateBGL(GetBillsID, AValue.Owner, StrToFloatDef(Text, 0), AField);
  320. if not Allow then Exit;
  321. AValue.Owner.ValueByName(AField + 'Flag').AsInteger := 2;
  322. AValue.Owner.ValueByName(AField + 'Quantity').AsString := '';
  323. if CheckStringNull(Text) or CheckNumeric(Text) then
  324. begin
  325. AValue.Owner.ValueByName(AField + 'Formula').AsString := '';
  326. Text := FloatToStr(TotalPriceRoundTo(StrToFloatDef(Text, 0)));
  327. end
  328. else
  329. begin
  330. AValue.Owner.ValueByName(AField + 'Formula').AsString := Text;
  331. Text := FloatToStr(TotalPriceRoundTo(EvaluateExprs(Text)));
  332. end;
  333. ANode.Rec.SetIntValue(ANode.Rec.CalcType, 1);
  334. end;
  335. procedure DoCurChanged(ANode: TBillsIDTreeNode);
  336. begin
  337. if SameText(AColumn.FieldName, 'CurDealQuantity') then
  338. SetQuantity(ANode, 'Deal')
  339. else if SameText(AColumn.FieldName, 'CurQcQuantity') then
  340. SetQuantity(ANode, 'Qc')
  341. else if SameText(AColumn.FieldName, 'CurPcQuantity') then
  342. SetQuantity(ANode, 'Pc')
  343. else if SameText(AColumn.FieldName, 'CurDealTotalPrice') then
  344. SetTotalPrice(ANode, 'Deal')
  345. else if SameText(AColumn.FieldName, 'CurQcTotalPrice') then
  346. SetTotalPrice(ANode, 'Qc')
  347. else if SameText(AColumn.FieldName, 'CurPcTotalPrice') then
  348. SetTotalPrice(ANode, 'Pc')
  349. else if (Pos('DgnQuantity', AColumn.FieldName) > 0) or
  350. SameText(AColumn.FieldName, 'Quantity') then
  351. Text := FloatToStr(QuantityRoundTo(StrToFloatDef(Text, 0)))
  352. else if SameText(AColumn.FieldName, 'NewPrice') or
  353. SameText(AColumn.FieldName, 'Price') then
  354. Text := FloatToStr(PriceRoundTo(StrToFloatDef(Text, 0)))
  355. else if SameText(AColumn.FieldName, 'Code') then
  356. BillsMeasureTree.RecodeChildrenCode(ANode, AValue.AsString, Text)
  357. else if SameText(AColumn.FieldName, 'B_Code') then
  358. BillsMeasureTree.RecodeChildrenB_Code(ANode, AValue.AsString, Text);
  359. end;
  360. function CheckValidData: Boolean;
  361. begin
  362. Result := (AValue.AsString <> Text);
  363. if (Pos('Quantity', AColumn.FieldName) > 0) or
  364. (Pos('Price', AColumn.FieldName) > 0) then
  365. begin
  366. if (AValue.AsFloat = 0) and (Text = '') then
  367. Result := False;
  368. end;
  369. end;
  370. var
  371. vNode: TBillsIDTreeNode;
  372. begin
  373. if not Assigned(AValue) then Exit;
  374. // 修改后数据与原数据相同则不提交
  375. if not CheckValidData then
  376. Allow := False;
  377. if not Allow then Exit;
  378. vNode := TBillsIDTreeNode(BillsMeasureTree.FindNode(GetBillsID));
  379. CheckLockedData;
  380. if not Allow then Exit;
  381. CheckNodeWritable(vNode);
  382. if not Allow then Exit;
  383. Text := Trim(Text);
  384. if Pos('=', Text) = 1 then
  385. Text := Copy(Text, 2, Length(Text) - 1);
  386. DoCurChanged(vNode);
  387. end;
  388. procedure TBillsMeasureData.sdvBillsMeasureNeedLookupRecord(
  389. ARecord: TsdDataRecord; AColumn: TsdViewColumn; ANewText: String);
  390. function CheckNeedAddPhaseRecord(ANode: TMeasureBillsIDTreeNode): Boolean;
  391. begin
  392. Result := SameText(AColumn.FieldName, 'CurDealQuantity') or
  393. SameText(AColumn.FieldName, 'CurQcQuantity') or
  394. SameText(AColumn.FieldName, 'CurPcQuantity') or
  395. SameText(AColumn.FieldName, 'CurDealTotalPrice') or
  396. SameText(AColumn.FieldName, 'CurQcTotalPrice') or
  397. SameText(AColumn.FieldName, 'CurPcTotalPrice');
  398. Result := Result and not ANode.HasChildren;
  399. Result := Result and not Assigned(ANode.StageRec);
  400. end;
  401. function HasCardinalNum(AFormula: string): Boolean;
  402. var
  403. iCharIndex: Integer;
  404. begin
  405. Result := False;
  406. iCharIndex := 1;
  407. while ((iCharIndex <= Length(AFormula)) and not Result) do
  408. begin
  409. if AFormula[iCharIndex] in ['A'..'D', 'a'..'d'] then
  410. Result := True;
  411. Inc(iCharIndex);
  412. end;
  413. end;
  414. procedure SetQuantityRec(ANode: TBillsIDTreeNode; APhaseRec: TsdDataRecord; const AType: string);
  415. var
  416. bAllow: Boolean;
  417. begin
  418. bAllow := True;
  419. // 变更应选择变更令
  420. if SameText(AType , 'Qc') or SameText(AType , 'Pc') then
  421. bAllow := SelectAndUpdateBGL(ARecord.ValueByName('ID').AsInteger,
  422. APhaseRec, StrToFloatDef(ANewText, 0), AType);
  423. if bAllow then
  424. begin
  425. if ANode.Rec.CalcType.AsInteger <> 0 then
  426. ANode.Rec.CalcType.AsInteger := 0;
  427. if CheckNumeric(ANewText) then
  428. APhaseRec.ValueByName(AType + 'Quantity').AsFloat := QuantityRoundTo(StrToFloatDef(ANewText, 0))
  429. else
  430. begin
  431. APhaseRec.ValueByName(AType + 'Flag').AsInteger := 1;
  432. APhaseRec.ValueByName(AType + 'Quantity').AsFloat := QuantityRoundTo(EvaluateExprs(ANewText));
  433. APhaseRec.ValueByName(AType + 'Formula').AsString := ANewText;
  434. end;
  435. end;
  436. end;
  437. procedure SetTotalPriceRec(ANode: TBillsIDTreeNode; APhaseRec: TsdDataRecord; const AType: string);
  438. begin
  439. if ANode.Rec.CalcType.AsInteger <> 1 then
  440. ANode.Rec.CalcType.AsInteger := 1;
  441. APhaseRec.ValueByName(AType + 'Flag').AsInteger := 2;
  442. if CheckNumeric(ANewText) then
  443. APhaseRec.ValueByName(AType + 'TotalPrice').AsFloat := TotalPriceRoundTo(StrToFloatDef(ANewText, 0))
  444. else
  445. begin
  446. APhaseRec.ValueByName(AType + 'TotalPrice').AsFloat := TotalPriceRoundTo(EvaluateExprs(ANewText));
  447. APhaseRec.ValueByName(AType + 'Formula').AsString := ANewText;
  448. end;
  449. end;
  450. procedure SetNewRecValue(ANode: TBillsIDTreeNode; APhaseRec: TsdDataRecord);
  451. begin
  452. if SameText(AColumn.FieldName, 'CurDealQuantity') then
  453. SetQuantityRec(ANode, APhaseRec, 'Deal')
  454. else if SameText(AColumn.FieldName, 'CurQcQuantity') then
  455. SetQuantityRec(ANode, APhaseRec, 'Qc')
  456. else if SameText(AColumn.FieldName, 'CurPcQuantity') then
  457. SetQuantityRec(ANode, APhaseRec, 'Pc')
  458. else if SameText(AColumn.FieldName, 'CurDealTotalPrice') then
  459. SetTotalPriceRec(ANode, APhaseRec, 'Deal')
  460. else if SameText(AColumn.FieldName, 'CurQcTotalPrice') then
  461. SetTotalPriceRec(ANode, APhaseRec, 'Qc')
  462. else if SameText(AColumn.FieldName, 'CurPcTotalPrice') then
  463. SetTotalPriceRec(ANode, APhaseRec, 'Pc');
  464. end;
  465. function CheckNodeWritable(ANode: TBillsIDTreeNode): Boolean;
  466. var
  467. iCreatePhase: Integer;
  468. begin
  469. Result := True;
  470. {if ANode.ID = iPriceMarginID then
  471. DataSetErrorMessage(Result, sBills_PMHint);}
  472. if ANode.HasChildren then
  473. begin
  474. if ANewText = '' then
  475. Result := False
  476. else
  477. DataSetErrorMessage(Result, '该清单有子计算项,不能直接修改!');
  478. end
  479. else
  480. begin
  481. // 目前仅允许本期合同计量,可直接输入金额
  482. if SameText('CurDealTotalPrice', AColumn.FieldName) then
  483. begin
  484. if not ANode.TotalPriceEnable then
  485. DataSetErrorMessage(Result, '该清单不可直接输入金额,如需直接输入金额,请先清空所有数量、单价!');
  486. end
  487. else if SameText('CurDealQuantity', AColumn.FieldName) or
  488. SameText('CurQcQuantity', AColumn.FieldName) or
  489. SameText('CurPcQuantity', AColumn.FieldName) then
  490. begin
  491. if not ANode.CountPriceEnable then
  492. DataSetErrorMessage(Result, '该清单不可输入数量单价,如需使用数量×单价计算,请先清空所有直接输入的金额!');
  493. end;
  494. end;
  495. // 变更清单允许填写本期合同计量,按超计论
  496. {iCreatePhase := ANode.Rec.ValueByName('CreatePhaseID').AsInteger;
  497. if ANode.Rec.ValueByName('IsMeasureAdd').AsBoolean and (iCreatePhase > 0) and
  498. (SameText('CurDealQuantity', AColumn.FieldName) or
  499. SameText('CurDealTotalPrice', AColumn.FieldName)) then
  500. begin
  501. ErrorMessage(Format('该清单为第%d期新增清单,不可填写本期合同计量数据!', [iCreatePhase]));
  502. Exit;
  503. end; }
  504. end;
  505. var
  506. NewRec: TStageRecord;
  507. vNode: TMeasureBillsIDTreeNode;
  508. begin
  509. vNode := TMeasureBillsIDTreeNode(BillsMeasureTree.FindNode(ARecord.ValueByName('ID').AsInteger));
  510. if not CheckNodeWritable(vNode) then
  511. Exit;
  512. if CheckNeedAddPhaseRecord(vNode) then
  513. begin
  514. if (Pos('Quantity', AColumn.FieldName) > 0) or (Pos('TotalPrice', AColumn.FieldName) > 0) then
  515. if HasCardinalNum(ANewText) then
  516. raise Exception.Create('公式不可输入参数');
  517. NewRec := StageData.AddStageRecord(ARecord.ValueByName('ID').AsInteger);
  518. vNode.StageRec := NewRec;
  519. SetNewRecValue(vNode, NewRec);
  520. end;
  521. end;
  522. procedure TBillsMeasureData.sdvBillsMeasureAfterClose(Sender: TObject);
  523. begin
  524. FBillsMeasureTree.Active := False;
  525. end;
  526. function TBillsMeasureData.OnGetCardinalNum(
  527. const ACardinalNum: string): Double;
  528. {
  529. function GetTotalPrice(ABillsID: Integer): Double;
  530. var
  531. stnNode: TsdIDTreeNode;
  532. begin
  533. stnNode := FBillsTree.FindNode(ABillsID);
  534. if Assigned(stnNode) then
  535. Result := stnNode.Rec.ValueByName('TotalPrice').AsFloat;
  536. end;
  537. function GetPhaseTotalPrice(ABillsID: Integer; const AType: string): Double;
  538. var
  539. Rec: TsdDataRecord;
  540. begin
  541. Rec := CurPhaseData.PhaseRecord(ABillsID);
  542. if Assigned(Rec) then
  543. Result := Rec.ValueByName(AType + 'TotalPrice').AsFloat;
  544. end;
  545. }
  546. function GetTotalPrice(ANode: TsdIDTreeNode): Double;
  547. var
  548. iChild: Integer;
  549. begin
  550. Result := 0;
  551. if not Assigned(ANode) then Exit;
  552. if ANode.HasChildren then
  553. for iChild := 0 to ANode.ChildCount - 1 do
  554. Result := Result + GetTotalPrice(ANode.ChildNodes[iChild])
  555. else
  556. Result := ANode.Rec.ValueByName('TotalPrice').AsFloat;
  557. end;
  558. function GetPhaseTotalPrice(ANode: TsdIDTreeNode; const AType: string): Double;
  559. var
  560. iChild: Integer;
  561. Rec: TsdDataRecord;
  562. begin
  563. Result := 0;
  564. if not Assigned(ANode) then Exit;
  565. if ANode.HasChildren then
  566. for iChild := 0 to ANode.ChildCount - 1 do
  567. Result := Result + GetPhaseTotalPrice(ANode.ChildNodes[iChild], AType)
  568. else
  569. begin
  570. Rec := StageData.StageRecord(ANode.ID);
  571. if Assigned(Rec) then
  572. Result := Rec.ValueByName(AType + 'TotalPrice').AsFloat;
  573. end;
  574. end;
  575. var
  576. iNodeID: Integer;
  577. begin
  578. Result := 0;
  579. iNodeID := StrToIntDef(Copy(ACardinalNum, 2, Length(ACardinalNum) - 1), -1);
  580. case ACardinalNum[1] of
  581. 'A','a': Result := GetTotalPrice(BillsMeasureTree.FindNode(iNodeID));
  582. 'B','b': Result := GetPhaseTotalPrice(BillsMeasureTree.FindNode(iNodeID), 'Deal');
  583. 'C','c': Result := GetPhaseTotalPrice(BillsMeasureTree.FindNode(iNodeID), 'Qc');
  584. 'D','d': Result := GetPhaseTotalPrice(BillsMeasureTree.FindNode(iNodeID), 'Pc');
  585. {'A','a': Result := GetTotalPrice(iNodeID);
  586. 'B','b': Result := GetPhaseTotalPrice(iNodeID, 'Deal');
  587. 'C','c': Result := GetPhaseTotalPrice(iNodeID, 'Qc');
  588. 'D','d': Result := GetPhaseTotalPrice(iNodeID, 'Pc');}
  589. end;
  590. end;
  591. function TBillsMeasureData.GetStageData: TStageData;
  592. begin
  593. Result := TProjectData(FProjectData).PhaseData.StageData;
  594. end;
  595. procedure TBillsMeasureData.ExpandNodeTo(ALevel: Integer);
  596. begin
  597. BillsMeasureTree.ExpandLevel := ALevel;
  598. end;
  599. procedure TBillsMeasureData.ExpandXmjNode;
  600. var
  601. iIndex: Integer;
  602. stnNode: TBillsIDTreeNode;
  603. begin
  604. for iIndex := 0 to BillsMeasureTree.Count - 1 do
  605. begin
  606. stnNode := TBillsIDTreeNode(BillsMeasureTree.Items[iIndex]);
  607. if (stnNode.ParentID <> -1) then
  608. stnNode.Parent.Expanded := stnNode.Rec.B_Code.AsString = '';
  609. end;
  610. end;
  611. procedure TBillsMeasureData.CalculateAll;
  612. var
  613. //Cacl: TBillsCalculate;
  614. i: Integer;
  615. begin
  616. if not TProjectData(FProjectData).StageDataReadOnly then
  617. for i := 0 to BillsMeasureTree.Count - 1 do
  618. CalculateNode(TMeasureBillsIDTreeNode(BillsMeasureTree.Items[i]));
  619. {Cacl := TBillsCalculate.Create(Self);
  620. try
  621. Cacl.Execute;
  622. finally
  623. Cacl.Free;
  624. end;}
  625. end;
  626. procedure TBillsMeasureData.UpdateRecordDeal(ABillsID: Integer; AQuantity,
  627. ATotalPrice: Double);
  628. var
  629. stnNode: TsdIDTreeNode;
  630. begin
  631. stnNode := BillsMeasureTree.FindNode(ABillsID);
  632. if not Assigned(stnNode) then Exit;
  633. with stnNode.Rec do
  634. begin
  635. if not stnNode.HasChildren then
  636. ValueByName('AddDealQuantity').AsFloat := QuantityRoundTo(
  637. ValueByName('AddDealQuantity').AsFloat + AQuantity);
  638. ValueByName('AddDealTotalPrice').AsFloat := TotalPriceRoundTo(
  639. ValueByName('AddDealTotalPrice').AsFloat + ATotalPrice);
  640. end;
  641. UpdateRecordGather(stnNode, AQuantity, ATotalPrice);
  642. UpdateRecordDeal(stnNode.ParentID, AQuantity, ATotalPrice);
  643. end;
  644. procedure TBillsMeasureData.UpdateRecordPc(ABillsID: Integer; AQuantity,
  645. ATotalPrice: Double);
  646. var
  647. stnNode: TsdIDTreeNode;
  648. begin
  649. stnNode := BillsMeasureTree.FindNode(ABillsID);
  650. if not Assigned(stnNode) then Exit;
  651. with stnNode.Rec do
  652. begin
  653. if not stnNode.HasChildren then
  654. ValueByName('AddPcQuantity').AsFloat := QuantityRoundTo(
  655. ValueByName('AddPcQuantity').AsFloat + AQuantity);
  656. ValueByName('AddPcTotalPrice').AsFloat := TotalPriceRoundTo(
  657. ValueByName('AddPcTotalPrice').AsFloat + ATotalPrice);
  658. end;
  659. UpdateRecordGather(stnNode, 0, ATotalPrice);
  660. UpdateRecordPc(stnNode.ParentID, AQuantity, ATotalPrice);
  661. end;
  662. procedure TBillsMeasureData.UpdateRecordQc(ABillsID: Integer; AQuantity,
  663. ATotalPrice: Double);
  664. var
  665. stnNode: TsdIDTreeNode;
  666. begin
  667. stnNode := BillsMeasureTree.FindNode(ABillsID);
  668. if not Assigned(stnNode) then Exit;
  669. with stnNode.Rec do
  670. begin
  671. if not stnNode.HasChildren then
  672. ValueByName('AddQcQuantity').AsFloat := QuantityRoundTo(
  673. ValueByName('AddQcQuantity').AsFloat + AQuantity);
  674. ValueByName('AddQcTotalPrice').AsFloat := TotalPriceRoundTo(
  675. ValueByName('AddQcTotalPrice').AsFloat + ATotalPrice);
  676. end;
  677. UpdateRecordGather(stnNode, AQuantity, ATotalPrice);
  678. UpdateRecordQc(stnNode.ParentID, AQuantity, ATotalPrice);
  679. end;
  680. procedure TBillsMeasureData.UpdateRecordGather(ANode: TsdIDTreeNode;
  681. AQuantity, ATotalPrice: Double);
  682. begin
  683. with ANode.Rec do
  684. begin
  685. if not ANode.HasChildren then
  686. ValueByName('AddGatherQuantity').AsFloat := QuantityRoundTo(
  687. ValueByName('AddGatherQuantity').AsFloat + AQuantity);
  688. ValueByName('AddGatherTotalPrice').AsFloat := TotalPriceRoundTo(
  689. ValueByName('AddGatherTotalPrice').AsFloat + ATotalPrice);
  690. end;
  691. CalcAddDgnPrice(ANode);
  692. CalcAddCompleteRate(ANode);
  693. end;
  694. function TBillsMeasureData.GatherRelaBGL(ANode: TsdIDTreeNode): string;
  695. var
  696. iChild: Integer;
  697. Rec: TsdDataRecord;
  698. begin
  699. Result := '';
  700. if not Assigned(ANode) then Exit;
  701. if ANode.HasChildren then
  702. begin
  703. for iChild := 0 to ANode.ChildCount - 1 do
  704. Result := MergeRelaBGL(Result, GatherRelaBGL(ANode.ChildNodes[iChild]));
  705. end
  706. else
  707. begin
  708. with TProjectData(FProjectData).PhaseData.StageData do
  709. Rec := StageRecord(ANode.ID);
  710. if Assigned(Rec) then
  711. Result := MergeRelaBGL(Rec.ValueByName('QcBGLCode').AsString, Rec.ValueByName('PcBGLCode').AsString);
  712. end;
  713. end;
  714. procedure TBillsMeasureData.sdvBillsMeasureAfterValueChanged(
  715. AValue: TsdValue);
  716. var
  717. iID: Integer;
  718. vNode: TBillsIDTreeNode;
  719. begin
  720. if AValue.Owner.Owner.Name = 'sddBills' then
  721. begin
  722. iID := AValue.Owner.ValueByName('ID').AsInteger;
  723. vNode := TBillsIDTreeNode(BillsMeasureTree.FindNode(iID));
  724. if SameText(AValue.FieldName, 'Price') then
  725. TProjectData(FProjectData).BillsCompileData.Calculate(iID);
  726. if TProjectData(FProjectData).PhaseData.Active then
  727. begin
  728. if AValue.FieldName = 'Price' then
  729. StageData.ReCalculate(iID);
  730. if AValue.FieldName = 'NewPrice' then
  731. StageData.ReCalculate(iID);
  732. end;
  733. if Pos('DgnQuantity1', AValue.FieldName) > 0 then
  734. CalcAddDgnPrice(vNode);
  735. if (AValue.FieldName = 'Code') then
  736. BillsMeasureTree.RecodeChildrenCode(vNode, VarToStrDef(AValue.OldValue, ''), AValue.AsString)
  737. else if (AValue.FieldName = 'B_Code') then
  738. BillsMeasureTree.RecodeChildrenB_Code(vNode, VarToStrDef(AValue.OldValue, ''), AValue.AsString);
  739. end;
  740. end;
  741. procedure TBillsMeasureData.ExpandCurPhase;
  742. var
  743. iIndex: Integer;
  744. stnNode: TsdIDTreeNode;
  745. StageRec: TStageRecord;
  746. begin
  747. for iIndex := 0 to BillsMeasureTree.Count - 1 do
  748. begin
  749. stnNode := BillsMeasureTree.Items[iIndex];
  750. StageRec := TMeasureBillsIDTreeNode(stnNode).StageRec;
  751. if (stnNode.ParentID <> -1) then
  752. if Assigned(StageRec) then
  753. stnNode.Expanded := StageRec.GatherTotalPrice.AsFloat <> 0
  754. else
  755. stnNode.Expanded := False;
  756. end;
  757. end;
  758. procedure TBillsMeasureData.UpdateBGLInfo(ABillsID: Integer;
  759. ARec: TsdDataRecord; const AType: string);
  760. var
  761. stnNode: TsdIDTreeNode;
  762. begin
  763. stnNode := BillsMeasureTree.FindNode(ABillsID);
  764. if not Assigned(stnNode) then Exit;
  765. stnNode.Rec.ValueByName('Add' + AType + 'BGLCode').AsString :=
  766. ARec.ValueByName('End' + AType + 'BGLCode').AsString;
  767. stnNode.Rec.ValueByName('Add' + AType + 'BGLNum').AsString :=
  768. ARec.ValueByName('End' + AType + 'BGLNum').AsString;
  769. end;
  770. function TBillsMeasureData.SelectAndUpdateBGL(ABillsID: Integer;
  771. ARec: TsdDataRecord; ANewValue: Double; const AType: string): Boolean;
  772. var
  773. AOrgBGL, ANewBGL: TBGLSelectInfo;
  774. ACurNode: TsdIDTreeNode;
  775. procedure UpdateBGL;
  776. begin
  777. ARec.ValueByName(AType + 'BGLCode').AsString := ANewBGL.MergedCode;
  778. ARec.ValueByName(AType + 'BGLNum').AsString := ANewBGL.MergedNum;
  779. TProjectData(ProjectData).BGLData.ApplyBGL(AOrgBGL, ANewBGL);
  780. end;
  781. begin
  782. Result := True;
  783. ACurNode := BillsMeasureTree.FindNode(ABillsID);
  784. AOrgBGL := TBGLSelectInfo.Create(ACurNode.Rec,
  785. ARec.ValueByName(AType + 'Quantity').AsFloat, True);
  786. AOrgBGL.MergedCode := ARec.ValueByName(AType + 'BGLCode').AsString;
  787. AOrgBGL.MergedNum := ARec.ValueByName(AType + 'BGLNum').AsString;
  788. ANewBGL := TBGLSelectInfo.Create(ACurNode.Rec, ANewValue, False);
  789. try
  790. if ANewBGL.TotalNum <> 0 then
  791. begin
  792. Result := SelectBGL(AOrgBGL, ANewBGL, ProjectData);
  793. if Result then
  794. UpdateBGL;
  795. end
  796. else
  797. UpdateBGL;
  798. StageData.UpdateBGLInfo(ARec, AType);
  799. UpdateBGLInfo(ABillsID, ARec, AType);
  800. finally
  801. AOrgBGL.Free;
  802. ANewBGL.Free;
  803. end;
  804. end;
  805. procedure TBillsMeasureData.Close;
  806. begin
  807. sdvBillsMeasure.Close;
  808. end;
  809. procedure TBillsMeasureData.CalcAddCompleteRate(ANode: TsdIDTreeNode);
  810. var
  811. fDividend, fDivisor: Double;
  812. begin
  813. with ANode.Rec do
  814. begin
  815. fDividend := ValueByName('AddGatherTotalPrice').AsFloat;
  816. fDivisor := ValueByName('TotalPrice').AsFloat + ValueByName('AddQcTotalPrice').AsFloat
  817. + ValueByName('AddPcTotalPrice').AsFloat;
  818. if fDivisor <> 0 then
  819. ValueByName('AddCompleteRate').AsFloat := AdvRoundTo(fDividend/fDivisor*100)
  820. else
  821. ValueByName('AddCompleteRate').Clear;
  822. end;
  823. end;
  824. procedure TBillsMeasureData.CalcAddDgnPrice(ANode: TsdIDTreeNode);
  825. var
  826. fDividend, fDivisor: Double;
  827. begin
  828. with ANode.Rec do
  829. begin
  830. fDividend := ValueByName('AddGatherTotalPrice').AsFloat;
  831. fDivisor := ValueByName('DealDgnQuantity1').AsFloat + ValueByName('CDgnQuantity1').AsFloat;
  832. if fDivisor <> 0 then
  833. ValueByName('AddDgnPrice').AsFloat := AdvRoundTo(fDividend/fDivisor);
  834. end;
  835. end;
  836. procedure TBillsMeasureData.SetOnRecChange(const Value: TRecChangeEvent);
  837. begin
  838. FOnRecChange := Value;
  839. end;
  840. procedure TBillsMeasureData.sdvBillsMeasureCurrentChanged(
  841. ARecord: TsdDataRecord);
  842. begin
  843. if Assigned(FOnRecChange) then
  844. FOnRecChange(ARecord);
  845. end;
  846. procedure TBillsMeasureData.ResetTreeNodeStageRec;
  847. var
  848. i: Integer;
  849. vNode: TMeasureBillsIDTreeNode;
  850. begin
  851. if not StageData.Active then Exit;
  852. for i := 0 to BillsMeasureTree.Count - 1 do
  853. begin
  854. vNode := TMeasureBillsIDTreeNode(BillsMeasureTree.Items[i]);
  855. vNode.StageRec := StageData.StageRecord(vNode.ID);
  856. end;
  857. end;
  858. procedure TBillsMeasureData.UpdateRecordPM(ABillsID: Integer;
  859. ADiffer: Double);
  860. var
  861. stnNode: TBillsIDTreeNode;
  862. begin
  863. stnNode := TBillsIDTreeNode(BillsMeasureTree.FindNode(ABillsID));
  864. if not Assigned(stnNode) then Exit;
  865. stnNode.Rec.PM_AddTotalPrice.AsFloat := stnNode.Rec.PM_AddTotalPrice.AsFloat + ADiffer;
  866. UpdateRecordPM(stnNode.ParentID, ADiffer);
  867. end;
  868. procedure TBillsMeasureData.CalculateNode(ANode: TMeasureBillsIDTreeNode);
  869. begin
  870. if Assigned(ANode.StageRec) then
  871. begin
  872. if not ANode.HasChildren then
  873. begin
  874. ANode.Rec.AddDealQuantity.AsFloat := ANode.StageRec.EndDealQuantity.AsFloat;
  875. ANode.Rec.AddQcQuantity.AsFloat := ANode.StageRec.EndQcQuantity.AsFloat;
  876. ANode.Rec.AddQcBGLCode.AsString := ANode.StageRec.EndQcBGLCode.AsString;
  877. ANode.Rec.AddQcBGLNum.AsString := ANode.StageRec.EndQcBGLNum.AsString;
  878. ANode.Rec.AddPcQuantity.AsFloat := ANode.StageRec.EndPcQuantity.AsFloat;
  879. ANode.Rec.AddPcBGLCode.AsString := ANode.StageRec.EndPcBGLCode.AsString;
  880. ANode.Rec.AddPcBGLNum.AsString := ANode.StageRec.EndPcBGLNum.AsString;
  881. ANode.Rec.AddGatherQuantity.AsFloat := ANode.StageRec.EndGatherQuantity.AsFloat;
  882. end;
  883. ANode.Rec.AddDealTotalPrice.AsFloat := ANode.StageRec.EndDealTotalPrice.AsFloat;
  884. ANode.Rec.AddQcTotalPrice.AsFloat := ANode.StageRec.EndQcTotalPrice.AsFloat;
  885. ANode.Rec.AddPcTotalPrice.AsFloat := ANode.StageRec.EndPcTotalPrice.AsFloat;
  886. ANode.Rec.AddGatherTotalPrice.AsFloat := ANode.StageRec.EndGatherTotalPrice.AsFloat;
  887. ANode.Rec.PM_AddTotalPrice.AsFloat := ANode.StageRec.PM_PreTotalPrice.AsFloat + ANode.StageRec.PM_TotalPrice.AsFloat;
  888. end;
  889. end;
  890. procedure TBillsMeasureData.UpdateGather(ABillsID: Integer;
  891. ADiffer: Double);
  892. var
  893. stnNode: TBillsIDTreeNode;
  894. begin
  895. stnNode := TBillsIDTreeNode(BillsMeasureTree.FindNode(ABillsID));
  896. if not Assigned(stnNode) then Exit;
  897. with stnNode.Rec do
  898. AddDifferValue(AddGatherTotalPrice, ADiffer);
  899. UpdateGather(stnNode.ParentID, ADiffer);
  900. end;
  901. procedure TBillsMeasureData.FreeTreeNodeStageRec;
  902. var
  903. i: Integer;
  904. vNode: TMeasureBillsIDTreeNode;
  905. begin
  906. for i := 0 to BillsMeasureTree.Count - 1 do
  907. begin
  908. vNode := TMeasureBillsIDTreeNode(BillsMeasureTree.Items[i]);
  909. vNode.StageRec := nil;
  910. end;
  911. end;
  912. function TBillsMeasureData.FindNodeWithZJJL(ANode: TsdIDTreeNode): TsdIDTreeNode;
  913. function CheckNodeHasZJJL(ANode: TsdIDTreeNode): Boolean;
  914. begin
  915. Result := Assigned(TProjectData(FProjectData).PhaseData.ZJJLData.sddZJJL.Locate('BillsID', ANode.ID));
  916. end;
  917. function FindChildWithZJJL(ANode: TsdIDTreeNode): TsdIDTreeNode;
  918. var
  919. iChild: Integer;
  920. vChild: TsdIDTreeNode;
  921. begin
  922. Result := nil;
  923. for iChild := 0 to ANode.ChildCount - 1 do
  924. begin
  925. vChild := ANode.ChildNodes[iChild];
  926. if CheckNodeHasZJJL(vChild) then
  927. Result := vChild
  928. else if vChild.HasChildren then
  929. Result := FindChildWithZJJL(vChild);
  930. if Assigned(Result) then
  931. Break;
  932. end;
  933. end;
  934. function FindParentWithZJJL(ANode: TsdIDTreeNode): TsdIDTreeNode;
  935. var
  936. vParent: TsdIDTreeNode;
  937. begin
  938. Result := nil;
  939. vParent := ANode.Parent;
  940. while Assigned(vParent) and not Assigned(Result) do
  941. begin
  942. if CheckNodeHasZJJL(vParent) then
  943. Result := vParent;
  944. vParent := vParent.Parent;
  945. end;
  946. end;
  947. begin
  948. if not CheckNodeHasZJJL(ANode) then
  949. begin
  950. Result := FindChildWithZJJL(ANode);
  951. if not Assigned(Result) then
  952. Result := FindParentWithZJJL(ANode);
  953. end
  954. else
  955. Result := ANode;
  956. end;
  957. end.