Skip to content

Add multiprice recipe #56

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 6 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion v2/recipes/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,6 @@ These recipes are all designed to work off of each other, so try it out - you ca

[Products](products.md) - Products and types.

[Orders](orders.md) - Orders, order items, and their types.
[Multiprice](multiprice.md) - Multiprice and multicurrency.

[Orders](orders.md) - Orders, order items, and their types.
229 changes: 229 additions & 0 deletions v2/recipes/multiprice.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,229 @@
# Multiprice and multicurrency

We want to define a specific price and currency for each language.

## Adding languages

Enable language module and add French and Japanese languages.

## Creating field

We need as many commerce_price fields as currency in product variation in place of default price field.

Add following fields in a custom module or add your own commerce_price fields to product variation.

```yaml
# config/install/field.field.commerce_product_variation.default.price_eur.yml
langcode: en
status: true
dependencies:
config:
- commerce_product.commerce_product_variation_type.default
- field.storage.commerce_product_variation.price_eur
module:
- commerce_price
id: commerce_product_variation.default.price_eur
field_name: price_eur
entity_type: commerce_product_variation
bundle: default
label: Price EUR
description: 'Define price for EUR currency'
required: true
translatable: false
default_value: { }
default_value_callback: ''
settings:
available_currencies:
- 'EUR'
field_type: commerce_price
```

```yaml
# config/install/field.storage.commerce_product_variation.price_eur.yml
langcode: en
status: true
dependencies:
module:
- commerce_price
- commerce_product
id: commerce_product_variation.price_eur
field_name: price_eur
entity_type: commerce_product_variation
type: commerce_price
settings: { }
module: commerce_price
locked: false
cardinality: 1
translatable: true
indexes: { }
persist_with_no_fields: false
custom_storage: false
```

```yaml
# config/install/field.field.commerce_product_variation.default.price_usd.yml
langcode: en
status: true
dependencies:
config:
- commerce_product.commerce_product_variation_type.default
- field.storage.commerce_product_variation.price_usd
module:
- commerce_price
id: commerce_product_variation.default.price_usd
field_name: price_usd
entity_type: commerce_product_variation
bundle: default
label: Price USD
description: 'Define price for USD currency'
required: true
translatable: false
default_value: { }
default_value_callback: ''
settings:
available_currencies:
- 'USD'
field_type: commerce_price
```

```yaml
# config/install/field.storage.commerce_product_variation.price_usd.yml
langcode: en
status: true
dependencies:
module:
- commerce_price
- commerce_product
id: commerce_product_variation.price_usd
field_name: price_usd
entity_type: commerce_product_variation
type: commerce_price
settings: { }
module: commerce_price
locked: false
cardinality: 1
translatable: true
indexes: { }
persist_with_no_fields: false
custom_storage: false
```

```yaml
# config/install/field.field.commerce_product_variation.default.price_jpy.yml
langcode: en
status: true
dependencies:
config:
- commerce_product.commerce_product_variation_type.default
- field.storage.commerce_product_variation.price_jpy
module:
- commerce_price
id: commerce_product_variation.default.price_jpy
field_name: price_jpy
entity_type: commerce_product_variation
bundle: default
label: Price JPY
description: 'Define price for JPY currency'
required: true
translatable: false
default_value: { }
default_value_callback: ''
settings:
available_currencies:
- 'JPY'
field_type: commerce_price
```

```yaml
# config/install/field.storage.commerce_product_variation.price_jpy.yml
langcode: en
status: true
dependencies:
module:
- commerce_price
- commerce_product
id: commerce_product_variation.price_jpy
field_name: price_jpy
entity_type: commerce_product_variation
type: commerce_price
settings: { }
module: commerce_price
locked: false
cardinality: 1
translatable: true
indexes: { }
persist_with_no_fields: false
custom_storage: false
```

* Hide default price field from product variation form display.
* Display default price field format to 'Calculated price' in display mode.

## Creating resolver

### Add resolver to services

```yaml
services:
commerce_multiprice_example.commerce_multicurrency_resolver:
class: Drupal\commerce_multiprice_example\Resolvers\CommerceMulticurrencyResolver
arguments: ['@language_manager']
tags:
- { name: commerce_price.price_resolver, priority: 600 }
```

### Creating resolver

Replace multiprice field name by your own field if needed.

```php
<?php
namespace Drupal\commerce_multiprice_example\Resolvers;

use Drupal\commerce\Context;
use Drupal\commerce\PurchasableEntityInterface;
use Drupal\commerce_price\Price;
use Drupal\commerce_price\Resolver\PriceResolverInterface;

/**
* Returns a price and currency depending of language.
*/
class CommerceMulticurrencyResolver implements PriceResolverInterface {

/**
* The language manager.
*
* @var \Drupal\Core\Language\LanguageManagerInterface
*/
protected $languageManager;

/**
* Constructs a new CommerceMulticurrencyResolver object.
*
* @param \Drupal\Core\Language\LanguageManagerInterface $language_manager
* The language manager.
*/
public function __construct(LanguageManagerInterface $language_manager) {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Working on https://www.drupal.org/node/2831954#comment-11906059
and using the implementation suggested here, the tests won't work with $language_manager construct argument.

Please check my PR for the issue drupalcommerce/commerce#626
And maybe we could get the right solution for how this CommerceMulticurrencyResolver should be done

$this->languageManager = $language_manager;
}

/**
* {@inheritdoc}
*/
public function resolve(PurchasableEntityInterface $entity, $quantity, Context $context) {
// Define mapping between language and currency.
$currency_by_language = ['en' => 'USD', 'fr' => 'EUR', 'ja' => 'JPY'];

// Get current language.
$language = $this->languageManager->getCurrentLanguage()->getId();

// Get value from currency price field.
if ($entity->hasField('price_' . strtolower($currency_by_language[$language]))) {
$price = $entity->get('price_' . strtolower($currency_by_language[$language]))->getValue();
$price = reset($price);

return new Price($price['number'], $price['currency_code']);
}
}
}
```