浏览代码

材料调差,批复后,锁定部分数据;
根据锁定信息、项目进度、查看数据等,控制输入、功能调用。

MaiXinRong 9 年之前
父节点
当前提交
87e69df52c

+ 51 - 3
DataModules/BillsMeasureDm.pas

@@ -40,6 +40,8 @@ type
     function SelectAndUpdateBGL(ABillsID: Integer; ARec: TsdDataRecord;
       ANewValue: Double; const AType: string): Boolean;
 
+    procedure CalculateNode(ANode: TBillsIDTreeNode);
+
     function GetStageData: TStageData;
     procedure SetOnRecChange(const Value: TRecChangeEvent);
   public
@@ -65,6 +67,7 @@ type
     procedure UpdateRecordDeal(ABillsID: Integer; AQuantity, ATotalPrice: Double);
     procedure UpdateRecordQc(ABillsID: Integer; AQuantity, ATotalPrice: Double);
     procedure UpdateRecordPc(ABillsID: Integer; AQuantity, ATotalPrice: Double);
+    procedure UpdateRecordPM(ABillsID: Integer; ADiffer: Double);
     procedure UpdateBGLInfo(ABillsID: Integer; ARec: TsdDataRecord; const AType: string);
 
     property ProjectData: TObject read FProjectData;
@@ -641,14 +644,20 @@ end;
 
 procedure TBillsMeasureData.CalculateAll;
 var
-  Cacl: TBillsCalculate;
+  //Cacl: TBillsCalculate;
+  i: Integer;
 begin
-  Cacl := TBillsCalculate.Create(Self);
+  if not TProjectData(FProjectData).StageDataReadOnly then
+
+  for i := 0 to BillsMeasureTree.Count - 1 do
+    CalculateNode(TBillsIDTreeNode(BillsMeasureTree.Items[i]));
+
+  {Cacl := TBillsCalculate.Create(Self);
   try
     Cacl.Execute;
   finally
     Cacl.Free;
-  end;
+  end;}
 end;
 
 procedure TBillsMeasureData.UpdateRecordDeal(ABillsID: Integer; AQuantity,
@@ -890,4 +899,43 @@ begin
   end;
 end;
 
+procedure TBillsMeasureData.UpdateRecordPM(ABillsID: Integer;
+  ADiffer: Double);
+var
+  stnNode: TBillsIDTreeNode;
+begin
+  stnNode := TBillsIDTreeNode(BillsMeasureTree.FindNode(ABillsID));
+  if not Assigned(stnNode) then Exit;
+
+  stnNode.Rec.PM_AddTotalPrice.AsFloat := stnNode.Rec.PM_AddTotalPrice.AsFloat + ADiffer;
+  UpdateRecordPM(stnNode.ParentID, ADiffer);
+end;
+
+procedure TBillsMeasureData.CalculateNode(ANode: TBillsIDTreeNode);
+begin
+  if Assigned(ANode.StageRec) then
+  begin
+    if not ANode.HasChildren then
+    begin
+      ANode.Rec.AddDealQuantity.AsFloat := ANode.StageRec.EndDealQuantity.AsFloat;
+
+      ANode.Rec.AddQcQuantity.AsFloat := ANode.StageRec.EndQcQuantity.AsFloat;
+      ANode.Rec.AddQcBGLCode.AsString := ANode.StageRec.EndQcBGLCode.AsString;
+      ANode.Rec.AddQcBGLNum.AsString := ANode.StageRec.EndQcBGLNum.AsString;
+
+      ANode.Rec.AddPcQuantity.AsFloat := ANode.StageRec.EndPcQuantity.AsFloat;
+      ANode.Rec.AddPcBGLCode.AsString := ANode.StageRec.EndPcBGLCode.AsString;
+      ANode.Rec.AddPcBGLNum.AsString := ANode.StageRec.EndPcBGLNum.AsString;
+
+      ANode.Rec.AddGatherQuantity.AsFloat := ANode.StageRec.EndGatherQuantity.AsFloat;
+    end;
+    ANode.Rec.AddDealTotalPrice.AsFloat := ANode.StageRec.EndDealTotalPrice.AsFloat;
+    ANode.Rec.AddQcTotalPrice.AsFloat := ANode.StageRec.EndQcTotalPrice.AsFloat;
+    ANode.Rec.AddPcTotalPrice.AsFloat := ANode.StageRec.EndPcTotalPrice.AsFloat;
+    ANode.Rec.AddGatherTotalPrice.AsFloat := ANode.StageRec.EndGatherTotalPrice.AsFloat;
+
+    ANode.Rec.PM_AddTotalPrice.AsFloat := ANode.StageRec.PM_PreTotalPrice.AsFloat + ANode.StageRec.PM_TotalPrice.AsFloat;
+  end;
+end;
+
 end.

+ 8 - 12
DataModules/DetailGLDm.dfm

@@ -12,6 +12,8 @@ object DetailGLData: TDetailGLData
   object sddDetailGL: TsdDataSet
     Active = False
     Provider = sdpDetailGL
+    BeforeDeleteRecord = sddDetailGLBeforeDeleteRecord
+    BeforeValueChange = sddDetailGLBeforeValueChange
     OnGetRecordClass = sddDetailGLGetRecordClass
     Left = 64
     Top = 80
@@ -31,18 +33,12 @@ object DetailGLData: TDetailGLData
       090001044E616D65060D43726561746550686173654944094669656C644E616D
       65060D4372656174655068617365494408446174615479706502030844617461
       53697A6502040549734B6579080F4E65656450726F636573734E616D65090001
-      044E616D65060D43726561746553746167654944094669656C644E616D65060D
-      437265617465537461676549440844617461547970650203084461746153697A
+      044E616D65060D4C6F636B656450686173654944094669656C644E616D65060D
+      4C6F636B6564506861736549440844617461547970650203084461746153697A
       6502040549734B6579080F4E65656450726F636573734E616D65090001044E61
-      6D650610504D5F507265546F74616C5072696365094669656C644E616D650610
-      504D5F507265546F74616C507269636508446174615479706502060844617461
-      53697A6502080549734B6579080F4E65656450726F636573734E616D65090001
-      044E616D650610504D5F437572546F74616C5072696365094669656C644E616D
-      650610504D5F437572546F74616C507269636508446174615479706502060844
-      61746153697A6502080549734B6579080F4E65656450726F636573734E616D65
-      090001044E616D650610504D5F456E64546F74616C5072696365094669656C64
-      4E616D650610504D5F456E64546F74616C507269636508446174615479706502
-      06084461746153697A6502080549734B6579080F4E65656450726F636573734E
-      616D65090000}
+      6D6506114C61737442696C6C735175616E74697479094669656C644E616D6506
+      114C61737442696C6C735175616E746974790844617461547970650206084461
+      746153697A6502080549734B6579080F4E65656450726F636573734E616D6509
+      0000}
   end
 end

