unit DetailGLDm; interface uses SysUtils, Classes, sdDB, sdProvider, ADODB, Variants, mDataRecord; type TDetailGLData = class(TDataModule) sdpDetailGL: TsdADOProvider; sddDetailGL: TsdDataSet; procedure sddDetailGLGetRecordClass(var ARecordClass: TsdRecordClass); procedure sddDetailGLBeforeDeleteRecord(ARecord: TsdDataRecord; var Allow: Boolean); procedure sddDetailGLBeforeValueChange(AValue: TsdValue; const NewValue: Variant; var Allow: Boolean); private FProjectData: TObject; procedure LoadRelaProjectGL; function FindDetailGL(ABillsID, AGLID: Integer): TDetailGLRecord; procedure ClearDetailGLs(ABillsID: Integer); public constructor Create(AProjectData: TObject); destructor Destroy; override; procedure Open(AConnection: TADOConnection); procedure Close; procedure Save; procedure SaveCacheData; function AddDetailGL(ABillsID: Integer; AProjectGLRec: TProjectGLRecord; var sMessage: string): TDetailGLRecord; procedure AddDetailGLs(ABillsID: Integer; AGLs: TList); procedure LoadDetailGLs(ABillsID: Integer; AGLs: TList); function HasLockedDetailGL(ABillsID: Integer): Boolean; procedure ResetDetailGLs(ABillsID: Integer; AGLs: TList); procedure LoadProjectGL_DetailGLs(AGLID: Integer; AGLs: TList); function GetUnitPriceMargin(ABillsID: Integer): Double; property ProjectData: TObject read FProjectData write FProjectData; end; implementation uses Math, UtilMethods, ProjectData, ProjectProperty, ProjectGLDm, PriceMarginBillsDm, StageDm, PhasePayDm; {$R *.dfm} { TDetailGLData } function TDetailGLData.AddDetailGL(ABillsID: Integer; AProjectGLRec: TProjectGLRecord; var sMessage: string): TDetailGLRecord; begin sMessage := ''; Result := FindDetailGL(ABillsID, AProjectGLRec.ID.AsInteger); if not Assigned(Result) then begin Result := TDetailGLRecord(sddDetailGL.Add(True)); Result.ID.AsInteger := GetsdDataSetNewID(sddDetailGL, 'idxID'); Result.BillsID.AsInteger := ABillsID; Result.GLID.AsInteger := AProjectGLRec.ID.AsInteger; Result.Code.AsString := AProjectGLRec.Code.AsString; Result.CreatePhaseID.AsInteger := TProjectData(FProjectData).ProjProperties.PhaseCount; Result.RelaProjectGL := AProjectGLRec; Result.EndUpdate; end else sMessage := Format('编号:%s 名称:%s', [AProjectGLRec.Code.AsString, AProjectGLRec.Name.AsString]); end; procedure TDetailGLData.AddDetailGLs(ABillsID: Integer; AGLs: TList); var i: Integer; sHint, sMessage: string; begin sHint := ''; for i := 0 to AGLs.Count - 1 do begin AddDetailGL(ABillsID, TProjectGLRecord(AGLs.Items[i]), sMessage); if sMessage <> '' then begin if sHint <> '' then sHint := sHint + #13#10; sHint := sHint + sMessage; end; end; if sHint <> '' then TipMessage('以下工料已添加至该清单,请勿重复添加:' + #13#10 + sHint); end; procedure TDetailGLData.ResetDetailGLs(ABillsID: Integer; AGLs: TList); var i, iNewID: Integer; Rec, GLRec: TDetailGLRecord; begin if HasLockedDetailGL(ABillsID) then Exit; ClearDetailGLs(ABillsID); sddDetailGL.BeginUpdate; try iNewID := GetsdDataSetNewID(sddDetailGL, 'idxID'); for i := 0 to AGLs.Count - 1 do begin GLRec := TDetailGLRecord(AGLs.Items[i]); Rec := TDetailGLRecord(sddDetailGL.Add); Rec.ID.AsInteger := iNewID + i; Rec.BillsID.AsInteger := ABillsID; Rec.GLID.AsInteger := GLRec.GLID.AsInteger; Rec.Code.AsInteger := GLRec.Code.AsInteger; Rec.Quantity.AsFloat := GLRec.Quantity.AsFloat; Rec.CreatePhaseID.AsInteger := TProjectData(FProjectData).ProjProperties.PhaseCount; Rec.RelaProjectGL := GLRec.RelaProjectGL; end; finally sddDetailGL.EndUpdate; end; end; procedure TDetailGLData.ClearDetailGLs(ABillsID: Integer); var idx: TsdIndex; iFirst, iLast, iRec: Integer; begin sddDetailGL.BeginUpdate; try idx := sddDetailGL.FindIndex('idxBillsID'); iFirst := idx.FindKeyIndex(ABillsID); if iFirst <> -1 then begin iLast := idx.FindKeyLastIndex(ABillsID); for iRec := iFirst to iLast do sddDetailGL.Remove(idx.Records[iRec]); end; finally sddDetailGL.EndUpdate; end; end; procedure TDetailGLData.Close; begin sddDetailGL.Close; end; constructor TDetailGLData.Create(AProjectData: TObject); begin inherited Create(nil); FProjectData := AProjectData; sddDetailGL.AddIndex('idxView', 'BillsID;Code'); sddDetailGL.AddIndex('idxFind', 'BillsID;GLID'); sddDetailGL.AddIndex('idxBillsID', 'BillsID'); sddDetailGL.AddIndex('idxID', 'ID'); sddDetailGL.AddIndex('idxGLID', 'GLID'); end; destructor TDetailGLData.Destroy; begin inherited; end; function TDetailGLData.FindDetailGL(ABillsID, AGLID: Integer): TDetailGLRecord; var idx: TsdIndex; begin idx := sddDetailGL.FindIndex('idxFind'); Result := TDetailGLRecord(idx.FindKey(VarArrayOf([ABillsID, AGLID]))); end; procedure TDetailGLData.Open(AConnection: TADOConnection); begin sdpDetailGL.Connection := AConnection; sddDetailGL.Open; // 建立与ProjectGL间的链接,以便计算时,快速获取工料的价格信息 LoadRelaProjectGL; end; procedure TDetailGLData.Save; begin SaveCacheData; sddDetailGL.Save; end; procedure TDetailGLData.LoadDetailGLs(ABillsID: Integer; AGLs: TList); var idx: TsdIndex; iRec, iFirst, iLast: Integer; begin idx := sddDetailGL.FindIndex('idxBillsID'); iFirst := idx.FindKeyIndex(ABillsID); if iFirst <> -1 then begin iLast := idx.FindKeyLastIndex(ABillsID); for iRec := iFirst to iLast do AGLs.Add(idx.Records[iRec]); end; end; function TDetailGLData.GetUnitPriceMargin(ABillsID: Integer): Double; var idx: TsdIndex; iRec, iFirst, iLast: Integer; Rec: TsdDataRecord; begin Result := 0; idx := sddDetailGL.FindIndex('idxBillsID'); iFirst := idx.FindKeyIndex(ABillsID); if iFirst <> -1 then begin iLast := idx.FindKeyLastIndex(ABillsID); for iRec := iFirst to iLast do begin Rec := idx.Records[iRec]; with TProjectData(FProjectData).ProjectGLData do Result := Result + Rec.ValueByName('Quantity').AsFloat * ValidDeltaPrice[Rec.ValueByName('GLID').AsInteger]; end; end; end; procedure TDetailGLData.LoadProjectGL_DetailGLs(AGLID: Integer; AGLs: TList); var idx: TsdIndex; iRec, iFirst, iLast: Integer; begin idx := sddDetailGL.FindIndex('idxGLID'); iFirst := idx.FindKeyIndex(AGLID); if iFirst <> -1 then begin iLast := idx.FindKeyLastIndex(AGLID); for iRec := iFirst to iLast do AGLs.Add(idx.Records[iRec]); end; end; procedure TDetailGLData.sddDetailGLGetRecordClass( var ARecordClass: TsdRecordClass); begin ARecordClass := TDetailGLRecord; end; procedure TDetailGLData.LoadRelaProjectGL; procedure LoadRela(AProjectGLRec: TProjectGLRecord); var vDetailGLs: TList; iGL: Integer; DetailGLRec: TDetailGLRecord; begin vDetailGLs := TList.Create; try LoadProjectGL_DetailGLs(AProjectGLRec.ID.AsInteger, vDetailGLs); for iGL := 0 to vDetailGLs.Count - 1 do begin DetailGLRec := TDetailGLRecord(vDetailGLs.Items[iGL]); DetailGLRec.RelaProjectGL := AProjectGLRec; end; finally vDetailGLs.Free; end; end; var idx: TsdIndex; i: Integer; ProjectGLRec: TProjectGLRecord; begin if not TProjectData(FProjectData).ProjectGLData.Active then Exit; idx := sddDetailGL.FindIndex('idxGLID'); with TProjectData(FProjectData).ProjectGLData do begin for i := 0 to sddProjectGL.RecordCount - 1 do begin ProjectGLRec := TProjectGLRecord(sddProjectGL.Records[i]); LoadRela(ProjectGLRec); end; end; end; procedure TDetailGLData.SaveCacheData; function GetBillsQuantity(ABillsID: Integer): Double; var StageRec: TStageRecord; begin StageRec := TProjectData(FProjectData).PhaseData.StageData.StageRecord(ABillsID); if Assigned(StageRec) then Result := StageRec.GatherQuantity.AsFloat else Result := 0; end; var idx: TsdIndex; DetailGL: TDetailGLRecord; fBillsQuantity: Double; iBillsID, iRec: Integer; begin if TProjectData(FProjectData).PhaseData.StageDataReadOnly then Exit; idx := sddDetailGL.FindIndex('idxBillsID'); iBillsID := -1; for iRec := 0 to idx.RecordCount - 1 do begin DetailGL := TDetailGLRecord(idx.Records[iRec]); if iBillsID <> DetailGL.BillsID.AsInteger then begin iBillsID := DetailGL.BillsID.AsInteger; fBillsQuantity := GetBillsQuantity(iBillsID); end; if DetailGL.LastBillsQuantity.AsFloat <> fBillsQuantity then DetailGL.LastBillsQuantity.AsFloat := fBillsQuantity; end; end; procedure TDetailGLData.sddDetailGLBeforeDeleteRecord( ARecord: TsdDataRecord; var Allow: Boolean); begin Allow := TDetailGLRecord(ARecord).LockedPhaseID.AsInteger = 0; if not Allow then ErrorMessage('当前调差工料已被锁定,不可删除。'); end; procedure TDetailGLData.sddDetailGLBeforeValueChange(AValue: TsdValue; const NewValue: Variant; var Allow: Boolean); begin if SameText(AValue.FieldName, 'Quantity') then begin if TDetailGLRecord(AValue.Owner).LockedPhaseID.AsInteger > 0 then DataSetErrorMessage(Allow, '当前调差工料已被锁定,不可修改数量。'); end; end; function TDetailGLData.HasLockedDetailGL(ABillsID: Integer): Boolean; var idx: TsdIndex; iFirst, iLast, iRec: Integer; Rec: TDetailGLRecord; begin Result := False; idx := sddDetailGL.FindIndex('idxBillsID'); iFirst := idx.FindKeyIndex(ABillsID); if iFirst > -1 then begin iLast := idx.FindKeyLastIndex(ABillsID); for iRec := iFirst to iLast do begin Rec := TDetailGLRecord(idx.Records[iRec]); if Rec.LockedPhaseID.AsInteger > 0 then begin Result := True; Break; end; end; end; end; end.