Awesome to see this in action! Twig is very powerful, and this allows us to write directly in a lot of different languages.
Since this is outputted as a string, you can write for example CSV in this:
name;sku;quantity
{% for item in items %}{{ item.productName }};{{ item.sku }};{{ item.qty }}{% endfor %}
Or use filters to make sure that the formatting of the strings is correct:
name;sku;quantity
{% for item in items %}{{ item.productName|slice(0,20) }};{{ item.sku|slice(0,20)| }};{{ item.qty|format_number({decimal_always_shown:true}, locale: 'en') }}{% endfor %}
Here a small sample of what Gemini could do to create a Shopware order:
{# This Twig template transforms an order from a Magento-like structure to a Shopware-like structure. #}
{# It assumes the original order data is available in a variable named 'data'. #}
{# It also handles deposits as separate line items and converts shipping to a line item. #}
{% set order = data %} {# Alias 'data' to 'order' for readability #}
{
"salesChannelId": "YOUR_SALES_CHANNEL_ID", {# Replace with your actual Sales Channel ID #}
"orderDateTime": "{{ order.created_at|date('Y-m-d H:i:s') }}",
"price": {
"netPrice": {{ (order.subtotal - order.discount_amount)|number_format(2, '.', '') }},
"totalPrice": {{ order.grand_total|number_format(2, '.', '') }},
"calculatedTaxes": [], {# You would typically calculate taxes here based on items and shipping #}
"taxRules": [],
"positionPrice": {{ order.subtotal|number_format(2, '.', '') }},
"taxStatus": "gross" {# Or "net" depending on your Shopware configuration #}
},
"shippingCosts": {
"unitPrice": 0, {# Shipping is moved to line items #}
"totalPrice": 0,
"calculatedTaxes": [],
"taxRules": [],
"referencePrice": null,
"listPrice": null,
"extensions": []
},
"stateId": "YOUR_ORDER_STATE_ID", {# Replace with your actual Order State ID (e.g., for "Open") #}
"billingAddressId": null, {# These will be set by Shopware during creation or you can map existing IDs #}
"shippingAddressId": null, {# Same as above #}
"addresses": [
{
"salutationId": "YOUR_SALUTATION_ID", {# e.g., for "Mr." or "Mrs." #}
"firstName": "{{ order.billing_address.first_name }}",
"lastName": "{{ order.billing_address.last_name }}",
"street": "{{ order.billing_address.street|first }}",
"zipcode": "{{ order.billing_address.postcode }}",
"city": "{{ order.billing_address.city }}",
"countryId": "YOUR_COUNTRY_ID", {# Map country code (e.g., "US") to Shopware's country UUID #}
"countryStateId": null, {# If you have states configured in Shopware #}
"company": "{{ order.billing_address.company|default('') }}",
"phoneNumber": "{{ order.billing_address.telephone|default('') }}",
"email": "{{ order.customer_email }}",
"billingAddress": true,
"shippingAddress": false
},
{% if order.shipping_address.street|first != order.billing_address.street|first or
order.shipping_address.postcode != order.billing_address.postcode or
order.shipping_address.city != order.billing_address.city %}
{
"salutationId": "YOUR_SALUTATION_ID",
"firstName": "{{ order.shipping_address.first_name }}",
"lastName": "{{ order.shipping_address.last_name }}",
"street": "{{ order.shipping_address.street|first }}",
"zipcode": "{{ order.shipping_address.postcode }}",
"city": "{{ order.shipping_address.city }}",
"countryId": "YOUR_COUNTRY_ID",
"countryStateId": null,
"company": "{{ order.shipping_address.company|default('') }}",
"phoneNumber": "{{ order.shipping_address.telephone|default('') }}",
"email": "{{ order.customer_email }}",
"billingAddress": false,
"shippingAddress": true
}
{% endif %}
],
"lineItems": [
{% for item in order.items %}
{
"id": "{{ item.item_id }}", {# Can be a UUID if you generate one, or rely on Shopware #}
"productId": null, {# You'd map this to an existing product ID in Shopware if possible #}
"referencedId": "{{ item.sku }}",
"type": "product",
"quantity": {{ item.qty_ordered }},
"label": "{{ item.name }}",
"unitPrice": {{ item.price|number_format(2, '.', '') }},
"totalPrice": {{ item.row_total|number_format(2, '.', '') }},
"price": {
"netPrice": {{ (item.row_total / (1 + 0.19))|number_format(2, '.', '') }}, {# Example: assuming 19% VAT #}
"totalPrice": {{ item.row_total|number_format(2, '.', '') }},
"calculatedTaxes": [],
"taxRules": [],
"positionPrice": {{ item.price|number_format(2, '.', '') }},
"taxStatus": "gross"
},
"good": true {# Indicates it's a shippable product #}
}{% if loop.last and order.shipping_amount <= 0 and item.deposit <= 0 %}{% else %},{% endif %} {# Add comma unless it's the very last line item #}
{% if item.deposit > 0 %}
{
"id": null, {# Shopware will generate an ID #}
"productId": null,
"referencedId": "DEPOSIT",
"type": "custom", {# Or "product" if you have a "deposit" product #}
"quantity": 1,
"label": "Deposit for {{ item.name }}",
"unitPrice": {{ item.deposit|number_format(2, '.', '') }},
"totalPrice": {{ item.deposit|number_format(2, '.', '') }},
"price": {
"netPrice": {{ (item.deposit / (1 + 0.19))|number_format(2, '.', '') }}, {# Example: assuming 19% VAT #}
"totalPrice": {{ item.deposit|number_format(2, '.', '') }},
"calculatedTaxes": [],
"taxRules": [],
"positionPrice": {{ item.deposit|number_format(2, '.', '') }},
"taxStatus": "gross"
},
"good": false {# Deposits are typically not shippable #}
}{% if loop.last and order.shipping_amount <= 0 %}{% else %},{% endif %}
{% endif %}
{% endfor %}
{# Add shipping as a separate line item if greater than 0 #}
{% if order.shipping_amount > 0 %}
{
"id": null, {# Shopware will generate an ID #}
"productId": null,
"referencedId": "SHIPPING",
"type": "shipping", {# Shopware has a 'shipping' type for line items #}
"quantity": 1,
"label": "Shipping Costs",
"unitPrice": {{ order.shipping_amount|number_format(2, '.', '') }},
"totalPrice": {{ order.shipping_amount|number_format(2, '.', '') }},
"price": {
"netPrice": {{ (order.shipping_amount / (1 + 0.19))|number_format(2, '.', '') }}, {# Example: assuming 19% VAT #}
"totalPrice": {{ order.shipping_amount|number_format(2, '.', '') }},
"calculatedTaxes": [],
"taxRules": [],
"positionPrice": {{ order.shipping_amount|number_format(2, '.', '') }},
"taxStatus": "gross"
},
"good": false {# Shipping is not a physical product #}
}
{% endif %}
],
"deliveries": [
{
"shippingMethodId": "YOUR_SHIPPING_METHOD_ID", {# Map to your Shopware shipping method UUID #}
"shippingOrderAddressId": null, {# Will be set by Shopware #}
"positions": [
{# This section typically lists the line item IDs that are part of this delivery. #}
{# For simplicity here, we're assuming all shippable items are in one delivery. #}
{% for item in order.items %}
{% if item.product_type == 'simple' %} {# Assuming simple products are shippable #}
{ "orderLineItemId": "{{ item.item_id }}" }{% if not loop.last or order.shipping_amount > 0 and item.deposit <= 0 %},{% endif %}
{% endif %}
{% endfor %}
{% if order.shipping_amount > 0 %}
{ "orderLineItemId": "SHIPPING_LINE_ITEM_ID" } {# You might need to generate a UUID for the shipping line item here #}
{% endif %}
]
}
],
"transactions": [
{
"paymentMethodId": "YOUR_PAYMENT_METHOD_ID", {# Map to your Shopware payment method UUID #}
"amount": {
"unitPrice": {{ order.payment.amount_ordered|number_format(2, '.', '') }},
"totalPrice": {{ order.payment.amount_ordered|number_format(2, '.', '') }},
"calculatedTaxes": [],
"taxRules": [],
"positionPrice": {{ order.payment.amount_ordered|number_format(2, '.', '') }},
"taxStatus": "gross"
},
"stateId": "YOUR_TRANSACTION_STATE_ID" {# e.g., for "Open" or "Paid" #}
}
],
"customerId": null, {# If you have an existing customer in Shopware, provide their ID #}
"customer": {
"email": "{{ order.customer_email }}",
"firstName": "{{ order.customer_firstname }}",
"lastName": "{{ order.customer_lastname }}",
"salutationId": "YOUR_SALUTATION_ID",
"guest": true {# Set to false if you are mapping to an existing customer #}
},
"languageId": "YOUR_LANGUAGE_ID", {# e.g., for "en-GB" or "de-DE" #}
"currencyId": "YOUR_CURRENCY_ID", {# Map currency code (e.g., "USD") to Shopware's currency UUID #}
"countryId": "YOUR_COUNTRY_ID",
"taxStatus": "gross" {# Or "net" depending on your Shopware configuration #}
}