<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0">
<channel>
<title>Efficy Overflow Q&amp;A - Recent questions tagged positiondetail</title>
<link>https://overflow.efficy.io/?qa=tag/positiondetail</link>
<description>Powered by Question2Answer</description>
<item>
<title>How to know if a PROD_OPPO relation exists based on DOCU_PROD</title>
<link>https://overflow.efficy.io/?qa=3499/how-to-know-if-prodoppo-relation-exists-based-on-docuprod</link>
<description>&lt;p&gt;Hi!&lt;/p&gt;

&lt;p&gt;When I commit Document I have to update product on Opportunity :&lt;br&gt;
- if a Docu&lt;em&gt;Prod is remove I want to remove it from the PROD&lt;/em&gt;OPPO&lt;br&gt;
- if a Docu&lt;em&gt;Prod is update I have to update PROD&lt;/em&gt;OPPO&lt;br&gt;
- if a Docu&lt;em&gt;Prod is added I have to insert it in the PROD&lt;/em&gt;OPPO&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;important notes :&lt;br&gt;
- insert copy DOCU&lt;em&gt;PROD.K&lt;/em&gt;RELATION in PROD&lt;em&gt;OPPO.K&lt;/em&gt;RELATION&lt;br&gt;
- PROD&lt;em&gt;OPPO have a F&lt;/em&gt;K&lt;em&gt;DOCUMENT field which contains the K&lt;/em&gt;DOCUMENT to know which Document linked it&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Unless I'm wrong, in the After or BeforeCommitDocu event, with GetDetailDataSet(EditHandle, ntProd) we are not able to know the removed relation, so, to remove the product on the Opportunity my workflow (example with Oppo as container) get:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Trigger AfterCommitDocu(EditHandle)&lt;/li&gt;
&lt;li&gt;Check the container (ntOppo op ntProj based on the reference of the document)&lt;/li&gt;
&lt;li&gt;Get the container key and open the edit context (containerEdit)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;First I check the products to delete on the Oppo :&lt;br&gt;
 4.1 Execute an SQL Query to get the products of the Oppo&lt;br&gt;
 4.2 Iterate through the result Dataset&lt;br&gt;
 4.3 To check if the product is not in the document I use PositionDetail(EditHanle) (cf workflow below)&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Link and update products of the document&lt;/li&gt;
&lt;li&gt;If the container is an Opportunity I update its BUDGET&lt;/li&gt;
&lt;li&gt;Commit the changes of the Oppo&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I have just a problem in the 5th bullet point : PositionDetail always return false and at the and all the PROD_OPPO obtained with the request are deleted.&lt;br&gt;
I think the CommitChanges calls all InsertDetails first, and then DeleteDetail..&lt;/p&gt;

&lt;p&gt;Why PositionDetail is not able to return me true ? I checked with the Logger and and the K&lt;em&gt;PRODUCT and K&lt;/em&gt;RELATION are correct. I can not find example of PositionDetail (edn, standard code, ...)&lt;/p&gt;

&lt;p&gt;P.S : in DeleteProdOnContainer what is the better way to delete the record ? Database.DeleteDetail() or or the TDataSet.delete() method ?&lt;/p&gt;

