mirror of
https://github.com/Part-DB/Part-DB-server.git
synced 2025-06-21 09:35:49 +02:00
Added an page for editing order informations
This commit is contained in:
parent
1776cd9a77
commit
8c6342bffe
14 changed files with 504 additions and 12 deletions
|
@ -52,6 +52,10 @@ services:
|
||||||
arguments:
|
arguments:
|
||||||
$base_current: '%default_currency%'
|
$base_current: '%default_currency%'
|
||||||
|
|
||||||
|
App\Form\Type\CurrencyEntityType:
|
||||||
|
arguments:
|
||||||
|
$base_currency: '%default_currency%'
|
||||||
|
|
||||||
|
|
||||||
# add more service definitions when explicit configuration is needed
|
# add more service definitions when explicit configuration is needed
|
||||||
# please note that last definitions always *replace* previous ones
|
# please note that last definitions always *replace* previous ones
|
||||||
|
|
|
@ -128,8 +128,8 @@ class Part extends AttachmentContainingDBElement
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var Orderdetail[]
|
* @var Orderdetail[]
|
||||||
* @ORM\OneToMany(targetEntity="App\Entity\PriceInformations\Orderdetail", mappedBy="part")
|
* @ORM\OneToMany(targetEntity="App\Entity\PriceInformations\Orderdetail", mappedBy="part", cascade={"persist", "remove"}, orphanRemoval=true)
|
||||||
*
|
* @Assert\Valid()
|
||||||
* @ColumnSecurity(prefix="orderdetails", type="object")
|
* @ColumnSecurity(prefix="orderdetails", type="object")
|
||||||
*/
|
*/
|
||||||
protected $orderdetails;
|
protected $orderdetails;
|
||||||
|
@ -279,6 +279,7 @@ class Part extends AttachmentContainingDBElement
|
||||||
{
|
{
|
||||||
parent::__construct();
|
parent::__construct();
|
||||||
$this->partLots = new ArrayCollection();
|
$this->partLots = new ArrayCollection();
|
||||||
|
$this->orderdetails = new ArrayCollection();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -510,6 +511,19 @@ class Part extends AttachmentContainingDBElement
|
||||||
return $this->orderdetails;
|
return $this->orderdetails;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function addOrderdetail(Orderdetail $orderdetail) : Part
|
||||||
|
{
|
||||||
|
$orderdetail->setPart($this);
|
||||||
|
$this->orderdetails->add($orderdetail);
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function removeOrderdetail(Orderdetail $orderdetail) : Part
|
||||||
|
{
|
||||||
|
$this->orderdetails->removeElement($orderdetail);
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get all devices which uses this part.
|
* Get all devices which uses this part.
|
||||||
*
|
*
|
||||||
|
|
|
@ -86,7 +86,7 @@ class Currency extends StructuralDBElement
|
||||||
* @param string $iso_code
|
* @param string $iso_code
|
||||||
* @return Currency
|
* @return Currency
|
||||||
*/
|
*/
|
||||||
public function setIsoCode(string $iso_code): Currency
|
public function setIsoCode(?string $iso_code): Currency
|
||||||
{
|
{
|
||||||
$this->iso_code = $iso_code;
|
$this->iso_code = $iso_code;
|
||||||
return $this;
|
return $this;
|
||||||
|
|
|
@ -65,9 +65,12 @@ use App\Entity\Base\DBElement;
|
||||||
use App\Entity\Base\TimestampTrait;
|
use App\Entity\Base\TimestampTrait;
|
||||||
use App\Entity\Parts\Part;
|
use App\Entity\Parts\Part;
|
||||||
use App\Entity\Parts\Supplier;
|
use App\Entity\Parts\Supplier;
|
||||||
|
use Doctrine\Common\Collections\ArrayCollection;
|
||||||
|
use Doctrine\Common\Collections\Collection;
|
||||||
use Doctrine\ORM\Mapping as ORM;
|
use Doctrine\ORM\Mapping as ORM;
|
||||||
use Doctrine\ORM\PersistentCollection;
|
use Doctrine\ORM\PersistentCollection;
|
||||||
use Exception;
|
use Exception;
|
||||||
|
use Symfony\Component\Form\Extension\Core\Type\CollectionType;
|
||||||
use Symfony\Component\Validator\Constraints as Assert;
|
use Symfony\Component\Validator\Constraints as Assert;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -85,6 +88,7 @@ class Orderdetail extends DBElement
|
||||||
* @var Part
|
* @var Part
|
||||||
* @ORM\ManyToOne(targetEntity="App\Entity\Parts\Part", inversedBy="orderdetails")
|
* @ORM\ManyToOne(targetEntity="App\Entity\Parts\Part", inversedBy="orderdetails")
|
||||||
* @ORM\JoinColumn(name="part_id", referencedColumnName="id")
|
* @ORM\JoinColumn(name="part_id", referencedColumnName="id")
|
||||||
|
* @Assert\NotNull()
|
||||||
*/
|
*/
|
||||||
protected $part;
|
protected $part;
|
||||||
|
|
||||||
|
@ -96,7 +100,8 @@ class Orderdetail extends DBElement
|
||||||
protected $supplier;
|
protected $supplier;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @ORM\OneToMany(targetEntity="Pricedetail", mappedBy="orderdetail")
|
* @ORM\OneToMany(targetEntity="Pricedetail", mappedBy="orderdetail", cascade={"persist", "remove"}, orphanRemoval=true)
|
||||||
|
* @Assert\Valid()
|
||||||
*/
|
*/
|
||||||
protected $pricedetails;
|
protected $pricedetails;
|
||||||
|
|
||||||
|
@ -119,6 +124,11 @@ class Orderdetail extends DBElement
|
||||||
*/
|
*/
|
||||||
protected $supplier_product_url = "";
|
protected $supplier_product_url = "";
|
||||||
|
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->pricedetails = new ArrayCollection();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the ID as an string, defined by the element class.
|
* Returns the ID as an string, defined by the element class.
|
||||||
* This should have a form like P000014, for a part with ID 14.
|
* This should have a form like P000014, for a part with ID 14.
|
||||||
|
@ -205,11 +215,34 @@ class Orderdetail extends DBElement
|
||||||
*
|
*
|
||||||
* @throws Exception if there was an error
|
* @throws Exception if there was an error
|
||||||
*/
|
*/
|
||||||
public function getPricedetails(): PersistentCollection
|
public function getPricedetails(): Collection
|
||||||
{
|
{
|
||||||
return $this->pricedetails;
|
return $this->pricedetails;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds an pricedetail to this orderdetail
|
||||||
|
* @param Pricedetail $pricedetail The pricedetail to add
|
||||||
|
* @return Orderdetail
|
||||||
|
*/
|
||||||
|
public function addPricedetail(Pricedetail $pricedetail) : Orderdetail
|
||||||
|
{
|
||||||
|
$pricedetail->setOrderdetail($this);
|
||||||
|
$this->pricedetails->add($pricedetail);
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes an pricedetail from this orderdetail
|
||||||
|
* @param Pricedetail $pricedetail
|
||||||
|
* @return Orderdetail
|
||||||
|
*/
|
||||||
|
public function removePricedetail(Pricedetail $pricedetail) : Orderdetail
|
||||||
|
{
|
||||||
|
$this->pricedetails->removeElement($pricedetail);
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the price for a specific quantity.
|
* Get the price for a specific quantity.
|
||||||
* @param int $quantity this is the quantity to choose the correct pricedetails
|
* @param int $quantity this is the quantity to choose the correct pricedetails
|
||||||
|
@ -264,6 +297,15 @@ class Orderdetail extends DBElement
|
||||||
*
|
*
|
||||||
*********************************************************************************/
|
*********************************************************************************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets a new part with which this orderdetail is associated
|
||||||
|
* @param Part $part
|
||||||
|
*/
|
||||||
|
public function setPart(Part $part)
|
||||||
|
{
|
||||||
|
$this->part = $part;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the new supplier associated with this orderdetail.
|
* Sets the new supplier associated with this orderdetail.
|
||||||
* @param Supplier $new_supplier
|
* @param Supplier $new_supplier
|
||||||
|
@ -310,6 +352,11 @@ class Orderdetail extends DBElement
|
||||||
*/
|
*/
|
||||||
public function setSupplierProductUrl(string $new_url)
|
public function setSupplierProductUrl(string $new_url)
|
||||||
{
|
{
|
||||||
|
//Only change the internal URL if it is not the auto generated one
|
||||||
|
if ($new_url == $this->supplier->getAutoProductUrl($this->getSupplierPartNr())) {
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
$this->supplier_product_url = $new_url;
|
$this->supplier_product_url = $new_url;
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
|
|
|
@ -85,6 +85,7 @@ class Pricedetail extends DBElement
|
||||||
* @var Orderdetail
|
* @var Orderdetail
|
||||||
* @ORM\ManyToOne(targetEntity="Orderdetail", inversedBy="pricedetails")
|
* @ORM\ManyToOne(targetEntity="Orderdetail", inversedBy="pricedetails")
|
||||||
* @ORM\JoinColumn(name="orderdetails_id", referencedColumnName="id")
|
* @ORM\JoinColumn(name="orderdetails_id", referencedColumnName="id")
|
||||||
|
* @Assert\NotNull()
|
||||||
*/
|
*/
|
||||||
protected $orderdetail;
|
protected $orderdetail;
|
||||||
|
|
||||||
|
@ -93,7 +94,7 @@ class Pricedetail extends DBElement
|
||||||
* @ORM\Column(type="decimal", precision=11, scale=5)
|
* @ORM\Column(type="decimal", precision=11, scale=5)
|
||||||
* @Assert\Positive()
|
* @Assert\Positive()
|
||||||
*/
|
*/
|
||||||
protected $price;
|
protected $price = 0.0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var ?Currency The currency used for the current price information.
|
* @var ?Currency The currency used for the current price information.
|
||||||
|
@ -109,19 +110,19 @@ class Pricedetail extends DBElement
|
||||||
* @ORM\Column(type="integer")
|
* @ORM\Column(type="integer")
|
||||||
* @Assert\Positive()
|
* @Assert\Positive()
|
||||||
*/
|
*/
|
||||||
protected $price_related_quantity;
|
protected $price_related_quantity = 1;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var int
|
* @var int
|
||||||
* @ORM\Column(type="integer")
|
* @ORM\Column(type="integer")
|
||||||
*/
|
*/
|
||||||
protected $min_discount_quantity;
|
protected $min_discount_quantity = 1;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var bool
|
* @var bool
|
||||||
* @ORM\Column(type="boolean")
|
* @ORM\Column(type="boolean")
|
||||||
*/
|
*/
|
||||||
protected $manual_input;
|
protected $manual_input = true;
|
||||||
|
|
||||||
|
|
||||||
/********************************************************************************
|
/********************************************************************************
|
||||||
|
@ -212,6 +213,17 @@ class Pricedetail extends DBElement
|
||||||
*
|
*
|
||||||
*********************************************************************************/
|
*********************************************************************************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the orderdetail to which this pricedetail belongs to.
|
||||||
|
* @param Orderdetail $orderdetail
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function setOrderdetail(Orderdetail $orderdetail)
|
||||||
|
{
|
||||||
|
$this->orderdetail = $orderdetail;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the currency associated with the price informations.
|
* Sets the currency associated with the price informations.
|
||||||
* Set to null, to use the global base currency.
|
* Set to null, to use the global base currency.
|
||||||
|
|
|
@ -45,6 +45,7 @@ class CurrencyAdminForm extends BaseEntityAdminForm
|
||||||
$is_new = $entity->getID() === null;
|
$is_new = $entity->getID() === null;
|
||||||
|
|
||||||
$builder->add('iso_code', CurrencyType::class , ['required' => true,
|
$builder->add('iso_code', CurrencyType::class , ['required' => true,
|
||||||
|
'required' => false,
|
||||||
'label' => 'currency.iso_code.label',
|
'label' => 'currency.iso_code.label',
|
||||||
'preferred_choices' => ['EUR', 'USD', 'GBP', 'JPY', 'CNY'],
|
'preferred_choices' => ['EUR', 'USD', 'GBP', 'JPY', 'CNY'],
|
||||||
'attr' => ['class' => 'selectpicker', 'data-live-search' => true],
|
'attr' => ['class' => 'selectpicker', 'data-live-search' => true],
|
||||||
|
|
82
src/Form/Part/OrderdetailType.php
Normal file
82
src/Form/Part/OrderdetailType.php
Normal file
|
@ -0,0 +1,82 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* part-db version 0.1
|
||||||
|
* Copyright (C) 2005 Christoph Lechner
|
||||||
|
* http://www.cl-projects.de/
|
||||||
|
*
|
||||||
|
* part-db version 0.2+
|
||||||
|
* Copyright (C) 2009 K. Jacobs and others (see authors.php)
|
||||||
|
* http://code.google.com/p/part-db/
|
||||||
|
*
|
||||||
|
* Part-DB Version 0.4+
|
||||||
|
* Copyright (C) 2016 - 2019 Jan Böhmer
|
||||||
|
* https://github.com/jbtronics
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace App\Form\Part;
|
||||||
|
|
||||||
|
use App\Entity\Parts\Supplier;
|
||||||
|
use App\Entity\PriceInformations\Orderdetail;
|
||||||
|
use App\Form\Type\StructuralEntityType;
|
||||||
|
use Symfony\Component\Form\AbstractType;
|
||||||
|
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
|
||||||
|
use Symfony\Component\Form\Extension\Core\Type\CollectionType;
|
||||||
|
use Symfony\Component\Form\Extension\Core\Type\TextType;
|
||||||
|
use Symfony\Component\Form\Extension\Core\Type\UrlType;
|
||||||
|
use Symfony\Component\Form\FormBuilderInterface;
|
||||||
|
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||||
|
|
||||||
|
class OrderdetailType extends AbstractType
|
||||||
|
{
|
||||||
|
public function buildForm(FormBuilderInterface $builder, array $options)
|
||||||
|
{
|
||||||
|
$builder->add('supplierpartnr', TextType::class, [
|
||||||
|
'required' => false,
|
||||||
|
'empty_data' => ""
|
||||||
|
]);
|
||||||
|
|
||||||
|
$builder->add('supplier', StructuralEntityType::class, ['class' => Supplier::class, 'disable_not_selectable' => true]);
|
||||||
|
|
||||||
|
$builder->add('supplierProductUrl', UrlType::class, [
|
||||||
|
'required' => false,
|
||||||
|
'empty_data' => ""
|
||||||
|
]);
|
||||||
|
|
||||||
|
$builder->add('obsolete', CheckboxType::class, [
|
||||||
|
'required' => false,
|
||||||
|
'label_attr' => ['class' => 'checkbox-custom']
|
||||||
|
]);
|
||||||
|
|
||||||
|
//Attachment section
|
||||||
|
$builder->add('priceDetails', CollectionType::class, [
|
||||||
|
'entry_type' => PricedetailType::class,
|
||||||
|
'allow_add' => true, 'allow_delete' => true,
|
||||||
|
'label' => false,
|
||||||
|
'by_reference' => false
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function configureOptions(OptionsResolver $resolver)
|
||||||
|
{
|
||||||
|
$resolver->setDefaults([
|
||||||
|
'data_class' => Orderdetail::class,
|
||||||
|
'error_bubbling' => false,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
|
@ -144,6 +144,14 @@ class PartBaseType extends AbstractType
|
||||||
'by_reference' => false
|
'by_reference' => false
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
//Attachment section
|
||||||
|
$builder->add('orderDetails', CollectionType::class, [
|
||||||
|
'entry_type' => OrderdetailType::class,
|
||||||
|
'allow_add' => true, 'allow_delete' => true,
|
||||||
|
'label' => false,
|
||||||
|
'by_reference' => false,
|
||||||
|
]);
|
||||||
|
|
||||||
$builder
|
$builder
|
||||||
//Buttons
|
//Buttons
|
||||||
->add('save', SubmitType::class, ['label' => 'part.edit.save'])
|
->add('save', SubmitType::class, ['label' => 'part.edit.save'])
|
||||||
|
|
62
src/Form/Part/PricedetailType.php
Normal file
62
src/Form/Part/PricedetailType.php
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* part-db version 0.1
|
||||||
|
* Copyright (C) 2005 Christoph Lechner
|
||||||
|
* http://www.cl-projects.de/
|
||||||
|
*
|
||||||
|
* part-db version 0.2+
|
||||||
|
* Copyright (C) 2009 K. Jacobs and others (see authors.php)
|
||||||
|
* http://code.google.com/p/part-db/
|
||||||
|
*
|
||||||
|
* Part-DB Version 0.4+
|
||||||
|
* Copyright (C) 2016 - 2019 Jan Böhmer
|
||||||
|
* https://github.com/jbtronics
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace App\Form\Part;
|
||||||
|
|
||||||
|
|
||||||
|
use App\Entity\PriceInformations\Currency;
|
||||||
|
use App\Entity\PriceInformations\Orderdetail;
|
||||||
|
use App\Entity\PriceInformations\Pricedetail;
|
||||||
|
use App\Form\Type\CurrencyEntityType;
|
||||||
|
use App\Form\Type\StructuralEntityType;
|
||||||
|
use Symfony\Component\Form\AbstractType;
|
||||||
|
use Symfony\Component\Form\Extension\Core\Type\IntegerType;
|
||||||
|
use Symfony\Component\Form\Extension\Core\Type\NumberType;
|
||||||
|
use Symfony\Component\Form\FormBuilderInterface;
|
||||||
|
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||||
|
|
||||||
|
class PricedetailType extends AbstractType
|
||||||
|
{
|
||||||
|
public function buildForm(FormBuilderInterface $builder, array $options)
|
||||||
|
{
|
||||||
|
$builder->add("minDiscountQuantity", IntegerType::class);
|
||||||
|
$builder->add("priceRelatedQuantity", IntegerType::class);
|
||||||
|
$builder->add("price", NumberType::class);
|
||||||
|
$builder->add("currency", CurrencyEntityType::class, ['required' => false]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function configureOptions(OptionsResolver $resolver)
|
||||||
|
{
|
||||||
|
$resolver->setDefaults([
|
||||||
|
'data_class' => Pricedetail::class,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
118
src/Form/Type/CurrencyEntityType.php
Normal file
118
src/Form/Type/CurrencyEntityType.php
Normal file
|
@ -0,0 +1,118 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* part-db version 0.1
|
||||||
|
* Copyright (C) 2005 Christoph Lechner
|
||||||
|
* http://www.cl-projects.de/
|
||||||
|
*
|
||||||
|
* part-db version 0.2+
|
||||||
|
* Copyright (C) 2009 K. Jacobs and others (see authors.php)
|
||||||
|
* http://code.google.com/p/part-db/
|
||||||
|
*
|
||||||
|
* Part-DB Version 0.4+
|
||||||
|
* Copyright (C) 2016 - 2019 Jan Böhmer
|
||||||
|
* https://github.com/jbtronics
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace App\Form\Type;
|
||||||
|
|
||||||
|
|
||||||
|
use App\Entity\Base\StructuralDBElement;
|
||||||
|
use App\Entity\PriceInformations\Currency;
|
||||||
|
use App\Services\TreeBuilder;
|
||||||
|
use Doctrine\ORM\EntityManagerInterface;
|
||||||
|
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
|
||||||
|
use Symfony\Component\Intl\Currencies;
|
||||||
|
use Symfony\Component\OptionsResolver\Options;
|
||||||
|
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||||
|
|
||||||
|
class CurrencyEntityType extends StructuralEntityType
|
||||||
|
{
|
||||||
|
protected $base_currency;
|
||||||
|
|
||||||
|
public function __construct(EntityManagerInterface $em, TreeBuilder $builder, $base_currency)
|
||||||
|
{
|
||||||
|
parent::__construct($em, $builder);
|
||||||
|
$this->base_currency = $base_currency;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function configureOptions(OptionsResolver $resolver)
|
||||||
|
{
|
||||||
|
//Important to call the parent resolver!
|
||||||
|
parent::configureOptions($resolver);
|
||||||
|
|
||||||
|
$resolver->setDefault('class', Currency::class);
|
||||||
|
$resolver->setDefault('disable_not_selectable', true);
|
||||||
|
|
||||||
|
// This options allows you to override the currency shown for the null value
|
||||||
|
$resolver->setDefault('base_currency', null);
|
||||||
|
|
||||||
|
$resolver->setDefault('empty_message', function (Options $options) {
|
||||||
|
//By default we use the global base currency:
|
||||||
|
$iso_code = $this->base_currency;
|
||||||
|
|
||||||
|
if ($options['base_currency']) { //Allow to override it
|
||||||
|
$iso_code = $options['base_currency'];
|
||||||
|
}
|
||||||
|
|
||||||
|
return Currencies::getSymbol($iso_code);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public function generateChoiceLabels(StructuralDBElement $choice, $key, $value): string
|
||||||
|
{
|
||||||
|
//Similar to StructuralEntityType, but we use the currency symbol instead if available
|
||||||
|
|
||||||
|
/** @var StructuralDBElement|null $parent */
|
||||||
|
$parent = $this->options['subentities_of'];
|
||||||
|
|
||||||
|
/*** @var Currency $choice */
|
||||||
|
$level = $choice->getLevel();
|
||||||
|
//If our base entity is not the root level, we need to change the level, to get zero position
|
||||||
|
if ($this->options['subentities_of'] !== null) {
|
||||||
|
$level -= $parent->getLevel() - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
$tmp = str_repeat(' ', $choice->getLevel()); //Use 3 spaces for intendation
|
||||||
|
if (empty($choice->getIsoCode())) {
|
||||||
|
$tmp .= htmlspecialchars($choice->getName());
|
||||||
|
} else {
|
||||||
|
$tmp .= Currencies::getSymbol($choice->getIsoCode());
|
||||||
|
}
|
||||||
|
return $tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function generateChoiceAttr(StructuralDBElement $choice, $key, $value) : array
|
||||||
|
{
|
||||||
|
/** @var Currency $choice */
|
||||||
|
|
||||||
|
$tmp = array();
|
||||||
|
|
||||||
|
if (!empty($choice->getIsoCode())) {
|
||||||
|
//Show the name of the currency
|
||||||
|
$tmp += ['data-subtext' => $choice->getName()];
|
||||||
|
}
|
||||||
|
|
||||||
|
//Disable attribute if the choice is marked as not selectable
|
||||||
|
if ($this->options['disable_not_selectable'] && $choice->isNotSelectable()) {
|
||||||
|
$tmp += ['disabled' => 'disabled'];
|
||||||
|
}
|
||||||
|
return $tmp;
|
||||||
|
}
|
||||||
|
}
|
|
@ -77,14 +77,14 @@ class StructuralEntityType extends AbstractType
|
||||||
function ($value) use ($options){
|
function ($value) use ($options){
|
||||||
return $this->transform($value, $options);
|
return $this->transform($value, $options);
|
||||||
}, function ($value) use ($options) {
|
}, function ($value) use ($options) {
|
||||||
return $this->reverseTransform($value, $options);
|
return $this->reverseTransform($value, $options);
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function configureOptions(OptionsResolver $resolver)
|
public function configureOptions(OptionsResolver $resolver)
|
||||||
{
|
{
|
||||||
$resolver->setRequired(['class']);
|
$resolver->setRequired(['class']);
|
||||||
$resolver->setDefaults(['attr' => ['class' => 'selectpicker', 'data-live-search' => true],
|
$resolver->setDefaults([
|
||||||
'show_fullpath_in_subtext' => true, //When this is enabled, the full path will be shown in subtext
|
'show_fullpath_in_subtext' => true, //When this is enabled, the full path will be shown in subtext
|
||||||
'subentities_of' => null, //Only show entities with the given parent class
|
'subentities_of' => null, //Only show entities with the given parent class
|
||||||
'disable_not_selectable' => false, //Disable entries with not selectable property
|
'disable_not_selectable' => false, //Disable entries with not selectable property
|
||||||
|
@ -99,6 +99,16 @@ class StructuralEntityType extends AbstractType
|
||||||
return $this->generateChoiceAttr($choice, $key, $value);
|
return $this->generateChoiceAttr($choice, $key, $value);
|
||||||
}
|
}
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
$resolver->setDefault('empty_message', null);
|
||||||
|
|
||||||
|
$resolver->setDefault('attr', function (Options $options) {
|
||||||
|
$tmp = ['class' => 'selectpicker', 'data-live-search' => true];
|
||||||
|
if ($options['empty_message']) {
|
||||||
|
$tmp['data-none-Selected-Text'] = $options['empty_message'];
|
||||||
|
}
|
||||||
|
return $tmp;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function generateChoiceAttr(StructuralDBElement $choice, $key, $value) : array
|
protected function generateChoiceAttr(StructuralDBElement $choice, $key, $value) : array
|
||||||
|
@ -130,7 +140,7 @@ class StructuralEntityType extends AbstractType
|
||||||
|
|
||||||
|
|
||||||
$tmp = str_repeat(' ', $choice->getLevel()); //Use 3 spaces for intendation
|
$tmp = str_repeat(' ', $choice->getLevel()); //Use 3 spaces for intendation
|
||||||
$tmp .= htmlspecialchars($choice->getName($parent));
|
$tmp .= htmlspecialchars($choice->getName());
|
||||||
return $tmp;
|
return $tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
66
templates/Parts/edit/_orderdetails.html.twig
Normal file
66
templates/Parts/edit/_orderdetails.html.twig
Normal file
|
@ -0,0 +1,66 @@
|
||||||
|
{% form_theme form 'Parts/edit/edit_form_styles.html.twig' %}
|
||||||
|
|
||||||
|
<table class="table table-striped" id="orderdetails_table" data-prototype="{{ form_widget(form.orderDetails.vars.prototype)|e('html_attr') }}">
|
||||||
|
<tbody>
|
||||||
|
{% for detail in form.orderDetails %}
|
||||||
|
{{ form_widget(detail) }}
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<button type="button" class="btn btn-success" onclick="create_orderdetail_entry(this)">
|
||||||
|
<i class="fas fa-plus-square fa-fw"></i>
|
||||||
|
{% trans %}orderdetail.create{% endtrans %}
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
function delete_pricedetail_entry(btn) {
|
||||||
|
window.bootbox.confirm('{% trans %}pricedetails.edit.delete.confirm{% endtrans %}', function (result) {
|
||||||
|
if(result) {
|
||||||
|
$(btn).closest("tr").remove();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function create_pricedetail_entry(btn) {
|
||||||
|
//Determine the table, so we can determine, how many entries there are already.
|
||||||
|
$holder = $(btn).siblings("table");
|
||||||
|
|
||||||
|
var index = $holder.find(":input").length;
|
||||||
|
var newForm = $holder.data("prototype");
|
||||||
|
|
||||||
|
//Increase the index
|
||||||
|
newForm = newForm.replace(/__name__/g, index);
|
||||||
|
|
||||||
|
$holder.children("tbody").append(newForm);
|
||||||
|
|
||||||
|
//Reinit the selectpickers
|
||||||
|
$(".selectpicker").selectpicker();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function delete_orderdetail_entry(btn) {
|
||||||
|
window.bootbox.confirm('{% trans %}orderdetails.edit.delete.confirm{% endtrans %}', function (result) {
|
||||||
|
if(result) {
|
||||||
|
$(btn).parents("tr").remove();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function create_orderdetail_entry(btn) {
|
||||||
|
//Determine the table, so we can determine, how many entries there are already.
|
||||||
|
$holder = $("#orderdetails_table");
|
||||||
|
|
||||||
|
var index = $holder.find(":input").length;
|
||||||
|
var newForm = $holder.data("prototype");
|
||||||
|
|
||||||
|
//Increase the index
|
||||||
|
newForm = newForm.replace(/__name__/g, index);
|
||||||
|
|
||||||
|
$holder.children("tbody").append(newForm);
|
||||||
|
|
||||||
|
//Reinit the selectpickers
|
||||||
|
$(".selectpicker").selectpicker();
|
||||||
|
|
||||||
|
}
|
||||||
|
</script>
|
59
templates/Parts/edit/edit_form_styles.html.twig
Normal file
59
templates/Parts/edit/edit_form_styles.html.twig
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
{% block pricedetail_widget %}
|
||||||
|
<tr>
|
||||||
|
<td>{{ form_widget(form.minDiscountQuantity) }} {{ form_errors(form.minDiscountQuantity) }}</td>
|
||||||
|
<td>
|
||||||
|
<div class="input-group">
|
||||||
|
{{ form_widget(form.price) }}
|
||||||
|
<div class="input-group-append">
|
||||||
|
{{ form_widget(form.currency) }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{{ form_errors(form.price) }}
|
||||||
|
{{ form_errors(form.currency) }}
|
||||||
|
</td>
|
||||||
|
<td>{{ form_widget(form.priceRelatedQuantity) }} {{ form_errors(form.price) }}</td>
|
||||||
|
<td><button type="button" class="btn btn-danger order_btn_delete" title="{% trans %}orderdetail.delete{% endtrans %}" onclick="delete_pricedetail_entry(this);">
|
||||||
|
<i class="fas fa-trash-alt fa-fw"></i>
|
||||||
|
</button>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block orderdetail_widget %}
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
{{ form_row(form.supplierpartnr) }}
|
||||||
|
{{ form_row(form.supplier) }}
|
||||||
|
{{ form_row(form.supplierProductUrl) }}
|
||||||
|
{{ form_row(form.obsolete) }}
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<table class="table table-sm table-bordered" data-prototype="{{ form_widget(form.priceDetails.vars.prototype)|e('html_attr') }}">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Min Qty.</th>
|
||||||
|
<th>Price</th>
|
||||||
|
<th>Price Qty</th>
|
||||||
|
<th></th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{% for price in form.priceDetails %}
|
||||||
|
{{ form_widget(price) }}
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<button type="button" class="btn btn-success" onclick="create_pricedetail_entry(this)">
|
||||||
|
<i class="fas fa-plus-square fa-fw"></i>
|
||||||
|
{% trans %}pricedetail.create{% endtrans %}
|
||||||
|
</button>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<button type="button" class="btn btn-danger order_btn_delete" onclick="delete_orderdetail_entry(this);">
|
||||||
|
<i class="fas fa-trash-alt fa-fw"></i>
|
||||||
|
{% trans %}orderdetail.delete{% endtrans %}
|
||||||
|
</button>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{% endblock %}
|
|
@ -46,6 +46,12 @@
|
||||||
{% trans %}part.edit.tab.attachments{% endtrans %}
|
{% trans %}part.edit.tab.attachments{% endtrans %}
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" data-toggle="tab" role="tab" href="#orderdetails">
|
||||||
|
<i class="fas fa-shopping-cart fa-fw"></i>
|
||||||
|
{% trans %}part.edit.tab.orderdetails{% endtrans %}
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a class="nav-link" data-toggle="tab" role="tab" href="#comment">
|
<a class="nav-link" data-toggle="tab" role="tab" href="#comment">
|
||||||
<i class="fas fa-sticky-note fa-fw"></i>
|
<i class="fas fa-sticky-note fa-fw"></i>
|
||||||
|
@ -72,6 +78,9 @@
|
||||||
<div class="tab-pane fade p-2" id="attachments" role="tabpanel">
|
<div class="tab-pane fade p-2" id="attachments" role="tabpanel">
|
||||||
{% include "Parts/edit/_attachments.html.twig" %}
|
{% include "Parts/edit/_attachments.html.twig" %}
|
||||||
</div>
|
</div>
|
||||||
|
<div class="tab-pane fade p-2" id="orderdetails" role="tabpanel">
|
||||||
|
{% include "Parts/edit/_orderdetails.html.twig" %}
|
||||||
|
</div>
|
||||||
<div class="tab-pane fade p-2" id="comment" role="tabpanel">
|
<div class="tab-pane fade p-2" id="comment" role="tabpanel">
|
||||||
{{ form_widget(form.comment)}}
|
{{ form_widget(form.comment)}}
|
||||||
</div>
|
</div>
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue