From 7e5acf044710dd3f5d9b4ade1fe93b7116a803d9 Mon Sep 17 00:00:00 2001 From: Adrien Crivelli Date: Mon, 10 Oct 2022 20:59:44 +0200 Subject: [PATCH] Update date is equal to creation date #9021 When creating something the update date is also set, instead of being left to `null`. This matches what is typically done on filesystem. And most importantly it allow for huge optimization when sorting things by their latest update, since we do not need to compute "either creation date or update date". That allows MariaDB DB to optimize the query, and even more so if we add an index on that single column. --- client/app/admin/admin-routing.module.ts | 9 +---- .../bookables/bookables.component.html | 6 +-- .../expenseClaims.component.html | 6 +-- .../expenseClaims/expenseClaims.component.ts | 2 +- .../finances/finances.component.html | 4 +- .../components/finances/finances.component.ts | 2 +- config/autoload/doctrine.global.php | 1 - package.json | 4 +- .../Api/Input/Sorting/LatestModification.php | 29 -------------- .../Migration/Version20221010154735.php | 39 +++++++++++++++++++ server/Application/Model/AbstractModel.php | 9 +++-- .../Api/Input/Sorting/AgeTest.php | 5 +++ .../Input/Sorting/LatestModificationTest.php | 33 ---------------- yarn.lock | 16 ++++---- 14 files changed, 71 insertions(+), 94 deletions(-) delete mode 100644 server/Application/Api/Input/Sorting/LatestModification.php create mode 100644 server/Application/Migration/Version20221010154735.php delete mode 100644 tests/ApplicationTest/Api/Input/Sorting/LatestModificationTest.php diff --git a/client/app/admin/admin-routing.module.ts b/client/app/admin/admin-routing.module.ts index 168eb1b5e..5f0a32822 100644 --- a/client/app/admin/admin-routing.module.ts +++ b/client/app/admin/admin-routing.module.ts @@ -251,14 +251,7 @@ const routes: Routes = [ seo: { title: 'Réservables', } as NaturalSeo, - selectedColumns: [ - 'name', - 'code', - 'purchasePrice', - 'initialPrice', - 'periodicPrice', - 'latestModification', - ], + selectedColumns: ['name', 'code', 'purchasePrice', 'initialPrice', 'periodicPrice', 'updateDate'], }, }, { diff --git a/client/app/admin/bookables/bookables/bookables.component.html b/client/app/admin/bookables/bookables/bookables.component.html index e72aec92c..1395b53f7 100644 --- a/client/app/admin/bookables/bookables/bookables.component.html +++ b/client/app/admin/bookables/bookables/bookables.component.html @@ -21,7 +21,7 @@ Prix d'achat Prix initial Prix périodique - Dernière modification + Dernière modification Utilisations Nombre d'utilisations Dernière vérification @@ -115,12 +115,12 @@ - + Dernière modification - {{ element.updateDate || element.creationDate | swissDate }} + {{ element.updateDate | swissDate }} diff --git a/client/app/admin/expenseClaim/expenseClaims/expenseClaims.component.html b/client/app/admin/expenseClaim/expenseClaims/expenseClaims.component.html index 5d03156de..bce6f2d7c 100644 --- a/client/app/admin/expenseClaim/expenseClaims/expenseClaims.component.html +++ b/client/app/admin/expenseClaim/expenseClaims/expenseClaims.component.html @@ -17,7 +17,7 @@ Nom Membre - Dernière modification + Dernière modification Status Type Remarques @@ -74,12 +74,12 @@ - + Dernière modification - {{ element.updateDate || element.creationDate | swissDate }} + {{ element.updateDate | swissDate }} diff --git a/client/app/admin/expenseClaim/expenseClaims/expenseClaims.component.ts b/client/app/admin/expenseClaim/expenseClaims/expenseClaims.component.ts index 461a3c23f..0882ba3b2 100644 --- a/client/app/admin/expenseClaim/expenseClaims/expenseClaims.component.ts +++ b/client/app/admin/expenseClaim/expenseClaims/expenseClaims.component.ts @@ -10,7 +10,7 @@ import {PermissionsService} from '../../../shared/services/permissions.service'; styleUrls: ['./expenseClaims.component.scss'], }) export class ExpenseClaimsComponent extends NaturalAbstractList implements OnInit { - public selectedColumns = ['name', 'owner', 'latestModification', 'status', 'type', 'remarks', 'amount']; + public selectedColumns = ['name', 'owner', 'updateDate', 'status', 'type', 'remarks', 'amount']; public constructor( expenseClaimService: ExpenseClaimService, diff --git a/client/app/profile/components/finances/finances.component.html b/client/app/profile/components/finances/finances.component.html index 3a1629ff3..ce05b05a6 100644 --- a/client/app/profile/components/finances/finances.component.html +++ b/client/app/profile/components/finances/finances.component.html @@ -86,10 +86,10 @@