+ 89 - 0
DataModules/DetailGLDm.pas

@@ -10,6 +10,10 @@ type
     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;
 
@@ -24,12 +28,14 @@ type
     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);
@@ -94,6 +100,8 @@ var
   i, iNewID: Integer;
   Rec, GLRec: TDetailGLRecord;
 begin
+  if HasLockedDetailGL(ABillsID) then Exit;
+
   sddDetailGL.BeginUpdate;
   try
     ClearDetailGLs(ABillsID);
@@ -171,6 +179,7 @@ end;
 
 procedure TDetailGLData.Save;
 begin
+  SaveCacheData;
   sddDetailGL.Save;
 end;
 
@@ -258,6 +267,8 @@ var
   i: Integer;
   ProjectGLRec: TProjectGLRecord;
 begin
+  if not TProjectData(FProjectData).ProjectGLData.Active then Exit;
+  
   idx := sddDetailGL.FindIndex('idxGLID');
   with TProjectData(FProjectData).ProjectGLData do
   begin
@@ -269,4 +280,82 @@ begin
   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 > 0 then
+      begin
+        Result := True;
+        Break;
+      end;
+    end;
+  end;
+end;
+
 end.

+ 1 - 0
DataModules/PhasePayDm.pas

@@ -160,6 +160,7 @@ var
   iIndex: Integer;
 begin
   if TPhaseData(FPhaseData).StageDataReadOnly then Exit;
+
   for iIndex := 0 to sddPhasePay.RecordCount - 1 do
     Calculate(sddPhasePay.Records[iIndex].ValueByName('ID').AsInteger);
   CalculateCurPay;

+ 1 - 0
DataModules/PriceMarginBillsDm.dfm

@@ -127,6 +127,7 @@ object PriceMarginBillsData: TPriceMarginBillsData
         FieldName = 'CurQcQuantity'
       end>
     OnCurrentChanged = sdvGclBillsCurrentChanged
+    OnGetText = sdvGclBillsGetText
     Left = 64
     Top = 136
   end

+ 21 - 0
DataModules/PriceMarginBillsDm.pas

@@ -26,6 +26,8 @@ type
       ARecord: TsdDataRecord; AValue: TsdValue; AColumn: TsdViewColumn;
       DisplayText: Boolean);
     procedure sdvDetailGLAfterDeleteRecord(ARecord: TsdDataRecord);
+    procedure sdvGclBillsGetText(var Text: String; ARecord: TsdDataRecord;
+      AValue: TsdValue; AColumn: TsdViewColumn; DisplayText: Boolean);
   private
     FProjectData: TObject;
     procedure WriteGclBillsData(AGcls: TList);
@@ -325,4 +327,23 @@ begin
   end;
 end;
 
+procedure TPriceMarginBillsData.sdvGclBillsGetText(var Text: String;
+  ARecord: TsdDataRecord; AValue: TsdValue; AColumn: TsdViewColumn;
+  DisplayText: Boolean);
+
+  procedure GetDisplayText;
+  begin
+    if ((Pos('Price', AColumn.FieldName) > 0) or
+        (Pos('Quantity', AColumn.FieldName) > 0)) then
+    begin
+      if AValue.AsFloat = 0 then
+        Text := '';
+    end;
+  end;
+
+begin
+  if DisplayText then
+    GetDisplayText;
+end;
+
 end.

+ 1 - 0
DataModules/ProjectGLDm.dfm

@@ -112,6 +112,7 @@ object ProjectGLData: TProjectGLData
         DisplayFormat = '0.##'
       end>
     OnGetText = sdvProjectGLGetText
+    OnSetText = sdvProjectGLSetText
     Left = 56
     Top = 136
   end

+ 89 - 3
DataModules/ProjectGLDm.pas

@@ -17,6 +17,8 @@ type
     procedure sdvProjectGLGetText(var Text: String; ARecord: TsdDataRecord;
       AValue: TsdValue; AColumn: TsdViewColumn; DisplayText: Boolean);
     procedure sddProjectGLGetRecordClass(var ARecordClass: TsdRecordClass);
