Fix merge service and passing of json to vue

This commit is contained in:
2025-03-06 18:34:27 +01:00
parent e1d308fd97
commit ae679e6997
5 changed files with 162 additions and 122 deletions

View File

@@ -12,6 +12,7 @@ declare(strict_types=1);
namespace Chill\PersonBundle\Service\AccompanyingPeriodWork;
use Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodWork;
use Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodWorkReferrerHistory;
use Doctrine\DBAL\Exception;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\Mapping\ClassMetadata;
@@ -24,57 +25,51 @@ class AccompanyingPeriodWorkMergeService
* @throws Exception
*/
public function merge(AccompanyingPeriodWork $toKeep, AccompanyingPeriodWork $toDelete): void
{
// Transfer non-duplicate data
$this->transferData($toKeep, $toDelete);
// Update linked entities
$this->updateReferences($toKeep, $toDelete);
$this->em->remove($toDelete);
$this->em->flush();
}
/**
* @throws Exception
*/
private function transferData(AccompanyingPeriodWork $toKeep, AccompanyingPeriodWork $toDelete): void
{
$conn = $this->em->getConnection();
$sqlStatements = [
$this->generateStartDateSQL(),
$this->generateEndDateSQL(),
$this->generateCommentSQL(),
];
$conn->beginTransaction();
try {
foreach ($sqlStatements as $sql) {
$conn->executeQuery($sql, ['toDelete' => $toDelete->getId(), 'toKeep' => $toKeep->getId()]);
$queries = array_merge(
$this->updateReferences($toKeep, $toDelete),
$this->generateStartDateSQL($toDelete, $toKeep),
$this->generateEndDateSQL($toDelete, $toKeep),
$this->removeAccompanyingPeriodWork($toDelete)
);
foreach ($queries as $query) {
$conn->executeStatement($query['sql'], $query['params']);
}
$conn->commit();
} catch (\Exception $e) {
dump($e->getMessage());
$conn->rollBack();
throw $e;
}
}
private function generateStartDateSQL(): string
private function generateStartDateSQL(AccompanyingPeriodWork $toDelete, AccompanyingPeriodWork $toKeep): array
{
return '
UPDATE chill_person_accompanying_period_work
$queries = [];
$queries[] = [
'sql' => 'UPDATE chill_person_accompanying_period_work
SET startdate = LEAST(
COALESCE((SELECT startdate FROM chill_person_accompanying_period_work WHERE id = :toDelete), startdate),
startdate
)
WHERE id = :toKeep';
WHERE id = :toKeep',
'params' => ['toDelete' => $toDelete->getId(), 'toKeep' => $toKeep->getId()],
];
return $queries;
}
private function generateEndDateSQL(): string
private function generateEndDateSQL(AccompanyingPeriodWork $toDelete, AccompanyingPeriodWork $toKeep): array
{
return '
$queries = [];
$queries[] = [
'sql' => '
UPDATE chill_person_accompanying_period_work
SET enddate =
CASE
@@ -86,89 +81,71 @@ class AccompanyingPeriodWorkMergeService
enddate
)
END
WHERE id = :toKeep';
WHERE id = :toKeep',
'params' => ['toDelete' => $toDelete->getId(), 'toKeep' => $toKeep->getId()],
];
return $queries;
}
private function generateCommentSQL(): string
{
return "
UPDATE chill_person_accompanying_period_work
SET note = CONCAT_WS(
'\n',
NULLIF(TRIM(note), ''),
NULLIF(TRIM((SELECT note FROM chill_person_accompanying_period_work WHERE id = :toDelete)), '')
)
WHERE id = :toKeep";
}
/**
* @throws Exception
*/
private function updateReferences(AccompanyingPeriodWork $toKeep, AccompanyingPeriodWork $toDelete): void
private function updateReferences(AccompanyingPeriodWork $toKeep, AccompanyingPeriodWork $toDelete): array
{
$queries = [];
$allMeta = $this->em->getMetadataFactory()->getAllMetadata();
$conn = $this->em->getConnection();
$sqlStatements = [];
foreach ($allMeta as $meta) {
if ($meta->isMappedSuperclass) {
continue;
}
$tableName = $meta->getTableName();
foreach ($meta->getAssociationMappings() as $assoc) {
if (AccompanyingPeriodWork::class !== $assoc['targetEntity']) {
if (AccompanyingPeriodWork::class !== $assoc['targetEntity'] && AccompanyingPeriodWork::class !== $assoc['sourceEntity']) {
continue;
}
if ($assoc['type'] & ClassMetadata::TO_ONE) {
if ('handlingThirdparty' === $assoc['fieldName']) {
continue;
}
$sqlStatements[] = $this->generateToOneUpdateQuery($meta, $assoc);
}
if (($assoc['type'] & ClassMetadata::TO_ONE) !== 0) {
$joinColumn = $meta->getSingleAssociationJoinColumnName($assoc['fieldName']);
if ($assoc['type'] & ClassMetadata::TO_MANY) {
if (!isset($assoc['joinTable'])) {
continue;
if (AccompanyingPeriodWorkReferrerHistory::class === $assoc['sourceEntity']) {
$queries[] = [
'sql' => "DELETE FROM {$tableName} WHERE {$joinColumn} = :toDelete",
'params' => ['toKeep' => $toKeep->getId(), 'toDelete' => $toDelete->getId()],
];
}
$queries[] = [
'sql' => "UPDATE {$tableName} SET {$joinColumn} = :toKeep WHERE {$joinColumn} = :toDelete",
'params' => ['toKeep' => $toKeep->getId(), 'toDelete' => $toDelete->getId()],
];
} elseif (8 === $assoc['type'] && isset($assoc['joinTable'])) {
if ($assoc['isOwningSide']) {
$joinTable = $assoc['joinTable']['name'];
$joinColumn = $assoc['joinTable']['joinColumns'][0]['name'];
$queries[] = [
'sql' => "UPDATE {$joinTable} SET {$joinColumn} = :toKeep WHERE {$joinColumn} = :toDelete AND NOT EXISTS (SELECT 1 FROM {$joinTable} WHERE {$joinColumn} = :toKeep)",
'params' => ['toDelete' => $toDelete->getId(), 'toKeep' => $toKeep->getId()],
];
$queries[] = [
'sql' => "DELETE FROM {$joinTable} WHERE {$joinColumn} = :toDelete",
'params' => ['toDelete' => $toDelete->getId()],
];
}
$sqlStatements = array_merge($sqlStatements, $this->generateToManyUpdateQueries($assoc));
}
}
}
$conn->beginTransaction();
try {
foreach ($sqlStatements as $sql) {
$conn->executeStatement($sql, ['toDelete' => $toDelete->getId(), 'toKeep' => $toKeep->getId()]);
}
$conn->commit();
} catch (\Exception $e) {
$conn->rollBack();
throw $e;
}
return $queries;
}
private function generateToOneUpdateQuery(ClassMetadata $meta, array $assoc): string
public function removeAccompanyingPeriodWork(AccompanyingPeriodWork $toDelete): array
{
$tableName = $meta->getTableName();
$joinColumn = $meta->getSingleAssociationJoinColumnName($assoc['fieldName']);
return "UPDATE {$tableName} SET {$joinColumn} = :toKeep WHERE {$joinColumn} = :toDelete";
}
private function generateToManyUpdateQueries(array $assoc): array
{
$sqls = [];
$joinTable = $assoc['joinTable']['name'];
$owningColumn = $assoc['joinTable']['joinColumns'][0]['name'];
$inverseColumn = $assoc['joinTable']['inverseJoinColumns'][0]['name'];
// Insert relations, skip already existing ones
$sqls[] = "INSERT IGNORE INTO {$joinTable} ({$owningColumn}, {$inverseColumn})
SELECT :toKeep, {$inverseColumn} FROM {$joinTable} WHERE {$owningColumn} = :toDelete";
// Delete old references
$sqls[] = "DELETE FROM {$joinTable} WHERE {$owningColumn} = :toDelete";
return $sqls;
return [[
'sql' => 'DELETE FROM chill_person_accompanying_period_work WHERE id = :toDelete',
'params' => ['toDelete' => $toDelete->getId()],
]];
}
}