Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Promotions exclusive mode

  • Loading branch information...
commit 549279fe90c8163084a542e539778354c8727770 1 parent f9f4f74
@umpirsky umpirsky authored
Showing with 167 additions and 13 deletions.
  1. +1 −0  app/config/config.yml
  2. +2 −0  app/config/parameters.yml.dist
  3. +1 −0  app/config/sylius.yml
  4. +6 −0 features/backend/promotions.feature
  5. +2 −0  src/Sylius/Bundle/CoreBundle/DataFixtures/ORM/LoadPromotionsData.php
  6. +1 −0  src/Sylius/Bundle/PromotionsBundle/DependencyInjection/Configuration.php
  7. +3 −1 src/Sylius/Bundle/PromotionsBundle/DependencyInjection/SyliusPromotionsExtension.php
  8. +4 −1 src/Sylius/Bundle/PromotionsBundle/Doctrine/ORM/PromotionRepository.php
  9. +25 −0 src/Sylius/Bundle/PromotionsBundle/Model/Promotion.php
  10. +16 −0 src/Sylius/Bundle/PromotionsBundle/Model/PromotionInterface.php
  11. +7 −1 src/Sylius/Bundle/PromotionsBundle/Processor/PromotionProcessor.php
  12. +3 −0  src/Sylius/Bundle/PromotionsBundle/Resources/config/doctrine/model/Promotion.orm.xml
  13. +2 −1  src/Sylius/Bundle/PromotionsBundle/Resources/config/services.xml
  14. +6 −0 src/Sylius/Bundle/PromotionsBundle/spec/Sylius/Bundle/PromotionsBundle/Model/PromotionSpec.php
  15. +1 −1  src/Sylius/Bundle/PromotionsBundle/spec/Sylius/Bundle/PromotionsBundle/Processor/PromotionProcessorSpec.php
  16. +5 −0 src/Sylius/Bundle/ResourceBundle/Controller/Configuration.php
  17. +19 −2 src/Sylius/Bundle/ResourceBundle/Controller/DomainManager.php
  18. +18 −0 src/Sylius/Bundle/ResourceBundle/Controller/ResourceController.php
  19. +1 −0  src/Sylius/Bundle/ResourceBundle/Resources/translations/flashes.en.yml
  20. +9 −0 src/Sylius/Bundle/ResourceBundle/Resources/views/Macros/buttons.html.twig
  21. +20 −0 src/Sylius/Bundle/WebBundle/Resources/config/routing/backend/promotion.yml
  22. +9 −6 src/Sylius/Bundle/WebBundle/Resources/translations/messages.en.yml
  23. +2 −0  src/Sylius/Bundle/WebBundle/Resources/views/Backend/Promotion/macros.html.twig
  24. +4 −0 src/Sylius/Bundle/WebBundle/Resources/views/Backend/Promotion/show.html.twig
