DetailGLDm.pas 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361
  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. private
  15. FProjectData: TObject;
  16. procedure LoadRelaProjectGL;
  17. function FindDetailGL(ABillsID, AGLID: Integer): TDetailGLRecord;
  18. procedure ClearDetailGLs(ABillsID: Integer);
  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 AddDetailGL(ABillsID: Integer; AProjectGLRec: TProjectGLRecord;
  27. var sMessage: string): TDetailGLRecord;
  28. procedure AddDetailGLs(ABillsID: Integer; AGLs: TList);
  29. procedure LoadDetailGLs(ABillsID: Integer; AGLs: TList);
  30. function HasLockedDetailGL(ABillsID: Integer): Boolean;
  31. procedure ResetDetailGLs(ABillsID: Integer; AGLs: TList);
  32. procedure LoadProjectGL_DetailGLs(AGLID: Integer; AGLs: TList);
  33. function GetUnitPriceMargin(ABillsID: Integer): Double;
  34. property ProjectData: TObject read FProjectData write FProjectData;
  35. end;
  36. implementation
  37. uses
  38. Math, UtilMethods, ProjectData, ProjectProperty, ProjectGLDm,
  39. PriceMarginBillsDm, StageDm, PhasePayDm;
  40. {$R *.dfm}
  41. { TDetailGLData }
  42. function TDetailGLData.AddDetailGL(ABillsID: Integer;
  43. AProjectGLRec: TProjectGLRecord;
  44. var sMessage: string): TDetailGLRecord;
  45. begin
  46. sMessage := '';
  47. Result := FindDetailGL(ABillsID, AProjectGLRec.ID.AsInteger);
  48. if not Assigned(Result) then
  49. begin
  50. Result := TDetailGLRecord(sddDetailGL.Add(True));
  51. Result.ID.AsInteger := GetsdDataSetNewID(sddDetailGL, 'idxID');
  52. Result.BillsID.AsInteger := ABillsID;
  53. Result.GLID.AsInteger := AProjectGLRec.ID.AsInteger;
  54. Result.Code.AsString := AProjectGLRec.Code.AsString;
  55. Result.CreatePhaseID.AsInteger := TProjectData(FProjectData).ProjProperties.PhaseCount;
  56. Result.RelaProjectGL := AProjectGLRec;
  57. Result.EndUpdate;
  58. end
  59. else
  60. sMessage := Format('编号:%s 名称:%s', [AProjectGLRec.Code.AsString, AProjectGLRec.Name.AsString]);
  61. end;
  62. procedure TDetailGLData.AddDetailGLs(ABillsID: Integer; AGLs: TList);
  63. var
  64. i: Integer;
  65. sHint, sMessage: string;
  66. begin
  67. for i := 0 to AGLs.Count - 1 do
  68. begin
  69. AddDetailGL(ABillsID, TProjectGLRecord(AGLs.Items[i]), sMessage);
  70. if sMessage <> '' then
  71. begin
  72. if sHint <> '' then
  73. sHint := sHint + #13#10;
  74. sHint := sHint + sMessage;
  75. end;
  76. end;
  77. if sMessage <> '' then
  78. TipMessage('以下工料已添加至该清单,请勿重复添加:' + #13#10 + sHint);
  79. end;
  80. procedure TDetailGLData.ResetDetailGLs(ABillsID: Integer; AGLs: TList);
  81. var
  82. i, iNewID: Integer;
  83. Rec, GLRec: TDetailGLRecord;
  84. begin
  85. if HasLockedDetailGL(ABillsID) then Exit;
  86. sddDetailGL.BeginUpdate;
  87. try
  88. ClearDetailGLs(ABillsID);
  89. iNewID := GetsdDataSetNewID(sddDetailGL, 'idxID');
  90. for i := 0 to AGLs.Count - 1 do
  91. begin
  92. GLRec := TDetailGLRecord(AGLs.Items[i]);
  93. Rec := TDetailGLRecord(sddDetailGL.Add);
  94. Rec.ID.AsInteger := iNewID + i;
  95. Rec.BillsID.AsInteger := ABillsID;
  96. Rec.GLID.AsInteger := GLRec.GLID.AsInteger;
  97. Rec.Code.AsInteger := GLRec.Code.AsInteger;
  98. Rec.Quantity.AsFloat := GLRec.Quantity.AsFloat;
  99. Rec.CreatePhaseID.AsInteger := TProjectData(FProjectData).ProjProperties.PhaseCount;
  100. Rec.RelaProjectGL := GLRec.RelaProjectGL;
  101. end;
  102. finally
  103. sddDetailGL.EndUpdate;
  104. end;
  105. end;
  106. procedure TDetailGLData.ClearDetailGLs(ABillsID: Integer);
  107. var
  108. idx: TsdIndex;
  109. Rec: TsdDataRecord;
  110. begin
  111. idx := sddDetailGL.FindIndex('idxBillsID');
  112. Rec := idx.FindKey(ABillsID);
  113. while Assigned(Rec) do
  114. begin
  115. sddDetailGL.Remove(Rec);
  116. Rec := idx.FindKey(ABillsID);
  117. end;
  118. end;
  119. procedure TDetailGLData.Close;
  120. begin
  121. sddDetailGL.Close;
  122. end;
  123. constructor TDetailGLData.Create(AProjectData: TObject);
  124. begin
  125. inherited Create(nil);
  126. FProjectData := AProjectData;
  127. sddDetailGL.AddIndex('idxView', 'BillsID;Code');
  128. sddDetailGL.AddIndex('idxFind', 'BillsID;GLID');
  129. sddDetailGL.AddIndex('idxBillsID', 'BillsID');
  130. sddDetailGL.AddIndex('idxID', 'ID');
  131. sddDetailGL.AddIndex('idxGLID', 'GLID');
  132. end;
  133. destructor TDetailGLData.Destroy;
  134. begin
  135. inherited;
  136. end;
  137. function TDetailGLData.FindDetailGL(ABillsID,
  138. AGLID: Integer): TDetailGLRecord;
  139. var
  140. idx: TsdIndex;
  141. begin
  142. idx := sddDetailGL.FindIndex('idxFind');
  143. Result := TDetailGLRecord(idx.FindKey(VarArrayOf([ABillsID, AGLID])));
  144. end;
  145. procedure TDetailGLData.Open(AConnection: TADOConnection);
  146. begin
  147. sdpDetailGL.Connection := AConnection;
  148. sddDetailGL.Open;
  149. // 建立与ProjectGL间的链接,以便计算时,快速获取工料的价格信息
  150. LoadRelaProjectGL;
  151. end;
  152. procedure TDetailGLData.Save;
  153. begin
  154. SaveCacheData;
  155. sddDetailGL.Save;
  156. end;
  157. procedure TDetailGLData.LoadDetailGLs(ABillsID: Integer; AGLs: TList);
  158. var
  159. idx: TsdIndex;
  160. iRec, iFirst, iLast: Integer;
  161. begin
  162. idx := sddDetailGL.FindIndex('idxBillsID');
  163. iFirst := idx.FindKeyIndex(ABillsID);
  164. if iFirst <> -1 then
  165. begin
  166. iLast := idx.FindKeyLastIndex(ABillsID);
  167. for iRec := iFirst to iLast do
  168. AGLs.Add(idx.Records[iRec]);
  169. end;
  170. end;
  171. function TDetailGLData.GetUnitPriceMargin(ABillsID: Integer): Double;
  172. var
  173. idx: TsdIndex;
  174. iRec, iFirst, iLast: Integer;
  175. Rec: TsdDataRecord;
  176. begin
  177. Result := 0;
  178. idx := sddDetailGL.FindIndex('idxBillsID');
  179. iFirst := idx.FindKeyIndex(ABillsID);
  180. if iFirst <> -1 then
  181. begin
  182. iLast := idx.FindKeyLastIndex(ABillsID);
  183. for iRec := iFirst to iLast do
  184. begin
  185. Rec := idx.Records[iRec];
  186. with TProjectData(FProjectData).ProjectGLData do
  187. Result := Result + Rec.ValueByName('Quantity').AsFloat * ValidDeltaPrice[Rec.ValueByName('GLID').AsInteger];
  188. end;
  189. end;
  190. end;
  191. procedure TDetailGLData.LoadProjectGL_DetailGLs(AGLID: Integer;
  192. AGLs: TList);
  193. var
  194. idx: TsdIndex;
  195. iRec, iFirst, iLast: Integer;
  196. begin
  197. idx := sddDetailGL.FindIndex('idxGLID');
  198. iFirst := idx.FindKeyIndex(AGLID);
  199. if iFirst <> -1 then
  200. begin
  201. iLast := idx.FindKeyLastIndex(AGLID);
  202. for iRec := iFirst to iLast do
  203. AGLs.Add(idx.Records[iRec]);
  204. end;
  205. end;
  206. procedure TDetailGLData.sddDetailGLGetRecordClass(
  207. var ARecordClass: TsdRecordClass);
  208. begin
  209. ARecordClass := TDetailGLRecord;
  210. end;
  211. procedure TDetailGLData.LoadRelaProjectGL;
  212. procedure LoadRela(AProjectGLRec: TProjectGLRecord);
  213. var
  214. vDetailGLs: TList;
  215. iGL: Integer;
  216. DetailGLRec: TDetailGLRecord;
  217. begin
  218. vDetailGLs := TList.Create;
  219. try
  220. LoadProjectGL_DetailGLs(AProjectGLRec.ID.AsInteger, vDetailGLs);
  221. for iGL := 0 to vDetailGLs.Count - 1 do
  222. begin
  223. DetailGLRec := TDetailGLRecord(vDetailGLs.Items[iGL]);
  224. DetailGLRec.RelaProjectGL := AProjectGLRec;
  225. end;
  226. finally
  227. vDetailGLs.Free;
  228. end;
  229. end;
  230. var
  231. idx: TsdIndex;
  232. i: Integer;
  233. ProjectGLRec: TProjectGLRecord;
  234. begin
  235. if not TProjectData(FProjectData).ProjectGLData.Active then Exit;
  236. idx := sddDetailGL.FindIndex('idxGLID');
  237. with TProjectData(FProjectData).ProjectGLData do
  238. begin
  239. for i := 0 to sddProjectGL.RecordCount - 1 do
  240. begin
  241. ProjectGLRec := TProjectGLRecord(sddProjectGL.Records[i]);
  242. LoadRela(ProjectGLRec);
  243. end;
  244. end;
  245. end;
  246. procedure TDetailGLData.SaveCacheData;
  247. function GetBillsQuantity(ABillsID: Integer): Double;
  248. var
  249. StageRec: TStageRecord;
  250. begin
  251. StageRec := TProjectData(FProjectData).PhaseData.StageData.StageRecord(ABillsID);
  252. if Assigned(StageRec) then
  253. Result := StageRec.GatherQuantity.AsFloat
  254. else
  255. Result := 0;
  256. end;
  257. var
  258. idx: TsdIndex;
  259. DetailGL: TDetailGLRecord;
  260. fBillsQuantity: Double;
  261. iBillsID, iRec: Integer;
  262. begin
  263. if TProjectData(FProjectData).PhaseData.StageDataReadOnly then Exit;
  264. idx := sddDetailGL.FindIndex('idxBillsID');
  265. iBillsID := -1;
  266. for iRec := 0 to idx.RecordCount - 1 do
  267. begin
  268. DetailGL := TDetailGLRecord(idx.Records[iRec]);
  269. if iBillsID <> DetailGL.BillsID.AsInteger then
  270. begin
  271. iBillsID := DetailGL.BillsID.AsInteger;
  272. fBillsQuantity := GetBillsQuantity(iBillsID);
  273. end;
  274. if DetailGL.LastBillsQuantity.AsFloat <> fBillsQuantity then
  275. DetailGL.LastBillsQuantity.AsFloat := fBillsQuantity;
  276. end;
  277. end;
  278. procedure TDetailGLData.sddDetailGLBeforeDeleteRecord(
  279. ARecord: TsdDataRecord; var Allow: Boolean);
  280. begin
  281. Allow := TDetailGLRecord(ARecord).LockedPhaseID.AsInteger = 0;
  282. if not Allow then
  283. ErrorMessage('当前调差工料已被锁定,不可删除。');
  284. end;
  285. procedure TDetailGLData.sddDetailGLBeforeValueChange(AValue: TsdValue;
  286. const NewValue: Variant; var Allow: Boolean);
  287. begin
  288. if SameText(AValue.FieldName, 'Quantity') then
  289. begin
  290. if TDetailGLRecord(AValue.Owner).LockedPhaseID.AsInteger > 0 then
  291. DataSetErrorMessage(Allow, '当前调差工料已被锁定,不可修改数量。');
  292. end;
  293. end;
  294. function TDetailGLData.HasLockedDetailGL(ABillsID: Integer): Boolean;
  295. var
  296. idx: TsdIndex;
  297. iFirst, iLast, iRec: Integer;
  298. Rec: TDetailGLRecord;
  299. begin
  300. Result := False;
  301. idx := sddDetailGL.FindIndex('idxBillsID');
  302. iFirst := idx.FindKeyIndex(ABillsID);
  303. if iFirst > -1 then
  304. begin
  305. iLast := idx.FindKeyLastIndex(ABillsID);
  306. for iRec := iFirst to iLast do
  307. begin
  308. Rec := TDetailGLRecord(idx.Records[iRec]);
  309. if Rec.LockedPhaseID > 0 then
  310. begin
  311. Result := True;
  312. Break;
  313. end;
  314. end;
  315. end;
  316. end;
  317. end.