[gelöst] Auftragsprodukte aktuelle Preisberechnung Plugin

14. Oktober 2015 14:06

Hallo zusammen,

ich habe ein Plugin geschrieben, dass beim erzeugen eines Auftragsprodukts bestimmte Felddaten aus dem Produkt im Produktkatalog zieht wie Beschreibung usw. und diese Daten in Felder des Auftragsprodukts speichert. Bisher lief das im alten CRM über ein JavaScript aber in der neuen schnell Eingabe über die Subgrids greift das JavaScript im Create ja nicht mehr. Gleiches Plugin habe ich auch für Angebot, Rechnung und Verkaufschance geschrieben. Bei Verkaufschance und Angebot läuft es Problemlos. Bei Auftrag und Rechnung machte es Probleme. Es kam immer die Fehlermeldung das product und Einheit gelockt wären. Das Produktfeld versuche ich im Plugin gar nicht zu setzen und auch nachdem ich die Einheit auskommentiert habe kam der Fehler weiterhin. Irgendwann viel mir das Schloss über dem Subgrid auf. Es hat den Status offen (Aktuelle Preisberechnung verwenden) oder geschlossen (Preisberechnung gesperrt). Wenn es auf Preisberechnung gesperrt steht funktioniert mein Plugin und das neue Produkt wird anstandslos angelegt. Wenn das Schloss aber offen ist dann kommt besagter Fehler. Wenn ich das Plugin ausschalte kann ich auch bei geöffnetem Schloss Produkte anlegen. Was genau passiert wenn ich das schloss auf mache, was wenn ich es zu mache? Und kann ich den zustand irgendwie im Plugin abfangen um die Fehlermeldung abzufangen? Oder was muss in meinem Plugincode anders laufen, damit das Produkt in jedem Fall abgespeichert werden kann?
Zuletzt geändert von Nicole Schmitz am 19. Oktober 2015 11:02, insgesamt 3-mal geändert.

Re: Auftragsprodukte aktuelle Preisberechnung Plugin

15. Oktober 2015 10:08

Hallo zusammen,

ich stand mal wieder auf dem Schlauch. Das Feld im Auftrag das ich suchte war ispricelocked. Ist ja auch recht einleuchtend. :lol:
Löst mein Problem zumindest in soweit als das ich das Updaten der Entität über das Plugin damit umgehen kann, wenn die Preise gesperrt sind. Das blöde ist das ich ja auch alle anderen Felder im Auftragsprodukt dadurch nicht anpassen kann, da selbst bei einem Entitätsupdate in dem ich nichts verändere eine Fehlermeldung kommt, das Product und Unit nicht angepasst werden dürfen. Gibt es noch irgendeine andere Möglichkeit, wie ich über das Plugin auch bei gesperrten Preisen Felder der Auftragsprodukte die nichts mit der Preisberechnung zu tun haben einzeln neu befüllen kann? Mir fällt dazu im Moment so gar nichts ein.
Hat einer von Euch vielleicht eine Idee?

Re: Auftragsprodukte aktuelle Preisberechnung Plugin

15. Oktober 2015 14:26

Hallo zusammen,

ist es denn generell möglich ein Auftragsprodukt über ein Plugin upzudaten, wenn für den Auftrag die Preise gesperrt sind? Oder ist das via Plugin einfach nicht erlaubt? Ich habe mich jetzt schon asynchron hinter das Create gehängt in der Hoffnung das es dann funktioniert aber leider ist dem nicht so. Wenn ich das angelegte Auftragsprodukt von Hand im Formular öffne kann ich die fehlenden Textwerte eintragen und das Auftragsprodukt ohne Probleme abspeichern. Daher verstehe ich nicht warum das über das Plugin nicht funktioniert.

Ich poste hier einfach mal den Quellcode mit rein. Vielleicht hat dann jemand eine Idee was ich da falsch mache.

Code:
using System;
using System.Diagnostics;
using System.ServiceModel;
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Metadata;
using Microsoft.Xrm.Sdk.Query;

namespace ZugeordnetesProduktCreate
{
   public class AuftragProduktCreate: IPlugin
   {
        private IOrganizationService _service;

