<commit_before>from django.dispatch import receiver

from oscar.core.loading import import_module
import_module('analytics.models', ['UserRecord', 'ProductRecord', 'UserProductView'], locals())
import_module('catalogue.signals', ['product_viewed', 'product_search'], locals())
import_module('basket.signals', ['basket_addition'], locals())
import_module('order.signals', ['order_placed'], locals())

# Helpers

def _record_product_view(product):
    record,_ = ProductRecord.objects.get_or_create(product=product)
    record.num_views += 1
    record.save()
    
def _record_user_product_view(user, product):
    if user.is_authenticated():
        # Update user record
        record,_ = UserRecord.objects.get_or_create(user=user)
        record.num_product_views += 1
        record.save()
        
        # Add user product view record
        UserProductView.objects.create(product=product, user=user)
        
def _record_basket_addition(product):
    record,_ = ProductRecord.objects.get_or_create(product=product)
    record.num_basket_additions += 1
    record.save()
    
def _record_user_basket_addition(user, product):
    if user.is_authenticated():
        record,_ = UserRecord.objects.get_or_create(user=user)
        record.num_basket_additions += 1
        record.save()

def _record_products_in_order(order):
    for line in order.lines.all():
        record,_ = ProductRecord.objects.get_or_create(product=line.product)
        record.num_purchases += line.quantity
        record.save()

def _record_user_order(user, order):
    if user.is_authenticated():
        record,_ = UserRecord.objects.get_or_create(user=user)
        record.num_orders += 1
        record.num_order_lines += order.num_lines
        record.num_order_items += order.num_items
        record.total_spent += order.total_incl_tax
        record.date_last_order = order.date_placed
        record.save()
<commit_msg>Catch and log IntegrityErrors in analytics to stop get_or_create breaking sites.<commit_after>from django.dispatch import receiver
from django.db import IntegrityError
import logging

from oscar.core.loading import import_module
import_module('analytics.models', ['UserRecord', 'ProductRecord', 'UserProductView'], locals())
import_module('catalogue.signals', ['product_viewed', 'product_search'], locals())
import_module('basket.signals', ['basket_addition'], locals())
import_module('order.signals', ['order_placed'], locals())

# Helpers

logger = logging.getLogger('oscar.analytics')

def _record_product_view(product):
    try:
        record,_ = ProductRecord.objects.get_or_create(product=product)
        record.num_views += 1
        record.save()
    except IntegrityError:
        # get_or_create sometimes fails due to MySQL's weird transactions, fail silently
        logger.error("IntegrityError on ProductRecord.objects.get_or_create(product=product)")
    
def _record_user_product_view(user, product):
    if user.is_authenticated():
        # Update user record
        try:
            record,_ = UserRecord.objects.get_or_create(user=user)
            record.num_product_views += 1
            record.save()
        except IntegrityError:
            logger.error("IntegrityError on UserRecord.objects.get_or_create(user=user)")
        
        # Add user product view record
        UserProductView.objects.create(product=product, user=user)

def _record_basket_addition(product):
    try:
        record,_ = ProductRecord.objects.get_or_create(product=product)
        record.num_basket_additions += 1
        record.save()
    except IntegrityError:
        logger.error("IntegrityError on ProductRecord.objects.get_or_create(product=product)")
    
def _record_user_basket_addition(user, product):
    if user.is_authenticated():
        try:
            record,_ = UserRecord.objects.get_or_create(user=user)
            record.num_basket_additions += 1
            record.save()
        except IntegrityError:
            logger.error("IntegrityError on UserRecord.objects.get_or_create(user=user)")

def _record_products_in_order(order):
    for line in order.lines.all():
        try:
            record,_ = ProductRecord.objects.get_or_create(product=line.product)
            record.num_purchases += line.quantity
            record.save()
        except IntegrityError:
            logger.error("IntegrityError on ProductRecord.objects.get_or_create(product=product)")

def _record_user_order(user, order):
    if user.is_authenticated():
        try:
            record,_ = UserRecord.objects.get_or_create(user=user)
            record.num_orders += 1
            record.num_order_lines += order.num_lines
            record.num_order_items += order.num_items
            record.total_spent += order.total_incl_tax
            record.date_last_order = order.date_placed
            record.save()
        except IntegrityError:
            logger.error("IntegrityError on UserRecord.objects.get_or_create(user=user)")

{'fraction_non_alphanumeric': 0.10161290322580645, 'fraction_numerical': 0.0020161290322580645, 'mean_word_length': 3.51, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3377510', 'n_tokens_mistral': 1453, 'n_tokens_neox': 1424, 'n_words': 258}