Skip to content
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

Update products for a catalog when updated in integrations #250

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
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
8 changes: 4 additions & 4 deletions temba/channels/types/whatsapp/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -583,16 +583,16 @@ def test_get_api_products(self, mock_get):
MockResponse(200, '{"data": ["bar"], "paging": {"next": null} }'),
]

products_data, no_error = WhatsAppType().get_api_products(channel, catalog)
products_data, no_error = WhatsAppType().get_api_products(channel, catalog.facebook_catalog_id)
self.assertEqual(1, HTTPLog.objects.filter(log_type=HTTPLog.WHATSAPP_PRODUCTS_SYNCED).count())
self.assertFalse(no_error)
self.assertEqual([], products_data)

products_data, no_error = WhatsAppType().get_api_products(channel, catalog)
products_data, no_error = WhatsAppType().get_api_products(channel, catalog.facebook_catalog_id)
self.assertFalse(no_error)
self.assertEqual([], products_data)

products_data, no_error = WhatsAppType().get_api_products(channel, catalog)
products_data, no_error = WhatsAppType().get_api_products(channel, catalog.facebook_catalog_id)
self.assertTrue(no_error)
self.assertEqual(["foo", "bar"], products_data)

Expand All @@ -601,6 +601,6 @@ def test_get_api_products(self, mock_get):
params={"access_token": "token123456", "limit": 255},
)

products_data, no_error = WhatsAppType().get_api_products(channel, catalog)
products_data, no_error = WhatsAppType().get_api_products(channel, catalog.facebook_catalog_id)
self.assertTrue(no_error)
self.assertEqual(["foo", "bar"], products_data)
7 changes: 3 additions & 4 deletions temba/channels/types/whatsapp/type.py
Original file line number Diff line number Diff line change
Expand Up @@ -160,22 +160,21 @@ def get_api_catalogs(self, channel):
HTTPLog.create_from_exception(HTTPLog.WHATSAPP_CATALOGS_SYNCED, url, e, start, channel=channel)
return [], False

def get_api_products(self, channel, catalog):
def get_api_products(self, channel, facebook_catalog_id):
if (
CONFIG_FB_BUSINESS_ID not in channel.config or CONFIG_FB_ACCESS_TOKEN not in channel.config
): # pragma: no cover
return [], False

catalog_id = catalog.facebook_catalog_id
if not catalog_id: # pragma: no cover
if not facebook_catalog_id: # pragma: no cover
return [], False

start = timezone.now()
try:
# Retrieve the template domain, fallback to the default for channels
# that have been setup earlier for backwards compatibility
facebook_product_domain = "graph.facebook.com"
url = PRODUCT_LIST_URL % (facebook_product_domain, catalog_id)
url = PRODUCT_LIST_URL % (facebook_product_domain, facebook_catalog_id)
product_data = []
while url:
response = requests.get(
Expand Down
10 changes: 5 additions & 5 deletions temba/channels/types/whatsapp_cloud/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -428,7 +428,7 @@ def test_get_api_catalogs(self, mock_get):

@override_settings(WHATSAPP_ADMIN_SYSTEM_USER_TOKEN="WA_ADMIN_TOKEN")
@patch("requests.get")
def test_get_api_produtcs(self, mock_get):
def test_get_api_products(self, mock_get):
Product.objects.all().delete()
Catalog.objects.all().delete()
Channel.objects.all().delete()
Expand Down Expand Up @@ -462,18 +462,18 @@ def test_get_api_produtcs(self, mock_get):
]

# RequestException check HTTPLog
products_data, no_error = WhatsAppCloudType().get_api_products(channel, catalog)
products_data, no_error = WhatsAppCloudType().get_api_products(channel, catalog.facebook_catalog_id)
self.assertEqual(1, HTTPLog.objects.filter(log_type=HTTPLog.WHATSAPP_PRODUCTS_SYNCED).count())
self.assertFalse(no_error)
self.assertEqual([], products_data)

# should be empty list with an error flag if fail with API
products_data, no_error = WhatsAppCloudType().get_api_products(channel, catalog)
products_data, no_error = WhatsAppCloudType().get_api_products(channel, catalog.facebook_catalog_id)
self.assertFalse(no_error)
self.assertEqual([], products_data)

# success no error and list
products_data, no_error = WhatsAppCloudType().get_api_products(channel, catalog)
products_data, no_error = WhatsAppCloudType().get_api_products(channel, catalog.facebook_catalog_id)
self.assertTrue(no_error)
self.assertEqual(["foo", "bar"], products_data)

Expand All @@ -484,7 +484,7 @@ def test_get_api_produtcs(self, mock_get):
)

# success no error and pagination
products_data, no_error = WhatsAppCloudType().get_api_products(channel, catalog)
products_data, no_error = WhatsAppCloudType().get_api_products(channel, catalog.facebook_catalog_id)
self.assertTrue(no_error)
self.assertEqual(["foo", "bar"], products_data)

