public void ProcessEditQueueItem(int id, bool publishEdit, int userId)
        {
            //prepare poi details
            int updatePOIId = 0;
            var queueItem   = DataModel.EditQueueItems.FirstOrDefault(e => e.ID == id);

            if (queueItem != null && queueItem.IsProcessed == false)
            {
                if (queueItem.EntityType.ID == (int)StandardEntityTypes.POI)
                {
                    //check current user is authorized to approve edits for this POIs country
                    bool hasEditPermission = false;
                    var  editPOI           = DeserializePOIFromJSON(queueItem.EditData);
                    var  userProfile       = new UserManager().GetUser(userId);
                    if (userProfile != null)
                    {
                        if (UserManager.HasUserPermission(userProfile, editPOI.AddressInfo.CountryID, PermissionLevel.Editor))
                        {
                            hasEditPermission = true;
                        }
                    }

                    //processing a POI add/edit
                    if (hasEditPermission)
                    {
                        if (publishEdit)
                        {
                            //get diff between previous and edit

                            POIManager        poiManager = new POIManager();
                            Model.ChargePoint poiA       = DeserializePOIFromJSON(queueItem.PreviousData);
                            Model.ChargePoint poiB       = DeserializePOIFromJSON(queueItem.EditData);

                            bool poiUpdateRequired = false;

                            if (poiA != null)
                            {
                                //this is an edit, load the latest version of the POI as version 'A'
                                poiA = poiManager.Get(poiA.ID);
                                if (poiManager.HasDifferences(poiA, poiB))
                                {
                                    poiUpdateRequired = true;
                                }
                            }

                            //save poi update
                            //if its an edit, load the original details before applying the change
                            if (poiUpdateRequired)
                            {
                                //updates to externally provided POIs require old version to be superseded (archived) first
                                if (poiA != null && poiA.DataProviderID != (int)StandardDataProviders.OpenChargeMapContrib)
                                {
                                    poiManager.SupersedePOI(DataModel, poiA, poiB);
                                }
                            }

                            //set/update cp properties from simple model to data model
                            var poiData = poiManager.PopulateChargePoint_SimpleToData(poiB, DataModel);

                            //set status type to published if previously unset
                            if (poiData.SubmissionStatusTypeID == null)
                            {
                                poiData.SubmissionStatusType = DataModel.SubmissionStatusTypes.First(s => s.ID == (int)StandardSubmissionStatusTypes.Submitted_Published);
                            }

                            poiData.DateLastStatusUpdate = DateTime.UtcNow;

                            //publish edit
                            DataModel.SaveChanges();

                            updatePOIId = poiData.ID;

                            //attribute submitter with reputation points
                            if (queueItem.UserID != null)
                            {
                                new UserManager().AddReputationPoints((int)queueItem.UserID, 1);
                            }
                        }

                        //update edit queue item as processed
                        queueItem.IsProcessed     = true;
                        queueItem.ProcessedByUser = DataModel.Users.FirstOrDefault(u => u.ID == userId);
                        queueItem.DateProcessed   = DateTime.UtcNow;
                        DataModel.SaveChanges();

                        //TODO: also award processing editor with reputation points if they are approving someone elses edit and they are not Admin

                        //Refresh POI cache
                        Task cacheRefresh = CacheManager.RefreshCachedPOI(updatePOIId);
                    }
                }
            }
        }