Преглед на файлове

材料调差计算相关,暂无锁定等信息,功能开发中途提交以防代码丢失

MaiXinRong преди 9 години
родител
ревизия
aa13b4cd53

+ 3 - 0
DataModules/BillsCompileDm.pas

@@ -583,6 +583,9 @@ procedure TBillsCompileData.sdvBillsCompileSetText(var Text: String;
     vNode := BillsCompileTree.FindNode(ARecord.ValueByName('ID').AsInteger);
     iCreatePhase := vNode.Rec.ValueByName('CreatePhaseID').AsInteger;
 
+    if vNode.ID = iPriceMarginID then
+      SetTextErrorHint(sBills_PMHint);
+
     if vNode.HasChildren then
     begin
       if Text = '' then

+ 4 - 1
DataModules/BillsDm.dfm

@@ -198,6 +198,9 @@ object BillsData: TBillsData
       02080549734B6579080F4E65656450726F636573734E616D65090001044E616D
       65060D4861734174746163686D656E74094669656C644E616D65060D48617341
       74746163686D656E740844617461547970650205084461746153697A65020105
-      49734B6579080F4E65656450726F636573734E616D65090000}
+      49734B6579080F4E65656450726F636573734E616D65090001044E616D650610
+      504D5F416464546F74616C5072696365094669656C644E616D650610504D5F41
+      6464546F74616C50726963650844617461547970650206084461746153697A65
+      02080549734B6579080F4E65656450726F636573734E616D65090000}
   end
 end

+ 15 - 0
DataModules/BillsMeasureDm.dfm

@@ -205,6 +205,21 @@ object BillsMeasureData: TBillsMeasureData
       end
       item
         FieldName = 'AddCompleteRate'
+      end
+      item
+        FieldName = 'PM_PreTotalPrice'
+        KeyFields = 'ID'
+        LookupKeyFields = 'BillsID'
+        LookupResultField = 'PM_PreTotalPrice'
+      end
+      item
+        FieldName = 'PM_TotalPrice'
+        KeyFields = 'ID'
+        LookupKeyFields = 'BillsID'
+        LookupResultField = 'PM_TotalPrice'
+      end
+      item
+        FieldName = 'PM_AddTotalPrice'
       end>
     AfterAddRecord = sdvBillsMeasureAfterAddRecord
     AfterValueChanged = sdvBillsMeasureAfterValueChanged

+ 11 - 1
DataModules/BillsMeasureDm.pas

@@ -80,7 +80,7 @@ implementation
 
 uses
   ProjectData, PhaseData, Math, ZhAPI, BillsCommand, BGLSelectFrm,
-  BGLDm, UtilMethods, mDataRecord;
+  BGLDm, UtilMethods, mDataRecord, ConstUnit;
 
 {$R *.dfm}
 
@@ -147,6 +147,9 @@ begin
     sdvBillsMeasure.Columns.FindColumn('EndPcTotalPrice').LookupDataSet := StageData.sddStage;
     sdvBillsMeasure.Columns.FindColumn('EndGatherQuantity').LookupDataSet := StageData.sddStage;
     sdvBillsMeasure.Columns.FindColumn('EndGatherTotalPrice').LookupDataSet := StageData.sddStage;
+
+    sdvBillsMeasure.Columns.FindColumn('PM_PreTotalPrice').LookupDataSet := StageData.sddStage;
+    sdvBillsMeasure.Columns.FindColumn('PM_TotalPrice').LookupDataSet := StageData.sddStage;
   end;
 end;
 
@@ -288,6 +291,9 @@ procedure TBillsMeasureData.sdvBillsMeasureSetText(var Text: String;
     vNode := BillsMeasureTree.FindNode(GetBillsID);
     iCreatePhase := vNode.Rec.ValueByName('CreatePhaseID').AsInteger;
 
+    if vNode.ID = iPriceMarginID then
+      DataSetErrorMessage(Allow, sBills_PMHint);
+
     if SameText('B_Code', AColumn.FieldName) or
         SameText('Name', AColumn.FieldName) or
         SameText('Units', AColumn.FieldName) then
@@ -491,6 +497,10 @@ procedure TBillsMeasureData.sdvBillsMeasureNeedLookupRecord(
     iCreatePhase: Integer;
   begin
     Result := True;
+
+    if ANode.ID = iPriceMarginID then
+      DataSetErrorMessage(Result, sBills_PMHint);
+
     if ANode.HasChildren then
     begin
       if ANewText = '' then

+ 1 - 0
DataModules/DetailGLDm.dfm

@@ -12,6 +12,7 @@ object DetailGLData: TDetailGLData
   object sddDetailGL: TsdDataSet
     Active = False
     Provider = sdpDetailGL
+    OnGetRecordClass = sddDetailGLGetRecordClass
     Left = 64
     Top = 80
     FieldListData = {

+ 127 - 36
DataModules/DetailGLDm.pas

@@ -3,16 +3,19 @@ unit DetailGLDm;
 interface
 
 uses
-  SysUtils, Classes, sdDB, sdProvider, ADODB, Variants;
+  SysUtils, Classes, sdDB, sdProvider, ADODB, Variants, mDataRecord;
 
 type
   TDetailGLData = class(TDataModule)
     sdpDetailGL: TsdADOProvider;
     sddDetailGL: TsdDataSet;
+    procedure sddDetailGLGetRecordClass(var ARecordClass: TsdRecordClass);
   private
     FProjectData: TObject;
 
-    function FindDetailGL(ABillsID, AGLID: Integer): TsdDataRecord;
+    procedure LoadRelaProjectGL;
+
+    function FindDetailGL(ABillsID, AGLID: Integer): TDetailGLRecord;
     procedure ClearDetailGLs(ABillsID: Integer);
   public
     constructor Create(AProjectData: TObject);
@@ -22,45 +25,49 @@ type
     procedure Close;
     procedure Save;
 
-    function AddDetailGL(ABillsID: Integer; AGLRec: TsdDataRecord; var sMessage: string): TsdDataRecord;
+    function AddDetailGL(ABillsID: Integer; AProjectGLRec: TProjectGLRecord;
+      var sMessage: string): TDetailGLRecord;
     procedure AddDetailGLs(ABillsID: Integer; AGLs: TList);
 
     procedure LoadDetailGLs(ABillsID: Integer; AGLs: TList);
     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;
+  Math, UtilMethods, ProjectData, ProjectProperty, ProjectGLDm,
+  PriceMarginBillsDm, StageDm, PhasePayDm;
 
 {$R *.dfm}
 
 { TDetailGLData }
 
 function TDetailGLData.AddDetailGL(ABillsID: Integer;
-  AGLRec: TsdDataRecord; var sMessage: string): TsdDataRecord;
+  AProjectGLRec: TProjectGLRecord;
+  var sMessage: string): TDetailGLRecord;
 begin
   sMessage := '';
-  Result := FindDetailGL(ABillsID, AGLRec.ValueByName('ID').AsInteger);
+  Result := FindDetailGL(ABillsID, AProjectGLRec.ID.AsInteger);
   if not Assigned(Result) then
   begin
-    Result := sddDetailGL.Add(True);
-    Result.ValueByName('ID').AsInteger := GetsdDataSetNewID(sddDetailGL, 'idxID');
-    Result.ValueByName('BillsID').AsInteger := ABillsID;
-    Result.ValueByName('GLID').AsInteger := AGLRec.ValueByName('ID').AsInteger;
-    Result.ValueByName('Code').AsString := AGLRec.ValueByName('Code').AsString;
-    with TProjectData(FProjectData).ProjProperties do
-    begin
-      Result.ValueByName('CreatePhaseID').AsInteger := PhaseCount;
-      Result.ValueByName('CreateStageID').AsInteger := AuditStatus;
-    end;    
+    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', [AGLRec.ValueByName('Code').AsString, AGLRec.ValueByName('Name').AsString]);
+    sMessage := Format('编号:%s 名称:%s', [AProjectGLRec.Code.AsString, AProjectGLRec.Name.AsString]);
 end;
 
 procedure TDetailGLData.AddDetailGLs(ABillsID: Integer; AGLs: TList);
@@ -70,7 +77,7 @@ var
 begin
   for i := 0 to AGLs.Count - 1 do
   begin
-    AddDetailGL(ABillsID, TsdDataRecord(AGLs.Items[i]), sMessage);
+    AddDetailGL(ABillsID, TProjectGLRecord(AGLs.Items[i]), sMessage);
     if sMessage <> '' then
     begin
       if sHint <> '' then
@@ -85,7 +92,7 @@ end;
 procedure TDetailGLData.ResetDetailGLs(ABillsID: Integer; AGLs: TList);
 var
   i, iNewID: Integer;
-  Rec, GLRec: TsdDataRecord;
+  Rec, GLRec: TDetailGLRecord;
 begin
   sddDetailGL.BeginUpdate;
   try
@@ -93,18 +100,16 @@ begin
     iNewID := GetsdDataSetNewID(sddDetailGL, 'idxID');
     for i := 0 to AGLs.Count - 1 do
     begin
-      GLRec := TsdDataRecord(AGLs.Items[i]);
-      Rec := sddDetailGL.Add;
-      Rec.ValueByName('ID').AsInteger := iNewID + i;
-      Rec.ValueByName('BillsID').AsInteger := ABillsID;
-      Rec.ValueByName('GLID').AsInteger := GLRec.ValueByName('GLID').AsInteger;
-      Rec.ValueByName('Code').AsInteger := GLRec.ValueByName('Code').AsInteger;
-      Rec.ValueByName('Quantity').AsFloat := GLRec.ValueByName('Quantity').AsFloat;
-      with TProjectData(FProjectData).ProjProperties do
-      begin
-        Rec.ValueByName('CreatePhaseID').AsInteger := PhaseCount;
-        Rec.ValueByName('CreateStageID').AsInteger := AuditStatus;
-      end;
+      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;
@@ -138,6 +143,7 @@ begin
   sddDetailGL.AddIndex('idxFind', 'BillsID;GLID');
   sddDetailGL.AddIndex('idxBillsID', 'BillsID');
   sddDetailGL.AddIndex('idxID', 'ID');
+  sddDetailGL.AddIndex('idxGLID', 'GLID');
 end;
 
 destructor TDetailGLData.Destroy;
@@ -147,18 +153,20 @@ begin
 end;
 
 function TDetailGLData.FindDetailGL(ABillsID,
-  AGLID: Integer): TsdDataRecord;
+  AGLID: Integer): TDetailGLRecord;
 var
   idx: TsdIndex;
 begin
   idx := sddDetailGL.FindIndex('idxFind');
-  Result := idx.FindKey(VarArrayOf([ABillsID, AGLID]));
+  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;
@@ -173,9 +181,92 @@ var
 begin
   idx := sddDetailGL.FindIndex('idxBillsID');
   iFirst := idx.FindKeyIndex(ABillsID);
-  iLast := idx.FindKeyLastIndex(ABillsID);
-  for iRec := iFirst to iLast do
-    AGLs.Add(idx.Records[iRec]);
+  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
+  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;
 
 end.

+ 12 - 0
DataModules/PriceMarginBillsDm.dfm

@@ -92,6 +92,12 @@ object PriceMarginBillsData: TPriceMarginBillsData
       4E616D6506114375724761746865725175616E74697479094669656C644E616D
       6506114375724761746865725175616E74697479084461746154797065020608
       4461746153697A6502080549734B6579080F4E65656450726F636573734E616D
+      65090001044E616D650610504D5F507265546F74616C5072696365094669656C
+      644E616D650610504D5F507265546F74616C5072696365084461746154797065
+      0206084461746153697A6502080549734B6579080F4E65656450726F63657373
+      4E616D65090001044E616D65060D504D5F546F74616C5072696365094669656C
+      644E616D65060D504D5F546F74616C5072696365084461746154797065020608
+      4461746153697A6502080549734B6579080F4E65656450726F636573734E616D
       65090000}
   end
   object sdvGclBills: TsdDataView
@@ -161,9 +167,13 @@ object PriceMarginBillsData: TPriceMarginBillsData
       end
       item
         FieldName = 'CurQcQuantity'
+      end
+      item
+        FieldName = 'PM_TotalPrice'
       end>
     OnFilterRecord = sdvDetailGclBillsFilterRecord
     OnCurrentChanged = sdvDetailGclBillsCurrentChanged
