From a6e0f1738b55142644547b060a656f878eff6928 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20B=C3=B6hmer?= Date: Sun, 8 Mar 2020 22:46:29 +0100 Subject: [PATCH] Added a basic possibility to create/edit/delete specifications for parts. --- composer.json | 1 + composer.lock | 68 +- config/bundles.php | 1 + .../Base/AbstractStructuralDBElement.php | 2 + src/Entity/Base/SpecificationsTrait.php | 54 + src/Entity/Parts/Part.php | 2 + src/Entity/Specifications/Specification.php | 214 +++ src/Form/Part/PartBaseType.php | 15 +- src/Form/SpecificationType.php | 67 + src/Migrations/Version20200308204758.php | 57 + .../Parts/edit/_specifications.html.twig | 53 + .../Parts/edit/edit_form_styles.html.twig | 18 + templates/Parts/edit/edit_part_info.html.twig | 9 + .../SchebTwoFactorBundle+intl-icu.de.xlf | 15 +- translations/messages.de.xlf | 1548 +++++++++-------- 15 files changed, 1359 insertions(+), 765 deletions(-) create mode 100644 src/Entity/Base/SpecificationsTrait.php create mode 100644 src/Entity/Specifications/Specification.php create mode 100644 src/Form/SpecificationType.php create mode 100644 src/Migrations/Version20200308204758.php create mode 100644 templates/Parts/edit/_specifications.html.twig diff --git a/composer.json b/composer.json index 52e3969c..446683ee 100644 --- a/composer.json +++ b/composer.json @@ -13,6 +13,7 @@ "beberlei/doctrineextensions": "^1.2", "doctrine/annotations": "^1.6", "doctrine/doctrine-bundle": "^2.0", + "dunglas/doctrine-json-odm": "^1.0", "florianv/swap": "^4.0", "friendsofsymfony/ckeditor-bundle": "^2.0", "gregwar/captcha-bundle": "^2.1.0", diff --git a/composer.lock b/composer.lock index 85769d98..7bb38835 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "6ebc8e9705e901be6f00f9f6418cf900", + "content-hash": "ec3095adecf24f5680e7c904c5f0731f", "packages": [ { "name": "beberlei/assert", @@ -1265,6 +1265,72 @@ ], "time": "2020-01-08T19:53:19+00:00" }, + { + "name": "dunglas/doctrine-json-odm", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/dunglas/doctrine-json-odm.git", + "reference": "70afdc23e68a31c7cbf8417f2dbb285ec929e14e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/dunglas/doctrine-json-odm/zipball/70afdc23e68a31c7cbf8417f2dbb285ec929e14e", + "reference": "70afdc23e68a31c7cbf8417f2dbb285ec929e14e", + "shasum": "" + }, + "require": { + "doctrine/orm": "^2.6.3", + "php": "^7.1", + "symfony/property-access": "^3.4 || ^4.1 || ^5.0", + "symfony/property-info": "^3.4 || ^4.1 || ^5.0", + "symfony/serializer": "^3.4 || ^4.1 || ^5.0" + }, + "require-dev": { + "doctrine/doctrine-bundle": "^1.8", + "symfony/finder": "^3.4 || ^4.1 || ^5.0", + "symfony/framework-bundle": "^3.4 || ^4.1 || ^5.0", + "symfony/phpunit-bridge": "^5.0" + }, + "suggest": { + "scienta/doctrine-json-functions": "To add support for JSON functions in DQL.", + "symfony/framework-bundle": "To use the provided bundle." + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Dunglas\\DoctrineJsonOdm\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Kévin Dunglas", + "email": "dunglas@gmail.com", + "homepage": "https://dunglas.fr" + } + ], + "description": "An object document mapper for Doctrine ORM using JSON types of modern RDBMS.", + "homepage": "https://dunglas.fr", + "keywords": [ + "database", + "json", + "mysql", + "odm", + "orm", + "postgresql", + "rdbms" + ], + "time": "2019-12-23T09:48:22+00:00" + }, { "name": "egulias/email-validator", "version": "2.1.17", diff --git a/config/bundles.php b/config/bundles.php index 6b24f5c2..18ed373d 100644 --- a/config/bundles.php +++ b/config/bundles.php @@ -23,4 +23,5 @@ return [ Scheb\TwoFactorBundle\SchebTwoFactorBundle::class => ['all' => true], R\U2FTwoFactorBundle\RU2FTwoFactorBundle::class => ['all' => true], Translation\Bundle\TranslationBundle::class => ['all' => true], + \Dunglas\DoctrineJsonOdm\Bundle\DunglasDoctrineJsonOdmBundle::class => ['all' => true], ]; diff --git a/src/Entity/Base/AbstractStructuralDBElement.php b/src/Entity/Base/AbstractStructuralDBElement.php index 687f0c3a..4611f193 100644 --- a/src/Entity/Base/AbstractStructuralDBElement.php +++ b/src/Entity/Base/AbstractStructuralDBElement.php @@ -50,6 +50,8 @@ use Symfony\Component\Serializer\Annotation\Groups; */ abstract class AbstractStructuralDBElement extends AttachmentContainingDBElement { + use SpecificationsTrait; + public const ID_ROOT_ELEMENT = 0; /** diff --git a/src/Entity/Base/SpecificationsTrait.php b/src/Entity/Base/SpecificationsTrait.php new file mode 100644 index 00000000..278061b5 --- /dev/null +++ b/src/Entity/Base/SpecificationsTrait.php @@ -0,0 +1,54 @@ +. + */ + +namespace App\Entity\Base; + + +use App\Entity\Specifications\Specification; +use Symfony\Component\Validator\Constraints as Assert; + +trait SpecificationsTrait +{ + /** + * @var Specification[] + * @ORM\Column(type="json_document") + * @Assert\Valid() + */ + protected $specifications = []; + + /** + * Return all associated specifications + * @return Specification[] + */ + public function getSpecifications(): array + { + return $this->specifications ?? []; + } + + /** + * @param array $specifications + * @return $this + */ + public function setSpecifications(array $specifications): self + { + $this->specifications = $specifications; + return $this; + } +} \ No newline at end of file diff --git a/src/Entity/Parts/Part.php b/src/Entity/Parts/Part.php index e2cd7623..12e295c7 100644 --- a/src/Entity/Parts/Part.php +++ b/src/Entity/Parts/Part.php @@ -52,6 +52,7 @@ namespace App\Entity\Parts; use App\Entity\Attachments\Attachment; use App\Entity\Attachments\AttachmentContainingDBElement; +use App\Entity\Base\SpecificationsTrait; use App\Entity\Devices\Device; use App\Entity\Parts\PartTraits\AdvancedPropertyTrait; use App\Entity\Parts\PartTraits\BasicPropertyTrait; @@ -81,6 +82,7 @@ class Part extends AttachmentContainingDBElement use InstockTrait; use ManufacturerTrait; use OrderTrait; + use SpecificationsTrait; /** * TODO. diff --git a/src/Entity/Specifications/Specification.php b/src/Entity/Specifications/Specification.php new file mode 100644 index 00000000..954a837e --- /dev/null +++ b/src/Entity/Specifications/Specification.php @@ -0,0 +1,214 @@ +. + */ + +namespace App\Entity\Specifications; + + +use Symfony\Component\Validator\Constraints as Assert; + +class Specification +{ + /** + * @var string The name of the specification (e.g. "Collector-Base Voltage"). Required! + * @Assert\NotBlank() + */ + protected $name = ""; + + /** + * @var string The mathematical symbol for this specification. Can be rendered pretty later. Should be short + * @Assert\Length(max=10) + */ + protected $symbol = ""; + + /** + * @var float|null The guaranteed minimum value of this property. + * @Assert\Type({"float","null"}) + * @Assert\LessThanOrEqual(propertyPath="value_typical") + * @Assert\LessThan(propertyPath="value_max") + */ + protected $value_min; + + /** + * @var float|null The typical value of this property. + * @Assert\Type({"null", "float"}) + */ + protected $value_typical; + + /** + * @var float|null The maximum value of this property. + * @Assert\Type({"float", "null"}) + * @Assert\GreaterThanOrEqual(propertyPath="value_typical") + */ + protected $value_max; + + /** + * @var string The unit in which the value values are given (e.g. V) + * @Assert\Length(max=5) + */ + protected $unit = ""; + + /** + * @var string A text value for the given property. + * + */ + protected $value_text = ""; + + /** + * Returns the name of the specification (e.g. "Collector-Base Voltage"). + * @return string + */ + public function getName(): string + { + return $this->name; + } + + /** + * Sets the name of the specification. This value is required. + * @param string $name + * @return $this + */ + public function setName(string $name): Specification + { + $this->name = $name; + return $this; + } + + /** + * Returns the mathematical symbol for this specification (e.g. "V_CB") + * @return string + */ + public function getSymbol(): string + { + return $this->symbol; + } + + /** + * Sets the mathematical symbol for this specification (e.g. "V_CB") + * @param string $symbol + * @return $this + */ + public function setSymbol(string $symbol): Specification + { + $this->symbol = $symbol; + return $this; + } + + /** + * Returns The guaranteed minimum value of this property. + * @return float|null + */ + public function getValueMin(): ?float + { + return $this->value_min; + } + + /** + * Sets the minimum value of this property. + * @param float|null $value_min + * @return $this + */ + public function setValueMin(?float $value_min): Specification + { + $this->value_min = $value_min; + return $this; + } + + /** + * Returns the typical value of this property. + * @return float|null + */ + public function getValueTypical(): ?float + { + return $this->value_typical; + } + + /** + * Sets the typical value of this property + * @param float $value_typical + * @return $this + */ + public function setValueTypical(?float $value_typical): Specification + { + $this->value_typical = $value_typical; + return $this; + } + + /** + * Returns the guaranteed maximum value + * @return float|null + */ + public function getValueMax(): ?float + { + return $this->value_max; + } + + /** + * Sets the guaranteed maximum value + * @param float|null $value_max + * @return $this + */ + public function setValueMax(?float $value_max): Specification + { + $this->value_max = $value_max; + return $this; + } + + /** + * Returns the unit used by the value (e.g. "V") + * @return string + */ + public function getUnit(): string + { + return $this->unit; + } + + /** + * Sets the unit used by the value. + * @param string $unit + * @return $this + */ + public function setUnit(string $unit): Specification + { + $this->unit = $unit; + return $this; + } + + /** + * Returns the text value. + * @return string + */ + public function getValueText(): string + { + return $this->value_text; + } + + /** + * Sets the text value. + * @param string $value_text + * @return $this + */ + public function setValueText(string $value_text): Specification + { + $this->value_text = $value_text; + return $this; + } + + +} \ No newline at end of file diff --git a/src/Form/Part/PartBaseType.php b/src/Form/Part/PartBaseType.php index cf30f988..6d173d20 100644 --- a/src/Form/Part/PartBaseType.php +++ b/src/Form/Part/PartBaseType.php @@ -50,7 +50,9 @@ use App\Entity\Parts\Manufacturer; use App\Entity\Parts\MeasurementUnit; use App\Entity\Parts\Part; use App\Entity\PriceInformations\Orderdetail; +use App\Entity\Specifications\Specification; use App\Form\AttachmentFormType; +use App\Form\SpecificationType; use App\Form\Type\MasterPictureAttachmentType; use App\Form\Type\SIUnitType; use App\Form\Type\StructuralEntityType; @@ -264,6 +266,15 @@ class PartBaseType extends AbstractType ], ]); + $builder->add('specifications', CollectionType::class, [ + 'entry_type' => SpecificationType::class, + 'allow_add' => true, + 'allow_delete' => true, + 'label' => false, + 'by_reference' => false, + 'prototype_data' => new Specification(), + ]); + $builder->add('log_comment', TextType::class, [ 'label' => 'edit.log_comment', 'mapped' => false, @@ -280,7 +291,7 @@ class PartBaseType extends AbstractType public function configureOptions(OptionsResolver $resolver): void { $resolver->setDefaults([ - 'data_class' => Part::class, - ]); + 'data_class' => Part::class, + ]); } } diff --git a/src/Form/SpecificationType.php b/src/Form/SpecificationType.php new file mode 100644 index 00000000..92393f09 --- /dev/null +++ b/src/Form/SpecificationType.php @@ -0,0 +1,67 @@ +. + */ + +namespace App\Form; + +use App\Entity\Specifications\Specification; +use Symfony\Component\Form\AbstractType; +use Symfony\Component\Form\Extension\Core\Type\NumberType; +use Symfony\Component\Form\Extension\Core\Type\TextType; +use Symfony\Component\Form\FormBuilderInterface; +use Symfony\Component\OptionsResolver\OptionsResolver; + +class SpecificationType extends AbstractType +{ + public function buildForm(FormBuilderInterface $builder, array $options) + { + $builder->add('name', TextType::class,[ + 'empty_data' => '', + ]); + $builder->add('symbol', TextType::class, [ + 'required' => false, + 'empty_data' => '', + ]); + $builder->add('value_text', TextType::class, [ + 'required' => false, + 'empty_data' => '', + ]); + + $builder->add('value_max', NumberType::class, [ + 'required' => false, + ]); + $builder->add('value_min', NumberType::class, [ + 'required' => false, + ]); + $builder->add('value_typical', NumberType::class, [ + 'required' => false + ]); + $builder->add('unit', TextType::class, [ + 'required' => false, + 'empty_data' => '', + ]); + } + + public function configureOptions(OptionsResolver $resolver) + { + $resolver->setDefaults([ + 'data_class' => Specification::class + ]); + } +} \ No newline at end of file diff --git a/src/Migrations/Version20200308204758.php b/src/Migrations/Version20200308204758.php new file mode 100644 index 00000000..27e2a657 --- /dev/null +++ b/src/Migrations/Version20200308204758.php @@ -0,0 +1,57 @@ +abortIf($this->connection->getDatabasePlatform()->getName() !== 'mysql', 'Migration can only be executed safely on \'mysql\'.'); + + $this->addSql('ALTER TABLE attachment_types ADD specifications JSON NOT NULL COMMENT \'(DC2Type:json_document)\''); + $this->addSql('ALTER TABLE categories ADD specifications JSON NOT NULL COMMENT \'(DC2Type:json_document)\''); + $this->addSql('ALTER TABLE currencies ADD specifications JSON NOT NULL COMMENT \'(DC2Type:json_document)\''); + $this->addSql('ALTER TABLE devices ADD specifications JSON NOT NULL COMMENT \'(DC2Type:json_document)\''); + $this->addSql('ALTER TABLE footprints ADD specifications JSON NOT NULL COMMENT \'(DC2Type:json_document)\''); + $this->addSql('ALTER TABLE manufacturers ADD specifications JSON NOT NULL COMMENT \'(DC2Type:json_document)\''); + $this->addSql('ALTER TABLE measurement_units ADD specifications JSON NOT NULL COMMENT \'(DC2Type:json_document)\''); + $this->addSql('ALTER TABLE storelocations ADD specifications JSON NOT NULL COMMENT \'(DC2Type:json_document)\''); + $this->addSql('ALTER TABLE suppliers ADD specifications JSON NOT NULL COMMENT \'(DC2Type:json_document)\''); + $this->addSql('ALTER TABLE groups ADD specifications JSON NOT NULL COMMENT \'(DC2Type:json_document)\''); + $this->addSql('ALTER TABLE parts ADD specifications JSON NOT NULL COMMENT \'(DC2Type:json_document)\''); + $this->addSql('ALTER TABLE log CHANGE level level TINYINT'); + } + + public function down(Schema $schema) : void + { + // this down() migration is auto-generated, please modify it to your needs + $this->abortIf($this->connection->getDatabasePlatform()->getName() !== 'mysql', 'Migration can only be executed safely on \'mysql\'.'); + + $this->addSql('ALTER TABLE `attachment_types` DROP specifications'); + $this->addSql('ALTER TABLE `categories` DROP specifications'); + $this->addSql('ALTER TABLE currencies DROP specifications'); + $this->addSql('ALTER TABLE `devices` DROP specifications'); + $this->addSql('ALTER TABLE `footprints` DROP specifications'); + $this->addSql('ALTER TABLE `groups` DROP specifications'); + $this->addSql('ALTER TABLE log CHANGE level level TINYINT(1) DEFAULT NULL'); + $this->addSql('ALTER TABLE `manufacturers` DROP specifications'); + $this->addSql('ALTER TABLE `measurement_units` DROP specifications'); + $this->addSql('ALTER TABLE `parts` DROP specifications'); + $this->addSql('ALTER TABLE `storelocations` DROP specifications'); + $this->addSql('ALTER TABLE `suppliers` DROP specifications'); + } +} diff --git a/templates/Parts/edit/_specifications.html.twig b/templates/Parts/edit/_specifications.html.twig new file mode 100644 index 00000000..479c60a0 --- /dev/null +++ b/templates/Parts/edit/_specifications.html.twig @@ -0,0 +1,53 @@ +{% form_theme form with ['Parts/edit/edit_form_styles.html.twig', "bootstrap_4_layout.html.twig"] %} + + + + + + + + + + + + + + + + {% for spec in form.specifications %} + {{ form_widget(spec) }} + {% endfor %} + +
{% trans %}specifications.property{% endtrans %}{% trans %}specifications.symbol{% endtrans %}{% trans %}specifications.value_min{% endtrans %}{% trans %}specifications.value_typ{% endtrans %}{% trans %}specifications.value_max{% endtrans %}{% trans %}specifications.unit{% endtrans %}{% trans %}specifications.text{% endtrans %}
+ + + + \ No newline at end of file diff --git a/templates/Parts/edit/edit_form_styles.html.twig b/templates/Parts/edit/edit_form_styles.html.twig index 0d357a18..714e6d57 100644 --- a/templates/Parts/edit/edit_form_styles.html.twig +++ b/templates/Parts/edit/edit_form_styles.html.twig @@ -62,4 +62,22 @@ {{ form_errors(form) }} +{% endblock %} + +{% block specification_widget %} + + {{ form_widget(form.name) }}{{ form_errors(form.name) }} + {{ form_widget(form.symbol) }}{{ form_errors(form.symbol) }} + {{ form_widget(form.value_min) }}{{ form_errors(form.value_min) }} + {{ form_widget(form.value_typical) }}{{ form_errors(form.value_typical) }} + {{ form_widget(form.value_max) }}{{ form_errors(form.value_max) }} + {{ form_widget(form.unit) }}{{ form_errors(form.unit) }} + {{ form_widget(form.value_text) }}{{ form_errors(form.value_text) }} + + + {{ form_errors(form) }} + + {% endblock %} \ No newline at end of file diff --git a/templates/Parts/edit/edit_part_info.html.twig b/templates/Parts/edit/edit_part_info.html.twig index b57e7653..3a437a32 100644 --- a/templates/Parts/edit/edit_part_info.html.twig +++ b/templates/Parts/edit/edit_part_info.html.twig @@ -52,6 +52,12 @@ {% trans %}part.edit.tab.orderdetails{% endtrans %} +