Expand Down
7 changes: 3 additions & 4 deletions temba/channels/types/whatsapp_cloud/type.py
Original file line number Diff line number Diff line change
Expand Up @@ -153,18 +153,17 @@ def get_api_catalogs(self, channel):
HTTPLog.create_from_exception(HTTPLog.WHATSAPP_CATALOGS_SYNCED, url, e, start, channel=channel)
return [], False

def get_api_products(self, channel, catalog):
def get_api_products(self, channel, facebook_catalog_id):
if not settings.WHATSAPP_ADMIN_SYSTEM_USER_TOKEN: # pragma: no cover
return [], False

catalog_id = catalog.facebook_catalog_id
if not catalog_id: # pragma: no cover
if not facebook_catalog_id: # pragma: no cover
return [], False

start = timezone.now()
try:
product_data = []
url = f"https://graph.facebook.com/v16.0/{catalog_id}/products"
url = f"https://graph.facebook.com/v16.0/{facebook_catalog_id}/products"

headers = {"Authorization": f"Bearer {settings.WHATSAPP_ADMIN_SYSTEM_USER_TOKEN}"}
while url:
Expand Down
29 changes: 26 additions & 3 deletions temba/utils/whatsapp/tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -194,18 +194,41 @@
update_api_version(channel)


def update_channel_catalogs_status(channel, facebook_catalog_id, is_active):
def update_channel_catalogs_status(channel, facebook_catalog_id, is_active, catalog_name):
channel.config["catalog_id"] = facebook_catalog_id if is_active else None
channel.save(update_fields=["config"])

filter_catalog = Catalog.objects.filter(channel=channel, facebook_catalog_id=facebook_catalog_id)
Catalog.objects.filter(channel=channel, is_active=True).update(is_active=False)

if is_active:
Catalog.objects.filter(channel=channel, facebook_catalog_id=facebook_catalog_id).update(is_active=True)
if filter_catalog:
filter_catalog.update(is_active=True)
else:
Catalog.objects.create(

Check warning on line 208 in temba/utils/whatsapp/tasks.py

View check run for this annotation

Codecov / codecov/patch

temba/utils/whatsapp/tasks.py#L208

Added line #L208 was not covered by tests
facebook_catalog_id=facebook_catalog_id,
name=catalog_name,
channel=channel,
org=channel.org,
is_active=is_active,
)

sync_products_catalogs(channel, facebook_catalog_id)

return True


def sync_products_catalogs(channel, facebook_catalog_id):
try:
products_data, valid = channel.get_type().get_api_products(channel, facebook_catalog_id)
catalog = Catalog.objects.filter(channel=channel, facebook_catalog_id=facebook_catalog_id).first()

update_local_products(catalog, products_data, channel)

except Exception as e:
logger.error(f"Error refreshing WhatsApp catalog and products: {str(e)}", exc_info=True)

Check warning on line 229 in temba/utils/whatsapp/tasks.py

View check run for this annotation

Codecov / codecov/patch

temba/utils/whatsapp/tasks.py#L228-L229

Added lines #L228 - L229 were not covered by tests


def set_false_is_active_catalog(channel, catalogs_data):
channel.config["catalog_id"] = ""
channel.save(update_fields=["config"])
Expand Down Expand Up @@ -327,7 +350,7 @@
for channel in Channel.objects.filter(is_active=True, channel_type="WAC"):
for catalog in Catalog.objects.filter(channel=channel, is_active=True):
# Fetch products for each catalog
products_data, valid = channel.get_type().get_api_products(channel, catalog)
products_data, valid = channel.get_type().get_api_products(channel, catalog.facebook_catalog_id)
if not valid:
continue

Expand Down
1 change: 1 addition & 0 deletions temba/wpp_products/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,6 @@


class UpdateCatalogSerializer(serializers.Serializer):
name = serializers.CharField(required=True)
facebook_catalog_id = serializers.CharField(required=True)
is_active = serializers.BooleanField()
2 changes: 1 addition & 1 deletion temba/wpp_products/tests/test_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ def test_update_active_catalog(self):
url = reverse("catalog-update-status-catalog", args=[self.new_channel.uuid])
self.client.force_login(self.user)

data = {"facebook_catalog_id": "112233445", "is_active": True}
data = {"facebook_catalog_id": "112233445", "is_active": True, "name": "catalog_name"}

serializer = UpdateCatalogSerializer(data=data)
self.assertTrue(serializer.is_valid(), "Serializer is not valid.")
Expand Down
5 changes: 4 additions & 1 deletion temba/wpp_products/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,10 @@ def update_status_catalog(self, request, pk, *args, **kwargs):
channel = get_object_or_404(Channel, uuid=pk, is_active=True)

update_channel_catalogs_status(
channel, validated_data.get("facebook_catalog_id"), validated_data.get("is_active")
channel,
validated_data.get("facebook_catalog_id"),
validated_data.get("is_active"),
validated_data.get("name"),
)
return Response(status=status.HTTP_200_OK)

Expand Down
Loading