+    OnGetText = sdvDetailGclBillsGetText
     Left = 160
     Top = 136
   end
@@ -198,6 +208,8 @@ object PriceMarginBillsData: TPriceMarginBillsData
       item
         FieldName = 'PM_EndTotalPrice'
       end>
+    AfterDeleteRecord = sdvDetailGLAfterDeleteRecord
+    AfterValueChanged = sdvDetailGLAfterValueChanged
     OnFilterRecord = sdvDetailGLFilterRecord
     Left = 264
     Top = 136

+ 94 - 0
DataModules/PriceMarginBillsDm.pas

@@ -21,6 +21,11 @@ type
     procedure sdvDetailGLFilterRecord(ARecord: TsdDataRecord;
       var Allow: Boolean);
     procedure sdvDetailGclBillsCurrentChanged(ARecord: TsdDataRecord);
+    procedure sdvDetailGLAfterValueChanged(AValue: TsdValue);
+    procedure sdvDetailGclBillsGetText(var Text: String;
+      ARecord: TsdDataRecord; AValue: TsdValue; AColumn: TsdViewColumn;
+      DisplayText: Boolean);
+    procedure sdvDetailGLAfterDeleteRecord(ARecord: TsdDataRecord);
   private
     FProjectData: TObject;
     procedure WriteGclBillsData(AGcls: TList);
@@ -32,6 +37,8 @@ type
     procedure RefreshBills;
     procedure AddDetailGLs(AGls: TList);
 
+    procedure RefreshDetailBills(ABillsID: Integer);
+
     property ProjectData: TObject read FProjectData;
     property MainBillsTree: TBillsIDTree read GetMainBillsTree;
   end;
@@ -59,6 +66,8 @@ begin
   sddDetailGclBills.Open;
   if not Assigned(sddDetailGclBills.FindIndex('idxSerialNo')) then
     sddDetailGclBills.AddIndex('idxSerialNo', 'BillsID;TreeSerialNo');
+  if not Assigned(sddDetailGclBills.FindIndex('idxRelaBills')) then
+    sddDetailGclBills.AddIndex('idxRelaBills', 'RelaBillsID');
   sdvDetailGclBills.Open;
   sdvDetailGclBills.IndexName := 'idxSerialNo';
 
@@ -151,6 +160,9 @@ procedure TPriceMarginBillsData.WriteGclBillsData(AGcls: TList);
       Rec.ValueByName('CurDealQuantity').AsFloat := vDetailGcl.CurDealQuantity;
       Rec.ValueByName('CurQcQuantity').AsFloat := vDetailGcl.CurQcQuantity;
       Rec.ValueByName('CurGatherQuantity').AsFloat := vDetailGcl.CurGatherQuantity;
+
+      Rec.ValueByName('PM_PreTotalPrice').AsFloat := vDetailGcl.PM_PreTotalPrice;
+      Rec.ValueByName('PM_TotalPrice').AsFloat := vDetailGcl.PM_TotalPrice;
     end;
   end;
 
@@ -231,4 +243,86 @@ begin
   sdvDetailGL.RefreshFilter;
 end;
 
+procedure TPriceMarginBillsData.RefreshDetailBills(ABillsID: Integer);
+var
+  Rec: TsdDataRecord;
+  StageRec: TStageRecord;
+begin
+  Rec := sddDetailGclBills.FindKey('idxRelaBills', ABillsID);
+  if not Assigned(Rec) then Exit;
+
+  StageRec := TProjectData(FProjectData).PhaseData.StageData.StageRecord(ABillsID);
+  if Assigned(StageRec) then
+    Rec.ValueByName('PM_TotalPrice').AsFloat := StageRec.PM_TotalPrice.AsFloat;
+end;
+
+procedure TPriceMarginBillsData.sdvDetailGLAfterValueChanged(
+  AValue: TsdValue);
+var
+  ARec: TDetailGLRecord;
+begin
+  if SameText(AValue.FieldName, 'Quantity') then
+  begin
+    ARec := TDetailGLRecord(AValue.Owner);
+    // 更新调差工料--本期价差
+    with TProjectData(FProjectData).ProjectGLData do
+      CalculateGL_PM(ARec.GLID.AsInteger);
+    // 更新清单调差数据,材料调差节点数据
+    with TProjectData(FProjectData).PhaseData.StageData do
+    begin
+      CalculatePriceMargin(ARec.BillsID.AsInteger);
+      CalculatePriceMarginNode;
+    end;
+    // 更新价差清单内存表信息
+    with TProjectData(FProjectData).PriceMarginBillsData do
+      RefreshDetailBills(ARec.BillsID.AsInteger);
+    // 更新合同支付
+    TProjectData(FProjectData).PhaseData.PhasePayData.CalculateAll;
+  end;
+end;
+
+procedure TPriceMarginBillsData.sdvDetailGclBillsGetText(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;
+
+procedure TPriceMarginBillsData.sdvDetailGLAfterDeleteRecord(
+  ARecord: TsdDataRecord);
+var
+  ARec: TDetailGLRecord;
+begin
+  if ARecord.ValueByName('Quantity').AsFloat <> 0 then
+  begin
+    ARec := TDetailGLRecord(ARecord);
+    // 更新调差工料--本期价差
+    with TProjectData(FProjectData).ProjectGLData do
+      CalculateGL_PM(ARec.GLID.AsInteger);
+    // 更新清单调差数据,材料调差节点数据
+    with TProjectData(FProjectData).PhaseData.StageData do
+    begin
+      CalculatePriceMargin(ARec.BillsID.AsInteger);
+      CalculatePriceMarginNode;
+    end;
+    // 更新价差清单内存表信息
+    with TProjectData(FProjectData).PriceMarginBillsData do
+      RefreshDetailBills(ARec.BillsID.AsInteger);
+    // 更新合同支付
+    TProjectData(FProjectData).PhaseData.PhasePayData.CalculateAll;
+  end;
+end;
+
 end.

+ 43 - 13
DataModules/ProjectGLDm.dfm

@@ -14,6 +14,8 @@ object ProjectGLData: TProjectGLData
     Provider = sdpProjectGL
     AfterAddRecord = sddProjectGLAfterAddRecord
     BeforeValueChange = sddProjectGLBeforeValueChange
+    AfterValueChanged = sddProjectGLAfterValueChanged
+    OnGetRecordClass = sddProjectGLGetRecordClass
     Left = 57
     Top = 80
     FieldListData = {
@@ -37,21 +39,29 @@ object ProjectGLData: TProjectGLData
       6D65090001044E616D65060D43726561746550686173654944094669656C644E
       616D65060D437265617465506861736549440844617461547970650203084461
       746153697A6502040549734B6579080F4E65656450726F636573734E616D6509
-      0001044E616D65060D43726561746553746167654944094669656C644E616D65
-      060D437265617465537461676549440844617461547970650203084461746153
+      0001044E616D65060D4C6F636B656450686173654944094669656C644E616D65
+      060D4C6F636B6564506861736549440844617461547970650203084461746153
       697A6502040549734B6579080F4E65656450726F636573734E616D6509000104
-      4E616D65060D4C6F636B656450686173654944094669656C644E616D65060D4C
-      6F636B6564506861736549440844617461547970650203084461746153697A65
+      4E616D65060D4C6F636B656453746167654944094669656C644E616D65060D4C
+      6F636B6564537461676549440844617461547970650203084461746153697A65
       02040549734B6579080F4E65656450726F636573734E616D65090001044E616D
-      65060D4C6F636B656453746167654944094669656C644E616D65060D4C6F636B
-      6564537461676549440844617461547970650203084461746153697A65020405
-      49734B6579080F4E65656450726F636573734E616D65090001044E616D650609
-      496E666F5072696365094669656C644E616D650609496E666F50726963650844
-      617461547970650206084461746153697A6502080549734B6579080F4E656564
-      50726F636573734E616D65090001044E616D650608496E666F44617465094669
-      656C644E616D650608496E666F44617465084461746154797065021808446174
-      6153697A6502140549734B6579080F4E65656450726F636573734E616D650900
-      00}
+      650609496E666F5072696365094669656C644E616D650609496E666F50726963
+      650844617461547970650206084461746153697A6502080549734B6579080F4E
+      65656450726F636573734E616D65090001044E616D650608496E666F44617465
+      094669656C644E616D650608496E666F44617465084461746154797065021808
+      4461746153697A6502140549734B6579080F4E65656450726F636573734E616D
+      65090001044E616D65060A44656C74615072696365094669656C644E616D6506
+      0A44656C746150726963650844617461547970650206084461746153697A6502
+      080549734B6579080F4E65656450726F636573734E616D65090001044E616D65
+      060F56616C696444656C74615072696365094669656C644E616D65060F56616C
+      696444656C746150726963650844617461547970650206084461746153697A65
+      02080549734B6579080F4E65656450726F636573734E616D65090001044E616D
+      65060B504D5F5175616E74697479094669656C644E616D65060B504D5F517561
+      6E746974790844617461547970650206084461746153697A6502080549734B65
+      79080F4E65656450726F636573734E616D65090001044E616D65060D504D5F54
+      6F74616C5072696365094669656C644E616D65060D504D5F546F74616C507269
+      63650844617461547970650206084461746153697A6502080549734B6579080F
+      4E65656450726F636573734E616D65090000}
   end
   object sdvProjectGL: TsdDataView
     Active = False
@@ -72,16 +82,36 @@ object ProjectGLData: TProjectGLData
       end
       item
         FieldName = 'BasePrice'
+        DisplayFormat = '0.##'
       end
       item
         FieldName = 'RiskRange'
+        DisplayFormat = '0.##'
       end
       item
         FieldName = 'InfoPrice'
+        DisplayFormat = '0.##'
       end
       item
         FieldName = 'InfoDate'
+      end
+      item
+        FieldName = 'DeltaPrice'
+        DisplayFormat = '0.##'
+      end
+      item
+        FieldName = 'ValidDeltaPrice'
+        DisplayFormat = '0.##'
+      end
+      item
+        FieldName = 'PM_Quantity'
+        DisplayFormat = '0.##'
+      end
+      item
+        FieldName = 'PM_TotalPrice'
+        DisplayFormat = '0.##'
       end>
+    OnGetText = sdvProjectGLGetText
     Left = 56
     Top = 136
   end

+ 297 - 34
DataModules/ProjectGLDm.pas

@@ -3,7 +3,7 @@ unit ProjectGLDm;
 interface
 
 uses
-  SysUtils, Classes, sdDB, sdProvider, ADODB;
+  SysUtils, Classes, sdDB, sdProvider, ADODB, mDataRecord;
 
 type
   TProjectGLData = class(TDataModule)
@@ -13,12 +13,33 @@ type
     procedure sddProjectGLAfterAddRecord(ARecord: TsdDataRecord);
     procedure sddProjectGLBeforeValueChange(AValue: TsdValue;
       const NewValue: Variant; var Allow: Boolean);
+    procedure sddProjectGLAfterValueChanged(AValue: TsdValue);
+    procedure sdvProjectGLGetText(var Text: String; ARecord: TsdDataRecord;
+      AValue: TsdValue; AColumn: TsdViewColumn; DisplayText: Boolean);
+    procedure sddProjectGLGetRecordClass(var ARecordClass: TsdRecordClass);
   private
     FProjectData: TObject;
+    FTempGLs: TList;
 
     function CheckSameCode(ACode: Integer): Boolean;
 
+    procedure LoadDetailGLs(AGLID: Integer);
+
+    procedure CalculateDeltaPrice(ARec: TProjectGLRecord);
+    procedure CalculatePrice;
+
+    procedure CalculatePM_Quantity(ARec: TProjectGLRecord);
+    procedure CalculatePM_TotalPrice(ARec: TProjectGLRecord);
+    procedure CalculatePriceMargin;
+
+    procedure CalculateRelaBills(ARec: TProjectGLRecord);
+
+    procedure ExecuteSql(const ASql: string);
     procedure SaveGLPrice;
+    procedure SavePM_CurData;
+
+    function GetValidDeltaPrice(AID: Integer): Double;
+    function GetPM_TotalPrice: Double;
   public
     constructor Create(AProjectData: TObject);
     destructor Destroy; override;
