Developer forum

Forum » Integration » Liveintegration and manipulating salesline price via BC plugin custom unit

Liveintegration and manipulating salesline price via BC plugin custom unit

Jan Sangill
Reply

Hi, we are trying to extend the BC plugin unit on Cloud. We have looked a little at this thread: https://doc.dynamicweb.com/forum?PID=1605&ThreadID=87816

We are trying to manipulate it, and when we do, we sometimes get an error.

Look at my attachments. One in this thread and one in a comment below. 

Our question is - since we get an error - like this: 'The remote server returned an error: (500) Internal Server Error. Response: Document No. must have a value in Sales Line: Document Type=Order, Document No.=, Line No.=10000. It cannot be zero or empty'

Can we run a: Data.validate(field,newdata) on a price line - or do we have to set it manually? If we run validate, BC will take care of all logic for us. Instead of us having code two places.

If we cannot validate a priceline - like unitprice, are you guys validating after the custom code, to make sure all is correctly applied?

Let me know if this makes any sense.

Regards

Jan 

MicrosoftTeams-image_(3).png

Replies

 
Jan Sangill
Reply

One more attachment:

MicrosoftTeams-image_(4).png
 
Dmitriy Benyuk Dynamicweb Employee
Dmitriy Benyuk
Reply

Hi Jan,
yes, you can not call Validate() on the salesLine object in the CalculateOrder request as in this mode the sales header is virtual and only exists in BC memory so it is not saved to database and doesn't not have any salesHeaderNo generated. We don't save it because of performance problems. So instead of Validate we have our own logic which following the same way as BC does internally (for the old prices flow) and instead of calling Validate we use direct assignment operator :=. For the new prices logic (new feature in BC) we use BC api and set the salesHeaderNo to the temp string like that:
salesheader."No." := 'TempCalculateOrder';
salesline."Document No." := salesheader."No.";
So it helped to fix the problems with a new prices flow calculation (this feature is disabled in BC by default for now).

So you can try to:
way 1: avoid using Validate for CaclulateOrder request
(
then we have several public procedures we use for the sales line price calculation:
1.1) Codeunit "Sales Price Calc. Mgt." :: FindSalesLineDisc, FindSalesPrice
1.2) codeunit 6211198 DynamicwebHelper :: CalcBestLineDisc, CalcBestUnitPrice, CalcLineAmount
Also there are CalculateSalesLine methods in the codeunit 6211196 DynamicwebOrders that use the methods from codeunits 1.1 and 1.2 from above.
They do our default sales lines calculations for CalculateOrder request, so maybe you can call one of them and then just override properties that you need
Or assign the needed unit price directly or by calling our public method that takes into account the LineDiscount:
salesline."Unit Price" := Helper.CalcLineAmount(TempSalesPrice."Allow Line Disc.",
                TempSalesPrice."Unit Price", 0);
)
or
way 2:
try to set salesHeaderNo and salesLine.DocumentNo to some temp string value and see if it helps.

BR, Dmitrij

 
Jan Sangill
Reply

Ty, Dmitriy.

I will let them know this.

I might open up this thread again later on - if that is ok:) 

 
Jan Sangill
Reply

Hi Dmitriy,

We have still not been able to solve this. Is there a possibility we can disucss further via teams? Or any other way?

To lay out the issue in simple terms:

When people are logged in, live integration is used.

However, they need something custom regarding specific scenarios in which a price other than that of the debitor has . A check must be made to see if there is a "web price". If there is, and it is less than a debitors - then live integration must send "web price" back to DW instead. If not, it should just continue as normal.

"Web price" also exists in BC - but web price is assigned to a certain DW debitor - which is used for all web prices - which we import into DW more than once a day - for prices for people who are not logged in.


My intial thought was to handle this via DW and not via BC extension - but as you know from prevoius threads, this has not worked very well either. Therefore I thought it might be easier to extend BC and do it this way.
 

Our ERP people are the ones who need a little guidance here to achieve the correct solution. They have tried - but have not come up with the correct place yet to insert this logic to actually make it work as intended.

Let me know what you think. 
Regards jan

 
Dmitriy Benyuk Dynamicweb Employee
Dmitriy Benyuk
Reply

Hi Jan,
it looks like mine previous reply was too compex. I'll try to explain more simple.
The CalculateOrderOnBeforeAddSalesLine event is fine to use for that and it is called after the Dynamicweb codeunit has calculated the sales line prices using the logic that is almost the same as BC does. Also there is another event called:
OnBeforeCalculateSalesLine similar to the previous one.
It has this definition:
procedure OnBeforeCalculateSalesLine(var isHandled: Boolean; var salesline: Record "Sales Line"; var item: Record Item;
        var Currency: Record Currency; var CurrencyFactor: Decimal; var GLSetup: Record "General Ledger Setup"; var uom: Text;
        var QtyPerUOM: Decimal; var useDynamicwebDiscount: Boolean; var customer: Record Customer; var VATPostingSetupVATPercent: decimal; var VATCalcType: Enum "Tax Calculation Type")

This event is called right before any price calculations are made on the sales line for the Calculate Order request, so you can also consider using it and set isHandled := true for the case if you have found that there is a WebPrice that you need to use instead, then DW codeunit will skip overriding this sales line with price re-calculations.

As for the code that is failing in your custom subscriber that is connected to the Validate calls - you can simply look inside BC calls that are made in the OnValidate() methods (right click and choose Goto Definition).
I have checked for those lines:

