Using Delphi 2005, I have a TwwDBGrid (InfoPower) that allows the user to select part(s) & quantities to generate a quote. Part of the selection process is to allow the user to add a discount for each part consisting of DiscountAmount and DiscountType. DiscountAmount is the amount of the discount and DiscountType is the type of discount amount (% off, $ off or flat price). This data is held in a ClientDataSet called ClientDataSetParts.
Within the OnCalc method (ClientDataSetPartsCalcFields) I have the following code which will recalculate the TotalPrice based on the parts cost and any discounts. RangePricing is used in the case where a price is calculated based on a quantity within a range (i.e., 1-100 = $100, 101-200 = $150, etc.):
procedure TfrmCustom_Services.ClientDataSetPartsCalcFields(
DataSet: TDataSet);
begin
inherited;
// if part is selected then calculate Total
if (ClientDataSetPartsSelected.Value) then begin
// if range pricing is defined
if (ClientDataSetParts.FieldByName('RangePricing').AsBoolean) then begin
ClientDataSetParts.FieldByName('TotalPrice').Value :=
ClientDataSetParts.FieldbyName('UnitPrice').Value;
// otherwise use regular pricing
end else begin
ClientDataSetParts.FieldByName('TotalPrice').Value :=
ClientDataSetParts.FieldbyName('UnitPrice').Value *
ClientDataSetParts.FieldByName('Quantity').Value;
end;
// otherwise clear the Total
end else begin
ClientDataSetParts.FieldByName('TotalPrice').Clear;
if (ClientDataSetParts.FieldByName('Quantity').Value <> null) then
ClientDataSetParts.FieldByName('Quantity').Clear;
if (ClientDataSetParts.FieldByName('DiscountAmount').Value <> null) then
ClientDataSetParts.FieldByName('DiscountAmount').Clear;
if (ClientDataSetParts.FieldByName('DiscountType').Value <> null) then
ClientDataSetParts.FieldByName('DiscountType').Clear;
end;
// Update totals if Discount is applied
// Only recalculate if both discount value and type are applied
// otherwise will constantly get errors when switching fields
if ((ClientDataSetPartsDiscountAmount.Value > 0) and (ClientDataSetPartsDiscountType.Value <> '')) then begin
case StringToCaseSelect((ClientDataSetPartsDiscountType.Value), ['% Disc','$ Disc','Price']) of
0 :
begin
ClientDataSetParts.FieldByName('DiscountDollarAmount').Value :=
ClientDataSetParts.FieldByName('TotalPrice').Value * (ClientDataSetParts.FieldByName('DiscountAmount').Value/100);
ClientDataSetPartsTotalPrice.Value := ClientDataSetPartsTotalPrice.Value - (ClientDataSetPartsTotalPrice.Value * (ClientDataSetPartsDiscountAmount.Value/100));
end;
1 :
begin
ClientDataSetParts.FieldByName('DiscountDollarAmount').Value := ClientDataSetPartsDiscountAmount.Value;
ClientDataSetPartsTotalPrice.Value := ClientDataSetPartsTotalPrice.Value - ClientDataSetPartsDiscountAmount.Value;
end;
2 :
begin
ClientDataSetParts.FieldByName('DiscountDollarAmount').Value :=
ClientDataSetPartsTotalPrice.Value - ClientDataSetPartsDiscountAmount.Value;
ClientDataSetPartsTotalPrice.Value := ClientDataSetPartsDiscountAmount.Value;
end;
end;
end;
end;
The problem comes when I try to calculate DiscountDollarAmount (the actual dollar figure of the discount that I have to return to an outside source via API). Each time I set the ClientDataSetParts.FieldByName('DiscountDollarAmount').Value, ClientDataSetPartsCalcFields is called again causing endless calls and eventually a stack overflow.
How can I update this value without calling ClientDataSetPartsCalcFields recursively?
AutoCalcFieldsto false?TotalPriceand any other calculated field used inDiscountDollarAmountto local variables when they're calculated, and use those variables in calculatingDiscountDollarAmountinstead of using the other field'sField.Value.