Commit 3a9ffe5e by Clinton Blackburn

Merge pull request #129 from edx/product-history

Tracking Product Change History
parents 9b305314 c5ef93e3
from oscar.apps.catalogue.admin import * # pylint: disable=unused-import,wildcard-import,unused-wildcard-import from oscar.apps.catalogue.admin import * # pylint: disable=unused-import,wildcard-import,unused-wildcard-import
from simple_history.admin import SimpleHistoryAdmin
class ProductAdminExtended(ProductAdmin): class ProductAdminExtended(SimpleHistoryAdmin):
list_display = ('get_title', 'upc', 'get_product_class', 'structure', list_display = ('get_title', 'upc', 'get_product_class', 'structure', 'attribute_summary', 'date_created', 'course')
'attribute_summary', 'date_created', 'course') prepopulated_fields = {"slug": ("title",)}
inlines = [AttributeInline, CategoryInline, ProductRecommendationInline]
admin.site.unregister(Product) admin.site.unregister(Product)
admin.site.register(Product, ProductAdminExtended) admin.site.register(Product, ProductAdminExtended)
class ProductAttributeValueAdminExtended(SimpleHistoryAdmin):
list_display = ('product', 'attribute', 'value')
admin.site.unregister(ProductAttributeValue)
admin.site.register(ProductAttributeValue, ProductAttributeValueAdminExtended)
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
import oscar.models.fields
import django.db.models.deletion
from django.conf import settings
class Migration(migrations.Migration):
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('contenttypes', '0001_initial'),
('courses', '0001_initial'),
('catalogue', '0003_product_course'),
]
operations = [
migrations.CreateModel(
name='HistoricalProduct',
fields=[
('id', models.IntegerField(verbose_name='ID', db_index=True, auto_created=True, blank=True)),
('structure', models.CharField(default=b'standalone', max_length=10, verbose_name='Product structure', choices=[(b'standalone', 'Stand-alone product'), (b'parent', 'Parent product'), (b'child', 'Child product')])),
('upc', oscar.models.fields.NullCharField(max_length=64, help_text='Universal Product Code (UPC) is an identifier for a product which is not specific to a particular supplier. Eg an ISBN for a book.', verbose_name='UPC', db_index=True)),
('title', models.CharField(max_length=255, verbose_name='Title', blank=True)),
('slug', models.SlugField(max_length=255, verbose_name='Slug')),
('description', models.TextField(verbose_name='Description', blank=True)),
('rating', models.FloatField(verbose_name='Rating', null=True, editable=False)),
('date_created', models.DateTimeField(verbose_name='Date created', editable=False, blank=True)),
('date_updated', models.DateTimeField(verbose_name='Date updated', db_index=True, editable=False, blank=True)),
('is_discountable', models.BooleanField(default=True, help_text='This flag indicates if this product can be used in an offer or not', verbose_name='Is discountable?')),
('history_id', models.AutoField(serialize=False, primary_key=True)),
('history_date', models.DateTimeField()),
('history_type', models.CharField(max_length=1, choices=[('+', 'Created'), ('~', 'Changed'), ('-', 'Deleted')])),
('changed_by', models.ForeignKey(related_name='+', on_delete=django.db.models.deletion.DO_NOTHING, db_constraint=False, blank=True, to=settings.AUTH_USER_MODEL, null=True)),
('course', models.ForeignKey(related_name='+', on_delete=django.db.models.deletion.DO_NOTHING, db_constraint=False, blank=True, to='courses.Course', null=True)),
('history_user', models.ForeignKey(related_name='+', on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL, null=True)),
('parent', models.ForeignKey(related_name='+', on_delete=django.db.models.deletion.DO_NOTHING, db_constraint=False, blank=True, to='catalogue.Product', null=True)),
('product_class', models.ForeignKey(related_name='+', on_delete=django.db.models.deletion.DO_NOTHING, db_constraint=False, blank=True, to='catalogue.ProductClass', null=True)),
],
options={
'ordering': ('-history_date', '-history_id'),
'get_latest_by': 'history_date',
'verbose_name': 'historical Product',
},
bases=(models.Model,),
),
migrations.CreateModel(
name='HistoricalProductAttributeValue',
fields=[
('id', models.IntegerField(verbose_name='ID', db_index=True, auto_created=True, blank=True)),
('value_text', models.TextField(null=True, verbose_name='Text', blank=True)),
('value_integer', models.IntegerField(null=True, verbose_name='Integer', blank=True)),
('value_boolean', models.NullBooleanField(verbose_name='Boolean')),
('value_float', models.FloatField(null=True, verbose_name='Float', blank=True)),
('value_richtext', models.TextField(null=True, verbose_name='Richtext', blank=True)),
('value_date', models.DateField(null=True, verbose_name='Date', blank=True)),
('value_file', models.TextField(max_length=255, null=True, blank=True)),
('value_image', models.TextField(max_length=255, null=True, blank=True)),
('entity_object_id', models.PositiveIntegerField(null=True, editable=False, blank=True)),
('history_id', models.AutoField(serialize=False, primary_key=True)),
('history_date', models.DateTimeField()),
('history_type', models.CharField(max_length=1, choices=[('+', 'Created'), ('~', 'Changed'), ('-', 'Deleted')])),
('attribute', models.ForeignKey(related_name='+', on_delete=django.db.models.deletion.DO_NOTHING, db_constraint=False, blank=True, to='catalogue.ProductAttribute', null=True)),
('changed_by', models.ForeignKey(related_name='+', on_delete=django.db.models.deletion.DO_NOTHING, db_constraint=False, blank=True, to=settings.AUTH_USER_MODEL, null=True)),
('entity_content_type', models.ForeignKey(related_name='+', on_delete=django.db.models.deletion.DO_NOTHING, db_constraint=False, blank=True, to='contenttypes.ContentType', null=True)),
('history_user', models.ForeignKey(related_name='+', on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL, null=True)),
('product', models.ForeignKey(related_name='+', on_delete=django.db.models.deletion.DO_NOTHING, db_constraint=False, blank=True, to='catalogue.Product', null=True)),
('value_option', models.ForeignKey(related_name='+', on_delete=django.db.models.deletion.DO_NOTHING, db_constraint=False, blank=True, to='catalogue.AttributeOption', null=True)),
],
options={
'ordering': ('-history_date', '-history_id'),
'get_latest_by': 'history_date',
'verbose_name': 'historical Product attribute value',
},
bases=(models.Model,),
),
migrations.AddField(
model_name='product',
name='changed_by',
field=models.ForeignKey(blank=True, to=settings.AUTH_USER_MODEL, null=True),
preserve_default=True,
),
migrations.AddField(
model_name='productattributevalue',
name='changed_by',
field=models.ForeignKey(blank=True, to=settings.AUTH_USER_MODEL, null=True),
preserve_default=True,
),
]
# noinspection PyUnresolvedReferences # noinspection PyUnresolvedReferences
from django.db import models from django.db import models
from oscar.apps.catalogue.abstract_models import AbstractProduct from oscar.apps.catalogue.abstract_models import AbstractProduct, AbstractProductAttributeValue
from simple_history.models import HistoricalRecords
class Product(AbstractProduct): class Product(AbstractProduct):
course = models.ForeignKey('courses.Course', null=True, blank=True, related_name='products') course = models.ForeignKey('courses.Course', null=True, blank=True, related_name='products')
changed_by = models.ForeignKey('user.User', null=True, blank=True)
history = HistoricalRecords()
@property
def _history_user(self): # pragma: no cover
return self.changed_by
@_history_user.setter
def _history_user(self, value): # pragma: no cover
self.changed_by = value
class ProductAttributeValue(AbstractProductAttributeValue):
changed_by = models.ForeignKey('user.User', null=True, blank=True)
history = HistoricalRecords()
@property
def _history_user(self): # pragma: no cover
return self.changed_by
@_history_user.setter
def _history_user(self, value): # pragma: no cover
self.changed_by = value
# noinspection PyUnresolvedReferences # noinspection PyUnresolvedReferences
from oscar.apps.catalogue.models import * # noqa pylint: disable=wildcard-import,unused-wildcard-import from oscar.apps.catalogue.models import * # noqa pylint: disable=wildcard-import,unused-wildcard-import
import oscar.apps.partner.admin # pragma: no cover pylint: disable=unused-import from oscar.apps.partner.admin import * # noqa pylint: disable=wildcard-import,unused-wildcard-import
from simple_history.admin import SimpleHistoryAdmin
class StockRecordAdminExtended(SimpleHistoryAdmin):
list_display = ('product', 'partner', 'partner_sku', 'price_excl_tax', 'cost_price', 'num_in_stock')
list_filter = ('partner',)
admin.site.unregister(StockRecord)
admin.site.register(StockRecord, StockRecordAdminExtended)
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
import oscar.core.utils
import django.db.models.deletion
from django.conf import settings
class Migration(migrations.Migration):
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('catalogue', '0004_auto_20150609_0129'),
('partner', '0003_auto_20150223_1130'),
]
operations = [
migrations.CreateModel(
name='HistoricalStockRecord',
fields=[
('id', models.IntegerField(verbose_name='ID', db_index=True, auto_created=True, blank=True)),
('partner_sku', models.CharField(max_length=128, verbose_name='Partner SKU')),
('price_currency', models.CharField(default=oscar.core.utils.get_default_currency, max_length=12, verbose_name='Currency')),
('price_excl_tax', models.DecimalField(null=True, verbose_name='Price (excl. tax)', max_digits=12, decimal_places=2, blank=True)),
('price_retail', models.DecimalField(null=True, verbose_name='Price (retail)', max_digits=12, decimal_places=2, blank=True)),
('cost_price', models.DecimalField(null=True, verbose_name='Cost Price', max_digits=12, decimal_places=2, blank=True)),
('num_in_stock', models.PositiveIntegerField(null=True, verbose_name='Number in stock', blank=True)),
('num_allocated', models.IntegerField(null=True, verbose_name='Number allocated', blank=True)),
('low_stock_threshold', models.PositiveIntegerField(null=True, verbose_name='Low Stock Threshold', blank=True)),
('date_created', models.DateTimeField(verbose_name='Date created', editable=False, blank=True)),
('date_updated', models.DateTimeField(verbose_name='Date updated', db_index=True, editable=False, blank=True)),
('history_id', models.AutoField(serialize=False, primary_key=True)),
('history_date', models.DateTimeField()),
('history_type', models.CharField(max_length=1, choices=[('+', 'Created'), ('~', 'Changed'), ('-', 'Deleted')])),
('changed_by', models.ForeignKey(related_name='+', on_delete=django.db.models.deletion.DO_NOTHING, db_constraint=False, blank=True, to=settings.AUTH_USER_MODEL, null=True)),
('history_user', models.ForeignKey(related_name='+', on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL, null=True)),
('partner', models.ForeignKey(related_name='+', on_delete=django.db.models.deletion.DO_NOTHING, db_constraint=False, blank=True, to='partner.Partner', null=True)),
('product', models.ForeignKey(related_name='+', on_delete=django.db.models.deletion.DO_NOTHING, db_constraint=False, blank=True, to='catalogue.Product', null=True)),
],
options={
'ordering': ('-history_date', '-history_id'),
'get_latest_by': 'history_date',
'verbose_name': 'historical Stock record',
},
bases=(models.Model,),
),
migrations.AddField(
model_name='stockrecord',
name='changed_by',
field=models.ForeignKey(blank=True, to=settings.AUTH_USER_MODEL, null=True),
preserve_default=True,
),
]
from oscar.apps.partner.models import * # pragma: no cover pylint: disable=wildcard-import from django.db import models
from oscar.apps.partner.abstract_models import AbstractStockRecord
from simple_history.models import HistoricalRecords
class StockRecord(AbstractStockRecord):
changed_by = models.ForeignKey('user.User', null=True, blank=True)
history = HistoricalRecords()
@property
def _history_user(self): # pragma: no cover
return self.changed_by
@_history_user.setter
def _history_user(self, value): # pragma: no cover
self.changed_by = value
# noinspection PyUnresolvedReferences
from oscar.apps.partner.models import * # noqa pylint: disable=wildcard-import,unused-wildcard-import
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment