public void UpdateFolderDescriptions(Screen screen)
        {
            var          tokenHandler = PXGraph.CreateInstance <UserTokenHandler>();
            EntityHelper entityHelper = new EntityHelper(this);

            BoxFolderCache screenFolderInfo = FoldersByScreen.Select(screen.ScreenID);

            foreach (BoxFolderCache boxFolderCache in FoldersByParentFolderID.Select(screenFolderInfo.FolderID))
            {
                object row = entityHelper.GetEntityRow(boxFolderCache.RefNoteID, true);
                if (row != null)
                {
                    var description = GetFolderDescriptionForEntityRow(row);
                    try
                    {
                        BoxUtils.UpdateFolderDescription(tokenHandler, boxFolderCache.FolderID, description).Wait();
                    }
                    catch (AggregateException ae)
                    {
                        ScreenUtils.HandleAggregateException(ae, HttpStatusCode.NotFound, (exception) =>
                        {
                            // Folder no longer exist on Box - it may have been deleted on purpose by the user
                            screenFolderInfo = FoldersByScreen.Delete(boxFolderCache);
                        });
                    }
                }
            }

            Actions.PressSave();
        }
        public BoxUtils.FileFolderInfo GetMiscellaneousFolder()
        {
            var bfc = (BoxFolderCache)FoldersByScreen.Select(MiscellaneousFolderScreenId);

            if (bfc == null)
            {
                throw new PXException(Messages.MiscFolderNotFoundRunSynchAgain);
            }
            else
            {
                try
                {
                    // Folder was found in BoxFolderCache, retrieve it by ID
                    var tokenHandler = PXGraph.CreateInstance <UserTokenHandler>();
                    BoxUtils.FileFolderInfo folderInfo = BoxUtils.GetFolderInfo(tokenHandler, bfc.FolderID).Result;
                    return(folderInfo);
                }
                catch (AggregateException ae)
                {
                    ScreenUtils.HandleAggregateException(ae, HttpStatusCode.NotFound, (exception) =>
                    {
                        using (new PXConnectionScope())
                        {
                            // Delete entry from BoxFolderCache so that it gets created again.
                            FoldersByScreen.Delete(bfc);
                            Actions.PressSave();
                        }

                        throw new PXException(Messages.MiscFolderNotFoundRunSynchAgain, bfc.FolderID, exception);
                    });

                    return(null);
                }
            }
        }
        protected virtual void moveFolders()
        {
            var fileHandlerGraph = PXGraph.CreateInstance <FileHandler>();
            var tokenHandler     = PXGraph.CreateInstance <UserTokenHandler>();

            PXLongOperation.StartOperation(this, () =>
            {
                EntityHelper entityHelper = new EntityHelper(this);

                var screenFolderCache = (BoxFolderCache)fileHandlerGraph.FoldersByScreen.Select(Screens.Current.ScreenID);

                var list = new List <BoxUtils.FileFolderInfo>();
                //For each subfolders of a screen found on box server
                try
                {
                    list = BoxUtils.GetFolderList(tokenHandler, screenFolderCache.FolderID, (int)BoxUtils.RecursiveDepth.FirstSubLevel).Result;
                }
                catch (AggregateException ae)
                {
                    ScreenUtils.HandleAggregateException(ae, HttpStatusCode.NotFound, (exception) => {
                        ScreenUtils.TraceAndThrowException(Messages.BoxFolderNotFoundRunSynchAgain, screenFolderCache.FolderID);
                    });
                }

                foreach (var folder in list)
                {
                    //If folder has a RefNoteID, it contains files and might need to be moved
                    BoxFolderCache bfc = (BoxFolderCache)fileHandlerGraph.FoldersByFolderID.Select(folder.ID);
                    if (bfc != null && bfc.RefNoteID.HasValue)
                    {
                        string presumedParentFolderID = screenFolderCache.FolderID;
                        if (fileHandlerGraph.FieldsGroupingByScreenID.Select(Screens.Current.ScreenID).Any())
                        {
                            presumedParentFolderID = fileHandlerGraph.GetOrCreateSublevelFolder(tokenHandler, Screens.Current.ScreenID, screenFolderCache.FolderID, bfc.RefNoteID.Value, false);
                        }

                        //if nested under the wrong folder
                        if (presumedParentFolderID != null && folder.ParentFolderID != presumedParentFolderID)
                        {
                            try
                            {
                                BoxUtils.MoveFolder(tokenHandler, folder.ID, presumedParentFolderID).Wait();
                                bfc.ParentFolderID = presumedParentFolderID;
                                fileHandlerGraph.FoldersByFolderID.Update(bfc);
                                fileHandlerGraph.Actions.PressSave();
                            }
                            catch (AggregateException ae)
                            {
                                ScreenUtils.HandleAggregateException(ae, HttpStatusCode.Conflict, (exception) => {
                                    //Skip this folder if a name conflict happens
                                });

                                continue;
                            }
                        }
                    }
                }
            });
        }
        public void SynchronizeScreen(Screen screen, BoxUtils.FileFolderInfo rootFolder, bool forceSync)
        {
            string folderName = string.Format("{0} ({1})", (object)BoxUtils.CleanFileOrFolderName(screen.Name), (object)screen.ScreenID);

            BoxFolderCache screenFolderInfo = FoldersByScreen.Select(screen.ScreenID);

            BoxUtils.FileFolderInfo folderInfo = null;
            var tokenHandler = PXGraph.CreateInstance <UserTokenHandler>();

            if (screenFolderInfo != null)
            {
                try
                {
                    folderInfo = BoxUtils.GetFolderInfo(tokenHandler, screenFolderInfo.FolderID).Result;
                }
                catch (AggregateException ae)
                {
                    ScreenUtils.HandleAggregateException(ae, HttpStatusCode.NotFound, (exception) =>
                    {
                        // Folder no longer exist on Box - it may have been deleted on purpose by the user. Remove it from cache so it is recreated on the next run.
                        screenFolderInfo = FoldersByScreen.Delete(screenFolderInfo);
                        Actions.PressSave();
                        throw new PXException(Messages.BoxFolderNotFoundRunSynchAgain, screenFolderInfo.ScreenID, exception);
                    });
                }
            }

            if (folderInfo == null)
            {
                // Folder wasn't found, try finding it by name in the root folder.
                folderInfo = BoxUtils.FindFolder(tokenHandler, rootFolder.ID, folderName).Result;
            }

            if (folderInfo == null)
            {
                // Folder doesn't exist at all - create it
                folderInfo = BoxUtils.CreateFolder(tokenHandler, folderName, rootFolder.ID).Result;
            }

            if (screenFolderInfo == null)
            {
                screenFolderInfo                      = (BoxFolderCache)FoldersByScreen.Cache.CreateInstance();
                screenFolderInfo.FolderID             = folderInfo.ID;
                screenFolderInfo.ParentFolderID       = folderInfo.ParentFolderID;
                screenFolderInfo.ScreenID             = screen.ScreenID;
                screenFolderInfo.LastModifiedDateTime = null; //To force initial sync
                screenFolderInfo                      = FoldersByScreen.Insert(screenFolderInfo);
                Actions.PressSave();
            }

            // We don't synchronize the miscellaneous files folder, since we can't easily identify the corresponding NoteID from folder
            if (screen.ScreenID != FileHandler.MiscellaneousFolderScreenId && (forceSync || screenFolderInfo.LastModifiedDateTime != folderInfo.ModifiedAt))
            {
                SynchronizeFolderContentsWithScreen(screenFolderInfo.ScreenID, screenFolderInfo.FolderID, forceSync);
                screenFolderInfo.LastModifiedDateTime = folderInfo.ModifiedAt;
                FoldersByScreen.Update(screenFolderInfo);
                Actions.PressSave();
            }
        }
        private string GetFolderNameForActivityRow(object entityRow)
        {
            PXCache cache      = Caches[entityRow.GetType()];
            string  folderName = String.Format("{0:yyyy-MM-dd} - {1} (ID: {2})",
                                               cache.GetValue(entityRow, "StartDate"),
                                               cache.GetValue(entityRow, "Subject"),
                                               cache.GetValue(entityRow, "NoteID"));

            return(BoxUtils.CleanFileOrFolderName(folderName));
        }
        public string GetOrCreateSublevelFolder(UserTokenHandler tokenHandler, string screenID, string parentFolderID, Guid?refNoteID, bool throwOnError)
        {
            BoxFolderSublevelCache sublevelFolder;
            var subLevelGrouping = GetSublevelName(refNoteID);

            if (string.IsNullOrEmpty(subLevelGrouping))
            {
                if (throwOnError)
                {
                    ScreenUtils.TraceAndThrowException(Messages.SubLevelConfigurationInvalid);
                }
                else
                {
                    PXTrace.WriteWarning(string.Format("No sublevel grouping found for note ID {0} (screen {1}, parent folder {2})", refNoteID, screenID, parentFolderID));
                    return(null);
                }
            }

            sublevelFolder = (BoxFolderSublevelCache)SubLevelByScreenAndGrouping.Select(screenID, subLevelGrouping);
            if (sublevelFolder == null)
            {
                var subLevelFolderInfo = GetOrCreateFolder(tokenHandler, parentFolderID, null, null, subLevelGrouping);

                sublevelFolder          = (BoxFolderSublevelCache)SubLevelByScreenAndGrouping.Cache.CreateInstance();
                sublevelFolder.FolderID = subLevelFolderInfo.ID;
                sublevelFolder.Grouping = subLevelGrouping;
                sublevelFolder.ScreenID = screenID;
                SubLevelByScreenAndGrouping.Insert(sublevelFolder);
            }
            else
            {
                try
                {
                    // Folder was found in BoxFolderCache, retrieve it by ID
                    var sublevelFolderInfo = BoxUtils.GetFolderInfo(tokenHandler, sublevelFolder.FolderID).Result;
                }
                catch (AggregateException ae)
                {
                    ScreenUtils.HandleAggregateException(ae, HttpStatusCode.NotFound, (exception) =>
                    {
                        using (new PXConnectionScope())
                        {
                            // Delete entry from BoxFolderCache so that it gets created again.
                            SubLevelByScreenAndGrouping.Delete(sublevelFolder);
                            Actions.PressSave();
                        }

                        throw new PXException(Messages.BoxFolderNotFoundTryAgain, sublevelFolder.FolderID, exception);
                    });
                }
            }

            return(sublevelFolder.FolderID);
        }
        private string GetFolderNameForEntityRow(object entityRow)
        {
            PXCache cache = Caches[entityRow.GetType()];

            string[] keyValues = new string[cache.BqlKeys.Count];
            for (int i = 0; i < cache.BqlKeys.Count; i++)
            {
                keyValues[i] = cache.GetValue(entityRow, cache.BqlKeys[i].Name).ToString();
            }

            return(BoxUtils.CleanFileOrFolderName(string.Join(" ", keyValues)));
        }
        public BoxUtils.FileFolderInfo GetBoxFileInfoForFileID(Guid fileID)
        {
            Guid         blobHandler  = GetBlobHandlerForFileID(fileID);
            BoxFileCache bfc          = GetFileInfoFromCache(blobHandler);
            var          tokenHandler = PXGraph.CreateInstance <UserTokenHandler>();

            BoxUtils.FileFolderInfo fileInfo = BoxUtils.GetFileInfo(tokenHandler, bfc.FileID).Result;
            if (fileInfo == null)
            {
                throw new PXException(Messages.FileNotFoundInBox, bfc.FileID);
            }

            return(fileInfo);
        }
        private BoxUtils.FileFolderInfo GetOrCreateActivityFolder(Guid?refNoteID, UserTokenHandler tokenHandler, object entityRow, object activityRefNoteID)
        {
            //Save an activity related file into the record's activity folder
            var activityRefNoteGuid = Guid.Parse(activityRefNoteID.ToString());

            //Get or create record folder
            string         folderID          = GetOrCreateBoxFolderForNoteID(activityRefNoteGuid);
            BoxFolderCache recordFolderCache = FoldersByFolderID.Select(folderID);

            //Get or create Activities folder
            BoxUtils.FileFolderInfo activityFolderInfo = null;
            if (string.IsNullOrEmpty(recordFolderCache.ActivityFolderID))
            {
                // Create Activities folder and update cache for future reference.
                activityFolderInfo = GetOrCreateFolder(tokenHandler, recordFolderCache.FolderID, null, null, Messages.ActivitiesFolderName);
                recordFolderCache.ActivityFolderID = activityFolderInfo.ID;
                FoldersByFolderID.Update(recordFolderCache);
                Actions.PressSave();
            }
            else
            {
                try
                {
                    // Folder was found in BoxFolderCache, retrieve it by ID
                    activityFolderInfo = BoxUtils.GetFolderInfo(tokenHandler, recordFolderCache.ActivityFolderID).Result;
                }
                catch (AggregateException ae)
                {
                    ScreenUtils.HandleAggregateException(ae, HttpStatusCode.NotFound, (exception) =>
                    {
                        using (new PXConnectionScope())
                        {
                            // Delete entry from BoxFolderCache so that it gets created again.
                            recordFolderCache.ActivityFolderID = null;
                            FoldersByNote.Update(recordFolderCache);
                            Actions.PressSave();
                        }

                        throw new PXException(Messages.BoxFolderNotFoundTryAgain, recordFolderCache.FolderID, exception);
                    });
                }
            }

            //Get/Create activityRecord folder
            string folderName = GetFolderNameForActivityRow(entityRow);

            return(GetOrCreateFolder(tokenHandler, activityFolderInfo.ID, entityRow, refNoteID, folderName));
        }
        public virtual IEnumerable CompleteAuthentication(PXAdapter adapter)
        {
            PXLongOperation.StartOperation(this, delegate
            {
                User.Cache.Clear();
                var tokenHandler        = PXGraph.CreateInstance <UserTokenHandler>();
                BoxUserTokens boxUser   = PXCache <BoxUserTokens> .CreateCopy(User.Select());
                var userInfo            = BoxUtils.GetUserInfo(tokenHandler).Result;
                boxUser.BoxUserID       = userInfo.Id;
                boxUser.BoxEmailAddress = userInfo.Login;
                User.Update(boxUser);
                Actions.PressSave();
            });

            return(adapter.Get());
        }
        public void DeleteFileFromBox(Guid blobHandler)
        {
            var          tokenHandler = PXGraph.CreateInstance <UserTokenHandler>();
            BoxFileCache bfc          = GetFileInfoFromCache(blobHandler);

            try
            {
                BoxUtils.DeleteFile(tokenHandler, bfc.FileID).Wait();
            }
            catch (AggregateException ae)
            {
                ScreenUtils.HandleAggregateException(ae, HttpStatusCode.NotFound, (exception) =>
                {
                    throw new PXException(Messages.FileNotFoundInBox, bfc.FileID, exception);
                });
            }
        }
        private BoxUtils.FileFolderInfo GetOrCreateFolder(UserTokenHandler tokenHandler, string parentFolderID, object entityRow, Guid?refNoteID, string folderName)
        {
            try
            {
                BoxUtils.FileFolderInfo folderInfo = BoxUtils.FindFolder(tokenHandler, parentFolderID, folderName).Result;

                if (folderInfo == null)
                {
                    // Folder doesn't exist on Box, create it.
                    var description = entityRow != null?GetFolderDescriptionForEntityRow(entityRow) : string.Empty;

                    folderInfo = BoxUtils.CreateFolder(tokenHandler, folderName, parentFolderID, description).Result;
                }

                if (!FoldersByFolderID.Select(folderInfo.ID).Any())
                {
                    // Store the folder info in our local cache for future reference
                    BoxFolderCache bfc = (BoxFolderCache)FoldersByFolderID.Cache.CreateInstance();
                    bfc.FolderID             = folderInfo.ID;
                    bfc.ParentFolderID       = folderInfo.ParentFolderID;
                    bfc.RefNoteID            = refNoteID;
                    bfc.LastModifiedDateTime = null; // To force initial sync of Box file list with record file ilst
                    bfc = FoldersByFolderID.Insert(bfc);
                }

                return(folderInfo);
            }
            catch (AggregateException ae)
            {
                ScreenUtils.HandleAggregateException(ae, HttpStatusCode.NotFound, (exception) =>
                {
                    using (new PXConnectionScope())
                    {
                        var bfc      = FoldersByFolderID.Cache.CreateInstance() as BoxFolderCache;
                        bfc.FolderID = parentFolderID;
                        FoldersByFolderID.Delete(bfc);
                        Actions.PressSave();
                    }

                    throw (new PXException(string.Format(Messages.BoxFolderNotFoundTryAgain, parentFolderID), exception));
                });

                return(null);
            }
        }
        public BoxUtils.FileFolderInfo GetRootFolder()
        {
            string rootFolderName = GetRootFolderName();

            if (string.IsNullOrEmpty(rootFolderName))
            {
                throw new PXException(Messages.RootFolderNotSetup);
            }

            var tokenHandler = PXGraph.CreateInstance <UserTokenHandler>();

            BoxUtils.FileFolderInfo rootFolder = BoxUtils.FindFolder(tokenHandler, "0", rootFolderName).Result;
            if (rootFolder == null)
            {
                throw new PXException(Messages.RootFolderNotFound, rootFolderName);
            }

            return(rootFolder);
        }
        public byte[] DownloadFileFromBox(Guid blobHandler)
        {
            var          tokenHandler = PXGraph.CreateInstance <UserTokenHandler>();
            BoxFileCache bfc          = GetFileInfoFromCache(blobHandler);

            try
            {
                return(BoxUtils.DownloadFile(tokenHandler, bfc.FileID).Result);
            }
            catch (AggregateException ae)
            {
                ScreenUtils.HandleAggregateException(ae, HttpStatusCode.NotFound, (exception) =>
                {
                    throw new PXException(Messages.BoxFileNotFound, exception);
                });

                return(new byte[0]);
            }
        }
        public static async Task <FileFolderInfo> CreateFolder(UserTokenHandler tokenHandler, string name, string parentFolderID)
        {
            var client = GetNewBoxClient(tokenHandler);

            return(await BoxUtils.CreateFolder(client, tokenHandler, name, parentFolderID).ConfigureAwait(false));
        }
        private void SynchronizeFolderContentsWithScreen(string screenID, string folderID, bool isForcingSync)
        {
            // Retrieve top-level folder list
            var tokenHandler = PXGraph.CreateInstance <UserTokenHandler>();
            List <BoxUtils.FileFolderInfo> boxFolderList = new List <BoxUtils.FileFolderInfo>();

            if (FieldsGroupingByScreenID.Select(screenID).Any())
            {
                boxFolderList = BoxUtils.GetFolderList(tokenHandler, folderID, (int)BoxUtils.RecursiveDepth.FirstSubLevel).Result;
                boxFolderList = boxFolderList.Where(x => x.Name.Contains("\\")).ToList();
            }
            else
            {
                boxFolderList = BoxUtils.GetFolderList(tokenHandler, folderID, (int)BoxUtils.RecursiveDepth.NoDepth).Result;
            }

            foreach (BoxUtils.FileFolderInfo boxFolderInfo in boxFolderList)
            {
                BoxFolderCache bfc = FoldersByFolderID.Select(boxFolderInfo.ID);
                if (bfc != null)
                {
                    //Make sure NoteDoc still exists
                    NoteDoc nd = NoteDocs.Select(bfc.RefNoteID);
                    if (nd == null)
                    {
                        //NoteDoc can't be found; this is likely a file coming from a record that was deleted.
                        //Since an existing folder may be renamed to something which exists, we want to force system to treat it as if it was a new folder
                        FoldersByFolderID.Delete(bfc);
                        bfc = null;
                    }
                }

                if (bfc == null)
                {
                    // We've never seen this folder; sync it
                    Guid?refNoteID;

                    if (screenID == ActivityMaintScreenId)
                    {
                        //Activity folders use custom naming defined in GetFolderNameForActivityRow() - just look for GUID inside it.
                        refNoteID = ExtractGuidFromString(boxFolderInfo.Name);
                    }
                    else
                    {
                        refNoteID = FindMatchingNoteIDForFolder(screenID, boxFolderInfo.Name);
                    }

                    if (refNoteID == null)
                    {
                        // User may have created some folder manually with a name not matching to any record, or record
                        // may have been deleted in Acumatica. We can safely ignore it, but let's write to trace.
                        PXTrace.WriteWarning(string.Format("No record found for folder {0} (screen {1}, ID {2})", boxFolderInfo.Name, screenID, boxFolderInfo.ID));
                        continue;
                    }

                    bfc = (BoxFolderCache)FoldersByNote.Select(refNoteID);
                    if (bfc != null)
                    {
                        // A folder existed before for this record; clear the previous entry for this refNoteID
                        FoldersByNote.Delete(bfc);
                    }

                    // Store folder in cache for future reference
                    bfc                      = (BoxFolderCache)FoldersByFolderID.Cache.CreateInstance();
                    bfc.FolderID             = boxFolderInfo.ID;
                    bfc.ParentFolderID       = boxFolderInfo.ParentFolderID;
                    bfc.RefNoteID            = refNoteID;
                    bfc.LastModifiedDateTime = null; //To force initial sync
                    bfc                      = FoldersByFolderID.Insert(bfc);
                }

                if (isForcingSync || bfc.LastModifiedDateTime != boxFolderInfo.ModifiedAt)
                {
                    RefreshRecordFileList(screenID, boxFolderInfo.Name, boxFolderInfo.ID, bfc.RefNoteID, isForcingSync);
                    bfc.LastModifiedDateTime = boxFolderInfo.ModifiedAt;
                    FoldersByFolderID.Update(bfc);
                    PXContext.SetSlot <bool>("BoxDisableLoad", true);
                    try
                    {
                        Actions.PressSave();
                    }
                    finally
                    {
                        PXContext.SetSlot <bool>("BoxDisableLoad", false);
                    }
                }
            }
        }
        public void RefreshRecordFileList(string screenID, string folderName, string folderID, Guid?refNoteID, bool isForcingSync)
        {
            var tokenHandler = PXGraph.CreateInstance <UserTokenHandler>();

            //Get list of files contained in the record folder. RecurseDepth=0 will retrieve all subfolders
            List <BoxUtils.FileFolderInfo> boxFileList = BoxUtils.GetFileList(tokenHandler, folderID, (int)BoxUtils.RecursiveDepth.Unlimited).Result;

            // Remove files from cache if they don't exist on Box server
            foreach (PXResult <BoxFileCache, UploadFileRevisionNoData, UploadFile, NoteDoc> result in FilesByNoteID.Select(refNoteID))
            {
                BoxUtils.FileFolderInfo boxFile = boxFileList.FirstOrDefault(f => f.ID == ((BoxFileCache)result).FileID);
                if (boxFile == null)
                {
                    //File was deleted
                    FilesByNoteID.Delete(result);
                    UploadFiles.Delete(result);
                    UploadFileRevisions.Delete(result);
                    NoteDocs.Delete(result);
                }
                else
                {
                    // File still exists, remove it from in-memory list
                    // so we don't process it as a new file in the next loop
                    boxFileList.Remove(boxFile);
                }
            }

            // Remove any files/folders coming from activities stored beneath the current record, they've been processed above
            var filesFoundOnlyOnServer = boxFileList.Where(x => !x.Name.StartsWith(Messages.ActivitiesFolderName)).ToList();

            //Check for underlying activities records
            BoxFolderCache currentFolder = FoldersByFolderID.Select(folderID);

            if (currentFolder != null && boxFileList.Any(x => x.Name.StartsWith(Messages.ActivitiesFolderName)))
            {
                // If nullOrEmpty, Folder may have been created manually
                if (string.IsNullOrEmpty(currentFolder.ActivityFolderID))
                {
                    //Find actual folder ID and save in BoxFolderCache's ActivityFolderID field
                    BoxUtils.FileFolderInfo activityFolderinfo = BoxUtils.FindFolder(tokenHandler, folderID, Messages.ActivitiesFolderName).Result;
                    if (activityFolderinfo != null)
                    {
                        currentFolder.ActivityFolderID = activityFolderinfo?.ID;
                        FoldersByFolderID.Update(currentFolder);
                    }
                }

                if (currentFolder.ActivityFolderID != null)
                {
                    SynchronizeFolderContentsWithScreen(ActivityMaintScreenId, currentFolder.ActivityFolderID, isForcingSync);
                }
            }

            //Remaining files aren't found in cache but are in Box server.
            if (filesFoundOnlyOnServer.Any())
            {
                if (refNoteID == null)
                {
                    // User may have created some folder manually with a name not matching to any record, or record
                    // may have been deleted in Acumatica. We can safely ignore it, but let's write to trace.
                    PXTrace.WriteWarning(string.Format("No record found for folder {0} (screen {1}, ID {2})", folderName, screenID, folderID));
                    return;
                }

                UploadFileMaintenance ufm = PXGraph.CreateInstance <UploadFileMaintenance>();
                ufm.IgnoreFileRestrictions = true;

                ufm.RowInserting.AddHandler <UploadFileRevision>(delegate(PXCache sender, PXRowInsertingEventArgs e)
                {
                    ((UploadFileRevision)e.Row).BlobHandler = Guid.NewGuid();
                });
                //Add files to the caches
                foreach (BoxUtils.FileFolderInfo boxFile in filesFoundOnlyOnServer)
                {
                    ufm.Clear();
                    string   fileName = string.Format("{0}\\{1}", folderName, boxFile.Name.Replace(Path.GetInvalidPathChars(), ' '));
                    FileInfo fileInfo = ufm.GetFileWithNoData(fileName);
                    Guid?    blobHandlerGuid;
                    if (fileInfo == null)
                    {
                        fileInfo = new FileInfo(fileName, null, new byte[0]);
                        //The SaveFile call will trigger a Load() on the BoxBlobStorageProvider which can be skipped
                        PXContext.SetSlot <bool>("BoxDisableLoad", true);
                        try
                        {
                            if (!ufm.SaveFile(fileInfo))
                            {
                                throw new PXException(Messages.ErrorAddingFileSaveFileFailed, fileName);
                            }
                        }
                        finally
                        {
                            PXContext.SetSlot <bool>("BoxDisableLoad", false);
                        }

                        if (!fileInfo.UID.HasValue)
                        {
                            throw new PXException(Messages.ErrorAddingFileUIDNull, fileName);
                        }

                        UploadFileMaintenance.SetAccessSource(fileInfo.UID.Value, null, screenID);
                        NoteDoc noteDoc = (NoteDoc)NoteDocs.Cache.CreateInstance();
                        noteDoc.NoteID = refNoteID;
                        noteDoc.FileID = fileInfo.UID;
                        NoteDocs.Insert(noteDoc);

                        blobHandlerGuid = ufm.Revisions.Current.BlobHandler;
                    }
                    else
                    {
                        //File already exists in the database, retrieve BlobHandler
                        if (!fileInfo.UID.HasValue)
                        {
                            throw new PXException(Messages.GetFileWithNoDataReturnedUIDNull, fileName);
                        }
                        blobHandlerGuid = GetBlobHandlerForFileID(fileInfo.UID.Value);

                        //Clear old references of this blob handler from cache; it will be reinserted with up-to-date info
                        var bfcOrphan = (BoxFileCache)FilesByBlobHandler.Select(blobHandlerGuid);
                        if (bfcOrphan != null)
                        {
                            FilesByBlobHandler.Delete(bfcOrphan);
                        }

                        //Update NoteDoc entry if existing file was moved to new NoteID or create it if not there
                        NoteDoc nd = (NoteDoc)NoteDocsByFileID.Select(fileInfo.UID);
                        if (nd == null)
                        {
                            nd        = (NoteDoc)NoteDocs.Cache.CreateInstance();
                            nd.NoteID = refNoteID;
                            nd.FileID = fileInfo.UID;
                            NoteDocs.Insert(nd);
                        }
                        else if (nd.NoteID != refNoteID)
                        {
                            nd.NoteID = refNoteID;
                            NoteDocs.Update(nd);
                        }
                    }

                    var bfc = (BoxFileCache)FilesByBlobHandler.Cache.CreateInstance();
                    bfc.BlobHandler    = blobHandlerGuid;
                    bfc.FileID         = boxFile.ID;
                    bfc.ParentFolderID = boxFile.ParentFolderID;
                    bfc = FilesByBlobHandler.Insert(bfc);
                }
            }
        }
        public Guid SaveFileToBoxAndUpdateFileCache(byte[] data, PXBlobStorageContext saveContext)
        {
            BoxUtils.FileFolderInfo boxFile = null;
            Guid blobHandlerGuid            = Guid.NewGuid();

            var tokenHandler = PXGraph.CreateInstance <UserTokenHandler>();

            if (saveContext == null || saveContext.FileInfo == null || !saveContext.NoteID.HasValue)
            {
                var fileName = string.Empty;
                if (saveContext?.FileInfo?.Name == null)
                {
                    fileName = blobHandlerGuid.ToString();
                }
                else
                {
                    fileName = BoxUtils.CleanFileOrFolderName(saveContext.FileInfo.Name);
                    fileName = $"{Path.GetFileNameWithoutExtension(fileName)} ({blobHandlerGuid.ToString()}){Path.GetExtension(fileName)}";
                }

                //We don't know on which screen this file belongs. We'll have to save it in miscellaneous files folder.
                BoxUtils.FileFolderInfo boxFolder = GetMiscellaneousFolder();
                boxFile = BoxUtils.UploadFile(tokenHandler, boxFolder.ID, fileName, data).Result;
            }
            else
            {
                CheckForMissingNoteRecord(saveContext);
                var    fileName    = BoxUtils.CleanFileOrFolderName(Path.GetFileName(saveContext.FileInfo.Name));
                string boxFolderID = GetOrCreateBoxFolderForNoteID(saveContext.NoteID.Value);
                try
                {
                    boxFile = BoxUtils.UploadFile(tokenHandler, boxFolderID, fileName, data).Result;
                }
                catch (AggregateException ae)
                {
                    ScreenUtils.HandleAggregateException(ae, HttpStatusCode.NotFound, exception =>
                    {
                        using (new PXConnectionScope())
                        {
                            BoxFolderCache folderCacheToDelete = FoldersByFolderID.Cache.CreateInstance() as BoxFolderCache;
                            folderCacheToDelete.FolderID       = boxFolderID;
                            var deletedFolderInfo = FoldersByFolderID.Delete(folderCacheToDelete);
                            Actions.PressSave();
                        }

                        ScreenUtils.TraceAndThrowException(Messages.BoxFolderNotFoundRunSynchAgain, boxFolderID);
                    });
                }

                if (!string.IsNullOrEmpty(saveContext.FileInfo.Comment))
                {
                    BoxUtils.SetFileDescription(tokenHandler, boxFile.ID, saveContext.FileInfo.Comment).Wait();
                }
            }

            var bfc = (BoxFileCache)FilesByBlobHandler.Cache.CreateInstance();

            bfc.BlobHandler    = blobHandlerGuid;
            bfc.FileID         = boxFile.ID;
            bfc.ParentFolderID = boxFile.ParentFolderID;
            bfc = FilesByBlobHandler.Insert(bfc);
            Actions.PressSave();

            return(blobHandlerGuid);
        }