BillsMeasureDm.pas 33 KB

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