@@ -28,13 +49,20 @@ type
 
     procedure LoadCurPhaseInfoPrice;
 
+    procedure CalculateAll;
+    procedure CalculateGL_PM(AGLID: Integer);
+    procedure CalculateGLs_PM(ADetailGLs: TList);
+
     property ProjectData: TObject read FProjectData write FProjectData;
+    property ValidDeltaPrice[AID: Integer]: Double read GetValidDeltaPrice;
+    property PM_TotalPrice: Double read GetPM_TotalPrice;
   end;
 
 implementation
 
 uses
-  ProjectData, UtilMethods, DB, Variants;
+  ProjectData, UtilMethods, DB, Variants, PhaseData, DetailGLDm,
+  BillsMeasureDm, BillsTree, sdIDTree, PhasePayDm, DateUtils;
 
 {$R *.dfm}
 
@@ -52,10 +80,12 @@ constructor TProjectGLData.Create(AProjectData: TObject);
 begin
   inherited Create(nil);
   FProjectData := AProjectData;
+  FTempGLs := TList.Create;
 end;
 
 destructor TProjectGLData.Destroy;
 begin
+  FTempGLs.Free;
   inherited;
 end;
 
@@ -68,15 +98,26 @@ var
 
   procedure LoadInfoPrice;
   var
-    Rec: TsdDataRecord;
+    iRec: Integer;
+    Rec: TProjectGLRecord;
   begin
-    vQuery.First;
-    while not vQuery.Eof do
+    for iRec := 0 to sddProjectGL.RecordCount - 1 do
     begin
-      Rec := sddProjectGL.FindKey('idxID', vQuery.FieldByName('GLID').AsInteger);
-      Rec.ValueByName('InfoPrice').AsFloat := vQuery.FieldByName('InfoPrice').AsFloat;
-      Rec.ValueByName('InfoDate').AsString := vQuery.FieldByName('InfoDate').AsVariant;
-      vQuery.Next;
+      Rec := TProjectGLRecord(sddProjectGL.Records[iRec]);
+      if vQuery.Active and vQuery.Locate('GLID', Rec.ValueByName('ID').AsInteger, []) then
+      begin
+        Rec.InfoPrice.AsFloat := vQuery.FieldByName('InfoPrice').AsFloat;
+        Rec.InfoDate.AsString := vQuery.FieldByName('InfoDate').AsString;
+        Rec.DeltaPrice.AsFloat := vQuery.FieldByName('DeltaPrice').AsFloat;
+        Rec.ValidDeltaPrice.AsFloat := vQuery.FieldByName('ValidDeltaPrice').AsFloat;
+      end
+      else
+      begin
+        Rec.InfoPrice.AsFloat := 0;
+        Rec.InfoDate.AsString := '';
+        Rec.DeltaPrice.AsFloat := 0;
+        Rec.ValidDeltaPrice.AsFloat := 0;
+      end;
     end;
   end;
 
@@ -85,10 +126,10 @@ begin
   vQuery := TADOQuery.Create(nil);
   try
     vQuery.Connection := sdpProjectGL.Connection;
-    sSql := Format(sSql, [TProjectData(FProjectData).PhaseIndex]);
+    sSql := Format(sSelectSql, [TProjectData(FProjectData).PhaseIndex]);
     vQuery.SQL.Clear;
     vQuery.SQL.Add(sSql);
-    vQuery.ExecSQL;
+    vQuery.Open;
     LoadInfoPrice;
   finally
     vQuery.Free;
@@ -111,39 +152,34 @@ end;
 procedure TProjectGLData.Save;
 begin
   sddProjectGL.Save;
-  with TProjectData(FProjectData) do
-    if Assigned(PhaseData) and not PhaseData.StageDataReadOnly and (PhaseData.StageCount > 1) then
-      SaveGLPrice;
+  if not TProjectData(FProjectData).PriceMarginReadOnly then
+    SaveGLPrice;
+  if not TProjectData(FProjectData).StageDataReadOnly then
+    SavePM_CurData;
 end;
 
 procedure TProjectGLData.SaveGLPrice;
 const
   sDeleteSql = 'Delete From GLPrice Where PhaseID = %d';
-const
   sInsertSql = 'Insert Into GLPrice'+
-               '  Select ID As GLID, %d As PhaseID, InfoPrice, InfoDate' +
+               '  Select ID As GLID, %d As PhaseID, InfoPrice, InfoDate, DeltaPrice, ValidDeltaPrice' +
                '  From ProjectGL';
+  sUpdateSql = 'Update GLPrice As G, ProjectGL As P'+
+               '    Set G.PM_PreQuantity = P.PM_PreQuantity, G.PM_PreTotalPrice = P.PM_PreTotalPrice'+
+               '  Where (G.PhaseID = %d) and (G.GLID = P.ID)';
 var
-  vQuery: TADOQuery;
   iPhaseID: Integer;
   sSql: String;
 begin
   iPhaseID := TProjectData(FProjectData).ProjProperties.PhaseCount;
-  vQuery := TADOQuery.Create(nil);
-  try
-    vQuery.Connection := sdpProjectGL.Connection;
-    sSql := Format(sDeleteSql, [iPhaseID]);
-    vQuery.SQL.Clear;
-    vQuery.SQL.Add(sSql);
-    vQuery.ExecSQL;
+  sSql := Format(sDeleteSql, [iPhaseID]);
+  ExecuteSql(sSql);
 
-    sSql := Format(sInsertSql, [iPhaseID]);
-    vQuery.SQL.Clear;
-    vQuery.SQL.Add(sSql);
-    vQuery.ExecSQL;
-  finally
-    vQuery.Free;
-  end;
+  sSql := Format(sInsertSql, [iPhaseID]);
+  ExecuteSql(sSql);
+
+  sSql := Format(sUpdateSql, [iPhaseID]);
+  ExecuteSql(sSql);
 end;
 
 procedure TProjectGLData.sddProjectGLAfterAddRecord(
@@ -151,7 +187,6 @@ procedure TProjectGLData.sddProjectGLAfterAddRecord(
 begin
   ARecord.ValueByName('ID').AsInteger := GetsdDataSetNewID(sddProjectGL, 'idxID');
   ARecord.ValueByName('CreatePhaseID').AsInteger := TProjectData(FProjectData).ProjProperties.PhaseCount;
-  ARecord.ValueByName('CreateStageID').AsInteger := TProjectData(FProjectData).ProjProperties.AuditStatus;
 end;
 
 procedure TProjectGLData.sddProjectGLBeforeValueChange(AValue: TsdValue;
@@ -168,8 +203,7 @@ begin
       Allow := True;
   end
   else if not(SameText(AValue.FieldName, 'ID') or
-      SameText(AValue.FieldName, 'CreatePhaseID') or
-      SameText(AValue.FieldName, 'CreateStageID')) then
+      SameText(AValue.FieldName, 'CreatePhaseID')) then
   begin
     Allow := False;
     if (AValue.Owner.ValueByName('Code').AsString = '') then
@@ -179,4 +213,233 @@ begin
   end;
 end;
 
+procedure TProjectGLData.sddProjectGLAfterValueChanged(AValue: TsdValue);
+begin
+  if SameText(AValue.FieldName, 'BasePrice') or
+     SameText(AValue.FieldName, 'RiskRange') or
+     SameText(AValue.FieldName, 'InfoPrice') then
+  begin
+    CalculateDeltaPrice(TProjectGLRecord(AValue.Owner));
+    CalculatePM_Quantity(TProjectGLRecord(AValue.Owner));
+    CalculatePM_TotalPrice(TProjectGLRecord(AValue.Owner));
+    CalculateRelaBills(TProjectGLRecord(AValue.Owner));
+  end;
+end;
+
+procedure TProjectGLData.CalculateDeltaPrice(ARec: TProjectGLRecord);
+var
+  C0, Ci, r, DeltaC, RiskC, ValidDeltaC: Double;
+begin
+  C0 := ARec.BasePrice.AsFloat;
+  Ci := ARec.InfoPrice.AsFloat;
+  r := ARec.RiskRange.AsFloat;
+
+  DeltaC := Ci - C0;
+  RiskC := C0 * r / 100;
+  if (DeltaC > 0) and (DeltaC - RiskC > 0) then
+    ValidDeltaC := DeltaC - RiskC
+  else if (DeltaC < 0) and (DeltaC + RiskC < 0) then
+    ValidDeltaC := DeltaC + RiskC;
+
+  if DeltaC <> ARec.DeltaPrice.AsFloat then
+    ARec.DeltaPrice.AsFloat := PriceRoundTo(DeltaC);
+  if ValidDeltaC <> ARec.ValidDeltaPrice.AsFloat then
+    ARec.ValidDeltaPrice.AsFloat := PriceRoundTo(ValidDeltaC);
+end;
+
+procedure TProjectGLData.sdvProjectGLGetText(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) or
+        SameText('RiskRange', AColumn.FieldName)) then
+    begin
+      if AValue.AsFloat = 0 then
+        Text := '';
+    end;
+  end;
+
+begin
+  if DisplayText then
+    GetDisplayText;
+end;
+
+procedure TProjectGLData.CalculateAll;
+begin
+  CalculatePrice;
+  CalculatePriceMargin;
+end;
+
+procedure TProjectGLData.ExecuteSql(const ASql: string);
+var
+  vQuery: TADOQuery;
+begin
+  vQuery := TADOQuery.Create(nil);
+  try
+    vQuery.Connection := sdpProjectGL.Connection;
+    vQuery.SQL.Add(ASql);
+    vQuery.ExecSQL;
+  finally
+    vQuery.Free;
+  end;
+end;
+
+function TProjectGLData.GetValidDeltaPrice(AID: Integer): Double;
+var
+  Rec: TProjectGLRecord;
+begin
+  Rec := TProjectGLRecord(sddProjectGL.FindKey('idxID', AID));
+  if Assigned(Rec) then
+    Result := Rec.ValidDeltaPrice.AsFloat
+  else
+    Result := 0;
+end;
+
+procedure TProjectGLData.CalculatePrice;
+var
+  iRec: Integer;
+begin
+  if TProjectData(FProjectData).PriceMarginReadOnly then Exit;
+
+  for iRec := 0 to sddProjectGL.RecordCount - 1 do
+    CalculateDeltaPrice(TProjectGLRecord(sddProjectGL.Records[iRec]));
+end;
+
+procedure TProjectGLData.CalculatePriceMargin;
+var
+  iRec: Integer;
+  Rec: TProjectGLRecord;
+begin
+  if TProjectData(FProjectData).PhaseData.StageDataReadOnly then Exit;
+
+  for iRec := 0 to sddProjectGL.RecordCount - 1 do
+  begin
+    Rec := TProjectGLRecord(sddProjectGL.Records[iRec]);
+    CalculatePM_Quantity(Rec);
+    CalculatePM_TotalPrice(Rec);
+  end;
+end;
+
+procedure TProjectGLData.CalculatePM_Quantity(ARec: TProjectGLRecord);
+var
+  vGLs: TList;
+  fQuantity: Double;
+  i: Integer;
+  GLRec: TsdDataRecord;
+  BillsNode: TBillsIDTreeNode;
+begin
+  vGLs := TList.Create;
+  try
+    fQuantity := 0;
+    with TProjectData(FProjectData).DetailGLData do
+      LoadProjectGL_DetailGLs(ARec.ValueByName('ID').AsInteger, vGLs);
+
+    for i := 0 to vGLs.Count - 1 do
+    begin
+      GLRec := TsdDataRecord(vGLs.Items[i]);
+      with TProjectData(FProjectData).BillsMeasureData do
+        BillsNode := TBillsIDTreeNode(BillsMeasureTree.FindNode(GLRec.ValueByName('BillsID').AsInteger));
+      if Assigned(BillsNode.StageRec) then
+        fQuantity := fQuantity + BillsNode.StageRec.GatherQuantity.AsFloat * GLRec.ValueByName('Quantity').AsFloat;
+    end;
+
+    if fQuantity <> ARec.PM_Quantity.AsFloat then
+      ARec.PM_Quantity.AsFloat := fQuantity;
+  finally
+    vGLs.Free;
+  end;
+end;
+
+procedure TProjectGLData.CalculatePM_TotalPrice(ARec: TProjectGLRecord);
+var
+  fTotalPrice: Double;
+begin
+  fTotalPrice := ARec.ValidDeltaPrice.AsFloat * ARec.PM_Quantity.AsFloat;
+  if fTotalPrice <> ARec.PM_TotalPrice.AsFloat then
+    ARec.PM_TotalPrice.AsFloat := fTotalPrice;
+end;
+
+procedure TProjectGLData.sddProjectGLGetRecordClass(
+  var ARecordClass: TsdRecordClass);
+begin
+  ARecordClass := TProjectGLRecord;
+end;
+
+function TProjectGLData.GetPM_TotalPrice: Double;
+var
+  i: Integer;
+  Rec: TProjectGLRecord;
+begin
+  Result := 0;
+  for i := 0 to sddProjectGL.RecordCount - 1 do
+  begin
+    Rec := TProjectGLRecord(sddProjectGL.Records[i]);
+    Result := Result + Rec.PM_TotalPrice.AsFloat;
+  end;
+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'+
+               '  Where (G.PhaseID = %d) and (G.GLID = P.ID)';
+var
+  iStageIndex: Integer;
+  iPhaseCount: Integer;
+  sSql: string;
+begin
+  iStageIndex := TProjectData(FProjectData).PhaseData.StageIndex;
+  iPhaseCount := TProjectData(FProjectData).ProjProperties.PhaseCount;
+  sSql := Format(sUpdateSql, [iStageIndex, iStageIndex, iPhaseCount]);
+end;
+
+procedure TProjectGLData.CalculateGL_PM(AGLID: Integer);
+var
+  Rec: TProjectGLRecord;
+begin
+  Rec := TProjectGLRecord(sddProjectGL.FindKey('idxID', AGLID));
+  if not Assigned(Rec) then Exit;
+
+  CalculatePM_Quantity(Rec);
+  CalculatePM_TotalPrice(Rec);
+end;
+
+procedure TProjectGLData.CalculateGLs_PM(ADetailGLs: TList);
+var
+  i: Integer;
+  DetailGLRec: TDetailGLRecord;
+begin
+  for i := 0 to ADetailGLs.Count - 1 do
+  begin
+    DetailGLRec := TDetailGLRecord(ADetailGLs.Items[i]);
+    CalculateGL_PM(DetailGLRec.GLID.AsInteger);
+  end;
+end;
+
+procedure TProjectGLData.CalculateRelaBills(ARec: TProjectGLRecord);
+var
+  iGL: Integer;
+  DetailGLRec: TDetailGLRecord;
+begin
+  LoadDetailGLs(ARec.ID.AsInteger);
+  for iGL := 0 to FTempGLs.Count - 1 do
+  begin
+    DetailGLRec := TDetailGLRecord(FTempGLs.Items[iGL]);
+    with TProjectData(FProjectData).PhaseData do
+      StageData.CalculatePriceMargin(DetailGLRec.BillsID.AsInteger);
+  end;
+  with TProjectData(FProjectData).PhaseData do
+    StageData.CalculatePriceMarginNode;
+end;
+
+procedure TProjectGLData.LoadDetailGLs(AGLID: Integer);
+begin
+  FTempGLs.Clear;
+  with TProjectData(FProjectData).DetailGLData do
+    LoadProjectGL_DetailGLs(AGLID, FTempGLs);
+end;
+
 end.

+ 6 - 0
DataModules/StageDm.dfm

@@ -146,6 +146,12 @@ object StageData: TStageData
       6450726F636573734E616D65090001044E616D6506084D61726B4D656D6F0946
       69656C644E616D6506084D61726B4D656D6F0844617461547970650218084461
       746153697A6503FF000549734B6579080F4E65656450726F636573734E616D65
+      090001044E616D650610504D5F507265546F74616C5072696365094669656C64
+      4E616D650610504D5F507265546F74616C507269636508446174615479706502
+      06084461746153697A6502080549734B6579080F4E65656450726F636573734E
+      616D65090001044E616D65060D504D5F546F74616C5072696365094669656C64
+      4E616D65060D504D5F546F74616C507269636508446174615479706502060844
+      61746153697A6502080549734B6579080F4E65656450726F636573734E616D65
       090000}
   end
 end