&lt;p&gt;Workflow :&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;// called by AfterCommitDocu
function GestionDocuProd(EditHandle, Inserted) {
  var containerHandle=0;
  var Ref = Database.GetFieldValue(EditHandle, 'REFERENCE');

  // update Oppo or Proj ?
  switch(true) {
    case /^D\d+$/.test(Ref) : // DEVIS
      // pas de traitement si Devis final
      if(Database.GetFieldValue(EditHandle, 'F_STATUS') == 5) {
        return;
      }
      containerHandle = ntOppo;
      break;
    case /^IPC/.test(Ref) : // COMMANDE
      containerHandle = ntProj;
      break;
    default:
      return;
      break;
  }

  // key of the container : Devis ==&amp;gt; Opportunity || IPC ==&amp;gt; Project
  var containerKey = Database.GetMainDetail(EditHandle, containerHandle);

  // Erreur si pas de container
  if(containerKey==0) {
    if(containerHandle==ntOppo) {
      throw new Error(&quot;This type of document must be linked to a container (devis = opportunity) / Le document doit être lié a un container (devis = Opportunité&quot;);
    }
    else if(containerHandle==ntProj) {
      throw new Error(&quot;This type of document must be linked to a container (Commande / IPC = Dossier) / Le document doit être lié a un container (Commande / IPC = Dossier&quot;);
    }
  }

  // Document key and container Edit context
  var docuKey = Database.GetEditKey(EditHandle);
  var containerEdit = Database.OpenEditContext(containerHandle, containerKey);

  Database.CopyDetails(containerEdit, EditHandle, [ntCont, ntComp, ntProf], false, false);

  try {
    /* delete product on Oppo/Proj */
    DeleteProdOnContainer(containerEdit, containerKey, EditHandle, docuKey);

    /* Insert &amp;amp; Update product */
    UpdateProdOnContainer(EditHandle, Ref, containerHandle, containerEdit)

    if(containerHandle == ntOppo) {
      Database.CommitChanges(containerEdit, true); // persist link to update BUDGET

      // Get new BUDGET
      var SQLGetNewBudget = &quot;Select Coalesce(Sum(TOTAL),0) as BUDGET from &amp;lt;#TABLE NAME='PROD_OPPO'&amp;gt; where K_OPPORTUNITY=:param1 and F_LOT &amp;lt;&amp;gt; K_PRODUCT&quot;;
      var result = ExecuteQuery(SQLGetNewBudget, containerKey);
      var newBudget = result.FieldByName('BUDGET').AsFloat || 0;

      // Update
      Database.UpdateField(containerEdit, 0, 'BUDGET', newBudget);
    }

    Database.CommitChanges(containerEdit, false);
  }
  finally {
    Database.CloseContext(containerEdit);
  }
}
function DeleteProdOnContainer(ContainerEdit, ContainerKey, DetailEdit, K_DOCUMENT) {
  var SQLGetProducts = &quot;select * from &amp;lt;#TABLE NAME=\&quot;PROD_OPPO\&quot;&amp;gt; where K_OPPORTUNITY=:param1 and F_K_DOCUMENT=:param2&quot;;
  var params = ContainerKey+'\n'+K_DOCUMENT;

  var prodDS = ExecuteQuery(SQLGetProducts, params);

  if(!prodDS.IsEmpty) {
    prodDS.First

    while(!prodDS.EoF) {
      var k_product = prodDS.FieldByName('K_PRODUCT').AsFloat;
      var k_relation = prodDS.FieldByName('K_RELATION').AsFloat;
      var k_lot = prodDS.FieldByName('F_LOT').AsFloat;
      var k_opportunity = prodDS.FieldByName('K_OPPORTUNITY').AsFloat;

      var debugStr = 'RELATION OPPO_PROD ' + k_opportunity+'-'+k_product + '('+k_relation+') from Batch ' + k_lot

      // if current PROD_OPPO/PROD_PROJ don't exists on Document ==&amp;gt; delete on Oppo
      if(!Database.PositionDetail(DetailEdit, ntProd, k_product, k_relation)) {

        // What is better ? delete() or DeleteDetail() ?
        // prodDS.delete();
        //Logger.Write('Delete Oppo-Prod 136-' + k_product + '('+k_relation+')');
        debugStr += ' | DELETE'

        Database.DeleteDetail(ContainerEdit, ntProd, k_product, k_relation);
      }
      Logger.Write(debugStr);
      prodDS.Next;
    }
  }
  else {
    Logger.Write('No product on container');
  }
}
// insert and/or update PROD_OPPO from current DOCU_PROD
function UpdateProdOnContainer(EditHandle, Ref, containerHandle, ContainerEdit) {
  var docuProdDataSet = Database.GetDetailDataSet(EditHandle, ntProd);
  if(!docuProdDataSet.IsEmpty) {
    docuProdDataSet.First;
    // fields to copy
    var FieldList = [&quot;QUANTITY&quot;, &quot;PRICE&quot;, &quot;TOTAL&quot;, &quot;F_LOT&quot;];

    if(containerHandle==ntOppo) { // PROD_OPPO have more field to copy than PROD_PROJ
      FieldList = FieldList.concat([&quot;RATE&quot;, &quot;DISCOUNT&quot;, &quot;VAT&quot;, &quot;CONSO_RATE&quot;, &quot;CONSO_TOTAL&quot;]);
    }

    while(!docuProdDataSet.EoF) {
      var prodKey = docuProdDataSet.FieldByName(&quot;K_PRODUCT&quot;).AsFloat;
      var relKey = docuProdDataSet.FieldByName(&quot;K_RELATION&quot;).AsFloat;
      Database.InsertDetail(ContainerEdit, ntProd, prodKey, relKey, false);

      // copy relation fields value
      for (var i = 0; i &amp;lt; FieldList.length; i++) {
        Database.UpdateDetailField(ContainerEdit, ntProd, 0, relKey, FieldList[i], docuProdDataSet.FieldByName(FieldList[i]).AsFloat);
      }
      Database.UpdateDetailField(ContainerEdit, ntProd, 0, relKey, 'F_K_DOCUMENT', docuProdDataSet.FieldByName('K_DOCUMENT').AsFloat);  // --&amp;gt; which document have linked the product
      Database.UpdateDetailStringField(ContainerEdit, ntProd, 0, relKey, 'F_DOCUREF', Ref);  // --&amp;gt; easy way to get the Document reference in the Opportunity.Products grid
      Database.UpdateDetailStringField(ContainerEdit, ntProd, 0, relKey, 'COMMENT', docuProdDataSet.FieldByName('COMMENT').AsString);

      docuProdDataSet.Next;
    }
  }
  else {
    Logger.Write('No product on document');
  }
}
&lt;/code&gt;&lt;/pre&gt;
</description>
<category>How to</category>
<guid isPermaLink="true">https://overflow.efficy.io/?qa=3499/how-to-know-if-prodoppo-relation-exists-based-on-docuprod</guid>
<pubDate>Mon, 03 Sep 2018 15:25:20 +0000</pubDate>
</item>
</channel>
</rss>