+    procedure sdvProjectGLSetText(var Text: String; ARecord: TsdDataRecord;
+      AValue: TsdValue; AColumn: TsdViewColumn; var Allow: Boolean);
   private
     FProjectData: TObject;
     FTempGLs: TList;
@@ -40,6 +42,7 @@ type
 
     function GetValidDeltaPrice(AID: Integer): Double;
     function GetPM_TotalPrice: Double;
+    function GetActive: Boolean;
   public
     constructor Create(AProjectData: TObject);
     destructor Destroy; override;
@@ -48,12 +51,15 @@ type
     procedure Save;
 
     procedure LoadCurPhaseInfoPrice;
+    procedure LoadStagePM_CalcData;
 
     procedure CalculateAll;
     procedure CalculateGL_PM(AGLID: Integer);
     procedure CalculateGLs_PM(ADetailGLs: TList);
 
     property ProjectData: TObject read FProjectData write FProjectData;
+    property Active: Boolean read GetActive;
+
     property ValidDeltaPrice[AID: Integer]: Double read GetValidDeltaPrice;
     property PM_TotalPrice: Double read GetPM_TotalPrice;
   end;
@@ -147,6 +153,8 @@ begin
     sddProjectGL.AddIndex('idxCode', 'Code');
   sdvProjectGL.Open;
   sdvProjectGL.IndexName := 'idxCode';
+  LoadCurPhaseInfoPrice;
+  LoadStagePM_CalcData;
 end;
 
 procedure TProjectGLData.Save;
@@ -207,7 +215,10 @@ begin
   begin
     Allow := False;
     if (AValue.Owner.ValueByName('Code').AsString = '') then
-      ErrorMessage('编号不可为空,请先填写编号,再填写其他信息。')
+    begin
+      ErrorMessage('编号不可为空,请先填写编号,再填写其他信息。');
+      sddProjectGL.Remove(AValue.Owner);
+    end
     else
       Allow := True;
   end;
@@ -239,7 +250,9 @@ begin
   if (DeltaC > 0) and (DeltaC - RiskC > 0) then
     ValidDeltaC := DeltaC - RiskC
   else if (DeltaC < 0) and (DeltaC + RiskC < 0) then
-    ValidDeltaC := DeltaC + RiskC;
+    ValidDeltaC := DeltaC + RiskC
+  else
+    ValidDeltaC := 0;
 
   if DeltaC <> ARec.DeltaPrice.AsFloat then
     ARec.DeltaPrice.AsFloat := PriceRoundTo(DeltaC);
@@ -384,7 +397,8 @@ end;
 procedure TProjectGLData.SavePM_CurData;
 const
   sUpdateSql = 'Update GLPrice As G, ProjectGL As P'+
-               '    Set G.PM_Quantity%d = P.PM_Quantity, G.PM_TotalPrice%d = P.PM_TotalPrice'+
+               '  Set G.PM_Quantity%d = P.PM_Quantity, G.PM_TotalPrice%d = P.PM_TotalPrice,'+
+               '    G.PM_Quantity_F = P.PM_Quantity, G.PM_TotalPrice_F = P.PM_TotalPrice'+
                '  Where (G.PhaseID = %d) and (G.GLID = P.ID)';
 var
   iStageIndex: Integer;
@@ -394,6 +408,7 @@ begin
   iStageIndex := TProjectData(FProjectData).PhaseData.StageIndex;
   iPhaseCount := TProjectData(FProjectData).ProjProperties.PhaseCount;
   sSql := Format(sUpdateSql, [iStageIndex, iStageIndex, iPhaseCount]);
+  ExecuteSql(sSql);
 end;
 
 procedure TProjectGLData.CalculateGL_PM(AGLID: Integer);
@@ -442,4 +457,75 @@ begin
     LoadProjectGL_DetailGLs(AGLID, FTempGLs);
 end;
 
+function TProjectGLData.GetActive: Boolean;
+begin
+  Result := sddProjectGL.Active;
+end;
+
+procedure TProjectGLData.sdvProjectGLSetText(var Text: String;
+  ARecord: TsdDataRecord; AValue: TsdValue; AColumn: TsdViewColumn;
+  var Allow: Boolean);
+var
+  iPhaseID: Integer;
+begin
+  if SameText(AColumn.FieldName, 'Code') or
+     SameText(AColumn.FieldName, 'Name') or
+     SameText(AColumn.FieldName, 'Units') or
+     SameText(AColumn.FieldName, 'Specs') or
+     SameText(AColumn.FieldName, 'BasePrice') or
+     SameText(AColumn.FieldName, 'RiskRange') then
+  begin
+    iPhaseID := TProjectGLRecord(ARecord).LockedPhaseID.AsInteger;
+    if iPhaseID > 0 then
+      DataSetErrorMessage(Allow, Format('该工料在第%d期已进行调差计算,不可修改基础数据。', [iPhaseID]));
+  end;
+end;
+
+procedure TProjectGLData.LoadStagePM_CalcData;
+const
+  sSelectSql = 'Select GLID, PhaseID, PM_PreQuantity, PM_PreTotalPrice,'+
+               '    PM_Quantity%d As PM_Quantity, PM_TotalPrice%d As PM_TotalPrice'+
+               '  From GLPrice Where PhaseID = %d';
+var
+  sSql: string;
+  vQuery: TADOQuery;
+
+  procedure LoadPM_Calc;
+  var
+    iRec: Integer;
+    Rec: TProjectGLRecord;
+  begin
+    for iRec := 0 to sddProjectGL.RecordCount - 1 do
+    begin
+      Rec := TProjectGLRecord(sddProjectGL.Records[iRec]);
+      if vQuery.Active and vQuery.Locate('GLID', Rec.ValueByName('ID').AsInteger, []) then
+      begin
+        Rec.PM_Quantity.AsFloat := vQuery.FieldByName('PM_Quantity').AsFloat;
+        Rec.PM_TotalPrice.AsFloat := vQuery.FieldByName('PM_TotalPrice').AsFloat;
+      end
+      else
+      begin
+        Rec.PM_Quantity.AsFloat := 0;
+        Rec.PM_TotalPrice.AsFloat := 0;
+      end;
+    end;
+  end;
+
+begin
+  sddProjectGL.BeginUpdate;
+  vQuery := TADOQuery.Create(nil);
+  try
+    vQuery.Connection := sdpProjectGL.Connection;
+    with TProjectData(FProjectData) do
+      sSql := Format(sSelectSql, [StageIndex, StageIndex, PhaseIndex]);
+    vQuery.SQL.Clear;
+    vQuery.SQL.Add(sSql);
+    vQuery.Open;
+    LoadPM_Calc;
+  finally
+    vQuery.Free;
+    sddProjectGL.EndUpdate;
+  end;
+end;
+
 end.

