locked
code to create sales order detail (order detail) RRS feed

  • Question

  • I need to create sales order detail along with sales order every month until our "production services Contract" is active (until service-end date).  I have a workflow that runs on "Production Services Contract"  and it is activated for every new/active contracts.

    When a new contract is activated,

    1. Workflow is activated
    2. Wait till 1st month and create an Order
    3. waitl till next month and create an order and so on.. untill service end-date  

    Workflow is working fine and creates new 'Sales Order' record. However, I am unable to create a 'SalesOrderDetail' record. Since workflow doesn't support custom wk activities in crm online, I can create a custom entity 'A' and insert salesorderdetail. I need a code that will take the record from 'A' and insert into salesorderdetail. Appreciate if any one can help me with a code. Thanks a lot.

     

     

    Monday, February 21, 2011 10:24 PM

Answers

  • There is a field of salesorderid in SalesOrder and SalesOrderDetail which links both the record. You are missing that.

    I haven't worked on CRM 2011 therefore I think you should close this thread and start a new thread by putting this code and asking what's wrong in this code. One thing is sure that it will work.


    Regards Faisal
    • Proposed as answer by Azure HA Monday, February 28, 2011 2:09 PM
    • Unproposed as answer by Azure HA Monday, February 28, 2011 2:10 PM
    • Marked as answer by SunnyCRM2011 Monday, February 28, 2011 2:11 PM
    Monday, February 28, 2011 1:58 PM

