Skip to content

Commit

Permalink
Merge pull request #3783 from starspire/feature/product-original-price
Browse files Browse the repository at this point in the history
[Product] added original price
  • Loading branch information
Paweł Jędrzejewski committed Dec 30, 2015
2 parents 2cb483c + 866613d commit 79b81d0
Show file tree
Hide file tree
Showing 22 changed files with 167 additions and 9 deletions.
28 changes: 28 additions & 0 deletions app/migrations/Version20151228175507.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?php

namespace Sylius\Migrations;

use Doctrine\DBAL\Migrations\AbstractMigration;
use Doctrine\DBAL\Schema\Schema;
/**
* Auto-generated Migration: Please modify to your needs!
*/
class Version20150922153417 extends AbstractMigration
{
/**
* @param Schema $schema
*/
public function up(Schema $schema)
{
// this up() migration is auto-generated, please modify it to your needs
$this->addSql("ALTER TABLE sylius_product_variant ADD original_price INT NULL;");
}
/**
* @param Schema $schema
*/
public function down(Schema $schema)
{
// this down() migration is auto-generated, please modify it to your needs
$this->addSql("ALTER TABLE sylius_product_variant DROP COLUMN original_price;");
}
}
7 changes: 7 additions & 0 deletions features/backend/product_variants.feature
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,13 @@ Feature: Product variants
And I press "Create"
Then I should see "Price must not be negative"

Scenario: Trying to create product variant with invalid original price
Given I am creating variant of "Black T-Shirt"
When I fill in "Price" with "1.00"
And I fill in "Original price" with "-0.01"
And I press "Create"
Then I should see "Original price must not be negative"

Scenario: Displaying the "Generate variants" button
only for products with options
Given I am viewing product "Mug"
Expand Down
13 changes: 7 additions & 6 deletions src/Sylius/Bundle/CoreBundle/Controller/ProductController.php
Original file line number Diff line number Diff line change
Expand Up @@ -224,12 +224,13 @@ public function searchAction(Request $request)
$helper = $this->get('sylius.templating.helper.currency');
foreach ($products as $product) {
$results[] = array(
'id' => $product->getMasterVariant()->getId(),
'name' => $product->getName(),
'image' => $product->getImage()->getPath(),
'price' => $helper->convertAndFormatAmount($product->getMasterVariant()->getPrice()),
'raw_price' => $helper->convertAndFormatAmount($product->getMasterVariant()->getPrice(), null, true),
'desc' => $product->getShortDescription(),
'id' => $product->getMasterVariant()->getId(),
'name' => $product->getName(),
'image' => $product->getImage()->getPath(),
'price' => $helper->convertAndFormatAmount($product->getMasterVariant()->getPrice()),
'original_price' => $helper->convertAndFormatAmount($product->getMasterVariant()->getOriginalPrice()),
'raw_price' => $helper->convertAndFormatAmount($product->getMasterVariant()->getPrice(), null, true),
'desc' => $product->getShortDescription(),
);
}