      /// <summary>
        /// Dieses Plugin wird bei jedem Create eines zugeordneten Produktes wie Verkaufschance Produkt, Angebots Produkt etc. ausgeführt.
        /// Gerade wenn die Produkte über die Schnellerfassung angelegt werden ist dies wichtig damit die Felder die aus dem Produktkatalog gezogen
        /// werden müssen auch gezogen werden.
        /// Früher ging dies beim öffen des Formulars im Status Create über JavaScript aber nach einer Schnellerfassung steht das Form schon im Status
        /// Update bevor es das erste mal geöffnet wird.
      /// </summary>
        /// <remarks>Register this plug-in on the Create message, account entity,
        /// and pre-operation stage.
        /// </remarks>
        public void Execute(IServiceProvider serviceProvider)
      {

            // Obtain the execution context from the service provider.
            Microsoft.Xrm.Sdk.IPluginExecutionContext context = (Microsoft.Xrm.Sdk.IPluginExecutionContext)
                serviceProvider.GetService(typeof(Microsoft.Xrm.Sdk.IPluginExecutionContext));

            IOrganizationServiceFactory factory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
                _service = factory.CreateOrganizationService(null);

            // The InputParameters collection contains all the data passed in the message request.
         if (context.InputParameters.Contains("Target") &&
            context.InputParameters["Target"] is Entity)
            {
                // Obtain the target entity from the input parameters.
            Entity entity = (Entity)context.InputParameters["Target"];

                // Überprüfen ob es sich um ein Auftrag Produkt handelt
                // Wenn nicht wurde das Plugin falsch registiert.
                if (entity.LogicalName == SalesOrderDetail.EntityLogicalName)
                {
                    //Wenn Create vollen datensatz holen
                    if (context.MessageName == "Create")
                    {
                        //Prüfen ob Preise gesperrt in übergeordnetem Auftrag gesetzt ist. Falls ja dürfen die Felder Einheit Preis per Unit und Produkt
                        //nicht vom Plugin gesetzt werdne sonst gibt es einen Fehler
                        Boolean priceLocked = true;
                        ColumnSet salesOrderDetailCols = new ColumnSet(new String[] { "salesorderid" });
                        Guid salesOrderDetailId = entity.Id;
                        SalesOrderDetail retrievedSalesOrderDetail =
                            (SalesOrderDetail)_service.Retrieve("salesorderdetail", entity.Id, salesOrderDetailCols);

                        ColumnSet salesOrderCols = new ColumnSet(new String[] { "ispricelocked" });
                        if (retrievedSalesOrderDetail.SalesOrderId != null)
                        {
                            EntityReference salesOrderReference = (EntityReference)retrievedSalesOrderDetail.SalesOrderId;
                            Guid salesOrderRefId = salesOrderReference.Id;

                            SalesOrder retrievedSalesOrder =
                                (SalesOrder)_service.Retrieve("salesorder", salesOrderRefId, salesOrderCols);
                            if (retrievedSalesOrder.IsPriceLocked != null)
                            {
                                priceLocked = (Boolean) retrievedSalesOrder.IsPriceLocked;
                            }

                        }

                        if (priceLocked)
                        {
                            //Preise sind gesperrt hier muss noch Lösung gefunden werden wie Daten gezogen werden können
                            //auch reines update der entität ohne veränderung geht nicht
                        }
                        else
                        {
                            //Preise sind nicht gesperrt hier können Daten ohne Probleme gezogen werden
                            //Wenn ein Produkt angegeben wird, dieses ermitteln und Daten in angebotprodukt schreiben
                            if (entity.Attributes.Contains("productid") && entity.Attributes["productid"] != null)
                            {
                                //Referenz auslesen und ID holen
                                EntityReference productEntityRef = (EntityReference)entity.Attributes["productid"];
                                Guid productRef = productEntityRef.Id;

                                // Retrieve the product containing several of its attributes.
                                ColumnSet cols = new ColumnSet(
                                    new String[] { "defaultuomid", "price", "name",  "cust_ueberschrift_kalkulation",
                                    "cust_produktnameenglisch", "customization_it", "customization_autom",
                                    "customization_e_plan", "customization_hardware", "cust_purchase_price",
                                    "cust_html_description_de", "cust_html_description_en"});

                                Product retrievedProduct = (Product)_service.Retrieve("product", productRef, cols);

                                entity.Attributes["uomid"] = retrievedProduct.DefaultUoMId;
                                entity.Attributes["cust_ics_shortdescription"] = retrievedProduct.Name;
                                entity.Attributes["cust_kurzbeschreibungenglisch"] = retrievedProduct.Cust_Produktnameenglisch;

                                entity.Attributes["cust_html_description_de"] = retrievedProduct.Cust_html_description_de;
                                entity.Attributes["cust_html_description_en"] = retrievedProduct.Cust_html_description_en;

                                entity.Attributes["priceperunit"] = retrievedProduct.Price;
                                Money listenpreis = retrievedProduct.Price;
                                if (retrievedProduct.cust_ueberschrift_kalkulation != null)
                                {
                                    Boolean isueberschrift = (Boolean)retrievedProduct.Cust_ueberschrift_kalkulation;
                                    if (listenpreis.Equals(new Money(0)) && isueberschrift.Equals(true))
                                    {
                                        entity.Attributes["priceperunit"] = new Money(0);
                                        entity.Attributes["ispriceoverridden"] = true;
                                    }
                                }                   

                                entity.Attributes["customization_it"] = retrievedProduct.Customization_it;
                                entity.Attributes["customization_autom"] = retrievedProduct.Customization_autom;
                                entity.Attributes["customization_e_plan"] = retrievedProduct.Customization_e_plan;
                                entity.Attributes["customization_hardware"] = retrievedProduct.Customization_hardware;

                                entity.Attributes["cust_purchase_price_per_unit"] = retrievedProduct.Cust_purchase_price;
                                entity.Attributes["cust_purchase_price_total"] = retrievedProduct.Cust_Einkaufspreiskostengesamt;                           

                                // Update the Auftragprodukt record.
                                _service.Update(entity);

                            }
                        }
                       
                    }   
            }
            }
      }
   }
}