All replies

  • Hello Sunny,

    Here's a solution that I hope you'll like. Make a custom bit field (or picklist) on your order, and set it to a certain value for the workflow created orders. And for those orders, register a plugin for the Post Create event and check if the field value was set by your workflow, if yes, programmatically create order details, using the CRM SDK. For some examples on how to use it, please read these articles: http://social.microsoft.com/forums/en-US/crmdevelopment/thread/5e4c9ed1-0899-4821-95d3-b5543581fba3http://msdn.microsoft.com/en-us/library/ff681571.aspx. Hope this helps.


    Cornel Croitoriu - Senior Software Developer & Entrepreneur

    If this post answers your question, please click "Mark As Answer" on the post and "Mark as Helpful"

    CWS SoftwareBiz-Forward.comCroitoriu.NET

    Monday, February 21, 2011 10:39 PM
  • Thanks. Looks like, I would need Windows 7/visual studio 2010 in order to run the SDK reg tool (I was able to do with less in crm online beta!). Is that so?  Can it work with Vista 64/visual web developer 2010 express or visual basic 2010 express? As an alternative, can webservices be utilized that will read the order entity and create order detail entity? Apprecaite your thoughts. Also a code base will be very helpful.

    Tuesday, February 22, 2011 3:01 AM
  • Here is the code. You can use it after changing invoice to salesoreder:-
    using System.Collections.Generic;
    using System.Text;
    using System;
    using System.Collections;
    using System.Workflow.ComponentModel.Compiler;
    using System.Workflow.ComponentModel.Serialization;
    using System.Workflow.ComponentModel;
    using System.Workflow.ComponentModel.Design;
    using System.Workflow.Runtime;
    using System.Workflow.Activities;
    using System.Workflow.Activities.Rules;
    using System.Reflection;
    using Microsoft.Crm.Workflow;
    using Microsoft.Crm.Sdk;
    using Microsoft.Crm.SdkTypeProxy;
    using Microsoft.Crm.Sdk.Query;
    
    
    namespace AutoProductDetail
    {
      [CrmWorkflowActivity("Invoice Detail Creation")]
    	public class AutoInvoiceProductDetailWF : Activity
      {
       protected override ActivityExecutionStatus Execute(ActivityExecutionContext executionContext)
       {
         IContextService contextService = (IContextService)executionContext.GetService(typeof(IContextService));
         IWorkflowContext context = contextService.Context;
    
         ICrmService crmService = context.CreateCrmService();
    
    		 invoicedetail entity = new invoicedetail();
    		 
    		 entity.invoiceid = new Lookup();
    		 entity.invoiceid.Value = invoiceId.Value;
    		 
    		 entity.productid = new Lookup();
    		 entity.productid.Value = productid.Value;
    		 
    		 entity.quantity = new CrmDecimal();
    		 entity.quantity.Value = quantity.Value;
    		 
    		 entity.uomid = new Lookup();
    		 entity.uomid.Value = uomid.Value;
    		 
    		 entity.tax = new CrmMoney();
    		 entity.tax.Value = tax.Value;
    		 
    		 	 
    		 entity.isproductoverridden = new CrmBoolean();
    		 entity.isproductoverridden.Value = false;
    		 
    		 crmService.Create(entity);
    		 
         return base.Execute(executionContext);
       }
    
    		public static DependencyProperty invoiceIdProperty =
    		 DependencyProperty.Register("invoiceId",
         typeof(Lookup),
    		 typeof(AutoInvoiceProductDetailWF));
    
    		[CrmInput("Invoice")]
    		[CrmReferenceTarget("invoice")]
    		public Lookup invoiceId
    		{
    			get
    			{
    				return (Lookup)base.GetValue(invoiceIdProperty);
    			}
    			set
    			{
    				base.SetValue(invoiceIdProperty, value);
    			}
    		}
    
    		public static DependencyProperty productidProperty =
    		 DependencyProperty.Register("productid",
    		 typeof(Lookup),
    		 typeof(AutoInvoiceProductDetailWF));
    
    		[CrmInput("Product")]
    		[CrmReferenceTarget("product")]
    		public Lookup productid
    		{
    			get
    			{
    				return (Lookup)base.GetValue(productidProperty);
    			}
    			set
    			{
    				base.SetValue(productidProperty, value);
    			}
    		}
    
    		public static DependencyProperty uomidProperty =
    		 DependencyProperty.Register("uomid",
    		 typeof(Lookup),
    		 typeof(AutoInvoiceProductDetailWF));
    
    		[CrmInput("Unit")]
    		[CrmReferenceTarget("uom")]
    		public Lookup uomid
    		{
    			get
    			{
    				return (Lookup)base.GetValue(uomidProperty);
    			}
    			set
    			{
    				base.SetValue(uomidProperty, value);
    			}
    		}
    
    		public static DependencyProperty quantityProperty = 
    			DependencyProperty.Register("quantity", 
    			typeof(CrmDecimal),
    			typeof(AutoInvoiceProductDetailWF));
    
    		[CrmInput("Quantity")]
    		public CrmDecimal quantity
    		{
    			get
    			{
    				return (CrmDecimal)base.GetValue(quantityProperty);
    			}
    			set
    			{
    				base.SetValue(quantityProperty, value);
    			}
    		}
    
    
    		public static DependencyProperty taxProperty =
    			DependencyProperty.Register("tax",
    			typeof(CrmMoney),
    			typeof(AutoInvoiceProductDetailWF));
    
    		[CrmInput("Tax")]
    		public CrmMoney tax
    		{
    			get
    			{
    				return (CrmMoney)base.GetValue(taxProperty);
    			}
    			set
    			{
    				base.SetValue(taxProperty, value);
    			}
    		}
    
      }
    }
    
    You will register this assembly. In the workflow you can check different conditions in order to add different orderdetail.
    Regards Faisal
    Tuesday, February 22, 2011 10:18 AM
  • Hi Faisal, thanks a lot. I really appreciate it. Could I use this code to just create the sales order details only. The workflow is as follow:

    "Create sales order workflow" runs against "production services entity"

    Workflow fires every month

    1. creates a new sales order record <take the values from production service record>
    2. creates sales order details <where I would want the code to create one>
    3. Repeat this until service end-date

    I can store the sales order details <such as product, date, quantity etc., in the order entity in a custom fields>

    Where and how should I use your code to create the sales order? I would much appreciate any help. thanks a lot

    Tuesday, February 22, 2011 12:41 PM
  • Also does the assembly is applicable in the CRM 2011 ONLINE? thanks
    Tuesday, February 22, 2011 12:42 PM
  • Not sure about CRM 2011 but someone will help you.

    This assembly will attach a product with the sales order. As invoice and order are similar entities therefore you just have to change invoicedetail to salesorderdetail, invoice to order and invoiceid to salesorderid. In you workflow when you create order you will select this assembly in Action and Add products to sales order. You can add as many products as you like by calling this assembly.

    You can store data such as product, date, quantity etc., in the order entity in a custom fields in order entity but you will have issue when the order has more than one product.

    You need to register this assembly(after making above mentioned changes) using visual studio 2005/8. Once it is registered on CRM server it will be available for use in the Action menu of workflows.

    Please feel free to ask any question if you find any issue.

     


    Regards Faisal
    Tuesday, February 22, 2011 2:53 PM
  • Thanks so much But the SDK CRM 2011 requires me to have windows 7/Visual studio 2010.

    Since there is only one sales order and 1 sales order detail per contract, so I think this should be fine. I cannot call the plug-in from the workflow in crm 2011 online.

    So I would need to register this plug-in for the CRM sales order Entity. Could it work? Or could I possible use in any of the form event?  Is there any easy way (withoutht having to register plug-in etc.,). Appreciate it.

     

     

    Tuesday, February 22, 2011 3:56 PM
  • Also I am wondering if I could edit your source code in web developer 2010 (is it a .cs file or jscript). Thank you
    Tuesday, February 22, 2011 4:06 PM
  • This code is for workflow assembly. You don't need plugin with it. You can also user Javascript to create orderdetails but it will not work with workflow and only work if user opens the form.
    Regards Faisal
    Tuesday, February 22, 2011 4:08 PM
  • Thanks. CRM 2011 online does not support custom workflow activities. Does it support assemblies? As a work-around, I can register this as a plug-in and run against the Sales Order entity. Every time a new sales order record is created by the workflow (I can set a flag to determine that this is created by the Worflow).  

    1. Workflow -> Creates Sales Order record
    2. <plug-in> creates the sales order detail.
    3. From what I understand, <Plug-in > can be called in the "Post Create event" to create the sales order detail.

    If I need to create a plug-in using code, what I would need to do? Appreciate your thoughts.

    Tuesday, February 22, 2011 4:27 PM
  • Hi,

    As you are 100% sure that one order will always have one product then you can create a relationship of product with salesorder by doing:-

    1. From customization open Order

    2. Click N:1 Relationships (LHS)

    3. Click Many to 1 Relationship button

    4. Select Product as Primary Entity

    5. Give it a name say Product

    6. In Display option select Do not Display

    7. Relationship Behaviour is default which is Referential.

    8. Click Save and Close

    9. Open the main form of order and Add Product field created above.

    10 Save and publish customization.

    Now you can add product to sales order using one workflow and you don't need any custom workflow or plugin.

    Same way you can add a int field of quantity. You can use CreatedOn or ModifiedOn dates or may create a new date field.

    As Opportunity, Quote, Order and Invoice are similar entities therefore you will have to do this on all these sales entities. Sales reports which comes with off the self CRM will not work as they fetch data from salesorderdetail entity therefore you will have to modify them.

     

     

     


    Regards Faisal
    • Proposed as answer by Seepath Tuesday, February 22, 2011 6:20 PM
    Tuesday, February 22, 2011 4:45 PM
  • This is awesome. I just can't to test this out. Thank you so much.
    Tuesday, February 22, 2011 6:20 PM
  • Hi Faisal, question: so my workflow will insert the Product, qty fields created in the Sales Order? Say, if quanity is 10, will the total amout be reflected in the sales order form.. Total amout is a read only value in sales order.. is there any other way to create sales order detail (even with above relationship settings) through workflow? Though its only one sales order detail, the quanty, product, will affect the total amount in the Sales Order. Appreicate any thoughts.
    Tuesday, February 22, 2011 7:13 PM
  • The totalamount property is read-only, additionally there is no way to modify the built-in calculations. You're probably best off using custom attributes for Total Amount.  You can use the above assembly code to attach a orderdetail to order using workflow.
    Regards Faisal
    Wednesday, February 23, 2011 11:51 AM
  • Thanks faisal. I will take your code and modify it for the sales oder detail. Now I have to register this as a plug-only in crm online. I hope that I can be able to create a plug-in using the above code in the visua studio. what would be the best way to do that. Should compile as cs, js, vb?. Appreciate any thoughts. 

     

    Wednesday, February 23, 2011 1:07 PM
  • I didn't realized that I have responding to two persons.

    This code is for a workflow assembly and will not work for a plugin. As you are using crm online therefore we have limited options. I think create a product (as stated above), quantity and Total Amount fields in sales order and populate them with workflows. Now you can also get the price of product from product entity in to order using workflows.

    If you still want to create a plugin follow these links:-

    http://wdeconinck.wordpress.com/2009/01/12/creating-a-simple-microsoft-crm-40-plugin/

    http://wdeconinck.wordpress.com/2009/01/12/creating-a-simple-microsoft-crm-40-plugin/


    Regards Faisal
    Wednesday, February 23, 2011 1:26 PM
  • thanks faisal.

    Thursday, February 24, 2011 6:16 PM
  • Hi cornel, I need the plug-in to create a salesorder detail based on the product, price per unit, quanity that I create in a cutom attributes in Sales Order.

    I can set the value for e.g. salesorderdetail.description = "new detail'; But How can I do this --> salesorderdetail.productid.id = salesorder.v_product ? Any thoughts

    Friday, February 25, 2011 2:26 AM
  • Hi Sunny,

    Sorry for replying late. Create one attribute in order 'quantity' Decimal. Create two N:1 relationships:-

    1. Primary Entity = Product      Name = Product        Schema Name = productid  Display = Donot Display    Realtionship = Referential

    2. Primary Entity = Unit      Name = UOM       Schema Name = uomid  Display = Donot Display    Realtionship = Referential

    Put these attributes on Order form and publish Order Form.

    Follow this link to deploy the plugin assembly:- http://msdn.microsoft.com/en-us/library/bb955365.aspx

    Replace the whole code of assembly with this code and register assembly on Create of Order:-

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using Microsoft.Crm.Sdk;
    using Microsoft.Crm.Sdk.Query;
    using Microsoft.Crm.SdkTypeProxy;
    
    namespace AutoConnectionCreation
    {
      public class AutoConnection : IPlugin
      {
    
        public void Execute(IPluginExecutionContext context)
        {
          ICrmService service = context.CreateCrmService(true);
    
          DynamicEntity entity = (DynamicEntity)context.InputParameters[ParameterName.Target];
          if (entity.Name == "salesorder")
          {
            try
            {
            // Create sales order detail
            DynamicEntity oDetail = new DynamicEntity();
            oDetail.Name = EntityName.salesorderdetail.ToString();
            oDetail.Properties.Add(new CrmDecimalProperty("quantity", (CrmDecimal)entity.Properties["new_quantity"]));
            oDetail.Properties.Add(new LookupProperty("productid", (Lookup)entity.Properties["new_productid"]));
            //oDetail.Properties.Add(new LookupProperty("salesorderid", (Lookup)entity.Properties["salesorderid"]));
            oDetail.Properties.Add(new LookupProperty("uomid", (Lookup)entity.Properties["new_uomid"]));
            oDetail.Properties.Add(new CrmBooleanProperty("isproductoverridden", new CrmBoolean(false)));
            if (context.OutputParameters.Properties.Contains("id"))
    
            {
              Lookup lookup = new Lookup();
              lookup.Value = new Guid(context.OutputParameters.Properties["id"].ToString());
              lookup.type = EntityName.salesorder.ToString();
              oDetail.Properties.Add(new LookupProperty("salesorderid", lookup));
            }
                TargetCreateDynamic targetCreate = new TargetCreateDynamic();
                targetCreate.Entity = oDetail;
    
                // Create the request object.
                CreateRequest create = new CreateRequest();
    
                // Set the properties of the request object.
                create.Target = targetCreate;
    
                // Execute the request.
                CreateResponse created = (CreateResponse)service.Execute(create);
    
              }
              
            
            catch (System.Web.Services.Protocols.SoapException ex)
            {
              throw new InvalidPluginExecutionException("An error occurred in the Create Connection plug-in.", ex);
            }
    
          }
        }
    
      }
    }
    

    I have tested by creating a record therefore it should work even the order is created by workflow. Please let me know if you find problem.

     

     


    Regards Faisal
    Friday, February 25, 2011 5:05 PM
  • Hello faisal, thanks so much. I really apprecaite it. I am actually testing code. I have a look up attributes in the Order form for product, unit and another quantity (decimal).
    Friday, February 25, 2011 9:04 PM
  • Hello Faisal, looks like your code is written for crm 4.0 and am trying to convert it for the CRM 2011 online (though I am not that proficient)
    Friday, February 25, 2011 11:10 PM
  • Yes, I have tested on crm 4 . I don't have 2011 at the moment.
    Regards Faisal
    Saturday, February 26, 2011 3:56 AM
  • Hello faisal, i tried to convert your code to crm 2011 but without success as below. (BTW, you could sign up for a 30 day free trial for crm 2011 online). I would love use the early bind concept but don't know what references that I should set. Also the "look up" for productID  doesn't seem to work!! Apprecaite if you could share your thoughts.

     


    Monday, February 28, 2011 1:31 PM
  • There is a field of salesorderid in SalesOrder and SalesOrderDetail which links both the record. You are missing that.

    I haven't worked on CRM 2011 therefore I think you should close this thread and start a new thread by putting this code and asking what's wrong in this code. One thing is sure that it will work.


    Regards Faisal
    • Proposed as answer by Azure HA Monday, February 28, 2011 2:09 PM
    • Unproposed as answer by Azure HA Monday, February 28, 2011 2:10 PM
    • Marked as answer by SunnyCRM2011 Monday, February 28, 2011 2:11 PM
    Monday, February 28, 2011 1:58 PM
  • Thanks a lot for your help and support. I will go ahead and create a new thread.

    Monday, February 28, 2011 2:12 PM