diff --git a/application/Espo/ORM/DB/Mapper.php b/application/Espo/ORM/DB/Mapper.php index d5d6172179..cf7a5b01e6 100644 --- a/application/Espo/ORM/DB/Mapper.php +++ b/application/Espo/ORM/DB/Mapper.php @@ -151,15 +151,21 @@ abstract class Mapper implements IMapper { $relOpt = $entity->relations[$relationName]; - if (!isset($relOpt['entity']) || !isset($relOpt['type'])) { - throw new \LogicException("Not appropriate defenition for relationship {$relationName} in " . $entity->getEntityType() . " entity"); + if (!isset($relOpt['type'])) { + throw new \LogicException("Missing 'type' in defenition for relationship {$relationName} in " . $entity->getEntityType() . " entity"); } - $relEntityName = (!empty($relOpt['class'])) ? $relOpt['class'] : $relOpt['entity']; - $relEntity = $this->entityFactory->create($relEntityName); + if ($relOpt['type'] !== IEntity::BELONGS_TO_PARENT) { + if (!isset($relOpt['entity'])) { + throw new \LogicException("Missing 'entity' in defenition for relationship {$relationName} in " . $entity->getEntityType() . " entity"); + } - if (!$relEntity) { - return null; + $relEntityName = (!empty($relOpt['class'])) ? $relOpt['class'] : $relOpt['entity']; + $relEntity = $this->entityFactory->create($relEntityName); + + if (!$relEntity) { + return null; + } } if ($totalCount) { @@ -167,7 +173,6 @@ abstract class Mapper implements IMapper $params['aggregationBy'] = 'id'; } - if (empty($params['whereClause'])) { $params['whereClause'] = array(); } @@ -207,8 +212,8 @@ abstract class Mapper implements IMapper $params['whereClause'][$foreignKey] = $entity->get($key); if ($relType == IEntity::HAS_CHILDREN) { - $foreignType = $keySet['foreignType']; - $params['whereClause'][$foreignType] = $entity->getEntityType(); + $foreignTypeKey = $keySet['foreignTypeKey']; + $params['whereClause'][$foreignTypeKey] = $entity->getEntityType(); } if ($relType == IEntity::HAS_ONE) { @@ -282,6 +287,33 @@ abstract class Mapper implements IMapper } else { return $resultArr; } + case IEntity::BELONGS_TO_PARENT: + $foreignEntityType = $entity->get($keySet['typeKey']); + $foreignEntityId = $entity->get($key); + if (!$foreignEntityType || !$foreignEntityId) { + return null; + } + $params['whereClause'][$foreignKey] = $foreignEntityId; + $params['offset'] = 0; + $params['limit'] = 1; + + $relEntity = $this->entityFactory->create($foreignEntityType); + + $sql = $this->query->createSelectQuery($foreignEntityType, $params); + + $ps = $this->pdo->query($sql); + + if ($ps) { + foreach ($ps as $row) { + if (!$totalCount) { + $relEntity = $this->fromRow($relEntity, $row); + return $relEntity; + } else { + return $row['AggregateValue']; + } + } + } + return null; } return false; diff --git a/application/Espo/ORM/DB/Query/Base.php b/application/Espo/ORM/DB/Query/Base.php index 7dba5d0cf7..aa77acce81 100644 --- a/application/Espo/ORM/DB/Query/Base.php +++ b/application/Espo/ORM/DB/Query/Base.php @@ -978,14 +978,14 @@ abstract class Base if (isset($relOpt['foreignKey'])) { $foreignKey = $relOpt['foreignKey']; } - $foreignType = 'parentType'; + $foreignTypeKey = 'parentType'; if (isset($relOpt['foreignType'])) { - $foreignType = $relOpt['foreignType']; + $foreignTypeKey = $relOpt['foreignType']; } return array( 'key' => $key, 'foreignKey' => $foreignKey, - 'foreignType' => $foreignType, + 'foreignTypeKey' => $foreignTypeKey, ); case IEntity::MANY_MANY: @@ -1007,7 +1007,15 @@ abstract class Base 'key' => $key, 'foreignKey' => $foreignKey, 'nearKey' => $nearKey, - 'distantKey' => $distantKey, + 'distantKey' => $distantKey + ); + case IEntity::BELONGS_TO_PARENT: + $key = $this->toDb($entity->getEntityType()) . 'Id'; + $typeKey = $this->toDb($entity->getEntityType()) . 'Type'; + return array( + 'key' => $key, + 'typeKey' => $typeKey, + 'foreignKey' => 'id' ); } } diff --git a/client/src/views/admin/entity-manager/modals/edit-entity.js b/client/src/views/admin/entity-manager/modals/edit-entity.js index 597fdcd0dd..846fe1dfb5 100644 --- a/client/src/views/admin/entity-manager/modals/edit-entity.js +++ b/client/src/views/admin/entity-manager/modals/edit-entity.js @@ -196,7 +196,7 @@ Espo.define('views/admin/entity-manager/modals/edit-entity', ['views/modal', 'mo var fieldDefs = this.getMetadata().get(['entityDefs', scope, 'fields']) || {}; var optionList = Object.keys(fieldDefs).filter(function (item) { - if (!~['varchar', 'text', 'phoneNumber', 'email', 'personName'].indexOf(this.getMetadata().get(['entityDefs', scope, 'fields', item, 'type']))) { + if (!~['varchar', 'text', 'phone', 'email', 'personName'].indexOf(this.getMetadata().get(['entityDefs', scope, 'fields', item, 'type']))) { return false; } if (this.getMetadata().get(['entityDefs', scope, 'fields', item, 'disabled'])) { diff --git a/client/src/views/dashboard.js b/client/src/views/dashboard.js index 5f017ce9ab..c7782878ff 100644 --- a/client/src/views/dashboard.js +++ b/client/src/views/dashboard.js @@ -78,6 +78,10 @@ Espo.define('views/dashboard', ['view', 'lib!gridstack'], function (Dep, Gridsta }); }, this); + this.dashletIdList.forEach(function (item) { + this.clearView('dashlet-' + item); + }, this); + this.dashboardLayout = dashboardLayout; this.saveLayout(); diff --git a/client/src/views/fields/link-parent.js b/client/src/views/fields/link-parent.js index 3fbfb9b0e9..61c28b890d 100644 --- a/client/src/views/fields/link-parent.js +++ b/client/src/views/fields/link-parent.js @@ -289,6 +289,9 @@ Espo.define('views/fields/link-parent', 'views/fields/base', function (Dep) { data[this.typeName] = this.$elementType.val() || null; data[this.nameName] = this.$elementName.val() || null; data[this.idName] = this.$elementId.val() || null; + if (data[this.idName] === null) { + data[this.typeName] = null; + } return data; }, @@ -316,33 +319,54 @@ Espo.define('views/fields/link-parent', 'views/fields/base', function (Dep) { var entityName = this.$elementName.val() var entityId = this.$elementId.val(); - if (!entityId || !entityType) { + if (!entityType) { return false; } - var data = { - frontType: 'is', - type: 'and', - field: this.idName, + var data; + if (entityId) { + data = { + frontType: 'is', + type: 'and', + field: this.idName, - value: [ - { - type: 'equals', - field: this.idName, - value: entityId, - }, - { - type: 'equals', - field: this.typeName, - value: entityType, - } - ], - valueId: entityId, - valueName: entityName, - valueType: entityType, - }; + value: [ + { + type: 'equals', + field: this.idName, + value: entityId, + }, + { + type: 'equals', + field: this.typeName, + value: entityType, + } + ], + valueId: entityId, + valueName: entityName, + valueType: entityType, + }; + } else { + data = { + frontType: 'is', + type: 'and', + field: this.idName, + value: [ + { + type: 'isNotNull', + field: this.idName + }, + { + type: 'equals', + field: this.typeName, + value: entityType, + } + ], + valueType: entityType + }; + } return data; - }, + } }); });