Customized report naming?

Edit: Got it down to 1 BPM !

You can remove the previous ones, and control it all from one BPM.
Haven’t tested in Kinetic yet, it’s possible it behaves differently.

Post-Processing BPM on Ice.BO.ReportMonitor.Update
/***************************************************************************************
Post-Processing BPM on Ice.BO.ReportMonitor.Update 
Author: Kevin Lincecum
Purpose: Renames files previewed from the System Monitor to a custom format based on
  criteria from the SysTaskParam table.
***************************************************************************************/

try
{
    //Isolate rows for processing based on these criteria
    var rowsForProcessing = ds.SysRptLst.Where(x =>
        x.PrintDriver == "SSRS" &&
        x.LastAction == "Process");

    //Loop through each selected row 
    foreach(SysRptLstRow sysRptLstRow in rowsForProcessing)
    {
        //Pull out for convenience / readability
        long sysTaskNum = sysRptLstRow.SysTaskNum;
        
        //Get all the Parameters for this report 
        List<SysTaskParam> sysTaskParams = Db.SysTaskParam.Where(stp => stp.SysTaskNum == sysTaskNum).ToList();
        
        //Get the Report ID
        string reportID = sysTaskParams.Where(stp => stp.ParamName == "ReportID").FirstOrDefault().ParamCharacter;
        
        //Get the Report Parameter DataSetID
        //string reportParameterDataSetId = sysTaskParams.Where(stp => stp.ParamName == "ReportParameterDataSetId").FirstOrDefault().ParamCharacter;
        
        //Checks based off of the "ReportID", so you could handle different kinds of reports etc.
        if(reportID == "OrderAck")
        //Or you could check the "ReportParameterDataSetId"
        //if(reportParameterDataSetId == "SalesOrderAck")
        {
            //Get the Report Style so you can check against it.. 
            int reportStyleNum = sysTaskParams.Where(stp => stp.ParamName == "ReportStyleNum").FirstOrDefault().ParamInteger;
            
            //Get the Order Number so we can pull further data..
            int orderNum       = sysTaskParams.Where(stp => stp.ParamName == "OrderNum").FirstOrDefault().ParamInteger;
            
            //I wanted the Customer ID, but we need to get the Customer Number first...
            int custNum = Db.OrderHed.Where(o => o.Company == Session.CompanyID && o.OrderNum == orderNum).FirstOrDefault().CustNum;
            
            //Get the Customer ID
            string custID = Db.Customer.Where(c => c.Company == Session.CompanyID && c.CustNum == custNum).FirstOrDefault().CustID;
            
            //Do different types of actions based on which Report Style is passed, use your imagination.
            switch(reportStyleNum)
            {
                case 2:
                    sysRptLstRow.RptDescription = $"Blistering_Donkey-{orderNum.ToString()}_CustID-{custID}";
                    break;
                    
                case 1001:
                    sysRptLstRow.RptDescription = $"Voluptuous_Mole-Rat-{orderNum.ToString()}_CustID-{custID}";
                    break;
                    
                default:
                    sysRptLstRow.RptDescription = $"I_LIKE_TURTLES";
                    break;
            }
            
            //Below is what is appended to the end of the filename.
            //Making the best of what you can do...
            
            //This will be "0";
            sysRptLstRow.SetSysTaskNumUnspecified();
            
            //Or set it to Ticks for something useful & unique 
            //sysRptLstRow.SysTaskNum = DateTime.Now.Ticks;            
            
            //Or set it to OrderNum, might be useful
            //sysRptLstRow.SysTaskNum = orderNum;
        }
    }
}
catch (Exception ex)
{
    //Do whatever you do with errors...
}

Old 2 BPM Post

Sure: 2 BPMs for a 1, 2 punch:

Fight Boxing GIF by We love MMA

Pre-Processing BPM on Erp.Rpt.SalesOrderAck.SubmitToAgent
/***************************************************************************************
Pre-Processing BPM on Erp.Rpt.SalesOrderAck.SubmitToAgent
Author: Kevin Lincecum
Purpose: Example of passing some data in the TaskNote field of a report parameter row
to be acted on in another BPM down the line.
In this case: Ice.BO.ReportMonitor.GetRowsKeepIdleTimeWithBallonInfo
***************************************************************************************/

