duplicating a line with related children

Hi all

I need to duplicate a line with its associated related data (although not all related data needs to be copied). I found an excellent forum post by Greg Pierce which pointed me in this direction, but I can’t get it to work:

var rec = foundset.getRecord(foundset.getSelectedIndex()); // current
var dup = foundset.getRecord(foundset.duplicateRecord()); // dupe

for(var ix=1; ix<=databaseManager.getFoundSetCount(rec.relation1); ix++)
{
   var relRec = rec.relation1.getRecord(ix);
   var relDupe = dup.relation1.getRecord(dup.relation1.newRecord());
   // copy cols, whatever here
}

This is how I’ve applied it to my own version. It copies the main line, but not the children.

databaseManager.saveData()	
	

		var rec = foundset.getRecord(foundset.getSelectedIndex()); // current

		var dup = foundset.getRecord(foundset.duplicateRecord(false,false)); // dupe
		var vtempdup = dup.line_itemsid

		// set the duplicate:
		dup.sales_id = forms.choose_groups_for_moved_line.foundset.sales_id
		dup.main_group = forms.choose_groups_for_moved_line.main_group
		dup.invoice_number = null
		dup.invoice_number_text = null
		dup.invoice_number_int_backup = null
		dup.invoice_number_text_backup = null
		dup.invoice_type_backup = null
		dup.invoice_type_from = null
		dup.invoice_type_to = null
			
		
//		application.output(line_items_to_line_items_fk_with_just_line_items_id.getSize())
		
		for(var ix=1; ix <= line_items_to_line_items_fk_with_just_line_items_id.getSize(); ix++)
				{
				var relRec = rec.line_items_to_line_items_fk_with_just_line_items_id.getRecord(ix);
				application.output('got relrec' + ix)
//				var relDupe = rec.line_items_to_line_items_fk_with_just_line_items_id.duplicateRecord();
//				application.output('relDup set')
				
		//		application.output(vtempdup)
				
				relDupe.line_items_fk = vtempdup
				relDupe.description = relRec.description
				relDupe.quantity = relRec.quantity
				relDupe.supplier = relRec.supplier
				relDupe.unit = relRec.unit
				relDupe.cost = relRec.cost
				
			
//			   	var relRec = rec.line_items_to_line_items_fk_with_just_line_items_id.getRecord(ix);
//			   	var relDupe = rec.line_items_to_line_items_fk_with_just_line_items_id.duplicateRecord();
				}
		
				
		rec.sales_id = rec.sales_id_backup
		rec.main_group = rec.main_group_backup_for_move
			
		globals.g_selected_line_action = 'Selected line'
		application.closeFormDialog();
	
		forms.line_items_complex_master.load_all_items_for_this_sale()

I’d be grateful for any help anyone can give…

:)

Bevil

Thunder:
application.output(line_items_to_line_items_fk_with_just_line_items_id.getSize())

for(var ix=1; ix <= line_items_to_line_items_fk_with_just_line_items_id.getSize(); ix++)
{
var relRec = rec.line_items_to_line_items_fk_with_just_line_items_id.getRecord(ix);

shouln’t ‘rec.’ be added to the upper 2 lines as well?

we use always this code:

var fs = arguments[0];
var relatedFsArray = arguments[1];

// Duplicate master record.
var dup = fs.getRecord(fs.duplicateRecord(false,false));
databaseManager.saveData();

for(var k=0;k<relatedFsArray.length;k++)
{
   var related = fs[relatedFsArray[k]];
   for(var i=1;i<=related.getSize();i++)
   {
       var relatedOriginal = related.getRecord(i);
       var relatedDub = dup[relatedFsArray[k]].getRecord(dup[relatedFsArray[k]].newRecord(false,false));
       databaseManager.copyMatchingColumns( relatedOriginal,  relatedDub);
   }
}
databaseManager.saveData();

use this as a global method, and pass the right foundset as first argument and an array of servoy relation(s) as a second argument
and this method will do the rest for you :-)

after this method, you can change what ever you want in the duplicated record, by using dup.mycolumn = newValue, etc…

Hi,

in Servoy 6 I get warnings in Harjo’s code for the duplicating records method.
How can I fix the issue of an undefined function getSize() and getRecord() as completion of the variable ‘related’?

dupl.png

Hi Thomas,

Servoy 6 is much more advanced in terms of code completion.
Therefore, you need to specify the types of variables when Servoy can not find out what it is.