+ 175 - 21
DataModules/StageDm.pas

@@ -30,6 +30,14 @@ type
 
     procedure UpdateParentRecord(ABillsID: Integer; ATotalPrice: Double; const AFieldName: string);
     procedure UpdateComplete(ABillsID: Integer; AQuantity, ATotalPrice: Double);
+
+    // 向父项增量--PM_TotalPrice
+    procedure UpdateParentPriceMargin(ABillsID: Integer; ADiffer: Double);
+    // 向价差调整节点增量--GatherTotalPrice
+    procedure UpdatePriceMarginNode(ADiffer: Double);
+    // 重新计算相关的项目工料的价差数据
+    procedure UpdateProjectGL(ABillsID: Integer);
+
     procedure CalculateDeal(ABillsID: Integer);
     procedure CalculateQuantityChange(ABillsID: Integer);
     procedure CalculatePriceChange(ABillsID: Integer);
@@ -39,6 +47,8 @@ type
 
     function GetTotalPrice(ABillsID, AType, AStageIndex: Integer): Double;
 
+    function GetBillsUnitPriceMargin(ABillsID: Integer): Double;
+
     function GetBillsPrice(ABillsID: Integer): Double;
     function GetBillsNewPrice(ABillsID: Integer): Double;
     function GetBillsPriceDiffer(ABillsID: Integer): Double;
@@ -62,6 +72,10 @@ type
     procedure Open(AConnection: TADOConnection);
     procedure Save;
 
+    // 计算任一清单节点的价差金额,并增量汇总至父项
+    procedure CalculatePriceMargin(ABillsID: Integer);
+    // 计算材料调差节点
+    procedure CalculatePriceMarginNode;
     procedure CalculateNode(ANode: TsdIDTreeNode);
     procedure CalculateAll;
 
@@ -74,7 +88,10 @@ type
     procedure ReCalculate(ABillsID: Integer);
     procedure UpdateBGLInfo(ARec: TsdDataRecord; const AType: string);
 
+    // 查找
     function StageRecord(ABillsID: Integer): TStageRecord;
+    // 查找,如未找到则新增
+    function StageRecordWithAdd(ABillsID: Integer): TStageRecord;
 
     // 将Bills表中存的累计计量数据拷贝至截止本期计量、截止上期计量,除新增一期计量外不可调用
     procedure CopyPrePhaseData;
@@ -115,7 +132,7 @@ implementation
 
 uses
   ProjectData, BillsDm, PhaseData, Math, BGLDm, BillsMeasureDm,
-  UtilMethods, ConditionalDefines, FormulaCalc;
+  UtilMethods, ConditionalDefines, FormulaCalc, DetailGLDm, ConstUnit;
 
 {$R *.dfm}
 
@@ -181,6 +198,9 @@ begin
   if TPhaseData(FPhaseData).IsLastStage then
     with TProjectData(TPhaseData(FPhaseData).ProjectData).BillsMeasureData do
       UpdateRecordDeal(ABillsID, fQtyDiffer, fTPDiffer);
+
+  CalculatePriceMargin(ABillsID);
+
   TPhaseData(FPhaseData).PhasePayData.CalculateAll;
 end;
 
@@ -233,6 +253,9 @@ begin
   if TPhaseData(FPhaseData).IsLastStage then
     with TProjectData(TPhaseData(FPhaseData).ProjectData).BillsMeasureData do
       UpdateRecordQc(ABillsID, fQtyDiffer, fTPDiffer);
+
+  CalculatePriceMargin(ABillsID);
+
   TPhaseData(FPhaseData).PhasePayData.CalculateAll;
 end;
 
@@ -354,15 +377,19 @@ begin
   if (AValue.FieldName = 'DealQuantity') or
      (AValue.FieldName = 'DealFormula') or
      (AValue.FieldName = 'DealTotalPrice') then
-    CalculateDeal(AValue.Owner.ValueByName('BillsID').AsInteger);
+    CalculateDeal(iBillsID);
   if (AValue.FieldName = 'QcQuantity') or
      (AValue.FieldName = 'QcFormula') or
      (AValue.FieldName = 'QcTotalPrice') then
-    CalculateQuantityChange(AValue.Owner.ValueByName('BillsID').AsInteger);
+    CalculateQuantityChange(iBillsID);
   if (AValue.FieldName = 'PcQuantity') or
      (AValue.FieldName = 'PcFormula') or
      (AValue.FieldName = 'PcTotalPrice') then
-    CalculatePriceChange(AValue.Owner.ValueByName('BillsID').AsInteger);
+    CalculatePriceChange(iBillsID);
+
+  if (AValue.FieldName = 'DealQuantity') or
+     (AValue.FieldName = 'QcQuantity') then
+    UpdateProjectGL(iBillsID);
 end;
 
 function TStageData.GetMainBillsTree: TBillsIDTree;