try
{
    //Isolate our row just for readability
    SalesOrderAckParamRow salesOrderAckParamRow = ds.SalesOrderAckParam.FirstOrDefault(); 
    
    //Only process if we are previewing
    if(salesOrderAckParamRow.AutoAction == "SSRSPREVIEW")
    {
        //Pull these fields out to pass in the TaskNote field. We can pull these out in the RptNote field
        //in Ice.BO.ReportMonitor.GetRowsKeepIdleTimeWithBallonInfo
        string orderNum = salesOrderAckParamRow.OrderNum.ToString();
        string reportStyle = salesOrderAckParamRow.ReportStyleNum.ToString();
        
        //Populate TaskNote field
        //RptNote/TaskNote is small, this is about all that would fit. It should be enough.
        salesOrderAckParamRow.TaskNote = $"SO.Rename>{reportStyle}-{orderNum}";
    }  
}
catch (Exception ex)
{
    //Do whatever you do with errors...
}
Post-Processing BPM on Ice.BO.ReportMonitor.GetRowsKeepIdleTimeWithBallonInfo
/***************************************************************************************
Post-Processing BPM on Ice.BO.ReportMonitor.GetRowsKeepIdleTimeWithBallonInfo 
Author: Kevin Lincecum
Purpose: Example of pulling some data from the RptNote field of a report parameter row
passed in the TaskNote field of a SubmitToAgent call.
In this case: Erp.Rpt.SalesOrderAck.SubmitToAgent 
***************************************************************************************/

try
{
    //Isolate our rows that meet these criteria
    var salesOrderRenamingRows = result.SysRptLst.Where(x =>
        x.PrintDriver == "SSRS" &&
        x.AutoAction == "PREVIEW" &&
        x.LastAction == "SSRSREADY" &&
        x.RptNote.StartsWith("SO.Rename>"));
  
    //Loop through the selected rows and process them
    foreach(SysRptLstRow sysReportLstRow in salesOrderRenamingRows)
    {
        //Split on '>' and take the second part for parsing
        string   renamingParamsString = sysReportLstRow.RptNote.Split('>')[1];
        
        //Split on '-' and fill an array with our params.
        string[] renamingParamsArray  = renamingParamsString.Split('-'); 
        
        //RptNote/TaskNote is small, this is about all that would fit
        int reportStyle = Convert.ToInt32(renamingParamsArray[0]);
        int orderNum    = Convert.ToInt32(renamingParamsArray[1]);
        
        //I wanted the Customer ID, but we need to get the Customer Number first...
        int custNum = Db.OrderHed.Where(o => o.Company == Session.CompanyID && o.OrderNum == orderNum).FirstOrDefault().CustNum;
        
        //Get the Customer ID
        string custID = Db.Customer.Where(c => c.Company == Session.CompanyID && c.CustNum == custNum).FirstOrDefault().CustID;
        
        //Do different types of actions based on which Report Style is passed, use your imagination.
        switch(reportStyle)
        {
            case 2:
                sysReportLstRow.RptDescription = $"Blistering_Donkey-{orderNum.ToString()}_CustID-{custID}__ST";
                break;
                
            case 1001:
                sysReportLstRow.RptDescription = $"Voluptuous_Mole-Rat-{orderNum.ToString()}_CustID-{custID}__ST";
                break;
                
            default:
                sysReportLstRow.RptDescription = $"I_LIKE_TURTLES";
                break;
        }
    }
}
catch (Exception ex)
{
    //Do whatever you do with errors...
}

Have fun.
:tada:

4 Likes

That worked. Thanks. I could not find those methods in 10.2.300, but it worked fine in Kinetic 2023. That’s fine we are in the process of moving to Kinetic.

2 Likes

I ran a few test and noticed the Task Id is appended to the end. Is this something the system is doing and we can’t get around?

1 Like

Yes. In my Example I put ST in there to signify what it was but didn’t explain it.

There is a hack for it that seems to work, you can replace the systasknum with anything numeric, and the update for the row must not be looking for that, so it still works properly.

I can show that if you’d like.

Be aware, if the filename exists already from the way you structure it, the system will also append _# on to it so it can write to the temp folder on your machine.

1 Like

Please, if you don’t mind? Thanks

1 Like

No problem. It’ll be this evening sometime.
I came home for lunch and am gonna screw off for a bit. :rofl:

1 Like

Got it down to 1 BPM !

You can remove the previous ones, and control it all from one BPM.
Haven’t tested in Kinetic yet, it’s possible it behaves differently.

Post-Processing BPM on Ice.BO.ReportMonitor.Update

/***************************************************************************************
Post-Processing BPM on Ice.BO.ReportMonitor.Update 
Author: Kevin Lincecum
Purpose: Renames files previewed from the System Monitor to a custom format based on
  criteria from the SysTaskParam table.
***************************************************************************************/

