Duplicate Record and line Items

I have two tables called bids and Bidlineitems.

It’s basically a form like an invoice, I have a record with a portal of related line items.

What I want to do is duplicate the form, assigning it a new Bid Number, I can do this with no problem.
At the same time I want to duplicate the all the line items from the original form and assign them the new bid number.

I know this can be accomplished by finding and looping, etc. I was hoping that there may be a simple way of accomplishing this without allot of coding.

Thanks for any help,
Erich

i think you mean duplicating a record. Duplicating a form is a UI (designer/developer) thing.

Currently there is no other way then loop of the relatedfoundset of the original record..
But look at databasemanager.copyMatchingColumns() for some help

for example:

var dup = foundset.getRecord(foundset.duplicateRecord(false,false));
for(var i=1;i<=relatedfoundset.getSize();i++)
{
var relatedOriginal = relatedfoundset.getRecord(i);
var relatedDub = foundset.getRecord(dup.relatedfoundset.newRecord(false,false));
databasemanager.copyMatchingRecords(relatedOriginal,relatedDub)
}

look for more info in the tooltip/sample of copyMatching…
Maybe you have to tweak what it can overwrite and what not..

I tried to follow this, but it wasn’t working for me.
I used this method

var dup = foundset.getRecord(foundset.duplicateRecord(false,false));
//controller.saveData();
for(var i=1;i<=orders_to_line_items.getSize();i++)
{
var relatedOriginal = orders_to_line_items.getRecord(i);
var relatedDub = foundset.getRecord(dup.orders_to_line_items.newRecord(false,false));
databaseManager.copyMatchingColumns( relatedOriginal, relatedDub);
}

(you had put copyMatchingRecords instead of copyMatchingColumns)

The main order record is duplicated, but none of the line items (orders_to_line_items) are.
If I use debugger and have a number of records in my orders foundset, then when I look at ‘dup’ in the variable debugger tab it shows data from the 1st order, not the one I was on when I run the method, but after the method has run, it is the record I was on that is duplicated. Anyway, when the loop is run relatedOriginal is set OK, but relatedDub is null. I assume the ‘dup.orders_to_line_items.newRecord(false,false)’ is meant to generate a new line item (related record) for the duplicated order (dup).
The only issue might be that I am using a ‘db_identity’ for the ‘orders’ and ‘line_items’ PK’s as I need the back end database to create the id as I am also creating records via the back end. Would this be what is causing the problem? As you can see, I had tried doing a saveData, but that didn’t help.
Do you know what I am doing wrong and/or what I can do to make this work as I really need to be able to do this as quickly and easily as possible.
(I did see mention in another forum post about a new version of Servoy (2.5?) offering an extra option on duplicateRecord that would make it duplicate all related records as well. Is this going to be available soon?)

Well, I used a bit of a different work around that I will look at it and post it, pretty sloppy but it works great. There are a few other things working here, beacuse of other thigs I have going on in tthe form. But you get the idea. I would follow Johan’s advise though.

// Duplicate Record
controller.duplicateRecord();
original_bid_number = globals.Text1;
revision_number = k + 1;
// Clear Dates, show visible buttons and fields
creation_date = null;
completion_date = null;
approval_date = null;
approved_by_password = null;
creation_date = application.getTimeStamp();
elements.BtnAddLine.visible = true;
elements.BtnPrint.visible = false;
elements.BtnRevise.visible = false;
elements.BtnEdit.visible = false;
elements.BtnSubmit.visible = true;
elements.CreatedByID.enabled = true;
elements.AccountID.enabled = false;
elements.AccountID1.enabled = false;
elements.CreationDate.enabled = false;
elements.SalesRepID.enabled = true;
elements.EquipmentType.enabled = true;
elements.EquipmenCondition.enabled = true;
elements.Qty.enabled = true;
elements.Cost.enabled = true;
elements.X.enabled = true;
// Capture new Bid Number
globals.Text3 = bid_number
// Return to old Bid
controller.find();
bid_number = globals.Text2 ;
controller.search();
// This code Duplicates Line Items and assigns New Bid Number
globals.Number1 = bids_to_bidlineitems.getSize();
var x = 1;
while (x <= globals.Number1)
{
elements.LineItems.recordIndex = x
bids_to_bidlineitems.empty = x
elements.LineItems.duplicateRecord();
bids_to_bidlineitems.bid_number = globals.Text3;
x++;
}
// Return To New Bid
controller.find();
bid_number = globals.Text3;
controller.search() ;

