DetailGLDm.pas 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367
  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. ClearDetailGLs(ABillsID);
  87. sddDetailGL.BeginUpdate;
  88. try
  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. iFirst, iLast, iRec: Integer;
  110. begin
  111. sddDetailGL.BeginUpdate;
  112. try
  113. idx := sddDetailGL.FindIndex('idxBillsID');
  114. iFirst := idx.FindKeyIndex(ABillsID);
  115. if iFirst <> -1 then
  116. begin
  117. iLast := idx.FindKeyLastIndex(ABillsID);
  118. for iRec := iFirst to iLast do
  119. sddDetailGL.Remove(idx.Records[iRec]);
  120. end;
  121. finally
  122. sddDetailGL.EndUpdate;
  123. end;
  124. end;
  125. procedure TDetailGLData.Close;
  126. begin
  127. sddDetailGL.Close;
  128. end;
  129. constructor TDetailGLData.Create(AProjectData: TObject);
  130. begin
  131. inherited Create(nil);
  132. FProjectData := AProjectData;
  133. sddDetailGL.AddIndex('idxView', 'BillsID;Code');
  134. sddDetailGL.AddIndex('idxFind', 'BillsID;GLID');
  135. sddDetailGL.AddIndex('idxBillsID', 'BillsID');
  136. sddDetailGL.AddIndex('idxID', 'ID');
  137. sddDetailGL.AddIndex('idxGLID', 'GLID');
  138. end;
  139. destructor TDetailGLData.Destroy;
  140. begin
  141. inherited;
  142. end;
  143. function TDetailGLData.FindDetailGL(ABillsID,
  144. AGLID: Integer): TDetailGLRecord;
  145. var
  146. idx: TsdIndex;
  147. begin
  148. idx := sddDetailGL.FindIndex('idxFind');
  149. Result := TDetailGLRecord(idx.FindKey(VarArrayOf([ABillsID, AGLID])));
  150. end;
  151. procedure TDetailGLData.Open(AConnection: TADOConnection);
  152. begin
  153. sdpDetailGL.Connection := AConnection;
  154. sddDetailGL.Open;
  155. // 建立与ProjectGL间的链接,以便计算时,快速获取工料的价格信息
  156. LoadRelaProjectGL;
  157. end;
  158. procedure TDetailGLData.Save;
  159. begin
  160. SaveCacheData;
  161. sddDetailGL.Save;
  162. end;
  163. procedure TDetailGLData.LoadDetailGLs(ABillsID: Integer; AGLs: TList);
  164. var
  165. idx: TsdIndex;
  166. iRec, iFirst, iLast: Integer;
  167. begin
  168. idx := sddDetailGL.FindIndex('idxBillsID');
  169. iFirst := idx.FindKeyIndex(ABillsID);
  170. if iFirst <> -1 then
  171. begin
  172. iLast := idx.FindKeyLastIndex(ABillsID);
  173. for iRec := iFirst to iLast do
  174. AGLs.Add(idx.Records[iRec]);
  175. end;
  176. end;
  177. function TDetailGLData.GetUnitPriceMargin(ABillsID: Integer): Double;
  178. var
  179. idx: TsdIndex;
  180. iRec, iFirst, iLast: Integer;
  181. Rec: TsdDataRecord;
  182. begin
  183. Result := 0;
  184. idx := sddDetailGL.FindIndex('idxBillsID');
  185. iFirst := idx.FindKeyIndex(ABillsID);
  186. if iFirst <> -1 then
  187. begin
  188. iLast := idx.FindKeyLastIndex(ABillsID);
  189. for iRec := iFirst to iLast do
  190. begin
  191. Rec := idx.Records[iRec];
  192. with TProjectData(FProjectData).ProjectGLData do
  193. Result := Result + Rec.ValueByName('Quantity').AsFloat * ValidDeltaPrice[Rec.ValueByName('GLID').AsInteger];
  194. end;
  195. end;
  196. end;
  197. procedure TDetailGLData.LoadProjectGL_DetailGLs(AGLID: Integer;
  198. AGLs: TList);
  199. var
  200. idx: TsdIndex;
  201. iRec, iFirst, iLast: Integer;
  202. begin
  203. idx := sddDetailGL.FindIndex('idxGLID');
  204. iFirst := idx.FindKeyIndex(AGLID);
  205. if iFirst <> -1 then
  206. begin
  207. iLast := idx.FindKeyLastIndex(AGLID);
  208. for iRec := iFirst to iLast do
  209. AGLs.Add(idx.Records[iRec]);
  210. end;
  211. end;
  212. procedure TDetailGLData.sddDetailGLGetRecordClass(
  213. var ARecordClass: TsdRecordClass);
  214. begin
  215. ARecordClass := TDetailGLRecord;
  216. end;
  217. procedure TDetailGLData.LoadRelaProjectGL;
  218. procedure LoadRela(AProjectGLRec: TProjectGLRecord);
  219. var
  220. vDetailGLs: TList;
  221. iGL: Integer;
  222. DetailGLRec: TDetailGLRecord;
  223. begin
  224. vDetailGLs := TList.Create;
  225. try
  226. LoadProjectGL_DetailGLs(AProjectGLRec.ID.AsInteger, vDetailGLs);
  227. for iGL := 0 to vDetailGLs.Count - 1 do
  228. begin
  229. DetailGLRec := TDetailGLRecord(vDetailGLs.Items[iGL]);
  230. DetailGLRec.RelaProjectGL := AProjectGLRec;
  231. end;
  232. finally
  233. vDetailGLs.Free;
  234. end;
  235. end;
  236. var
  237. idx: TsdIndex;
  238. i: Integer;
  239. ProjectGLRec: TProjectGLRecord;
  240. begin
  241. if not TProjectData(FProjectData).ProjectGLData.Active then Exit;
  242. idx := sddDetailGL.FindIndex('idxGLID');
  243. with TProjectData(FProjectData).ProjectGLData do
  244. begin
  245. for i := 0 to sddProjectGL.RecordCount - 1 do
  246. begin
  247. ProjectGLRec := TProjectGLRecord(sddProjectGL.Records[i]);
  248. LoadRela(ProjectGLRec);
  249. end;
  250. end;
  251. end;
  252. procedure TDetailGLData.SaveCacheData;
  253. function GetBillsQuantity(ABillsID: Integer): Double;
  254. var
  255. StageRec: TStageRecord;
  256. begin
  257. StageRec := TProjectData(FProjectData).PhaseData.StageData.StageRecord(ABillsID);
  258. if Assigned(StageRec) then
  259. Result := StageRec.GatherQuantity.AsFloat
  260. else
  261. Result := 0;
  262. end;
  263. var
  264. idx: TsdIndex;
  265. DetailGL: TDetailGLRecord;
  266. fBillsQuantity: Double;
  267. iBillsID, iRec: Integer;
  268. begin
  269. if TProjectData(FProjectData).PhaseData.StageDataReadOnly then Exit;
  270. idx := sddDetailGL.FindIndex('idxBillsID');
  271. iBillsID := -1;
  272. for iRec := 0 to idx.RecordCount - 1 do
  273. begin
  274. DetailGL := TDetailGLRecord(idx.Records[iRec]);
  275. if iBillsID <> DetailGL.BillsID.AsInteger then
  276. begin
  277. iBillsID := DetailGL.BillsID.AsInteger;
  278. fBillsQuantity := GetBillsQuantity(iBillsID);
  279. end;
  280. if DetailGL.LastBillsQuantity.AsFloat <> fBillsQuantity then
  281. DetailGL.LastBillsQuantity.AsFloat := fBillsQuantity;
  282. end;
  283. end;
  284. procedure TDetailGLData.sddDetailGLBeforeDeleteRecord(
  285. ARecord: TsdDataRecord; var Allow: Boolean);
  286. begin
  287. Allow := TDetailGLRecord(ARecord).LockedPhaseID.AsInteger = 0;
  288. if not Allow then
  289. ErrorMessage('当前调差工料已被锁定,不可删除。');
  290. end;
  291. procedure TDetailGLData.sddDetailGLBeforeValueChange(AValue: TsdValue;
  292. const NewValue: Variant; var Allow: Boolean);
  293. begin
  294. if SameText(AValue.FieldName, 'Quantity') then
  295. begin
  296. if TDetailGLRecord(AValue.Owner).LockedPhaseID.AsInteger > 0 then
  297. DataSetErrorMessage(Allow, '当前调差工料已被锁定,不可修改数量。');
  298. end;
  299. end;
  300. function TDetailGLData.HasLockedDetailGL(ABillsID: Integer): Boolean;
  301. var
  302. idx: TsdIndex;
  303. iFirst, iLast, iRec: Integer;
  304. Rec: TDetailGLRecord;
  305. begin
  306. Result := False;
  307. idx := sddDetailGL.FindIndex('idxBillsID');
  308. iFirst := idx.FindKeyIndex(ABillsID);
  309. if iFirst > -1 then
  310. begin
  311. iLast := idx.FindKeyLastIndex(ABillsID);
  312. for iRec := iFirst to iLast do
  313. begin
  314. Rec := TDetailGLRecord(idx.Records[iRec]);
  315. if Rec.LockedPhaseID.AsInteger > 0 then
  316. begin
  317. Result := True;
  318. Break;
  319. end;
  320. end;
  321. end;
  322. end;
  323. end.