- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
‎10-05-2016 05:05 AM
Hello all,
On our Purchase Order table(proc_po), we will be creating PO's for service provisions (not physical products), and these will be charged on a per month basis.
We have been asked to create PO Line Items (on the table 'proc_po_line_items') based automatically on the start and end time fields of the PO.
For example, if we save a new PO with the dates 01-01-2017 to 31-12-2017, we need 12 Purchase Order Line Items to be created automatically, one for each month with the correct dates showing on Start and End date fields on the line items table. (i.e. 01-01-2017 > 31-01-2017 on the first line item, 01-02-2017 > 28-02-2017 on the second etc...)
To complicate thing a little, the start date may not be from 1st of the selected month. for example, if we have the dates 12-01-2017 - 11-01-2018 then the dates on the Line Item records would need to be 12-01-2017 > 11-02-2017 on the first line item, 12-02-2017 > 11-03-2017 on the second etc... .
Can anyone point me in the right direction for creating a business rule that would achieve this?
Thanks very much,
Charles
Solved! Go to Solution.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
‎10-06-2016 06:15 AM
When you say no other business rules operate on the record, what do you mean, are they business rule on the proc_po table or on the proc_po_item table? The script I proposed was pretty simple in the sense that it only cared about the relation and the start and end date, so it did not populate other fields even if mandatory (default values should however be respected). I don't know if you added the value to these fields inside the script, but you should probably look to do so and check the conditions of the business rules running. It's kind of hard to troubleshoot without knowing what you have.
As for your frequency requirement, you could change it to this:
(function executeRule(current, previous /*null when async*/) {
var startGDT = new GlideDateTime(current.u_start);
var finalEndGDT = new GlideDateTime(current.u_end);
var frequency = current.u_frequency;
while(startGDT.compareTo(finalEndGDT) <= 0){ //Final end date is after start date
var line = new GlideRecord('proc_po_item');
line.initialize();
line.purchase_order = current.getUniqueValue();
line.u_start = startGDT;
var endGDT = new GlideDateTime(startGDT);
if(frequency == 'month'){
endGDT.addMonthsUTC(1);
}
else if(frequency == 'year'){
endGDT.addYearsUTC(1);
}
if(endGDT.compareTo(startGDT) != 0){
//PO line of more than one day
endGDT.addDaysUTC(-1);
}
if(finalEndGDT.compareTo(endGDT) == -1){
//End date is after final end date
//Should use the final end date
line.u_end = finalEndGDT;
}
else{
line.u_end = endGDT;
}
line.insert();
if(frequency == 'day'){
startGDT.addDaysUTC(1);
}
else if(frequency == 'month'){
startGDT.addMonthsUTC(1);
}
else if(frequency == 'year'){
startGDT.addYearsUTC(1);
}
}
})(current, previous);
I was not sure how you wanted to deal with daily, I assumed the PO had identical start date and end date.
I also modified the script to accept PO Line of a single day as before if you had start date 2016-01-01 and end date 2016-02-01, you would get a single PO of 2016-01-01 to 2016-01-31. Now you also get the PO for 2016-02-01 to 2016-01-01.
If you eventually have the need for weeks you could follow the pattern in the script and use the function addWeeksUTC(int). Also if you eventually have the need for a different occurrence lets say every 2 years then you could add a new field and that field could be used instead of the "1" in the addXXXXUTC(int) function.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
‎01-17-2017 06:53 AM
Hello Laurent,
Thanks again for your help with the above request - I wonder if I could pick your brains about a new requirement along the same lines?
There is a new request to create the Line Items not on the basis of day/month & year schedule, but on a month basis based only on the start & end dates.
For example, if a record starts on 1st Jan and runs to 15th April, we need to create four line items - one for Jan, Feb, March and April. Basically, if any of the time frame crosses over into another month, then we need a line item.
Any ideas?
Thanks so much,
Charles
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
‎01-17-2017 01:40 PM
Hi Charles,
Will these line items, representing the different months, be represented with Start: first day of the month, End: last day of the month? Or will it be a new field (string or choice field) that will have the month this line is for stored inside of it?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
‎01-17-2017 02:08 PM
Hi Laurent - thanks for getting back to me.
Yes so we will be updating the existing line.u_start_day and line.u_end_day fields with the start of the month (01) and end of the month (28,30,31), for all those months that are complete. We will also be looking to create a new string field with the appropriate name of the month, if this is possible.
So for example, if we save a new PO with the dates 15-01-2017 to 25-03-2017, we need 3 Purchase Order Line Items to be created automatically, one for each calendar month with the correct dates showing on Start and End date fields on the line items table. (i.e. 15-01-2017 > 31-01-2017 on the first line item (January), 01-02-2017 > 28-02-2017 on the second (February) and 01-03-2017 > 25-03-17 on the last (March)).
I've reduced your code to that shown below, but these still create the records with the dates 15-01-2017 > 14-02-2017, 15-02-2017>14-03-2017, 15-03-2017>25-03-2017 - i.e. the full month from the start date, not split into the actual calendar months.
function createLinesServer(){
var startGDT = new GlideDateTime(current.u_start_date);
var finalEndGDT = new GlideDateTime(current.u_end_date);
while(startGDT.compareTo(finalEndGDT) <= 0){ //Final end date is after start date
var line = new GlideRecord('proc_po_item');
line.initialize();
var endGDT = new GlideDateTime(startGDT);
endGDT.addMonthsUTC(1);
if(finalEndGDT.compareTo(endGDT) == -1){
//End date is after final end date
//Should use the final end date
line.u_end_day = finalEndGDT;
}
else{
line.u_end_day = endGDT;
}
line.insert();
startGDT.addMonthsUTC(1);
}
action.setRedirectURL(current);
current.update();
}
Thanks so much again for all your help
Charles
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
‎01-17-2017 04:30 PM
Hi Charles,
Here you go, I've fully adapted the code for it to generate what you asked. If you want to offer both maybe add a parameter in a field or create a second UI Action.
I've added a choice field on the proc_po_item table to store the month (integer field with choices with the value of the month number and the name of the month as a label, script only work with month number so it is easier that way). The advantage of an integer field is that when sorting by the column, the order will be the order of the month instead of alphabetical order. For this example I named the field u_month.
function createLinesServer(){
var startGDT = new GlideDateTime(current.u_start);
var finalEndGDT = new GlideDateTime(current.u_end);
while(startGDT.compareTo(finalEndGDT) <= 0){ //Final end date is after start date
var line = new GlideRecord('proc_po_item');
line.initialize();
line.purchase_order = current.getUniqueValue();
line.u_month = startGDT.getMonthUTC();
startGDT.setDayOfMonthUTC(1);
line.u_start = startGDT;
var endGDT = new GlideDateTime(startGDT);
endGDT.setDayOfMonthUTC(endGDT.getDaysInMonthUTC());
line.u_end = endGDT;
line.insert();
startGDT.addMonthsUTC(1);
}
action.setRedirectURL(current);
current.update();
}
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
‎01-18-2017 02:24 AM
Hi Laurent - so easy when you know how! Thank you again so much - this is superb.
Charles