Hi, I made this little method for duplicating a master and all his details records…and it seems to work ;)

var tab_detail = companies_to_contacts; // save all the  detail records in memory
var number_detail_rows = tab_detail.getSize(); // number of detail records
foundset.duplicateRecord(foundset.getSelectedIndex() ,true,true); //duplicates and selects new master record
for ( var i = 1 ; i <= number_detail_rows ; i++ ) // loop on previouly saved detail records
{ 
   tab_detail.duplicateRecord(i,false,true); // duplicate the detail
   tab_detail.company_id = companiesid; // assigns the new master primary key to the detail record
} 
controller.saveData();

Enrico,

that is very clean. I would like to I would like to accomplish this same concept using a portal. I was unsure about the saving to memory though.

var tab_detail = companies_to_contacts; // save all the detail records in memory

Thanks,
Erich

Enrico, you are amazing!
That is EXACTLY what I needed!!!
It works really well.
I needed to be able to reverse invoices (orders), so I am also negating the item quantity (and I need to change the prices as well…) in the for loop, and using an extra saveData after generating the order duplicate record works.
I am SO impressed with this forum. The speed and quality of responses is amazing.

Thanks,
Rafi.

Erich, the memory bit is just loading the related line items into a variable in memory to make access easier (and faster). Just try it.

I have used global varilables on a field to field to field basis. I am not sure how to load several fields into one varible yet, I assume it is basically like an array? I have not worked with arrays yet, I will be when I start the sql/html reporting tho.

automazione:
Hi, I made this little method for duplicating a master and all his details records…and it seems to work :wink:

var tab_detail = companies_to_contacts; // save all the  detail records in memory

var number_detail_rows = tab_detail.getSize(); // number of detail records
foundset.duplicateRecord(foundset.getSelectedIndex() ,true,true); //duplicates and selects new master record
for ( var i = 1 ; i <= number_detail_rows ; i++ ) // loop on previouly saved detail records
{
tab_detail.duplicateRecord(i,false,true); // duplicate the detail
tab_detail.company_id = companiesid; // assigns the new master primary key to the detail record
}
controller.saveData();

Hi Ricardo, GREAT Tip

but what if the related records are more than 200?
does it still work than?

automazione:
Hi, I made this little method for duplicating a master and all his details records…and it seems to work :wink:

var tab_detail = companies_to_contacts; // save all the  detail records in memory

var number_detail_rows = tab_detail.getSize(); // number of detail records
foundset.duplicateRecord(foundset.getSelectedIndex() ,true,true); //duplicates and selects new master record
for ( var i = 1 ; i <= number_detail_rows ; i++ ) // loop on previouly saved detail records
{
tab_detail.duplicateRecord(i,false,true); // duplicate the detail
tab_detail.company_id = companiesid; // assigns the new master primary key to the detail record
}
controller.saveData();

I’ve tested this method in a products table with related images. Everything except the larger images is duplicated. Adding controller.saveData() inside the loop helps but is unpredicatable. Sometimes the images save, sometimes they don’t. If it’s possible, I would love to see a feature that allows easy duplication of parent and all records from any number of relationships.

Something like:
duplicateRecordRel(products_to_colors, products_to_sizes, products_to_prod_prices)

I’ll also post in Feature Requests.

Looks like this feature is planned for version 2.5. Is there any way this might be added sooner?

See Post: duplicate records - Classic Servoy - Servoy Community

I can’t speak for the development team, but the EXCELLENT example that Enrico supplied above is awesome - and compact.

While a one-line function would be cool - there are 1,000 things that I would like to see before that feature. :D

Bob Cusick

see: http://forum.servoy.com/viewtopic.php?p=15696#15696

this would be pretty much the same as a call to duplicateFoundset itself. So using one global method is almost as easy.

Thanks Johan!

Write (or copy) 1 global and pass it 1 line. :o

I have a lot to learn.

Hi Ricardo, GREAT Tip

but what if the related records are more than 200?
does it still work than?

I agree that this is a truly great tip. With regard to the 200 limit, I just tried it with 333 related records and it only worked on the first 201 records (not sure why it was 201 and not 200). Is there a way to get beyond this limit?

Westy,

Try the global method Johan has posted at:
http://forum.servoy.com/viewtopic.php?p=15696#15696

for going beyond the 200 limit you can never do this:

var number_detail_rows = relation.getSize();
for ( var i = 1 ; i <= number_detail_rows ; i++ )

always do this:

for ( var i = 1 ; i <= relation.getSize() ; i++ )