first of all you have to specify the type of the arguments.
but you also have to specify the type of ‘related’, something like this:

/**
    	 * @type {JSFoundset<db:/udm/contacts>}
    	 */
       var related = fs[relatedFsArray[k]];

more on this subject can be found here:http://wiki.servoy.com/display/public/DOCS/Code+Writing+Features
and here: http://wiki.servoy.com/display/public/DOCS/Annotating+JavaScript+using+JSDoc

Hope this helps

Hi Marc,

the JSDoc syntax is still not my friend, but I’m learning and trying.
I got it work like:

for(var k = 0;k < relArr.length;k++){
	/**
	 * @type {JSFoundset<fs>}
	 * @param {Array} related
	 */
	var related = fs[relArr[k]];
	for(var i = 1;i <= related.getSize();i++){
		var relatedOriginal = related.getRecord(i);
		var relatedDup = dup[relArr[k]].getRecord(dup[relArr[k]].newRecord(false,false));
		databaseManager.copyMatchingColumns(relatedOriginal,relatedDup);
	}
}

/**

  • @type {JSFoundset}
  • @param {Array} related
    */

that inside a function doesn’t make any sense
First there is no @param thats only for functions
and second JSFoundset is not a right type

it just should be:

/**
  * @type {JSFoundset<db:/udm/contacts>}
  */
var related = fs[relatedFsArray[k]];

(with the db:/xxxx/yyy of the databsae if you know it or a relation name if you know the relation)

or just use:

/**
  * @type {JSFoundset}
  */
var related = fs[relatedFsArray[k]];

if you want to see it is a plain JSFoundset and you don’t need to explicitly type it to a table.

Ok, this is the complete global method:

/**
 * fs == master record(s) foundset
 * relArr == array of servoy relation(s) records
 * uid == uid_<table> (e.g. uid_order)
 * 
 * @properties={typeid:24,uuid:"E964EAF4-1018-485F-9DAC-37896CD170A4"}
 */
function gm_duplicateRec(fs,relArr,uid) {
	//duplicate master record
	var dup = fs.getRecord(fs.duplicateRecord(false,false));
	var pk = dup[uid];//uid duplicated record
	databaseManager.saveData();
	//duplicate related record(s)
	for(var k = 0;k < relArr.length;k++){
		var related = fs[relArr[k]];
		for(var i = 1;i <= related.getSize();i++){
			var relatedOriginal = related.getRecord(i);
			var relatedDup = dup[relArr[k]].getRecord(dup[relArr[k]].newRecord(false,false));
			databaseManager.copyMatchingColumns(relatedOriginal,relatedDup);
		}
	}
	databaseManager.saveData();
	return pk;//returns uid of duplicated record
}

How should I specify the JSDoc syntax correct?
In my (wrong) way the warnings was gone!? Do I try like your explanation Johan, I still have the warnings for ‘related.getSize()’ and ‘related.getRecord()’?

Sure you have the warnings you have not specify JSDoc for related

Try this code:

/**
* @param {JSFoundset} fs == master record(s) foundset  IF YOU NEED THIS FOUNDSET FIELDS YOU MUST DECLARE IT PROPERLY
* @param {Array} relArr == array of servoy relation(s) records
* @param {String} uid == uid_<table> (e.g. uid_order)
* 
* @properties={typeid:24,uuid:"E964EAF4-1018-485F-9DAC-37896CD170A4"}
*/
function gm_duplicateRec(fs,relArr,uid) {
   //duplicate master record
   var dup = fs.getRecord(fs.duplicateRecord(false,false));
   var pk = dup[uid];//uid duplicated record
   databaseManager.saveData();
   //duplicate related record(s)
   for(var k = 0;k < relArr.length;k++){
      /** @type {JSFoundset} */
      var related = fs[relArr[k]];
      for(var i = 1;i <= related.getSize();i++){
         var relatedOriginal = related.getRecord(i);
         var relatedDup = dup[relArr[k]].getRecord(dup[relArr[k]].newRecord(false,false));
         databaseManager.copyMatchingColumns(relatedOriginal,relatedDup);
      }
   }
   databaseManager.saveData();
   return pk;//returns uid of duplicated record
}

Thank you Juan Antonio Santana Medina,

you made me this things clearer… and your solution works fine!

I missunderstood Johan where I should set the specifications. :oops: