Keeping Attachments in jobhead

I’ve fairly new to BPM and Epicor so I would appreciate a direction to be looking. The goal is to retain attachments, of a specific doc type, that get added to the job head in job entry.

When you change rev or part numbers on the job head the entire set of attachments get replaced by attachments related to the rev/part number, this includes the attachments that were added to the job head.

  1. We’ve gone ahead and enforced doc types when any attachment is being added.
  • Still working on this one but the idea is to prevent new attachments in the xfileref table with no doc type, using data directives and throwing an error when that happens.
  1. Is to use a method directive to pre-process file attachments when the job entry is updated. This would capture the documents I want to save and then push it off to the post-process to re-attach them to the job head.
  • I can’t seem to get the full list of attachments from the job head. I’ve tried using a query to fill a table, this only gets me 1 attachment number/xfilerefnum

  • Custom code, I can’t seem to access the xfileattch table and pull out the list of attachments.

  • traceing and dumping the jobheadattch table. In the preprocess it seems like the jobheadattch is empty. Even though in the trace I can see all the files.

If you have any help or direction I would appreciate it.

@IdleProgrammer Welcome. There are a lot of moving parts with this and you will need to hold all of the files contents in Callcontext variables or a ud temp table while they are being deleted and then put them back probably as new attachments. Epicor will remove the XfileAttch and XFileRef records and move the actual file to the deleted subdirectory.

References:

/* Check if jobHead has attachment */

callContextBpmData.Character01 = string.Empty; // you should also clear this when the put back is completed.

Ice.Diagnostics.Log.WriteEntry("in check Job has attachment");

foreach (var jhRow in ds.JobHead.Where(w => w.Unchanged()))
{
    foreach (var atchRow in Db.XFileAttch.Where(x => x.Company == Session.CompanyID && x.RelatedToFile == "JobHead" && x.Key1 == jhRow.JobNum))
    {
        if(string.IsNullOrEmpty(callContextBpmData.Character01))
        {
            callContextBpmData.Character01 = atchRow.XFileRefNum.ToString();
        }
        else
        {
            callContextBpmData.Character01 = callContextBpmData.Character01 + "~" + atchRow.XFileRefNum.ToString();
        }
    }
    
    
    Ice.Diagnostics.Log.WriteEntry($"Job {jhRow.JobNum} Part {jhRow.PartNum} has these attachments {callContextBpmData.Character01}");
}

1 Like

This is exactly the direction I needed. Here are a few changes I made that is specific to my solution.

This is in the pre-processing collecting the specific attachments that I know get blown away. REC doctype are the documents we want to keep between revisions. I added the second foreach to pull the exact filenames so I can resave them.

/* Check if jobHead has attachment */

// you should also clear this when the put back is completed.
callContextBpmData.Character01 = string.Empty; // File attachment 
callContextBpmData.Character02 = string.Empty; // File Path.
callContextBpmData.Character03 = string.Empty; // Filename.

Ice.Diagnostics.Log.WriteEntry("in check Job has attachment");

foreach (var jhRow in ds.JobHead.Where(w => w.RowMod == "U"))
{
    foreach (var atchRow in Db.XFileAttch.Where(x => x.Company == Session.CompanyID && x.RelatedToFile == "JobHead" && x.Key1 == jhRow.JobNum))
    {
      foreach(var docType in Db.XFileRef.Where(x=> x.Company == Session.CompanyID && x.DocTypeID == "REC" && x.XFileRefNum == atchRow.XFileRefNum))      
      {        
          if(string.IsNullOrEmpty(callContextBpmData.Character01))
            {
            callContextBpmData.Character01 = atchRow.XFileRefNum.ToString();
            callContextBpmData.Character02 = docType.XFileName.ToString();
            callContextBpmData.Character03 = docType.XFileDesc.ToString();
            }
          else
            {
              callContextBpmData.Character01 = callContextBpmData.Character01 + "~" + atchRow.XFileRefNum.ToString();
              callContextBpmData.Character02 = callContextBpmData.Character02 + "~" + docType.XFileName.ToString();
              callContextBpmData.Character03 = callContextBpmData.Character03 + "~" + docType.XFileDesc.ToString();
            }       
      }        
    }   
    
    Ice.Diagnostics.Log.WriteEntry($"Job {jhRow.JobNum} Part {jhRow.PartNum} has these attachments {callContextBpmData.Character01}");
    Ice.Diagnostics.Log.WriteEntry($"Job {jhRow.JobNum} Part {jhRow.PartNum} has these attachments {callContextBpmData.Character02}");
    Ice.Diagnostics.Log.WriteEntry($"Job {jhRow.JobNum} Part {jhRow.PartNum} has these attachments {callContextBpmData.Character03}");
}

In the Post-processing

Func<string, string, string, Guid, string, string, int> AttachFile = (iPath, iFilename, DocType, iRelatedGuid, iRelatedTable, iKey1) =>
{
  int outAttchNum = 0;
  using (var txscope = IceDataContext.CreateDefaultTransactionScope())
  {
    // Create the system file reference
    XFileRef xref = new XFileRef();
    Db.XFileRef.Insert(xref);
    xref.Company = callContextClient.CurrentCompany;
    xref.XFileName = iPath;
    xref.XFileDesc = iFilename;
    xref.DocTypeID = DocType;
    Db.Validate(xref);
      
    // Attach the file to the record
    XFileAttch xfile = new XFileAttch();
    Db.XFileAttch.Insert(xfile);
    xfile.Company = callContextClient.CurrentCompany;
    xfile.RelatedToSchemaName = "Erp";
    xfile.RelatedToFile = iRelatedTable;
    xfile.Key1 = iKey1.ToString();
    xfile.ForeignSysRowID = iRelatedGuid;
    xfile.XFileRefNum = xref.XFileRefNum;
    Db.Validate(xfile);
      
    // Store the new attachment number for a rainy day
    outAttchNum = xfile.AttachNum;    
    txscope.Complete();
  }
    
  return outAttchNum;
};

callContextBpmData.Character10 = string.Empty;

if(callContextBpmData.Character01 != null)
{
 var fileRefNum = callContextBpmData.Character01.ToString().Split('~');
 var filePath = callContextBpmData.Character02.ToString().Split('~');
 var fileDesc = callContextBpmData.Character03.ToString().Split('~');
 var jobNum = ds.JobHead[0].JobNum;
 var sys = ds.JobHead[0].SysRowID;
 for(int i = 0; i <= fileRefNum.Count() -1; i++)
 {
  int attchnum = AttachFile(filePath[i],fileDesc[i],"REC", sys, "JobHead", jobNum);
 }
 callContextBpmData.Character01 = string.Empty;
 callContextBpmData.Character02 = string.Empty;
 callContextBpmData.Character03 = string.Empty;
 }
 

We split the context and for loop through adding any records back.

Thanks a lot