Re: Auftragsprodukte aktuelle Preisberechnung Plugin

16. Oktober 2015 08:06

Hallo Nicole,

wenn in einem Auftrag die Preise gesperrt sind, kannst du sie auch mit einem PlugIn nicht direkt ändern.
Du kannst aber per PlugIn die Sperre entfernen, die Preise ändern und anschließend den Auftrag wieder sperren.

Re: Auftragsprodukte aktuelle Preisberechnung Plugin

19. Oktober 2015 09:48

Hallo Michael,

das ist natürlich auch eine Idee. Super das versuche ich. Danke :)

Re: Auftragsprodukte aktuelle Preisberechnung Plugin

19. Oktober 2015 10:40

Hallo Michael,

ich habe versucht über mein Plugin die Auftragsvariable IsPriceLocked zu setzen, aber schon beim Programmieren wird mir angezeigt "The Property SalesOrder.IsPriceLocked has no setter". Wenn ich das richtig verstehe kann ich diese Variable also gar nicht über den Code setzen. Habe ich da was falsch gemacht?

Re: Auftragsprodukte aktuelle Preisberechnung Plugin

19. Oktober 2015 11:02

Hallo,

mein Fehler, ich wollte die Variable setzen und habe übersehen dass es ja extra einen Request dafür gibt. Ich muss natürlich über UnlockSalesOrderPricingRequest und LockSalesOrderPricingRequest die Preisberechnung entsperren und sperren.
Code:
// Unlock the order pricing
UnlockSalesOrderPricingRequest unlockOrderRequest =
  new UnlockSalesOrderPricingRequest()
  {
    SalesOrderId = salesOrderReference.Id
  };
_service.Execute(unlockOrderRequest);


//Lock the order pricing
LockSalesOrderPricingRequest lockOrderRequest =
  new LockSalesOrderPricingRequest()
  {
    SalesOrderId = salesOrderReference.Id
  };
_service.Execute(lockOrderRequest);


Dann funktioniert das Ganze einwandfrei.