+ 48 - 11
DataModules/StageDm.pas

@@ -44,6 +44,7 @@ type
 
     procedure CalculateParent(ANode: TBillsIDTreeNode);
     procedure CalculateLeaf(ANode: TBillsIDTreeNode);
+    procedure CalculateSpecialLeaf(ANode: TBillsIDTreeNode);
 
     function GetTotalPrice(ABillsID, AType, AStageIndex: Integer): Double;
 
@@ -132,7 +133,8 @@ implementation
 
 uses
   ProjectData, BillsDm, PhaseData, Math, BGLDm, BillsMeasureDm,
-  UtilMethods, ConditionalDefines, FormulaCalc, DetailGLDm, ConstUnit;
+  UtilMethods, ConditionalDefines, FormulaCalc, DetailGLDm, ConstUnit,
+  ProjectGLDm;
 
 {$R *.dfm}
 
@@ -197,7 +199,7 @@ begin
   UpdateComplete(ABillsID, fQtyDiffer, fTPDiffer);
   if TPhaseData(FPhaseData).IsLastStage then
     with TProjectData(TPhaseData(FPhaseData).ProjectData).BillsMeasureData do
-      UpdateRecordDeal(ABillsID, fQtyDiffer, fTPDiffer);
+     UpdateRecordDeal(ABillsID, fQtyDiffer, fTPDiffer);
 
   CalculatePriceMargin(ABillsID);
 
@@ -634,6 +636,12 @@ begin
 end;
 
 procedure TStageData.CalculateNode(ANode: TsdIDTreeNode);
+
+  function IsSpecialNode: Boolean;
+  begin
+    Result := ANode.ID = iPriceMarginID;
+  end;
+
 begin
   if not Assigned(ANode) then Exit;
   if ANode.HasChildren then
@@ -642,7 +650,12 @@ begin
     CalculateParent(TBillsIDTreeNode(ANode));
   end
   else
-    CalculateLeaf(TBillsIDTreeNode(ANode));
+  begin
+    if IsSpecialNode then
+      CalculateSpecialLeaf(TBillsIDTreeNode(ANode))
+    else
+      CalculateLeaf(TBillsIDTreeNode(ANode));
+  end;
   CalculateNode(ANode.NextSibling);
 end;
 
@@ -716,7 +729,7 @@ procedure TStageData.CalculateLeaf(ANode: TBillsIDTreeNode);
     fPrice: Double;
   begin
     fPrice := GetBillsUnitPriceMargin(ARec.BillsID.AsInteger);
-    ARec.PM_TotalPrice.AsFloat := TotalPriceRoundTo(ARec.GatherQuantity.AsFloat * fPrice);
+    ARec.SetFloatValue(ARec.PM_TotalPrice, TotalPriceRoundTo(ARec.GatherQuantity.AsFloat * fPrice));
   end;
 
 var
@@ -796,19 +809,20 @@ end;
 procedure TStageData.CalculatePriceMarginNode;
 var
   Rec: TStageRecord;
-  fTotalPrice: Double;
+  fDiffer: Double;
 begin
   with TProjectData(TPhaseData(FPhaseData).ProjectData) do
   begin
     Rec := StageRecord(iPriceMarginID);
     if not Assigned(Rec) then
       Rec := AddStageRecord(iPriceMarginID);
-      
-    fTotalPrice := TotalPriceRoundTo(ProjectGLData.PM_TotalPrice - Rec.GatherTotalPrice.AsFloat);
-    if fTotalPrice <> 0 then
+
+    fDiffer := TotalPriceRoundTo(ProjectGLData.PM_TotalPrice - Rec.GatherTotalPrice.AsFloat);
+    if fDiffer <> 0 then
     begin
-      Rec.GatherTotalPrice.AsFloat := Rec.GatherTotalPrice.AsFloat + fTotalPrice;
-      UpdateParentRecord(Rec.BillsID.AsInteger, fTotalPrice, 'GatherTotalPrice');
+      Rec.AddDifferValue(Rec.GatherTotalPrice, fDiffer);
+      Rec.AddDifferValue(Rec.EndGatherTotalPrice, fDiffer);
+      UpdateParentRecord(Rec.BillsID.AsInteger, fDiffer, 'GatherTotalPrice');
     end;
   end;
 end;
@@ -841,7 +855,7 @@ var
 begin
   Rec := StageRecord(ABillsID);
   if not Assigned(Rec) then Exit;