@@ -399,7 +426,7 @@ procedure TStageData.sddStageBeforeValueChange(AValue: TsdValue;
         DataSetErrorMessage(Allow, '不可超过0号台账合同数量!');
     end;
   end;
-
+  
 begin
   // 不检查超计
   //CheckOverRange;
@@ -453,9 +480,7 @@ var
 begin
   iParentID := MainBillsTree.FindNode(ABillsID).ParentID;
   if iParentID = -1 then Exit;
-  Rec := StageRecord(iParentID);
-  if not Assigned(Rec) then
-    Rec := AddStageRecord(iParentID);
+  Rec := StageRecordWithAdd(iParentID);
   Rec.ValueByName(AFieldName).AsFloat := TotalPriceRoundTo(
       Rec.ValueByName(AFieldName).AsFloat + ATotalPrice);
   Rec.ValueByName('End' + AFieldName).AsFloat := TotalPriceRoundTo(
@@ -551,8 +576,9 @@ begin
         if (Rec.ValueByName('AddGatherTotalPrice').AsFloat = 0) and
            (Rec.ValueByName('AddDealTotalPrice').AsFloat = 0) and
            (Rec.ValueByName('AddQcTotalPrice').AsFloat = 0) and
-           (Rec.ValueByName('AddPcTotalPrice').AsFloat = 0) then Continue;
-           
+           (Rec.ValueByName('AddPcTotalPrice').AsFloat = 0) and
+           (Rec.ValueByName('PM_AddTotalPrice').AsFloat = 0) then Continue;
+
         NewRec := sddStage.Add;
         NewRec.ValueByName('BillsID').AsInteger := Rec.ValueByName('ID').AsInteger;
         NewRec.ValueByName('EndDealQuantity').AsFloat := Rec.ValueByName('AddDealQuantity').AsFloat;
@@ -579,6 +605,8 @@ begin
         NewRec.ValueByName('PrePcBGLNum').AsString := Rec.ValueByName('AddPcBGLNum').AsString;
         NewRec.ValueByName('PreGatherQuantity').AsFloat := Rec.ValueByName('AddGatherQuantity').AsFloat;
         NewRec.ValueByName('PreGatherTotalPrice').AsFloat := Rec.ValueByName('AddGatherTotalPrice').AsFloat;
+
+        NewRec.ValueByName('PM_PreTotalPrice').AsFloat := Rec.ValueByName('PM_AddTotalPrice').AsFloat;
       end;
   finally
     AfterBatchOperation;
@@ -622,13 +650,14 @@ procedure TStageData.CalculateParent(ANode: TBillsIDTreeNode);
 var
   iChild: Integer;
   ChildNode: TBillsIDTreeNode;
-  fDeal, fQc, fPc: Double;
+  fDeal, fQc, fPc, fPM: Double;
 begin
   if not Assigned(ANode.StageRec) then Exit;
 
   fDeal := 0;
   fQc := 0;
-  FPc := 0;
+  fPc := 0;
+  fPM := 0;
   for iChild := 0 to ANode.ChildCount - 1 do
   begin
     ChildNode := TBillsIDTreeNode(ANode.ChildNodes[iChild]);
@@ -636,19 +665,28 @@ begin
     fDeal := TotalPriceRoundTo(fDeal + ChildNode.StageRec.DealTotalPrice.AsFloat);
     fQc := TotalPriceRoundTo(fQc + ChildNode.StageRec.QcTotalPrice.AsFloat);
     fPc := TotalPriceRoundTo(fPc + ChildNode.StageRec.PcTotalPrice.AsFloat);
+    fPM := TotalPriceRoundTo(fPM + ChildNode.StageRec.PM_TotalPrice.AsFloat);
   end;
 
   with ANode.StageRec do
   begin
-    DealTotalPrice.AsFloat := fDeal;
-    QcTotalPrice.AsFloat := fQc;
-    PcTotalPrice.AsFloat := fPc;
-    GatherTotalPrice.AsFloat := TotalPriceRoundTo(fDeal + fQc + fPc);
-    EndDealTotalPrice.AsFloat := TotalPriceRoundTo(PreDealTotalPrice.AsFloat + fDeal);
-    EndQcTotalPrice.AsFloat := TotalPriceRoundTo(PreQcTotalPrice.AsFloat + fQc);
-    EndPcTotalPrice.AsFloat := TotalPriceRoundTo(PrePcTotalPrice.AsFloat + fPc);
-    EndGatherTotalPrice.AsFloat := TotalPriceRoundTo(
-      PreGatherTotalPrice.AsFloat + GatherTotalPrice.AsFloat);
+    if (DealTotalPrice.AsFloat <> fDeal) or
+       (QcTotalPrice.AsFloat <> fQc) or
+       (PcTotalPrice.AsFloat <> fPc) then
+    begin
+      DealTotalPrice.AsFloat := fDeal;
+      QcTotalPrice.AsFloat := fQc;
+      PcTotalPrice.AsFloat := fPc;
+      GatherTotalPrice.AsFloat := TotalPriceRoundTo(fDeal + fQc + fPc);
+      EndDealTotalPrice.AsFloat := TotalPriceRoundTo(PreDealTotalPrice.AsFloat + fDeal);
+      EndQcTotalPrice.AsFloat := TotalPriceRoundTo(PreQcTotalPrice.AsFloat + fQc);
+      EndPcTotalPrice.AsFloat := TotalPriceRoundTo(PrePcTotalPrice.AsFloat + fPc);
+      EndGatherTotalPrice.AsFloat := TotalPriceRoundTo(
+        PreGatherTotalPrice.AsFloat + GatherTotalPrice.AsFloat);
+    end;
+
+    if PM_TotalPrice.AsFloat <> fPM then
+      PM_TotalPrice.AsFloat := fPM;
   end;
 end;
 
@@ -673,6 +711,14 @@ procedure TStageData.CalculateLeaf(ANode: TBillsIDTreeNode);
       ARec.ValueByName('Pre' + AType + 'TotalPrice').AsFloat + ARec.ValueByName(AType + 'TotalPrice').AsFloat);
   end;
 
+  procedure CalculatePriceMargin(ARec: TStageRecord);
+  var
+    fPrice: Double;
+  begin
+    fPrice := GetBillsUnitPriceMargin(ARec.BillsID.AsInteger);
+    ARec.PM_TotalPrice.AsFloat := TotalPriceRoundTo(ARec.GatherQuantity.AsFloat * fPrice);
+  end;
+
 var
   Rec: TStageRecord;
 begin
@@ -689,6 +735,8 @@ begin
       Rec.PreGatherQuantity.AsFloat + Rec.GatherQuantity.AsFloat);
   Rec.EndGatherTotalPrice.AsFloat := TotalPriceRoundTo(
       Rec.PreGatherTotalPrice.AsFloat + Rec.GatherTotalPrice.AsFloat);
+      
+  CalculatePriceMargin(Rec);
 end;
 
 function TStageData.GetActive: Boolean;
@@ -745,4 +793,110 @@ begin
   end;
 end;
 
+procedure TStageData.CalculatePriceMarginNode;
+var
+  Rec: TStageRecord;
+  fTotalPrice: 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
+    begin
+      Rec.GatherTotalPrice.AsFloat := Rec.GatherTotalPrice.AsFloat + fTotalPrice;
+      UpdateParentRecord(Rec.BillsID.AsInteger, fTotalPrice, 'GatherTotalPrice');
+    end;
+  end;
+end;
+
+function TStageData.GetBillsUnitPriceMargin(ABillsID: Integer): Double;
+var
+  vGLs: TList;
+  iGL: Integer;
+  GLRec: TDetailGLRecord;
+begin
+  Result := 0;
+  vGLs := TList.Create;
+  try
+    with TProjectData(TPhaseData(FPhaseData).ProjectData).DetailGLData do
+      LoadDetailGLs(ABillsID, vGLs);
+    for iGL := 0 to vGLs.Count - 1 do
+    begin
+      GLRec := TDetailGLRecord(vGLs.Items[iGL]);
+      Result := Result + GLRec.Quantity.AsFloat * GLRec.RelaProjectGL.ValidDeltaPrice.AsFloat;
+    end;
+  finally
+    vGLs.Free;
+  end;
+end;
+
+procedure TStageData.CalculatePriceMargin(ABillsID: Integer);
+var
+  Rec: TStageRecord;
+  fPM, fPMDiffer: Double;
+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
+    fPMDiffer := fPM - Rec.PM_TotalPrice.AsFloat;
+    Rec.PM_TotalPrice.AsFloat := fPM;
+    UpdateParentPriceMargin(ABillsID, fPMDiffer);
+    UpdatePriceMarginNode(fPMDiffer);
+  end;
+end;
+
+procedure TStageData.UpdatePriceMarginNode(ADiffer: Double);
+var
+  Rec: TStageRecord;
+begin
+  Rec := StageRecord(iPriceMarginID);
+  Rec.GatherTotalPrice.AsFloat := Rec.GatherTotalPrice.AsFloat + ADiffer;
+  UpdateParentRecord(iPriceMarginID, ADiffer, 'GatherTotalPrice');
+end;
+
+procedure TStageData.UpdateParentPriceMargin(ABillsID: Integer; ADiffer: Double);
+var
+  iParentID: Integer;
+  Rec: TStageRecord;
+begin
+  iParentID := MainBillsTree.FindNode(ABillsID).ParentID;
+  if iParentID = -1 then Exit;
+
+  Rec := StageRecordWithAdd(iParentID);
+  Rec.PM_TotalPrice.AsFloat := TotalPriceRoundTo(Rec.PM_TotalPrice.AsFloat + ADiffer);
+  UpdateParentPriceMargin(iParentID, ADiffer);
+end;
+
+function TStageData.StageRecordWithAdd(ABillsID: Integer): TStageRecord;
+begin
+  Result := StageRecord(ABillsID);
+  if not Assigned(Result) then
+    Result := AddStageRecord(ABillsID);
+end;
+
+procedure TStageData.UpdateProjectGL(ABillsID: Integer);
+var
+  vGLs: TList;
+  iGL: Integer;
+  GLRec: TDetailGLRecord;
+begin
+  vGLs := TList.Create;
+  try
+    with TProjectData(TPhaseData(FPhaseData).ProjectData) do
+    begin
+      DetailGLData.LoadDetailGLs(ABillsID, vGLs);
+      ProjectGLData.CalculateGLs_PM(vGLs);
+    end;
+  finally
+    vGLs.Free;
+  end;
+end;
+
 end.

+ 7 - 0
Forms/MainFrm.dfm

@@ -981,6 +981,13 @@ object MainForm: TMainForm
       Hint = #24212#29992#35843#24046#24037#26009#33267#30456#21516#28165#21333
       Visible = ivAlways
     end
+    object dxbtnCalculatePriceMargin: TdxBarButton
+      Caption = #20215#24046#35745#31639
+      Category = 0
+      Hint = #20215#24046#35745#31639
+      Visible = ivAlways
+      ImageIndex = 15
+    end
   end
   object Images: TImageList
     DrawingStyle = dsTransparent

+ 1 - 0
Forms/MainFrm.pas

@@ -146,6 +146,7 @@ type
     dxbtnAddDetailGLs: TdxBarButton;
     dxbtnCopyDetailGls: TdxBarButton;
     dxbtnApplyToSameBills: TdxBarButton;