Dépenses et remboursements en attente {{ expenseClaim.description }} - + Dernière modification - {{ expenseClaim.updateDate || expenseClaim.creationDate | date: 'dd.MM.y' }} + {{ expenseClaim.updateDate | date: 'dd.MM.y' }} diff --git a/client/app/profile/components/finances/finances.component.ts b/client/app/profile/components/finances/finances.component.ts index 4e22f14e5..b33a5531b 100644 --- a/client/app/profile/components/finances/finances.component.ts +++ b/client/app/profile/components/finances/finances.component.ts @@ -26,7 +26,7 @@ export class FinancesComponent extends NaturalAbstractController implements OnIn @Input() public user!: CurrentUserForProfile_viewer; public runningExpenseClaimsDS!: NaturalDataSource; - public expenseClaimsColumns = ['name', 'latestModification', 'status', 'type', 'remarks', 'amount', 'cancel']; + public expenseClaimsColumns = ['name', 'updateDate', 'status', 'type', 'remarks', 'amount', 'cancel']; public ibanLocked = true; diff --git a/config/autoload/doctrine.global.php b/config/autoload/doctrine.global.php index 0e722b614..912778591 100644 --- a/config/autoload/doctrine.global.php +++ b/config/autoload/doctrine.global.php @@ -40,7 +40,6 @@ ], 'datetime_functions' => [], 'string_functions' => [ - 'greatest' => \DoctrineExtensions\Query\Mysql\Greatest::class, 'if' => \DoctrineExtensions\Query\Mysql\IfElse::class, 'ifnull' => \DoctrineExtensions\Query\Mysql\IfNull::class, ], diff --git a/package.json b/package.json index c4e66ddaa..80639196a 100644 --- a/package.json +++ b/package.json @@ -28,8 +28,8 @@ "@angular/router": "^14.1.1", "@apollo/client": "^3.6.9", "@ecodev/fab-speed-dial": "^11.0.0", - "@ecodev/natural": "^45.0.1", - "@ecodev/natural-editor": "^45.0.1", + "@ecodev/natural": "^45.2.0", + "@ecodev/natural-editor": "^45.2.0", "@graphql-tools/mock": "^8.7.1", "angular-particle-effect-button": "^0.0.50", "apollo": "^2.34.0", diff --git a/server/Application/Api/Input/Sorting/LatestModification.php b/server/Application/Api/Input/Sorting/LatestModification.php deleted file mode 100644 index 005cb328b..000000000 --- a/server/Application/Api/Input/Sorting/LatestModification.php +++ /dev/null @@ -1,29 +0,0 @@ -addOrderBy($latestDate, $order); - } -} diff --git a/server/Application/Migration/Version20221010154735.php b/server/Application/Migration/Version20221010154735.php new file mode 100644 index 000000000..9baf6333f --- /dev/null +++ b/server/Application/Migration/Version20221010154735.php @@ -0,0 +1,39 @@ +connection->executeQuery('SHOW TRIGGERS;')->fetchFirstColumn(); + foreach ($triggers as $trigger) { + $this->addSql("DROP TRIGGER `$trigger`"); + } + + $this->addSql('UPDATE `accounting_document` SET updater_id = creator_id, update_date = creation_date WHERE updater_id IS NULL AND update_date IS NULL;'); + $this->addSql('UPDATE `configuration` SET updater_id = creator_id, update_date = creation_date WHERE updater_id IS NULL AND update_date IS NULL;'); + $this->addSql('UPDATE `bookable_tag` SET updater_id = creator_id, update_date = creation_date WHERE updater_id IS NULL AND update_date IS NULL;'); + $this->addSql('UPDATE `transaction_line` SET updater_id = creator_id, update_date = creation_date WHERE updater_id IS NULL AND update_date IS NULL;'); + $this->addSql('UPDATE `user_tag` SET updater_id = creator_id, update_date = creation_date WHERE updater_id IS NULL AND update_date IS NULL;'); + $this->addSql('UPDATE `transaction` SET updater_id = creator_id, update_date = creation_date WHERE updater_id IS NULL AND update_date IS NULL;'); + $this->addSql('UPDATE `booking` SET updater_id = creator_id, update_date = creation_date WHERE updater_id IS NULL AND update_date IS NULL;'); + $this->addSql('UPDATE `bookable_metadata` SET updater_id = creator_id, update_date = creation_date WHERE updater_id IS NULL AND update_date IS NULL;'); + $this->addSql('UPDATE `country` SET updater_id = creator_id, update_date = creation_date WHERE updater_id IS NULL AND update_date IS NULL;'); + $this->addSql('UPDATE `license` SET updater_id = creator_id, update_date = creation_date WHERE updater_id IS NULL AND update_date IS NULL;'); + $this->addSql('UPDATE `log` SET updater_id = creator_id, update_date = creation_date WHERE updater_id IS NULL AND update_date IS NULL;'); + $this->addSql('UPDATE `bookable` SET updater_id = creator_id, update_date = creation_date WHERE updater_id IS NULL AND update_date IS NULL;'); + $this->addSql('UPDATE `transaction_tag` SET updater_id = creator_id, update_date = creation_date WHERE updater_id IS NULL AND update_date IS NULL;'); + $this->addSql('UPDATE `account` SET updater_id = creator_id, update_date = creation_date WHERE updater_id IS NULL AND update_date IS NULL;'); + $this->addSql('UPDATE `expense_claim` SET updater_id = creator_id, update_date = creation_date WHERE updater_id IS NULL AND update_date IS NULL;'); + $this->addSql('UPDATE `user` SET updater_id = creator_id, update_date = creation_date WHERE updater_id IS NULL AND update_date IS NULL;'); + $this->addSql('UPDATE `image` SET updater_id = creator_id, update_date = creation_date WHERE updater_id IS NULL AND update_date IS NULL;'); + $this->addSql('UPDATE `message` SET updater_id = creator_id, update_date = creation_date WHERE updater_id IS NULL AND update_date IS NULL;'); + } +} diff --git a/server/Application/Model/AbstractModel.php b/server/Application/Model/AbstractModel.php index d64a6f7fb..e58977ae5 100644 --- a/server/Application/Model/AbstractModel.php +++ b/server/Application/Model/AbstractModel.php @@ -23,7 +23,6 @@ * @API\Filter(field="custom", operator="Application\Api\Input\Operator\SearchOperatorType", type="string"), * }) * @API\Sorting({ - * "Application\Api\Input\Sorting\LatestModification", * "Application\Api\Input\Sorting\Owner" * }) */ @@ -189,8 +188,12 @@ protected function getOwnerForCreation(): ?User */ public function timestampCreation(): void { - $this->setCreationDate(new Chronos()); - $this->setCreator(User::getCurrent()); + $now = new Chronos(); + $user = User::getCurrent(); + $this->setCreationDate($now); + $this->setUpdateDate($now); + $this->setCreator($user); + $this->setUpdater($user); if (!$this->getOwner()) { $this->setOwner($this->getOwnerForCreation()); diff --git a/tests/ApplicationTest/Api/Input/Sorting/AgeTest.php b/tests/ApplicationTest/Api/Input/Sorting/AgeTest.php index 3b471fa8c..1d74f39fd 100644 --- a/tests/ApplicationTest/Api/Input/Sorting/AgeTest.php +++ b/tests/ApplicationTest/Api/Input/Sorting/AgeTest.php @@ -9,6 +9,11 @@ class AgeTest extends AbstractSorting { + protected function tearDown(): void + { + User::setCurrent(null); + } + public function testSorting(): void { $administrator = new User(User::ROLE_ADMINISTRATOR); diff --git a/tests/ApplicationTest/Api/Input/Sorting/LatestModificationTest.php b/tests/ApplicationTest/Api/Input/Sorting/LatestModificationTest.php deleted file mode 100644 index 2abcbb813..000000000 --- a/tests/ApplicationTest/Api/Input/Sorting/LatestModificationTest.php +++ /dev/null @@ -1,33 +0,0 @@ -getRepository(User::class)->getOneByLoginOrEmail('member'); - User::setCurrent($user); - - $result = $this->getSortedQueryResult(_types(), ExpenseClaim::class, 'latestModification'); - self::assertSame([ - 7005, - 7002, - 7001, - 7000, - 7003, - ], $result); - } -} diff --git a/yarn.lock b/yarn.lock index d3c1bf81a..b012fb318 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1497,10 +1497,10 @@ dependencies: tslib "^2.3.1" -"@ecodev/natural-editor@^45.0.1": - version "45.0.1" - resolved "https://registry.yarnpkg.com/@ecodev/natural-editor/-/natural-editor-45.0.1.tgz#64bf66374d6575ea6c8e4d863d3045a5bbb26cf7" - integrity sha512-lAdXR92QUXQKGodOLFiOe+0+lFOolq5C1EJMYMiPPGhPN3S5yEJyDd5fUWPLGdyUHAfezQDLvNOpvM5ebBf2mg== +"@ecodev/natural-editor@^45.2.0": + version "45.2.0" + resolved "https://registry.yarnpkg.com/@ecodev/natural-editor/-/natural-editor-45.2.0.tgz#a46a1a749b7166a3d5f863d9ea9874ae90a684e2" + integrity sha512-jcd+3i3/pRxKyQ6Y2bQD8yAzqn9SyBH/kh9314imJ2R9wNwwPc7ZH7/XLTEqpnHOdY/E0uqNM5pQOKG/h7tk4Q== dependencies: "@types/prosemirror-commands" "^1.0.4" "@types/prosemirror-dropcursor" "^1.0.3" @@ -1529,10 +1529,10 @@ prosemirror-view "^1.23.5" tslib "^2.3.0" -"@ecodev/natural@^45.0.1": - version "45.0.1" - resolved "https://registry.yarnpkg.com/@ecodev/natural/-/natural-45.0.1.tgz#4e102121fe7d49d072accb243f11ec773673f41e" - integrity sha512-E4FbzYYjiawlifo9C5xd5475WKKbfDjp1K6n95cEBf1WIdTKg7hz3zkmxEH8c3GpaFexoSnIgboO6mPALQeXOA== +"@ecodev/natural@^45.2.0": + version "45.2.0" + resolved "https://registry.yarnpkg.com/@ecodev/natural/-/natural-45.2.0.tgz#0ed34a4ee41b2d5af3306782aaba08cfe938ea29" + integrity sha512-1kGc9OExJmEHkRrWjqQ+UutTsET97GDDQnpGZTvL2IM8eREDT6zzRe3+XS41kZhhaTmb1bHNnR3S49DOJEj5wg== dependencies: tslib "^2.3.1"