Пример #1
0
        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;
            }
        }
Пример #2
0
        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;
                }
            }
        }
Пример #3
0
		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;
			}

		}
Пример #4
0
        public ResponseModel EvaluateImportEntityRecordsFromCsv(string entityName, JObject postObject, bool enableWebHooks = true, object controller = null)
        {
            ResponseModel response = new ResponseModel();
            response.Message = "Records successfully evaluated";
            response.Timestamp = DateTime.UtcNow;
            response.Success = true;
            response.Object = null;

            List<EntityRelation> relations = relMan.Read().Object;
            EntityListResponse entitiesResponse = entMan.ReadEntities();
            List<Entity> entities = entitiesResponse.Object;
            Entity entity = entities.FirstOrDefault(e => e.Name == entityName);
            if (entity == null)
            {
                response.Success = false;
                response.Message = "Entity not found";
                return response;
            }

            var entityFields = entity.Fields;
            string fileTempPath = "";
            string clipboard = "";
            string generalCommand = "evaluate";
            EntityRecord commands = new EntityRecord();
            if (!postObject.IsNullOrEmpty() && postObject.Properties().Any(p => p.Name == "fileTempPath"))
            {
                fileTempPath = postObject["fileTempPath"].ToString();
            }

            if (!postObject.IsNullOrEmpty() && postObject.Properties().Any(p => p.Name == "clipboard"))
            {
                clipboard = postObject["clipboard"].ToString();
            }

            if (!postObject.IsNullOrEmpty() && postObject.Properties().Any(p => p.Name == "general_command"))
            {
                generalCommand = postObject["general_command"].ToString(); //could be "evaluate" & "evaluate-import" the first will just evaluate, the second one will evaluate and import if all is fine
            }

            if (!postObject.IsNullOrEmpty() && generalCommand == "evaluate-import" &&
                postObject.Properties().Any(p => p.Name == "commands") && !((JToken)postObject["commands"]).IsNullOrEmpty())
            {
                var commandsObject = postObject["commands"].Value<JObject>();
                if (!commandsObject.IsNullOrEmpty() && commandsObject.Properties().Any())
                {
                    foreach (var property in commandsObject.Properties())
                    {
                        commands[property.Name] = ((JObject)property.Value).ToObject<EntityRecord>();
                    }
                }
            }

            //VALIDATE:
            if (fileTempPath == "" && clipboard == "")
            {
                response.Success = false;
                response.Message = "Both clipboard and file CSV sources are empty!";
                return response;
            }

            CsvReader csvReader = null;
            string csvContent = "";
            bool usingClipboard = false;
            //CASE: 1 If fileTempPath != "" -> get the csv from the file
            if (fileTempPath != "")
            {
                if (fileTempPath.StartsWith("/fs"))
                    fileTempPath = fileTempPath.Remove(0, 3);

                if (!fileTempPath.StartsWith("/"))
                    fileTempPath = "/" + fileTempPath;

                fileTempPath = fileTempPath.ToLowerInvariant();

                DbFileRepository fs = new DbFileRepository();
                DbFile file = fs.Find(fileTempPath);

                if (file == null)
                {
                    response.Timestamp = DateTime.UtcNow;
                    response.Success = false;
                    response.Message = "Import failed! File does not exist!";
                    response.Errors.Add(new ErrorModel("fileTempPath", fileTempPath, "Import failed! File does not exist!"));
                    return response;
                }

                byte[] fileBytes = file.GetBytes();
                MemoryStream fileStream = new MemoryStream(fileBytes);
                TextReader reader = new StreamReader(fileStream);
                csvReader = new CsvReader(reader);
            }
            //CASE: 2 If fileTempPath == "" -> get the csv from the clipboard
            else
            {
                csvContent = clipboard;
                usingClipboard = true;
                csvReader = new CsvReader(new StringReader(csvContent));
            }

            csvReader.Configuration.HasHeaderRecord = true;
            csvReader.Configuration.IsHeaderCaseSensitive = false;
            if (usingClipboard)
            {
                csvReader.Configuration.Delimiter = "\t";
            }
            //The evaluation object has two properties - errors and warnings. Both are objects
            //The error validation object should return arrays by field name ex. {field_name:[null,null,"error message"]}
            //The warning validation object should return arrays by field name ex. {field_name:[null,null,"warning message"]}
            var evaluationObj = new EntityRecord();
            evaluationObj["errors"] = new EntityRecord();
            evaluationObj["warnings"] = new EntityRecord();
            evaluationObj["records"] = new List<EntityRecord>();
            evaluationObj["commands"] = new EntityRecord(); // the commands is object with properties the fieldNames and the following object as value {command: "to_create" | "no_import" | "to_update", fieldType: 14, fieldName: "name", fieldLabel: "label"}
            var statsObject = new EntityRecord();
            statsObject["to_create"] = 0;
            statsObject["no_import"] = 0;
            statsObject["to_update"] = 0;
            statsObject["errors"] = 0;
            statsObject["warnings"] = 0;
            evaluationObj["stats"] = statsObject;
            evaluationObj["general_command"] = generalCommand;

            csvReader.Read();
            List<string> columnNames = csvReader.FieldHeaders.ToList();
            foreach (var columnName in columnNames)
            {
                //Init the error list for this field
                if (!((EntityRecord)evaluationObj["errors"]).GetProperties().Any(p => p.Key == columnName))
                {
                    ((EntityRecord)evaluationObj["errors"])[columnName] = new List<string>();
                }
                //Init the warning list for this field
                var warningList = new List<string>();
                if (!((EntityRecord)evaluationObj["warnings"]).GetProperties().Any(p => p.Key == columnName))
                {
                    ((EntityRecord)evaluationObj["warnings"])[columnName] = new List<string>();
                }

                bool existingField = false;

                Field currentFieldMeta = null;
                Field relationEntityFieldMeta = null;
                Field relationFieldMeta = null;
                Entity relationEntity = null;
                string direction = "origin-target";
                EntityRelationType relationType = EntityRelationType.OneToMany;
                string fieldEnityName = entity.Name;
                string fieldRelationName = string.Empty;

                if (!commands.GetProperties().Any(p => p.Key == columnName))
                {
                    commands[columnName] = new EntityRecord();
                    ((EntityRecord)commands[columnName])["command"] = "no_import";
                    ((EntityRecord)commands[columnName])["entityName"] = fieldEnityName;
                    ((EntityRecord)commands[columnName])["fieldType"] = FieldType.TextField;
                    ((EntityRecord)commands[columnName])["fieldName"] = columnName;
                    ((EntityRecord)commands[columnName])["fieldLabel"] = columnName;
                }

                if (columnName.Contains(RELATION_SEPARATOR))
                {
                    var relationData = columnName.Split(RELATION_SEPARATOR).Select(x => x.Trim()).Where(x => !string.IsNullOrWhiteSpace(x)).ToList();
                    if (relationData.Count > 2)
                    {
                        ((List<string>)((EntityRecord)evaluationObj["errors"])[columnName]).Add(string.Format("The specified field name '{0}' is incorrect. Only first level relation can be specified.", columnName));
                        ((EntityRecord)evaluationObj["stats"])["errors"] = (int)((EntityRecord)evaluationObj["stats"])["errors"] + 1;
                        continue;
                    }

                    string relationName = relationData[0];
                    string relationFieldName = relationData[1];

                    if (string.IsNullOrWhiteSpace(relationName) || relationName == "$" || relationName == "$$")
                    {
                        ((List<string>)((EntityRecord)evaluationObj["errors"])[columnName]).Add(string.Format("Invalid relation '{0}'. The relation name is not specified.", columnName));
                        ((EntityRecord)evaluationObj["stats"])["errors"] = (int)((EntityRecord)evaluationObj["stats"])["errors"] + 1;
                        continue;
                    }
                    else if (!relationName.StartsWith("$"))
                    {
                        ((List<string>)((EntityRecord)evaluationObj["errors"])[columnName]).Add(string.Format("Invalid relation '{0}'. The relation name is not correct.", columnName));
                        ((EntityRecord)evaluationObj["stats"])["errors"] = (int)((EntityRecord)evaluationObj["stats"])["errors"] + 1;
                        continue;
                    }
                    else
                        relationName = relationName.Substring(1);

                    //check for target priority mark $$
                    if (relationName.StartsWith("$"))
                    {
                        relationName = relationName.Substring(1);
                        direction = "target-origin";
                    }

                    if (string.IsNullOrWhiteSpace(relationFieldName))
                    {
                        ((List<string>)((EntityRecord)evaluationObj["errors"])[columnName]).Add(string.Format("Invalid relation '{0}'. The relation field name is not specified.", columnName));
                        ((EntityRecord)evaluationObj["stats"])["errors"] = (int)((EntityRecord)evaluationObj["stats"])["errors"] + 1;
                        continue;
                    }

                    var relation = relations.SingleOrDefault(x => x.Name == relationName);
                    if (relation == null)
                    {
                        ((List<string>)((EntityRecord)evaluationObj["errors"])[columnName]).Add(string.Format("Invalid relation '{0}'. The relation does not exist.", columnName));
                        ((EntityRecord)evaluationObj["stats"])["errors"] = (int)((EntityRecord)evaluationObj["stats"])["errors"] + 1;
                        continue;
                    }

                    if (relation.TargetEntityId != entity.Id && relation.OriginEntityId != entity.Id)
                    {
                        ((List<string>)((EntityRecord)evaluationObj["errors"])[columnName]).Add(string.Format("Invalid relation '{0}'. The relation field belongs to entity that does not relate to current entity.", columnName));
                        ((EntityRecord)evaluationObj["stats"])["errors"] = (int)((EntityRecord)evaluationObj["stats"])["errors"] + 1;
                        continue;
                    }

                    if (relation.OriginEntityId == relation.TargetEntityId)
                    {
                        if (direction == "origin-target")
                        {
                            relationEntity = entity;
                            relationEntityFieldMeta = relationEntity.Fields.FirstOrDefault(f => f.Id == relation.TargetFieldId);
                            currentFieldMeta = relationEntity.Fields.FirstOrDefault(f => f.Name == relationFieldName);
                            relationFieldMeta = entity.Fields.FirstOrDefault(f => f.Id == relation.OriginFieldId);
                        }
                        else
                        {
                            relationEntity = entity;
                            relationEntityFieldMeta = relationEntity.Fields.FirstOrDefault(f => f.Id == relation.OriginFieldId);
                            currentFieldMeta = relationEntity.Fields.FirstOrDefault(f => f.Name == relationFieldName);
                            relationFieldMeta = entity.Fields.FirstOrDefault(f => f.Id == relation.TargetFieldId);
                        }
                    }
                    else if (relation.OriginEntityId == entity.Id)
                    {
                        //direction doesn't matter
                        relationEntity = entities.FirstOrDefault(e => e.Id == relation.TargetEntityId);
                        relationEntityFieldMeta = relationEntity.Fields.FirstOrDefault(f => f.Id == relation.TargetFieldId);
                        currentFieldMeta = relationEntity.Fields.FirstOrDefault(f => f.Name == relationFieldName);
                        relationFieldMeta = entity.Fields.FirstOrDefault(f => f.Id == relation.OriginFieldId);
                    }
                    else
                    {
                        //direction doesn't matter
                        relationEntity = entities.FirstOrDefault(e => e.Id == relation.OriginEntityId);
                        relationEntityFieldMeta = relationEntity.Fields.FirstOrDefault(f => f.Id == relation.OriginFieldId);
                        currentFieldMeta = relationEntity.Fields.FirstOrDefault(f => f.Name == relationFieldName);
                        relationFieldMeta = entity.Fields.FirstOrDefault(f => f.Id == relation.TargetFieldId);
                    }

                    if (currentFieldMeta == null)
                    {
                        ((List<string>)((EntityRecord)evaluationObj["errors"])[columnName]).Add(string.Format("Invalid relation '{0}'. Fields with such name does not exist.", columnName));
                        ((EntityRecord)evaluationObj["stats"])["errors"] = (int)((EntityRecord)evaluationObj["stats"])["errors"] + 1;
                        continue;
                    }

                    if (currentFieldMeta.GetFieldType() == FieldType.MultiSelectField || currentFieldMeta.GetFieldType() == FieldType.TreeSelectField)
                    {
                        ((List<string>)((EntityRecord)evaluationObj["errors"])[columnName]).Add(string.Format("Invalid relation '{0}'. Fields from Multiselect and Treeselect types can't be used as relation fields.", columnName));
                        ((EntityRecord)evaluationObj["stats"])["errors"] = (int)((EntityRecord)evaluationObj["stats"])["errors"] + 1;
                        continue;
                    }

                    if (relation.RelationType == EntityRelationType.OneToOne &&
                        ((relation.TargetEntityId == entity.Id && relationFieldMeta.Name == "id") || (relation.OriginEntityId == entity.Id && relationEntityFieldMeta.Name == "id")))
                    {
                        ((List<string>)((EntityRecord)evaluationObj["errors"])[columnName]).Add(string.Format("Invalid relation '{0}'. Can't use relations when relation field is id field.", columnName));
                        ((EntityRecord)evaluationObj["stats"])["errors"] = (int)((EntityRecord)evaluationObj["stats"])["errors"] + 1;
                        continue;
                    }

                    fieldEnityName = relationEntity.Name;
                    fieldRelationName = relationName;
                    relationType = relation.RelationType;
                }
                else
                {
                    currentFieldMeta = entity.Fields.FirstOrDefault(f => f.Name == columnName);
                }

                if (currentFieldMeta != null)
                {
                    existingField = true;
                }

                if (!existingField && !string.IsNullOrWhiteSpace(fieldRelationName))
                {
                    ((List<string>)((EntityRecord)evaluationObj["errors"])[columnName]).Add(string.Format("Creation of a new relation field is not allowed.", columnName));
                    ((EntityRecord)evaluationObj["stats"])["errors"] = (int)((EntityRecord)evaluationObj["stats"])["errors"] + 1;
                }

                #region << Commands >>
                //we need to init the command for this column - if it is new field the default is do nothing, if it is existing the default is update
                if (existingField)
                {
                    if (generalCommand == "evaluate")
                    {
                        ((EntityRecord)commands[columnName])["command"] = "to_update";
                        ((EntityRecord)commands[columnName])["relationName"] = fieldRelationName;
                        ((EntityRecord)commands[columnName])["relationDirection"] = direction;
                        ((EntityRecord)commands[columnName])["relationType"] = relationType;
                        ((EntityRecord)commands[columnName])["entityName"] = fieldEnityName;
                        ((EntityRecord)commands[columnName])["fieldType"] = currentFieldMeta.GetFieldType();
                        ((EntityRecord)commands[columnName])["fieldName"] = currentFieldMeta.Name;
                        ((EntityRecord)commands[columnName])["fieldLabel"] = currentFieldMeta.Label;

                        bool hasPermisstion = SecurityContext.HasEntityPermission(EntityPermission.Update, entity);
                        if (!hasPermisstion)
                        {
                            ((List<string>)((EntityRecord)evaluationObj["errors"])[columnName]).Add($"Access denied. Trying to update record in entity '{entity.Name}' with no update access.");
                            ((EntityRecord)evaluationObj["stats"])["errors"] = (int)((EntityRecord)evaluationObj["stats"])["errors"] + 1;
                        }
                    }

                    ((EntityRecord)commands[columnName])["currentFieldMeta"] = currentFieldMeta;
                    ((EntityRecord)commands[columnName])["relationEntityFieldMeta"] = relationEntityFieldMeta;
                    ((EntityRecord)commands[columnName])["relationFieldMeta"] = relationFieldMeta;
                }
                else
                {
                    if (generalCommand == "evaluate")
                    {
                        //we need to check wheather the property of the command match the fieldName
                        ((EntityRecord)commands[columnName])["command"] = "to_create";
                        ((EntityRecord)commands[columnName])["entityName"] = fieldEnityName;
                        ((EntityRecord)commands[columnName])["fieldType"] = FieldType.TextField;
                        ((EntityRecord)commands[columnName])["fieldName"] = columnName;
                        ((EntityRecord)commands[columnName])["fieldLabel"] = columnName;

                        bool hasPermisstion = SecurityContext.HasEntityPermission(EntityPermission.Create, entity);
                        if (!hasPermisstion)
                        {
                            ((List<string>)((EntityRecord)evaluationObj["errors"])[columnName]).Add($"Access denied. Trying to create record in entity '{entity.Name}' with no create access.");
                            ((EntityRecord)evaluationObj["stats"])["errors"] = (int)((EntityRecord)evaluationObj["stats"])["errors"] + 1;
                        }
                    }
                }
                #endregion
            }

            evaluationObj["commands"] = commands;

            do
            {
                Dictionary<string, EntityRecord> fieldsFromRelationList = new Dictionary<string, EntityRecord>();
                Dictionary<string, string> rowRecordData = new Dictionary<string, string>();

                foreach (var columnName in columnNames)
                {
                    string fieldValue = csvReader.GetField<string>(columnName);
                    rowRecordData[columnName] = fieldValue;

                    EntityRecord commandRecords = ((EntityRecord)commands[columnName]);
                    Field currentFieldMeta = new TextField();
                    if (commandRecords.GetProperties().Any(p => p.Key == "currentFieldMeta"))
                        currentFieldMeta = (Field)commandRecords["currentFieldMeta"];

                    if (columnName.Contains(RELATION_SEPARATOR))
                    {
                        string relationName = (string)((EntityRecord)commands[columnName])["relationName"];
                        string relationDirection = (string)((EntityRecord)commands[columnName])["relationDirection"];
                        string relationEntityName = (string)((EntityRecord)commands[columnName])["entityName"];

                        EntityRelationType relationType = (EntityRelationType)Enum.Parse(typeof(EntityRelationType), (((EntityRecord)commands[columnName])["relationType"]).ToString());
                        Field relationEntityFieldMeta = (Field)((EntityRecord)commands[columnName])["relationEntityFieldMeta"];
                        Field relationFieldMeta = (Field)((EntityRecord)commands[columnName])["relationFieldMeta"];

                        var relation = relations.SingleOrDefault(x => x.Name == relationName);

                        string relationFieldValue = "";
                        if (columnNames.Any(c => c == relationFieldMeta.Name))
                            relationFieldValue = csvReader.GetField<string>(relationFieldMeta.Name);

                        QueryObject filter = null;
                        if ((relationType == EntityRelationType.OneToMany && relation.OriginEntityId == relation.TargetEntityId && relationDirection == "origin-target") ||
                            (relationType == EntityRelationType.OneToMany && relation.OriginEntityId != relation.TargetEntityId && relation.OriginEntityId == entity.Id) ||
                            relationType == EntityRelationType.ManyToMany)
                        {
                            //expect array of values
                            if (!columnNames.Any(c => c == relationFieldMeta.Name) || string.IsNullOrEmpty(relationFieldValue))
                            {
                                ((List<string>)((EntityRecord)evaluationObj["errors"])[columnName]).Add(string.Format("Invalid relation '{0}'. Relation field does not exist into input record data or its value is null.", columnName));
                                ((EntityRecord)evaluationObj["stats"])["errors"] = (int)((EntityRecord)evaluationObj["stats"])["errors"] + 1;
                            }

                            List<string> values = new List<string>();
                            if (relationFieldValue.StartsWith("[") && relationFieldValue.EndsWith("]"))
                            {
                                values = JsonConvert.DeserializeObject<List<string>>(relationFieldValue);
                            }
                            if (values.Count < 1)
                                continue;

                            List<QueryObject> queries = new List<QueryObject>();
                            foreach (var val in values)
                            {
                                queries.Add(EntityQuery.QueryEQ(currentFieldMeta.Name, val));
                            }

                            filter = EntityQuery.QueryOR(queries.ToArray());
                        }
                        else
                        {
                            filter = EntityQuery.QueryEQ(currentFieldMeta.Name, DbRecordRepository.ExtractFieldValue(fieldValue, currentFieldMeta, true));
                        }

                        EntityRecord fieldsFromRelation = new EntityRecord();

                        if (fieldsFromRelationList.Any(r => r.Key == relation.Name))
                        {
                            fieldsFromRelation = fieldsFromRelationList[relationName];
                        }
                        else
                        {
                            fieldsFromRelation["columns"] = new List<string>();
                            fieldsFromRelation["queries"] = new List<QueryObject>();
                            fieldsFromRelation["direction"] = relationDirection;
                            fieldsFromRelation["relationEntityName"] = relationEntityName;
                        }

                        ((List<string>)fieldsFromRelation["columns"]).Add(columnName);
                        ((List<QueryObject>)fieldsFromRelation["queries"]).Add(filter);
                        fieldsFromRelationList[relationName] = fieldsFromRelation;
                    }
                }

                foreach (var fieldsFromRelation in fieldsFromRelationList)
                {
                    EntityRecord fieldsFromRelationValue = fieldsFromRelation.Value;
                    List<string> columnList = (List<string>)fieldsFromRelationValue["columns"];
                    List<QueryObject> queries = (List<QueryObject>)fieldsFromRelationValue["queries"];
                    string relationDirection = (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 = recMan.Find(new EntityQuery(relationEntityName, "*", filter, null, null, null));

                    if (!relatedRecordResponse.Success || relatedRecordResponse.Object.Data.Count < 1)
                    {
                        foreach (var columnName in columnList)
                        {
                            ((List<string>)((EntityRecord)evaluationObj["errors"])[columnName]).Add(string.Format("Invalid relation '{0}'. The relation record does not exist.", columnName));
                            ((EntityRecord)evaluationObj["stats"])["errors"] = (int)((EntityRecord)evaluationObj["stats"])["errors"] + 1;
                        }
                    }
                    else if (relatedRecordResponse.Object.Data.Count > 1 && ((relation.RelationType == EntityRelationType.OneToMany && relation.OriginEntityId == relation.TargetEntityId && relationDirection == "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
                        foreach (var columnName in columnList)
                        {
                            ((List<string>)((EntityRecord)evaluationObj["errors"])[columnName]).Add(string.Format("Invalid relation '{0}'. There are multiple relation records matching this value.", columnName));
                            ((EntityRecord)evaluationObj["stats"])["errors"] = (int)((EntityRecord)evaluationObj["stats"])["errors"] + 1;
                        }
                    }

                    fieldsFromRelationList[fieldsFromRelation.Key]["relatedRecordResponse"] = relatedRecordResponse;
                }

                var rowRecord = new EntityRecord();
                if ((int)statsObject["errors"] == 0)
                {
                    foreach (var columnName in columnNames)
                    {
                        string fieldValue = rowRecordData[columnName];
                        EntityRecord commandRecords = ((EntityRecord)commands[columnName]);
                        Field currentFieldMeta = new TextField();
                        if (commandRecords.GetProperties().Any(p => p.Key == "currentFieldMeta"))
                            currentFieldMeta = (Field)commandRecords["currentFieldMeta"];
                        string fieldEnityName = (string)commandRecords["entityName"];
                        string command = (string)commandRecords["command"];

                        bool existingField = false;
                        if (command == "to_update")
                            existingField = true;

                        if (existingField)
                        {
                            #region << Validation >>

                            var errorsList = (List<string>)((EntityRecord)evaluationObj["errors"])[columnName];
                            var warningList = (List<string>)((EntityRecord)evaluationObj["warnings"])[columnName];

                            if (columnName.Contains(RELATION_SEPARATOR))
                            {
                                string relationName = (string)((EntityRecord)commands[columnName])["relationName"];
                                string relationDirection = (string)((EntityRecord)commands[columnName])["relationDirection"];
                                string relationEntityName = (string)((EntityRecord)commands[columnName])["entityName"];

                                EntityRelationType relationType = (EntityRelationType)Enum.Parse(typeof(EntityRelationType), (((EntityRecord)commands[columnName])["relationType"]).ToString());
                                Field relationEntityFieldMeta = (Field)((EntityRecord)commands[columnName])["relationEntityFieldMeta"];
                                Field relationFieldMeta = (Field)((EntityRecord)commands[columnName])["relationFieldMeta"];

                                var relation = relations.SingleOrDefault(x => x.Name == relationName);

                                QueryResponse relatedRecordResponse = (QueryResponse)fieldsFromRelationList[relationName]["relatedRecordResponse"];

                                var relatedRecords = relatedRecordResponse.Object.Data;
                                List<Guid> relatedRecordValues = new List<Guid>();
                                foreach (var relatedRecord in relatedRecords)
                                {
                                    relatedRecordValues.Add((Guid)relatedRecord[relationEntityFieldMeta.Name]);
                                }

                                string relationFieldValue = "";
                                if (columnNames.Any(c => c == relationFieldMeta.Name))
                                    relationFieldValue = rowRecordData[relationFieldMeta.Name];

                                if (relation.RelationType == EntityRelationType.OneToOne &&
                                    ((relation.OriginEntityId == relation.TargetEntityId && relationDirection == "origin-target") || relation.OriginEntityId == entity.Id))
                                {
                                    if (!columnNames.Any(c => c == relationFieldMeta.Name) || string.IsNullOrWhiteSpace(relationFieldValue))
                                    {
                                        errorsList.Add(string.Format("Invalid relation '{0}'. Relation field does not exist into input record data or its value is null.", columnName));
                                        ((EntityRecord)evaluationObj["stats"])["errors"] = (int)((EntityRecord)evaluationObj["stats"])["errors"] + 1;
                                    }
                                }
                                else if (relation.RelationType == EntityRelationType.OneToMany &&
                                    ((relation.OriginEntityId == relation.TargetEntityId && relationDirection == "origin-target") || relation.OriginEntityId == entity.Id))
                                {
                                    if (!columnNames.Any(c => c == relationFieldMeta.Name) || string.IsNullOrWhiteSpace(relationFieldValue))
                                    {
                                        errorsList.Add(string.Format("Invalid relation '{0}'. Relation field does not exist into input record data or its value is null.", columnName));
                                        ((EntityRecord)evaluationObj["stats"])["errors"] = (int)((EntityRecord)evaluationObj["stats"])["errors"] + 1;
                                    }
                                }
                                else if (relation.RelationType == EntityRelationType.ManyToMany)
                                {
                                    foreach (Guid relatedRecordIdValue in relatedRecordValues)
                                    {
                                        Guid relRecordId = Guid.Empty;
                                        if (!Guid.TryParse(relationFieldValue, out relRecordId))
                                        {
                                            errorsList.Add("Invalid record value for field: '" + columnName + "'. Invalid value: '" + fieldValue + "'");
                                            ((EntityRecord)evaluationObj["stats"])["errors"] = (int)((EntityRecord)evaluationObj["stats"])["errors"] + 1;
                                        }
                                    }
                                }

                            }
                            if (string.IsNullOrWhiteSpace(fieldValue))
                            {
                                if (currentFieldMeta.Required && currentFieldMeta.Name != "id")
                                {
                                    errorsList.Add("Field is required. Value can not be empty!");
                                    ((EntityRecord)evaluationObj["stats"])["errors"] = (int)((EntityRecord)evaluationObj["stats"])["errors"] + 1;
                                }
                            }
                            else if (!(fieldValue.StartsWith("[") && fieldValue.EndsWith("]")))
                            {
                                FieldType fType = (FieldType)currentFieldMeta.GetFieldType();
                                switch (fType)
                                {
                                    case FieldType.AutoNumberField:
                                    case FieldType.CurrencyField:
                                    case FieldType.NumberField:
                                    case FieldType.PercentField:
                                        {
                                            decimal decValue;
                                            if (!decimal.TryParse(fieldValue, out decValue))
                                            {
                                                errorsList.Add("Value have to be of decimal type!");
                                                ((EntityRecord)evaluationObj["stats"])["errors"] = (int)((EntityRecord)evaluationObj["stats"])["errors"] + 1;
                                            }
                                        }
                                        break;
                                    case FieldType.CheckboxField:
                                        {
                                            bool bValue;
                                            if (!bool.TryParse(fieldValue, out bValue))
                                            {
                                                errorsList.Add("Value have to be of boolean type!");
                                                ((EntityRecord)evaluationObj["stats"])["errors"] = (int)((EntityRecord)evaluationObj["stats"])["errors"] + 1;
                                            }
                                        }
                                        break;
                                    case FieldType.DateField:
                                    case FieldType.DateTimeField:
                                        {
                                            DateTime dtValue;
                                            if (!DateTime.TryParse(fieldValue, out dtValue))
                                            {
                                                errorsList.Add("Value have to be of datetime type!");
                                                ((EntityRecord)evaluationObj["stats"])["errors"] = (int)((EntityRecord)evaluationObj["stats"])["errors"] + 1;
                                            }
                                        }
                                        break;
                                    case FieldType.MultiSelectField:
                                        {

                                        }
                                        break;
                                    case FieldType.SelectField:
                                        {
                                            if (!((SelectField)currentFieldMeta).Options.Any(o => o.Key == fieldValue))
                                            {
                                                errorsList.Add("Value does not exist in select field options!");
                                                ((EntityRecord)evaluationObj["stats"])["errors"] = (int)((EntityRecord)evaluationObj["stats"])["errors"] + 1;
                                            }
                                        }
                                        break;
                                    case FieldType.TreeSelectField:
                                        {

                                        }
                                        break;
                                    case FieldType.GuidField:
                                        {
                                            Guid gValue;
                                            if (!Guid.TryParse(fieldValue, out gValue))
                                            {
                                                errorsList.Add("Value have to be of guid type!");
                                                ((EntityRecord)evaluationObj["stats"])["errors"] = (int)((EntityRecord)evaluationObj["stats"])["errors"] + 1;
                                            }

                                        }
                                        break;
                                }
                            }

                            ((EntityRecord)evaluationObj["errors"])[columnName] = errorsList;

                            //validate the value for warnings
                            ((EntityRecord)evaluationObj["warnings"])[columnName] = warningList;
                            #endregion
                        }

                        #region << Data >>
                        //Submit row data

                        if (!(command == "no_import" && generalCommand == "evaluate-import"))
                            rowRecord[columnName] = fieldValue;
                        #endregion
                    }

                    if (enableWebHooks && generalCommand == "evaluate-import")
                    {
                        #region << WebHook Filters >>

                        Guid? recordId = null;
                        if (rowRecord.GetProperties().Any(p => p.Key == "id") && !string.IsNullOrWhiteSpace((string)rowRecord["id"]))
                        {
                            Guid id;
                            if (Guid.TryParse((string)rowRecord["id"], out id))
                                recordId = id;
                        }
                        //////////////////////////////////////////////////////////////////////////////////////
                        //WEBHOOK FILTERS << create_record_input_filter >> AND << update_record_input_filter >>
                        //////////////////////////////////////////////////////////////////////////////////////
                        #region
                        try
                        {
                            dynamic hookFilterObj = new ExpandoObject();
                            hookFilterObj.record = rowRecord;
                            hookFilterObj.recordId = recordId;
                            hookFilterObj.controller = controller;
                            string webHookName = (!recordId.HasValue || recordId.Value == Guid.Empty) ? SystemWebHookNames.CreateRecordInput : SystemWebHookNames.UpdateRecordInput;
                            hookFilterObj = hooksService.ProcessFilters(webHookName, entityName, hookFilterObj);
                            rowRecord = hookFilterObj.record;
                        }
                        catch (Exception ex)
                        {
                            response.Success = false;
                            response.Object = evaluationObj;
                            response.Timestamp = DateTime.UtcNow;
                            response.Message = (!recordId.HasValue || recordId.Value == Guid.Empty) ?
                                "Plugin error in web hook create_record_input_filter: " + ex.Message :
                                "Plugin error in web hook update_record_input_filter: " + ex.Message;
                            return response;
                            //throw new Exception("Plugin error in web hook update_record_input_filter: " + ex.Message);
                        }// <<<
                        #endregion

                        var validationErrors = new List<ErrorModel>();

                        //////////////////////////////////////////////////////////////////////////////////////
                        //WEBHOOK FILTER << update_record_validation_errors_filter >>
                        //////////////////////////////////////////////////////////////////////////////////////
                        #region
                        try
                        {
                            dynamic hookFilterObj = new ExpandoObject();
                            hookFilterObj.errors = validationErrors;
                            hookFilterObj.record = rowRecord;
                            hookFilterObj.recordId = recordId;
                            hookFilterObj.controller = controller;
                            string webHookName = (!recordId.HasValue || recordId.Value == Guid.Empty) ? SystemWebHookNames.CreateRecordValidationErrors : SystemWebHookNames.UpdateRecordValidationErrors;
                            hookFilterObj = hooksService.ProcessFilters(SystemWebHookNames.UpdateRecordValidationErrors, entityName, hookFilterObj);
                            validationErrors = hookFilterObj.errors;
                        }
                        catch (Exception ex)
                        {
                            response.Success = false;
                            response.Object = evaluationObj;
                            response.Timestamp = DateTime.UtcNow;
                            response.Message = (!recordId.HasValue || recordId.Value == Guid.Empty) ?
                                "Plugin error in web hook create_record_validation_errors_filter: " + ex.Message :
                                "Plugin error in web hook update_record_validation_errors_filter: " + ex.Message;
                            return response;
                            //throw new Exception ("Plugin error in web hook update_record_validation_errors_filter: " + ex.Message));
                        }// <<<
                        #endregion

                        if (validationErrors.Count > 0)
                        {
                            List<string> errorsList = (List<string>)((EntityRecord)evaluationObj["errors"])["id"];
                            foreach (var validationError in validationErrors)
                            {
                                errorsList.Add(validationError.Message);
                                ((EntityRecord)evaluationObj["stats"])["errors"] = (int)((EntityRecord)evaluationObj["stats"])["errors"] + 1;
                                continue;
                            }
                        }

                        #endregion
                    }
                }
                else
                {
                    foreach (var columnName in columnNames)
                    {
                        EntityRecord commandRecords = ((EntityRecord)commands[columnName]);
                        string command = (string)commandRecords["command"];

                        string fieldValue = csvReader.GetField<string>(columnName);
                        if (!(command == "no_import" && generalCommand == "evaluate-import"))
                            rowRecord[columnName] = fieldValue;
                    }
                }

                ((List<EntityRecord>)evaluationObj["records"]).Add(rowRecord);

            }
            while (csvReader.Read());

            foreach (var columnName in columnNames)
            {
                if (commands.GetProperties().Any(p => p.Key == columnName))
                {
                    ((EntityRecord)commands[columnName]).Properties.Remove("currentFieldMeta");
                    ((EntityRecord)commands[columnName]).Properties.Remove("relationEntityFieldMeta");
                    ((EntityRecord)commands[columnName]).Properties.Remove("relationFieldMeta");
                }
            }

            if ((int)statsObject["errors"] > 0)
            {
                if (generalCommand == "evaluate-import")
                {
                    response.Success = false;
                    //evaluationObj["general_command"] = "evaluate";
                }
                response.Object = evaluationObj;
                return response;
            }

            if (generalCommand == "evaluate-import")
            {
                using (DbConnection connection = DbContext.Current.CreateConnection())
                {
                    connection.BeginTransaction();

                    try
                    {
                        int fieldCreated = 0;
                        foreach (var columnName in columnNames)
                        {
                            string command = (string)((EntityRecord)commands[columnName])["command"];

                            if (command == "to_create")
                            {
                                FieldType fieldType = (FieldType)Enum.Parse(typeof(FieldType), (((EntityRecord)commands[columnName])["fieldType"]).ToString());
                                string fieldName = (string)((EntityRecord)commands[columnName])["fieldName"];
                                string fieldLabel = (string)((EntityRecord)commands[columnName])["fieldLabel"];
                                var result = entMan.CreateField(entity.Id, fieldType, null, fieldName, fieldLabel);

                                if (!result.Success)
                                {
                                    string message = result.Message;
                                    if (result.Errors.Count > 0)
                                    {
                                        foreach (ErrorModel error in result.Errors)
                                            message += " " + error.Message;
                                    }
                                    throw new Exception(message);
                                }
                                fieldCreated++;
                            }
                        }

                        int successfullyCreatedRecordsCount = 0;
                        int successfullyUpdatedRecordsCount = 0;

                        List<EntityRecord> records = (List<EntityRecord>)evaluationObj["records"];
                        foreach (EntityRecord record in records)
                        {
                            EntityRecord newRecord = record;
                            QueryResponse result;
                            if (!newRecord.GetProperties().Any(x => x.Key == "id") || newRecord["id"] == null || string.IsNullOrEmpty(newRecord["id"].ToString()))
                            {
                                newRecord["id"] = Guid.NewGuid();
                                if (enableWebHooks)
                                {
                                    //////////////////////////////////////////////////////////////////////////////////////
                                    //WEBHOOK FILTER << create_record_pre_save_filter >>
                                    //////////////////////////////////////////////////////////////////////////////////////
                                    #region
                                    try
                                    {
                                        dynamic hookFilterObj = new ExpandoObject();
                                        hookFilterObj.record = newRecord;
                                        hookFilterObj.recordId = (Guid)newRecord["id"];
                                        hookFilterObj.controller = controller;
                                        hookFilterObj = hooksService.ProcessFilters(SystemWebHookNames.CreateRecordPreSave, entityName, hookFilterObj);
                                        newRecord = hookFilterObj.record;
                                    }
                                    catch (Exception ex)
                                    {
                                        throw new Exception("Plugin error in web hook create_record_pre_save_filter: " + ex.Message);
                                    }// <<<
                                    #endregion
                                }

                                result = recMan.CreateRecord(entityName, newRecord);

                                if (result.Success)
                                    successfullyCreatedRecordsCount++;

                                if (result.Success && enableWebHooks)
                                {
                                    //////////////////////////////////////////////////////////////////////////////////////
                                    //WEBHOOK ACTION << create_record >>
                                    //////////////////////////////////////////////////////////////////////////////////////
                                    #region
                                    try
                                    {
                                        dynamic hookActionObj = new ExpandoObject();
                                        hookActionObj.record = result.Object.Data[0];
                                        hookActionObj.result = result;
                                        hookActionObj.controller = controller;
                                        hooksService.ProcessActions(SystemWebHookNames.CreateRecordAction, entityName, hookActionObj);
                                    }
                                    catch (Exception ex)
                                    {
                                        throw new Exception("Plugin error in web hook create_record_success_action: " + ex.Message);
                                    }// <<<
                                    #endregion
                                }
                            }
                            else
                            {
                                if (enableWebHooks)
                                {
                                    Guid id;
                                    if (Guid.TryParse((string)newRecord["id"], out id))
                                        newRecord["id"] = id;
                                    //////////////////////////////////////////////////////////////////////////////////////
                                    //WEBHOOK FILTER << update_record_pre_save_filter >>
                                    //////////////////////////////////////////////////////////////////////////////////////
                                    #region
                                    try
                                    {
                                        dynamic hookFilterObj = new ExpandoObject();
                                        hookFilterObj.record = newRecord;
                                        hookFilterObj.recordId = new Guid(newRecord["id"].ToString());
                                        hookFilterObj.controller = controller;
                                        hookFilterObj = hooksService.ProcessFilters(SystemWebHookNames.UpdateRecordPreSave, entityName, hookFilterObj);
                                        newRecord = hookFilterObj.record;
                                    }
                                    catch (Exception ex)
                                    {
                                        throw new Exception("Plugin error in web hook update_record_pre_save_filter: " + ex.Message);
                                    }// <<<
                                    #endregion
                                }
                                result = recMan.UpdateRecord(entityName, newRecord);

                                if (result.Success)
                                    successfullyUpdatedRecordsCount++;

                                if (result.Success && enableWebHooks)
                                {
                                    //////////////////////////////////////////////////////////////////////////////////////
                                    //WEBHOOK ACTION << update_record_success_action >>
                                    //////////////////////////////////////////////////////////////////////////////////////
                                    #region
                                    try
                                    {
                                        dynamic hookActionObj = new ExpandoObject();
                                        hookActionObj.record = result.Object.Data[0];
                                        hookActionObj.oldRecord = newRecord;
                                        hookActionObj.result = result;
                                        hookActionObj.recordId = result.Object.Data[0]["id"];
                                        hookActionObj.controller = controller;
                                        hooksService.ProcessActions(SystemWebHookNames.UpdateRecordAction, entityName, hookActionObj);
                                    }
                                    catch (Exception ex)
                                    {
                                        throw new Exception("Plugin error in web hook update_record_success_action: " + ex.Message);
                                    }// <<<
                                    #endregion
                                }
                            }

                            if (!result.Success)
                            {
                                string message = result.Message;
                                if (result.Errors.Count > 0)
                                {
                                    foreach (ErrorModel error in result.Errors)
                                        message += " " + error.Message;
                                }
                                throw new Exception(message);
                            }
                        }

                        ((EntityRecord)evaluationObj["stats"])["to_create"] = successfullyCreatedRecordsCount;
                        ((EntityRecord)evaluationObj["stats"])["to_update"] = successfullyUpdatedRecordsCount;
                        ((EntityRecord)evaluationObj["stats"])["total_records"] = records.Count;
                        ((EntityRecord)evaluationObj["stats"])["fields_created"] = fieldCreated;

                        connection.CommitTransaction();
                    }
                    catch (Exception e)
                    {
                        //WebVella.ERP.Api.Cache.ClearEntities();

                        connection.RollbackTransaction();

                        ((EntityRecord)evaluationObj["stats"])["errors"] = (int)((EntityRecord)evaluationObj["stats"])["errors"] + 1;

                        response.Success = false;
                        response.Object = evaluationObj;
                        response.Timestamp = DateTime.UtcNow;
            #if DEBUG
                        response.Message = e.Message + e.StackTrace;
            #else
                            response.Message = "Import failed! An internal error occurred!";
            #endif
                    }
                }

                Cache.ClearEntities();
                response.Object = evaluationObj;
                return response;
            }

            response.Object = evaluationObj;
            return response;
        }
Пример #5
0
        public ResponseModel ImportEntityRecordsFromCsv(string entityName, string fileTempPath)
        {
            //The import CSV should have column names matching the names of the imported fields. The first column should be "id" matching the id of the record to be updated.
            //If the 'id' of a record equals 'null', a new record will be created with the provided columns and default values for the missing ones.

            ResponseModel response = new ResponseModel();
            response.Message = "Records successfully imported";
            response.Timestamp = DateTime.UtcNow;
            response.Success = true;
            response.Object = null;

            //string fileTempPath = @"D:\csv\test.csv";
            //FileInfo fileInfo = new FileInfo(fileTempPath);

            //if (!fileInfo.Exists)
            //	throw new Exception("FILE_NOT_EXIST");

            //FileStream fileStream = fileInfo.OpenRead();
            //TextReader reader = new StreamReader(fileStream);

            if (string.IsNullOrWhiteSpace(fileTempPath))
            {
                response.Timestamp = DateTime.UtcNow;
                response.Success = false;
                response.Message = "Import failed! fileTempPath parameter cannot be empty or null!";
                response.Errors.Add(new ErrorModel("fileTempPath", fileTempPath, "Import failed! File does not exist!"));
                return response;
            }

            if (fileTempPath.StartsWith("/fs"))
                fileTempPath = fileTempPath.Remove(0, 3);

            if (!fileTempPath.StartsWith("/"))
                fileTempPath = "/" + fileTempPath;

            fileTempPath = fileTempPath.ToLowerInvariant();

            using (DbConnection connection = DbContext.Current.CreateConnection())
            {
                List<EntityRelation> relations = relMan.Read().Object;
                EntityListResponse entitiesResponse = entMan.ReadEntities();
                List<Entity> entities = entitiesResponse.Object;
                Entity entity = entities.FirstOrDefault(e => e.Name == entityName);

                if (entity == null)
                {
                    response.Timestamp = DateTime.UtcNow;
                    response.Success = false;
                    response.Message = "Import failed! Entity with such name does not exist!";
                    response.Errors.Add(new ErrorModel("entityName", entityName, "Entity with such name does not exist!"));
                    return response;
                }

                DbFileRepository fs = new DbFileRepository();
                DbFile file = fs.Find(fileTempPath);

                if (file == null)
                {
                    response.Timestamp = DateTime.UtcNow;
                    response.Success = false;
                    response.Message = "Import failed! File does not exist!";
                    response.Errors.Add(new ErrorModel("fileTempPath", fileTempPath, "Import failed! File does not exist!"));
                    return response;
                }

                byte[] fileBytes = file.GetBytes();
                MemoryStream fileStream = new MemoryStream(fileBytes);
                //fileStream.Write(fileBytes, 0, fileBytes.Length);
                //fileStream.Flush();
                TextReader reader = new StreamReader(fileStream);

                CsvReader csvReader = new CsvReader(reader);
                csvReader.Configuration.HasHeaderRecord = true;
                csvReader.Configuration.IsHeaderCaseSensitive = false;

                csvReader.Read();
                List<string> columns = csvReader.FieldHeaders.ToList();

                List<dynamic> fieldMetaList = new List<dynamic>();

                foreach (var column in columns)
                {
                    Field field;
                    if (column.Contains(RELATION_SEPARATOR))
                    {
                        var relationData = column.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.", column));

                        string relationName = relationData[0];
                        string relationFieldName = relationData[1];

                        if (string.IsNullOrWhiteSpace(relationName) || relationName == "$" || relationName == "$$")
                            throw new Exception(string.Format("Invalid relation '{0}'. The relation name is not specified.", column));
                        else if (!relationName.StartsWith("$"))
                            throw new Exception(string.Format("Invalid relation '{0}'. The relation name is not correct.", column));
                        else
                            relationName = relationName.Substring(1);

                        //check for target priority mark $$
                        if (relationName.StartsWith("$"))
                        {
                            relationName = relationName.Substring(1);
                        }

                        if (string.IsNullOrWhiteSpace(relationFieldName))
                            throw new Exception(string.Format("Invalid relation '{0}'. The relation field name is not specified.", column));

                        var relation = relations.SingleOrDefault(x => x.Name == relationName);
                        if (relation == null)
                            throw new Exception(string.Format("Invalid relation '{0}'. The relation does not exist.", column));

                        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.", column));

                        Entity relationEntity = null;

                        if (relation.OriginEntityId == entity.Id)
                        {
                            relationEntity = entities.FirstOrDefault(e => e.Id == relation.TargetEntityId);
                            field = relationEntity.Fields.FirstOrDefault(f => f.Name == relationFieldName);
                        }
                        else
                        {
                            relationEntity = entities.FirstOrDefault(e => e.Id == relation.OriginEntityId);
                            field = relationEntity.Fields.FirstOrDefault(f => f.Name == relationFieldName);
                        }
                    }
                    else
                    {
                        field = entity.Fields.FirstOrDefault(f => f.Name == column);
                    }

                    dynamic fieldMeta = new ExpandoObject();
                    fieldMeta.ColumnName = column;
                    fieldMeta.FieldType = field.GetFieldType();

                    fieldMetaList.Add(fieldMeta);
                }

                connection.BeginTransaction();

                try
                {
                    do
                    {
                        EntityRecord newRecord = new EntityRecord();
                        foreach (var fieldMeta in fieldMetaList)
                        {
                            string columnName = fieldMeta.ColumnName.ToString();
                            string value = csvReader.GetField<string>(columnName);

                            if (value.StartsWith("[") && value.EndsWith("]"))
                            {
                                newRecord[columnName] = JsonConvert.DeserializeObject<List<string>>(value);
                            }
                            else
                            {
                                switch ((FieldType)fieldMeta.FieldType)
                                {
                                    case FieldType.AutoNumberField:
                                    case FieldType.CurrencyField:
                                    case FieldType.NumberField:
                                    case FieldType.PercentField:
                                        {
                                            decimal decValue;
                                            if (decimal.TryParse(value, out decValue))
                                                newRecord[columnName] = decValue;
                                            else
                                                newRecord[columnName] = null;
                                        }
                                        break;
                                    case FieldType.CheckboxField:
                                        {
                                            bool bValue;
                                            if (bool.TryParse(value, out bValue))
                                                newRecord[columnName] = bValue;
                                            else
                                                newRecord[columnName] = null;
                                        }
                                        break;
                                    case FieldType.DateField:
                                    case FieldType.DateTimeField:
                                        {
                                            DateTime dtValue;
                                            if (DateTime.TryParse(value, out dtValue))
                                                newRecord[columnName] = dtValue;
                                            else
                                                newRecord[columnName] = null;
                                        }
                                        break;
                                    case FieldType.MultiSelectField:
                                        {
                                            if (!string.IsNullOrWhiteSpace(value))
                                                newRecord[columnName] = new List<string>(new string[] { value });
                                            else
                                                newRecord[columnName] = null;
                                        }
                                        break;
                                    case FieldType.TreeSelectField:
                                        {
                                            if (!string.IsNullOrWhiteSpace(value))
                                                newRecord[columnName] = new List<string>(new string[] { value });
                                            else
                                                newRecord[columnName] = null;
                                        }
                                        break;
                                    case FieldType.GuidField:
                                        {
                                            Guid gValue;
                                            if (Guid.TryParse(value, out gValue))
                                                newRecord[columnName] = gValue;
                                            else
                                                newRecord[columnName] = null;
                                        }
                                        break;
                                    default:
                                        {
                                            newRecord[columnName] = value;
                                        }
                                        break;
                                }
                            }
                        }

                        QueryResponse result;
                        if (!newRecord.GetProperties().Any(x => x.Key == "id") || newRecord["id"] == null || string.IsNullOrEmpty(newRecord["id"].ToString()))
                        {
                            newRecord["id"] = Guid.NewGuid();
                            result = recMan.CreateRecord(entityName, newRecord);
                        }
                        else
                        {
                            result = recMan.UpdateRecord(entityName, newRecord);
                        }
                        if (!result.Success)
                        {
                            string message = result.Message;
                            if (result.Errors.Count > 0)
                            {
                                foreach (ErrorModel error in result.Errors)
                                    message += " " + error.Message;
                            }
                            throw new Exception(message);
                        }
                    } while (csvReader.Read());
                    connection.CommitTransaction();
                }
                catch (Exception e)
                {
                    connection.RollbackTransaction();

                    response.Success = false;
                    response.Object = null;
                    response.Timestamp = DateTime.UtcNow;
            #if DEBUG
                    response.Message = e.Message + e.StackTrace;
            #else
                            response.Message = "Import failed! An internal error occurred!";
            #endif
                }
                finally
                {
                    reader.Close();
                    fileStream.Close();
                }

                return response;
            }
        }
Пример #6
0
        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);
                }


                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);

                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 = DbContext.Current.RecordRepository;
                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);
            }
        }