try
{
    //Isolate rows for processing based on these criteria
    var rowsForProcessing = ds.SysRptLst.Where(x =>
        x.PrintDriver == "SSRS" &&
        x.LastAction == "Process");

    //Loop through each selected row 
    foreach(SysRptLstRow sysRptLstRow in rowsForProcessing)
    {
        //Pull out for convenience / readability
        long sysTaskNum = sysRptLstRow.SysTaskNum;
        
        //Get all the Parameters for this report 
        List<SysTaskParam> sysTaskParams = Db.SysTaskParam.Where(stp => stp.SysTaskNum == sysTaskNum).ToList();
        
        //Get the Report ID
        string reportID = sysTaskParams.Where(stp => stp.ParamName == "ReportID").FirstOrDefault().ParamCharacter;
        
        //Get the Report Parameter DataSetID
        //string reportParameterDataSetId = sysTaskParams.Where(stp => stp.ParamName == "ReportParameterDataSetId").FirstOrDefault().ParamCharacter;
        
        //Checks based off of the "ReportID", so you could handle different kinds of reports etc.
        if(reportID == "OrderAck")
        //Or you could check the "ReportParameterDataSetId"
        //if(reportParameterDataSetId == "SalesOrderAck")
        {
            //Get the Report Style so you can check against it.. 
            int reportStyleNum = sysTaskParams.Where(stp => stp.ParamName == "ReportStyleNum").FirstOrDefault().ParamInteger;
            
            //Get the Order Number so we can pull further data..
            int orderNum       = sysTaskParams.Where(stp => stp.ParamName == "OrderNum").FirstOrDefault().ParamInteger;
            
            //I wanted the Customer ID, but we need to get the Customer Number first...
            int custNum = Db.OrderHed.Where(o => o.Company == Session.CompanyID && o.OrderNum == orderNum).FirstOrDefault().CustNum;
            
            //Get the Customer ID
            string custID = Db.Customer.Where(c => c.Company == Session.CompanyID && c.CustNum == custNum).FirstOrDefault().CustID;
            
            //Do different types of actions based on which Report Style is passed, use your imagination.
            switch(reportStyleNum)
            {
                case 2:
                    sysRptLstRow.RptDescription = $"Blistering_Donkey-{orderNum.ToString()}_CustID-{custID}";
                    break;
                    
                case 1001:
                    sysRptLstRow.RptDescription = $"Voluptuous_Mole-Rat-{orderNum.ToString()}_CustID-{custID}";
                    break;
                    
                default:
                    sysRptLstRow.RptDescription = $"I_LIKE_TURTLES";
                    break;
            }
            
            //Below is what is appended to the end of the filename.
            //Making the best of what you can do...
            
            //This will be "0";
            sysRptLstRow.SetSysTaskNumUnspecified();
            
            //Or set it to Ticks for something useful & unique 
            //sysRptLstRow.SysTaskNum = DateTime.Now.Ticks;            
            
            //Or set it to OrderNum, might be useful
            //sysRptLstRow.SysTaskNum = orderNum;
        }
    }
}
catch (Exception ex)
{
    //Do whatever you do with errors...
}
8 Likes

Thanks for your time. This works great.

I had a feeling there was a way. I was tinkering around with the ReportMonitor BO and when I tried to change the SysTaskNum or something similar it basically crashed my test environment. I had to go SQL direct to fix it so that it would let me do anything lol. Then I thought, I’ll leave it to the experts.

Is there a logical reason this would not be working for the JobTrav or PackSlip reports? I successfully used this solution for Orders, AR Invoices, and Quotes, but Job Travelers and Packing Slips continue to use the default PDF exported file name.

I cleared everything else out to isolate just the Job Traveler in the code. Can anyone see why this wouldn’t work?

