public QueryResponse CreateRelationManyToManyRecord(Guid relationId, Guid originValue, Guid targetValue) { QueryResponse response = new QueryResponse(); response.Object = null; response.Success = true; response.Timestamp = DateTime.UtcNow; try { var relation = relationRepository.Read(relationId); if (relation == null) response.Errors.Add(new ErrorModel { Message = "Relation does not exists." }); if (response.Errors.Count > 0) { response.Object = null; response.Success = false; response.Timestamp = DateTime.UtcNow; return response; } relationRepository.CreateManyToManyRecord(relationId, originValue, targetValue); return response; } catch (Exception e) { response.Success = false; response.Object = null; response.Timestamp = DateTime.UtcNow; #if DEBUG response.Message = e.Message + e.StackTrace; #else response.Message = "The entity relation record was not created. An internal error occurred!"; #endif return response; } }
public IActionResult AllActivitiesUserCanSee(string label = "all", int page = 1) { var response = new ResponseModel(); try { //var queryString = HttpContext.Request.QueryString; #region << Can user read activities >> //Get current user ErpUser user = SecurityContext.CurrentUser; //Get entity meta var entity = entMan.ReadEntity("wv_project_activity").Object; //check if user role has permissions var canRead = user.Roles.Any(x => entity.RecordPermissions.CanRead.Any(z => z == x.Id)); var canCreate = user.Roles.Any(x => entity.RecordPermissions.CanCreate.Any(z => z == x.Id)); var canUpdate = user.Roles.Any(x => entity.RecordPermissions.CanUpdate.Any(z => z == x.Id)); var canDelete = user.Roles.Any(x => entity.RecordPermissions.CanDelete.Any(z => z == x.Id)); if (!canRead) { response.Success = false; response.Message = "You do not have permission to read the activities in this system"; response.Timestamp = DateTime.UtcNow; return Json(response); //return empty object } #endregion var activityQueryResponse = new QueryResponse(); var userCanSeeProjectIds = new List<Guid>(); #region << Generate list of projects user can see >> { var requestedFields = "id,$user_1_n_project_owner.id,$role_n_n_project_team.id,$role_n_n_project_customer.id"; //QueryObject filterObj = EntityQuery.QueryEQ("id", recordId); QueryObject filterObj = null; EntityQuery resultQuery = new EntityQuery("wv_project", requestedFields, filterObj, null, null, null, null); QueryResponse result = recMan.Find(resultQuery); var resultRecordsList = new List<EntityRecord>(); if (!result.Success) { response.Success = false; response.Timestamp = DateTime.UtcNow; response.Message = result.Message; response.Object = null; return Json(response); } foreach (var record in result.Object.Data) { //Check if user can view the object var userIsPM = false; var userIsStaff = false; var userIsCustomer = false; #region << Check user roles >> foreach (var userRole in user.Roles) { if (!userIsPM) { userIsPM = ((List<EntityRecord>)record["$user_1_n_project_owner"]).Any(z => (Guid)z["id"] == user.Id); } if (!userIsStaff) { userIsStaff = ((List<EntityRecord>)record["$role_n_n_project_team"]).Any(z => (Guid)z["id"] == userRole.Id); } if (!userIsCustomer) { userIsCustomer = ((List<EntityRecord>)record["$role_n_n_project_customer"]).Any(z => (Guid)z["id"] == userRole.Id); } } #endregion if (userIsPM || userIsStaff || userIsCustomer) { userCanSeeProjectIds.Add((Guid)record["id"]); } } } #endregion #region << Get activities >> { var fields = "id,label,created_on,description,subject," + "$user_wv_project_activity_created_by.username,$user_wv_project_activity_created_by.image," + "$project_1_n_activity.name"; QueryObject rootFilterSection = null; QueryObject auxFilterSection = null; QueryObject projectIdFilterSection = null; #region << project id filters >> var projectIdRulesList = new List<QueryObject>(); foreach (var projectId in userCanSeeProjectIds) { var projectIdRule = EntityQuery.QueryEQ("project_id", projectId); projectIdRulesList.Add(projectIdRule); } projectIdFilterSection = EntityQuery.QueryOR(projectIdRulesList.ToArray()); #endregion #region << Aux filters & Sort>> var auxRulesList = new List<QueryObject>(); QueryObject auxRule = new QueryObject(); if (label != "all") { auxRule = EntityQuery.QueryEQ("label", label); auxRulesList.Add(auxRule); } auxFilterSection = EntityQuery.QueryAND(auxRulesList.ToArray()); //Add default sort by created_on var sortRulesList = new List<QuerySortObject>(); var defaultSortRule = new QuerySortObject("created_on", QuerySortType.Descending); sortRulesList.Add(defaultSortRule); #endregion rootFilterSection = EntityQuery.QueryAND(projectIdFilterSection, auxFilterSection); //Calculate page var pageSize = 10; var skipRecords = (page - 1) * pageSize; var activityQuery = new EntityQuery("wv_project_activity", fields, rootFilterSection, sortRulesList.ToArray(), skipRecords, pageSize, null); activityQueryResponse = recMan.Find(activityQuery); if (!activityQueryResponse.Success) { response.Success = false; response.Timestamp = DateTime.UtcNow; response.Message = activityQueryResponse.Message; response.Object = null; return Json(response); } } #endregion response.Success = true; response.Timestamp = DateTime.UtcNow; response.Message = "Successful read"; response.Object = activityQueryResponse.Object.Data; return Json(response); } catch (Exception ex) { response.Success = false; response.Timestamp = DateTime.UtcNow; response.Message = ex.Message; response.Object = null; return Json(response); } }
public IActionResult AllTaskUserCanSee(string listName, int page = 0) { var response = new ResponseModel(); try { //var queryString = HttpContext.Request.QueryString; #region << Can user read tasks >> //Get current user ErpUser user = SecurityContext.CurrentUser; //Get entity meta var entity = entMan.ReadEntity("wv_task").Object; //check if user role has permissions var canRead = user.Roles.Any(x => entity.RecordPermissions.CanRead.Any(z => z == x.Id)); var canCreate = user.Roles.Any(x => entity.RecordPermissions.CanCreate.Any(z => z == x.Id)); var canUpdate = user.Roles.Any(x => entity.RecordPermissions.CanUpdate.Any(z => z == x.Id)); var canDelete = user.Roles.Any(x => entity.RecordPermissions.CanDelete.Any(z => z == x.Id)); if (!canRead) { response.Success = false; response.Message = "You do not have permission to read the projects in this system"; response.Timestamp = DateTime.UtcNow; return Json(response); //return empty object } #endregion var taskQueryResponse = new QueryResponse(); var userCanSeeProjectIds = new List<Guid>(); #region << Generate list of projects user can see >> { var requestedFields = "id,$user_1_n_project_owner.id,$role_n_n_project_team.id,$role_n_n_project_customer.id"; //QueryObject filterObj = EntityQuery.QueryEQ("id", recordId); QueryObject filterObj = null; EntityQuery resultQuery = new EntityQuery("wv_project", requestedFields, filterObj, null, null, null, null); QueryResponse result = recMan.Find(resultQuery); var resultRecordsList = new List<EntityRecord>(); if (!result.Success) { response.Success = false; response.Timestamp = DateTime.UtcNow; response.Message = result.Message; response.Object = null; return Json(response); } foreach (var record in result.Object.Data) { //Check if user can view the object var userIsPM = false; var userIsStaff = false; var userIsCustomer = false; #region << Check user roles >> foreach (var userRole in user.Roles) { if (!userIsPM) { userIsPM = ((List<EntityRecord>)record["$user_1_n_project_owner"]).Any(z => (Guid)z["id"] == user.Id); } if (!userIsStaff) { userIsStaff = ((List<EntityRecord>)record["$role_n_n_project_team"]).Any(z => (Guid)z["id"] == userRole.Id); } if (!userIsCustomer) { userIsCustomer = ((List<EntityRecord>)record["$role_n_n_project_customer"]).Any(z => (Guid)z["id"] == userRole.Id); } } #endregion if (userIsPM || userIsStaff || userIsCustomer) { userCanSeeProjectIds.Add((Guid)record["id"]); } } } #endregion #region << Get tasks >> { var fields = "id,code,number,subject,start_date,end_date,status,priority,$user_1_n_task_owner.id,$user_1_n_task_owner.image"; QueryObject rootFilterSection = null; QueryObject auxFilterSection = null; QueryObject projectIdFilterSection = null; #region << project id filters >> var projectIdRulesList = new List<QueryObject>(); foreach (var projectId in userCanSeeProjectIds) { var projectIdRule = EntityQuery.QueryEQ("project_id", projectId); projectIdRulesList.Add(projectIdRule); } projectIdFilterSection = EntityQuery.QueryOR(projectIdRulesList.ToArray()); #endregion #region << Aux filters & Sort>> var sortRulesList = new List<QuerySortObject>(); var queryString = HttpContext.Request.QueryString.ToString(); var queryKeyValueList = QueryHelpers.ParseQuery(queryString); var auxRulesList = new List<QueryObject>(); var getListObject = entMan.ReadRecordList(entity.Name, listName).Object; //Currently we will hardcode the query generation //auxFilterSection = RecordListQuery.ConvertQuery(getListObject.Query); QueryObject auxRule = new QueryObject(); foreach (var query in queryKeyValueList) { switch (query.Key.ToLowerInvariant()) { case "code": auxRule = new QueryObject(); auxRule = EntityQuery.QueryContains("code", (string)query.Value); auxRulesList.Add(auxRule); break; case "subject": auxRule = new QueryObject(); auxRule = EntityQuery.QueryContains("subject", (string)query.Value); auxRulesList.Add(auxRule); break; case "status": auxRule = new QueryObject(); auxRule = EntityQuery.QueryEQ("status", (string)query.Value); auxRulesList.Add(auxRule); break; case "priority": auxRule = new QueryObject(); auxRule = EntityQuery.QueryEQ("priority", (string)query.Value); auxRulesList.Add(auxRule); break; case "sortby": var sortRule = new QuerySortObject((string)query.Value, QuerySortType.Descending); if (!queryKeyValueList.ContainsKey("sortOrder") || (string)queryKeyValueList["sortOrder"] == "ascending") { sortRule = new QuerySortObject((string)query.Value, QuerySortType.Ascending); } sortRulesList.Add(sortRule); break; } } auxFilterSection = EntityQuery.QueryAND(auxRulesList.ToArray()); //Add default sort by created_on var defaultSortRule = new QuerySortObject("created_on", QuerySortType.Ascending); sortRulesList.Add(defaultSortRule); #endregion rootFilterSection = EntityQuery.QueryAND(projectIdFilterSection, auxFilterSection); //Calculate page var pageSize = getListObject.PageSize; var skipRecords = (page - 1) * pageSize; var taskQuery = new EntityQuery("wv_task", fields, rootFilterSection, sortRulesList.ToArray(), skipRecords, pageSize, null); taskQueryResponse = recMan.Find(taskQuery); if (!taskQueryResponse.Success) { response.Success = false; response.Timestamp = DateTime.UtcNow; response.Message = taskQueryResponse.Message; response.Object = null; return Json(response); } } #endregion var taskList = new List<EntityRecord>(); #region << Post-process >> foreach (var task in taskQueryResponse.Object.Data) { var record = new EntityRecord(); record["id"] = (Guid)task["id"]; record["code"] = (string)task["code"]; record["subject"] = (string)task["subject"]; record["start_date"] = (DateTime)task["start_date"]; record["end_date"] = (DateTime)task["end_date"]; record["status"] = (string)task["status"]; record["priority"] = (string)task["priority"]; var taskOwnerIdList = new List<Guid>(); var taskOwnerImageList = new List<string>(); var taskOwnerId = (Guid)((List<EntityRecord>)task["$user_1_n_task_owner"])[0]["id"]; var taskOwnerImage = (string)((List<EntityRecord>)task["$user_1_n_task_owner"])[0]["image"]; taskOwnerIdList.Add(taskOwnerId); taskOwnerImageList.Add(taskOwnerImage); record["$field$user_1_n_task_owner$id"] = taskOwnerIdList; record["$field$user_1_n_task_owner$image"] = taskOwnerImageList; taskList.Add(record); } #endregion response.Success = true; response.Timestamp = DateTime.UtcNow; response.Message = "Successful read"; response.Object = taskList; return Json(response); } catch (Exception ex) { response.Success = false; response.Timestamp = DateTime.UtcNow; response.Message = ex.Message; response.Object = null; return Json(response); } }
public QueryResponse UpdateRecord(Entity entity, EntityRecord record) { QueryResponse response = new QueryResponse(); response.Object = null; response.Success = true; response.Timestamp = DateTime.UtcNow; try { if (entity == null) response.Errors.Add(new ErrorModel { Message = "Invalid entity name." }); if (record == null) response.Errors.Add(new ErrorModel { Message = "Invalid record. Cannot be null." }); else if (!record.Properties.ContainsKey("id")) response.Errors.Add(new ErrorModel { Message = "Invalid record. Missing ID field." }); if (response.Errors.Count > 0) { response.Object = null; response.Success = false; response.Timestamp = DateTime.UtcNow; return response; } List<KeyValuePair<string, object>> storageRecordData = new List<KeyValuePair<string, object>>(); var recordFields = record.GetProperties(); foreach (var field in entity.Fields) { var pair = recordFields.SingleOrDefault(x => x.Key == field.Name); try { if (pair.Key == null) continue; if (field is PasswordField && pair.Value == null) continue; storageRecordData.Add(new KeyValuePair<string, object>(field.Name, ExtractFieldValue(pair, field, true))); } catch (Exception ex) { if (pair.Key == null) throw new Exception("Error during processing value for field: '" + field.Name + "'. No value is specified."); else throw new Exception("Error during processing value for field: '" + field.Name + "'. Invalid value: '" + pair.Value + "'", ex); } } var recRepo = erpService.StorageService.GetRecordRepository(); recRepo.Update(entity.Name, storageRecordData); //fixes issue with ID comming from webapi request Guid recordId = Guid.Empty; if (record["id"] is string) recordId = new Guid(record["id"] as string); else if (record["id"] is Guid) recordId = (Guid)record["id"]; else throw new Exception("Invalid record id"); var query = EntityQuery.QueryEQ("id", recordId); var entityQuery = new EntityQuery(entity.Name, "*", query); response = Find(entityQuery); if (response.Object != null && response.Object.Data.Count > 0) response.Message = "Record was updated successfully"; else { response.Success = false; response.Message = "Record was not updated successfully"; } return response; } catch (Exception e) { response.Success = false; response.Object = null; response.Timestamp = DateTime.UtcNow; #if DEBUG response.Message = e.Message + e.StackTrace; #else response.Message = "The entity record was not update. An internal error occurred!"; #endif return response; } }
public QueryResponse UpdateRecord(Guid entityId, EntityRecord record) { Entity entity = GetEntity(entityId); if (entity == null) { QueryResponse response = new QueryResponse { Success = false, Object = null, Timestamp = DateTime.UtcNow }; response.Errors.Add(new ErrorModel { Message = "Entity cannot be found." }); return response; } return UpdateRecord(entity, record); }
public IActionResult UpdateEntityRecord(string entityName, Guid recordId, [FromBody]EntityRecord postObj) { if (!postObj.Properties.ContainsKey("id")) { postObj["id"] = recordId; } ////////////////////////////////////////////////////////////////////////////////////// //WEBHOOK FILTER << update_record_input_filter >> ////////////////////////////////////////////////////////////////////////////////////// #region try { dynamic hookFilterObj = new ExpandoObject(); hookFilterObj.record = postObj; hookFilterObj.recordId = recordId; hookFilterObj.controller = this; hookFilterObj = hooksService.ProcessFilters(SystemWebHookNames.UpdateRecordInput, entityName, hookFilterObj); postObj = hookFilterObj.record; } catch (Exception ex) { return Json(CreateErrorResponse("Plugin error in web hook update_record_input_filter: " + ex.Message)); }// <<< #endregion var validationErrors = new List<ErrorModel>(); //TODO implement validation ////////////////////////////////////////////////////////////////////////////////////// //WEBHOOK FILTER << update_record_validation_errors_filter >> ////////////////////////////////////////////////////////////////////////////////////// #region try { dynamic hookFilterObj = new ExpandoObject(); hookFilterObj.errors = validationErrors; hookFilterObj.record = postObj; hookFilterObj.recordId = recordId; hookFilterObj.controller = this; hookFilterObj = hooksService.ProcessFilters(SystemWebHookNames.UpdateRecordValidationErrors, entityName, hookFilterObj); validationErrors = hookFilterObj.errors; } catch (Exception ex) { return Json(CreateErrorResponse("Plugin error in web hook update_record_validation_errors_filter: " + ex.Message)); }// <<< #endregion if (validationErrors.Count > 0) { var response = new ResponseModel(); response.Success = false; response.Timestamp = DateTime.UtcNow; response.Errors = validationErrors; response.Message = "Validation error occurred!"; response.Object = null; return Json(response); } //clear authentication cache if (entityName == "user") WebSecurityUtil.RemoveIdentityFromCache(recordId); //Create transaction var result = new QueryResponse(); using (var connection = DbContext.Current.CreateConnection()) { try { connection.BeginTransaction(); ////////////////////////////////////////////////////////////////////////////////////// //WEBHOOK FILTER << update_record_pre_save_filter >> ////////////////////////////////////////////////////////////////////////////////////// #region try { dynamic hookFilterObj = new ExpandoObject(); hookFilterObj.record = postObj; hookFilterObj.recordId = new Guid(postObj["id"].ToString()); hookFilterObj.controller = this; hookFilterObj = hooksService.ProcessFilters(SystemWebHookNames.UpdateRecordPreSave, entityName, hookFilterObj); postObj = hookFilterObj.record; } catch (Exception ex) { connection.RollbackTransaction(); return Json(CreateErrorResponse("Plugin error in web hook update_record_pre_save_filter: " + ex.Message)); }// <<< #endregion result = recMan.UpdateRecord(entityName, postObj); connection.CommitTransaction(); } catch (Exception ex) { connection.RollbackTransaction(); var response = new ResponseModel(); response.Success = false; response.Timestamp = DateTime.UtcNow; response.Message = "Error while saving the record: " + ex.Message; response.Object = null; return Json(response); } } ////////////////////////////////////////////////////////////////////////////////////// //WEBHOOK ACTION << update_record_success_action >> ////////////////////////////////////////////////////////////////////////////////////// #region try { dynamic hookActionObj = new ExpandoObject(); hookActionObj.record = postObj; hookActionObj.oldRecord = postObj; hookActionObj.result = result; hookActionObj.recordId = recordId; hookActionObj.controller = this; hooksService.ProcessActions(SystemWebHookNames.UpdateRecordAction, entityName, hookActionObj); } catch (Exception ex) { return Json(CreateErrorResponse("Plugin error in web hook update_record_success_action: " + ex.Message)); }// <<< #endregion return DoResponse(result); }
public IActionResult DeleteRecord(Guid recordId, string entityName) { ////////////////////////////////////////////////////////////////////////////////////// //WEBHOOK FILTER << delete_record_input_filter >> ////////////////////////////////////////////////////////////////////////////////////// try { dynamic hookFilterObj = new ExpandoObject(); hookFilterObj.recordId = recordId; hookFilterObj.controller = this; hookFilterObj = hooksService.ProcessFilters(SystemWebHookNames.DeleteRecordInput, entityName, hookFilterObj); recordId = hookFilterObj.recordId; } catch (Exception ex) { return Json(CreateErrorResponse("Plugin error in web hook delete_record_input_filter: " + ex.Message)); }// <<< var validationErrors = new List<ErrorModel>(); ////////////////////////////////////////////////////////////////////////////////////// //WEBHOOK FILTER << delete_record_validation_errors_filter >> ////////////////////////////////////////////////////////////////////////////////////// try { dynamic hookFilterObj = new ExpandoObject(); hookFilterObj.errors = validationErrors; hookFilterObj.recordId = recordId; hookFilterObj.controller = this; hookFilterObj = hooksService.ProcessFilters(SystemWebHookNames.DeleteRecordValidationErrors, entityName, hookFilterObj); validationErrors = hookFilterObj.errors; } catch (Exception ex) { return Json(CreateErrorResponse("Plugin error in web hook delete_record_validation_errors_filter: " + ex.Message)); }// <<< if (validationErrors.Count > 0) { var response = new ResponseModel(); response.Success = false; response.Timestamp = DateTime.UtcNow; response.Errors = validationErrors; response.Message = "Validation error occurred!"; response.Object = null; return Json(response); } //Create transaction var result = new QueryResponse(); using (var connection = DbContext.Current.CreateConnection()) { try { connection.BeginTransaction(); ////////////////////////////////////////////////////////////////////////////////////// //WEBHOOK FILTER << delete_record_pre_save_filter >> ////////////////////////////////////////////////////////////////////////////////////// try { dynamic hookFilterObj = new ExpandoObject(); hookFilterObj.recordId = recordId; hookFilterObj.controller = this; hookFilterObj = hooksService.ProcessFilters(SystemWebHookNames.DeleteRecordPreSave, entityName, hookFilterObj); recordId = hookFilterObj.recordId; } catch (Exception ex) { connection.RollbackTransaction(); return Json(CreateErrorResponse("Plugin error in web hook delete_record_pre_save_filter: " + ex.Message)); }// <<< result = recMan.DeleteRecord(entityName, recordId); connection.CommitTransaction(); } catch (Exception ex) { connection.RollbackTransaction(); var response = new ResponseModel(); response.Success = false; response.Timestamp = DateTime.UtcNow; response.Message = "Error while delete the record: " + ex.Message; response.Object = null; return Json(response); } } ////////////////////////////////////////////////////////////////////////////////////// //WEBHOOK ACTION << delete_record_success_action >> ////////////////////////////////////////////////////////////////////////////////////// try { dynamic hookActionObj = new ExpandoObject(); hookActionObj.recordId = recordId; hookActionObj.result = result; hookActionObj.controller = this; hooksService.ProcessActions(SystemWebHookNames.DeleteRecordAction, entityName, hookActionObj); } catch (Exception ex) { return Json(CreateErrorResponse("Plugin error in web hook delete_record_success_action: " + ex.Message)); }// <<< return DoResponse(result); }
public QueryResponse DeleteRecord(Entity entity, Guid id) { QueryResponse response = new QueryResponse(); response.Object = null; response.Success = true; response.Timestamp = DateTime.UtcNow; try { if (entity == null) { response.Errors.Add(new ErrorModel { Message = "Invalid entity name." }); response.Success = false; return response; } if (!ignoreSecurity) { bool hasPermisstion = SecurityContext.HasEntityPermission(EntityPermission.Delete, entity); if (!hasPermisstion) { response.StatusCode = HttpStatusCode.Forbidden; response.Success = false; response.Message = "Trying to delete record in entity '" + entity.Name + "' with no delete access."; response.Errors.Add(new ErrorModel { Message = "Access denied." }); return response; } } List<KeyValuePair<string, object>> storageRecordData = new List<KeyValuePair<string, object>>(); var query = EntityQuery.QueryEQ("id", id); var entityQuery = new EntityQuery(entity.Name, "*", query); response = Find(entityQuery); if (response.Object != null && response.Object.Data.Count == 1) { DbContext.Current.RecordRepository.Delete(entity.Name, id); } else { response.Success = false; response.Message = "Record was not found."; return response; } return response; } catch (Exception e) { response.Success = false; response.Object = null; response.Timestamp = DateTime.UtcNow; #if DEBUG response.Message = e.Message + e.StackTrace; #else response.Message = "The entity record was not update. An internal error occurred!"; #endif return response; } }
public QueryResponse Find(EntityQuery query) { QueryResponse response = new QueryResponse { Success = true, Message = "The query was successfully executed.", Timestamp = DateTime.UtcNow }; try { var entity = GetEntity(query.EntityName); if (entity == null) { response.Success = false; response.Message = string.Format("The query is incorrect. Specified entity '{0}' does not exist.", query.EntityName); response.Object = null; response.Errors.Add(new ErrorModel { Message = response.Message }); response.Timestamp = DateTime.UtcNow; return response; } if (!ignoreSecurity) { bool hasPermisstion = SecurityContext.HasEntityPermission(EntityPermission.Read, entity); if (!hasPermisstion) { response.StatusCode = HttpStatusCode.Forbidden; response.Success = false; response.Message = "Trying to read records from entity '" + entity.Name + "' with no read access."; response.Errors.Add(new ErrorModel { Message = "Access denied." }); return response; } } //try //{ // if (query.Query != null) // ProcessQueryObject(entity, query.Query); //} //catch (Exception ex) //{ // response.Success = false; // response.Message = "The query is incorrect and cannot be executed."; // response.Object = null; // response.Errors.Add(new ErrorModel { Message = ex.Message }); // response.Timestamp = DateTime.UtcNow; // return response; //} var fields = DbContext.Current.RecordRepository.ExtractQueryFieldsMeta(query); var data = DbContext.Current.RecordRepository.Find(query); response.Object = new QueryResult { FieldsMeta = fields, Data = data }; } catch (Exception ex) { response.Success = false; response.Message = "The query is incorrect and cannot be executed"; response.Object = null; response.Errors.Add(new ErrorModel { Message = ex.Message }); response.Timestamp = DateTime.UtcNow; return response; } return response; }
public IActionResult GetListFilter(string filter_id) { QueryObject filterObj = EntityQuery.QueryEQ("filter_id", filter_id); EntityQuery queryFilterEntity = new EntityQuery("filter", "*", filterObj, null, null, null); QueryResponse resultFilters = recMan.Find(queryFilterEntity); if (!resultFilters.Success) return DoResponse(resultFilters); List<EntityRecord> filterRecords = new List<EntityRecord>(); if (resultFilters.Object.Data != null && resultFilters.Object.Data.Any()) { filterRecords = resultFilters.Object.Data; } var response = new QueryResponse(); response.Success = true; response.Message = "Query successfully executed"; response.Object.Data = filterRecords; return Json(response); }
public QueryResponse UpdateRecord(Entity entity, EntityRecord record, bool skipRecordReturn = false) { QueryResponse response = new QueryResponse(); response.Object = null; response.Success = true; response.Timestamp = DateTime.UtcNow; using (DbConnection connection = DbContext.Current.CreateConnection()) { bool isTransactionActive = false; try { if (entity == null) response.Errors.Add(new ErrorModel { Message = "Invalid entity name." }); if (record == null) response.Errors.Add(new ErrorModel { Message = "Invalid record. Cannot be null." }); else if (!record.Properties.ContainsKey("id")) response.Errors.Add(new ErrorModel { Message = "Invalid record. Missing ID field." }); if (response.Errors.Count > 0) { response.Object = null; response.Success = false; response.Timestamp = DateTime.UtcNow; return response; } if (!ignoreSecurity) { bool hasPermisstion = SecurityContext.HasEntityPermission(EntityPermission.Update, entity); if (!hasPermisstion) { response.StatusCode = HttpStatusCode.Forbidden; response.Success = false; response.Message = "Trying to update record in entity '" + entity.Name + "' with no update access."; response.Errors.Add(new ErrorModel { Message = "Access denied." }); return response; } } SetRecordServiceInformation(record, false, ignoreSecurity); //fixes issue with ID comming from webapi request Guid recordId = Guid.Empty; if (record["id"] is string) recordId = new Guid(record["id"] as string); else if (record["id"] is Guid) recordId = (Guid)record["id"]; else throw new Exception("Invalid record id"); if (record.Properties.Any(p => p.Key.StartsWith("$"))) { connection.BeginTransaction(); isTransactionActive = true; } QueryObject filterObj = EntityQuery.QueryEQ("id", recordId); var oldRecordResponse = Find(new EntityQuery(entity.Name, "*", filterObj, null, null, null)); if (!oldRecordResponse.Success) throw new Exception(oldRecordResponse.Message); else if (oldRecordResponse.Object.Data.Count == 0) { throw new Exception("Record with such Id is not found"); } var oldRecord = oldRecordResponse.Object.Data[0]; List<KeyValuePair<string, object>> storageRecordData = new List<KeyValuePair<string, object>>(); List<dynamic> oneToOneRecordData = new List<dynamic>(); List<dynamic> oneToManyRecordData = new List<dynamic>(); List<dynamic> manyToManyRecordData = new List<dynamic>(); Dictionary<string, EntityRecord> fieldsFromRelationList = new Dictionary<string, EntityRecord>(); Dictionary<string, EntityRecord> relationFieldMetaList = new Dictionary<string, EntityRecord>(); foreach (var pair in record.GetProperties()) { try { if (pair.Key == null) continue; if (pair.Key.Contains(RELATION_SEPARATOR)) { var relations = GetRelations(); var relationData = pair.Key.Split(RELATION_SEPARATOR).Select(x => x.Trim()).Where(x => !string.IsNullOrWhiteSpace(x)).ToList(); if (relationData.Count > 2) throw new Exception(string.Format("The specified field name '{0}' is incorrect. Only first level relation can be specified.", pair.Key)); string relationName = relationData[0]; string relationFieldName = relationData[1]; string direction = "origin-target"; if (string.IsNullOrWhiteSpace(relationName) || relationName == "$" || relationName == "$$") throw new Exception(string.Format("Invalid relation '{0}'. The relation name is not specified.", pair.Key)); else if (!relationName.StartsWith("$")) throw new Exception(string.Format("Invalid relation '{0}'. The relation name is not correct.", pair.Key)); else relationName = relationName.Substring(1); //check for target priority mark $$ if (relationName.StartsWith("$")) { direction = "target-origin"; relationName = relationName.Substring(1); } if (string.IsNullOrWhiteSpace(relationFieldName)) throw new Exception(string.Format("Invalid relation '{0}'. The relation field name is not specified.", pair.Key)); var relation = relations.SingleOrDefault(x => x.Name == relationName); if (relation == null) throw new Exception(string.Format("Invalid relation '{0}'. The relation does not exist.", pair.Key)); if (relation.TargetEntityId != entity.Id && relation.OriginEntityId != entity.Id) throw new Exception(string.Format("Invalid relation '{0}'. The relation field belongs to entity that does not relate to current entity.", pair.Key)); Entity relationEntity = null; Field relationField = null; Field realtionSearchField; Field field = null; if (relation.OriginEntityId == relation.TargetEntityId) { if (direction == "origin-target") { relationEntity = entity; relationField = relationEntity.Fields.FirstOrDefault(f => f.Id == relation.TargetFieldId); realtionSearchField = relationEntity.Fields.FirstOrDefault(f => f.Name == relationFieldName); field = entity.Fields.FirstOrDefault(f => f.Id == relation.OriginFieldId); } else { relationEntity = entity; relationField = relationEntity.Fields.FirstOrDefault(f => f.Id == relation.OriginFieldId); realtionSearchField = relationEntity.Fields.FirstOrDefault(f => f.Name == relationFieldName); field = entity.Fields.FirstOrDefault(f => f.Id == relation.TargetFieldId); } } else if (relation.OriginEntityId == entity.Id) { //direction doesn't matter relationEntity = GetEntity(relation.TargetEntityId); relationField = relationEntity.Fields.FirstOrDefault(f => f.Id == relation.TargetFieldId); realtionSearchField = relationEntity.Fields.FirstOrDefault(f => f.Name == relationFieldName); field = entity.Fields.FirstOrDefault(f => f.Id == relation.OriginFieldId); } else { //direction doesn't matter relationEntity = GetEntity(relation.OriginEntityId); relationField = relationEntity.Fields.FirstOrDefault(f => f.Id == relation.OriginFieldId); realtionSearchField = relationEntity.Fields.FirstOrDefault(f => f.Name == relationFieldName); field = entity.Fields.FirstOrDefault(f => f.Id == relation.TargetFieldId); } if (realtionSearchField == null) throw new Exception(string.Format("Invalid relation '{0}'. Field does not exist.", pair.Key)); if (realtionSearchField.GetFieldType() == FieldType.MultiSelectField || realtionSearchField.GetFieldType() == FieldType.TreeSelectField) throw new Exception(string.Format("Invalid relation '{0}'. Fields from Multiselect and Treeselect types can't be used as relation fields.", pair.Key)); QueryObject filter = null; if ((relation.RelationType == EntityRelationType.OneToMany && relation.OriginEntityId == relation.TargetEntityId && direction == "origin-target") || (relation.RelationType == EntityRelationType.OneToMany && relation.OriginEntityId != relation.TargetEntityId && relation.OriginEntityId == entity.Id) || relation.RelationType == EntityRelationType.ManyToMany) { //expect array of values if (!record.Properties.ContainsKey(field.Name) || record[field.Name] == null) throw new Exception(string.Format("Invalid relation '{0}'. Relation field does not exist into input record data or its value is null.", pair.Key)); List<string> values = new List<string>(); if (pair.Value is JArray) values = ((JArray)pair.Value).Select(x => ((JToken)x).Value<string>()).ToList<string>(); else if (pair.Value is List<object>) values = ((List<object>)pair.Value).Select(x => ((object)x).ToString()).ToList<string>(); else if (pair.Value is List<Guid>) values = ((List<Guid>)pair.Value).Select(x => ((Guid)x).ToString()).ToList<string>(); else if (pair.Value is List<string>) values = (List<string>)pair.Value; else if (pair.Value != null) values.Add(pair.Value.ToString()); if (relation.RelationType == EntityRelationType.ManyToMany) { Guid? originFieldOldValue = (Guid)oldRecord[field.Name]; Guid? targetFieldOldValue = null; if (relation.TargetEntityId == entity.Id) { originFieldOldValue = null; targetFieldOldValue = (Guid)oldRecord[field.Name]; } var mmResponse = RemoveRelationManyToManyRecord(relation.Id, originFieldOldValue, targetFieldOldValue); if (!mmResponse.Success) throw new Exception(mmResponse.Message); } if (values.Count < 1) continue; List<QueryObject> queries = new List<QueryObject>(); foreach (var val in values) { queries.Add(EntityQuery.QueryEQ(realtionSearchField.Name, val)); } filter = EntityQuery.QueryOR(queries.ToArray()); } else { filter = EntityQuery.QueryEQ(realtionSearchField.Name, ExtractFieldValue(pair, realtionSearchField, true)); } EntityRecord relationFieldMeta = new EntityRecord(); relationFieldMeta["key"] = pair.Key; relationFieldMeta["direction"] = direction; relationFieldMeta["relationName"] = relationName; relationFieldMeta["relationEntity"] = relationEntity; relationFieldMeta["relationField"] = relationField; relationFieldMeta["realtionSearchField"] = realtionSearchField; relationFieldMeta["field"] = field; relationFieldMetaList[pair.Key] = relationFieldMeta; EntityRecord fieldsFromRelation = new EntityRecord(); if (fieldsFromRelationList.Any(r => r.Key == relation.Name)) { fieldsFromRelation = fieldsFromRelationList[relationName]; } else { fieldsFromRelation["queries"] = new List<QueryObject>(); fieldsFromRelation["direction"] = direction; fieldsFromRelation["relationEntityName"] = relationEntity.Name; } ((List<QueryObject>)fieldsFromRelation["queries"]).Add(filter); fieldsFromRelationList[relationName] = fieldsFromRelation; } } catch (Exception ex) { if (pair.Key != null) throw new Exception("Error during processing value for field: '" + pair.Key + "'. Invalid value: '" + pair.Value + "'", ex); } } foreach (var fieldsFromRelation in fieldsFromRelationList) { EntityRecord fieldsFromRelationValue = (EntityRecord)fieldsFromRelation.Value; List<QueryObject> queries = (List<QueryObject>)fieldsFromRelationValue["queries"]; string direction = (string)fieldsFromRelationValue["direction"]; string relationEntityName = (string)fieldsFromRelationValue["relationEntityName"]; QueryObject filter = EntityQuery.QueryAND(queries.ToArray()); var relation = relations.SingleOrDefault(r => r.Name == fieldsFromRelation.Key); //get related records QueryResponse relatedRecordResponse = Find(new EntityQuery(relationEntityName, "*", filter, null, null, null)); if (!relatedRecordResponse.Success || relatedRecordResponse.Object.Data.Count < 1) { throw new Exception(string.Format("Invalid relation '{0}'. The relation record does not exist.", relationEntityName)); } else if (relatedRecordResponse.Object.Data.Count > 1 && ((relation.RelationType == EntityRelationType.OneToMany && relation.OriginEntityId == relation.TargetEntityId && direction == "target-origin") || (relation.RelationType == EntityRelationType.OneToMany && relation.OriginEntityId != relation.TargetEntityId && relation.TargetEntityId == entity.Id) || relation.RelationType == EntityRelationType.OneToOne)) { //there can be no more than 1 records throw new Exception(string.Format("Invalid relation '{0}'. There are multiple relation records matching this value.", relationEntityName)); } ((EntityRecord)fieldsFromRelationList[fieldsFromRelation.Key])["relatedRecordResponse"] = relatedRecordResponse; } foreach (var pair in record.GetProperties()) { try { if (pair.Key == null) continue; if (pair.Key.Contains(RELATION_SEPARATOR)) { EntityRecord relationFieldMeta = relationFieldMetaList.FirstOrDefault(f => f.Key == pair.Key).Value; if (relationFieldMeta == null) continue; string direction = (string)relationFieldMeta["direction"]; string relationName = (string)relationFieldMeta["relationName"]; Entity relationEntity = (Entity)relationFieldMeta["relationEntity"]; Field relationField = (Field)relationFieldMeta["relationField"]; Field realtionSearchField = (Field)relationFieldMeta["realtionSearchField"]; Field field = (Field)relationFieldMeta["field"]; var relation = relations.SingleOrDefault(r => r.Name == relationName); QueryResponse relatedRecordResponse = (QueryResponse)((EntityRecord)fieldsFromRelationList[relationName])["relatedRecordResponse"]; var relatedRecords = relatedRecordResponse.Object.Data; List<Guid> relatedRecordValues = new List<Guid>(); foreach (var relatedRecord in relatedRecords) { relatedRecordValues.Add((Guid)relatedRecord[relationField.Name]); } if (relation.RelationType == EntityRelationType.OneToOne && ((relation.OriginEntityId == relation.TargetEntityId && direction == "origin-target") || relation.OriginEntityId == entity.Id)) { if (!record.Properties.ContainsKey(field.Name) || record[field.Name] == null) throw new Exception(string.Format("Invalid relation '{0}'. Relation field does not exist into input record data or its value is null.", pair.Key)); var relatedRecord = relatedRecords[0]; List<KeyValuePair<string, object>> relRecordData = new List<KeyValuePair<string, object>>(); relRecordData.Add(new KeyValuePair<string, object>("id", relatedRecord["id"])); relRecordData.Add(new KeyValuePair<string, object>(relationField.Name, record[field.Name])); dynamic ooRelationData = new ExpandoObject(); ooRelationData.RelationId = relation.Id; ooRelationData.RecordData = relRecordData; ooRelationData.EntityName = relationEntity.Name; oneToOneRecordData.Add(ooRelationData); } else if (relation.RelationType == EntityRelationType.OneToMany && ((relation.OriginEntityId == relation.TargetEntityId && direction == "origin-target") || relation.OriginEntityId == entity.Id)) { if (!record.Properties.ContainsKey(field.Name) || record[field.Name] == null) throw new Exception(string.Format("Invalid relation '{0}'. Relation field does not exist into input record data or its value is null.", pair.Key)); foreach (var data in relatedRecordResponse.Object.Data) { List<KeyValuePair<string, object>> relRecordData = new List<KeyValuePair<string, object>>(); relRecordData.Add(new KeyValuePair<string, object>("id", data["id"])); relRecordData.Add(new KeyValuePair<string, object>(relationField.Name, record[field.Name])); dynamic omRelationData = new ExpandoObject(); omRelationData.RelationId = relation.Id; omRelationData.RecordData = relRecordData; omRelationData.EntityName = relationEntity.Name; oneToManyRecordData.Add(omRelationData); } } else if (relation.RelationType == EntityRelationType.ManyToMany) { foreach (Guid relatedRecordIdValue in relatedRecordValues) { Guid relRecordId = Guid.Empty; if (record[field.Name] is string) relRecordId = new Guid(record[field.Name] as string); else if (record[field.Name] is Guid) relRecordId = (Guid)record[field.Name]; else throw new Exception("Invalid record value for field: '" + pair.Key + "'. Invalid value: '" + pair.Value + "'"); Guid originFieldValue = relRecordId; Guid targetFieldValue = relatedRecordIdValue; if (relation.TargetEntityId == entity.Id) { originFieldValue = relatedRecordIdValue; targetFieldValue = relRecordId; } dynamic mmRelationData = new ExpandoObject(); mmRelationData.RelationId = relation.Id; mmRelationData.OriginFieldValue = originFieldValue; mmRelationData.TargetFieldValue = targetFieldValue; if (!manyToManyRecordData.Any(r => r.RelationId == mmRelationData.RelationId && r.OriginFieldValue == mmRelationData.OriginFieldValue && r.TargetFieldValue == mmRelationData.TargetFieldValue)) manyToManyRecordData.Add(mmRelationData); } } else { if (!storageRecordData.Any(r => r.Key == field.Name)) storageRecordData.Add(new KeyValuePair<string, object>(field.Name, relatedRecordValues[0])); } } else { //locate the field var field = entity.Fields.SingleOrDefault(x => x.Name == pair.Key); if (field is PasswordField && pair.Value == null) continue; if (field is AutoNumberField && pair.Value == null) continue; if (!storageRecordData.Any(r => r.Key == field.Name)) storageRecordData.Add(new KeyValuePair<string, object>(field.Name, ExtractFieldValue(pair, field, true))); } } catch (Exception ex) { if (pair.Key != null) throw new Exception("Error during processing value for field: '" + pair.Key + "'. Invalid value: '" + pair.Value + "'", ex); } } var recRepo = DbContext.Current.RecordRepository; recRepo.Update(entity.Name, storageRecordData); foreach (var ooRelData in oneToOneRecordData) { recRepo.Update(ooRelData.EntityName, ooRelData.RecordData); } foreach (var omRelData in oneToManyRecordData) { recRepo.Update(omRelData.EntityName, omRelData.RecordData); } foreach (var mmRelData in manyToManyRecordData) { var mmResponse = CreateRelationManyToManyRecord(mmRelData.RelationId, mmRelData.OriginFieldValue, mmRelData.TargetFieldValue); if (!mmResponse.Success) throw new Exception(mmResponse.Message); } if (skipRecordReturn) { response.Object = null; response.Success = true; response.Message = "Record was updated successfully"; if (isTransactionActive) connection.CommitTransaction(); return response; } var query = EntityQuery.QueryEQ("id", recordId); var entityQuery = new EntityQuery(entity.Name, "*", query); response = Find(entityQuery); if (response.Object != null && response.Object.Data.Count > 0) response.Message = "Record was updated successfully"; else { response.Success = false; response.Message = "Record was not updated successfully"; } if (isTransactionActive) connection.CommitTransaction(); return response; } catch (Exception e) { if (isTransactionActive) connection.RollbackTransaction(); response.Success = false; response.Object = null; response.Timestamp = DateTime.UtcNow; #if DEBUG response.Message = e.Message + e.StackTrace; #else response.Message = "The entity record was not update. An internal error occurred!"; #endif return response; } } }
public IActionResult DeleteAreaRecord(Guid recordId) { QueryResponse response = new QueryResponse(); //Begin transaction var recRep = Storage.GetRecordRepository(); var transaction = recRep.CreateTransaction(); try { transaction.Begin(); //Delete the area var areaDeleteResult = recMan.DeleteRecord("area", recordId); if (!areaDeleteResult.Success) { response.Timestamp = DateTime.UtcNow; response.Success = false; response.Message = areaDeleteResult.Message; transaction.Rollback(); return Json(response); } transaction.Commit(); } catch { transaction.Rollback(); throw; } response.Timestamp = DateTime.UtcNow; response.Success = true; response.Message = "Area successfully deleted"; return DoResponse(response); }
public IActionResult GetSitemap() { var columnsNeeded = "id,name,label,color,icon_name,weight,roles,subscriptions"; EntityQuery queryAreas = new EntityQuery("area", columnsNeeded, null, null, null, null); QueryResponse resultAreas = recMan.Find(queryAreas); if (!resultAreas.Success) return DoResponse(resultAreas); List<EntityRecord> areas = new List<EntityRecord>(); List<EntityRecord> responseAreas = new List<EntityRecord>(); if (resultAreas.Object.Data != null && resultAreas.Object.Data.Any()) { areas = resultAreas.Object.Data; foreach (EntityRecord area in areas) { if ((string)area["subscriptions"] != "[]") { responseAreas.Add(area); } } } var response = new QueryResponse(); response.Success = true; response.Message = "Query successfully executed"; if (responseAreas == new List<EntityRecord>()) { response.Object.Data = null; } else { response.Object.Data = responseAreas; } return Json(response); }
public QueryResponse Find(EntityQuery query) { QueryResponse response = new QueryResponse { Success = true, Message = "The query was successfully executed.", Timestamp = DateTime.UtcNow }; try { var entity = GetEntity(query.EntityName); if (entity == null) { response.Success = false; response.Message = string.Format("The query is incorrect. Specified entity '{0}' does not exist.", query.EntityName); response.Object = null; response.Errors.Add(new ErrorModel { Message = response.Message }); response.Timestamp = DateTime.UtcNow; return response; } if (!ignoreSecurity) { bool hasPermisstion = SecurityContext.HasEntityPermission(EntityPermission.Read, entity); if (!hasPermisstion) { response.StatusCode = HttpStatusCode.Forbidden; response.Success = false; response.Message = "Trying to read records from entity '" + entity.Name + "' with no read access."; response.Errors.Add(new ErrorModel { Message = "Access denied." }); return response; } } try { if (query.Query != null) ProcessQueryObject(entity, query.Query); } catch (Exception ex) { response.Success = false; response.Message = "The query is incorrect and cannot be executed."; response.Object = null; response.Errors.Add(new ErrorModel { Message = ex.Message }); response.Timestamp = DateTime.UtcNow; return response; } List<Field> fields = ExtractQueryFieldsMeta(query); var recRepo = erpService.StorageService.GetRecordRepository(); var storageRecords = recRepo.Find(query.EntityName, query.Query, query.Sort, query.Skip, query.Limit); Hashtable relationDataCache = new Hashtable(); List<EntityRecord> data = new List<EntityRecord>(); foreach (var record in storageRecords) { var dataRecord = new EntityRecord(); foreach (var field in fields) { var recValue = record.SingleOrDefault(x => x.Key == field.Name); if (!(field is RelationFieldMeta)) { dataRecord[field.Name] = ExtractFieldValue(recValue, field); } else //relation field { RelationFieldMeta relationField = (RelationFieldMeta)field; if (relationField.Relation.RelationType == EntityRelationType.OneToOne) { IEnumerable<KeyValuePair<string, object>> relatedStorageRecord = null; //when the relation is origin -> target entity if (relationField.Relation.OriginEntityId == entity.Id) { recValue = record.SingleOrDefault(x => x.Key == relationField.OriginField.Name); if (recValue.Value != null) { var cacheKey = relationField.Relation.Name + ":" + recValue.Value; relatedStorageRecord = relationDataCache[cacheKey] as IEnumerable<KeyValuePair<string, object>>; if (relatedStorageRecord == null) { var relQuery = EntityQuery.QueryEQ(relationField.TargetField.Name, recValue.Value); relatedStorageRecord = recRepo.Find(relationField.TargetEntity.Name, relQuery, null, 0, 1).SingleOrDefault(); relationDataCache[cacheKey] = relatedStorageRecord; } } } else //when the relation is target -> origin, we have to query origin entity { recValue = record.SingleOrDefault(x => x.Key == relationField.TargetField.Name); if (recValue.Value != null) { var cacheKey = relationField.Relation.Name + ":" + recValue.Value; relatedStorageRecord = relationDataCache[cacheKey] as IEnumerable<KeyValuePair<string, object>>; if (relatedStorageRecord == null) { var relQuery = EntityQuery.QueryEQ(relationField.OriginField.Name, recValue.Value); relatedStorageRecord = recRepo.Find(relationField.OriginEntity.Name, relQuery, null, 0, 1).SingleOrDefault(); relationDataCache[cacheKey] = relatedStorageRecord; } } } var dataArrayRecord = new List<EntityRecord>(); if (relatedStorageRecord != null) { var relatedObject = new EntityRecord(); foreach (var relField in relationField.Fields) { var relValue = relatedStorageRecord.SingleOrDefault(x => x.Key == relField.Name); relatedObject[relField.Name] = ExtractFieldValue(relValue, relField); } dataArrayRecord.Add(relatedObject); } dataRecord[field.Name] = dataArrayRecord; } else if (relationField.Relation.RelationType == EntityRelationType.OneToMany) { IEnumerable<IEnumerable<KeyValuePair<string, object>>> relatedStorageRecords = null; if (relationField.Relation.OriginEntityId != relationField.Relation.TargetEntityId) { if (relationField.Relation.OriginEntityId == entity.Id) { recValue = record.SingleOrDefault(x => x.Key == relationField.OriginField.Name); if (recValue.Value != null) { var cacheKey = relationField.Relation.Name + ":" + recValue.Value; relatedStorageRecords = relationDataCache[cacheKey] as IEnumerable<IEnumerable<KeyValuePair<string, object>>>; if (relatedStorageRecords == null) { var relQuery = EntityQuery.QueryEQ(relationField.TargetField.Name, recValue.Value); relatedStorageRecords = recRepo.Find(relationField.TargetEntity.Name, relQuery, null, null, null); relationDataCache[cacheKey] = relatedStorageRecords; } } } else //when the relation is target -> origin, we have to query origin entity { recValue = record.SingleOrDefault(x => x.Key == relationField.TargetField.Name); if (recValue.Value != null) { var cacheKey = relationField.Relation.Name + ":" + recValue.Value; relatedStorageRecords = relationDataCache[cacheKey] as IEnumerable<IEnumerable<KeyValuePair<string, object>>>; if (relatedStorageRecords == null) { var relQuery = EntityQuery.QueryEQ(relationField.OriginField.Name, recValue.Value); relatedStorageRecords = recRepo.Find(relationField.OriginEntity.Name, relQuery, null, null, null); relationDataCache[cacheKey] = relatedStorageRecords; } } } } else { if (relationField.Direction == "target-origin") { recValue = record.SingleOrDefault(x => x.Key == relationField.TargetField.Name); if (recValue.Value != null) { var cacheKey = relationField.Relation.Name + ":" + recValue.Value + ":" + relationField.Direction; relatedStorageRecords = relationDataCache[cacheKey] as IEnumerable<IEnumerable<KeyValuePair<string, object>>>; if (relatedStorageRecords == null) { var relQuery = EntityQuery.QueryEQ(relationField.OriginField.Name, recValue.Value); relatedStorageRecords = recRepo.Find(relationField.OriginEntity.Name, relQuery, null, null, null); relationDataCache[cacheKey] = relatedStorageRecords; } } } else { recValue = record.SingleOrDefault(x => x.Key == relationField.OriginField.Name); if (recValue.Value != null) { var cacheKey = relationField.Relation.Name + ":" + recValue.Value + ":" + relationField.Direction; relatedStorageRecords = relationDataCache[cacheKey] as IEnumerable<IEnumerable<KeyValuePair<string, object>>>; if (relatedStorageRecords == null) { var relQuery = EntityQuery.QueryEQ(relationField.TargetField.Name, recValue.Value); relatedStorageRecords = recRepo.Find(relationField.TargetEntity.Name, relQuery, null, null, null); relationDataCache[cacheKey] = relatedStorageRecords; } } } } var dataArrayRecord = new List<EntityRecord>(); if (relatedStorageRecords != null) { foreach (var relatedStorageRecord in relatedStorageRecords) { var relatedObject = new EntityRecord(); foreach (var relField in relationField.Fields) { var relValue = relatedStorageRecord.SingleOrDefault(x => x.Key == relField.Name); relatedObject[relField.Name] = ExtractFieldValue(relValue, relField); } dataArrayRecord.Add(relatedObject); } } dataRecord[field.Name] = dataArrayRecord; } else if (relationField.Relation.RelationType == EntityRelationType.ManyToMany) { List<IEnumerable<KeyValuePair<string, object>>> relatedStorageRecords = null; if (relationField.Relation.OriginEntityId == relationField.Relation.TargetEntityId) { if (relationField.Direction == "target-origin") { recValue = record.SingleOrDefault(x => x.Key == relationField.TargetField.Name); if (recValue.Value != null) { var cacheKey = relationField.Relation.Name + ":" + recValue.Value + ":" + relationField.Direction; relatedStorageRecords = relationDataCache[cacheKey] as List<IEnumerable<KeyValuePair<string, object>>>; if (relatedStorageRecords == null) { var targetEntity = GetEntity(relationField.Relation.TargetEntityId); var targetField = targetEntity.Fields.Single(x => x.Id == relationField.Relation.TargetFieldId); var relatedRecord = recRepo.Find(targetEntity.Name, EntityQuery.QueryEQ(targetField.Name, (Guid)recValue.Value), null, null, null); if (relatedRecord.Count() > 1) throw new Exception("There are more than 1 record in entity field that should be unique and used for relation."); if (relatedRecord.Count() == 1) { var relationData = record.SingleOrDefault(x => x.Key == $"#{relationField.Relation.Name}_origins"); List<object> relatedRecordIds = relationData.Value as List<object>; relatedStorageRecords = new List<IEnumerable<KeyValuePair<string, object>>>(); if (relatedRecordIds != null) { foreach (Guid id in relatedRecordIds) { var relQuery = EntityQuery.QueryEQ(relationField.OriginField.Name, id); var relatedStorageRecord = recRepo.Find(relationField.OriginEntity.Name, relQuery, null, null, null).FirstOrDefault(); if (relatedStorageRecord != null) relatedStorageRecords.Add(relatedStorageRecord); } } } relationDataCache[cacheKey] = relatedStorageRecords; } } } else { recValue = record.SingleOrDefault(x => x.Key == relationField.OriginField.Name); if (recValue.Value != null) { var cacheKey = relationField.Relation.Name + ":" + recValue.Value + ":" + relationField.Direction; relatedStorageRecords = relationDataCache[cacheKey] as List<IEnumerable<KeyValuePair<string, object>>>; if (relatedStorageRecords == null) { var relationData = record.SingleOrDefault(x => x.Key == $"#{relationField.Relation.Name}_targets"); if (relationData.Key != null) { List<object> relatedRecordIds = relationData.Value as List<object>; relatedStorageRecords = new List<IEnumerable<KeyValuePair<string, object>>>(); if (relatedRecordIds != null) { foreach (Guid id in relatedRecordIds) { var relQuery = EntityQuery.QueryEQ(relationField.TargetField.Name, id); var relatedStorageRecord = recRepo.Find(relationField.TargetEntity.Name, relQuery, null, null, null).FirstOrDefault(); if (relatedStorageRecord != null) relatedStorageRecords.Add(relatedStorageRecord); } } } relationDataCache[cacheKey] = relatedStorageRecords; } } } } else if (relationField.Relation.OriginEntityId == entity.Id) { recValue = record.SingleOrDefault(x => x.Key == relationField.OriginField.Name); if (recValue.Value != null) { var cacheKey = relationField.Relation.Name + ":" + recValue.Value + ":" + relationField.Direction; relatedStorageRecords = relationDataCache[cacheKey] as List<IEnumerable<KeyValuePair<string, object>>>; if (relatedStorageRecords == null) { var relationData = record.SingleOrDefault(x => x.Key == $"#{relationField.Relation.Name}_targets"); if (relationData.Key != null) { List<object> relatedRecordIds = relationData.Value as List<object>; relatedStorageRecords = new List<IEnumerable<KeyValuePair<string, object>>>(); if (relatedRecordIds != null) { foreach (Guid id in relatedRecordIds) { var relQuery = EntityQuery.QueryEQ(relationField.TargetField.Name, id); var relatedStorageRecord = recRepo.Find(relationField.TargetEntity.Name, relQuery, null, null, null).FirstOrDefault(); if (relatedStorageRecord != null) relatedStorageRecords.Add(relatedStorageRecord); } } } relationDataCache[cacheKey] = relatedStorageRecords; } } } else //when the relation is target -> origin, we have to query origin entity { recValue = record.SingleOrDefault(x => x.Key == relationField.TargetField.Name); if (recValue.Value != null) { var cacheKey = relationField.Relation.Name + ":" + recValue.Value + ":" + relationField.Direction; relatedStorageRecords = relationDataCache[cacheKey] as List<IEnumerable<KeyValuePair<string, object>>>; if (relatedStorageRecords == null) { var targetEntity = GetEntity(relationField.Relation.TargetEntityId); var targetField = targetEntity.Fields.Single(x => x.Id == relationField.Relation.TargetFieldId); var relatedRecord = recRepo.Find(targetEntity.Name, EntityQuery.QueryEQ(targetField.Name, (Guid)recValue.Value), null, null, null); if (relatedRecord.Count() > 1) throw new Exception("There are more than 1 record in entity field that should be unique and used for relation."); if (relatedRecord.Count() == 1) { var relationData = record.SingleOrDefault(x => x.Key == $"#{relationField.Relation.Name}_origins"); List<object> relatedRecordIds = relationData.Value as List<object>; //List<Guid> relatedRecordIds = entityRelationRepository.ReadManyToManyRecordByTarget(relationField.Relation.Id, (Guid)recValue.Value); relatedStorageRecords = new List<IEnumerable<KeyValuePair<string, object>>>(); if (relatedRecordIds != null) { foreach (Guid id in relatedRecordIds) { var relQuery = EntityQuery.QueryEQ(relationField.OriginField.Name, id); var relatedStorageRecord = recRepo.Find(relationField.OriginEntity.Name, relQuery, null, null, null).FirstOrDefault(); if (relatedStorageRecord != null) relatedStorageRecords.Add(relatedStorageRecord); } } } relationDataCache[cacheKey] = relatedStorageRecords; } } } var dataArrayRecord = new List<EntityRecord>(); if (relatedStorageRecords != null) { foreach (var relatedStorageRecord in relatedStorageRecords) { var relatedObject = new EntityRecord(); foreach (var relField in relationField.Fields) { var relValue = relatedStorageRecord.SingleOrDefault(x => x.Key == relField.Name); relatedObject[relField.Name] = ExtractFieldValue(relValue, relField); } dataArrayRecord.Add(relatedObject); } } dataRecord[field.Name] = dataArrayRecord; } } } data.Add(dataRecord); } response.Object = new QueryResult { FieldsMeta = fields, Data = data }; } catch (Exception ex) { response.Success = false; response.Message = "The query is incorrect and cannot be executed"; response.Object = null; response.Errors.Add(new ErrorModel { Message = ex.Message }); response.Timestamp = DateTime.UtcNow; return response; } return response; }
public IActionResult LastUpdatedTasksUserOwns(int page = 1) { var response = new ResponseModel(); try { //var queryString = HttpContext.Request.QueryString; #region << Can user read activities >> //Get current user ErpUser user = SecurityContext.CurrentUser; //Get entity meta var entity = entMan.ReadEntity("wv_task").Object; //check if user role has permissions var canRead = user.Roles.Any(x => entity.RecordPermissions.CanRead.Any(z => z == x.Id)); var canCreate = user.Roles.Any(x => entity.RecordPermissions.CanCreate.Any(z => z == x.Id)); var canUpdate = user.Roles.Any(x => entity.RecordPermissions.CanUpdate.Any(z => z == x.Id)); var canDelete = user.Roles.Any(x => entity.RecordPermissions.CanDelete.Any(z => z == x.Id)); if (!canRead) { response.Success = false; response.Message = "You do not have permission to read the tasks in this system"; response.Timestamp = DateTime.UtcNow; return Json(response); //return empty object } #endregion var taskQueryResponse = new QueryResponse(); #region << Get tasks >> { var fields = "id,number,subject,priority,last_modified_on,$user_wv_task_modified_by.username"; //Add default sort by created_on var sortRulesList = new List<QuerySortObject>(); var defaultSortRule = new QuerySortObject("last_modified_on", QuerySortType.Descending); sortRulesList.Add(defaultSortRule); #endregion var ownerFilter = EntityQuery.QueryEQ("owner_id", SecurityContext.CurrentUser.Id); var notClosedFilter = EntityQuery.QueryNOT("status", "completed"); var rootFilterSection = EntityQuery.QueryAND(ownerFilter, notClosedFilter); //Calculate page var pageSize = 5; var skipRecords = (page - 1) * pageSize; var activityQuery = new EntityQuery("wv_task", fields, rootFilterSection, sortRulesList.ToArray(), skipRecords, pageSize, null); taskQueryResponse = recMan.Find(activityQuery); if (!taskQueryResponse.Success) { response.Success = false; response.Timestamp = DateTime.UtcNow; response.Message = taskQueryResponse.Message; response.Object = null; return Json(response); } } response.Success = true; response.Timestamp = DateTime.UtcNow; response.Message = "Successful read"; response.Object = taskQueryResponse.Object.Data; return Json(response); } catch (Exception ex) { response.Success = false; response.Timestamp = DateTime.UtcNow; response.Message = ex.Message; response.Object = null; return Json(response); } }
public QueryResponse DeleteRecord(Entity entity, Guid id) { QueryResponse response = new QueryResponse(); response.Object = null; response.Success = true; response.Timestamp = DateTime.UtcNow; try { if (entity == null) { response.Errors.Add(new ErrorModel { Message = "Invalid entity name." }); response.Success = false; return response; } List<KeyValuePair<string, object>> storageRecordData = new List<KeyValuePair<string, object>>(); var query = EntityQuery.QueryEQ("id", id); var entityQuery = new EntityQuery(entity.Name, "*", query); response = Find(entityQuery); if (response.Object != null && response.Object.Data.Count == 1) { var recRepo = erpService.StorageService.GetRecordRepository(); recRepo.Delete(entity.Name, id); } else { response.Success = false; response.Message = "Record was not found."; return response; } return response; } catch (Exception e) { response.Success = false; response.Object = null; response.Timestamp = DateTime.UtcNow; #if DEBUG response.Message = e.Message + e.StackTrace; #else response.Message = "The entity record was not update. An internal error occurred!"; #endif return response; } }
public IActionResult GetRecordsByEntityName(string entityName, string ids = "", string fields = "", int? limit = null) { var response = new QueryResponse(); var recordIdList = new List<Guid>(); var fieldList = new List<string>(); if (!String.IsNullOrWhiteSpace(ids) && ids != "null") { var idStringList = ids.Split(','); var outGuid = Guid.Empty; foreach (var idString in idStringList) { if (Guid.TryParse(idString, out outGuid)) { recordIdList.Add(outGuid); } else { response.Message = "One of the record ids is not a Guid"; response.Timestamp = DateTime.UtcNow; response.Success = false; response.Object.Data = null; } } } if (!String.IsNullOrWhiteSpace(fields) && fields != "null") { var fieldsArray = fields.Split(','); var hasId = false; foreach (var fieldName in fieldsArray) { if (fieldName == "id") { hasId = true; } fieldList.Add(fieldName); } if (!hasId) { fieldList.Add("id"); } } var QueryList = new List<QueryObject>(); foreach (var recordId in recordIdList) { QueryList.Add(EntityQuery.QueryEQ("id", recordId)); } QueryObject recordsFilterObj = null; if (QueryList.Count > 0) { recordsFilterObj = EntityQuery.QueryOR(QueryList.ToArray()); } var columns = "*"; if (fieldList.Count > 0) { if (!fieldList.Contains("id")) { fieldList.Add("id"); } columns = String.Join(",", fieldList.Select(x => x.ToString()).ToArray()); } //var sortRulesList = new List<QuerySortObject>(); //var sortRule = new QuerySortObject("id",QuerySortType.Descending); //sortRulesList.Add(sortRule); //EntityQuery query = new EntityQuery(entityName, columns, recordsFilterObj, sortRulesList.ToArray(), null, null); EntityQuery query = new EntityQuery(entityName, columns, recordsFilterObj, null, null, null); if (limit != null && limit > 0) { query = new EntityQuery(entityName, columns, recordsFilterObj, null, null, limit); } var queryResponse = recMan.Find(query); if (!queryResponse.Success) { response.Message = queryResponse.Message; response.Timestamp = DateTime.UtcNow; response.Success = false; response.Object = null; return DoResponse(response); } response.Message = "Success"; response.Timestamp = DateTime.UtcNow; response.Success = true; response.Object.Data = queryResponse.Object.Data; return DoResponse(response); }
public QueryResponse Find(EntityQuery query) { QueryResponse response = new QueryResponse { Success = true, Message = "The query was successfully executed.", Timestamp = DateTime.UtcNow }; try { var entity = GetEntity(query.EntityName); if (entity == null) { response.Success = false; response.Message = string.Format("The query is incorrect. Specified entity '{0}' does not exist.", query.EntityName); response.Object = null; response.Errors.Add(new ErrorModel { Message = response.Message }); response.Timestamp = DateTime.UtcNow; return response; } try { if (query.Query != null) ProcessQueryObject(entity, query.Query); } catch (Exception ex) { response.Success = false; response.Message = "The query is incorrect and cannot be executed"; response.Object = null; response.Errors.Add(new ErrorModel { Message = ex.Message }); response.Timestamp = DateTime.UtcNow; return response; } IStorageEntityRelationRepository entityRelationRepository = erpService.StorageService.GetEntityRelationRepository(); List<Field> fields = ExtractQueryFieldsMeta(query); var recRepo = erpService.StorageService.GetRecordRepository(); var storageRecords = recRepo.Find(query.EntityName, query.Query, query.Sort, query.Skip, query.Limit); List<EntityRecord> data = new List<EntityRecord>(); foreach (var record in storageRecords) { var dataRecord = new EntityRecord(); foreach (var field in fields) { var recValue = record.SingleOrDefault(x => x.Key == field.Name); if (!(field is RelationFieldMeta)) { dataRecord[field.Name] = ExtractFieldValue(recValue, field); } else //relation field { RelationFieldMeta relationField = (RelationFieldMeta)field; if (relationField.Relation.RelationType == EntityRelationType.OneToOne) { IEnumerable<KeyValuePair<string, object>> relatedStorageRecord = null; //when the relation is origin -> target entity if (relationField.Relation.OriginEntityId == entity.Id) { recValue = record.SingleOrDefault(x => x.Key == relationField.OriginField.Name); if (recValue.Value != null) { var relQuery = EntityQuery.QueryEQ(relationField.TargetField.Name, recValue.Value); relatedStorageRecord = recRepo.Find(relationField.TargetEntity.Name, relQuery, null, 0, 1).SingleOrDefault(); } } else //when the relation is target -> origin, we have to query origin entity { recValue = record.SingleOrDefault(x => x.Key == relationField.TargetField.Name); if (recValue.Value != null) { var relQuery = EntityQuery.QueryEQ(relationField.OriginField.Name, recValue.Value); relatedStorageRecord = recRepo.Find(relationField.OriginEntity.Name, relQuery, null, 0, 1).SingleOrDefault(); } } var dataArrayRecord = new List<EntityRecord>(); if (relatedStorageRecord != null) { var relatedObject = new EntityRecord(); foreach (var relField in relationField.Fields) { var relValue = relatedStorageRecord.SingleOrDefault(x => x.Key == relField.Name); relatedObject[relField.Name] = ExtractFieldValue(relValue, relField); } dataArrayRecord.Add(relatedObject); } dataRecord[field.Name] = dataArrayRecord; } else if (relationField.Relation.RelationType == EntityRelationType.OneToMany) { IEnumerable<IEnumerable<KeyValuePair<string, object>>> relatedStorageRecords = null; //when the relation is origin -> target entity if (relationField.Relation.OriginEntityId == entity.Id) { recValue = record.SingleOrDefault(x => x.Key == relationField.OriginField.Name); if (recValue.Value != null) { var relQuery = EntityQuery.QueryEQ(relationField.TargetField.Name, recValue.Value); relatedStorageRecords = recRepo.Find(relationField.TargetEntity.Name, relQuery, null, null, null); } } else //when the relation is target -> origin, we have to query origin entity { recValue = record.SingleOrDefault(x => x.Key == relationField.TargetField.Name); if (recValue.Value != null) { var relQuery = EntityQuery.QueryEQ(relationField.OriginField.Name, recValue.Value); relatedStorageRecords = recRepo.Find(relationField.OriginEntity.Name, relQuery, null, null, null); } } var dataArrayRecord = new List<EntityRecord>(); if (relatedStorageRecords != null) { foreach (var relatedStorageRecord in relatedStorageRecords) { var relatedObject = new EntityRecord(); foreach (var relField in relationField.Fields) { var relValue = relatedStorageRecord.SingleOrDefault(x => x.Key == relField.Name); relatedObject[relField.Name] = ExtractFieldValue(relValue, relField); } dataArrayRecord.Add(relatedObject); } } dataRecord[field.Name] = dataArrayRecord; } else if (relationField.Relation.RelationType == EntityRelationType.ManyToMany) { List<IEnumerable<KeyValuePair<string, object>>> relatedStorageRecords = null; //when the relation is origin -> target entity if (relationField.Relation.OriginEntityId == entity.Id) { recValue = record.SingleOrDefault(x => x.Key == relationField.OriginField.Name); if (recValue.Value != null) { List<Guid> relatedRecordIds = entityRelationRepository.ReadManyToManyRecordByOrigin(relationField.Relation.Id, (Guid)recValue.Value); relatedStorageRecords = new List<IEnumerable<KeyValuePair<string, object>>>(); foreach (Guid id in relatedRecordIds) { var relQuery = EntityQuery.QueryEQ(relationField.TargetField.Name, id); var relatedStorageRecord = recRepo.Find(relationField.TargetEntity.Name, relQuery, null, null, null).FirstOrDefault(); if (relatedStorageRecord != null) relatedStorageRecords.Add(relatedStorageRecord); } } } else //when the relation is target -> origin, we have to query origin entity { recValue = record.SingleOrDefault(x => x.Key == relationField.TargetField.Name); if (recValue.Value != null) { List<Guid> relatedRecordIds = entityRelationRepository.ReadManyToManyRecordByTarget(relationField.Relation.Id, (Guid)recValue.Value); relatedStorageRecords = new List<IEnumerable<KeyValuePair<string, object>>>(); foreach (Guid id in relatedRecordIds) { var relQuery = EntityQuery.QueryEQ(relationField.OriginField.Name, id); var relatedStorageRecord = recRepo.Find(relationField.OriginEntity.Name, relQuery, null, null, null).FirstOrDefault(); if (relatedStorageRecord != null) relatedStorageRecords.Add(relatedStorageRecord); } } } var dataArrayRecord = new List<EntityRecord>(); if (relatedStorageRecords != null) { foreach (var relatedStorageRecord in relatedStorageRecords) { var relatedObject = new EntityRecord(); foreach (var relField in relationField.Fields) { var relValue = relatedStorageRecord.SingleOrDefault(x => x.Key == relField.Name); relatedObject[relField.Name] = ExtractFieldValue(relValue, relField); } dataArrayRecord.Add(relatedObject); } } dataRecord[field.Name] = dataArrayRecord; } } } data.Add(dataRecord); } response.Object = new QueryResult { FieldsMeta = fields, Data = data }; } catch (Exception ex) { response.Success = false; response.Message = "The query is incorrect and cannot be executed"; response.Object = null; response.Errors.Add(new ErrorModel { Message = ex.Message }); response.Timestamp = DateTime.UtcNow; return response; } return response; }
private QueryResponse CreateErrorResponse(string message) { var response = new QueryResponse(); response.Success = false; response.Timestamp = DateTime.UtcNow; response.Message = message; response.Object = null; return response; }
public QueryResponse UpdateRecord(string entityName, EntityRecord record) { if (string.IsNullOrWhiteSpace(entityName)) { QueryResponse response = new QueryResponse { Success = false, Object = null, Timestamp = DateTime.UtcNow }; response.Errors.Add(new ErrorModel { Message = "Invalid entity name." }); return response; } Entity entity = GetEntity(entityName); if (entity == null) { QueryResponse response = new QueryResponse { Success = false, Object = null, Timestamp = DateTime.UtcNow }; response.Errors.Add(new ErrorModel { Message = "Entity cannot be found." }); return response; } return UpdateRecord(entity, record); }
public IActionResult CreateEntityRecord(string entityName, [FromBody]EntityRecord postObj) { ////////////////////////////////////////////////////////////////////////////////////// //WEBHOOK FILTER << create_record_input_filter >> ////////////////////////////////////////////////////////////////////////////////////// try { dynamic hookFilterObj = new ExpandoObject(); hookFilterObj.record = postObj; hookFilterObj.controller = this; hookFilterObj = hooksService.ProcessFilters(SystemWebHookNames.CreateRecordInput, entityName, hookFilterObj); postObj = hookFilterObj.record; } catch (Exception ex) { return Json(CreateErrorResponse("Plugin error in web hook create_record_input_filter: " + ex.Message)); }// <<< var validationErrors = new List<ErrorModel>(); //TODO implement validation if (postObj == null) postObj = new EntityRecord(); ////////////////////////////////////////////////////////////////////////////////////// //WEBHOOK FILTER << create_record_validation_errors_filter >> ////////////////////////////////////////////////////////////////////////////////////// try { dynamic hookFilterObj = new ExpandoObject(); hookFilterObj.errors = validationErrors; hookFilterObj.record = postObj; hookFilterObj.controller = this; hookFilterObj = hooksService.ProcessFilters(SystemWebHookNames.CreateRecordValidationErrors, entityName, hookFilterObj); validationErrors = hookFilterObj.errors; } catch (Exception ex) { return Json(CreateErrorResponse("Plugin error in web hook create_record_validation_errors_filter: " + ex.Message)); }// <<< if (validationErrors.Count > 0) { var response = new ResponseModel(); response.Success = false; response.Timestamp = DateTime.UtcNow; response.Errors = validationErrors; response.Message = "Validation error occurred!"; response.Object = null; return Json(response); } if (!postObj.GetProperties().Any(x => x.Key == "id")) postObj["id"] = Guid.NewGuid(); else if (string.IsNullOrEmpty(postObj["id"] as string)) postObj["id"] = Guid.NewGuid(); //Create transaction var result = new QueryResponse(); using (var connection = DbContext.Current.CreateConnection()) { try { connection.BeginTransaction(); ////////////////////////////////////////////////////////////////////////////////////// //WEBHOOK FILTER << create_record_pre_save_filter >> ////////////////////////////////////////////////////////////////////////////////////// try { dynamic hookFilterObj = new ExpandoObject(); hookFilterObj.record = postObj; hookFilterObj.recordId = (Guid)postObj["id"]; hookFilterObj.controller = this; hookFilterObj = hooksService.ProcessFilters(SystemWebHookNames.CreateRecordPreSave, entityName, hookFilterObj); postObj = hookFilterObj.record; } catch (Exception ex) { connection.RollbackTransaction(); return Json(CreateErrorResponse("Plugin error in web hook create_record_pre_save_filter: " + ex.Message)); }// <<< result = recMan.CreateRecord(entityName, postObj); connection.CommitTransaction(); } catch (Exception ex) { connection.RollbackTransaction(); var response = new ResponseModel(); response.Success = false; response.Timestamp = DateTime.UtcNow; response.Message = "Error while saving the record: " + ex.Message; response.Object = null; return Json(response); } } ////////////////////////////////////////////////////////////////////////////////////// //WEBHOOK ACTION << create_record >> ////////////////////////////////////////////////////////////////////////////////////// try { dynamic hookActionObj = new ExpandoObject(); hookActionObj.record = postObj; hookActionObj.result = result; hookActionObj.controller = this; hooksService.ProcessActions(SystemWebHookNames.CreateRecordAction, entityName, hookActionObj); } catch (Exception ex) { return Json(CreateErrorResponse("Plugin error in web hook create_record_success_action: " + ex.Message)); }// <<< return DoResponse(result); }
public QueryResponse CreateRecord(Entity entity, EntityRecord record) { QueryResponse response = new QueryResponse(); response.Object = null; response.Success = true; response.Timestamp = DateTime.UtcNow; var recRepo = erpService.StorageService.GetRecordRepository(); try { if (entity == null) response.Errors.Add(new ErrorModel { Message = "Invalid entity name." }); if (record == null) response.Errors.Add(new ErrorModel { Message = "Invalid record. Cannot be null." }); if (response.Errors.Count > 0) { response.Object = null; response.Success = false; response.Timestamp = DateTime.UtcNow; return response; } if (!ignoreSecurity) { bool hasPermisstion = SecurityContext.HasEntityPermission(EntityPermission.Create, entity); if (!hasPermisstion) { response.StatusCode = HttpStatusCode.Forbidden; response.Success = false; response.Message = "Trying to create record in entity '" + entity.Name + "' with no create access."; response.Errors.Add(new ErrorModel { Message = "Access denied." }); return response; } } SetRecordServiceInformation(record, true); List<KeyValuePair<string, object>> storageRecordData = new List<KeyValuePair<string, object>>(); var recordFields = record.GetProperties(); foreach (var field in entity.Fields) { var pair = recordFields.SingleOrDefault(x => x.Key == field.Name); try { if( field is AutoNumberField ) { var maxValue = recRepo.GetAutoNumberRecordFieldMaxValue(entity.Name, field.Name); storageRecordData.Add(new KeyValuePair<string, object>(field.Name, maxValue+1)); } else storageRecordData.Add(new KeyValuePair<string, object>(field.Name, ExtractFieldValue(pair, field, true))); } catch (Exception ex) { if (pair.Key == null) throw new Exception("Error during processing value for field: '" + field.Name + "'. No value is specified."); else throw new Exception("Error during processing value for field: '" + field.Name + "'. Invalid value: '" + pair.Value + "'", ex); } } Guid recordId = Guid.Empty; if (!record.Properties.ContainsKey("id")) { recordId = Guid.NewGuid(); storageRecordData.Add(new KeyValuePair<string, object>("id", recordId)); } //fixes issue with ID comming from webapi request if (record["id"] is string) recordId = new Guid(record["id"] as string); else if (record["id"] is Guid) recordId = (Guid)record["id"]; else throw new Exception("Invalid record id"); if (recordId == Guid.Empty) throw new Exception("Guid.Empty value cannot be used as valid value for record id."); recRepo.Create(entity.Name, storageRecordData); var query = EntityQuery.QueryEQ("id", recordId); var entityQuery = new EntityQuery(entity.Name, "*", query); // when user create record, it is get returned ignoring create permissions bool oldIgnoreSecurity = ignoreSecurity; response = Find(entityQuery); ignoreSecurity = oldIgnoreSecurity; if (response.Object != null && response.Object.Data != null && response.Object.Data.Count > 0) response.Message = "Record was created successfully"; else { response.Success = false; response.Message = "Record was not created successfully"; } return response; } catch (Exception e) { response.Success = false; response.Object = null; response.Timestamp = DateTime.UtcNow; #if DEBUG response.Message = e.Message + e.StackTrace; #else response.Message = "The entity record was not created. An internal error occurred!"; #endif return response; } }