diff --git a/app/migrations/Version20150708104025.php b/app/migrations/Version20150708104025.php new file mode 100644 index 00000000000..f7aaed6e12f --- /dev/null +++ b/app/migrations/Version20150708104025.php @@ -0,0 +1,36 @@ +abortIf($this->connection->getDatabasePlatform()->getName() != 'mysql', 'Migration can only be executed safely on \'mysql\'.'); + + $this->addSql('ALTER TABLE sylius_product ADD available_until DATETIME DEFAULT NULL'); + $this->addSql('ALTER TABLE sylius_product_variant ADD available_until DATETIME DEFAULT NULL'); + } + + /** + * @param Schema $schema + */ + public function down(Schema $schema) + { + // 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 sylius_product DROP available_until'); + $this->addSql('ALTER TABLE sylius_product_variant DROP available_until'); + } +} diff --git a/src/Sylius/Bundle/ProductBundle/Form/Type/VariantType.php b/src/Sylius/Bundle/ProductBundle/Form/Type/VariantType.php index 374c1fd57db..a0dacb3adfd 100644 --- a/src/Sylius/Bundle/ProductBundle/Form/Type/VariantType.php +++ b/src/Sylius/Bundle/ProductBundle/Form/Type/VariantType.php @@ -35,6 +35,14 @@ public function buildForm(FormBuilderInterface $builder, array $options) 'time_widget' => 'text', 'label' => 'sylius.form.product_variant.available_on' )) + ->add('availableUntil', 'datetime', array( + 'date_format' => 'y-M-d', + 'date_widget' => 'choice', + 'time_widget' => 'text', + 'label' => 'sylius.form.product_variant.available_until', + 'empty_value' => '-', + 'required' => false + )) ; } } diff --git a/src/Sylius/Bundle/ProductBundle/Resources/config/doctrine/model/Product.orm.xml b/src/Sylius/Bundle/ProductBundle/Resources/config/doctrine/model/Product.orm.xml index 382e21d2a51..6cb173e3b61 100644 --- a/src/Sylius/Bundle/ProductBundle/Resources/config/doctrine/model/Product.orm.xml +++ b/src/Sylius/Bundle/ProductBundle/Resources/config/doctrine/model/Product.orm.xml @@ -23,6 +23,10 @@ + + + + diff --git a/src/Sylius/Bundle/ProductBundle/Resources/config/doctrine/model/Variant.orm.xml b/src/Sylius/Bundle/ProductBundle/Resources/config/doctrine/model/Variant.orm.xml index 9e56e27b60e..103578bcb0b 100644 --- a/src/Sylius/Bundle/ProductBundle/Resources/config/doctrine/model/Variant.orm.xml +++ b/src/Sylius/Bundle/ProductBundle/Resources/config/doctrine/model/Variant.orm.xml @@ -18,6 +18,7 @@ + diff --git a/src/Sylius/Bundle/ProductBundle/Resources/translations/messages.cs.yml b/src/Sylius/Bundle/ProductBundle/Resources/translations/messages.cs.yml index cbf4200d99b..5506b713bac 100644 --- a/src/Sylius/Bundle/ProductBundle/Resources/translations/messages.cs.yml +++ b/src/Sylius/Bundle/ProductBundle/Resources/translations/messages.cs.yml @@ -10,6 +10,9 @@ sylius: available_on: Dostupný od meta_keywords: Meta klíčová slova meta_description: Meta popis + product_variant: + available_on: Dostupné od + available_until: Dostupné do archetype: name: Jméno properties: Vlastnosti diff --git a/src/Sylius/Bundle/ProductBundle/Resources/translations/messages.en.yml b/src/Sylius/Bundle/ProductBundle/Resources/translations/messages.en.yml index fa7d5af3f79..6920f4953d0 100644 --- a/src/Sylius/Bundle/ProductBundle/Resources/translations/messages.en.yml +++ b/src/Sylius/Bundle/ProductBundle/Resources/translations/messages.en.yml @@ -9,6 +9,7 @@ sylius: meta_description: Meta description product_variant: available_on: Available on + available_until: Available until product_archetype: name: Name parent: Parent diff --git a/src/Sylius/Bundle/WebBundle/Resources/translations/messages.cs.yml b/src/Sylius/Bundle/WebBundle/Resources/translations/messages.cs.yml index 65316e142c4..e6756f465f7 100644 --- a/src/Sylius/Bundle/WebBundle/Resources/translations/messages.cs.yml +++ b/src/Sylius/Bundle/WebBundle/Resources/translations/messages.cs.yml @@ -263,8 +263,11 @@ sylius: name: Jméno updated_at: Poslední aktualizace product: + available_now: Aktuálně dostupný available_on: Dostupný od available_on_demand: K dispozici na požádání + available_unlimited: Neomezeno + available_until: Dostupný do categorization: Kategorizace create_header: Nový produkt description: Popis @@ -337,6 +340,9 @@ sylius: shipping_address: Doručovací adresa username: Uživatelské jméno variant: + available_on: Dostupnost od + available_unlimited: Neomezená + available_until: Dostupnost do available_on_demand: K dispozici na požádání last_update: Poslední aktualizace options: Možnosti diff --git a/src/Sylius/Bundle/WebBundle/Resources/translations/messages.en.yml b/src/Sylius/Bundle/WebBundle/Resources/translations/messages.en.yml index 897ed03c4fb..28e39e54e67 100644 --- a/src/Sylius/Bundle/WebBundle/Resources/translations/messages.en.yml +++ b/src/Sylius/Bundle/WebBundle/Resources/translations/messages.en.yml @@ -594,8 +594,11 @@ sylius: updated_at: Last update product: add_attribute: Add attribute + available_now: Available now available_on: Available on available_on_demand: Available on demand + available_unlimited: Unlimited + available_until: Available until categorization: Categorization contain_variants: Contain Variants create: Create product @@ -850,6 +853,10 @@ sylius: variant: add_image: Add image availability: Availability + available_on: Available since + available_unlimited: Unlimited + available_until: Available until + available: Available available_on_demand: Available on demand create: Create variant create_header: New product variant diff --git a/src/Sylius/Bundle/WebBundle/Resources/views/Backend/Product/Form/_main.html.twig b/src/Sylius/Bundle/WebBundle/Resources/views/Backend/Product/Form/_main.html.twig index a3f7c562b04..17da9870596 100644 --- a/src/Sylius/Bundle/WebBundle/Resources/views/Backend/Product/Form/_main.html.twig +++ b/src/Sylius/Bundle/WebBundle/Resources/views/Backend/Product/Form/_main.html.twig @@ -5,8 +5,8 @@
- {{ form_label(form.masterVariant.availableOn) }} - {{ form_widget(form.masterVariant.availableOn, {'label': false}) }} + {{ form_row(form.masterVariant.availableOn) }} + {{ form_row(form.masterVariant.availableUntil) }} {{ form_row(form.masterVariant.availableOnDemand) }} {{ form_row(form.masterVariant.onHand) }}
diff --git a/src/Sylius/Bundle/WebBundle/Resources/views/Backend/Product/show.html.twig b/src/Sylius/Bundle/WebBundle/Resources/views/Backend/Product/show.html.twig index 8b8b2c05987..665402fad53 100644 --- a/src/Sylius/Bundle/WebBundle/Resources/views/Backend/Product/show.html.twig +++ b/src/Sylius/Bundle/WebBundle/Resources/views/Backend/Product/show.html.twig @@ -71,9 +71,17 @@ {{ 'sylius.product.name'|trans }} {{ product.name }} + + {{ 'sylius.product.available_now'|trans }} + {{ product.available ? 'sylius.yes'|trans : 'sylius.no'|trans }} + {{ 'sylius.product.available_on'|trans }} - {{ product.availableOn|date }} + {{ product.availableOn|date }} + + + {{ 'sylius.product.available_until'|trans }} + {{ product.availableUntil == null ? 'sylius.product.available_unlimited'|trans : product.availableUntil|date }} {{ 'sylius.product.options'|trans }} diff --git a/src/Sylius/Bundle/WebBundle/Resources/views/Backend/ProductVariant/_form.html.twig b/src/Sylius/Bundle/WebBundle/Resources/views/Backend/ProductVariant/_form.html.twig index 51182dc6ce4..5a22cdb5ec7 100644 --- a/src/Sylius/Bundle/WebBundle/Resources/views/Backend/ProductVariant/_form.html.twig +++ b/src/Sylius/Bundle/WebBundle/Resources/views/Backend/ProductVariant/_form.html.twig @@ -15,6 +15,15 @@
{{ form_row(form.availableOn.date, {'label': false}) }} {{ form_row(form.availableOn.time, {'label': false}) }} + {{ form_errors(form.availableOn) }} +
+
+
+ {{ form_label(form.availableUntil) }} +
+ {{ form_row(form.availableUntil.date, {'label': false}) }} + {{ form_row(form.availableUntil.time, {'label': false}) }} + {{ form_errors(form.availableUntil) }}
{{ form_row(form.price) }} diff --git a/src/Sylius/Bundle/WebBundle/Resources/views/Backend/ProductVariant/macros.html.twig b/src/Sylius/Bundle/WebBundle/Resources/views/Backend/ProductVariant/macros.html.twig index c21b1ab3592..092473590ba 100644 --- a/src/Sylius/Bundle/WebBundle/Resources/views/Backend/ProductVariant/macros.html.twig +++ b/src/Sylius/Bundle/WebBundle/Resources/views/Backend/ProductVariant/macros.html.twig @@ -10,7 +10,8 @@ id {{ 'sylius.variant.sku'|trans }} - {{ 'sylius.variant.availability'|trans }} + {{ 'sylius.variant.available_on'|trans }} + {{ 'sylius.variant.available_until'|trans }} {{ 'sylius.variant.last_update'|trans }} {{ 'sylius.variant.options'|trans }} {{ 'sylius.variant.available_on_demand'|trans }} @@ -29,7 +30,14 @@ {% endif %} - {{ variant.availableOn|date }} + + + {{ variant.availableOn|date }} + + + + {{ variant.availableUntil == null ? 'sylius.variant.available_unlimited'|trans : variant.availableUntil|date }} + {{ product.updatedAt|date }}
- {% if not product.hasVariants and not sylius_inventory_is_available(product.masterVariant) %} + {% if not product.available %} + {{ 'sylius.product.unavailable'|trans }} + {% elseif not product.hasVariants and not sylius_inventory_is_available(product.masterVariant) %} {{ 'sylius.out_of_stock'|trans }} {% else %} {{ form_row(form.quantity, {'attr': {'class': 'center-text'}, 'empty_value': '1'}) }} diff --git a/src/Sylius/Component/Product/Model/Product.php b/src/Sylius/Component/Product/Model/Product.php index afa51f95e3f..fefef701b5a 100644 --- a/src/Sylius/Component/Product/Model/Product.php +++ b/src/Sylius/Component/Product/Model/Product.php @@ -11,6 +11,7 @@ namespace Sylius\Component\Product\Model; +use DateTime; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\Collection; use Sylius\Component\Archetype\Model\ArchetypeInterface as BaseArchetypeInterface; @@ -42,10 +43,18 @@ class Product extends AbstractTranslatable implements ProductInterface /** * Available on. * - * @var \DateTime + * @var DateTime */ protected $availableOn; + + /** + * Available until. + * + * @var DateTime + */ + protected $availableUntil; + /** * Attributes. * @@ -70,21 +79,21 @@ class Product extends AbstractTranslatable implements ProductInterface /** * Creation time. * - * @var \DateTime + * @var DateTime */ protected $createdAt; /** * Last update time. * - * @var \DateTime + * @var DateTime */ protected $updatedAt; /** * Deletion time. * - * @var \DateTime + * @var DateTime */ protected $deletedAt; @@ -94,11 +103,12 @@ class Product extends AbstractTranslatable implements ProductInterface public function __construct() { parent::__construct(); - $this->availableOn = new \DateTime(); + $this->availableOn = new DateTime(); + $this->availableUntil = null; $this->attributes = new ArrayCollection(); $this->variants = new ArrayCollection(); $this->options = new ArrayCollection(); - $this->createdAt = new \DateTime(); + $this->createdAt = new DateTime(); } /** @@ -222,7 +232,14 @@ public function setMetaDescription($metaDescription) */ public function isAvailable() { - return new \DateTime() >= $this->availableOn; + $now = new DateTime(); + return + $now >= $this->availableOn + && ( + $this->availableUntil === null ? + true : + ( $now < $this->availableUntil ) + ); } /** @@ -236,13 +253,29 @@ public function getAvailableOn() /** * {@inheritdoc} */ - public function setAvailableOn(\DateTime $availableOn = null) + public function setAvailableOn(DateTime $availableOn = null) { $this->availableOn = $availableOn; - return $this; } + /** + * {@inheritdoc} + */ + public function getAvailableUntil() + { + return $this->availableUntil; + } + + /** + * {@inheritdoc} + */ + public function setAvailableUntil(DateTime $availableUntil = null) + { + $this->availableUntil = $availableUntil; + return $this; + } + /** * {@inheritdoc} */ @@ -499,7 +532,7 @@ public function getCreatedAt() /** * {@inheritdoc} */ - public function setCreatedAt(\DateTime $createdAt) + public function setCreatedAt(DateTime $createdAt) { $this->createdAt = $createdAt; @@ -517,7 +550,7 @@ public function getUpdatedAt() /** * {@inheritdoc} */ - public function setUpdatedAt(\DateTime $updatedAt) + public function setUpdatedAt(DateTime $updatedAt) { $this->updatedAt = $updatedAt; @@ -529,7 +562,7 @@ public function setUpdatedAt(\DateTime $updatedAt) */ public function isDeleted() { - return null !== $this->deletedAt && new \DateTime() >= $this->deletedAt; + return null !== $this->deletedAt && new DateTime() >= $this->deletedAt; } /** @@ -543,7 +576,7 @@ public function getDeletedAt() /** * {@inheritdoc} */ - public function setDeletedAt(\DateTime $deletedAt) + public function setDeletedAt(DateTime $deletedAt) { $this->deletedAt = $deletedAt; diff --git a/src/Sylius/Component/Product/Model/ProductInterface.php b/src/Sylius/Component/Product/Model/ProductInterface.php index 9318ef82880..4cc9df5e175 100644 --- a/src/Sylius/Component/Product/Model/ProductInterface.php +++ b/src/Sylius/Component/Product/Model/ProductInterface.php @@ -23,30 +23,44 @@ * @author Gonzalo Vilaseca */ interface ProductInterface extends - ArchetypeSubjectInterface, - SlugAwareInterface, - SoftDeletableInterface, - TimestampableInterface, - ProductTranslationInterface + ArchetypeSubjectInterface, + SlugAwareInterface, + SoftDeletableInterface, + TimestampableInterface, + ProductTranslationInterface { - /** - * Check whether the product is available. - * - * @return bool - */ - public function isAvailable(); - - /** - * Return available on. - * - * @return \DateTime - */ - public function getAvailableOn(); - - /** - * Set available on. - * - * @param null|\DateTime $availableOn - */ - public function setAvailableOn(\DateTime $availableOn = null); + /** + * Check whether the product is available. + * + * @return bool + */ + public function isAvailable(); + + /** + * Return available on. + * + * @return \DateTime + */ + public function getAvailableOn(); + + /** + * Set available on. + * + * @param null|\DateTime $availableOn + */ + public function setAvailableOn(\DateTime $availableOn = null); + + /** + * Return available until. + * + * @return \DateTime + */ + public function getAvailableUntil(); + + /** + * Set available until. + * + * @param null|\DateTime $availableUntil + */ + public function setAvailableUntil(\DateTime $availableUntil = null); } diff --git a/src/Sylius/Component/Product/Model/Variant.php b/src/Sylius/Component/Product/Model/Variant.php index 4131676af9d..e7b7bcb379f 100644 --- a/src/Sylius/Component/Product/Model/Variant.php +++ b/src/Sylius/Component/Product/Model/Variant.php @@ -11,6 +11,7 @@ namespace Sylius\Component\Product\Model; +use DateTime; use Sylius\Component\Variation\Model\Variant as BaseVariant; use Sylius\Component\Variation\Model\VariantInterface as BaseVariantInterface; @@ -21,82 +22,119 @@ */ class Variant extends BaseVariant implements VariantInterface { - /** - * Available on. - * - * @var \DateTime - */ - protected $availableOn; - - /** - * Constructor. - */ - public function __construct() - { - parent::__construct(); - - $this->availableOn = new \DateTime(); - } - - /** - * {@inheritdoc} - */ - public function getProduct() - { - return parent::getObject(); - } - - /** - * {@inheritdoc} - */ - public function setProduct(ProductInterface $product = null) - { - return parent::setObject($product); - } - - /** - * {@inheritdoc} - */ - public function isAvailable() - { - return new \DateTime() >= $this->availableOn; - } - - /** - * {@inheritdoc} - */ - public function getAvailableOn() - { - return $this->availableOn; - } - - /** - * {@inheritdoc} - */ - public function setAvailableOn(\DateTime $availableOn = null) - { - $this->availableOn = $availableOn; - - if ($this->isMaster() && null !== $this->object) { - $this->getProduct()->setAvailableOn($availableOn); - } - - return $this; - } - - /** - * {@inheritdoc} - */ - public function setDefaults(BaseVariantInterface $masterVariant) - { - parent::setDefaults($masterVariant); - - if (!$masterVariant instanceof VariantInterface) { - throw new \InvalidArgumentException('Product variants must implement "Sylius\Component\Product\Model\VariantInterface".'); - } - - $this->setAvailableOn($masterVariant->getAvailableOn()); - - return $this; - } + /** + * Available on. + * + * @var \DateTime + */ + protected $availableOn; + + /** + * Available until. + * + * @var DateTime + */ + protected $availableUntil; + + /** + * Constructor. + */ + public function __construct() + { + parent::__construct(); + + $this->availableOn = new \DateTime(); + $this->availableUntil = null; + } + + /** + * {@inheritdoc} + */ + public function getProduct() + { + return parent::getObject(); + } + + /** + * {@inheritdoc} + */ + public function setProduct(ProductInterface $product = null) + { + return parent::setObject($product); + } + + /** + * {@inheritdoc} + */ + public function isAvailable() + { + $now = new DateTime(); + return + $now >= $this->availableOn + && ( + $this->availableUntil === null ? + true : + ( $now < $this->availableUntil ) + ); + } + + /** + * {@inheritdoc} + */ + public function getAvailableOn() + { + return $this->availableOn; + } + + /** + * {@inheritdoc} + */ + public function setAvailableOn(\DateTime $availableOn = null) + { + $this->availableOn = $availableOn; + + if ($this->isMaster() && null !== $this->object) { + $this->getProduct()->setAvailableOn($availableOn); + } + + return $this; + } + + /** + * {@inheritdoc} + */ + public function getAvailableUntil() + { + return $this->availableUntil; + } + + /** + * {@inheritdoc} + */ + public function setAvailableUntil(DateTime $availableUntil = null) + { + $this->availableUntil = $availableUntil; + + if ($this->isMaster() && null !== $this->object) { + $this->getProduct()->setAvailableUntil($availableUntil); + } + + return $this; + } + + /** + * {@inheritdoc} + */ + public function setDefaults(BaseVariantInterface $masterVariant) + { + parent::setDefaults($masterVariant); + + if (!$masterVariant instanceof VariantInterface) { + throw new \InvalidArgumentException('Product variants must implement "Sylius\Component\Product\Model\VariantInterface".'); + } + + $this->setAvailableOn($masterVariant->getAvailableOn()); + + return $this; + } } diff --git a/src/Sylius/Component/Product/Model/VariantInterface.php b/src/Sylius/Component/Product/Model/VariantInterface.php index c973ac2f42c..41bb5887daa 100644 --- a/src/Sylius/Component/Product/Model/VariantInterface.php +++ b/src/Sylius/Component/Product/Model/VariantInterface.php @@ -52,4 +52,18 @@ public function getAvailableOn(); * @param null|\DateTime $availableOn */ public function setAvailableOn(\DateTime $availableOn = null); + + /** + * Return available until. + * + * @return \DateTime + */ + public function getAvailableUntil(); + + /** + * Set available until. + * + * @param null|\DateTime $availableUntil + */ + public function setAvailableUntil(\DateTime $availableUntil = null); }