diff --git a/CHANGELOG.md b/CHANGELOG.md index 412ea41f..9212ccd5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +* [PR-281](https://github.com/itk-dev/economics/pull/281) + Reworked index page columns and added project lead filter. + Added createdAt/updatedAt as read-only text on edit page. + Moved cybersecurity price to cybersecurity agreement entity. * [PR-280](https://github.com/itk-dev/economics/pull/280) Extended service agreement overview with new and updated fields. Tweaked form styling. diff --git a/migrations/Version20260410104113.php b/migrations/Version20260410131200.php similarity index 65% rename from migrations/Version20260410104113.php rename to migrations/Version20260410131200.php index 20b0c919..bb0e401d 100644 --- a/migrations/Version20260410104113.php +++ b/migrations/Version20260410131200.php @@ -10,7 +10,7 @@ /** * Auto-generated Migration: Please modify to your needs! */ -final class Version20260410104113 extends AbstractMigration +final class Version20260410131200 extends AbstractMigration { public function getDescription(): string { @@ -20,12 +20,14 @@ public function getDescription(): string public function up(Schema $schema): void { // this up() migration is auto-generated, please modify it to your needs - $this->addSql('ALTER TABLE service_agreement ADD system_owner_notices JSON NOT NULL COMMENT \'(DC2Type:json)\', ADD is_eol TINYINT(1) NOT NULL, ADD leantime_url VARCHAR(255) DEFAULT NULL, ADD client_contact_name VARCHAR(255) DEFAULT NULL, ADD client_contact_email VARCHAR(255) DEFAULT NULL, ADD dedicated_server TINYINT(1) NOT NULL, ADD server_size VARCHAR(255) DEFAULT NULL, ADD cybersecurity_price DOUBLE PRECISION DEFAULT NULL, ADD git_repos LONGTEXT DEFAULT NULL, ADD created_by VARCHAR(255) DEFAULT NULL, ADD updated_by VARCHAR(255) DEFAULT NULL, ADD created_at DATETIME NOT NULL, ADD updated_at DATETIME NOT NULL, DROP system_owner_notice, CHANGE valid_to valid_to DATETIME DEFAULT NULL'); + $this->addSql('ALTER TABLE cybersecurity_agreement ADD price DOUBLE PRECISION DEFAULT NULL'); + $this->addSql('ALTER TABLE service_agreement ADD system_owner_notices JSON NOT NULL COMMENT \'(DC2Type:json)\', ADD is_eol TINYINT(1) NOT NULL, ADD leantime_url VARCHAR(255) DEFAULT NULL, ADD client_contact_name VARCHAR(255) DEFAULT NULL, ADD client_contact_email VARCHAR(255) DEFAULT NULL, ADD dedicated_server TINYINT(1) NOT NULL, ADD server_size VARCHAR(255) DEFAULT NULL, ADD git_repos LONGTEXT DEFAULT NULL, ADD created_by VARCHAR(255) DEFAULT NULL, ADD updated_by VARCHAR(255) DEFAULT NULL, ADD created_at DATETIME NOT NULL, ADD updated_at DATETIME NOT NULL, DROP system_owner_notice, CHANGE valid_to valid_to DATETIME DEFAULT NULL'); } public function down(Schema $schema): void { // this down() migration is auto-generated, please modify it to your needs - $this->addSql('ALTER TABLE service_agreement ADD system_owner_notice VARCHAR(255) NOT NULL, DROP system_owner_notices, DROP is_eol, DROP leantime_url, DROP client_contact_name, DROP client_contact_email, DROP dedicated_server, DROP server_size, DROP cybersecurity_price, DROP git_repos, DROP created_by, DROP updated_by, DROP created_at, DROP updated_at, CHANGE valid_to valid_to DATETIME NOT NULL'); + $this->addSql('ALTER TABLE cybersecurity_agreement DROP price'); + $this->addSql('ALTER TABLE service_agreement ADD system_owner_notice VARCHAR(255) NOT NULL, DROP system_owner_notices, DROP is_eol, DROP leantime_url, DROP client_contact_name, DROP client_contact_email, DROP dedicated_server, DROP server_size, DROP git_repos, DROP created_by, DROP updated_by, DROP created_at, DROP updated_at, CHANGE valid_to valid_to DATETIME NOT NULL'); } } diff --git a/src/Controller/ServiceAgreementController.php b/src/Controller/ServiceAgreementController.php index 232658dd..894ff6f6 100644 --- a/src/Controller/ServiceAgreementController.php +++ b/src/Controller/ServiceAgreementController.php @@ -28,6 +28,7 @@ final class ServiceAgreementController extends AbstractController public function index(Request $request, ServiceAgreementRepository $serviceAgreementRepository, CybersecurityAgreementRepository $cybersecurityAgreementRepository): Response { $serviceAgreementFilterData = new ServiceAgreementFilterData(); + $serviceAgreementFilterData->active = true; $form = $this->createForm(ServiceAgreementFilterType::class, $serviceAgreementFilterData); $form->handleRequest($request); diff --git a/src/Entity/CybersecurityAgreement.php b/src/Entity/CybersecurityAgreement.php index ec20ef27..34a9d473 100644 --- a/src/Entity/CybersecurityAgreement.php +++ b/src/Entity/CybersecurityAgreement.php @@ -20,6 +20,9 @@ class CybersecurityAgreement #[ORM\Column(nullable: true)] private ?float $quarterlyHours = null; + #[ORM\Column(nullable: true)] + private ?float $price = null; + #[ORM\Column(length: 255, nullable: true)] private ?string $note = null; @@ -52,6 +55,18 @@ public function setQuarterlyHours(float $quarterlyHours): static return $this; } + public function getPrice(): ?float + { + return $this->price; + } + + public function setPrice(?float $price): static + { + $this->price = $price; + + return $this; + } + public function getNote(): ?string { return $this->note; diff --git a/src/Entity/ServiceAgreement.php b/src/Entity/ServiceAgreement.php index eb5a6d27..f2834f67 100644 --- a/src/Entity/ServiceAgreement.php +++ b/src/Entity/ServiceAgreement.php @@ -69,9 +69,6 @@ class ServiceAgreement extends AbstractBaseEntity #[ORM\Column(enumType: ServerSizeEnum::class, nullable: true)] private ?ServerSizeEnum $serverSize = null; - #[ORM\Column(nullable: true)] - private ?float $cybersecurityPrice = null; - #[ORM\Column(type: Types::TEXT, nullable: true)] private ?string $gitRepos = null; @@ -291,18 +288,6 @@ public function setServerSize(?ServerSizeEnum $serverSize): static return $this; } - public function getCybersecurityPrice(): ?float - { - return $this->cybersecurityPrice; - } - - public function setCybersecurityPrice(?float $cybersecurityPrice): static - { - $this->cybersecurityPrice = $cybersecurityPrice; - - return $this; - } - public function getGitRepos(): ?string { return $this->gitRepos; diff --git a/src/Form/CybersecurityAgreementType.php b/src/Form/CybersecurityAgreementType.php index d66b37ff..b611f9d0 100644 --- a/src/Form/CybersecurityAgreementType.php +++ b/src/Form/CybersecurityAgreementType.php @@ -23,6 +23,15 @@ public function buildForm(FormBuilderInterface $builder, array $options): void 'row_attr' => ['class' => 'form-row'], 'required' => false, ]) + ->add('price', NumberType::class, [ + 'label' => 'service_agreement.cybersecurity_price', + 'label_attr' => ['class' => 'label'], + 'attr' => ['class' => 'form-element'], + 'help_attr' => ['class' => 'form-help'], + 'row_attr' => ['class' => 'form-row'], + 'html5' => true, + 'required' => false, + ]) ->add('note', TextareaType::class, [ 'label' => 'service_agreement.note', 'label_attr' => ['class' => 'label'], diff --git a/src/Form/ServiceAgreementFilterType.php b/src/Form/ServiceAgreementFilterType.php index b00c45bc..fa88e66e 100644 --- a/src/Form/ServiceAgreementFilterType.php +++ b/src/Form/ServiceAgreementFilterType.php @@ -2,8 +2,11 @@ namespace App\Form; +use App\Entity\Worker; use App\Enum\HostingProviderEnum; use App\Model\Invoices\ServiceAgreementFilterData; +use Doctrine\ORM\EntityRepository; +use Symfony\Bridge\Doctrine\Form\Type\EntityType; use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\Extension\Core\Type\ChoiceType; use Symfony\Component\Form\Extension\Core\Type\SearchType; @@ -56,6 +59,18 @@ public function buildForm(FormBuilderInterface $builder, array $options): void 'service_agreement.no' => false, ], 'attr' => ['class' => 'form-element'], + ]) + ->add('projectLead', EntityType::class, [ + 'required' => false, + 'class' => Worker::class, + 'label' => 'service_agreement.project_lead', + 'label_attr' => ['class' => 'label'], + 'attr' => ['class' => 'form-element'], + 'placeholder' => '', + 'query_builder' => fn (EntityRepository $er) => $er->createQueryBuilder('w') + ->innerJoin('App\Entity\ServiceAgreement', 'sa', 'WITH', 'sa.projectLead = w') + ->groupBy('w.id') + ->orderBy('w.name', 'ASC'), ]); } diff --git a/src/Form/ServiceAgreementType.php b/src/Form/ServiceAgreementType.php index f0ccfda5..1ef8b1bd 100644 --- a/src/Form/ServiceAgreementType.php +++ b/src/Form/ServiceAgreementType.php @@ -178,15 +178,6 @@ public function buildForm(FormBuilderInterface $builder, array $options): void 'help_attr' => ['class' => 'form-help'], 'row_attr' => ['class' => 'form-row'], ]) - ->add('cybersecurityPrice', NumberType::class, [ - 'label' => 'service_agreement.cybersecurity_price', - 'label_attr' => ['class' => 'label'], - 'attr' => ['class' => 'form-element'], - 'help_attr' => ['class' => 'form-help'], - 'row_attr' => ['class' => 'form-row'], - 'html5' => true, - 'required' => false, - ]) ->add('gitRepos', TextareaType::class, [ 'label' => 'service_agreement.git_repos', 'label_attr' => ['class' => 'label'], diff --git a/src/Model/Invoices/ServiceAgreementFilterData.php b/src/Model/Invoices/ServiceAgreementFilterData.php index 1d47132f..ec70554f 100644 --- a/src/Model/Invoices/ServiceAgreementFilterData.php +++ b/src/Model/Invoices/ServiceAgreementFilterData.php @@ -2,6 +2,7 @@ namespace App\Model\Invoices; +use App\Entity\Worker; use App\Enum\HostingProviderEnum; class ServiceAgreementFilterData @@ -11,4 +12,5 @@ class ServiceAgreementFilterData public ?bool $cybersecurityAgreement = null; public ?HostingProviderEnum $hostingProvider = null; public ?bool $active = null; + public ?Worker $projectLead = null; } diff --git a/src/Repository/ServiceAgreementRepository.php b/src/Repository/ServiceAgreementRepository.php index 645e7937..28e8ed46 100644 --- a/src/Repository/ServiceAgreementRepository.php +++ b/src/Repository/ServiceAgreementRepository.php @@ -59,6 +59,11 @@ public function getFilteredPagination(ServiceAgreementFilterData $serviceAgreeme ->setParameter('active', $serviceAgreementFilterData->active); } + if (!is_null($serviceAgreementFilterData->projectLead)) { + $qb->andWhere('service_agreement.projectLead = :projectLead') + ->setParameter('projectLead', $serviceAgreementFilterData->projectLead); + } + return $this->paginator->paginate( $qb, $page, diff --git a/templates/service_agreement/edit.html.twig b/templates/service_agreement/edit.html.twig index ea7d1eeb..5bf617ba 100644 --- a/templates/service_agreement/edit.html.twig +++ b/templates/service_agreement/edit.html.twig @@ -5,8 +5,13 @@ {% block content %}
{{ 'service_agreement.created_at'|trans }}: {{ service_agreement.createdAt ? service_agreement.createdAt|date('d/m Y H:i') : '-' }}
+{{ 'service_agreement.updated_at'|trans }}: {{ service_agreement.updatedAt ? service_agreement.updatedAt|date('d/m Y H:i') : '-' }}
+