DealPaymentDm.pas 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806
  1. unit DealPaymentDm;
  2. interface
  3. uses
  4. SysUtils, Classes, sdDB, sdProvider, ADODB, FormulaCalc, UtilMethods;
  5. type
  6. TDealPaymentData = class(TDataModule)
  7. sdpDealPayment: TsdADOProvider;
  8. sddDealPayment: TsdDataSet;
  9. sdvDealPayment: TsdDataView;
  10. procedure sddDealPaymentAfterAddRecord(ARecord: TsdDataRecord);
  11. procedure sdvDealPaymentGetText(var Text: String;
  12. ARecord: TsdDataRecord; AValue: TsdValue; AColumn: TsdViewColumn;
  13. DisplayText: Boolean);
  14. procedure sdvDealPaymentNeedLookupRecord(ARecord: TsdDataRecord;
  15. AColumn: TsdViewColumn; ANewText: String);
  16. procedure sdvDealPaymentSetText(var Text: string;
  17. ARecord: TsdDataRecord; AValue: TsdValue; AColumn: TsdViewColumn;
  18. var Allow: Boolean);
  19. procedure sddDealPaymentBeforeAddRecord(ARecord: TsdDataRecord;
  20. var Allow: Boolean);
  21. procedure sddDealPaymentAfterValueChanged(AValue: TsdValue);
  22. procedure sddDealPaymentBeforeDeleteRecord(ARecord: TsdDataRecord;
  23. var Allow: Boolean);
  24. procedure sdvDealPaymentBeforeAddRecord(ARecord: TsdDataRecord;
  25. var Allow: Boolean);
  26. private
  27. FProjectData: TObject;
  28. FPayFormula: TPayFormula;
  29. procedure InitPredefinedPayItems;
  30. procedure RepairSerialNo;
  31. procedure RepairLockedFormula;
  32. function GetNewID: Integer;
  33. function GetNewSerialNo: Integer;
  34. function GetAddTotalPrice: Double;
  35. function GetCutTotalPrice: Double;
  36. function GetPaidTotalPrice: Double;
  37. public
  38. constructor Create(AProjectData: TObject);
  39. destructor Destroy; override;
  40. procedure Open(AConnection: TADOConnection);
  41. procedure Close;
  42. procedure Save;
  43. procedure Init;
  44. // 扣款项是否已达起扣金额
  45. function CheckStartedPrice(AID: Integer): Boolean;
  46. function CheckReachPlan(ARec: TsdDataRecord): Boolean;
  47. function GetAllowTotalPrice(AID: Integer; ATotalPrice, APreTotalPrice: Double): Double;
  48. procedure UpdateTotalPrice(AID: Integer; ATotalPrice: Double);
  49. procedure SetTotalPrice(AID: Integer; ATotalPrice: Double);
  50. function DealPayRecord(const AName: string): TsdDataRecord;
  51. function PlanStr(ARec: TsdDataRecord): string;
  52. function GetStartedPrice(AID: Integer): Double;
  53. procedure CalcStarted_RangePrice;
  54. procedure ResetPhaseLink;
  55. procedure LockedData;
  56. procedure UpdateLinkSerialNo;
  57. property ProjectData: TObject read FProjectData;
  58. // 扣款项,累计金额合计
  59. property CutTotalPrice: Double read GetCutTotalPrice;
  60. // 非扣款项,累计金额合计
  61. property AddTotalPrice: Double read GetAddTotalPrice;
  62. // 实付
  63. property PaidTotalPrice: Double read GetPaidTotalPrice;
  64. property PayFormula: TPayFormula read FPayFormula;
  65. end;
  66. implementation
  67. uses
  68. ProjectData, PhasePayDm, PhaseData, ZhAPI, BillsDm, Math, Variants,
  69. ProjectProperty;
  70. {$R *.dfm}
  71. { TDealPaymentData }
  72. function TDealPaymentData.CheckStartedPrice(AID: Integer): Boolean;
  73. var
  74. Rec: TsdDataRecord;
  75. begin
  76. Rec := sddDealPayment.FindKey('idxID', AID);
  77. with TProjectData(FProjectData).BillsData do
  78. begin
  79. if (Rec.ValueByName('StartedPrice').AsFloat = 0) then
  80. Result := True
  81. else
  82. Result := Settlement[AddGatherIndex] >= Rec.ValueByName('StartedPrice').AsFloat;
  83. end;
  84. end;
  85. constructor TDealPaymentData.Create(AProjectData: TObject);
  86. begin
  87. inherited Create(nil);
  88. FProjectData := AProjectData;
  89. FPayFormula := TPayFormula.Create(FProjectData);
  90. with TProjectData(FProjectData) do
  91. FPayFormula.Decimal := ProjProperties.DecimalManager.DealPay;
  92. end;
  93. destructor TDealPaymentData.Destroy;
  94. begin
  95. FPayFormula.Free;
  96. inherited;
  97. end;
  98. function TDealPaymentData.GetAllowTotalPrice(AID: Integer;
  99. ATotalPrice, APreTotalPrice: Double): Double;
  100. var
  101. Rec: TsdDataRecord;
  102. fAllowPrice: Double;
  103. begin
  104. Result := ATotalPrice;
  105. Rec := sddDealPayment.FindKey('idxID', AID);
  106. if Rec.ValueByName('RangePrice').AsFloat = 0 then Exit;
  107. fAllowPrice := Rec.ValueByName('RangePrice').AsFloat - APreTotalPrice;
  108. if not CheckReachPlan(Rec) then
  109. Result := Min(fAllowPrice, ATotalPrice)
  110. else
  111. Result := fAllowPrice;
  112. end;
  113. function TDealPaymentData.GetNewID: Integer;
  114. var
  115. idx: TsdIndex;
  116. begin
  117. idx := sddDealPayment.FindIndex('idxID');
  118. if idx.RecordCount > 0 then
  119. Result := idx.Records[idx.RecordCount - 1].ValueByName('ID').AsInteger + 1
  120. else
  121. Result := 1;
  122. end;
  123. procedure TDealPaymentData.Init;
  124. begin
  125. if sddDealPayment.RecordCount > 0 then Exit;
  126. InitPredefinedPayItems;
  127. end;
  128. procedure TDealPaymentData.InitPredefinedPayItems;
  129. procedure AddPredefinedPayItem(const AItem: string);
  130. var
  131. sgsItem: TStrings;
  132. f: Double;
  133. Rec: TsdDataRecord;
  134. begin
  135. sgsItem := TStringList.Create;
  136. try
  137. sgsItem.Delimiter := ';';
  138. sgsItem.DelimitedText := AItem;
  139. if sgsItem.Count < 7 then Exit;
  140. Rec := sddDealPayment.Add;
  141. Rec.ValueByName('Name').AsString := sgsItem[0];
  142. Rec.ValueByName('CalcType').AsInteger := StrToIntDef(sgsItem[1], 0);
  143. Rec.ValueByName('IsMinus').AsBoolean := sgsItem[2] = '1';
  144. if TryStrToFloat(sgsItem[3], f) then
  145. Rec.ValueByName('StartedPrice').AsFloat := f
  146. else
  147. Rec.ValueByName('SFormula').AsString := sgsItem[3];
  148. if TryStrToFloat(sgsItem[4], f) then
  149. Rec.ValueByName('RangePrice').AsFloat := f
  150. else
  151. Rec.ValueByName('RFormula').AsString := sgsItem[4];
  152. Rec.ValueByName('Formula').AsString := sgsItem[5];
  153. if SameText(sgsItem[5], 'bqwc') then
  154. Rec.ValueByName('LockedFormula').AsBoolean := True;
  155. Rec.ValueByName('PreDefined').AsBoolean := StrToBoolDef(sgsItem[6], False);
  156. finally
  157. sgsItem.Free;
  158. end;
  159. end;
  160. var
  161. sgsItems: TStrings;
  162. I: Integer;
  163. begin
  164. sgsItems := TStringList.Create;
  165. try
  166. sgsItems.LoadFromFile(GetAppFilePath + 'DealPayment.txt');
  167. for I := 0 to sgsItems.Count - 1 do
  168. if sgsItems[I] <> '' then
  169. AddPredefinedPayItem(sgsItems[I]);
  170. finally
  171. sgsItems.Free;
  172. end;
  173. end;
  174. procedure TDealPaymentData.LockedData;
  175. var
  176. iIndex: Integer;
  177. Rec: TsdDataRecord;
  178. begin
  179. for iIndex := 0 to sddDealPayment.RecordCount - 1 do
  180. begin
  181. Rec := sddDealPayment.Records[iIndex];
  182. Rec.ValueByName('Locked').AsBoolean := True;
  183. if Rec.ValueByName('Formula').AsString <> '' then
  184. Rec.ValueByName('LockedFormula').AsBoolean := True;
  185. end;
  186. end;
  187. procedure TDealPaymentData.Open(AConnection: TADOConnection);
  188. begin
  189. sdpDealPayment.Connection := AConnection;
  190. sddDealPayment.Open;
  191. RepairSerialNo;
  192. RepairLockedFormula;
  193. if not Assigned(sddDealPayment.IndexList.FindByName('idxID')) then
  194. sddDealPayment.AddIndex('idxID', 'ID');
  195. if not Assigned(sddDealPayment.IndexList.FindByName('idxView')) then
  196. sddDealPayment.AddIndex('idxView', 'SerialNo');
  197. // 开始计量前,CutTotalPrice链接至TotalPrice,已解决无计量数据时无法输入问题
  198. sddDealPayment.FieldByName('TotalPrice').ValidChars := sddDealPayment.FieldByName('TotalPrice').ValidChars + ArithmeticCharSet + ExprsBaseCharSet;
  199. sddDealPayment.FieldByName('StartedPrice').ValidChars := sddDealPayment.FieldByName('StartedPrice').ValidChars + ArithmeticCharSet + ExprsExceptCharSet;
  200. sddDealPayment.FieldByName('RangePrice').ValidChars := sddDealPayment.FieldByName('RangePrice').ValidChars + ArithmeticCharSet + ExprsExceptCharSet;
  201. sdvDealPayment.Open;
  202. sdvDealPayment.IndexName := 'idxView';
  203. end;
  204. procedure TDealPaymentData.ResetPhaseLink;
  205. begin
  206. with TProjectData(FProjectData).PhaseData do
  207. begin
  208. sdvDealPayment.Columns.FindColumn('CurTotalPrice').LookupDataSet := PhasePayData.sddPhasePay;
  209. sdvDealPayment.Columns.FindColumn('CurTotalPrice').LookupResultField := 'TotalPrice' + IntToStr(StageIndex);
  210. sdvDealPayment.Columns.FindColumn('EndTotalPrice').LookupDataSet := PhasePayData.sddPhasePay;
  211. sdvDealPayment.Columns.FindColumn('EndTotalPrice').LookupResultField := 'EndTotalPrice' + IntToStr(StageIndex);
  212. end;
  213. end;
  214. procedure TDealPaymentData.Save;
  215. begin
  216. sddDealPayment.Save;
  217. end;
  218. procedure TDealPaymentData.sddDealPaymentAfterAddRecord(
  219. ARecord: TsdDataRecord);
  220. var
  221. iSerialNo: Integer;
  222. begin
  223. iSerialNo := GetNewSerialNo;
  224. ARecord.ValueByName('ID').AsInteger := GetNewID;
  225. ARecord.ValueByName('SerialNo').AsInteger := iSerialNo;
  226. ARecord.ValueByName('CreatePhaseID').AsInteger := TProjectData(FProjectData).PhaseIndex;
  227. end;
  228. procedure TDealPaymentData.sdvDealPaymentGetText(var Text: String;
  229. ARecord: TsdDataRecord; AValue: TsdValue; AColumn: TsdViewColumn;
  230. DisplayText: Boolean);
  231. procedure GetDisplayText;
  232. begin
  233. if not Assigned(AValue) or
  234. ((Pos('Price', AValue.FieldName) > 0) and (AValue.AsFloat = 0)) then
  235. Text := '';
  236. end;
  237. function GetFormulaField(const APriceField: string): string;
  238. begin
  239. if SameText(APriceField, 'StartedPrice') then
  240. Result := 'SFormula'
  241. else if SameText(APriceField, 'RangePrice') then
  242. Result := 'RFormula'
  243. else if SameText(APriceField, 'CurTotalPrice') then
  244. Result := 'Formula'
  245. else if Pos('TotalPrice', APriceField) = 1 then
  246. Result := StringReplace(AValue.FieldName, 'TotalPrice', 'Formula', []);
  247. end;
  248. procedure GetStageEditText;
  249. var
  250. sField, sFormula: string;
  251. begin
  252. if Assigned(AValue) then
  253. begin
  254. sField := GetFormulaField(AValue.FieldName);
  255. sFormula := AValue.Owner.ValueByName(sField).AsString;
  256. if (sField <> '') and (sFormula <> '') then
  257. Text:= sFormula;
  258. end
  259. else
  260. Text := '';
  261. end;
  262. procedure GetMainEditText;
  263. var
  264. sField, sFormula: string;
  265. begin
  266. sField := GetFormulaField(AColumn.FieldName);
  267. if (sField <> '') then
  268. begin
  269. sFormula := ARecord.ValueByName(sField).AsString;
  270. if (sFormula <> '') then
  271. Text := sFormula;
  272. end
  273. else
  274. Text := '';
  275. end;
  276. begin
  277. if Pos('Price', AColumn.FieldName)> 0 then
  278. begin
  279. if DisplayText then
  280. GetDisplayText
  281. else if TProjectData(FProjectData).PhaseIndex > 0 then
  282. GetStageEditText
  283. else
  284. GetMainEditText;
  285. end;
  286. end;
  287. procedure TDealPaymentData.sdvDealPaymentNeedLookupRecord(
  288. ARecord: TsdDataRecord; AColumn: TsdViewColumn; ANewText: String);
  289. procedure SetNewRecData(APayRec: TsdDataRecord);
  290. var
  291. iID: Integer;
  292. sTPField, sFField: string;
  293. fTotalPrice, fAllow: Double;
  294. begin
  295. sTPField := 'TotalPrice' + IntToStr(TProjectData(FProjectData).PhaseData.StageIndex);
  296. sFField := 'Formula' + IntToStr(TProjectData(FProjectData).PhaseData.StageIndex);
  297. if CheckNumeric(ANewText) then
  298. begin
  299. APayRec.ValueByName(sFField).AsString := ANewText;
  300. fTotalPrice := StrToFloat(ANewText);
  301. end
  302. else
  303. begin
  304. APayRec.ValueByName(sFField).AsString := ANewText;
  305. ARecord.ValueByName('Formula').AsString := ANewText;
  306. fTotalPrice := FPayFormula.Calculate(ANewText, ARecord.ValueByName('StartedPrice').AsFloat);
  307. end;
  308. iID := ARecord.ValueByName('ID').AsInteger;
  309. if CheckStartedPrice(iID) then
  310. begin
  311. fAllow := GetAllowTotalPrice(iID, fTotalPrice, 0);
  312. APayRec.ValueByName(sTPField).AsFloat := fAllow;
  313. if fAllow < fTotalPrice then
  314. TipMessage(Format('“%s”已达扣款限额,本期金额计%s。', [ARecord.ValueByName('Name').AsString, FloatToStr(fAllow)]))
  315. else if fAllow > fTotalPrice then
  316. TipMessage(Format('“%s”已达计提期限,本期金额计%s。', [ARecord.ValueByName('Name').AsString, FloatToStr(fAllow)]));
  317. end
  318. else
  319. TipMessage(Format('“%s”未达到起扣金额,本期金额计零。', [ARecord.ValueByName('Name').AsString]));
  320. end;
  321. var
  322. NewRec: TsdDataRecord;
  323. begin
  324. if SameText(AColumn.FieldName, 'CurTotalPrice') then
  325. begin
  326. with TProjectData(FProjectData).PhaseData.PhasePayData do
  327. NewRec := AddPayRecord(ARecord.ValueByName('ID').AsInteger);
  328. SetNewRecData(NewRec);
  329. end;
  330. end;
  331. procedure TDealPaymentData.sdvDealPaymentSetText(var Text: string;
  332. ARecord: TsdDataRecord; AValue: TsdValue; AColumn: TsdViewColumn;
  333. var Allow: Boolean);
  334. procedure CheckLockedData;
  335. var
  336. Rec: TsdDataRecord;
  337. sFormula: string;
  338. begin
  339. Rec := ARecord;//sddDealPayment.FindKey('idxID', ARecord.ValueByName('ID').AsInteger);
  340. if Rec.ValueByName('CalcType').AsInteger = 1 then
  341. begin
  342. if SameText(AValue.FieldName, 'Name') or
  343. SameText(AValue.FieldName, 'IsMinus') or
  344. (Pos('TotalPrice', AValue.FieldName) > 0) or
  345. SameText(AValue.FieldName, 'StartedPrice') or
  346. SameText(AValue.FieldName, 'RangePrice') then
  347. DataSetErrorMessage(Allow, '固定项不可修改!');
  348. end;
  349. if not Allow then Exit;
  350. if Rec.ValueByName('LockedFormula').AsBoolean then
  351. begin
  352. if (Pos('TotalPrice', AValue.FieldName) = 1) and
  353. (Rec.ValueByName('Formula').AsString <> '') and
  354. (Rec.ValueByName('CalcType').AsInteger <> 2) then
  355. begin
  356. // 如果有公式计算,如果是纯数学计算式,则可设置,基数计算,则不可
  357. sFormula := Rec.ValueByName('Formula').AsString;
  358. if (Pos('bqwc', sFormula)>0) or (Pos('htj', sFormula)>0) or
  359. (Pos('kgyfk', sFormula)>0) or (Pos('clyfk', sFormula)>0) then
  360. DataSetErrorMessage(Allow, '该支付(扣款)项已设置基数计算公式且被锁定,不可修改!');
  361. end;
  362. end;
  363. if not Allow then Exit;
  364. if Rec.ValueByName('Locked').AsBoolean then
  365. begin
  366. if SameText(AValue.FieldName, 'StartedPrice') then
  367. DataSetErrorMessage(Allow, '该支付(扣款)项的起扣金额被锁定,不可修改!')
  368. else if SameText(AValue.FieldName, 'RangePrice') then
  369. DataSetErrorMessage(Allow, '该支付(扣款)项的付(扣)款限额被锁定,不可修改!')
  370. else if SameText(AValue.FieldName, 'Name') or SameText(AValue.FieldName, 'IsMinus') then
  371. DataSetErrorMessage(Allow, '该项已被锁定,不可修改!');
  372. end;
  373. end;
  374. procedure DoStartedPriceChanged;
  375. begin
  376. if AValue.Owner.ValueByName('TotalPrice').AsFloat <> 0 then
  377. DataSetErrorMessage(Allow, '该付(扣)款金额已经计量,不可修改起扣金额!');
  378. if not Allow then Exit;
  379. if CheckStringNull(Text) or CheckNumeric(Text) then
  380. AValue.Owner.ValueByName('SFormula').AsString := ''
  381. else if Pos('bqwc', Text) = 0 then
  382. begin
  383. AValue.Owner.ValueByName('SFormula').AsString := Text;
  384. Text := FloatToStr(FPayFormula.Calculate(Text));
  385. end
  386. else
  387. DataSetErrorMessage(Allow, '起扣金额不可引用“本期计算价”进行计算!');
  388. end;
  389. procedure DoRangePriceChanged;
  390. begin
  391. if AValue.Owner.ValueByName('TotalPrice').AsFloat <> 0 then
  392. DataSetErrorMessage(Allow, '该付(扣)款金额已经计量,不可修改付(扣)款限额!');
  393. if not Allow then Exit;
  394. if CheckStringNull(Text) or CheckNumeric(Text) then
  395. AValue.Owner.ValueByName('RFormula').AsString := ''
  396. else if Pos('bqwc', Text) = 0 then
  397. begin
  398. AValue.Owner.ValueByName('RFormula').AsString := Text;
  399. Text := FloatToStr(FPayFormula.Calculate(Text));
  400. end
  401. else
  402. DataSetErrorMessage(Allow, '付(扣)款限额不可引用“本期计算价”进行计算!');
  403. end;
  404. procedure DoCurTotalPriceChanged;
  405. var
  406. iID: Integer;
  407. sFField, sPreField: string;
  408. fTotalPrice, fAllow: Double;
  409. Rec: TsdDataRecord;
  410. begin
  411. Rec := ARecord;//sddDealPayment.FindKey('idxID', ARecord.ValueByName('ID').AsInteger);
  412. sFField := StringReplace(AValue.FieldName, 'TotalPrice', 'Formula', []);
  413. if CheckStringNull(Text) or CheckNumeric(Text) then
  414. begin
  415. Rec.ValueByName('Formula').AsString := '';
  416. AValue.Owner.ValueByName(sFField).AsString := Text;
  417. fTotalPrice := StrToFloatDef(Text, 0);
  418. end
  419. else
  420. begin
  421. Rec.ValueByName('Formula').AsString := Text;
  422. AValue.Owner.ValueByName(sFField).AsString := Text;
  423. if AValue.Owner.ValueByName('Pre' + AValue.FieldName).AsFloat = 0 then
  424. fTotalPrice := FPayFormula.Calculate(Text, Rec.ValueByName('StartedPrice').AsFloat)
  425. else
  426. fTotalPrice := FPayFormula.Calculate(Text);
  427. end;
  428. if AValue.Owner.ValueByName('StopCalc').AsBoolean then
  429. begin
  430. fTotalPrice := 0;
  431. Text := '';
  432. end
  433. else
  434. begin
  435. iID := ARecord.ValueByName('ID').AsInteger;
  436. if CheckStartedPrice(iID) then
  437. begin
  438. sPreField := StringReplace(AValue.FieldName, 'TotalPrice', 'PreTotalPrice', []);
  439. fAllow := GetAllowTotalPrice(iID, fTotalPrice, AValue.Owner.ValueByName(sPreField).AsFloat);
  440. Text := FloatToStr(fAllow);
  441. if fAllow < fTotalPrice then
  442. TipMessage(Format('“%s”已达扣款限额,本期金额计%s。', [Rec.ValueByName('Name').AsString, Text]))
  443. else if fAllow > fTotalPrice then
  444. TipMessage(Format('“%s”已达计提期限,本期金额计%s。', [Rec.ValueByName('Name').AsString, Text]));
  445. end
  446. else
  447. begin
  448. Text := '';
  449. TipMessage(Format('“%s”未达到起扣金额,本期金额计零。', [Rec.ValueByName('Name').AsString]));
  450. end;
  451. end;
  452. end;
  453. procedure DoLedgerFormulaChanged;
  454. begin
  455. if CheckStringNull(Text) or CheckNumeric(Text) then
  456. ARecord.ValueByName('Formula').AsString := ''
  457. else
  458. ARecord.ValueByName('Formula').AsString := Text;
  459. Text := '';
  460. end;
  461. begin
  462. if not Assigned(AValue) then Exit;
  463. Text := Trim(Text);
  464. if SameText('Name', AValue.FieldName) and (Text = '') then
  465. begin
  466. ErrorMessage('合同支付项名称不允许为空,如需删除,请点击右键进行删除');
  467. Allow := False;
  468. Exit;
  469. end;
  470. CheckLockedData;
  471. if not Allow then Exit;
  472. if SameText('StartedPrice', AValue.FieldName) then
  473. DoStartedPriceChanged;
  474. if SameText('RangePrice', AValue.FieldName) then
  475. DoRangePriceChanged;
  476. if SameText('CurTotalPrice', AColumn.FieldName) then
  477. if TProjectData(FProjectData).ProjProperties.PhaseCount > 0 then
  478. DoCurTotalPriceChanged
  479. else
  480. DoLedgerFormulaChanged;
  481. end;
  482. procedure TDealPaymentData.UpdateTotalPrice(AID: Integer;
  483. ATotalPrice: Double);
  484. var
  485. Rec: TsdDataRecord;
  486. begin
  487. Rec := sddDealPayment.FindKey('idxID', AID);
  488. Rec.ValueByName('TotalPrice').AsFloat := Rec.ValueByName('TotalPrice').AsFloat + ATotalPrice;
  489. end;
  490. procedure TDealPaymentData.sddDealPaymentBeforeAddRecord(
  491. ARecord: TsdDataRecord; var Allow: Boolean);
  492. begin
  493. { if ARecord.ValueByName('Name').AsString = '' then
  494. Allow := False;}
  495. end;
  496. procedure TDealPaymentData.CalcStarted_RangePrice;
  497. var
  498. I: Integer;
  499. Rec: TsdDataRecord;
  500. begin
  501. with TProjectData(FProjectData).ProjProperties do
  502. if (PhaseCount > 1) or ((PhaseCount = 1) and (AuditStatus <> 0)) then Exit;
  503. for I := 0 to sddDealPayment.RecordCount - 1 do
  504. begin
  505. Rec := sddDealPayment.Records[I];
  506. if Rec.ValueByName('CalcType').AsInteger <> 0 then Continue;
  507. if Rec.ValueByName('SFormula').AsString <> '' then
  508. Rec.ValueByName('StartedPrice').AsFloat := FPayFormula.Calculate(Rec.ValueByName('SFormula').AsString);
  509. if Rec.ValueByName('RFormula').AsString <> '' then
  510. Rec.ValueByName('RangePrice').AsFloat := FPayFormula.Calculate(Rec.ValueByName('RFormula').AsString);
  511. end;
  512. end;
  513. procedure TDealPaymentData.sddDealPaymentAfterValueChanged(
  514. AValue: TsdValue);
  515. begin
  516. if SameText('IsMinus', AValue.FieldName) then
  517. TProjectData(FProjectData).PhaseData.PhasePayData.CalculateCurPay;
  518. end;
  519. function TDealPaymentData.GetAddTotalPrice: Double;
  520. var
  521. iIndex: Integer;
  522. Rec: TsdDataRecord;
  523. begin
  524. Result := 0;
  525. for iIndex := 0 to sddDealPayment.RecordCount - 1 do
  526. begin
  527. Rec := sddDealPayment.Records[iIndex];
  528. if (Rec.ValueByName('CalcType').AsInteger = 0) and not Rec.ValueByName('IsMinus').AsBoolean then
  529. Result := Result + Rec.ValueByName('TotalPrice').AsFloat;
  530. end;
  531. end;
  532. function TDealPaymentData.GetCutTotalPrice: Double;
  533. var
  534. iIndex: Integer;
  535. Rec: TsdDataRecord;
  536. begin
  537. Result := 0;
  538. for iIndex := 0 to sddDealPayment.RecordCount - 1 do
  539. begin
  540. Rec := sddDealPayment.Records[iIndex];
  541. if (Rec.ValueByName('CalcType').AsInteger = 0) and Rec.ValueByName('IsMinus').AsBoolean then
  542. Result := Result + Rec.ValueByName('TotalPrice').AsFloat;
  543. end;
  544. end;
  545. function TDealPaymentData.GetPaidTotalPrice: Double;
  546. var
  547. Rec: TsdDataRecord;
  548. begin
  549. Rec := sddDealPayment.Locate('CalcType', 2);
  550. if Assigned(Rec) then
  551. Result := Rec.ValueByName('TotalPrice').AsFloat
  552. else
  553. Result := 0;
  554. end;
  555. procedure TDealPaymentData.sddDealPaymentBeforeDeleteRecord(
  556. ARecord: TsdDataRecord; var Allow: Boolean);
  557. begin
  558. if ARecord.ValueByName('Locked').AsBoolean then
  559. DataSetErrorMessage(Allow, '该支付(扣款)项已锁定,不可删除!')
  560. else if ARecord.ValueByName('PreDefined').AsBoolean then
  561. DataSetErrorMessage(Allow, '此项为预定义项,不允许删除!')
  562. else if ARecord.ValueByName('TotalPrice').AsFloat <> 0 then
  563. DataSetErrorMessage(Allow, '该支付(扣款)项存在数据,如需删除请先清除本期金额!');
  564. if Allow and TProjectData(FProjectData).PhaseData.Active then
  565. TProjectData(FProjectData).PhaseData.PhasePayData.Delete(ARecord.ValueByName('ID').AsInteger);
  566. end;
  567. procedure TDealPaymentData.Close;
  568. begin
  569. sddDealPayment.Close;
  570. end;
  571. procedure TDealPaymentData.RepairSerialNo;
  572. var
  573. Rec: TsdDataRecord;
  574. iRec: Integer;
  575. begin
  576. if sddDealPayment.RecordCount = 0 then Exit;
  577. Rec := sddDealPayment.Records[0];
  578. if Rec.ValueByName('SerialNo').AsString = '' then
  579. begin
  580. for iRec := 0 to sddDealPayment.RecordCount - 1 do
  581. begin
  582. Rec := sddDealPayment.Records[iRec];
  583. Rec.ValueByName('SerialNo').AsInteger := iRec;
  584. end;
  585. end;
  586. end;
  587. function TDealPaymentData.GetNewSerialNo: Integer;
  588. var
  589. idx: TsdIndex;
  590. begin
  591. idx := sddDealPayment.FindIndex('idxView');
  592. if idx.RecordCount > 0 then
  593. Result := idx.Records[idx.RecordCount - 1].ValueByName('SerialNo').AsInteger + 1
  594. else
  595. Result := 1;
  596. end;
  597. procedure TDealPaymentData.RepairLockedFormula;
  598. function CheckHasRepair: Boolean;
  599. var
  600. iRec: Integer;
  601. Rec: TsdDataRecord;
  602. begin
  603. Result := True;
  604. for iRec := 0 to sddDealPayment.RecordCount - 1 do
  605. begin
  606. Rec := sddDealPayment.Records[iRec];
  607. if Rec.ValueByName('Locked').AsBoolean and
  608. (Rec.ValueByName('Formula').AsString <> '') and (Rec.ValueByName('LockedFormula').AsBoolean) then
  609. begin
  610. Result := False;
  611. Break;
  612. end;
  613. end;
  614. end;
  615. var
  616. iRec: Integer;
  617. Rec: TsdDataRecord;
  618. begin
  619. if sddDealPayment.RecordCount = 0 then Exit;
  620. if CheckHasRepair then
  621. begin
  622. for iRec := 0 to sddDealPayment.RecordCount - 1 do
  623. begin
  624. Rec := sddDealPayment.Records[iRec];
  625. if Rec.ValueByName('Locked').AsBoolean and (Rec.ValueByName('Formula').AsString <> '') then
  626. Rec.ValueByName('LockedFormula').AsBoolean := True;
  627. end;
  628. end;
  629. end;
  630. function TDealPaymentData.GetStartedPrice(AID: Integer): Double;
  631. var
  632. Rec: TsdDataRecord;
  633. begin
  634. Rec := sddDealPayment.FindKey('idxID', AID);
  635. Result := Rec.ValueByName('StartedPrice').AsFloat;
  636. end;
  637. function TDealPaymentData.CheckReachPlan(ARec: TsdDataRecord): Boolean;
  638. var
  639. fCurValue, fDeadlineValue: Double;
  640. begin
  641. Result := False;
  642. if ARec.ValueByName('PlanType').AsInteger <> 0 then
  643. begin
  644. if ARec.ValueByName('PlanType').AsInteger = 1 then
  645. fCurValue := TProjectData(FProjectData).ProjProperties.PhaseCount
  646. else if ARec.ValueByName('PlanSubType').AsInteger = 0 then
  647. fCurValue := TProjectData(FProjectData).BillsData.Settlement[4]
  648. else if ARec.ValueByName('PlanSubType').AsInteger = 1 then
  649. fCurValue := TProjectData(FProjectData).BillsData.Settlement[1]
  650. else if ARec.ValueByName('PlanSubType').AsInteger = 2 then
  651. fCurValue := TProjectData(FProjectData).BillsData.Settlement[2];
  652. fDeadlineValue := ARec.ValueByName('PlanDeadline').AsFloat;
  653. Result := fCurValue >= fDeadlineValue;
  654. end;
  655. end;
  656. function TDealPaymentData.PlanStr(ARec: TsdDataRecord): string;
  657. begin
  658. if ARec.ValueByName('PlanType').AsInteger = 0 then
  659. Result := '无'
  660. else if ARec.ValueByName('PlanType').AsInteger = 1 then
  661. Result := Format('计量期数 >= %d', [ARec.ValueByName('PlanDeadline').AsInteger])
  662. else if ARec.ValueByName('PlanSubType').AsInteger = 0 then
  663. Result := Format('累计完成计量金额 >= %f', [ARec.ValueByName('PlanDeadline').AsFloat])
  664. else if ARec.ValueByName('PlanSubType').AsInteger = 1 then
  665. Result := Format('累计合同计量金额 >= %f', [ARec.ValueByName('PlanDeadline').AsFloat])
  666. else if ARec.ValueByName('PlanSubType').AsInteger = 2 then
  667. Result := Format('累计变更计量金额 >= %f', [ARec.ValueByName('PlanDeadline').AsFloat]);
  668. end;
  669. procedure TDealPaymentData.UpdateLinkSerialNo;
  670. var
  671. iPay, iCut, iIndex: Integer;
  672. Rec: TsdDataRecord;
  673. begin
  674. iPay := 1;
  675. iCut := 1;
  676. for iIndex := 0 to sdvDealPayment.RecordCount - 1 do
  677. begin
  678. Rec := sdvDealPayment.Records[iIndex];
  679. if Rec.ValueByName('CalcType').AsInteger = 0 then
  680. begin
  681. if Rec.ValueByName('IsMinus').AsBoolean then
  682. begin
  683. Rec.ValueByName('LinkSerialNo').AsInteger := iCut;
  684. Inc(iCut);
  685. end
  686. else
  687. begin
  688. Rec.ValueByName('LinkSerialNo').AsInteger := iPay;
  689. Inc(iPay);
  690. end;
  691. end;
  692. end;
  693. end;
  694. function TDealPaymentData.DealPayRecord(
  695. const AName: string): TsdDataRecord;
  696. var
  697. iRec: Integer;
  698. Rec: TsdDataRecord;
  699. begin
  700. Result := nil;
  701. for iRec := 0 to sddDealPayment.RecordCount - 1 do
  702. begin
  703. Rec := sddDealPayment.Records[iRec];
  704. if SameText(AName, Rec.ValueByName('Name').AsString) then
  705. begin
  706. Result := Rec;
  707. Break;
  708. end;
  709. end;
  710. end;
  711. procedure TDealPaymentData.sdvDealPaymentBeforeAddRecord(
  712. ARecord: TsdDataRecord; var Allow: Boolean);
  713. begin
  714. Allow := VarToStrDef(ARecord.ValueByName('Name').CachedValue, '') <> '';
  715. end;
  716. procedure TDealPaymentData.SetTotalPrice(AID: Integer;
  717. ATotalPrice: Double);
  718. var
  719. Rec: TsdDataRecord;
  720. begin
  721. Rec := sddDealPayment.FindKey('idxID', AID);
  722. Rec.ValueByName('TotalPrice').AsFloat := ATotalPrice;
  723. end;
  724. end.