View
1  app/config/config.yml
@@ -76,6 +76,7 @@ stof_doctrine_extensions:
timestampable: true
softdeleteable: true
loggable: true
+ sortable: true
fos_user:
db_driver: orm
View
2  app/config/parameters.yml.dist
@@ -39,3 +39,5 @@ parameters:
sylius.inventory.backorders_enabled: true
sylius.inventory.tracking_enabled: true
+
+ sylius.promotions.exclusive: false
View
1  app/config/sylius.yml
@@ -64,6 +64,7 @@ sylius_shipping:
form: Sylius\Bundle\CoreBundle\Form\Type\ShippingMethodType
sylius_promotions:
+ exclusive: %sylius.promotions.exclusive%
classes:
promotion_subject:
model: %sylius.model.order.class%
View
6 features/backend/promotions.feature
@@ -229,6 +229,12 @@ Feature: Promotions
And I press "Save changes"
Then I should be on the page of promotion "New Year Sale"
+ Scenario: Setting promotion priorities
+ Given I am on the promotion index page
+ When I press "move down"
+ Then I should be on the promotion index page
+ And I should see "Promotion has been successfully moved."
+
@javascript
Scenario: Deleting promotion with
Given I am on the page of promotion "New Year"
View
2  src/Sylius/Bundle/CoreBundle/DataFixtures/ORM/LoadPromotionsData.php
@@ -36,6 +36,8 @@ public function load(ObjectManager $manager)
$manager->persist($promotion);
+ $manager->flush();
+
$promotion = $this->createPromotion(
'Christmas',
'Christmas Sale for orders over 100 EUR.',
View
1  src/Sylius/Bundle/PromotionsBundle/DependencyInjection/Configuration.php
@@ -34,6 +34,7 @@ public function getConfigTreeBuilder()
->addDefaultsIfNotSet()
->children()
->scalarNode('driver')->isRequired()->cannotBeEmpty()->end()
+ ->booleanNode('exclusive')->defaultFalse()->end()
->end()
;
View
4 src/Sylius/Bundle/PromotionsBundle/DependencyInjection/SyliusPromotionsExtension.php
@@ -26,6 +26,8 @@ class SyliusPromotionsExtension extends AbstractResourceExtension
*/
public function load(array $config, ContainerBuilder $container)
{
- $this->configure($config, new Configuration(), $container, self::CONFIGURE_LOADER | self::CONFIGURE_DATABASE | self::CONFIGURE_PARAMETERS | self::CONFIGURE_VALIDATORS);
+ list($config) = $this->configure($config, new Configuration(), $container, self::CONFIGURE_LOADER | self::CONFIGURE_DATABASE | self::CONFIGURE_PARAMETERS | self::CONFIGURE_VALIDATORS);
+
+ $container->setParameter('sylius.promotions_exclusive', $config['exclusive']);
}
}
View
5 src/Sylius/Bundle/PromotionsBundle/Doctrine/ORM/PromotionRepository.php
@@ -27,7 +27,10 @@ class PromotionRepository extends EntityRepository implements PromotionRepositor
*/
public function findActive()
{
- $qb = $this->getCollectionQueryBuilder();
+ $qb = $this
+ ->getCollectionQueryBuilder()
+ ->orderBy($this->getAlias().'.priority', 'DESC')
+ ;
$this->filterByActive($qb);
View
25 src/Sylius/Bundle/PromotionsBundle/Model/Promotion.php
@@ -43,6 +43,13 @@ class Promotion implements PromotionInterface
protected $description;
/**
+ * When using exclusive mode, promotion with top priority will be applied
+ *
+ * @var integer
+ */
+ protected $priority = 0;
+
+ /**
* Usage limit
*
* @var integer
@@ -170,6 +177,24 @@ public function setDescription($description)
/**
* {@inheritdoc}
*/
+ public function getPriority()
+ {
+ return $this->priority;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function setPriority($priority)
+ {
+ $this->priority = $priority;
+
+ return $this;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
public function getUsageLimit()
{
return $this->usageLimit;
View
16 src/Sylius/Bundle/PromotionsBundle/Model/PromotionInterface.php
@@ -50,6 +50,22 @@ public function getDescription();
public function setDescription($description);
/**
+ * Get priority
+ *
+ * @return integer
+ */
+ public function getPriority();
+
+ /**
+ * Set priority
+ *
+ * @param integer $priority
+ *
+ * @return PromotionInterface
+ */
+ public function setPriority($priority);
+
+ /**
* Get usage limit
*
* @return integer
View
8 src/Sylius/Bundle/PromotionsBundle/Processor/PromotionProcessor.php
@@ -28,12 +28,14 @@ class PromotionProcessor implements PromotionProcessorInterface
protected $repository;
protected $checker;
protected $applicator;
+ protected $exclusive;
- public function __construct(PromotionRepositoryInterface $repository, PromotionEligibilityCheckerInterface $checker, PromotionApplicatorInterface $applicator)
+ public function __construct(PromotionRepositoryInterface $repository, PromotionEligibilityCheckerInterface $checker, PromotionApplicatorInterface $applicator, $exclusive)
{
$this->repository = $repository;
$this->checker = $checker;
$this->applicator = $applicator;
+ $this->exclusive = $exclusive;
}
public function process(PromotionSubjectInterface $subject)
@@ -45,6 +47,10 @@ public function process(PromotionSubjectInterface $subject)
foreach ($this->repository->findActive() as $promotion) {
if ($this->checker->isEligible($subject, $promotion)) {
$this->applicator->apply($subject, $promotion);
+
+ if ($this->exclusive) {
+ return;
+ }
}
}
}
View
3  src/Sylius/Bundle/PromotionsBundle/Resources/config/doctrine/model/Promotion.orm.xml
@@ -21,6 +21,9 @@
<field name="name" type="string" />
<field name="description" type="string" />
+ <field name="priority" type="integer">
+ <gedmo:sortable-position/>
+ </field>
<field name="usageLimit" column="usage_limit" type="integer" nullable="true" />
<field name="used" type="integer" />
<field name="couponBased" column="coupon_based" type="boolean" />
View
3  src/Sylius/Bundle/PromotionsBundle/Resources/config/services.xml
@@ -40,7 +40,7 @@
<parameter key="sylius.form.type.promotion_action.fixed_discount_configuration.class">Sylius\Bundle\PromotionsBundle\Form\Type\Action\FixedDiscountConfigurationType</parameter>
<parameter key="sylius.form.type.promotion_action.percentage_discount_configuration.class">Sylius\Bundle\PromotionsBundle\Form\Type\Action\PercentageDiscountConfigurationType</parameter>
-
+
<parameter key="sylius.form.type.promotion_coupon_to_code.class">Sylius\Bundle\PromotionsBundle\Form\Type\CouponToCodeType</parameter>
<parameter key="sylius.form.type.promotion_coupon_generate_instruction.class">Sylius\Bundle\PromotionsBundle\Form\Type\CouponGenerateInstructionType</parameter>
@@ -52,6 +52,7 @@
<argument type="service" id="sylius.repository.promotion" />
<argument type="service" id="sylius.promotion_eligibility_checker" />
<argument type="service" id="sylius.promotion_applicator" />
+ <argument>%sylius.promotions_exclusive%</argument>
</service>
<service id="sylius.promotion_eligibility_checker" class="%sylius.promotion_eligibility_checker.class%">
View
6 src/Sylius/Bundle/PromotionsBundle/spec/Sylius/Bundle/PromotionsBundle/Model/PromotionSpec.php
@@ -48,6 +48,12 @@ function its_description_should_be_mutable()
$this->getDescription()->shouldReturn('New Year Sale 50% off.');
}
+ function its_priority_should_be_mutable()
+ {
+ $this->setPriority(5);
+ $this->getPriority()->shouldReturn(5);
+ }
+
function it_should_have_no_usage_limit_by_default()
{
$this->getUsageLimit()->shouldReturn(null);
View
2  src/Sylius/Bundle/PromotionsBundle/spec/Sylius/Bundle/PromotionsBundle/Processor/PromotionProcessorSpec.php
@@ -29,7 +29,7 @@ function let(
PromotionApplicatorInterface $applicator
)
{
- $this->beConstructedWith($repository, $checker, $applicator);
+ $this->beConstructedWith($repository, $checker, $applicator, false);
}
function it_should_be_initializable()
View
5 src/Sylius/Bundle/ResourceBundle/Controller/Configuration.php
@@ -269,6 +269,11 @@ public function getFlashMessage($message = null)
return $this->get('flash', $message);
}
+ public function getSortablePosition()
+ {
+ return $this->get('sortable_position', 'position');
+ }
+
protected function get($parameter, $default = null)
{
return isset($this->parameters[$parameter]) ? $this->parameters[$parameter] : $default;
View
21 src/Sylius/Bundle/ResourceBundle/Controller/DomainManager.php
@@ -15,6 +15,7 @@
use Sylius\Bundle\ResourceBundle\Event\ResourceEvent;
use Symfony\Component\EventDispatcher\Event;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
+use Symfony\Component\PropertyAccess\PropertyAccess;
/**
* Domain manager.
@@ -86,10 +87,11 @@ public function create($resource)
/**
* @param object $resource
+ * @param string $flash
*
* @return object|null
*/
- public function update($resource)
+ public function update($resource, $flash = 'update')
{
/** @var ResourceEvent $event */
$event = $this->dispatchEvent('pre_update', new ResourceEvent($resource));
@@ -106,13 +108,28 @@ public function update($resource)
$this->manager->persist($resource);
$this->manager->flush();
- $this->flashHelper->setFlash('success', 'update');
+ $this->flashHelper->setFlash('success', $flash);
$this->dispatchEvent('post_update', new ResourceEvent($resource));
return $resource;
}
+ public function move($resource, $movement)
+ {
+ $position = $this->config->getSortablePosition();
+
+ $accessor = PropertyAccess::createPropertyAccessor();
+
+ $accessor->setValue(
+ $resource,
+ $position,
+ $accessor->getValue($resource, $position) + $movement
+ );
+
+ return $this->update($resource, 'move');
+ }
+
/**
* @param object $resource
*
View
18 src/Sylius/Bundle/ResourceBundle/Controller/ResourceController.php
@@ -203,6 +203,24 @@ public function updateAction(Request $request)
return $this->handleView($view);
}
+ public function moveUpAction(Request $request)
+ {
+ $resource = $this->findOr404($request);
+
+ $this->domainManager->move($resource, 1);
+
+ return $this->redirectHandler->redirectToIndex();
+ }
+
+ public function moveDownAction(Request $request)
+ {
+ $resource = $this->findOr404($request);
+
+ $this->domainManager->move($resource, -1);
+
+ return $this->redirectHandler->redirectToIndex();
+ }
+
/**
* @param Request $request
* @return RedirectResponse
View
1  src/Sylius/Bundle/ResourceBundle/Resources/translations/flashes.en.yml
@@ -3,4 +3,5 @@ sylius:
create: %resource% has been successfully created.
update: %resource% has been successfully updated.
delete: %resource% has been successfully deleted.
+ move: %resource% has been successfully moved.
generate: %resource%s have been successfully generated.
View
9 src/Sylius/Bundle/ResourceBundle/Resources/views/Macros/buttons.html.twig
@@ -42,3 +42,12 @@
<i class="glyphicon glyphicon-folder-open"></i><span>{{ message is empty ? 'sylius.manage'|trans : message }}</span>
</a>
{% endmacro %}
+
+{% macro move(url, direction, first=false, last=false, message='') %}
+<form action="{{ url }}" method="post" class="delete-action-form" novalidate>
+ <input type="hidden" name="_method" value="PUT">
+ <button title="{{ message is empty ? ('sylius.move_'~direction)|trans : message }}" class="btn btn-default {% if ('up' == direction and first) or ('down' == direction and last) %}disabled{% endif %}" type="submit">
+ <i class="glyphicon glyphicon-arrow-{{ direction }}"></i>
+ </button>
+</form>
+{% endmacro %}
View
20 src/Sylius/Bundle/WebBundle/Resources/config/routing/backend/promotion.yml
@@ -9,6 +9,8 @@ sylius_backend_promotion_index:
_sylius:
template: SyliusWebBundle:Backend/Promotion:index.html.twig
sortable: true
+ sorting:
+ priority: desc
sylius_backend_promotion_create:
pattern: /new
@@ -28,6 +30,24 @@ sylius_backend_promotion_update:
template: SyliusWebBundle:Backend/Promotion:update.html.twig
redirect: sylius_backend_promotion_show
+sylius_backend_promotion_move_up:
+ pattern: /{id}/move-up
+ methods: [PUT]
+ defaults:
+ _controller: sylius.controller.promotion:moveUpAction
+ _sylius:
+ redirect: referer
+ sortable_position: priority
+
+sylius_backend_promotion_move_down:
+ pattern: /{id}/move-down
+ methods: [PUT]
+ defaults:
+ _controller: sylius.controller.promotion:moveDownAction
+ _sylius:
+ redirect: referer
+ sortable_position: priority
+
sylius_backend_promotion_delete:
pattern: /{id}
methods: [DELETE]
View
15 src/Sylius/Bundle/WebBundle/Resources/translations/messages.en.yml
@@ -20,8 +20,8 @@ sylius:
list: All your addresses
update: Edit my address
home:
- email: Email :
- id: Customer ID :
+ email: Email :
+ id: Customer ID :
outline: Enjoy all the features that are available on your personal space to view, track and manage all your data.
since: You are customer since
welcome: Welcome to your space
@@ -32,16 +32,16 @@ sylius:
empty: You have placed no order yet.
invoice: Invoice
list: All your orders
- number: Number :
- payment_mode: Payment mode :
+ number: Number :
+ payment_mode: Payment mode :
placed_at: Placed at %at%
shipment:
pending: Pending
ready: Ready since %at%
returned: Returned %at%
shipped: Shipped %at%
- shipment_mode: Shipment mode :
- state: State :
+ shipment_mode: Shipment mode :
+ state: State :
total: Total
tracking_number: Tracking number
title: My account
@@ -236,6 +236,8 @@ sylius:
delete: delete
deleted: Deleted
edit: edit
+ move_up: move up
+ move_down: move down
email: E-Mail
exchange_rate:
create: Create exchange rate
@@ -522,6 +524,7 @@ sylius:
updated_at: Last update
usage_limit: Usage limit
used: Used
+ priority: Priority
promotion_action:
configuration: Configuration
type: Type
View
2  src/Sylius/Bundle/WebBundle/Resources/views/Backend/Promotion/macros.html.twig
@@ -46,6 +46,8 @@
<td>{{ promotion.endsAt is empty ? '-' : promotion.endsAt|date }}</td>
<td>
<div class="pull-right">
+ {{ buttons.move(path('sylius_backend_promotion_move_up', {'id': promotion.id}), 'up', loop.first, loop.last) }}
+ {{ buttons.move(path('sylius_backend_promotion_move_down', {'id': promotion.id}), 'down', loop.first, loop.last) }}
{{ buttons.show(path('sylius_backend_promotion_show', {'id': promotion.id})) }}
{{ buttons.edit(path('sylius_backend_promotion_update', {'id': promotion.id})) }}
{{ buttons.delete(path('sylius_backend_promotion_delete', {'id': promotion.id})) }}
View
4 src/Sylius/Bundle/WebBundle/Resources/views/Backend/Promotion/show.html.twig
@@ -71,6 +71,10 @@
</span>
</td>
</tr>
+ <tr>
+ <td><strong>{{ 'sylius.promotion.priority'|trans }}</strong></td>
+ <td>{{ promotion.priority }}</td>
+ </tr>
</tbody>
</table>
</div>
Please sign in to comment.
Something went wrong with that request. Please try again.