Options

Running code in OnAfterValidate trigger

StephenGStephenG Member Posts: 99
edited 2003-07-18 in Navision Financials
Hi

On the Sales Quote form I have code on the "Sell-to Customer No." OnAfterValidate trigger. This runs a Confirmation form passing a parameter of SalesHeader, if You Select Yes then a second form is run displaying any Outstanding back order sales lines, and you select any lines you want and the rest the quantise are reset or lines deleted depending on what posted. If you say No on the confirm form then all the outstanding lines are reset or deleted.

This is OK when the form is called from the S&R menu but when the form is called form the Sales command button of the Customer card I cannot fire the code on the "Sell-to Customer No" OnAfterValidate trigger. I have tried putting code on the OnInsert trigger of the "Sales Header" table but I can not seem to be able to pass the correct Sales Header parameter on to the Confirmation form

Can anybody help?
Answer the question and wait for the answer.

Comments

  • Options
    eromeineromein Member Posts: 589
    Altough I don't think placing the code as you describe on the form and I'm thinking of a completly other solution, here is what you have to do:

    Create a function on your sales header form. Call it "SetShowOustandingLines(Showform:Boolean)".

    Place this parameter in a global boolean variable on your form. If this boolean is true, show the form.

    call the form from the menu as following:

    Salesquote.setshowoutstandinglines(true);
    Salesquote.runmodal;

    This should do the trick.

    Kind regards,

    Emiel Romein
    "Real programmers don't comment their code.
    If it was hard to write, it should be hard to understand."
  • Options
    StephenGStephenG Member Posts: 99
    Thanks or your reply.

    The problem seems to be that one of the functions on the forms or a Codeunit function filed.VALIDATE being called returns "Sales Header does Not exist". This is not a problem when you call the Sales Quote from the S&R menu because you fire the "Sell-to Customer No." OnAfterValidate trigger on the form where you can SAVERECORD and COMMIT before calling the forms when the "Sell-to Customer No." is keyed in.

    But when the Sales Quote form is run from the called from the customer card "Sell-to Customer No." is passed through as a filter and VALIDATED during the table OnInsert Trigger. So i can't put the code on OnValidate "Sell-to Customer No." because the record hasn't been inserted into the table yet.
    Answer the question and wait for the answer.
  • Options
    eromeineromein Member Posts: 589
    Hi,

    I'm not quite sure what you are trying to do here. My guess would be that you want to create a sales document from the customer card.

    Please take a good look at the Navision 3.70 functionality on this. It could very well be that the same functionality already exists in previous versions of Navision.

    If you open the order form from the customer card you can create a new order just by pressing F3. When inserting the new order Navision will automaticly fill and validate the customer no. on this order.

    If you are able to copy this functionality, you can move you open-outstanding-quantity form to the onvalidate of the customer number.

    You can then show or not show this form by passing booleans trough a function just like I described in my previous post.

    Not that you should re-programm your code, but if I understand your functionality correctly, this should be the "standard" Navision solution to deal with these kinds of problems.

    Kind regards,

    Emiel Romein
    "Real programmers don't comment their code.
    If it was hard to write, it should be hard to understand."
  • Options
    StephenGStephenG Member Posts: 99
    Hi Emiel

    Thanks for replying again.

    I am using the standard functionality for creating a Sales Quote from the Customer Card. The problem as i see it is with the code placed on the OnValidate "Sell- to Customer No.", is that the "Sell-to Customer No." is Validated during the OnInsert Trigger, I want to pass "Sales Header" as parameter on to the form(s) i want to call. The problem is when any lines are being created some of low lying code call GetSalesHeader, and as this Validation is On the OnInsert Trigger the record as not actual been inserted into the database.

    It's a case of Timing, what i really coul do with is an OnAfterInsert trigger, No chance of that.

    Thanks again
    Answer the question and wait for the answer.
  • Options
    eromeineromein Member Posts: 589
    Aaaah, now I get the problem.

    In that case it's a choice between re-programming the code (in forms) to work with your parameter, or keep your code in the OnAfterValidate trigger.

    I think we both know what option would be best. ;)

    But now to figure out a solution for your problem. I think you should copy your code into a function in the table. Make sure you call it after you validated the customer. What you could do to create a workaround for this problem is temoprarily insert the record and delete it again.
    OnInsert;
    BEGIN
      Validate(Customer,NewValue);
      OpenForm;
    END; // <- Moment of inserting record. So you can insert and delete it before this moment in time.
    
    Funtion OpenForm;
    BEGIN
      SalesHeader := Rec;
      IF SalesHeader.INSERT THEN; 
      FORM.SetParameters(SalesHeader);
      FORM.RUNMODAL; 
      SalesHeader.Delete;
    END;
    

    I'm not sure if it will work. I didn;t test it. I even think you can do this action on rec instead of copieing it to a var. But this is much nicer. Condition is that your form do not make any changes to the salesheader. If it does, you should maybe add this statement Rec := SalesHeader. And you can not use data that is not filled by creating a order and validating the customer.

    Good luck, or replay any questions.
    "Real programmers don't comment their code.
    If it was hard to write, it should be hard to understand."
  • Options
    StephenGStephenG Member Posts: 99
    Emiel

    Initial testing seems to be working.


    OnInsert()

    IF GETFILTER("Sell-to Customer No.") <> '' THEN
    IF GETRANGEMIN("Sell-to Customer No.") = GETRANGEMAX("Sell-to Customer No.") THEN BEGIN
    VALIDATE("Sell-to Customer No.",GETRANGEMIN("Sell-to Customer No."));
    IF "Document Type" = "Document Type"::Quote THEN
    IF NOT "Disallow Back Orders" THEN
    QuoteGetBackOrders;
    END;

    QuoteGetBackOrders()
    INSERT;
    COMMIT;
    TmpQuoteHeader := Rec;
    IF BackOrderMgt.OutStandingOrdersFound(Rec) THEN
    BackOrderMgt.ConfirmBackOrders(Rec);
    DELETE;
    Rec := TmpQuoteHeader;


    I needed the Commit because the ConfirmBackOrders is a RunModal FORM


    Many Many thanks for your help. :D
    Answer the question and wait for the answer.
  • Options
    eromeineromein Member Posts: 589
    You are welcome!

    Looks very nice. Some comments / suggestions / questions just to keep the post going.

    1.) Does the function BackOrderMgt.OutStandingOrdersFound(Rec) need the record to be inserted? If not it's better to do something like this:
    QuoteGetBackOrders() 
    IF NOT BackOrderMgt.OutStandingOrdersFound(Rec) THEN 
      EXIT;
    
    INSERT; 
    COMMIT; 
    TmpQuoteHeader := Rec; 
    BackOrderMgt.ConfirmBackOrders(Rec); 
    DELETE; 
    Rec := TmpQuoteHeader;
    

    or if you need to have the record inserted:
    QuoteGetBackOrders() 
    INSERT;
    IF BackOrderMgt.OutStandingOrdersFound(Rec) THEN BEGIN
      COMMIT;   
      TmpQuoteHeader := Rec;  
      BackOrderMgt.ConfirmBackOrders(Rec); 
      Rec := TmpQuoteHeader;
    END;
    DELETE; 
    

    In this case the INSERT, COMMIT and DELETE will not be executed if not nessesary.

    2.) I think it's better to insert you variable then inserting rec. I do not have the right arguments, but it's just a feeling.
    QuoteGetBackOrders() 
    TmpQuoteHeader := Rec;
    TmpQuoteHeader.INSERT; 
    COMMIT; 
    IF BackOrderMgt.OutStandingOrdersFound(TmpQuoteHeader) THEN
    BackOrderMgt.ConfirmBackOrders(TmpQuoteHeader); 
    TmpQuoteHeader.DELETE; 
    Rec := TmpQuoteHeader;
    

    3.) Do you make any changes to the sales header in the functions you call. If not it will not be nessesary to update your rec var. (rec := TempQuoteHeader).

    4.) I do not think you your "OutStandingOrderFound" function is a form. If it is, what I'm about to say is not correct. So this means you only have to commit any changes when you found something.
    QuoteGetBackOrders() 
    INSERT; 
    TmpQuoteHeader := Rec; 
    IF BackOrderMgt.OutStandingOrdersFound(Rec) THEN BEGIN
      COMMIT; 
      BackOrderMgt.ConfirmBackOrders(Rec); 
    END;
    DELETE; 
    Rec := TmpQuoteHeader; 
    
    "Real programmers don't comment their code.
    If it was hard to write, it should be hard to understand."
  • Options
    StephenGStephenG Member Posts: 99
    Hi Emiel

    Just early days of testing at the moment.
    You may not have the right for arguments but i don't care, but I am always open to suggestions and ideas, otherwise how else do we learn or improve.

    1) Sales Header is mainly passed so i can filter on "Sell-to Customer No."
    but then it is then passed to confirm form and then from there down into the code units which do all the work. They take details from the sales Header, but the Sales Header is NOT updated.

    2) I agree with about inserting the Variable.

    3) So with my answer above there is no reason why i shouldn't pass the Variable instead.

    4) You're right OutStandingOrdersFound is a Codeunit Function whic returns a Boolean, so the commit can be moved to where you said.


    As I have already said it's early days testing.

    Many thanks again for your knowledgable help and suggestions.

    I will let you know how I get on, I go on my summer Holiday at the end of next week :D , so it might not be until after I get back.
    Answer the question and wait for the answer.
  • Options
    eromeineromein Member Posts: 589
    Well it's my last day. Hello 3 week holiday!!!!

    I'll check the forum to read you posts.

    1 suggestion, I forgot in the last post. You can do this.
    IF ("Document Type" = "Document Type"::Quote) AND NOT "Disallow Back Orders" THEN 
      QuoteGetBackOrders; 
    END; 
    
    "Real programmers don't comment their code.
    If it was hard to write, it should be hard to understand."
  • Options
    StephenGStephenG Member Posts: 99
    Emiel

    Enjoy your holiday, I am only having 2 weeks (in Sunny France).

    I normally do my "if" Statements the way you said.

    Thanks
    Answer the question and wait for the answer.
Sign In or Register to comment.