-  
+
   fPM := TotalPriceRoundTo(Rec.GatherQuantity.AsFloat * GetBillsUnitPriceMargin(ABillsID));
   if fPM <> Rec.PM_TotalPrice.AsFloat then
   begin
@@ -849,6 +863,8 @@ begin
     Rec.PM_TotalPrice.AsFloat := fPM;
     UpdateParentPriceMargin(ABillsID, fPMDiffer);
     UpdatePriceMarginNode(fPMDiffer);
+    with TProjectData(TPhaseData(FPhaseData).ProjectData).BillsMeasureData do
+     UpdateRecordPM(ABillsID, fPMDiffer);
   end;
 end;
 
@@ -899,4 +915,25 @@ begin
   end;
 end;
 
+procedure TStageData.CalculateSpecialLeaf(ANode: TBillsIDTreeNode);
+
+  procedure GatherPriceMargin(ARec: TStageRecord);
+  begin
+    with TProjectData(TPhaseData(FPhaseData).ProjectData).ProjectGLData do
+        ARec.SetFloatValue(ARec.GatherTotalPrice, PM_TotalPrice);
+    ARec.SetFloatValue(ARec.EndGatherTotalPrice,
+        ARec.PreGatherTotalPrice.AsFloat + ARec.GatherTotalPrice.AsFloat);
+  end;
+
+var
+  StageRec: TStageRecord;
+begin
+  StageRec := ANode.StageRec;
+  if not Assigned(StageRec) then Exit;
+
+  case ANode.ID of
+    iPriceMarginID: GatherPriceMargin(StageRec);
+  end;
+end;
+
 end.

+ 1 - 1
Forms/SelectDetailGLsFrm.dfm

@@ -4,7 +4,7 @@ object SelectDetailGLsForm: TSelectDetailGLsForm
   Width = 480
   Height = 529
   BorderIcons = [biSystemMenu]
-  Caption = 'SelectDetailGLsForm'
+  Caption = #36873#25321#35843#24046#24037#26009
   Color = clBtnFace
   Font.Charset = DEFAULT_CHARSET
   Font.Color = clWindowText

+ 2 - 2
Frames/ProjectFme.pas

@@ -365,7 +365,7 @@ begin
     jcbAudit.Enabled := True;
     jcbPhase.Items.Add(Format(' µÚ %d ÆÚÊý¾Ý', [jcbPhase.Items.Count + 1]));
     jcbPhase.ItemIndex := jcbPhase.Items.Count - 1;
-    FProjectData.PhaseData.CopyPreData;
+    FProjectData.CopyPreData;
     RefreshProjectState;
 
     if G_IsCloud then
@@ -437,7 +437,7 @@ end;
 procedure TProjectFrame.jcbAuditChanged(Sender: TObject);
 begin
   if FProjectData.PhaseData.StageIndex = jcbAudit.ItemIndex then Exit;
-  FProjectData.PhaseData.StageIndex := jcbAudit.ItemIndex;
+  FProjectData.StageIndex := jcbAudit.ItemIndex;
   RefreshProjectState;
 end;
 

+ 12 - 4
Frames/ProjectGLFme.pas

@@ -50,12 +50,20 @@ begin
 end;
 
 procedure TProjectGLFrame.ResetViewControl;
+var
+  AReadOnly: Boolean;
 begin
   with TProjectData(FProjectGLData.ProjectData) do
