0 votes


Some of the product linked to a document are batches (type of product).
On click on a "duplicate document" button :

  1. click on button
  2. iterate through DetailDataSet(DOCUPROD)
    2.1 if it's a batch --> duplicate it and replace the old ones with the new ones
    2.2 if it's not a batch, check F
    LOT and if it is not null update it with the last Batch

The function below works, but I found two ways to do this (cf. code) :
The first one duplicate the product (Batch), get the "old data", delete the "old" relation, insert the duplicate and update the relation fields with the "old data"

The second one just update the fields of the current relation.

I keep the second because it avoid me to copy the relation fields.

First problem : "CommiChanges" of prodEdit :
- if I don't commit it, the product don't exists in the DB, the Document is displayed properly, but an error is thrown when the user click on "save" or "apply" button
- if I commit it, the product is added in the DB, so the save/apply works, but if the user "cancel" the document the product is still in the DB...

Can I solve this problem or is it impossible ?

Second problem : docuProdDS.Edit
You can see 3 "docuProdDS.Edit()" in the function, it's because the first don't do anything :
- if I Use the first one, Efficy throw an error

Message: Error while executing Script "DuplicateDocu" at line 707 char
21. Message: "DSDocuEdit6DocuProd: Dataset not in edit or insert mode"

  • if I use the 2 last it works

Why Efficy say me that the Dataset is not editable if I don't use the first one and not le 2 last ?

To call my script I customized Efficy.js/Duplicate() in Custom.js :

function Duplicate(Entity, Key, Action, ExtraParam) {
    var Param = "copyfrom=" + Key;
    if (ExtraParam) Param += "&" + ExtraParam;

    if(Entity=='Docu') { // custom duplicate if it's a Document
        EditNewWithScript("Docu", Param, "serverscripts/Document.js", "DuplicateDocu")
    else { // else standard duplicate
        EditNew(Entity, Param, Action)


function DuplicateDocu() {
    Database.disableWorkflow = true; // don't trigger workflow ! (CommitDocu and InsertDocu_Prod)
    // document generated by the /Edit request
    var duplicateContext = Request.ContextHandle;
    var duplicateKey = Database.GetEditKey(duplicateContext);

    // get products
    var docuProdDS = Database.GetDetailDataSet(duplicateContext, ntProd);
    docuProdDS.Edit(); // don't works (error)

    if(docuProdDS && !docuProdDS.IsEmpty) {
        var batchKey; // contains the current batch key (K_PRODUCT)

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

            // debug only
            var k_lot = docuProdDS.FieldByName('F_LOT').AsFloat;
            var k_sort = docuProdDS.FieldByName('K_SORT').AsFloat;

            // Batch ? ==> duplicate lot
            if(k_product==k_lot) {
                var prodEdit = Database.OpenEditContext(ntProd, 0);    // batch destination

                try {
                    // duplicate the batch (same values) and get the generated key
                    Database.CopyFromExisting(prodEdit, k_product);
                    batchKey = Database.GetFieldValue(prodEdit, 'K_PRODUCT');

                    // update master NAME
                    Database.UpdateFields(prodEdit, 0, 'NAME', 'Nouveau lot (nom a changer)');
                    Database.CommitChanges(prodEdit, true); // HOW TO LINK NON PERSISTED BATCH (NO KEY) WITH THE DOCUMENT ???

                    /*** update detail ***/

                     * METHOD 1
                     * delete old relation
                     * insert the new Batch as detail, update relation fields
                     * delete the old batch
                     * PROBLEMS :
                     *  - even if the workflow is disabled it still works

                    // delete old batch from document
                    Database.DeleteDetail(duplicateContext, ntProd, k_product, k_relation);

                    // update detail field
                    Database.InsertDetail(duplicateContext, ntProd, batchKey, -1, false); // trigger workflow event OnInsertDetailDocuProd
                    Database.UpdateDetail(duplicateContext, ntProd, 0, 0, "F_LOT", batchKey);
                    Database.UpdateDetail(duplicateContext, ntProd, 0, 0, "K_SORT", k_sort);
                    Database.UpdateDetailStringField(duplicateContext, ntProd, 0, 0, 'NAME', 'Nouveau lot (nom a changer)');

                     * METHOD 2
                     * update fields of current relation
                     * delete the old batch

                    docuProdDS.FieldByName('K_PRODUCT').AsString = batchKey;
                    docuProdDS.FieldByName('NAME').AsString = 'Nouveau lot (nom a changer)';
                    docuProdDS.FieldByName('F_LOT').AsString = batchKey;
                    docuProdDS.FieldByName('K_SORT').AsString = k_sort;

                    // do I have to Commit ? If yes, is refresh require (true/fale) ?
                    //Database.CommitChanges(prodEdit, false);

                catch (e) {
                    Database.disableWorkflow = false; // if an exception is throw
                finally {
            else if(k_lot != '') { // if product come from a batch, update F_LOT
                docuProdDS.FieldByName('F_LOT').AsString = batchKey;

            Database.disableWorkflow = false;
asked in Efficy/ Client side by (245 points)
edited by

1 Answer

0 votes


for your first problem. A way to solve this, is to mark the Product to be dublicated and do the duplicate process in the workflow. The downside of this solution could be that the user doesn't see the name of the new Product yet. I haven't tested this solution, so I don't now if you could change the Name of the Product to display.

For your second problem, you can only put a row in the detail dataset in edit and not the entire detail dataset. As you didn't select an existing row yet when you do the first "docuProdDS.Edit();" that's why the error occured.

I hope this makes it more clear for you.

Best regards,

answered ago by (314 points)
1,167 questions
1,425 answers
325 users