Expand Down
3 changes: 3 additions & 0 deletions src/Sylius/Bundle/CoreBundle/Form/Type/ProductVariantType.php
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ public function buildForm(FormBuilderInterface $builder, array $options)
->add('price', 'sylius_money', array(
'label' => 'sylius.form.variant.price'
))
->add('originalPrice', 'sylius_money', array(
'label' => 'sylius.form.variant.original_price'
))
->add('availableOnDemand', 'checkbox', array(
'label' => 'sylius.form.variant.available_on_demand'
))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@
<field name="price" column="price" type="integer">
<gedmo:versioned />
</field>
<field name="originalPrice" column="original_price" type="integer" nullable="true">
<gedmo:versioned />
</field>
<field name="pricingCalculator" column="pricing_calculator" type="string">
<gedmo:versioned/>
</field>
Expand Down
7 changes: 7 additions & 0 deletions src/Sylius/Bundle/CoreBundle/Resources/config/validation.xml
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,13 @@
<option name="groups">sylius</option>
</constraint>
</property>
<property name="originalPrice">
<constraint name="Range">
<option name="min">0.00</option>
<option name="minMessage">sylius.product_variant.original_price.min</option>
<option name="groups">sylius</option>
</constraint>
</property>
<property name="onHand">
<constraint name="NotBlank">
<option name="message">sylius.product_variant.onHand.not_blank</option>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ sylius:
images: Images
on_hand: Current stock
price: Price
original_price: Original price
sku: SKU
weight: Weight
width: Width
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ sylius:
price:
min: Price must not be negative.
not_blank: Please enter the price.
original_price:
min: Original price must not be negative.
product_translation:
short_description:
max: Short description must not be longer then {{ limit }} characters.
Expand Down
2 changes: 2 additions & 0 deletions src/Sylius/Bundle/WebBundle/Resources/public/css/backend.css
Original file line number Diff line number Diff line change
Expand Up @@ -493,11 +493,13 @@ form.form-signin .btn-success:hover {
.sylius-products-table .id,
.sylius-products-table .stock,
.sylius-products-table .retail-price,
.sylius-products-table .original-price,
.sylius-products-table .updated-at {
text-align: center;
}
.sylius-products-table .stock,
.sylius-products-table .retail-price,
.sylius-products-table .original-price,
.sylius-products-table .updated-at {
width: 150px;
}
Expand Down
9 changes: 9 additions & 0 deletions src/Sylius/Bundle/WebBundle/Resources/public/css/frontend.css
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,15 @@ a.create-ui-toggle {
background-repeat: no-repeat !important;
cursor: pointer;
}

/* Specific rules */
.crossed {
text-decoration: line-through;
}
.label-originalprice {
margin-right: 0.3em;
}

.create-ui-toolbar-wrapper a {
font-family: "Open Sans", "Helvetica Neue", "Helvetica", "Arial", sans-serif !important;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -740,6 +740,7 @@ sylius:
options: Options
variants: Variants
price: Retail price
original_price: Original price
attributes: Attributes
restricted_zone: Restricted zone
remove_attribute: Remove attribute
Expand Down Expand Up @@ -1023,6 +1024,7 @@ sylius:
no_results: There are no variants to display.
options: Options
price: Price
original_price: Original price
sku: SKU
stock: Current stock
update_header: Editing variant
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
{{ form_row(form.masterVariant.onHand) }}
<hr />
{{ form_row(form.masterVariant.price) }}
{{ form_row(form.masterVariant.originalPrice) }}
{{ form_row(form.masterVariant.pricingCalculator) }}

{% if form.masterVariant.pricingConfiguration is defined %}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
<th class="info">{{ sylius_resource_sort('name', 'sylius.product.name'|trans) }}</th>
<th class="stock">{{ 'sylius.product.stock'|trans }}</th>
<th class="retail-price">{{ 'sylius.product.price'|trans }}</th>
<th class="original-price">{{ 'sylius.product.original_price'|trans }}</th>
<th class="updated-at">{{ sylius_resource_sort('updatedAt', 'Updated At') }}</th>
<th></th>
</tr>
Expand Down Expand Up @@ -76,10 +77,16 @@
<td class="retail-price">
{{ product.masterVariant.price|sylius_price }}
</td>
<td class="original-price">
{{ product.masterVariant.originalPrice|sylius_price }}
</td>
{% else %}
<td class="retail-price text-muted">
<em>{{ 'sylius.na'|trans }}</em>
</td>
<td class="original-price text-muted">
<em>{{ 'sylius.na'|trans }}</em>
</td>
{% endif %}

<td class="updated-at">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,10 @@
<td>{{ 'sylius.product.price'|trans }}</td>
<td>{{ product.masterVariant.price|sylius_price }}</td>
</tr>
<tr>
<td>{{ 'sylius.product.original_price'|trans }}</td>
<td>{{ product.masterVariant.originalPrice|sylius_price }}</td>
</tr>
{% if product.masterVariant.pricingCalculator == 'volume_based' %}
<tr>
<td>{{ 'sylius.product.volume_price'|trans }}</td>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
</div>
</div>
{{ form_row(form.price) }}
{{ form_row(form.originalPrice) }}
{{ form_row(form.pricingCalculator) }}
{% if form.pricingConfiguration is defined %}
{% if form.pricingCalculator.vars.value == 'volume_based' %}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
<th>{{ 'sylius.variant.available_on_demand'|trans }}</th>
<th>{{ 'sylius.variant.stock'|trans }}</th>
<th>{{ 'sylius.variant.price'|trans }}</th>
<th>{{ 'sylius.variant.original_price'|trans }}</th>
<th></th>
</tr>
</thead>
Expand Down Expand Up @@ -45,6 +46,7 @@
</td>
<td><span class="label label-{{ variant.inStock ? 'success' : 'important' }}">{{ variant.onHand }}</span></td>
<td>{{ variant.price|sylius_price }}</td>
<td>{{ variant.originalPrice|sylius_price }}</td>
<td>
<div class="pull-right">
{% if not variant.deleted %}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
{% from 'SyliusWebBundle:Frontend/Product:macros.html.twig' import sylius_display_price %}
<div class="product-box">
<a href="{{ path(product) }}"><h4>{{ product.name|truncate(18) }}</h4></a>
<a href="{{ path(product) }}">
<img class="img-rounded img-responsive" src="{{ product.image ? product.image.path|imagine_filter('sylius_medium') : 'http://placehold.it/262x255' }}" alt="{{ product.name }}" />
<span class="label label-primary">{{ sylius_calculate_price(product.masterVariant)|sylius_price }}</span>
{{ sylius_display_price(product.masterVariant) }}
<button class="btn btn-success btn-xs pull-right"><i class="icon-shopping-cart icon-white"></i> {{ 'sylius.add_to_cart'|trans }}</button>
</a>
</div>
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,10 @@
</div>

{% endmacro %}

{% macro sylius_display_price(variant) %}
{% if (variant.isPriceReduced) %}
<span class='label label-success crossed'>{{ variant.originalPrice|sylius_price }}</span>
{% endif %}
<span class='label label-success'>{{ sylius_calculate_price(variant)|sylius_price }}</span>
{% endmacro %}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
{% extends 'SyliusWebBundle:Frontend:layout.html.twig' %}

{% set form = sylius_cart_form({'product': product}) %}
{% from 'SyliusWebBundle:Frontend/Product:macros.html.twig' import sylius_display_price %}

{% block content %}
<div class="row">
Expand Down Expand Up @@ -80,7 +81,7 @@
{% endif %}
</td>
<td>
<span class="label label-success">{{ sylius_calculate_price(variant)|sylius_price }}</span>
{{ sylius_display_price(variant) }}
</td>
<td>
{% if sylius_inventory_is_available(variant) %}
Expand All @@ -100,7 +101,9 @@
{% endif %}
{% else %}
<h4>
<span class="label label-success pull-right">{{ sylius_calculate_price(product.masterVariant)|sylius_price }}</span>
<span class="pull-right">
{{ sylius_display_price(product.masterVariant) }}
</span>
{{ 'sylius.variant.price'|trans }}
</h4>
{% endif %}
Expand Down
32 changes: 32 additions & 0 deletions src/Sylius/Component/Core/Model/ProductVariant.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,11 @@ class ProductVariant extends BaseVariant implements ProductVariantInterface
*/
protected $price;

/**
* @var int
*/
protected $originalPrice;

/**
* The pricing calculator.
*
Expand Down Expand Up @@ -181,6 +186,25 @@ public function setPrice($price)
return $this;
}

/**
* {@inheritdoc}
*/
public function setOriginalPrice($originalPrice)
{
if (!is_int($originalPrice)) {
throw new \InvalidArgumentException('Original price must be an integer.');
}
$this->originalPrice = $originalPrice;
}

/**
* {@inheritdoc}
*/
public function getOriginalPrice()
{
return $this->originalPrice;
}

/**
* {@inheritdoc}
*/
Expand Down Expand Up @@ -492,4 +516,12 @@ public function getShippingVolume()
{
return $this->depth * $this->height * $this->width;
}

/**
* {@inheritdoc}
*/
public function isPriceReduced()
{
return $this->originalPrice > $this->price;
}
}
15 changes: 15 additions & 0 deletions src/Sylius/Component/Core/Model/ProductVariantInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -117,4 +117,19 @@ public function getDepth();
* @param float $depth
*/
public function setDepth($depth);

/**
* @return int
*/
public function getOriginalPrice();

/**
* @param int $originalPrice
*/
public function setOriginalPrice($originalPrice);

/**
* @return bool
*/
public function isPriceReduced();
}
20 changes: 20 additions & 0 deletions src/Sylius/Component/Core/spec/Model/ProductVariantSpec.php
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,11 @@ function it_should_not_have_price_by_default()
$this->getPrice()->shouldReturn(null);
}

