unit DetailItemsDM; interface uses SysUtils, Classes, DB, DBClient, DataBase, ScBillsTree; type TDMDetailItems = class(TDataModule) cdsPPItems: TClientDataSet; cdsPPDrawQty: TClientDataSet; cdsPPDetailItems: TClientDataSet; cdsPQBills: TClientDataSet; cdsPPItemsCode: TWideStringField; cdsPPItemsName: TWideStringField; cdsPPItemsUnits: TWideStringField; cdsPPItemsQuantity: TFloatField; cdsPPItemsUnitPrice: TFloatField; cdsPPItemsTotalPrice: TFloatField; cdsPPDetailItemsCode: TWideStringField; cdsPPDetailItemsName: TWideStringField; cdsPPDetailItemsUnits: TWideStringField; cdsPPDetailItemsQuantity: TFloatField; cdsPPDetailItemsUnitPrice: TFloatField; cdsPPDetailItemsTotalPrice: TFloatField; cdsPPDrawQtyName: TWideStringField; cdsPPDrawQtyUnits: TWideStringField; cdsPPDrawQtyQuantity: TFloatField; cdsPPDrawQtyMemoStr: TWideStringField; cdsPQBillsUnits: TWideStringField; cdsPQBillsQuantity: TFloatField; cdsPQBillsUnitPrice: TBCDField; cdsPQBillsTotalPrice: TBCDField; cdsPQBillsMemoStr: TMemoField; cdsPQBillsCode: TWideStringField; cdsPQBillsName: TWideStringField; cdsPQBillsID: TIntegerField; cdsPPItemsBillsID: TIntegerField; cdsPPItemsID: TIntegerField; cdsPPDetailItemsID: TIntegerField; cdsPPDetailItemsItemID: TIntegerField; cdsPPDrawQtyBillsID: TIntegerField; cdsBills: TClientDataSet; cdsBillsB_Code: TWideStringField; cdsBillsName: TWideStringField; cdsBillsUnits: TWideStringField; cdsBillsQuantity: TFloatField; cdsBillsUnitPrice: TBCDField; cdsBillsTotalPrice: TBCDField; cdsBillsMemoStr: TMemoField; cdsBillsCode: TWideStringField; cdsPPDrawQtySerialNo: TIntegerField; cdsPPDrawQtyDesignQuantity: TFloatField; cdsQIItems: TClientDataSet; cdsQIDetailItems: TClientDataSet; cdsQIDrawQty: TClientDataSet; cdsQIItemsID: TIntegerField; cdsQIItemsCode: TWideStringField; cdsQIItemsName: TWideStringField; cdsQIItemsUnits: TWideStringField; cdsQIItemsQuantity: TFloatField; cdsQIItemsUnitPrice: TFloatField; cdsQIItemsTotalPrice: TFloatField; cdsQIItemsBillsID: TIntegerField; cdsQIDetailItemsID: TIntegerField; cdsQIDetailItemsCode: TWideStringField; cdsQIDetailItemsName: TWideStringField; cdsQIDetailItemsUnits: TWideStringField; cdsQIDetailItemsQuantity: TFloatField; cdsQIDetailItemsUnitPrice: TFloatField; cdsQIDetailItemsTotalPrice: TFloatField; cdsQIDetailItemsItemID: TIntegerField; cdsQIDrawQtyName: TWideStringField; cdsQIDrawQtyUnits: TWideStringField; cdsQIDrawQtyQuantity: TFloatField; cdsQIDrawQtyDesignQuantity: TFloatField; cdsQIDrawQtyMemoStr: TWideStringField; cdsQIDrawQtyBillsID: TIntegerField; cdsQIDrawQtySerialNo: TIntegerField; cdsPPDrawQtyDQID: TIntegerField; cdsQIDrawQtyDQID: TIntegerField; procedure cdsPQBillsAfterScroll(DataSet: TDataSet); procedure cdsPPItemsAfterScroll(DataSet: TDataSet); procedure cdsPPDetailItemsAfterScroll(DataSet: TDataSet); procedure DataModuleCreate(Sender: TObject); procedure cdsQIItemsAfterScroll(DataSet: TDataSet); procedure cdsPPDrawQtyQuantityChange(Sender: TField); procedure cdsPPDrawQtyBeforePost(DataSet: TDataSet); procedure cdsPQBillsQuantityGetText(Sender: TField; var Text: String; DisplayText: Boolean); private { Private declarations } FActive: Boolean; FUpdate: Integer; FBillsData: TDMDataBase; FProject: TObject; procedure SetBillsData(const Value: TDMDataBase); procedure SetAcitve(const Value: Boolean); { detail } procedure PPBeginDetail; procedure PPEndDetail; procedure QIBeginDetail; procedure QIEndDetail; procedure QIEmptyDetial; { update } procedure BeginUpdate; procedure EndUpdate; { pq do execute after scroll } procedure AddDrawItemQty(aCdsDrawQty: TClientDataSet; aItemID: Integer; aAddQty: Boolean = False); procedure ClearQIDrawQuantity; procedure UpdateQIDrawQty(aItemID: Integer); procedure AddItems(aNode: TScBillsItem); procedure AddDetailItems(aNode: TScBillsItem); procedure FilterItems(aNode: TScBillsItem; const aBCode: string); overload; procedure FilterItems(aNode: TScBillsItem; const aBCode, aName: string); overload; procedure RefreshDetailQtyItems(const aBCode: string); overload; procedure RefreshDetailQtyItems(const aBCode, aName: string); overload; procedure RefreshQIDrawQtyItems(aNode: TScBillsItem; const aBCode: string); { pp } procedure AddPPItem(aNode: TScBillsItem); procedure AddPPDetailItem(aNode: TScBillsItem); procedure FilterItems(aNode: TScBillsItem); overload; procedure RefreshDetailProItems(aNode: TScBillsItem; const aBCode: string); procedure RefreshDrawQtyItems(aNode: TScBillsItem; const aCode, aBCode: string; aAddQty: Boolean); { find } function FindNode(var aNode: TScBillsItem; const aCode: string; aIsCode: Boolean): Boolean; public { Public declarations } constructor Create(aProject: TObject); { Empty Dataset } procedure PPEmptyDetail; procedure PQEmptyDetail; { Refresh Items } procedure RefreshPQItems; procedure RefreshPPItems; { locate } procedure LocateBills(const aCode, aBCode: string); overload; procedure LocateBills; overload; function CanLocateBills: Boolean; property Active: Boolean read FActive write SetAcitve; property BillsData: TDMDataBase read FBillsData write SetBillsData; end; implementation uses Math, ScProjectManager, ConstVarUnit, ConstTypeUnit, ConstMethodUnit, ZjIDTree, ScConfig, Variants; {$R *.dfm} { TDMDetailItems } constructor TDMDetailItems.Create(aProject: TObject); begin inherited Create(nil); FProject := aProject; end; function Compare(Item1, Item2: Pointer): Integer; begin Result := CompareCodeWithChar(TBillIDRecord(Item1).Code, TBillIDRecord(Item2).Code); if not ScConfigInfo.MatchCodeOnly and (Result = 0) then Result := CompareText(TBillIDRecord(Item1).Name, TBillIDRecord(Item2).Name) end; procedure TDMDetailItems.RefreshPQItems; var strOldCode : string; strOldName : string; strOldUnit : string; strOldMemo : string; strNewCode : string; strNewName : string; strNewUnit : string; strNewMemo : string; dQuantity : Double; dTotalPrice : Double; dUnitPrice : Double; bFirst : Boolean; lstPQ : TList; bRecord : TBillIDRecord; iLoop : Integer; begin if not Assigned(FProject) then Exit; BillsData := TProject(FProject).BillsData; // FBillsData.SaveSerialNo; lstPQ := TList.Create; cdsPQBills.DisableControls; try bFirst := True; cdsPQBills.EmptyDataSet; while not cdsBills.Eof do begin strNewCode := cdsBillsB_Code.Value; strNewName := cdsBillsName.Value; strNewUnit := cdsBillsUnits.Value; strNewMemo := cdsBillsMemoStr.Value; if bFirst then begin dQuantity := 0; dTotalPrice := 0; dUnitPrice := 0; strOldCode := strNewCode; strOldName := strNewName; strOldUnit := strNewUnit; strOldMemo := strNewMemo; bFirst := False; end; if (ScConfigInfo.MatchCodeOnly and (strOldCode <> strNewCode)) or (not ScConfigInfo.MatchCodeOnly and ((strOldCode <> strNewCode) or (strOldName <> strNewName))) then begin bRecord := TBillIDRecord.Create; bRecord.Code := strOldCode; bRecord.Name := strOldName; bRecord.Units := strOldUnit; bRecord.Quantity := dQuantity; if dQuantity <> 0 then bRecord.UnitPrice := RoundTo(dTotalPrice/dQuantity, -2); bRecord.TotalPrice := RoundTo(dQuantity*bRecord.UnitPrice, 0); {if dQuantity = 0 then bRecord.UnitPrice := 0 else bRecord.UnitPrice := RoundTo(dTotalPrice / dQuantity, -2); bRecord.TotalPrice := dTotalPrice; } bRecord.MemoStr := strOldMemo; lstPQ.Add(bRecord); { cdsPQBills.Append; cdsPQBillsCode.Value := strOldCode; cdsPQBillsName.Value := strOldName; cdsPQBillsUnits.Value := strOldUnit; cdsPQBillsQuantity.Value := dQuantity; if dQuantity = 0 then cdsPQBillsUnitPrice.Value := 0 else cdsPQBillsUnitPrice.Value := RoundTo(dTotalPrice / dQuantity, -2); cdsPQBillsTotalPrice.Value := dTotalPrice; cdsPQBillsMemoStr.Value := strOldMemo; cdsPQBills.Post; } dQuantity := cdsBillsQuantity.AsFloat; //dUnitPrice := cdsBillsUnitPrice.AsFloat; dTotalPrice := cdsBillsQuantity.AsFloat*cdsBillsUnitPrice.AsFloat; strOldCode := strNewCode; strOldName := strNewName; strOldUnit := strNewUnit; strOldMemo := strNewMemo; end else begin //if dQuantity + cdsBillsQuantity.AsFloat <> 0 then // dUnitPrice := (dQuantity*dUnitPrice + cdsBillsQuantity.AsFloat*cdsBillsUnitPrice.AsFloat)/(dQuantity + cdsBillsQuantity.AsFloat); dQuantity := dQuantity + cdsBillsQuantity.AsFloat; dTotalPrice := dTotalPrice + cdsBillsQuantity.AsFloat*cdsBillsUnitPrice.AsFloat; end; cdsBills.Next; end; bRecord := TBillIDRecord.Create; bRecord.Code := strOldCode; bRecord.Name := strOldName; bRecord.Units := strOldUnit; bRecord.Quantity := dQuantity; if dQuantity <> 0 then bRecord.UnitPrice := RoundTo(dTotalPrice/dQuantity, -2); bRecord.TotalPrice := RoundTo(dQuantity*bRecord.UnitPrice, 0); {if dQuantity = 0 then bRecord.UnitPrice := 0 else bRecord.UnitPrice := RoundTo(dTotalPrice / dQuantity, -2); bRecord.TotalPrice := dTotalPrice; } bRecord.MemoStr := strOldMemo; lstPQ.Add(bRecord); { 排序Code } lstPQ.Sort(Compare); for iLoop := 0 to lstPQ.Count - 1 do begin bRecord := TBillIDRecord(lstPQ.List^[iLoop]); if (ScConfigInfo.MatchCodeOnly and (cdsPQBillsCode.AsString <> bRecord.Code)) or (not ScConfigInfo.MatchCodeOnly and ((cdsPQBillsCode.AsString <> bRecord.Code) or (cdsPQBillsName.AsString <> bRecord.Name))) then begin cdsPQBills.Append; cdsPQBillsCode.Value := bRecord.Code; cdsPQBillsName.Value := bRecord.Name; cdsPQBillsUnits.Value := bRecord.Units; cdsPQBillsQuantity.Value := bRecord.Quantity; cdsPQBillsUnitPrice.Value := bRecord.UnitPrice; cdsPQBillsTotalPrice.Value := bRecord.TotalPrice; cdsPQBillsMemoStr.Value := bRecord.MemoStr; cdsPQBills.Post; end else begin cdsPQBills.Edit; if cdsPQBillsQuantity.AsFloat + bRecord.Quantity <> 0 then cdsPQBillsUnitPrice.Value := RoundTo((cdsPQBillsQuantity.AsFloat*cdsPQBillsUnitPrice.AsFloat + bRecord.Quantity*bRecord.UnitPrice)/(cdsPQBillsQuantity.AsFloat + bRecord.UnitPrice), -2); cdsPQBillsQuantity.Value := cdsPQBillsQuantity.AsFloat + bRecord.Quantity; cdsPQBillsTotalPrice.Value := cdsPQBillsTotalPrice.AsFloat + bRecord.TotalPrice; cdsPQBills.Post; end; end; cdsPQBills.First; finally cdsPQBills.EnableControls; ClearObjectList(lstPQ); lstPQ.Free; end; end; procedure TDMDetailItems.SetAcitve(const Value: Boolean); begin FActive := Value; if FActive <> Value then begin { cdsPQBills.Active := FActive; cdsPPItems.Active := FActive; cdsPPDetailItems.Active := FActive; cdsQIItems.Active := FActive; cdsQIDetailItems.Active := FActive; } end; end; procedure TDMDetailItems.SetBillsData(const Value: TDMDataBase); begin FBillsData := Value; if Assigned(FBillsData) then begin cdsBills.CloneCursor(FBillsData.cdsBills, True); cdsBills.IndexFieldNames := sB_Code; cdsBills.Filter := 'B_Code<>'''''; cdsBills.Filtered := True; end; end; procedure TDMDetailItems.cdsPQBillsAfterScroll(DataSet: TDataSet); begin if ScConfigInfo.MatchCodeOnly then RefreshDetailQtyItems(cdsPQBillsCode.AsString) else RefreshDetailQtyItems(cdsPQBillsCode.AsString, cdsPQBillsName.AsString); end; procedure TDMDetailItems.RefreshDetailQtyItems(const aBCode: string); begin if aBCode = '' then Exit; BillsData := TProject(FProject).BillsData; BeginUpdate; QIEmptyDetial; QIBeginDetail; FBillsData.cdsBills.Filter := 'Code<>'''''; FBillsData.cdsBills.Filtered := True; try FilterItems(TScBillsItem(FBillsData.BillsTree.FirstNode), aBCode); finally FBillsData.cdsBills.Filtered := False; EndUpdate; cdsQIItems.First; QIEndDetail; end; end; procedure TDMDetailItems.FilterItems(aNode: TScBillsItem; const aBCode: string); begin if Assigned(aNode) then begin if aNode.SBillBCode = aBCode then begin AddDrawItemQty(cdsQIDrawQty, aNode.ID, True); AddItems(aNode); end; FilterItems(TScBillsItem(aNode.FirstChild), aBCode); FilterItems(TScBillsItem(aNode.NextSibling), aBCode); end; end; procedure TDMDetailItems.PPBeginDetail; begin cdsPPItems.DisableControls; cdsPPDetailItems.DisableControls; cdsPPDrawQty.DisableControls; end; procedure TDMDetailItems.PPEndDetail; begin cdsPPItems.EnableControls; cdsPPDetailItems.EnableControls; cdsPPDrawQty.EnableControls; end; procedure TDMDetailItems.PPEmptyDetail; begin cdsPPItems.EmptyDataSet; cdsPPDetailItems.EmptyDataSet; cdsPPDrawQty.EmptyDataSet; end; procedure TDMDetailItems.AddDrawItemQty(aCdsDrawQty: TClientDataSet; aItemID: Integer; aAddQty: Boolean); var bFlag: Boolean; CDS: TClientDataSet; begin CDS := TClientDataSet.Create(nil); try CDS.CloneCursor(FBillsData.cdsDrawingQuantity, True); CDS.IndexFieldNames := sBillsID; CDS.SetRange([aItemID], [aItemID]); while not CDS.Eof do begin if CDS.FieldByName(sName).AsString <> '' then begin bFlag := False; aCdsDrawQty.First; while not aCdsDrawQty.Eof do begin if SameText(CDS.FieldByName(sName).AsString, aCdsDrawQty.FieldByName(sName).AsString) then begin aCdsDrawQty.Edit; aCdsDrawQty.FieldByName(sDQID).AsInteger := CDS.FieldByName(SID).AsInteger; aCdsDrawQty.FieldByName(sDesignQuantity).AsFloat := aCdsDrawQty.FieldByName(sDesignQuantity).AsFloat + CDS.FieldByName(sDQuantity1).AsFloat; if aAddQty then aCdsDrawQty.FieldByName(sQuantity).AsFloat := aCdsDrawQty.FieldByName(sQuantity).AsFloat + CDS.FieldByName(sDQuantity1).AsFloat; aCdsDrawQty.Post; bFlag := True; Break; end; aCdsDrawQty.Next; end; if not bFlag then begin aCdsDrawQty.Append; aCdsDrawQty.FieldByName(sName).AsString := CDS.FieldByName(sName).AsString; aCdsDrawQty.FieldByName(sUnits).AsString := CDS.FieldByName(sUnits).AsString; aCdsDrawQty.FieldByName(sDesignQuantity).AsFloat := CDS.FieldByName(sDQuantity1).AsFloat; if aAddQty then aCdsDrawQty.FieldByName(sQuantity).AsFloat := CDS.FieldByName(sDQuantity1).AsFloat; aCdsDrawQty.FieldByName(sMemoStr).AsString := CDS.FieldByName(sMemoContext).AsString; aCdsDrawQty.FieldByName(sDQID).AsInteger := CDS.FieldByName(SID).AsInteger; aCdsDrawQty.Post; end; end; CDS.Next; end; finally CDS.Free; end; end; procedure TDMDetailItems.AddItems(aNode: TScBillsItem); var bIsExists: Boolean; begin if not Assigned(aNode) then Exit; if aNode.SBillCode <> '' then // if aNode.Selected then begin bIsExists := False; cdsQIItems.First; while not cdsQIItems.Eof do begin if cdsQIItemsCode.AsString = aNode.SBillCode then begin bIsExists := True; Break; end; cdsQIItems.Next; end; if not bIsExists then begin if FBillsData.cdsBills.FindKey([aNode.ID]) then begin cdsQIItems.Append; cdsQIItemsCode.Value := FBillsData.cdsBillsCode.AsString; cdsQIItemsName.Value := FBillsData.cdsBillsName.AsString; cdsQIItemsUnits.Value := FBillsData.cdsBillsUnits.AsString; cdsQIItemsQuantity.Value := FBillsData.cdsBillsDesignQuantity.AsFloat; cdsQIItemsUnitPrice.Value := FBillsData.cdsBillsDesignPrice.AsFloat; cdsQIItemsTotalPrice.Value := FBillsData.cdsBillsTotalPrice.AsFloat; cdsQIItemsBillsID.Value := aNode.ID; cdsQIItems.Post; { cdsDetailItems.EmptyDataSet; AddDetailItems(TScBillsItem(aNode.Parent)); } end; end; end else AddItems(TScBillsItem(aNode.Parent)); end; procedure TDMDetailItems.AddDetailItems(aNode: TScBillsItem); begin if not Assigned(aNode) then Exit; if aNode.Level = 0 then Exit; cdsQIDetailItems.Append; cdsQIDetailItemsCode.Value := aNode.SBillCode; cdsQIDetailItemsName.Value := aNode.SBillName; cdsQIDetailItems.Post; AddDetailItems(TScBillsItem(aNode.Parent)); end; procedure TDMDetailItems.RefreshPPItems; var sbiNode: TScBillsItem; begin FBillsData := TProject(FProject).BillsData; if FBillsData.XMJBillsTree.Selected = nil then Exit; sbiNode := TScBillsItem(FBillsData.BillsTree.FindNode(FBillsData.XMJBillsTree.Selected.ID)); if not Assigned(sbiNode) then Exit; if sbiNode.SBillCode = '' then Exit; PPEmptyDetail; PPBeginDetail; BeginUpdate; FBillsData.cdsBills.Filter := 'B_Code<>'''''; FBillsData.cdsBills.Filtered := True; try FilterItems(TScBillsItem(sbiNode.FirstChild)); finally FBillsData.cdsBills.Filtered := False; EndUpdate; cdsPPItems.First; PPEndDetail; end; end; procedure TDMDetailItems.FilterItems(aNode: TScBillsItem); begin if Assigned(aNode) then begin if aNode.HasChildren then FilterItems(TScBillsItem(aNode.FirstChild)) else begin if aNode.SBillBCode <> '' then AddPPItem(aNode); end; FilterItems(TScBillsItem(aNode.NextSibling)); end; end; procedure TDMDetailItems.AddPPItem(aNode: TScBillsItem); var bFlag: Boolean; strCode, strName: string; begin bFlag := False; cdsPPItems.First; while not cdsPPItems.Eof do begin strCode := cdsPPItemsCode.AsString; strName := cdsPPItemsName.AsString; if (ScConfigInfo.MatchCodeOnly and (strCode = aNode.SBillBCode)) or (not ScConfigInfo.MatchCodeOnly and (strCode = aNode.SBillBCode) and (strName = aNode.SBillName)) then begin if FBillsData.cdsBills.FindKey([aNode.ID]) then begin cdsPPItems.Edit; cdsPPItemsQuantity.Value := cdsPPItemsQuantity.AsFloat + FBillsData.cdsBillsQuantity.AsFloat; cdsPPItemsTotalPrice.Value := cdsPPItemsTotalPrice.AsFloat + FBillsData.cdsBillsTotalPrice.AsFloat; if cdsPPItemsQuantity.Value = 0 then cdsPPItemsUnitPrice.Value := 0 else cdsPPItemsUnitPrice.Value := RoundTo(cdsPPItemsTotalPrice.AsFloat / cdsPPItemsQuantity.AsFloat, -2); cdsPPItems.Post; end; bFlag := True; Break; end; //if CompareStr(strCode, aNode.SBillBCode) > 0 then Break; cdsPPItems.Next; end; if not bFlag then begin if FBillsData.cdsBills.FindKey([aNode.ID]) then begin cdsPPItems.Append; cdsPPItemsCode.Value := FBillsData.cdsBillsB_Code.AsString; cdsPPItemsName.Value := FBillsData.cdsBillsName.AsString; cdsPPItemsUnits.Value := FBillsData.cdsBillsUnits.AsString; cdsPPItemsQuantity.Value := FBillsData.cdsBillsQuantity.AsFloat; cdsPPItemsUnitPrice.Value := FBillsData.cdsBillsUnitPrice.AsFloat; cdsPPItemsTotalPrice.Value := FBillsData.cdsBillsTotalPrice.AsFloat; cdsPPItems.Post; end; end; end; procedure TDMDetailItems.cdsPPItemsAfterScroll(DataSet: TDataSet); var sbiNode: TScBillsItem; begin if FUpdate > 0 then Exit; FBillsData := TProject(FProject).BillsData; sbiNode := TScBillsItem(FBillsData.BillsTree.FindNode(FBillsData.XMJBillsTree.Selected.ID)); if Assigned(sbiNode) then begin // if sbiNode.SBillBCode <> '' then Exit; while sbiNode.SBillBCode <> '' do sbiNode := TScBillsItem(sbiNode.Parent); cdsPPDetailItems.EmptyDataSet; cdsPPDrawQty.EmptyDataSet; BeginUpdate; PPBeginDetail; try RefreshDetailProItems(TScBillsItem(sbiNode.FirstChild), cdsPPItemsCode.AsString); RefreshDrawQtyItems(TScBillsItem(sbiNode.FirstChild), cdsPPDetailItemsCode.AsString, cdsPPItemsCode.AsString, True); cdsPPDetailItems.First; cdsPPDrawQty.First; finally PPEndDetail; EndUpdate; end; end; end; procedure TDMDetailItems.RefreshDetailProItems(aNode: TScBillsItem; const aBCode: string); begin if Assigned(aNode) then begin if aNode.SBillBCode = aBCode then AddPPDetailItem(aNode) else RefreshDetailProItems(TScBillsItem(aNode.FirstChild), aBCode); RefreshDetailProItems(TScBillsItem(aNode.NextSibling), aBCode); end; end; procedure TDMDetailItems.RefreshDrawQtyItems(aNode: TScBillsItem; const aCode, aBCode: string; aAddQty: Boolean); begin if Assigned(aNode) then begin if aNode.SBillCode = aCode then RefreshDrawQtyItems(TScBillsItem(aNode.FirstChild), aCode, aBCode, True) else begin if aNode.SBillBCode = aBCode then AddDrawItemQty(cdsPPDrawQty, aNode.ID, aAddQty); RefreshDrawQtyItems(TScBillsItem(aNode.FirstChild), aCode, aBCode, aAddQty) end; RefreshDrawQtyItems(TScBillsItem(aNode.NextSibling), aCode, aBCode, aAddQty); end; end; procedure TDMDetailItems.AddPPDetailItem(aNode: TScBillsItem); var bItemExists: Boolean; begin if not Assigned(aNode) then Exit; bItemExists := False; aNode := TScBillsItem(aNode.Parent); while Assigned(aNode) do begin if aNode.SBillCode <> '' then begin cdsPPDetailItems.First; while not cdsPPDetailItems.Eof do begin if cdsPPDetailItemsCode.AsString = aNode.SBillCode then begin bItemExists := True; Break; end; cdsPPDetailItems.Next; end; if not bItemExists then begin if FBillsData.cdsBills.FindKey([aNode.ID]) then begin cdsPPDetailItems.Append; cdsPPDetailItemsCode.Value := FBillsData.cdsBillsCode.AsString; cdsPPDetailItemsName.Value := FBillsData.cdsBillsName.AsString; cdsPPDetailItemsUnits.Value := FBillsData.cdsBillsUnits.AsString; cdsPPDetailItemsQuantity.Value := FBillsData.cdsBillsDesignQuantity.AsFloat; cdsPPDetailItemsUnitPrice.Value := FBillsData.cdsBillsDesignPrice.AsFloat; cdsPPDetailItemsTotalPrice.Value := FBillsData.cdsBillsTotalPrice.AsFloat; cdsPPDetailItems.Post; end; end; Break; end; aNode := TScBillsItem(aNode.Parent); end; end; procedure TDMDetailItems.LocateBills(const aCode, aBCode: string); var sbiNode: TScBillsItem; begin if (aCode = '') or (aBCode = '') then Exit; FBillsData := TProject(FProject).BillsData; sbiNode := TScBillsItem(FBillsData.XMJBillsTree.Selected); if Assigned(sbiNode) then begin { make sure sbillcode <> '' , and then locate it's children } while Pos(sbiNode.SBillCode, aCode) <> 1 do sbiNode := TScBillsItem(sbiNode.Parent); { find Node } if FindNode(sbiNode, aCode, True) {and FindNode(sbiNode, aBCode, False)} then begin sbiNode.LocateDBRecord; end; end; end; function TDMDetailItems.FindNode(var aNode: TScBillsItem; const aCode: string; aIsCode: Boolean): Boolean; var I: Integer; sbiChild: TScBillsItem; begin Result := False; if aIsCode then begin if aNode.SBillCode = aCode then begin Result := True; Exit; end; end else begin if aNode.SBillBCode = aCode then begin Result := True; Exit; end; end; for I := 0 to aNode.ChildCount - 1 do begin sbiChild := TScBillsItem(aNode.ChildNodes[I]); if FindNode(sbiChild, aCode, aIsCode) then begin aNode := sbiChild; Result := True; Break; end; end; end; procedure TDMDetailItems.cdsPPDetailItemsAfterScroll(DataSet: TDataSet); var sbiNode: TScBillsItem; begin { if FUpdate > 0 then Exit; FBillsData := TProject(FProject).BillsData; sbiNode := TScBillsItem(FBillsData.XMJBillsTree.Selected); if not FindNode(sbiNode, cdsPPDetailItemsCode.AsString, True) then Exit; sbiNode := TScBillsItem(FBillsData.BillsTree.FindNode(sbiNode.ID)); if Assigned(sbiNode) then begin if sbiNode.SBillBCode <> '' then Exit; cdsPPDrawQty.EmptyDataSet; RefreshDrawQtyItems(TScBillsItem(sbiNode.FirstChild), cdsPPDetailItemsCode.AsString, cdsPPItemsCode.AsString, True); cdsPPDrawQty.First; end; } end; procedure TDMDetailItems.BeginUpdate; begin Inc(FUpdate); end; procedure TDMDetailItems.EndUpdate; begin Dec(FUpdate); if FUpdate <= 0 then begin FUpdate := 0; end; end; procedure TDMDetailItems.DataModuleCreate(Sender: TObject); begin cdsPPItems.IndexFieldNames := sCode; cdsPPDetailItems.IndexFieldNames := sCode; cdsQIItems.IndexFieldNames := sCode; cdsQIDetailItems.IndexFieldNames := sCode; end; procedure TDMDetailItems.cdsQIItemsAfterScroll(DataSet: TDataSet); var sbiNode: TScBillsItem; begin if FUpdate > 0 then Exit; FBillsData := TProject(FProject).BillsData; sbiNode := TScBillsItem(FBillsData.BillsTree.FindNode(cdsQIItemsBillsID.AsInteger)); if Assigned(sbiNode) then begin cdsQIDetailItems.EmptyDataSet; ClearQIDrawQuantity; AddDetailItems(TScBillsItem(sbiNode.Parent)); RefreshQIDrawQtyItems(TScBillsItem(sbiNode.FirstChild), cdsPQBillsCode.AsString); // RefreshDrawQtyItems(cdsQIDrawQty, TScBillsItem(sbiNode.FirstChild), cdsQIItemsCode.AsString, // cdsPQBillsCode.AsString, False); end; end; procedure TDMDetailItems.QIBeginDetail; begin cdsQIItems.DisableControls; cdsQIDetailItems.DisableControls; cdsQIDrawQty.DisableControls; end; procedure TDMDetailItems.QIEndDetail; begin cdsQIItems.EnableControls; cdsQIDetailItems.EnableControls; cdsQIDrawQty.EnableControls; end; procedure TDMDetailItems.QIEmptyDetial; begin cdsQIItems.EmptyDataSet; cdsQIDetailItems.EmptyDataSet; cdsQIDrawQty.EmptyDataSet; end; procedure TDMDetailItems.RefreshQIDrawQtyItems(aNode: TScBillsItem; const aBCode: string); begin if Assigned(aNode) then begin if aNode.SBillBCode = aBCode then UpdateQIDrawQty(aNode.ID); RefreshQIDrawQtyItems(TScBillsItem(aNode.FirstChild), aBCode); RefreshQIDrawQtyItems(TScBillsItem(aNode.NextSibling), aBCode); end; end; procedure TDMDetailItems.UpdateQIDrawQty(aItemID: Integer); var CDS: TClientDataSet; begin CDS := TClientDataSet.Create(nil); try CDS.CloneCursor(FBillsData.cdsDrawingQuantity, True); CDS.IndexFieldNames := sBillsID; CDS.SetRange([aItemID], [aItemID]); while not CDS.Eof do begin if CDS.FieldByName(sName).AsString <> '' then begin cdsQIDrawQty.First; while not cdsQIDrawQty.Eof do begin if SameText(CDS.FieldByName(sName).AsString, cdsQIDrawQty.FieldByName(sName).AsString) then begin cdsQIDrawQty.Edit; cdsQIDrawQty.FieldByName(sQuantity).AsFloat := cdsQIDrawQty.FieldByName(sQuantity).AsFloat + CDS.FieldByName(sDQuantity1).AsFloat; cdsQIDrawQty.Post; Break; end; cdsQIDrawQty.Next; end; end; CDS.Next; end; finally CDS.Free; end; end; procedure TDMDetailItems.ClearQIDrawQuantity; begin cdsQIDrawQty.First; while not cdsQIDrawQty.Eof do begin cdsQIDrawQty.Edit; cdsQIDrawQtyQuantity.Value := 0; cdsQIDrawQty.Post; cdsQIDrawQty.Next; end; end; procedure TDMDetailItems.PQEmptyDetail; begin cdsPQBills.EmptyDataSet; QIEmptyDetial; end; procedure TDMDetailItems.cdsPPDrawQtyQuantityChange(Sender: TField); begin Sender.Tag := 1; end; procedure TDMDetailItems.cdsPPDrawQtyBeforePost(DataSet: TDataSet); var dQuantity: Double; begin if FUpdate > 0 then Exit; FBillsData := TProject(FProject).BillsData; if FBillsData.XMJBillsTree.Selected.HasChildren then begin DataSet.Cancel; raise Exception.Create('当前节点不是最底层,不能修改细目工程量.'); end; if cdsPPDrawQtyQuantity.Tag = 1 then begin if FBillsData.cdsDrawingQuantity.FindKey([cdsPPDrawQtyDQID.AsInteger]) then begin dQuantity := FBillsData.cdsDrawingQuantityDQuantity1.AsFloat; FBillsData.cdsDrawingQuantity.Edit; FBillsData.cdsDrawingQuantityDQuantity1.Value := cdsPPDrawQtyQuantity.AsFloat; FBillsData.cdsDrawingQuantity.Post; end; cdsPPDrawQtyDesignQuantity.Value := cdsPPDrawQtyDesignQuantity.AsFloat + cdsPPDrawQtyQuantity.AsFloat - dQuantity; cdsPPDrawQtyQuantity.Tag := 0; end; end; procedure TDMDetailItems.LocateBills; begin TProject(FProject).BillsData.LocateBills(cdsQIItemsCode.AsString); end; function TDMDetailItems.CanLocateBills: Boolean; begin Result := cdsQIItems.RecordCount > 0; end; type TFieldAccess = class(TField); procedure TDMDetailItems.cdsPQBillsQuantityGetText(Sender: TField; var Text: String; DisplayText: Boolean); begin if DisplayText then begin TFieldAccess(Sender).GetText(Text, DisplayText); if Text = '0' then Text := ''; end; end; procedure TDMDetailItems.RefreshDetailQtyItems(const aBCode, aName: string); begin if (aBCode = '') and (aName = '') then Exit; BillsData := TProject(FProject).BillsData; BeginUpdate; QIEmptyDetial; QIBeginDetail; FBillsData.cdsBills.Filter := 'Code<>'''''; FBillsData.cdsBills.Filtered := True; try FilterItems(TScBillsItem(FBillsData.BillsTree.FirstNode), aBCode, aName); finally FBillsData.cdsBills.Filtered := False; EndUpdate; cdsQIItems.First; QIEndDetail; end; end; procedure TDMDetailItems.FilterItems(aNode: TScBillsItem; const aBCode, aName: string); begin if Assigned(aNode) then begin if (aNode.SBillBCode = aBCode) and (aNode.SBillName = aName) then begin AddDrawItemQty(cdsQIDrawQty, aNode.ID, True); AddItems(aNode); end; FilterItems(TScBillsItem(aNode.FirstChild), aBCode, aName); FilterItems(TScBillsItem(aNode.NextSibling), aBCode, aName); end; end; end.