I am encountering the following error when trying to save a Custom Entity:
EspoCRM Version: 8.1.1
PHP Version: PHP 8.2.7 (cli) (built: Jun 9 2023 19:37:27) (NTS)
STEPS TO REPRODUCE
My Custom Entity inside a custom Module is Defined as follows.
File: custom/Espo/Modules/Natera/Resources/metadata/entityDefs/NateraJob.json
File: custom/Espo/Modules/Natera/Entities/NateraJob.php
When I try to update an Entity I get the above error.
For testing to recreate the error, I created code as follows inside a CLI job:
Output from code:
Code:
Espo\Core\FieldProcessing\NextNumber\BeforeSaveProcessor::process(): Argument #1 ($entity) must be of type Espo\Core\ORM\Entity, Espo\Modules\Natera\Entities\NateraJob given, called in /App/application/Espo/Hooks/Common/NextNumber.php on line 51
EspoCRM Version: 8.1.1
PHP Version: PHP 8.2.7 (cli) (built: Jun 9 2023 19:37:27) (NTS)
STEPS TO REPRODUCE
My Custom Entity inside a custom Module is Defined as follows.
File: custom/Espo/Modules/Natera/Resources/metadata/entityDefs/NateraJob.json
PHP Code:
{
"fields": {
"jobId": {
"label": "Natera Job ID",
"type": "varchar",
"length": 12,
"required": true,
"readOnlyAfterCreate": true
},
"assignmentId": {
"label": "Assignment",
"type": "varchar",
"length": 17,
"required": false
},
"technicianId": {
"label": "Natera Technician ID",
"type": "varchar",
"length": 12,
"required": true
},
"status": {
"label": "Job Status",
"type": "enum",
"required": true,
"default": "available",
"options": [
"available",
"published",
"assigned",
"scheduled",
"on_the_way",
"on_site",
"in_progress",
"completed",
"cancelled",
"error"
]
},
"mpxData": {
"type": "text",
"required": true,
"isEncrypted": true
},
"mpxLog": {
"type": "text",
"required": true
},
"createdAt": {
"type": "datetime",
"readOnly": true
},
"modifiedAt": {
"type": "datetime",
"readOnly": true
},
"address": {
"type": "address",
"notStorable": true,
"utility": true
}
},
"indexes": {
"natera_id": {
"columns": ["jobId"],
"unique": true
},
"entity_id": {
"columns": ["assignmentId"]
},
"by_status": {
"columns": [
"status",
"createdAt"
]
}
},
"collection": {
"orderBy": "createdAt",
"order": "asc",
"textFilterFields": [
"status"
]
}
}
PHP Code:
namespace Espo\Modules\Natera\Entities;
use Espo\ORM\BaseEntity;
use Espo\ORM\EntityManager;
use Espo\ORM\Value\ValueAccessorFactory;
use Espo\Core\Utils\Crypt;
class NateraJob extends BaseEntity
{
private $isEncrypted;
public function __construct(
string $entityType,
array $defs,
?EntityManager $entityManager = null,
?ValueAccessorFactory $valueAccessorFactory = null,
private Crypt $crypt,
) {
parent::__construct(
$entityType,
$defs,
$entityManager,
$valueAccessorFactory
);
$this->isEncrypted = [];
foreach ($defs['fields'] as $field => $value) {
if (array_key_exists('isEncrypted', $value) && $value['isEncrypted']) {
$this->isEncrypted[] = $field;
}
}
}
protected function setInContainer(string $attribute, $value): void
{
if (in_array($attribute, $this->isEncrypted)) {
$value = $this->crypt->encrypt($value);
}
parent::setInContainer($attribute, $value);
return;
}
public function setFetched(string $attribute, $value): void
{
if (in_array($attribute, $this->isEncrypted)) {
$value = $this->crypt->decrypt($value);
parent::setInContainer($attribute, $value);
}
parent::setFetched($attribute, $value);
}
protected function getFromContainer(string $attribute)
{
$value = parent::getFromContainer($attribute);
if (in_array($attribute, $this->isEncrypted)) {
return $this->crypt->decrypt($value);
}
return $value;
}
public function getFetched(string $attribute)
{
$value = parent::getFetched($attribute);
if (in_array($attribute, $this->isEncrypted) && !is_null($value)) {
$value = $this->crypt->decrypt($value);
}
return $value;
}
}
For testing to recreate the error, I created code as follows inside a CLI job:
PHP Code:
try {
$em = $this->container->get('entityManager');
$entity = $em->getEntityById('NateraJob', '65e26caac9c5d60f9');
print_r($entity->getValueMap());
$entity->set('assignmentId', '65a0d16b7f222e498');
$em->saveEntity($entity, ['SKIP_NATERA' => true]);
} catch (\Throwable $error) {
echo $error->getMessage();
echo "\n";
echo $error->getTraceAsString();
}
Code:
stdClass Object
(
[id] => 65e26caac9c5d60f9
[deleted] =>
[jobId] => h9c74fg2
[assignmentId] =>
[technicianId] => wosv2mwl
[status] => scheduled
[mpxData] => {"id":"h9c74fg2",/** removed private data **/}
[mpxLog] => [{"at":"2024-01-12 19:33:19","type":"EVENT","message":"Complete Job Data Updated"},{"at":"2024-01-17 17:55:25","type":"EVENT","message":"Job Status changed to ASSIGNED"},{"at":"2024-01-17 17:55:25","type":"EVENT","message":"Job assignee changed"},{"at":"2024-01-17 17:55:25","type":"EVENT","message":"Complete Job Data Updated"},{"at":"2024-01-31 15:58:42","type":"EVENT","message":"Job Status changed to SCHEDULED"},{"at":"2024-01-31 15:58:42","type":"EVENT","message":"Job startTime changed"},{"at":"2024-03-02 00:02:50","type":"EVENT","message":"Job Migrated"}]
[createdAt] => 2024-03-02 00:02:50
[modifiedAt] => 2024-03-02 00:02:50
)
Espo\Core\FieldProcessing\NextNumber\BeforeSaveProcessor::process(): Argument #1 ($entity) must be of type Espo\Core\ORM\Entity, Espo\Modules\Natera\Entities\NateraJob given, called in /App/application/Espo/Hooks/Common/NextNumber.php on line 51
#0 /App/application/Espo/Hooks/Common/NextNumber.php(51): Espo\Core\FieldProcessing\NextNumber\BeforeSaveProcessor->process()
#1 /App/application/Espo/Core/Hook/GeneralInvoker.php(186): Espo\Hooks\Common\NextNumber->beforeSave()
#2 /App/application/Espo/Core/HookManager.php(118): Espo\Core\Hook\GeneralInvoker->invoke()
#3 /App/application/Espo/Core/Repositories/Database.php(298): Espo\Core\HookManager->process()
#4 /App/application/Espo/ORM/Repository/RDBRepository.php(139): Espo\Core\Repositories\Database->beforeSave()
#5 /App/application/Espo/Core/Repositories/Database.php(136): Espo\ORM\Repository\RDBRepository->save()
#6 /App/application/Espo/ORM/EntityManager.php(244): Espo\Core\Repositories\Database->save()
#7 /App/custom/Espo/Modules/Natera/Services/Utils/Tasks/Task/Test.php(25): Espo\ORM\EntityManager->saveEntity()
#8 /App/custom/Espo/Modules/Natera/Services/Utils/Tasks/TaskManager.php(49): Espo\Modules\Natera\Services\Utils\Tasks\Task\Test->execute()
#9 /App/application/Espo/Core/Job/JobRunner.php(233): Espo\Modules\Natera\Services\Utils\Tasks\TaskManager->run()
#10 /App/application/Espo/Core/Job/JobRunner.php(194): Espo\Core\Job\JobRunner->runJob()
#11 /App/application/Espo/Core/Job/JobRunner.php(123): Espo\Core\Job\JobRunner->runJobNamed()
#12 /App/application/Espo/Core/Job/JobRunner.php(77): Espo\Core\Job\JobRunner->runInternal()
#13 /App/application/Espo/Core/Job/JobManager.php(145): Espo\Core\Job\JobRunner->runThrowingException()
#14 /App/application/Espo/Core/Console/Commands/RunJob.php(92): Espo\Core\Job\JobManager->runJob()
#15 /App/application/Espo/Core/Console/CommandManager.php(95): Espo\Core\Console\Commands\RunJob->run()
#16 /App/application/Espo/Core/ApplicationRunners/Command.php(51): Espo\Core\Console\CommandManager->run()
#17 /App/application/Espo/Core/Application/RunnerRunner.php(84): Espo\Core\ApplicationRunners\Command->run()
#18 /App/application/Espo/Core/Application.php(78): Espo\Core\Application\RunnerRunner->run()
#19 /App/command.php(35): Espo\Core\Application->run()
#20 /App/bin/command(4): include('...')
#21 {main}

Comment