Skip to content
Merged
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
{
Expand All @@ -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');
}
}
1 change: 1 addition & 0 deletions src/Controller/ServiceAgreementController.php
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
15 changes: 15 additions & 0 deletions src/Entity/CybersecurityAgreement.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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;
Expand Down
15 changes: 0 additions & 15 deletions src/Entity/ServiceAgreement.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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;
Expand Down
9 changes: 9 additions & 0 deletions src/Form/CybersecurityAgreementType.php
Original file line number Diff line number Diff line change
Expand Up @@ -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'],
Expand Down
15 changes: 15 additions & 0 deletions src/Form/ServiceAgreementFilterType.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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'),
]);
}

Expand Down
9 changes: 0 additions & 9 deletions src/Form/ServiceAgreementType.php
Original file line number Diff line number Diff line change
Expand Up @@ -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'],
Expand Down
2 changes: 2 additions & 0 deletions src/Model/Invoices/ServiceAgreementFilterData.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace App\Model\Invoices;

use App\Entity\Worker;
use App\Enum\HostingProviderEnum;

class ServiceAgreementFilterData
Expand All @@ -11,4 +12,5 @@ class ServiceAgreementFilterData
public ?bool $cybersecurityAgreement = null;
public ?HostingProviderEnum $hostingProvider = null;
public ?bool $active = null;
public ?Worker $projectLead = null;
}
5 changes: 5 additions & 0 deletions src/Repository/ServiceAgreementRepository.php
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
7 changes: 6 additions & 1 deletion templates/service_agreement/edit.html.twig
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,13 @@
{% block content %}
<h1 class="page-title">{{ 'service_agreement.edit'|trans }}</h1>

<div class="mb-4 text-sm text-gray-500 dark:text-gray-400">
<p>{{ 'service_agreement.created_at'|trans }}: {{ service_agreement.createdAt ? service_agreement.createdAt|date('d/m Y H:i') : '-' }}</p>
<p>{{ 'service_agreement.updated_at'|trans }}: {{ service_agreement.updatedAt ? service_agreement.updatedAt|date('d/m Y H:i') : '-' }}</p>
</div>

{{ form_start(form) }}
<div class="selections" data-controller="choices eol-required">
<div class="selections" {{ stimulus_controller('choices eol-required') }}>
{{ form_rest(form) }}
</div>
<button class="button mt-3">{{ 'clients.action_save'|trans }}</button>
Expand Down
Loading
Loading