you can simply use the direct assignment operator instead since you are disabling the Line discounts using this code, so it can look like this:
pSalesLine."Allow Line Disc." := false;
pSalesLine."Line Discount %" := 0;
pSalesLine."Line Discount Amount" := 0; // this what is called inside the OnValidate for LineDiscount% field and "Unit Price" field
pSalesLine."Unit Price" := DynSalesPrice."Unit Price";


Hope this helps
BR, Dmitrij

 
Jan Sangill
Reply

Hi Dmitrij, I will look into this and let you know.

 
Jan Sangill
Reply

Hi again, we have looked into it, and have two more questions:

1) When trying to manipulate the price for the products returned, not the order, via: "<GetEcomData ExternalUserId="" AccessUserCustomerNumber="" VatCountryCode="" VatPostingGroup="">
<tables> <Products type="filter" unitPrices="true">" - then what method would be ebst to sue if we do not wish to add any xml. Just the price. We have looked into OnBeforeFindItemPrice - but this simply does nothing for us, with what they tried. Can it not be done here, or should we use another method? Or should we return it different. Look below

[EventSubscriber(ObjectType::Codeunit, Codeunit::DynamicwebProductsPublisher, 'OnBeforeFindItemPrice', '', false, false)]
local procedure DynFindItemPrice(var item: Record Item; var priceToReturn: Decimal; requestXmlNode: XmlNode; var isHandled: Boolean; var qty:       Decimal; var customer: Record Customer; var Currency: Record Currency)

    var lSalesLine: Record "Sales Line";
    begin
       priceToReturn := 99.00;
    end

2) When a debitor have a discount applied to their order, this is still returned, even if we try to disable it. Any ideas what we are missing? I am still getting the orderline node with my altered price and I am receiving the discount that was applied before. However when altering the price, the discount should not be applied anymore. We are using this method: CalculateOrderOnBeforeAddSalesLine. The code that modifies is below:
 pSalesLine."Allow Line Disc." := false;
pSalesLine."Line Discount %" := 0;
pSalesLine.ValidateLineDiscountPercent(true);
pSalesLine."Line Discount Amount" := 0;
pSalesLine."Line Amount" := 0;
pSalesLine."Unit Price" := DynSalesPrice."Unit Price";

Hope you can help us with this. Almost there:)

 
Dmitriy Benyuk Dynamicweb Employee
Dmitriy Benyuk
Reply

Hi Jan,
1) you forgot to update the isHanled parameter, needs to be:
[EventSubscriber(ObjectType::Codeunit, Codeunit::DynamicwebProductsPublisher, 'OnBeforeFindItemPrice', '', false, false)]
local procedure DynFindItemPrice(var item: Record Item; var priceToReturn: Decimal; requestXmlNode: XmlNode; var isHandled: Boolean; var qty:       Decimal; var customer: Record Customer; var Currency: Record Currency)

    var lSalesLine: Record "Sales Line";
    begin
       priceToReturn := 99.00;
       isHandled := true;
    end

2) not clear: who is handling discounts Dynamciweb or ERP (there is a checbox for that in the Live integration)? Then what kind of discount is causing the problem: invoice/total order discount or a product discount? 
If it is a discount line that comes from Dynamicweb then you can subscribe to: OnBeforeAddSalesLineToResponse
and set parameter cancelAdd := true; for those kind of the lines 

BR, Dmitrij

 
Jan Sangill
Reply

Hi Dmitrij,

In regards to number 1: It does not seem to work. The price returned in XML below is not 99, and we have set in that method (OnBeforeFindItemPrice). The price returned is the "real" price still. It seems as if we dont even reach this method, eif we try to check if we enter it.

GetEcomData ExternalUserId="xx" AccessUserCustomerNumber="xx" VatCountryCode="xx" VatPostingGroup="">
  <tables>
    <Products type="filter" unitPrices="true">
      <Product>
        <ProductId>70000011</ProductId>
        <ProductVariantId></ProductVariantId>
        <ProductNumber>70000011</ProductNumber>
        <ProductUnitId></ProductUnitId>
        <ProductIdentifier>70000011..LANG1</ProductIdentifier>
        <CurrencyCode>DKK</CurrencyCode>
        <Quantity>10</Quantity>
      </Product>
    </Products>
  </tables>
</GetEcomData>

In regards to number 2: The discounts are handled via BC. The type of discount I am refering too is is a product discount from the product.

I hope this clarifies. Let me know what you think we might need further to do.

 
Dmitriy Benyuk Dynamicweb Employee
Dmitriy Benyuk
Reply

Hi Jan,
1) sorry, wrong method suggested. There are 2 methods matching the same functionality but having different names, so "OnBeforeFindItemPrice" is used when New prices feature is ON, and there is the same for current prices called "OnBeforeFindItemPriceOld", so try to use this one instead.

2) try to use OnBeforeAddSalesLineToResponse with cancelAdd := true; for those kind of the lines. Not sure why it is added, it can happen if the Dynamicweb keept this wrong discount order line in the existing order/cart so you can try to clear the cart and check again. Or somehow the salesline."Line Discount Amount" <> 0.
Maybe you can try to change the order of those lines:
pSalesLine."Unit Price" := DynSalesPrice."Unit Price";
 pSalesLine."Allow Line Disc." := false;
pSalesLine."Line Discount %" := 0;
pSalesLine."Line Discount Amount" := 0;
pSalesLine."Line Amount" := 0;
BR, Dmitrij

 
Jan Sangill
Reply

Hi again,

1) It seems like we got it to work this part.  I will let you know if not.

2) This did work . With the canceladd.  It seems so far atleast. A shame its needed to add here too.

Will let you know if any issues

dyn-issue.png

 

You must be logged in to post in the forum