Repository: saleor/saleor

Issue:
data_feeds - google_merchant doesn't fetch product's taxes
`saleor/data_feeds/google_merchant.py`

```
def item_tax(item, discounts):
    """Return item tax.
    For some countries you need to set tax info
    Read more:
    https://support.google.com/merchants/answer/6324454
    """
    price = item.get_price(discounts=discounts)
    return "US::%s:y" % price.tax
```
Current approach requires taxes passed explicitly to product. In this case `price.tax` will be always zero.
After we merge logic that extracts taxes outside product, we should fix this.


Discussion:

Resolving patch:
diff --git a/saleor/data_feeds/google_merchant.py b/saleor/data_feeds/google_merchant.py
--- a/saleor/data_feeds/google_merchant.py
+++ b/saleor/data_feeds/google_merchant.py
@@ -8,10 +8,12 @@
 from django.core.files.storage import default_storage
 from django.utils import timezone
 from django.utils.encoding import smart_text
+from django_countries.fields import Country
 
-from ..core.taxes import zero_money
+from ..core.taxes import charge_taxes_on_shipping
 from ..discount import DiscountInfo
 from ..discount.utils import fetch_discounts
+from ..plugins.manager import get_plugins_manager
 from ..product.models import Attribute, AttributeValue, Category, ProductVariant
 from ..warehouse.availability import is_variant_in_stock
 
@@ -116,15 +118,25 @@ def item_brand(item: ProductVariant, attributes_dict, attribute_values_dict):
     return brand
 
 
-def item_tax(item: ProductVariant, discounts: Iterable[DiscountInfo]):
+def item_tax(
+    item: ProductVariant,
+    discounts: Iterable[DiscountInfo],
+    is_charge_taxes_on_shipping: bool,
+):
     """Return item tax.
 
     For some countries you need to set tax info
     Read more:
     https://support.google.com/merchants/answer/6324454
     """
-    # FIXME https://github.com/mirumee/saleor/issues/4311
-    return "US::%s:y" % zero_money()
+    country = Country(settings.DEFAULT_COUNTRY)
+    tax_rate = get_plugins_manager().get_tax_rate_percentage_value(
+        item.product.product_type, country
+    )
+    if tax_rate:
+        tax_ship = "yes" if is_charge_taxes_on_shipping else "no"
+        return "%s::%s:%s" % (country.code, tax_rate, tax_ship)
+    return None
 
 
 def item_group_id(item: ProductVariant):
@@ -182,6 +194,7 @@ def item_attributes(
     discounts: Iterable[DiscountInfo],
     attributes_dict,
     attribute_values_dict,
+    is_charge_taxes_on_shipping: bool,
 ):
     product_data = {
         "id": item_id(item),
@@ -204,7 +217,7 @@ def item_attributes(
     if sale_price != price:
         product_data["sale_price"] = sale_price
 
-    tax = item_tax(item, discounts)
+    tax = item_tax(item, discounts, is_charge_taxes_on_shipping)
     if tax:
         product_data["tax"] = tax
 
@@ -217,6 +230,7 @@ def item_attributes(
 
 def write_feed(file_obj):
     """Write feed contents info provided file object."""
+    is_charge_taxes_on_shipping = charge_taxes_on_shipping()
     writer = csv.DictWriter(file_obj, ATTRIBUTES, dialect=csv.excel_tab)
     writer.writeheader()
     categories = Category.objects.all()
@@ -236,6 +250,7 @@ def write_feed(file_obj):
             discounts,
             attributes_dict,
             attribute_values_dict,
+            is_charge_taxes_on_shipping,
         )
         writer.writerow(item_data)
 


Test patch:
diff --git a/saleor/data_feeds/tests/test_data_feeds.py b/saleor/data_feeds/tests/test_data_feeds.py
--- a/saleor/data_feeds/tests/test_data_feeds.py
+++ b/saleor/data_feeds/tests/test_data_feeds.py
@@ -3,23 +3,27 @@
 from unittest.mock import Mock
 
 from django.utils.encoding import smart_text
+from django_prices_vatlayer.models import VAT
 
+from ...core.taxes import charge_taxes_on_shipping
 from ...product.models import AttributeValue, Category
 from ..google_merchant import (
     get_feed_items,
     item_attributes,
     item_availability,
     item_google_product_category,
+    item_tax,
     write_feed,
 )
 
 
-def test_saleor_feed_items(product, site_settings):
+def test_saleor_feed_items(product, discount_info, site_settings):
+    is_charge_taxes_on_shipping = charge_taxes_on_shipping()
     valid_variant = product.variants.first()
     items = get_feed_items()
     assert len(items) == 1
     categories = Category.objects.all()
-    discounts = []
+    discounts = [discount_info]
     category_paths = {}
     attributes_dict = {}
     current_site = site_settings.site
@@ -34,9 +38,13 @@ def test_saleor_feed_items(product, site_settings):
         discounts,
         attributes_dict,
         attribute_values_dict,
+        is_charge_taxes_on_shipping,
     )
     assert attributes.get("mpn") == valid_variant.sku
     assert attributes.get("availability") == "in stock"
+    assert attributes.get("tax") is None
+    assert attributes.get("price") == "10.00 USD"
+    assert attributes.get("sale_price") == "5.00 USD"
 
 
 def test_saleor_get_feed_items_having_no_stock_info(variant, site_settings):
@@ -55,6 +63,14 @@ def test_category_formatter(db):
     assert item_google_product_category(sub_category_item, {}) == "Main > Sub"
 
 
+def test_tax_formatter(variant, vatlayer, tax_rates):
+    discounts = []
+    VAT.objects.create(country_code="US", data=tax_rates)
+    is_charge_taxes_on_shipping = charge_taxes_on_shipping()
+    item_tax_value = item_tax(variant, discounts, is_charge_taxes_on_shipping)
+    assert item_tax_value == "US::23:yes"
+
+
 def test_write_feed(product, monkeypatch):
     buffer = StringIO()
     write_feed(buffer)