try
{
    //Isolate rows for processing based on these criteria
    var rowsForProcessing = ds.SysRptLst.Where(x =>
        x.PrintDriver == "SSRS" &&
        x.LastAction == "Process");

    //Loop through each selected row 
    foreach(SysRptLstRow sysRptLstRow in rowsForProcessing)
    {
        //Pull out for convenience / readability
        long sysTaskNum = sysRptLstRow.SysTaskNum;
        
        //Get all the Parameters for this report 
        List<SysTaskParam> sysTaskParams = Db.SysTaskParam.Where(stp => stp.SysTaskNum == sysTaskNum).ToList();
        
        //Get the Report ID
        string reportID = sysTaskParams.Where(stp => stp.ParamName == "ReportID").FirstOrDefault().ParamCharacter;
        
        //Get the Report Parameter DataSetID
        //string reportParameterDataSetId = sysTaskParams.Where(stp => stp.ParamName == "ReportParameterDataSetId").FirstOrDefault().ParamCharacter;
        
        //Checks based off of the "ReportID", so you could handle different kinds of reports etc.
        if(reportID == "JobTrav")
        //Or you could check the "ReportParameterDataSetId"
        //if(reportParameterDataSetId == "JobTrav")
        {
            //Get the Report Style so you can check against it.. 
            int reportStyleNum = sysTaskParams.Where(stp => stp.ParamName == "ReportStyleNum").FirstOrDefault().ParamInteger;
            
            //Get the Job Number so we can pull further data..
            int jobNum = sysTaskParams.Where(stp => stp.ParamName == "JobNum").FirstOrDefault().ParamInteger;
            
            //Do different types of actions based on which Report Style is passed, use your imagination.
            switch(reportStyleNum)
            {
                case 2:
                    sysRptLstRow.RptDescription = $"Job {jobNum.ToString()}";
                    break;
                    
                case 1001:
                    sysRptLstRow.RptDescription = $"Job {jobNum.ToString()}";
                    break;
                    
                case 1003:
                    sysRptLstRow.RptDescription = $"Job {jobNum.ToString()}";
                    break;
                
                case 1004:
                    sysRptLstRow.RptDescription = $"Job {jobNum.ToString()}";
                    break;
                
                default:
                    sysRptLstRow.RptDescription = $"Job {jobNum.ToString()}";
                    break;
            }
            
            //Below is what is appended to the end of the filename.
            //Making the best of what you can do...
            
            //This will be "0";
            sysRptLstRow.SetSysTaskNumUnspecified();
            
            //Or set it to Ticks for something useful & unique 
            //sysRptLstRow.SysTaskNum = DateTime.Now.Ticks;            
         
        }
    }
}
catch (Exception ex)
{
    //Do whatever you do with errors...
}

Man, ya’ll gotta stop asking me stuff about stuff I posted over a week or so ago.
I just can’t keep up. :rofl:

Yes, but it’s not the BO, it’s got to be an error in your code somewhere.
To verify, I just did a very quick and dirty BO:

  foreach(SysRptLstRow r in ds.SysRptLst)
  {
      r.RptDescription = $"Test_{DateTime.Now.ToString("yyyyMMdd_ss_fff")}";
  }

And it renamed whatever I threw at it, including the job traveler.

I’d try sending any errors somewhere you can read them, and maybe try to send the finished file name somewhere too. Something is off.

1 Like

Of course you were right about my code being the issue, but I think the reason might be helpful for other people.

While the ICE.SysTaskParam table uses the ParamName ‘InvoiceNum’ for the InvoiceNum, ‘OrderNum’ for the OrderNum, ‘QuoteNum’ for the QuoteNum, etc. . . it uses ‘Jobs’ for the JobNum :expressionless:.

Additionally, JobNum is actually a string (maybe that’s custom for us though) instead of an int, so the problematic line of code that previously matched the syntax for other reports looked like this:

int jobNum = sysTaskParams.Where(stp => stp.ParamName == "JobNum").FirstOrDefault().ParamInteger;

. . . but it actually had to be this for it to work:

string jobNum = sysTaskParams.Where(stp => stp.ParamName == "Jobs").FirstOrDefault().ParamCharacter;

Thank you again for all your help. I hope some other newbie like me stumbles across this thread and wastes less time than I did!

1 Like

We are ALL “Newbie”.

Twd GIF by The Walking Dead

Cheers @klincecum! Works well in Client.

Browser (Kinetic) opens the .pdf directly and then if you go to save, it wants to rename the files as “Download”. So, unfortunately, it doesn’t seem like the new naming carries through that portion. Not sure if/where that could be intercepted.

No biggie. Just thought I’d chime in as I was successful in Client and was able to test the Browser as well.

I think I solved that one or looked at it at least at one point. I’ll go see if I have any notes or if we are SOL.

@dcamlin Looks like we may be SOL. At least for now.

Hi folks,

I am resurrecting this thread as I used Kevin’s code recently to rename some of our reports. I have a couple of questions regarding this:

  1. Is there a way to remove the underscore that gets added between whatever I declare in my sysRptLstRow.RptDescription and sysRptLstRow.SysTaskNum variables
  2. I noticed that if download the same document several times then a version number gets added at the end of the my file’s name. Is there a way to prevent this ?
  3. Is there a way to leave SysTaskNum blank at the end of the file name( I know its a long variable so probably not but a lot of people in here are much smarter than I am so maybe somebody figured something out ).

Thank you for your help,

  1. No
  2. No
  3. No, null will be “0”

That being said, if it is coming from the system monitor, there might be something you could do in a customization on that, but if it’s coming from the edge agent, you’re sol.

1 Like

thank you for the answer Kevin