function it_should_not_have_original_price_by_default()
{
$this->getOriginalPrice()->shouldReturn(null);
}

function it_initializes_image_collection_by_default()
{
$this->getImages()->shouldHaveType('Doctrine\Common\Collections\Collection');
Expand All @@ -51,6 +56,12 @@ function its_price_should_be_mutable()
$this->setPrice(499)->getPrice()->shouldReturn(499);
}

function its_original_price_should_be_mutable()
{
$this->setOriginalPrice(399);
$this->getOriginalPrice()->shouldReturn(399);
}

function its_price_should_accept_only_integer()
{
$this->setPrice(410)->getPrice()->shouldBeInteger();
Expand All @@ -61,6 +72,15 @@ function its_price_should_accept_only_integer()
$this->shouldThrow('\InvalidArgumentException')->duringSetPrice(new \stdClass());
}

function its_original_price_should_accept_only_integer()
{
$this->shouldThrow(\InvalidArgumentException::class)->duringSetOriginalPrice(3.1 * 100);
$this->shouldThrow(\InvalidArgumentException::class)->duringSetOriginalPrice('310');
$this->shouldThrow(\InvalidArgumentException::class)->duringSetOriginalPrice(round(3.1 * 100));
$this->shouldThrow(\InvalidArgumentException::class)->duringSetOriginalPrice(array(310));
$this->shouldThrow(\InvalidArgumentException::class)->duringSetOriginalPrice(new \stdClass());
}

function it_should_inherit_price_from_master_variant(ProductVariantInterface $masterVariant)
{
$masterVariant->isMaster()->willReturn(true);
Expand Down

0 comments on commit 79b81d0

Please sign in to comment.