-  begin
-    saProjectGL.Columns.ColumnByName('InfoPrice').ReadOnly := PriceMarginReadOnly;
-    saProjectGL.Columns.ColumnByName('InfoDate').ReadOnly := PriceMarginReadOnly;
-  end;
+    AReadOnly := PriceMarginReadOnly;
+
+  saProjectGL.Columns.ColumnByName('Code').ReadOnly := AReadOnly;
+  saProjectGL.Columns.ColumnByName('Name').ReadOnly := AReadOnly;
+  saProjectGL.Columns.ColumnByName('Units').ReadOnly := AReadOnly;
+  saProjectGL.Columns.ColumnByName('Specs').ReadOnly := AReadOnly;
+  saProjectGL.Columns.ColumnByName('BasePrice').ReadOnly := AReadOnly;
+  saProjectGL.Columns.ColumnByName('RiskRange').ReadOnly := AReadOnly;
+  saProjectGL.Columns.ColumnByName('InfoPrice').ReadOnly := AReadOnly;
+  saProjectGL.Columns.ColumnByName('InfoDate').ReadOnly := AReadOnly;
 end;
 
 procedure TProjectGLFrame.zgProjectGLMouseDown(Sender: TObject;

+ 11 - 8
Units/DataBaseTables.pas

@@ -402,7 +402,7 @@ const
 
   {调差工料}
   SProjectGL = 'ProjectGL';
-  tdProjectGL: array [0..17] of TScFieldDef =(
+  tdProjectGL: array [0..16] of TScFieldDef =(
     (FieldName: 'ID'; FieldType: ftInteger; Size: 0; NotNull: True; PrimaryKey: True; ForceUpdate: False),
     // 工料机编号
     (FieldName: 'Code'; FieldType: ftInteger; Size: 0; NotNull: False; PrimaryKey: False; ForceUpdate: False),
@@ -418,8 +418,6 @@ const
     (FieldName: 'RiskRange'; FieldType: ftDouble; Size: 0; NotNull: False; PrimaryKey: False; ForceUpdate: False),
     // 锁定期号: 取值范围0~50, 0表示未锁定, 1~50表示在第1~50期锁定
     (FieldName: 'LockedPhaseID'; FieldType: ftInteger; Size: 0; NotNull: False; PrimaryKey: False; ForceUpdate: False),
-    // 锁定阶段号: 取值范围-1~14, -1表示未锁定, 0表示原报锁定, 1~14表示在1~14审锁定
-    (FieldName: 'LockedStageID'; FieldType: ftInteger; Size: 0; NotNull: False; PrimaryKey: False; ForceUpdate: False),
     // 创建期号: 取值范围0~50(台账编制, 1期~50期)
     (FieldName: 'CreatePhaseID'; FieldType: ftInteger; Size: 0; NotNull: False; PrimaryKey: False; ForceUpdate: False),
     {--------------------Begin 当期缓存数据----------------------}
@@ -444,7 +442,7 @@ const
 
   {调差工料--价格信息及计算}
   SGLPrice = 'GLPrice';
-  tdGLPrice: array [0..37] of TScFieldDef =(
+  tdGLPrice: array [0..39] of TScFieldDef =(
     // 工料ID
     (FieldName: 'GLID'; FieldType: ftInteger; Size: 0; NotNull: True; PrimaryKey: True; ForceUpdate: False),
     // 期号
@@ -491,12 +489,15 @@ const
     (FieldName: 'PM_Quantity13'; FieldType: ftDouble; Size: 0; NotNull: False; PrimaryKey: False; ForceUpdate: False),
     (FieldName: 'PM_TotalPrice13'; FieldType: ftDouble; Size: 0; NotNull: False; PrimaryKey: False; ForceUpdate: False),
     (FieldName: 'PM_Quantity14'; FieldType: ftDouble; Size: 0; NotNull: False; PrimaryKey: False; ForceUpdate: False),
-    (FieldName: 'PM_TotalPrice14'; FieldType: ftDouble; Size: 0; NotNull: False; PrimaryKey: False; ForceUpdate: False)
+    (FieldName: 'PM_TotalPrice14'; FieldType: ftDouble; Size: 0; NotNull: False; PrimaryKey: False; ForceUpdate: False),
+    // 本期 -- 终审数据(当前文件中最后一人的数据)-- 数据缓存
+    (FieldName: 'PM_Quantity_F'; FieldType: ftDouble; Size: 0; NotNull: False; PrimaryKey: False; ForceUpdate: False),
+    (FieldName: 'PM_TotalPrice_F'; FieldType: ftDouble; Size: 0; NotNull: False; PrimaryKey: False; ForceUpdate: False)
   );
 
   {清单使用的工料}
   SDetailGL = 'DetailGL';
-  tdDetailGL: array [0..6] of TScFieldDef =(
+  tdDetailGL: array [0..7] of TScFieldDef =(
     (FieldName: 'ID'; FieldType: ftInteger; Size: 0; NotNull: True; PrimaryKey: True; ForceUpdate: False),
     // 清单ID
     (FieldName: 'BillsID'; FieldType: ftInteger; Size: 0; NotNull: True; PrimaryKey: False; ForceUpdate: False),
@@ -508,8 +509,10 @@ const
     (FieldName: 'Quantity'; FieldType: ftDouble; Size: 0; NotNull: False; PrimaryKey: False; ForceUpdate: False),
     // 创建期号
     (FieldName: 'CreatePhaseID'; FieldType: ftInteger; Size: 0; NotNull: False; PrimaryKey: False; ForceUpdate: False),
-    // 创建阶段
-    (FieldName: 'CreateStageID'; FieldType: ftInteger; Size: 0; NotNull: False; PrimaryKey: False; ForceUpdate: False)
+    // 最新一期最新一阶段的清单计量信息 -- 数据缓存
+    (FieldName: 'LastBillsQuantity'; FieldType: ftInteger; Size: 0; NotNull: False; PrimaryKey: False; ForceUpdate: False),
+    // 锁定期号
+    (FieldName: 'LockedPhaseID'; FieldType: ftInteger; Size: 0; NotNull: False; PrimaryKey: False; ForceUpdate: False)
   );
 
   {各期总数据 -- 为更新项目管理而储存的缓存数据}

+ 79 - 12
Units/ProjectData.pas

@@ -75,6 +75,8 @@ type
     procedure LockBillsBaseData;
     procedure LockDealPaymentData;
     procedure LockBGLData;
+    procedure LockProjectGLData;
+    procedure LockDetailGLData;
 
     procedure UpdatePhaseData;
 
@@ -91,6 +93,8 @@ type
     procedure SetCheckers(const Value: TCheckers);
     function GetStageDataReadOnly: Boolean;
     function GetPriceMarginReadOnly: Boolean;
+    function GetStageIndex: Integer;
+    procedure SetStageIndex(const Value: Integer);
   public
     constructor Create;
     destructor Destroy; override;
@@ -106,7 +110,7 @@ type
     {OpenForSubmit: ProjProperties, StaffData}
     procedure OpenForSubmit(const AFileName: string);
     procedure SaveAsForSubmit(const AFileName: string);
-    {OpenForReply: ProjProperties, StaffData, PhaseData}
+    {OpenForReply: ProjProperties, StaffData, PhaseData, DetailGLData}
     procedure OpenForReply(const AFileName: string);
     procedure SaveForReply(const AFileName: string);
     {OpenForReceive: ProjProperties, StaffData, PhaseData, StageData}
@@ -125,6 +129,7 @@ type
 
     procedure SaveLastestPhaseMainData;
 
+    procedure CopyPreData;
     procedure CreateNewPhase;
 
     {重设所有LookUpDataset连接}
@@ -173,6 +178,7 @@ type
     property BillsBookmarkData: TBillsBookmarkData read FBillsBookmarkData;
     property DealBillsData: TDealBillsData read FDealBillsData;
     property PhaseIndex: Integer read FPhaseIndex write SetPhaseIndex;
+    property StageIndex: Integer read GetStageIndex write SetStageIndex;
     property PhaseData: TPhaseData read FPhaseData;
     property ProjProperties: TProjProperties read FProjProperties;
     property PhaseCompareData: TPhaseCompareData read FPhaseCompareData;
@@ -216,7 +222,8 @@ type
 implementation
 
 uses UtilMethods, Globals, ProjectCommands, sdIDTree, StageDm,
-  ZJJLDm, PHPWebDm, XMLDoc, XMLIntf, ConstUnit, PasswordInputFrm;
+  ZJJLDm, PHPWebDm, XMLDoc, XMLIntf, ConstUnit, PasswordInputFrm,
+  mDataRecord;
 
 { TProjectData }
 
@@ -273,7 +280,6 @@ procedure TProjectData.CreateNewPhase;
 var
   sPhaseFileName: string;
 begin
-  FProjectGLData.Save;
   FBillsData.LockedBaseData;
   FProjProperties.PhaseCount := FProjProperties.PhaseCount + 1;
   FProjProperties.AuditStatus := 0;
@@ -343,6 +349,8 @@ procedure TProjectData.LockedDataForReply;
 begin
   LockBillsBaseData;
   LockDealPaymentData;
+  LockProjectGLData;
+  LockDetailGLData;
   FPhaseData.PhaseProperty.FinalAudit := True;
   // 有顺序限制,谨慎修改
   FProjProperties.AuditCompany := FStaffData.FinalStaffCompany;
@@ -397,8 +405,6 @@ begin
   UpdateSysProgress(65, '正在读取数据');
 
   FBillsBookmarkData.Open;
-  FProjectGLData.Open(FConnection.Connection);
-  FDetailGLData.Open(FConnection.Connection);
   UpdateSysProgress(70, '正在读取数据');
 
   FDealBillsData.Open(FConnection.Connection);
@@ -412,6 +418,9 @@ begin
   OpenLastPhaseData;
   UpdateSysProgress(140, '正在读取数据');
 
+  // 价差数据应在当期数据打开后打开
+  FProjectGLData.Open(FConnection.Connection);
+  FDetailGLData.Open(FConnection.Connection);
   FBGLData.Open(FConnection.Connection);
   UpdateSysProgress(160, '正在读取数据');
 
@@ -430,7 +439,6 @@ begin
   FProjProperties.PhaseIndex := FPhaseIndex;
   FPhaseData.Open(Format('%sPhase%d.dat', [TempPath, FPhaseIndex]));
   ResetPhaseDataLink;
-  FProjectGLData.LoadCurPhaseInfoPrice;
 end;
 
 procedure TProjectData.Save;
@@ -509,6 +517,7 @@ procedure TProjectData.SetPhaseIndex(const Value: Integer);
 
 begin
   SaveLastestPhaseMainData;
+  FProjectGLData.Save;
   FPhaseIndex := Value;
   ProjProperties.PhaseIndex := FPhaseIndex;
   ReCreatePhaseData;
@@ -516,6 +525,7 @@ begin
   ResetPhaseDataLink;
   // 须保存项目工料数据,重新加载当期的项目工料数据
   FProjectGLData.LoadCurPhaseInfoPrice;
+  FProjectGLData.LoadStagePM_CalcData;
   //BillsGatherData.RefreshBills;
 end;
 
@@ -1099,12 +1109,11 @@ end;
 
 procedure TProjectData.CalculateAll;
 begin
-  FBillsCompileData.CalculateAll;
-  FProjectGLData.CalculateAll;
-  if not FPhaseData.StageDataReadOnly then
-    FPhaseData.StageData.CalculateAll;
-  FBillsMeasureData.CalculateAll;
-  // To Do
+  FBillsCompileData.CalculateAll; //台账
+  FProjectGLData.CalculateAll; //工料价差
+  FPhaseData.StageData.CalculateAll; //计量&清单价差
+  FBillsMeasureData.CalculateAll; //累计
+  FPhaseData.PhasePayData.CalculateAll;
 end;
 
 procedure TProjectData.ImportCloudTenderFile(const AFileName: string);
@@ -1338,10 +1347,12 @@ begin
     FPhaseData.SimpleOpen(Format('%sPhase%d.dat', [TempPath, FPhaseIndex]));
   end;
   FStaffData.Open(FConnection.Connection);
+  FDetailGLData.Open(FConnection.Connection);
 end;
 
 procedure TProjectData.SaveForReply(const AFileName: string);
 begin
+  FDetailGLData.Save;
   FStaffData.Save;
   if FPhaseData.Active then
     FPhaseData.SimpleSave;
@@ -1605,4 +1616,60 @@ begin
   end;
 end;
 
+procedure TProjectData.LockProjectGLData;
+const
+  sLockSql = 'Update ProjectGL As P, GLPrice As G' +
+             '  Set P.LockedPhaseID = %d'+
+             '  Where (P.ID = G.GLID) and (G.PM_Quantity_F <> 0) and (IsNull(P.LockedPhaseID) or (P.LockedPhaseID = 0))';
+var
+  sSql: string;
+begin
+  sSql := Format(sLockSql, [FProjProperties.PhaseCount]);
+  ExecuteSql(sSql);
+end;
+
+procedure TProjectData.LockDetailGLData;
+const
+  sLockSql = 'Update DetailGL As D Set D.LockedPhaseID = %d' +
+             '  Where (D.LastBillsQuantity <> 0) and (IsNull(D.LockedPhaseID) or (D.LockedPhaseID = 0))';
+var
+  sSql: string;
+begin
+  sSql := Format(sLockSql, [FProjProperties.PhaseCount]);
+  ExecuteSql(sSql);
+end;
+
+procedure TProjectData.CopyPreData;
+
+  procedure CopyPreGLPrice;
+  const
+    sCopySql = 'Insert Into GLPrice (GLID, PhaseID,' +
+               '    InfoPrice, InfoDate, DeltaPrice, ValidDeltaPrice,' +
+               '    PM_PreQuantity, PM_PreTotalPrice'+
+               '  Select GLID, %d,'+
+               '    InfoPrice, InfoDate, DeltaPrice, ValidDeltaPrice,'+
+               '    PM_PreQuantity+PM_Quantity_F, PM_PreTotalPrice+PM_TotalPrice_F'+
+               '  From GLPrice Where PhaseID = %d';
+  begin
+    if FProjProperties.PhaseCount > 1 then
+      ExecuteSql(Format(sCopySql, [FProjProperties.PhaseCount, FProjProperties.PhaseCount - 1]));
+  end;
+
+begin
+  CopyPreGLPrice;
+  PhaseData.CopyPreData;
+end;
+
+function TProjectData.GetStageIndex: Integer;
+begin
+  Result := FPhaseData.StageIndex;
+end;
+
+procedure TProjectData.SetStageIndex(const Value: Integer);
+begin
+  FProjectGLData.Save;
+  FPhaseData.StageIndex := Value;
+  FProjectGLData.LoadStagePM_CalcData;
+end;
+
 end.

+ 51 - 4
Units/mDataRecord.pas

@@ -6,7 +6,16 @@ uses
   Classes, sdDB;
 
 type
-  TBillsRecord = class(TsdDataRecord)
+  TMeasureBaseRecord = class(TsdDataRecord)
+  public
+    procedure SetFloatValue(AValue: TsdValue; AFloat: Double);
+    procedure SetIntValue(AValue: TsdValue; AInt: Integer);
+    procedure SetBoolValue(AValue: TsdValue; ABool: Boolean);
+
+    procedure AddDifferValue(AValue: TsdValue; ADiffer: Double);
+  end;
+
+  TBillsRecord = class(TMeasureBaseRecord)
   private
     // Ê÷½á¹¹
     FID: TsdValue;
@@ -172,7 +181,7 @@ type
     property PM_AddTotalPrice: TsdValue read FPM_AddTotalPrice;
   end;
 
-  TStageRecord = class(TsdDataRecord)
+  TStageRecord = class(TMeasureBaseRecord)
   private
     FBillsID: TsdValue;
 
@@ -289,7 +298,7 @@ type
     property PM_TotalPrice: TsdValue read FPM_TotalPrice;
   end;
 
-  TProjectGLRecord = class(TsdDataRecord)
+  TProjectGLRecord = class(TMeasureBaseRecord)
   private
     FID: TsdValue;
     FCode: TsdValue;
@@ -336,7 +345,7 @@ type
     property PM_TotalPrice: TsdValue read FPM_TotalPrice;
   end;
 
-  TDetailGLRecord = class(TsdDataRecord)
+  TDetailGLRecord = class(TMeasureBaseRecord)
   private
     FID: TsdValue;
     FBillsID: TsdValue;
@@ -347,6 +356,9 @@ type
 
     FCreatePhaseID: TsdValue;
 
+    FLastBillsQuantity: TsdValue;
+    FLockedPhaseID: TsdValue;
+
     FRelaProjectGL: TProjectGLRecord;
   protected
     procedure DoAfterAddFields; override;
@@ -360,6 +372,9 @@ type
 
     property CreatePhaseID: TsdValue read FCreatePhaseID;
 
+    property LastBillsQuantity: TsdValue read FLastBillsQuantity;
+    property LockedPhaseID: TsdValue read FLockedPhaseID;
+
     property RelaProjectGL: TProjectGLRecord read FRelaProjectGL write FRelaProjectGL;
   end;
 
@@ -553,6 +568,38 @@ begin
   FQuantity := ValueByName('Quantity');
 
   FCreatePhaseID := ValueByName('CreatePhaseID');
+
+  FLastBillsQuantity := ValueByName('LastBillsQuantity');
+  FLockedPhaseID := ValueByName('LockedPhaseID');
+end;
+
+{ TMeasureBaseRecord }
+
+procedure TMeasureBaseRecord.AddDifferValue(AValue: TsdValue;
+  ADiffer: Double);
+begin
+  if ADiffer <> 0 then
+    AValue.AsFloat := AValue.AsFloat + ADiffer;
+end;
+
+procedure TMeasureBaseRecord.SetBoolValue(AValue: TsdValue;
+  ABool: Boolean);
+begin
+  if AValue.AsBoolean <> ABool then
+    AValue.AsBoolean := ABool;
+end;
+
+procedure TMeasureBaseRecord.SetFloatValue(AValue: TsdValue;
+  AFloat: Double);
+begin
+  if AValue.AsFloat <> AFloat then
+    AValue.AsFloat := AFloat;
+end;
+
+procedure TMeasureBaseRecord.SetIntValue(AValue: TsdValue; AInt: Integer);
+begin
+  if AValue.AsInteger <> AInt then
+    AValue.AsInteger := AInt;
 end;
 
 end.