+    dxbtnCalculatePriceMargin: TdxBarButton;
     procedure FormCreate(Sender: TObject);
     procedure FormDestroy(Sender: TObject);
     procedure jtsProjectsChange(Sender: TObject; NewTab: Integer;

+ 22 - 1
Frames/PriceMarginBillsFme.dfm

@@ -186,7 +186,7 @@ object PriceMarginBillsFrame: TPriceMarginBillsFrame
           Height = 187
           Options = [goRangeSelect, goRowSizing, goColSizing, goCellNotMaintainData, goFixedRowShowNo, goFixedColShowNo, goAlwaysShowSelection]
           OptionsEx = []
-          ColCount = 12
+          ColCount = 13
           RowCount = 6
           FixedRowCount = 2
           ShowGridLine = False
@@ -536,6 +536,25 @@ object PriceMarginBillsFrame: TPriceMarginBillsFrame
         FieldName = 'CurGatherQuantity'
         Width = 60
         ReadOnly = True
+      end
+      item
+        Title.Caption = #26412#26399#20215#24046
+        Title.CaptionAcrossCols = '1'
+        Title.CaptionAcrossRows = 2
+        Title.Font.Charset = GB2312_CHARSET
+        Title.Font.Color = clWindowText
+        Title.Font.Height = -12
+        Title.Font.Name = #23435#20307
+        Title.Font.Style = []
+        Alignment = taRightJustify
+        Font.Charset = GB2312_CHARSET
+        Font.Color = clWindowText
+        Font.Height = -12
+        Font.Name = #23435#20307
+        Font.Style = []
+        FieldName = 'PM_TotalPrice'
+        Width = 60
+        ReadOnly = True
       end>
     Grid = zgDetailGclBills
     ExtendRowCount = 3
@@ -645,6 +664,7 @@ object PriceMarginBillsFrame: TPriceMarginBillsFrame
       Caption = #26032#22686#35843#24046#24037#26009
       ImageIndex = 2
       OnExecute = actnAddDetailGLsExecute
+      OnUpdate = actnAddDetailGLsUpdate
     end
     object actnCopyDetailGLs: TAction
       Caption = #22797#21046#35843#24046#24037#26009
@@ -653,6 +673,7 @@ object PriceMarginBillsFrame: TPriceMarginBillsFrame
     object actnApplyToSameBills: TAction
       Caption = #24212#29992#35843#24046#24037#26009#33267#30456#21516#28165#21333
       OnExecute = actnApplyToSameBillsExecute
+      OnUpdate = actnAddDetailGLsUpdate
     end
   end
   object dxpmDetailGclBills: TdxBarPopupMenu

+ 26 - 4
Frames/PriceMarginBillsFme.pas

@@ -47,6 +47,7 @@ type
     procedure actnApplyToSameBillsExecute(Sender: TObject);
     procedure zgDetailGclBillsMouseDown(Sender: TObject;
       Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
+    procedure actnAddDetailGLsUpdate(Sender: TObject);
   private
     FPriceMarginBillsData: TPriceMarginBillsData;
     FProjectGLData: TProjectGLData;
@@ -56,6 +57,8 @@ type
   public
     constructor Create(APriceMarginBillsData: TPriceMarginBillsData);
     destructor Destroy; override;
+
+    procedure ResetViewControl;
   end;
 
 implementation
@@ -104,10 +107,8 @@ var
 begin
   iID := saDetailGclBills.DataView.Current.ValueByName('RelaBillsID').AsInteger;
   vNode := TBillsIDTreeNode(FPriceMarginBillsData.MainBillsTree.FindNode(iID));
-  if not vNode.HasPriceMargin then
-    AddDetailGLs
-  else
-    ErrorMessage('当前清单已进行材料调差,不可再添加调差工料。');
+  AddDetailGLs
+  {  ErrorMessage('当前清单已进行材料调差,不可再添加调差工料。');}
 end;
 
 procedure TPriceMarginBillsFrame.AddDetailGLs;
@@ -146,7 +147,15 @@ begin
     begin
       Rec := saDetailGclBills.DataView.Records[iRec];
       if Rec <> CurRec then
+      begin
         FDetailGLData.ResetDetailGLs(Rec.ValueByName('RelaBillsID').AsInteger, vGLs);
+        // 应重新计算清单
+        with TProjectData(FPriceMarginBillsData.ProjectData) do
+          PhaseData.StageData.CalculatePriceMargin(Rec.ValueByName('RelaBillsID').AsInteger);
+        FPriceMarginBillsData.RefreshDetailBills(Rec.ValueByName('RelaBillsID').AsInteger);
+      end;
+      // 应重新计算使用到的工料
+      FProjectGLData.CalculateGLs_PM(vGLs);
     end;
   finally
     vGLs.Free;
@@ -160,4 +169,17 @@ begin
     dxpmDetailGclBills.PopupFromCursorPos;
 end;
 
+procedure TPriceMarginBillsFrame.actnAddDetailGLsUpdate(Sender: TObject);
+begin
+  TAction(Sender).Enabled := not TProjectData(FPriceMarginBillsData.ProjectData).PriceMarginReadOnly;
+end;
+
+procedure TPriceMarginBillsFrame.ResetViewControl;
+begin
+  with TProjectData(FPriceMarginBillsData.ProjectData) do
+  begin
+    saDetailGL.Columns.ColumnByName('Quantity').ReadOnly := PriceMarginReadOnly;
+  end;
+end;
+
 end.

+ 8 - 0
Frames/PriceMarginFme.pas

@@ -29,6 +29,8 @@ type
     destructor Destroy; override;
 
     procedure RefreshBills;
+
+    procedure ResetViewControl;
   end;
 
 implementation
@@ -64,6 +66,12 @@ begin
   FProjectData.PriceMarginBillsData.RefreshBills;
 end;
 
+procedure TPriceMarginFrame.ResetViewControl;
+begin
+  FProjectGLFrame.ResetViewControl;
+  FPriceMarginBillsFrame.ResetViewControl;
+end;
+
 procedure TPriceMarginFrame.tobtnBillsClick(Sender: TObject);
 begin
   tobtnGL.Down := tobtnGL.Tag = TToolButton(Sender).Tag;

+ 15 - 3
Frames/ProjectFme.pas

@@ -526,7 +526,6 @@ procedure TProjectFrame.dxsbViewControlItemClick(Sender: TObject;
     case Item.Tag of
       0, 2: jpsMain.ActivePageIndex := Item.Tag;
       1, 3: if CheckMeasureEdition then jpsMain.ActivePageIndex := Item.Tag;
-      //2: if CheckPlanEdition then jpsMain.ActivePageIndex := Item.Tag;
     end;
     AfterChangeView;
   end;
@@ -560,12 +559,23 @@ procedure TProjectFrame.dxsbViewControlItemClick(Sender: TObject;
         jpsMain.ActivePageIndex := Item.Tag;
       end;
       AfterChangeView;
-    finally             
+    finally
       Screen.Cursor := crDefault;
       CloseProgressHint;
     end;
   end;
 
+  procedure DispalyPriceMargin;
+  begin
+    if ProjectData.ProjProperties.PhaseCount = 0 then
+    begin
+      TipMessage('未计量前不可进行材料调差。');
+      dxsbViewControl.SelectedItem := dxsbViewControl.ActiveGroup.Items[jpsMain.ActivePageIndex];
+      Abort;
+    end;
+    ChangeView;
+  end;
+
 begin
   if Item.Tag = jpsMain.ActivePageIndex then Exit;
 
@@ -573,7 +583,8 @@ begin
     CloseCompare;
 
   case Item.Tag of
-    0..3: ChangeView;
+    0..2: ChangeView;
+    3: DispalyPriceMargin;
     4: DisplayCompare;
     5: DisplayReports;
   end;
@@ -1319,6 +1330,7 @@ begin
   FBillsCompileFrame.RefreshPhase_Stage;
   FBillsMeasureFrame.RefreshPhase_Stage;
   FDealPaymentFrame.RefreshPhase_Stage;
+  FPriceMarginFrame.ResetViewControl;
 end;
 
 procedure TProjectFrame.ExpandCurPhase;

+ 93 - 5
Frames/ProjectGLFme.dfm

@@ -1,17 +1,17 @@
 object ProjectGLFrame: TProjectGLFrame
   Left = 0
   Top = 0
-  Width = 665
+  Width = 946
   Height = 313
   TabOrder = 0
   object zgProjectGL: TZJGrid
     Left = 0
     Top = 0
-    Width = 665
+    Width = 946
     Height = 313
     Options = [goRangeSelect, goRowSizing, goColSizing, goCellNotMaintainData, goFixedRowShowNo, goFixedColShowNo, goAlwaysShowSelection]
     OptionsEx = []
-    ColCount = 9
+    ColCount = 13
     RowCount = 6
     FixedRowCount = 2
     ShowGridLine = False
@@ -142,13 +142,13 @@ object ProjectGLFrame: TProjectGLFrame
       end
       item
         Title.Caption = #26412#26399#20449#24687#20215'|'#20215#26684
-        Title.CaptionAcrossCols = '2'
+        Title.CaptionAcrossCols = '4'
         Title.Font.Charset = GB2312_CHARSET
         Title.Font.Color = clWindowText
         Title.Font.Height = -12
         Title.Font.Name = #23435#20307
         Title.Font.Style = []
-        Alignment = taLeftJustify
+        Alignment = taRightJustify
         Font.Charset = GB2312_CHARSET
         Font.Color = clWindowText
         Font.Height = -12
@@ -174,6 +174,78 @@ object ProjectGLFrame: TProjectGLFrame
         Font.Style = []
         FieldName = 'InfoDate'
         ReadOnly = False
+      end
+      item
+        Title.Caption = '|'#20215#24046
+        Title.CaptionAcrossCols = '1'
+        Title.Font.Charset = GB2312_CHARSET
+        Title.Font.Color = clWindowText
+        Title.Font.Height = -12
+        Title.Font.Name = #23435#20307
+        Title.Font.Style = []
+        Alignment = taRightJustify
+        Font.Charset = GB2312_CHARSET
+        Font.Color = clWindowText
+        Font.Height = -12
+        Font.Name = #23435#20307
+        Font.Style = []
+        FieldName = 'DeltaPrice'
+        Width = 60
+        ReadOnly = True
+      end
+      item
+        Title.Caption = '|'#26377#25928#20215#24046
+        Title.CaptionAcrossCols = '1'
+        Title.Font.Charset = GB2312_CHARSET
+        Title.Font.Color = clWindowText
+        Title.Font.Height = -12
+        Title.Font.Name = #23435#20307
+        Title.Font.Style = []
+        Alignment = taRightJustify
+        Font.Charset = GB2312_CHARSET
+        Font.Color = clWindowText
+        Font.Height = -12
+        Font.Name = #23435#20307
+        Font.Style = []
+        FieldName = 'ValidDeltaPrice'
+        Width = 60
+        ReadOnly = True
+      end
+      item
+        Title.Caption = #26412#26399#20215#24046#35745#31639'|'#25968#37327
+        Title.CaptionAcrossCols = '2'
+        Title.Font.Charset = GB2312_CHARSET
+        Title.Font.Color = clWindowText
+        Title.Font.Height = -12
+        Title.Font.Name = #23435#20307
+        Title.Font.Style = []
+        Alignment = taRightJustify
+        Font.Charset = GB2312_CHARSET
+        Font.Color = clWindowText
+        Font.Height = -12
+        Font.Name = #23435#20307
+        Font.Style = []
+        FieldName = 'PM_Quantity'
+        Width = 60
+        ReadOnly = True
+      end
+      item
+        Title.Caption = '|'#37329#39069
+        Title.CaptionAcrossCols = '1'
+        Title.Font.Charset = GB2312_CHARSET
+        Title.Font.Color = clWindowText
+        Title.Font.Height = -12
+        Title.Font.Name = #23435#20307
+        Title.Font.Style = []
+        Alignment = taRightJustify
+        Font.Charset = GB2312_CHARSET
+        Font.Color = clWindowText
+        Font.Height = -12
+        Font.Name = #23435#20307
+        Font.Style = []
+        FieldName = 'PM_TotalPrice'
+        Width = 60
+        ReadOnly = True
       end>
     Grid = zgProjectGL
     ExtendRowCount = 3
@@ -184,6 +256,11 @@ object ProjectGLFrame: TProjectGLFrame
     BarManager = MainForm.dxBarManager
     ItemLinks = <
       item
+        Item = MainForm.dxbtnCalculatePriceMargin
+        Visible = True
+      end
+      item
+        BeginGroup = True
         Item = MainForm.dxbtnCopy
         Visible = True
       end
@@ -197,7 +274,18 @@ object ProjectGLFrame: TProjectGLFrame
         Visible = True
       end>
     UseOwnFont = False
+    OnPopup = dxpmProjectGLPopup
     Left = 152
     Top = 88
   end
+  object actnProjectGL: TActionList
+    Images = MainForm.Images
+    Left = 208
+    Top = 88
+    object actnCalculatePriceMargin: TAction
+      Caption = #20215#24046#35745#31639
+      ImageIndex = 15
+      OnExecute = actnCalculatePriceMarginExecute
+    end
+  end
 end

+ 33 - 1
Frames/ProjectGLFme.pas

@@ -5,24 +5,33 @@ interface
 uses
   ProjectGLDm,
   Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, 
-  Dialogs, sdGridDBA, ZJGrid, dxBar;
+  Dialogs, sdGridDBA, ZJGrid, dxBar, ActnList;
 
 type
   TProjectGLFrame = class(TFrame)
     zgProjectGL: TZJGrid;
     saProjectGL: TsdGridDBA;
     dxpmProjectGL: TdxBarPopupMenu;
+    actnProjectGL: TActionList;
+    actnCalculatePriceMargin: TAction;
     procedure zgProjectGLMouseDown(Sender: TObject; Button: TMouseButton;
       Shift: TShiftState; X, Y: Integer);
+    procedure dxpmProjectGLPopup(Sender: TObject);
+    procedure actnCalculatePriceMarginExecute(Sender: TObject);
   private
     FProjectGLData: TProjectGLData;
   public
     constructor Create(AProjectGLData: TProjectGLData);
     destructor Destroy; override;
+
+    procedure ResetViewControl;
   end;
 
 implementation
 
+uses
+  ProjectData, MainFrm, UtilMethods;
+
 {$R *.dfm}
 
 { TProjectGLFrame }
@@ -32,6 +41,7 @@ begin
   inherited Create(nil);
   FProjectGLData := AProjectGLData;
   saProjectGL.DataView := FProjectGLData.sdvProjectGL;
+  ResetViewControl;
 end;
 
 destructor TProjectGLFrame.Destroy;
@@ -39,6 +49,15 @@ begin
   inherited;
 end;
 
+procedure TProjectGLFrame.ResetViewControl;
+begin
+  with TProjectData(FProjectGLData.ProjectData) do
+  begin
+    saProjectGL.Columns.ColumnByName('InfoPrice').ReadOnly := PriceMarginReadOnly;
+    saProjectGL.Columns.ColumnByName('InfoDate').ReadOnly := PriceMarginReadOnly;
+  end;
+end;
+
 procedure TProjectGLFrame.zgProjectGLMouseDown(Sender: TObject;
   Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
 begin
@@ -46,4 +65,17 @@ begin
     dxpmProjectGL.PopupFromCursorPos;
 end;
 
+procedure TProjectGLFrame.dxpmProjectGLPopup(Sender: TObject);
+begin
+  SetDxBtnAction(actnCalculatePriceMargin, MainForm.dxbtnCalculatePriceMargin);
+end;
+
+procedure TProjectGLFrame.actnCalculatePriceMarginExecute(Sender: TObject);
+begin
+  if TProjectData(FProjectGLData.ProjectData).PhaseData.StageDataReadOnly then
+    TipMessage('历史数据不可重新计算。')
+  else
+    TProjectData(FProjectGLData.ProjectData).CalculatePriceMargin;
+end;
+
 end.

+ 3 - 0
Units/ConstUnit.pas

@@ -16,6 +16,9 @@ const
   iTotalPriceDigit = 0;
 
   iMaxStageCount = 15;
+// 固定ID
+  iPriceMarginID = 54;
+  sBills_PMHint = '该清单为材料调差清单节点,结果由材料调差计算得到,不可编辑。';
 
 {$O-}
   {$IFDEF _mCloud}

+ 70 - 19
Units/DataBaseTables.pas

@@ -103,7 +103,7 @@ const
 
   {清单数据 -- 台账编辑界面}
   SBills = 'Bills';
-  tdBills: array [0..78] of TScFieldDef =(
+  tdBills: array [0..79] of TScFieldDef =(
     (FieldName: 'ID'; FieldType: ftInteger; Size: 0; NotNull: True; PrimaryKey: True; ForceUpdate: False),
     (FieldName: 'ParentID'; FieldType: ftInteger; Size: 0; NotNull: True; PrimaryKey: False; ForceUpdate: False),
     (FieldName: 'NextSiblingID'; FieldType: ftInteger; Size: 0; NotNull: True; PrimaryKey: False; ForceUpdate: False),
@@ -266,8 +266,9 @@ const
     // 签约清单数量
     (FieldName: 'GclDealQuantity'; FieldType: ftDouble; Size: 0; NotNull: False; PrimaryKey: False; ForceUpdate: False),
     // 签约清单金额
-    (FieldName: 'GclDealTotalPrice'; FieldType: ftDouble; Size: 0; NotNull: False; PrimaryKey: False; ForceUpdate: False)
+    (FieldName: 'GclDealTotalPrice'; FieldType: ftDouble; Size: 0; NotNull: False; PrimaryKey: False; ForceUpdate: False),
     {------------------ End Reports --------------------------}
+    (FieldName: 'PM_AddTotalPrice'; FieldType: ftDouble; Size: 0; NotNull: False; PrimaryKey: False; ForceUpdate: False)
   );
 
   {合同支付}
@@ -401,7 +402,7 @@ const
 
   {调差工料}
   SProjectGL = 'ProjectGL';
-  tdProjectGL: array [0..12] of TScFieldDef =(
+  tdProjectGL: array [0..17] 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),
@@ -419,18 +420,31 @@ const
     (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, 0
+    // 创建期号: 取值范围0~50(台账编制, 1期~50期)
     (FieldName: 'CreatePhaseID'; FieldType: ftInteger; Size: 0; NotNull: False; PrimaryKey: False; ForceUpdate: False),
-    (FieldName: 'CreateStageID'; FieldType: ftInteger; Size: 0; NotNull: False; PrimaryKey: False; ForceUpdate: False),
-    // 当期信息价
+    {--------------------Begin 当期缓存数据----------------------}
+    // 信息价
     (FieldName: 'InfoPrice'; FieldType: ftDouble; Size: 0; NotNull: False; PrimaryKey: False; ForceUpdate: False),
-    // 当期信息价--时间
-    (FieldName: 'InfoDate'; FieldType: ftString; Size: 20; NotNull: False; PrimaryKey: False; ForceUpdate: False)
+    // 信息价时间
+    (FieldName: 'InfoDate'; FieldType: ftString; Size: 20; NotNull: False; PrimaryKey: False; ForceUpdate: False),
+    // 价差
+    (FieldName: 'DeltaPrice'; FieldType: ftDouble; Size: 0; NotNull: False; PrimaryKey: False; ForceUpdate: False),
+    // 有效价差
+    (FieldName: 'ValidDeltaPrice'; FieldType: ftDouble; Size: 0; NotNull: False; PrimaryKey: False; ForceUpdate: False),
+    // 截止上期 -- 调差数量
+    (FieldName: 'PM_PreQuantity'; FieldType: ftDouble; Size: 0; NotNull: False; PrimaryKey: False; ForceUpdate: False),
+    // 截止上期 -- 调差金额
+    (FieldName: 'PM_PreTotalPrice'; FieldType: ftDouble; Size: 0; NotNull: False; PrimaryKey: False; ForceUpdate: False),
+    // 当前阶段 -- 调差数量
+    (FieldName: 'PM_Quantity'; FieldType: ftDouble; Size: 0; NotNull: False; PrimaryKey: False; ForceUpdate: False),
+    // 当期阶段 -- 调差金额
+    (FieldName: 'PM_TotalPrice'; FieldType: ftDouble; Size: 0; NotNull: False; PrimaryKey: False; ForceUpdate: False)
+    {--------------------End 当期缓存数据----------------------}
   );
 
-  {调差工料--信息价}
+  {调差工料--价格信息及计算}
   SGLPrice = 'GLPrice';
-  tdGLPrice: array [0..3] of TScFieldDef =(
+  tdGLPrice: array [0..37] of TScFieldDef =(
     // 工料ID
     (FieldName: 'GLID'; FieldType: ftInteger; Size: 0; NotNull: True; PrimaryKey: True; ForceUpdate: False),
     // 期号
@@ -438,12 +452,51 @@ const
     // 信息价
     (FieldName: 'InfoPrice'; FieldType: ftDouble; Size: 0; NotNull: False; PrimaryKey: False; ForceUpdate: False),
     // 信息价--时间
-    (FieldName: 'InfoDate'; FieldType: ftString; Size: 20; NotNull: False; PrimaryKey: False; ForceUpdate: False)
+    (FieldName: 'InfoDate'; FieldType: ftString; Size: 20; NotNull: False; PrimaryKey: False; ForceUpdate: False),
+    // 价差
+    (FieldName: 'DeltaPrice'; FieldType: ftDouble; Size: 0; NotNull: False; PrimaryKey: False; ForceUpdate: False),
+    // 有效价差
+    (FieldName: 'ValidDeltaPrice'; FieldType: ftDouble; Size: 0; NotNull: False; PrimaryKey: False; ForceUpdate: False),
+    // 截止上期
+    (FieldName: 'PM_PreQuantity'; FieldType: ftDouble; Size: 0; NotNull: False; PrimaryKey: False; ForceUpdate: False),
+    (FieldName: 'PM_PreTotalPrice'; FieldType: ftDouble; Size: 0; NotNull: False; PrimaryKey: False; ForceUpdate: False),
+    // 本期 -- 原报
+    (FieldName: 'PM_Quantity0'; FieldType: ftDouble; Size: 0; NotNull: False; PrimaryKey: False; ForceUpdate: False),
+    (FieldName: 'PM_TotalPrice0'; FieldType: ftDouble; Size: 0; NotNull: False; PrimaryKey: False; ForceUpdate: False),
+    // 本期 -- 1审~14审
+    (FieldName: 'PM_Quantity1'; FieldType: ftDouble; Size: 0; NotNull: False; PrimaryKey: False; ForceUpdate: False),
+    (FieldName: 'PM_TotalPrice1'; FieldType: ftDouble; Size: 0; NotNull: False; PrimaryKey: False; ForceUpdate: False),
+    (FieldName: 'PM_Quantity2'; FieldType: ftDouble; Size: 0; NotNull: False; PrimaryKey: False; ForceUpdate: False),
+    (FieldName: 'PM_TotalPrice2'; FieldType: ftDouble; Size: 0; NotNull: False; PrimaryKey: False; ForceUpdate: False),
+    (FieldName: 'PM_Quantity3'; FieldType: ftDouble; Size: 0; NotNull: False; PrimaryKey: False; ForceUpdate: False),
+    (FieldName: 'PM_TotalPrice3'; FieldType: ftDouble; Size: 0; NotNull: False; PrimaryKey: False; ForceUpdate: False),
+    (FieldName: 'PM_Quantity4'; FieldType: ftDouble; Size: 0; NotNull: False; PrimaryKey: False; ForceUpdate: False),
+    (FieldName: 'PM_TotalPrice4'; FieldType: ftDouble; Size: 0; NotNull: False; PrimaryKey: False; ForceUpdate: False),
+    (FieldName: 'PM_Quantity5'; FieldType: ftDouble; Size: 0; NotNull: False; PrimaryKey: False; ForceUpdate: False),
+    (FieldName: 'PM_TotalPrice5'; FieldType: ftDouble; Size: 0; NotNull: False; PrimaryKey: False; ForceUpdate: False),
+    (FieldName: 'PM_Quantity6'; FieldType: ftDouble; Size: 0; NotNull: False; PrimaryKey: False; ForceUpdate: False),
+    (FieldName: 'PM_TotalPrice6'; FieldType: ftDouble; Size: 0; NotNull: False; PrimaryKey: False; ForceUpdate: False),
+    (FieldName: 'PM_Quantity7'; FieldType: ftDouble; Size: 0; NotNull: False; PrimaryKey: False; ForceUpdate: False),
+    (FieldName: 'PM_TotalPrice7'; FieldType: ftDouble; Size: 0; NotNull: False; PrimaryKey: False; ForceUpdate: False),
+    (FieldName: 'PM_Quantity8'; FieldType: ftDouble; Size: 0; NotNull: False; PrimaryKey: False; ForceUpdate: False),
+    (FieldName: 'PM_TotalPrice8'; FieldType: ftDouble; Size: 0; NotNull: False; PrimaryKey: False; ForceUpdate: False),
+    (FieldName: 'PM_Quantity9'; FieldType: ftDouble; Size: 0; NotNull: False; PrimaryKey: False; ForceUpdate: False),
+    (FieldName: 'PM_TotalPrice9'; FieldType: ftDouble; Size: 0; NotNull: False; PrimaryKey: False; ForceUpdate: False),
+    (FieldName: 'PM_Quantity10'; FieldType: ftDouble; Size: 0; NotNull: False; PrimaryKey: False; ForceUpdate: False),
+    (FieldName: 'PM_TotalPrice10'; FieldType: ftDouble; Size: 0; NotNull: False; PrimaryKey: False; ForceUpdate: False),
+    (FieldName: 'PM_Quantity11'; FieldType: ftDouble; Size: 0; NotNull: False; PrimaryKey: False; ForceUpdate: False),
+    (FieldName: 'PM_TotalPrice11'; FieldType: ftDouble; Size: 0; NotNull: False; PrimaryKey: False; ForceUpdate: False),
+    (FieldName: 'PM_Quantity12'; FieldType: ftDouble; Size: 0; NotNull: False; PrimaryKey: False; ForceUpdate: False),
+    (FieldName: 'PM_TotalPrice12'; FieldType: ftDouble; Size: 0; NotNull: False; PrimaryKey: False; ForceUpdate: False),
+    (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)
   );
 
   {清单使用的工料}
   SDetailGL = 'DetailGL';
-  tdDetailGL: array [0..9] of TScFieldDef =(
+  tdDetailGL: array [0..6] 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),
@@ -456,11 +509,7 @@ const
     // 创建期号
     (FieldName: 'CreatePhaseID'; FieldType: ftInteger; Size: 0; NotNull: False; PrimaryKey: False; ForceUpdate: False),
     // 创建阶段
-    (FieldName: 'CreateStageID'; FieldType: ftInteger; Size: 0; NotNull: False; PrimaryKey: False; ForceUpdate: False),
-    // ------ Cache Data
-    (FieldName: 'PM_PreTotalPrice'; FieldType: ftDouble; Size: 0; NotNull: False; PrimaryKey: False; ForceUpdate: False),
-    (FieldName: 'PM_CurTotalPrice'; FieldType: ftDouble; Size: 0; NotNull: False; PrimaryKey: False; ForceUpdate: False),
-    (FieldName: 'PM_EndTotalPrice'; FieldType: ftDouble; Size: 0; NotNull: False; PrimaryKey: False; ForceUpdate: False)
+    (FieldName: 'CreateStageID'; FieldType: ftInteger; Size: 0; NotNull: False; PrimaryKey: False; ForceUpdate: False)
   );
 
   {各期总数据 -- 为更新项目管理而储存的缓存数据}
@@ -509,7 +558,7 @@ const
   // ......
   SRefer = 'Refer';
   SAudit = 'Audit';
-  tdRefer_Audit: array [0..45] of TScFieldDef = (
+  tdRefer_Audit: array [0..46] of TScFieldDef = (
     (FieldName: 'BillsID'; FieldType: ftInteger; Size: 0; NotNull: True; PrimaryKey: True; ForceUpdate: False),
     //------------------   本期合同计量  ----------------
     // 数量
@@ -614,8 +663,10 @@ const
 //    (FieldName: 'HasAttachment'; FieldType: ftBoolean; Size: 0; NotNull: False; PrimaryKey: False; ForceUpdate: False),
     // 书签批注
     (FieldName: 'MarkMemo'; FieldType: ftString; Size: 255; NotNull: False; PrimaryKey: False; ForceUpdate: False),
+    // 截止上期材料调差
+    (FieldName: 'PM_PreTotalPrice'; FieldType: ftDouble; Size: 0; NotNull: False; PrimaryKey: False; ForceUpdate: False),
     // 本期材料调差
-    (FieldName: 'PriceMarginTotalPrice'; FieldType: ftDouble; Size: 0; NotNull: False; PrimaryKey: False; ForceUpdate: False)
+    (FieldName: 'PM_TotalPrice'; FieldType: ftDouble; Size: 0; NotNull: False; PrimaryKey: False; ForceUpdate: False)
   );
 
   // 计量期合同支付

+ 9 - 0
Units/GclBillsGatherModel.pas

@@ -43,6 +43,9 @@ type
     FPreQcTotalPrice: Double;
     FPreGatherQuantity: Double;
     FPreGatherTotalPrice: Double;
+
+    FPM_PreTotalPrice: Double;
+    FPM_TotalPrice: Double;
   public
     constructor Create(AID: Integer);
 
@@ -80,6 +83,9 @@ type
     property PreQcTotalPrice: Double read FPreQcTotalPrice write FPreQcTotalPrice;
     property PreGatherQuantity: Double read FPreGatherQuantity write FPreGatherQuantity;
     property PreGatherTotalPrice: Double read FPreGatherTotalPrice write FPreGatherTotalPrice;
+
+    property PM_PreTotalPrice: Double read FPM_PreTotalPrice write FPM_PreTotalPrice;
+    property PM_TotalPrice: Double read FPM_TotalPrice write FPM_TotalPrice;
   end;
 
   TDetailDealNode = class
@@ -320,6 +326,9 @@ begin
     vDetailGclNode.PreQcTotalPrice := ANode.StageRec.PreQcTotalPrice.AsFloat;
     vDetailGclNode.PreGatherQuantity := ANode.StageRec.PreGatherQuantity.AsFloat;
     vDetailGclNode.PreGatherTotalPrice := ANode.StageRec.PreGatherTotalPrice.AsFloat;
+
+    vDetailGclNode.PM_PreTotalPrice := ANode.StageRec.PM_PreTotalPrice.AsFloat;
+    vDetailGclNode.PM_TotalPrice := ANode.StageRec.PM_TotalPrice.AsFloat;
   end;
 
   vLeafXmj := GetFirstXmjParent;

+ 30 - 0
Units/ProjectData.pas

@@ -90,6 +90,7 @@ type
     function GetADOConnection: TADOConnection;
     procedure SetCheckers(const Value: TCheckers);
     function GetStageDataReadOnly: Boolean;
+    function GetPriceMarginReadOnly: Boolean;
   public
     constructor Create;
     destructor Destroy; override;
@@ -156,6 +157,7 @@ type
     procedure CopyPhaseData;
 
     procedure CalculateAll;
+    procedure CalculatePriceMargin;
 
     procedure ImportCloudTenderFile(const AFileName: string);
 
@@ -190,6 +192,7 @@ type
     property AllowInsert: Boolean read GetAllowInsert;
     property BaseDataReadOnly: Boolean read GetBaseDataReadOnly;
     property StageDataReadOnly: Boolean read GetStageDataReadOnly;
+    property PriceMarginReadOnly: Boolean read GetPriceMarginReadOnly;
 
     property CanUnlockInfo: Boolean read FCanUnlockInfo write FCanUnlockInfo;
 
@@ -270,6 +273,7 @@ procedure TProjectData.CreateNewPhase;
 var
   sPhaseFileName: string;
 begin
+  FProjectGLData.Save;
   FBillsData.LockedBaseData;
   FProjProperties.PhaseCount := FProjProperties.PhaseCount + 1;
   FProjProperties.AuditStatus := 0;
@@ -426,6 +430,7 @@ begin
   FProjProperties.PhaseIndex := FPhaseIndex;
   FPhaseData.Open(Format('%sPhase%d.dat', [TempPath, FPhaseIndex]));
   ResetPhaseDataLink;
+  FProjectGLData.LoadCurPhaseInfoPrice;
 end;
 
 procedure TProjectData.Save;
@@ -509,6 +514,8 @@ begin
   ReCreatePhaseData;
   FPhaseData.Open(GetPhaseFileName);
   ResetPhaseDataLink;
+  // 须保存项目工料数据,重新加载当期的项目工料数据
+  FProjectGLData.LoadCurPhaseInfoPrice;
   //BillsGatherData.RefreshBills;
 end;
 
@@ -1093,9 +1100,11 @@ end;
 procedure TProjectData.CalculateAll;
 begin
   FBillsCompileData.CalculateAll;
+  FProjectGLData.CalculateAll;
   if not FPhaseData.StageDataReadOnly then
     FPhaseData.StageData.CalculateAll;
   FBillsMeasureData.CalculateAll;
+  // To Do
 end;
 
 procedure TProjectData.ImportCloudTenderFile(const AFileName: string);
@@ -1575,4 +1584,25 @@ begin
   FBillsMeasureData.ResetTreeNodeStageRec;
 end;
 
+function TProjectData.GetPriceMarginReadOnly: Boolean;
+begin
+  if FPhaseData.Active then
+    Result := not((FPhaseIndex = FProjProperties.PhaseCount) and (FPhaseData.StageCount = 1))
+  else
+    Result := True;
+end;
+
+procedure TProjectData.CalculatePriceMargin;
+begin
+  // 计算工料价差数据
+  FProjectGLData.CalculateAll;
+  if not FPhaseData.StageDataReadOnly then
+  begin
+    // 计算清单价差节点
+    PhaseData.StageData.CalculatePriceMarginNode;
+    // 计算合同支付
+    PhaseData.PhasePayData.CalculateAll;
+  end;
+end;
+
 end.

+ 131 - 0
Units/mDataRecord.pas

@@ -86,6 +86,8 @@ type
     FAddPayTotalPrice: TsdValue;
 
     FAddCompleteRate: TsdValue;
+
+    FPM_AddTotalPrice: TsdValue;
   protected
     procedure DoAfterAddFields; override;
   public
@@ -166,6 +168,8 @@ type
     property AddPayTotalPrice: TsdValue read FAddPayTotalPrice;
 
     property AddCompleteRate: TsdValue read FAddCompleteRate;
+
+    property PM_AddTotalPrice: TsdValue read FPM_AddTotalPrice;
   end;
 
   TStageRecord = class(TsdDataRecord)
@@ -222,6 +226,9 @@ type
 
     FHasBookMark: TsdValue;
     FMarkMemo: TsdValue;
+
+    FPM_PreTotalPrice: TsdValue;
+    FPM_TotalPrice: TsdValue;
   protected
     procedure DoAfterAddFields; override;
   public
@@ -277,6 +284,83 @@ type
 
     property HasBookMark: TsdValue read FHasBookMark;
     property MarkMemo: TsdValue read FMarkMemo;
+
+    property PM_PreTotalPrice: TsdValue read FPM_PreTotalPrice;
+    property PM_TotalPrice: TsdValue read FPM_TotalPrice;
+  end;
+
+  TProjectGLRecord = class(TsdDataRecord)
+  private
+    FID: TsdValue;
+    FCode: TsdValue;
+    FName: TsdValue;
+    FUnits: TsdValue;
+    FSpecs: TsdValue;
+    FBasePrice: TsdValue;
+    FRiskRange: TsdValue;
+    FLockedPhaseID: TsdValue;
+    FLockedStageID: TsdValue;
+    FCreatePhaseID: TsdValue;
+
+    FInfoPrice: TsdValue;
+    FInfoDate: TsdValue;
+    FDeltaPrice: TsdValue;
+    FValidDeltaPrice: TsdValue;
+
+    FPM_PreQuantity: TsdValue;
+    FPM_PreTotalPrice: TsdValue;
+    FPM_Quantity: TsdValue;
+    FPM_TotalPrice: TsdValue;
+  protected
+    procedure DoAfterAddFields; override;
+  public
+    property ID: TsdValue read FID;
+    property Code: TsdValue read FCode;
+    property Name: TsdValue read FName;
+    property Units: TsdValue read FUnits;
+    property Specs: TsdValue read FSpecs;
+    property BasePrice: TsdValue read FBasePrice;
+    property RiskRange: TsdValue read FRiskRange;
+    property LockedPhaseID: TsdValue read FLockedPhaseID;
+    property LockedStageID: TsdValue read FLockedStageID;
+    property CreatePhaseID: TsdValue read FCreatePhaseID;
+
+    property InfoPrice: TsdValue read FInfoPrice;
+    property InfoDate: TsdValue read FInfoDate;
+    property DeltaPrice: TsdValue read FDeltaPrice;
+    property ValidDeltaPrice: TsdValue read FValidDeltaPrice;
+
+    property PM_PreQuantity: TsdValue read FPM_PreQuantity;
+    property PM_PreTotalPrice: TsdValue read FPM_PreTotalPrice;
+    property PM_Quantity: TsdValue read FPM_Quantity;
+    property PM_TotalPrice: TsdValue read FPM_TotalPrice;
+  end;
+
+  TDetailGLRecord = class(TsdDataRecord)
+  private
+    FID: TsdValue;
+    FBillsID: TsdValue;
+    FGLID: TsdValue;
+
+    FCode: TsdValue;
+    FQuantity: TsdValue;
+
+    FCreatePhaseID: TsdValue;
+
+    FRelaProjectGL: TProjectGLRecord;
+  protected
+    procedure DoAfterAddFields; override;
+  public
+    property ID: TsdValue read FID;
+    property BillsID: TsdValue read FBillsID;
+    property GLID: TsdValue read FGLID;
+
+    property Code: TsdValue read FCode;
+    property Quantity: TsdValue read FQuantity;
+
+    property CreatePhaseID: TsdValue read FCreatePhaseID;
+
+    property RelaProjectGL: TProjectGLRecord read FRelaProjectGL write FRelaProjectGL;
   end;
 
 implementation
@@ -363,6 +447,8 @@ begin
   FAddPayTotalPrice := ValueByName('AddPayTotalPrice');
 
   FAddCompleteRate := ValueByName('AddCompleteRate');
+  
+  FPM_AddTotalPrice := ValueByName('PM_AddTotalPrice');
 end;
 
 { TStageRecord }
@@ -422,6 +508,51 @@ begin
 
   FHasBookMark := ValueByName('HasBookMark');
   FMarkMemo := ValueByName('MarkMemo');
+
+  FPM_PreTotalPrice := ValueByName('PM_PreTotalPrice');
+  FPM_TotalPrice := ValueByName('PM_TotalPrice');
+end;
+
+{ TProjectGLRecord }
+
+procedure TProjectGLRecord.DoAfterAddFields;
+begin
+  inherited;
+  FID := ValueByName('ID');
+  FCode := ValueByName('Code');
+  FName := ValueByName('Name');
+  FUnits := ValueByName('Units');
+  FSpecs := ValueByName('Specs');
+  FBasePrice := ValueByName('BasePrice');
+  FRiskRange := ValueByName('RiskRange');
+  FLockedPhaseID := ValueByName('LockedPhaseID');
+  FLockedStageID := ValueByName('LockedStageID');
+  FCreatePhaseID := ValueByName('CreatePhaseID');
+
+  FInfoPrice := ValueByName('InfoPrice');
+  FInfoDate := ValueByName('InfoDate');
+  FDeltaPrice := ValueByName('DeltaPrice');
+  FValidDeltaPrice := ValueByName('ValidDeltaPrice');
+
+  FPM_PreQuantity := ValueByName('PM_PreQuantity');
+  FPM_PreTotalPrice := ValueByName('PM_PreTotalPrice');
+  FPM_Quantity := ValueByName('PM_Quantity');
+  FPM_TotalPrice := ValueByName('PM_TotalPrice');
+end;
+
+{ TDetailGLRecord }
+
+procedure TDetailGLRecord.DoAfterAddFields;
+begin
+  inherited;
+  FID := ValueByName('ID');
+  FBillsID := ValueByName('BillsID');
+  FGLID := ValueByName('GLID');
+
+  FCode := ValueByName('Code');
+  FQuantity := ValueByName('Quantity');
+
+  FCreatePhaseID := ValueByName('CreatePhaseID');
 end;
 
 end.