| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435 | unit PhasePayDm;interfaceuses  SysUtils, Classes, sdDB, sdProvider, ADODB, FormulaCalc, CalcDecimal;type  TPhasePayData = class(TDataModule)    sdpPhasePay: TsdADOProvider;    sddPhasePay: TsdDataSet;    procedure sddPhasePayBeforeValueChange(AValue: TsdValue;      const NewValue: Variant; var Allow: Boolean);    procedure sddPhasePayAfterValueChanged(AValue: TsdValue);  private    FPhaseData: TObject;    FPayFormula: TPayFormula;    FBeforeChangeTotalPrice: Double;    FDecimal: TCalcDecimal;    function CheckMinus(AID: Integer): Boolean;    function GetFormula(AID: Integer): string;    function GetCalcType(AID: Integer): Integer;    function GetPayablePrice(AIndex: Integer): Double;    procedure RepairPhaseRecord;    procedure BeforeBatchOperation;    procedure AfterBatchOperation;    function GetCurPayable: Double;    function GetLastestPhasePay(AType: Integer): Double;    procedure SetFieldValidChar;  public    constructor Create(APhaseData: TObject);    destructor Destroy; override;    procedure Open(AConnection: TADOConnection);    procedure Save;    function AddPayRecord(AID: Integer): TsdDataRecord;    function PayRecord(AID: Integer): TsdDataRecord;    procedure Delete(AID: Integer);    procedure CalculateAll;    procedure Calculate(AID: Integer);    procedure CalculateCurPay;    procedure UpdateDataForNewAudit;    procedure CopyPrePhasePayData;    property PayablePrice[AIndex: Integer]: Double read GetPayablePrice;    // 本期应付    property CurPayable: Double read GetCurPayable;    // AType表示不同类型,取值如下:    // 1: 本期数据  2: 截止本期数据  3: 截止上期数据    property LastestPhasePay[AType: Integer]: Double read GetLastestPhasePay;    property Decimal: TCalcDecimal read FDecimal;  end;implementationuses  PhaseData, ProjectData, DealPaymentDm, BillsDm, ConstUnit;{$R *.dfm}{ TPhasePayData }constructor TPhasePayData.Create(APhaseData: TObject);begin  inherited Create(nil);  FPhaseData := APhaseData;  FPayFormula := TPayFormula.Create(TPhaseData(FPhaseData).ProjectData);  with TProjectData(TPhaseData(FPhaseData).ProjectData) do  begin    FPayFormula.Decimal := ProjProperties.DecimalManager.DealPay;    FDecimal := ProjProperties.DecimalManager.DealPay;  end;end;procedure TPhasePayData.Delete(AID: Integer);begin  sddPhasePay.Remove(sddPhasePay.FindKey('idxID', AID));end;destructor TPhasePayData.Destroy;begin  FPayFormula.Free;  inherited;end;procedure TPhasePayData.UpdateDataForNewAudit;var  iNewAudit, iIndex: Integer;  Rec: TsdDataRecord;begin  BeforeBatchOperation;  try    iNewAudit := TPhaseData(FPhaseData).PhaseProperty.AuditCount;    for iIndex := 0 to sddPhasePay.RecordCount - 1 do    begin      Rec := sddPhasePay.Records[iIndex];      Rec.ValueByName('TotalPrice' + IntToStr(iNewAudit)).AsString :=        Rec.ValueByName('TotalPrice' + IntToStr(iNewAudit - 1)).AsString;      Rec.ValueByName('Formula' + IntToStr(iNewAudit)).AsString :=        Rec.ValueByName('Formula' + IntToStr(iNewAudit - 1)).AsString;      Rec.ValueByName('EndTotalPrice' + IntToStr(iNewAudit)).AsString :=        Rec.ValueByName('EndTotalPrice' + IntToStr(iNewAudit - 1)).AsString;      Rec.ValueByName('PreTotalPrice' + IntToStr(iNewAudit)).AsString :=        Rec.ValueByName('PreTotalPrice' + IntToStr(iNewAudit - 1)).AsString;    end;  finally    AfterBatchOperation;  end;end;procedure TPhasePayData.Open(AConnection: TADOConnection);begin  sdpPhasePay.Connection := AConnection;  sddPhasePay.Open;  if not Assigned(sddPhasePay.IndexList.FindByName('idxID')) then    sddPhasePay.AddIndex('idxID', 'ID');  SetFieldValidChar;  // 为适应旧项目处不计算合同支付值所做修改。  if sddPhasePay.RecordCount = 0 then  begin    CopyPrePhasePayData;    CalculateAll;  end;end;procedure TPhasePayData.Save;begin  sddPhasePay.Save;end;function TPhasePayData.AddPayRecord(AID: Integer): TsdDataRecord;begin  Result := sddPhasePay.Add;  Result.ValueByName('ID').AsInteger := AID;end;procedure TPhasePayData.sddPhasePayBeforeValueChange(AValue: TsdValue;  const NewValue: Variant; var Allow: Boolean);begin  if not Assigned(AValue) then Exit;  if Pos('TotalPrice', AValue.FieldName) = 1 then    FBeforeChangeTotalPrice := AValue.AsFloat; end;procedure TPhasePayData.sddPhasePayAfterValueChanged(AValue: TsdValue);begin  if Pos('TotalPrice', AValue.FieldName) = 1 then  begin    AValue.Owner.ValueByName('End' + AValue.FieldName).AsFloat := AValue.AsFloat        + AValue.Owner.ValueByName('Pre' + AValue.FieldName).AsFloat;    with TProjectData(TPhaseData(FPhaseData).ProjectData).DealPaymentData do      UpdateTotalPrice(AValue.Owner.ValueByName('ID').AsInteger, AValue.AsFloat - FBeforeChangeTotalPrice);  end;  CalculateCurPay;      end;procedure TPhasePayData.CalculateAll;var  iIndex: Integer;  Rec: TsdDataRecord;begin  if TPhaseData(FPhaseData).StageDataReadOnly then Exit;  RepairPhaseRecord;  for iIndex := 0 to sddPhasePay.RecordCount - 1 do  begin    Rec := sddPhasePay.Records[iIndex];    if GetCalcType(Rec.ValueByName('ID').AsInteger) in [0, 3] then      Calculate(Rec.ValueByName('ID').AsInteger);  end;  CalculateCurPay;end;procedure TPhasePayData.Calculate(AID: Integer);var  Rec: TsdDataRecord;  // 金额列名, 公式列名  sTPField, sFField, sPreField: string;  iID: Integer;  fTotalPrice, fStartedPrice: Double;begin  Rec := sddPhasePay.FindKey('idxID', AID);  sTPField := 'TotalPrice' + IntToStr(TPhaseData(FPhaseData).StageIndex);  sFField := 'Formula' + IntToStr(TPhaseData(FPhaseData).StageIndex);  sPreField := 'PreTotalPrice' + IntToStr(TPhaseData(FPhaseData).StageIndex);  if not Rec.ValueByName('StopCalc').AsBoolean then  begin    iID := Rec.ValueByName('ID').AsInteger;    with TProjectData(TPhaseData(FPhaseData).ProjectData).DealPaymentData do    begin      // 获取起扣金额      fStartedPrice :=  GetStartedPrice(iID);      if Rec.ValueByName(sFField).AsString <> '' then      begin        // 初次达到起扣金额时,bqwc基数值取值为累计完成计量-起扣金额        if FDecimal.TotalPrice.RoundTo(Rec.ValueByName('Pre'+sTPField).AsFloat) = 0 then          fTotalPrice := FPayFormula.Calculate(Rec.ValueByName(sFField).AsString, fStartedPrice)        else          fTotalPrice := FPayFormula.Calculate(Rec.ValueByName(sFField).AsString);      end      else        fTotalPrice := 0;      if CheckStartedPrice(iID) then        Rec.ValueByName(sTPField).AsFloat := GetAllowTotalPrice(iID, fTotalPrice, Rec.ValueByName(sPreField).AsFloat)      else        Rec.ValueByName(sTPField).AsFloat := 0;    end;  end  else    Rec.ValueByName(sTPField).AsFloat := 0;  {if Rec.ValueByName(sFField).AsString <> '' then  begin    with TProjectData(TPhaseData(FPhaseData).ProjectData).DealPaymentData do    begin      iID := Rec.ValueByName('ID').AsInteger;      // 获取起扣金额      fStartedPrice :=  GetStartedPrice(iID);      // 初次达到起扣金额时,bqwc基数值取值为累计完成计量-起扣金额      if Rec.ValueByName('Pre'+sTPField).AsFloat = 0 then        fTotalPrice := FPayFormula.Calculate(Rec.ValueByName(sFField).AsString, fStartedPrice)      else        fTotalPrice := FPayFormula.Calculate(Rec.ValueByName(sFField).AsString);      if CheckStartedPrice(iID) then        Rec.ValueByName(sTPField).AsFloat := GetAllowTotalPrice(iID, fTotalPrice, Rec.ValueByName(sPreField).AsFloat)      else        Rec.ValueByName(sTPField).AsFloat := 0;    end;  end;}  // 计算截止数据  Rec.ValueByName('End' + sTPField).AsFloat := FDecimal.TotalPrice.RoundTo(Rec.ValueByName(sTPField).AsFloat      + Rec.ValueByName('Pre' + sTPField).AsFloat);end;function TPhasePayData.GetPayablePrice(AIndex: Integer): Double;var  iIndex: Integer;  sTotalPriceField: string;  Rec: TsdDataRecord;begin  Result := 0;  // 阶段在0--14之间  if (AIndex < 0) or (AIndex > iMaxStageCount-1) then Exit;  sTotalPriceField := 'TotalPrice' + IntToStr(AIndex);  for iIndex := 0 to sddPhasePay.RecordCount - 1 do  begin    Rec := sddPhasePay.Records[iIndex];    if CheckMinus(Rec.ValueByName('ID').AsInteger) then      Result := Result - Rec.ValueByName(sTotalPriceField).AsFloat    else      Result := Result + Rec.ValueByName(sTotalPriceField).AsFloat;  end;end;function TPhasePayData.CheckMinus(AID: Integer): Boolean;begin  with TProjectData(TPhaseData(FPhaseData).ProjectData).DealPaymentData do    Result := sddDealPayment.FindKey('idxID', AID).ValueByName('IsMinus').AsBoolean;end;function TPhasePayData.GetFormula(AID: Integer): string;begin  with TProjectData(TPhaseData(FPhaseData).ProjectData).DealPaymentData do    Result := sddDealPayment.FindKey('idxID', AID).ValueByName('Formula').AsString;end;procedure TPhasePayData.AfterBatchOperation;begin  sddPhasePay.BeforeValueChange := sddPhasePayBeforeValueChange;  sddPhasePay.AfterValueChanged := sddPhasePayAfterValueChanged;  sddPhasePay.EndUpdate;end;procedure TPhasePayData.BeforeBatchOperation;begin  sddPhasePay.BeginUpdate;  sddPhasePay.BeforeValueChange := nil;  sddPhasePay.AfterValueChanged := nil;end;procedure TPhasePayData.CalculateCurPay;var  Rec: TsdDataRecord;  sTPField: string;  I: Integer;begin  sTPField := 'TotalPrice' + IntToStr(TPhaseData(FPhaseData).StageIndex);  for I := 0 to sddPhasePay.RecordCount - 1 do  begin    Rec := sddPhasePay.Records[I];    if GetCalcType(Rec.ValueByName('ID').AsInteger) = 1 then    begin      Rec.ValueByName(sTPField).AsFloat := CurPayable;      Rec.ValueByName('End' + sTPField).AsFloat := Rec.ValueByName(sTPField).AsFloat          + Rec.ValueByName('Pre' + sTPField).AsFloat;      Break;    end;  end;end;function TPhasePayData.GetCurPayable: Double;var  Rec: TsdDataRecord;  sTPField: string;  i: Integer;begin  sTPField := 'TotalPrice' + IntToStr(TPhaseData(FPhaseData).StageIndex);  Result := 0;  for I := 0 to sddPhasePay.RecordCount - 1 do  begin    Rec := sddPhasePay.Records[I];    // 检查是否为一般项    if GetCalcType(Rec.ValueByName('ID').AsInteger) = 0 then      if CheckMinus(Rec.ValueByName('ID').AsInteger) then        Result := Result - Rec.ValueByName(sTPField).AsFloat      else        Result := Result + Rec.ValueByName(sTPField).AsFloat;  end;end;function TPhasePayData.GetCalcType(AID: Integer): Integer;var  Rec: TsdDataRecord;begin  Result := 0;  with TProjectData(TPhaseData(FPhaseData).ProjectData).DealPaymentData do    Rec := sddDealPayment.FindKey('idxID', AID);  if Assigned(Rec) then    Result := Rec.ValueByName('CalcType').AsInteger;end;function TPhasePayData.GetLastestPhasePay(AType: Integer): Double;var  Rec: TsdDataRecord;  sTPField: string;  i: Integer;begin  case AType of    1: sTPField := 'TotalPrice' + IntToStr(TPhaseData(FPhaseData).PhaseProperty.AuditCount);    2: sTPField := 'EndTotalPrice' + IntToStr(TPhaseData(FPhaseData).PhaseProperty.AuditCount);    3: sTPField := 'PreTotalPrice' + IntToStr(TPhaseData(FPhaseData).PhaseProperty.AuditCount);  end;  Result := 0;  for i := 0 to sddPhasePay.RecordCount - 1 do  begin    Rec := sddPhasePay.Records[i];    // 检查是否为一般项    if GetCalcType(Rec.ValueByName('ID').AsInteger) = 0 then      if CheckMinus(Rec.ValueByName('ID').AsInteger) then        Result := Result - Rec.ValueByName(sTPField).AsFloat      else        Result := Result + Rec.ValueByName(sTPField).AsFloat;  end;end;procedure TPhasePayData.CopyPrePhasePayData;var  iRecord: Integer;  Rec, NewRec: TsdDataRecord;begin  BeforeBatchOperation;  try    if sddPhasePay.RecordCount > 0 then Exit;    with TProjectData(TPhaseData(FPhaseData).ProjectData).DealPaymentData do      for iRecord := 0 to sddDealPayment.RecordCount - 1 do      begin        Rec := sddDealPayment.Records[iRecord];        NewRec := sddPhasePay.Add;        NewRec.ValueByName('ID').AsInteger := Rec.ValueByName('ID').AsInteger;        NewRec.ValueByName('EndTotalPrice0').AsFloat := Rec.ValueByName('TotalPrice').AsFloat;        NewRec.ValueByName('PreTotalPrice0').AsFloat := Rec.ValueByName('TotalPrice').AsFloat;        NewRec.ValueByName('Formula0').AsString := Rec.ValueByName('Formula').AsString;        NewRec.ValueByName('StopCalc').AsBoolean := Rec.ValueByName('StopCalc').AsBoolean;      end;  finally    AfterBatchOperation;  end;end;procedure TPhasePayData.SetFieldValidChar;var  i: Integer;  sField: string;begin  for i := 0 to iMaxStageCount - 1 do  begin    sField := 'TotalPrice' + IntToStr(i);    sddPhasePay.FieldByName(sField).ValidChars := sddPhasePay.FieldByName(sField).ValidChars + ArithmeticCharSet + ExprsBaseCharSet;  end;end;function TPhasePayData.PayRecord(AID: Integer): TsdDataRecord;begin  Result := sddPhasePay.FindKey('idxID', AID);end;procedure TPhasePayData.RepairPhaseRecord;var  i: Integer;  vDealRec, vPhaseRec: TsdDataRecord;begin  // 旧设计中,DealPayment中数据多于PhasePay  // 在于用户新增了合同支付项,但未输入金额或公式,以减少数据  // 现,要求存在合同支付项,设置了计提期限,但未输入金额或公式时,达计提期限时,金额需计  // 故在每次计算前,检查一遍合同支付数据,以兼容旧项目,并保证DealPayment与PhasePay数据行相同  with TProjectData(TPhaseData(FPhaseData).ProjectData).DealPaymentData do  begin    if sddDealPayment.RecordCount > sddPhasePay.RecordCount then    begin      for i := 0 to sddDealPayment.RecordCount - 1 do      begin        vDealRec := sddDealPayment.Records[i];        vPhaseRec := PayRecord(vDealRec.ValueByName('ID').AsInteger);        if not Assigned(vPhaseRec) then          vPhaseRec := AddPayRecord(vDealRec.ValueByName('ID').AsInteger);      end;    end;  end;end;end.
 |