DetailGLDm.pas 9.6 KB

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