DetailGLDm.pas 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455
  1. unit DetailGLDm;
  2. interface
  3. uses
  4. SysUtils, Classes, sdDB, sdProvider, ADODB, Variants, mDataRecord;
  5. type
  6. TDetailGLData = class(TDataModule)
  7. sdpDetailGL: TsdADOProvider;
  8. sddDetailGL: TsdDataSet;
  9. procedure sddDetailGLGetRecordClass(var ARecordClass: TsdRecordClass);
  10. procedure sddDetailGLBeforeDeleteRecord(ARecord: TsdDataRecord;
  11. var Allow: Boolean);
  12. procedure sddDetailGLBeforeValueChange(AValue: TsdValue;
  13. const NewValue: Variant; var Allow: Boolean);
  14. procedure sddDetailGLAfterDeleteRecord(ARecord: TsdDataRecord);
  15. private
  16. FProjectData: TObject;
  17. procedure LoadRelaProjectGL;
  18. function FindDetailGL(ABillsID, AGLID: Integer): TDetailGLRecord;
  19. public
  20. constructor Create(AProjectData: TObject);
  21. destructor Destroy; override;
  22. procedure Open(AConnection: TADOConnection);
  23. procedure Close;
  24. procedure Save;
  25. procedure SaveCacheData;
  26. function AddLeafXmjGl(ARec: TDetailGLRecord): TsdDataRecord;
  27. function AddDetailGL(ABillsID: Integer; AProjectGLRec: TProjectGLRecord;
  28. var sMessage: string): TDetailGLRecord;
  29. procedure AddDetailGLs(ABillsID: Integer; AGLs: TList);
  30. procedure LoadDetailGLs(ABillsID: Integer; AGLs: TList);
  31. function HasLockedDetailGL(ABillsID: Integer): Boolean;
  32. procedure ClearDetailGLs(ABillsID: Integer);
  33. procedure ResetDetailGLs(ABillsID: Integer; AGLs: TList);
  34. procedure LoadXmjDetailGLs(AXmjID, AGLID: Integer; AGLs: TList);
  35. procedure LoadProjectGL_DetailGLs(AGLID: Integer; AGLs: TList);
  36. function HasXmjDetailGL(AXmjID, AGLID: Integer): Boolean;
  37. function GetUnitPriceMargin(ABillsID: Integer): Double;
  38. property ProjectData: TObject read FProjectData write FProjectData;
  39. end;
  40. implementation
  41. uses
  42. Math, UtilMethods, ProjectData, ProjectProperty, ProjectGLDm,
  43. PriceMarginBillsDm, StageDm, PhasePayDm, sdIDTree;
  44. {$R *.dfm}
  45. { TDetailGLData }
  46. function TDetailGLData.AddDetailGL(ABillsID: Integer;
  47. AProjectGLRec: TProjectGLRecord;
  48. var sMessage: string): TDetailGLRecord;
  49. begin
  50. sMessage := '';
  51. Result := FindDetailGL(ABillsID, AProjectGLRec.ID.AsInteger);
  52. if not Assigned(Result) then
  53. begin
  54. Result := TDetailGLRecord(sddDetailGL.Add(True));
  55. Result.ID.AsInteger := GetsdDataSetNewID(sddDetailGL, 'idxID');
  56. Result.BillsID.AsInteger := ABillsID;
  57. Result.GLID.AsInteger := AProjectGLRec.ID.AsInteger;
  58. Result.Code.AsString := AProjectGLRec.Code.AsString;
  59. Result.CreatePhaseID.AsInteger := TProjectData(FProjectData).ProjProperties.PhaseCount;
  60. Result.RelaProjectGL := AProjectGLRec;
  61. Result.EndUpdate;
  62. end
  63. else
  64. sMessage := Format('编号:%s 名称:%s', [AProjectGLRec.Code.AsString, AProjectGLRec.Name.AsString]);
  65. AddLeafXmjGl(Result);
  66. end;
  67. procedure TDetailGLData.AddDetailGLs(ABillsID: Integer; AGLs: TList);
  68. var
  69. i: Integer;
  70. sHint, sMessage: string;
  71. begin
  72. sHint := '';
  73. for i := 0 to AGLs.Count - 1 do
  74. begin
  75. AddDetailGL(ABillsID, TProjectGLRecord(AGLs.Items[i]), sMessage);
  76. if sMessage <> '' then
  77. begin
  78. if sHint <> '' then
  79. sHint := sHint + #13#10;
  80. sHint := sHint + sMessage;
  81. end;
  82. end;
  83. if sHint <> '' then
  84. TipMessage('以下工料已添加至该清单,请勿重复添加:' + #13#10 + sHint);
  85. end;
  86. procedure TDetailGLData.ResetDetailGLs(ABillsID: Integer; AGLs: TList);
  87. var
  88. i, iNewID: Integer;
  89. Rec, GLRec: TDetailGLRecord;
  90. begin
  91. if HasLockedDetailGL(ABillsID) then Exit;
  92. ClearDetailGLs(ABillsID);
  93. sddDetailGL.BeginUpdate;
  94. try
  95. iNewID := GetsdDataSetNewID(sddDetailGL, 'idxID');
  96. for i := 0 to AGLs.Count - 1 do
  97. begin
  98. GLRec := TDetailGLRecord(AGLs.Items[i]);
  99. Rec := TDetailGLRecord(sddDetailGL.Add);
  100. Rec.ID.AsInteger := iNewID + i;
  101. Rec.BillsID.AsInteger := ABillsID;
  102. Rec.GLID.AsInteger := GLRec.GLID.AsInteger;
  103. Rec.Code.AsInteger := GLRec.Code.AsInteger;
  104. Rec.Quantity.AsFloat := GLRec.Quantity.AsFloat;
  105. Rec.CreatePhaseID.AsInteger := TProjectData(FProjectData).ProjProperties.PhaseCount;
  106. Rec.RelaProjectGL := GLRec.RelaProjectGL;
  107. AddLeafXmjGl(Rec);
  108. end;
  109. finally
  110. sddDetailGL.EndUpdate;
  111. end;
  112. end;
  113. procedure TDetailGLData.ClearDetailGLs(ABillsID: Integer);
  114. var
  115. idx: TsdIndex;
  116. iFirst, iLast, iRec, iLeafXmjID, iGLID: Integer;
  117. Rec: TDetailGLRecord;
  118. begin
  119. sddDetailGL.BeginUpdate;
  120. try
  121. iLeafXmjID := TProjectData(FProjectData).BillsCompileData.GetLeafXmjParentID(ABillsID);
  122. idx := sddDetailGL.FindIndex('idxBillsID');
  123. iFirst := idx.FindKeyIndex(ABillsID);
  124. if iFirst <> -1 then
  125. begin
  126. iLast := idx.FindKeyLastIndex(ABillsID);
  127. for iRec := iFirst to iLast do
  128. begin
  129. Rec := TDetailGLRecord(idx.Records[iRec]);
  130. iGLID := Rec.GLID.AsInteger;
  131. sddDetailGL.Remove(Rec);
  132. if not HasXmjDetailGL(iLeafXmjID, iGLID) then
  133. TProjectData(FProjectData).LeafXmjGlData.DeleteLeafXmjGl(iLeafXmjID, iGLID);
  134. end;
  135. end;
  136. finally
  137. sddDetailGL.EndUpdate;
  138. end;
  139. end;
  140. procedure TDetailGLData.Close;
  141. begin
  142. sddDetailGL.Close;
  143. end;
  144. constructor TDetailGLData.Create(AProjectData: TObject);
  145. begin
  146. inherited Create(nil);
  147. FProjectData := AProjectData;
  148. sddDetailGL.AddIndex('idxView', 'BillsID;Code');
  149. sddDetailGL.AddIndex('idxFind', 'BillsID;GLID');
  150. sddDetailGL.AddIndex('idxBillsID', 'BillsID');
  151. sddDetailGL.AddIndex('idxID', 'ID');
  152. sddDetailGL.AddIndex('idxGLID', 'GLID');
  153. end;
  154. destructor TDetailGLData.Destroy;
  155. begin
  156. inherited;
  157. end;
  158. function TDetailGLData.FindDetailGL(ABillsID,
  159. AGLID: Integer): TDetailGLRecord;
  160. var
  161. idx: TsdIndex;
  162. begin
  163. idx := sddDetailGL.FindIndex('idxFind');
  164. Result := TDetailGLRecord(idx.FindKey(VarArrayOf([ABillsID, AGLID])));
  165. end;
  166. procedure TDetailGLData.Open(AConnection: TADOConnection);
  167. begin
  168. sdpDetailGL.Connection := AConnection;
  169. sddDetailGL.Open;
  170. // 建立与ProjectGL间的链接,以便计算时,快速获取工料的价格信息
  171. LoadRelaProjectGL;
  172. end;
  173. procedure TDetailGLData.Save;
  174. begin
  175. SaveCacheData;
  176. sddDetailGL.Save;
  177. end;
  178. procedure TDetailGLData.LoadDetailGLs(ABillsID: Integer; AGLs: TList);
  179. var
  180. idx: TsdIndex;
  181. iRec, iFirst, iLast: Integer;
  182. begin
  183. idx := sddDetailGL.FindIndex('idxBillsID');
  184. iFirst := idx.FindKeyIndex(ABillsID);
  185. if iFirst <> -1 then
  186. begin
  187. iLast := idx.FindKeyLastIndex(ABillsID);
  188. for iRec := iFirst to iLast do
  189. AGLs.Add(idx.Records[iRec]);
  190. end;
  191. end;
  192. function TDetailGLData.GetUnitPriceMargin(ABillsID: Integer): Double;
  193. var
  194. idx: TsdIndex;
  195. iRec, iFirst, iLast: Integer;
  196. Rec: TsdDataRecord;
  197. begin
  198. Result := 0;
  199. idx := sddDetailGL.FindIndex('idxBillsID');
  200. iFirst := idx.FindKeyIndex(ABillsID);
  201. if iFirst <> -1 then
  202. begin
  203. iLast := idx.FindKeyLastIndex(ABillsID);
  204. for iRec := iFirst to iLast do
  205. begin
  206. Rec := idx.Records[iRec];
  207. with TProjectData(FProjectData).ProjectGLData do
  208. Result := Result + Rec.ValueByName('Quantity').AsFloat * ValidDeltaPrice[Rec.ValueByName('GLID').AsInteger];
  209. end;
  210. end;
  211. end;
  212. procedure TDetailGLData.LoadProjectGL_DetailGLs(AGLID: Integer;
  213. AGLs: TList);
  214. var
  215. idx: TsdIndex;
  216. iRec, iFirst, iLast: Integer;
  217. begin
  218. idx := sddDetailGL.FindIndex('idxGLID');
  219. iFirst := idx.FindKeyIndex(AGLID);
  220. if iFirst <> -1 then
  221. begin
  222. iLast := idx.FindKeyLastIndex(AGLID);
  223. for iRec := iFirst to iLast do
  224. AGLs.Add(idx.Records[iRec]);
  225. end;
  226. end;
  227. procedure TDetailGLData.sddDetailGLGetRecordClass(
  228. var ARecordClass: TsdRecordClass);
  229. begin
  230. ARecordClass := TDetailGLRecord;
  231. end;
  232. procedure TDetailGLData.LoadRelaProjectGL;
  233. procedure LoadRela(AProjectGLRec: TProjectGLRecord);
  234. var
  235. vDetailGLs: TList;
  236. iGL: Integer;
  237. DetailGLRec: TDetailGLRecord;
  238. begin
  239. vDetailGLs := TList.Create;
  240. try
  241. LoadProjectGL_DetailGLs(AProjectGLRec.ID.AsInteger, vDetailGLs);
  242. for iGL := 0 to vDetailGLs.Count - 1 do
  243. begin
  244. DetailGLRec := TDetailGLRecord(vDetailGLs.Items[iGL]);
  245. DetailGLRec.RelaProjectGL := AProjectGLRec;
  246. end;
  247. finally
  248. vDetailGLs.Free;
  249. end;
  250. end;
  251. var
  252. idx: TsdIndex;
  253. i: Integer;
  254. ProjGLRec: TProjectGLRecord;
  255. begin
  256. if not TProjectData(FProjectData).ProjectGLData.Active then Exit;
  257. idx := sddDetailGL.FindIndex('idxGLID');
  258. with TProjectData(FProjectData).ProjectGLData do
  259. begin
  260. for i := 0 to sddProjectGL.RecordCount - 1 do
  261. begin
  262. ProjGLRec := TProjectGLRecord(sddProjectGL.Records[i]);
  263. LoadRela(ProjGLRec);
  264. end;
  265. end;
  266. end;
  267. procedure TDetailGLData.SaveCacheData;
  268. function GetBillsQuantity(ABillsID: Integer): Double;
  269. var
  270. StageRec: TStageRecord;
  271. begin
  272. StageRec := TProjectData(FProjectData).PhaseData.StageData.StageRecord(ABillsID);
  273. if Assigned(StageRec) then
  274. Result := StageRec.GatherQuantity.AsFloat
  275. else
  276. Result := 0;
  277. end;
  278. var
  279. idx: TsdIndex;
  280. DetailGL: TDetailGLRecord;
  281. fBillsQuantity: Double;
  282. iBillsID, iRec: Integer;
  283. begin
  284. if TProjectData(FProjectData).PhaseData.StageDataReadOnly then Exit;
  285. idx := sddDetailGL.FindIndex('idxBillsID');
  286. iBillsID := -1;
  287. for iRec := 0 to idx.RecordCount - 1 do
  288. begin
  289. DetailGL := TDetailGLRecord(idx.Records[iRec]);
  290. if iBillsID <> DetailGL.BillsID.AsInteger then
  291. begin
  292. iBillsID := DetailGL.BillsID.AsInteger;
  293. fBillsQuantity := GetBillsQuantity(iBillsID);
  294. end;
  295. if DetailGL.LastBillsQuantity.AsFloat <> fBillsQuantity then
  296. DetailGL.LastBillsQuantity.AsFloat := fBillsQuantity;
  297. end;
  298. end;
  299. procedure TDetailGLData.sddDetailGLBeforeDeleteRecord(
  300. ARecord: TsdDataRecord; var Allow: Boolean);
  301. begin
  302. Allow := TDetailGLRecord(ARecord).LockedPhaseID.AsInteger = 0;
  303. if not Allow then
  304. ErrorMessage('当前调差工料已被锁定,不可删除。');
  305. end;
  306. procedure TDetailGLData.sddDetailGLBeforeValueChange(AValue: TsdValue;
  307. const NewValue: Variant; var Allow: Boolean);
  308. begin
  309. if SameText(AValue.FieldName, 'Quantity') then
  310. begin
  311. if TDetailGLRecord(AValue.Owner).LockedPhaseID.AsInteger > 0 then
  312. DataSetErrorMessage(Allow, '当前调差工料已被锁定,不可修改数量。');
  313. end;
  314. end;
  315. function TDetailGLData.HasLockedDetailGL(ABillsID: Integer): Boolean;
  316. var
  317. idx: TsdIndex;
  318. iFirst, iLast, iRec: Integer;
  319. Rec: TDetailGLRecord;
  320. begin
  321. Result := False;
  322. idx := sddDetailGL.FindIndex('idxBillsID');
  323. iFirst := idx.FindKeyIndex(ABillsID);
  324. if iFirst > -1 then
  325. begin
  326. iLast := idx.FindKeyLastIndex(ABillsID);
  327. for iRec := iFirst to iLast do
  328. begin
  329. Rec := TDetailGLRecord(idx.Records[iRec]);
  330. if Rec.LockedPhaseID.AsInteger > 0 then
  331. begin
  332. Result := True;
  333. Break;
  334. end;
  335. end;
  336. end;
  337. end;
  338. function TDetailGLData.AddLeafXmjGl(ARec: TDetailGLRecord): TsdDataRecord;
  339. var
  340. iLeafXmjID: Integer;
  341. begin
  342. // 对应最底层项目节应新增
  343. with TProjectData(FProjectData) do
  344. begin
  345. iLeafXmjID := BillsCompileData.GetLeafXmjParentID(ARec.BillsID.AsInteger);
  346. LeafXmjGlData.AddLeafXmjGl(iLeafXmjID, ARec.GLID.AsInteger);
  347. end;
  348. end;
  349. procedure TDetailGLData.sddDetailGLAfterDeleteRecord(
  350. ARecord: TsdDataRecord);
  351. var
  352. iLeafXmjID: Integer;
  353. begin
  354. with TProjectData(FProjectData) do
  355. begin
  356. iLeafXmjID := BillsCompileData.GetLeafXmjParentID(TDetailGLRecord(ARecord).BillsID.AsInteger);
  357. if not HasXmjDetailGL(iLeafXmjID, TDetailGLRecord(ARecord).GLID.AsInteger) then
  358. LeafXmjGlData.DeleteLeafXmjGl(iLeafXmjID, TDetailGLRecord(ARecord).GLID.AsInteger);
  359. end;
  360. end;
  361. procedure TDetailGLData.LoadXmjDetailGLs(AXmjID, AGLID: Integer; AGLs: TList);
  362. var
  363. vLeafBills: TList;
  364. i: Integer;
  365. Rec: TsdDataRecord;
  366. begin
  367. vLeafBills := TList.Create;
  368. try
  369. TProjectData(FProjectData).BillsCompileData.LoadLeafBillsID(AXmjID, vLeafBills);
  370. for i := 0 to vLeafBills.Count - 1 do
  371. begin
  372. Rec := sddDetailGL.FindKey('idxFind', VarArrayOf([Integer(vLeafBills.Items[i]), AGLID]));
  373. if Assigned(Rec) then
  374. AGLs.Add(Rec);
  375. end;
  376. finally
  377. vLeafBills.Free;
  378. end;
  379. end;
  380. function TDetailGLData.HasXmjDetailGL(AXmjID, AGLID: Integer): Boolean;
  381. var
  382. vXmj, vChild: TsdIDTreeNode;
  383. iChild: Integer;
  384. begin
  385. Result := False;
  386. vXmj := TProjectData(FProjectData).BillsCompileData.BillsCompileTree.FindNode(AXmjID);
  387. if vXmj.HasChildren then
  388. begin
  389. for iChild := 0 to vXmj.ChildCount - 1 do
  390. begin
  391. vChild := vXmj.ChildNodes[iChild];
  392. if HasXmjDetailGL(vChild.ID, AGLID) then
  393. begin
  394. Result := True;
  395. Break;
  396. end;
  397. end;
  398. end
  399. else
  400. Result := Assigned(sddDetailGL.FindKey('idxFind', VarArrayOf([AXmjID, AGLID])));
  401. end;
  402. end.