From d8b8a7852bd78e098e8a158bf22ae2c008ddd659 Mon Sep 17 00:00:00 2001 From: Lance Edgar Date: Mon, 19 Nov 2012 09:42:01 -0800 Subject: [PATCH] bunch more stuff! (savepoint) --- rattail/django/rattail/admin.py | 178 +++++++++- .../django/rattail/migrations/0001_initial.py | 269 ++++++++++++++ rattail/django/rattail/models/__init__.py | 2 + rattail/django/rattail/models/auth.py | 106 ++++++ rattail/django/rattail/models/contact.py | 67 +++- rattail/django/rattail/models/rattail.py | 333 +++++++++++++++++- 6 files changed, 941 insertions(+), 14 deletions(-) create mode 100644 rattail/django/rattail/models/auth.py diff --git a/rattail/django/rattail/admin.py b/rattail/django/rattail/admin.py index 51a345e..621db96 100644 --- a/rattail/django/rattail/admin.py +++ b/rattail/django/rattail/admin.py @@ -27,8 +27,10 @@ """ from django.contrib import admin +from django.contrib.admin.widgets import AdminTextInputWidget from rattail.django.rattail.models import * +from rattail.django.rattail.models.rattail import GPCField class ModelAdmin(admin.ModelAdmin): @@ -36,27 +38,74 @@ class ModelAdmin(admin.ModelAdmin): Base admin manager for all Rattail models. """ - def get_form(self, request, obj=None, **kwargs): - kwargs.setdefault('exclude', ('uuid',)) - form = super(ModelAdmin, self).get_form(request, obj, **kwargs) - return form + exclude = ('uuid',) -class StoreContactInfoInline(admin.TabularInline): +class ContactInfoInline(admin.TabularInline): + """ + Base inline manager for all contact info models. + """ + exclude = ('uuid', 'parent_type') extra = 0 -class StorePhoneNumberInline(StoreContactInfoInline): - model = StorePhoneNumber - verbose_name_plural = "Phone Numbers" -class StoreEmailAddressInline(StoreContactInfoInline): +class PersonPhoneNumberInline(ContactInfoInline): + model = PersonPhoneNumber + +class PersonEmailAddressInline(ContactInfoInline): + model = PersonEmailAddress + +class PersonAdmin(ModelAdmin): + inlines = [PersonPhoneNumberInline, PersonEmailAddressInline] + + def get_formsets(self, request, obj=None): + for inline in self.get_inline_instances(request): + if isinstance(inline, ContactInfoInline) and obj is None: + continue + yield inline.get_formset(request, obj) + +admin.site.register(Person, PersonAdmin) + + +admin.site.register(Role, ModelAdmin) + + +class UserRoleInline(admin.TabularInline): + model = UserRole + verbose_name = "Role" + verbose_name_plural = "Roles" + exclude = ('uuid',) + extra = 0 + +class UserAdmin(ModelAdmin): + exclude = ('uuid', 'password', 'salt') + inlines = [UserRoleInline] + + def get_formsets(self, request, obj=None): + for inline in self.get_inline_instances(request): + if isinstance(inline, UserRoleInline) and obj is None: + continue + yield inline.get_formset(request, obj) + +admin.site.register(User, UserAdmin) + + +class StorePhoneNumberInline(ContactInfoInline): + model = StorePhoneNumber + +class StoreEmailAddressInline(ContactInfoInline): model = StoreEmailAddress - verbose_name_plural = "Email Addresses" class StoreAdmin(ModelAdmin): inlines = [StorePhoneNumberInline, StoreEmailAddressInline] + def get_formsets(self, request, obj=None): + for inline in self.get_inline_instances(request): + if isinstance(inline, ContactInfoInline) and obj is None: + continue + yield inline.get_formset(request, obj) + admin.site.register(Store, StoreAdmin) @@ -72,13 +121,120 @@ admin.site.register(Category, ModelAdmin) admin.site.register(Brand, ModelAdmin) +class VendorPhoneNumberInline(ContactInfoInline): + model = VendorPhoneNumber + +class VendorEmailAddressInline(ContactInfoInline): + model = VendorEmailAddress + +class VendorContactInline(admin.TabularInline): + model = VendorContact + verbose_name = "Contact" + verbose_name_plural = "Contacts" + exclude = ('uuid',) + extra = 0 + +class VendorAdmin(ModelAdmin): + inlines = [VendorPhoneNumberInline, VendorEmailAddressInline, + VendorContactInline] + + def get_formsets(self, request, obj=None): + for inline in self.get_inline_instances(request): + if isinstance(inline, ContactInfoInline) and obj is None: + continue + if isinstance(inline, VendorContactInline) and obj is None: + continue + yield inline.get_formset(request, obj) + +admin.site.register(Vendor, VendorAdmin) + + class ProductPriceInline(admin.TabularInline): model = ProductPrice + verbose_name = "Price" verbose_name_plural = "Prices" exclude = ('uuid',) extra = 0 +class ProductCostInline(admin.TabularInline): + model = ProductCost + verbose_name = "Cost" + verbose_name_plural = "Costs" + exclude = ('uuid',) + extra = 0 + class ProductAdmin(ModelAdmin): - inlines = [ProductPriceInline] + inlines = [ProductPriceInline, ProductCostInline] + + formfield_overrides = { + GPCField: { + 'widget': AdminTextInputWidget, + }, + } + + def get_form(self, request, obj=None, **kwargs): + if obj is None: + kwargs['exclude'] = ('uuid', 'regular_price', 'current_price') + return super(ProductAdmin, self).get_form(request, obj, **kwargs) + + def get_formsets(self, request, obj=None): + for inline in self.get_inline_instances(request): + if isinstance(inline, ProductPriceInline) and obj is None: + continue + if isinstance(inline, ProductCostInline) and obj is None: + continue + yield inline.get_formset(request, obj) admin.site.register(Product, ProductAdmin) + + +class EmployeePhoneNumberInline(ContactInfoInline): + model = EmployeePhoneNumber + +class EmployeeEmailAddressInline(ContactInfoInline): + model = EmployeeEmailAddress + +class EmployeeAdmin(ModelAdmin): + inlines = [EmployeePhoneNumberInline, EmployeeEmailAddressInline] + + def get_formsets(self, request, obj=None): + for inline in self.get_inline_instances(request): + if isinstance(inline, ContactInfoInline) and obj is None: + continue + yield inline.get_formset(request, obj) + +admin.site.register(Employee, EmployeeAdmin) + + +admin.site.register(CustomerGroup, ModelAdmin) + + +class CustomerPhoneNumberInline(ContactInfoInline): + model = CustomerPhoneNumber + +class CustomerEmailAddressInline(ContactInfoInline): + model = CustomerEmailAddress + +class CustomerGroupAssignmentInline(admin.TabularInline): + model = CustomerGroupAssignment + verbose_name = "Group Assignment" + verbose_name_plural = "Group Assignments" + exclude = ('uuid',) + extra = 0 + +class CustomerAdmin(ModelAdmin): + inlines = [CustomerPhoneNumberInline, CustomerEmailAddressInline, + CustomerGroupAssignmentInline] + + def get_formsets(self, request, obj=None): + for inline in self.get_inline_instances(request): + if isinstance(inline, ContactInfoInline) and obj is None: + continue + if isinstance(inline, CustomerGroupAssignmentInline) and obj is None: + continue + yield inline.get_formset(request, obj) + +admin.site.register(Customer, CustomerAdmin) + + +admin.site.register(LabelProfile, ModelAdmin) diff --git a/rattail/django/rattail/migrations/0001_initial.py b/rattail/django/rattail/migrations/0001_initial.py index e1586a6..f04bdd0 100644 --- a/rattail/django/rattail/migrations/0001_initial.py +++ b/rattail/django/rattail/migrations/0001_initial.py @@ -8,6 +8,15 @@ from django.db import models class Migration(SchemaMigration): def forwards(self, orm): + # Adding model 'Person' + db.create_table('rattail_people', ( + ('uuid', self.gf('rattail.django.rattail.models.core.UUIDField')(max_length=32, primary_key=True)), + ('first_name', self.gf('django.db.models.fields.CharField')(max_length=50, null=True, blank=True)), + ('last_name', self.gf('django.db.models.fields.CharField')(max_length=50, null=True, blank=True)), + ('display_name', self.gf('django.db.models.fields.CharField')(max_length=100, null=True, blank=True)), + )) + db.send_create_signal('rattail', ['Person']) + # Adding model 'PhoneNumber' db.create_table('rattail_phone_numbers', ( ('uuid', self.gf('rattail.django.rattail.models.core.UUIDField')(max_length=32, primary_key=True)), @@ -30,6 +39,31 @@ class Migration(SchemaMigration): )) db.send_create_signal('rattail', ['EmailAddress']) + # Adding model 'Role' + db.create_table('rattail_roles', ( + ('uuid', self.gf('rattail.django.rattail.models.core.UUIDField')(max_length=32, primary_key=True)), + ('name', self.gf('django.db.models.fields.CharField')(unique=True, max_length=25)), + )) + db.send_create_signal('rattail', ['Role']) + + # Adding model 'User' + db.create_table('rattail_users', ( + ('uuid', self.gf('rattail.django.rattail.models.core.UUIDField')(max_length=32, primary_key=True)), + ('username', self.gf('django.db.models.fields.CharField')(unique=True, max_length=25)), + ('password', self.gf('django.db.models.fields.CharField')(max_length=60, null=True, blank=True)), + ('salt', self.gf('django.db.models.fields.CharField')(max_length=29, null=True, blank=True)), + ('person', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['rattail.Person'], null=True, db_column='person_uuid', blank=True)), + )) + db.send_create_signal('rattail', ['User']) + + # Adding model 'UserRole' + db.create_table('rattail_users_roles', ( + ('uuid', self.gf('rattail.django.rattail.models.core.UUIDField')(max_length=32, primary_key=True)), + ('user', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['rattail.User'], db_column='user_uuid')), + ('role', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['rattail.Role'], db_column='role_uuid')), + )) + db.send_create_signal('rattail', ['UserRole']) + # Adding model 'Store' db.create_table('rattail_stores', ( ('uuid', self.gf('rattail.django.rattail.models.core.UUIDField')(max_length=32, primary_key=True)), @@ -71,6 +105,24 @@ class Migration(SchemaMigration): )) db.send_create_signal('rattail', ['Brand']) + # Adding model 'Vendor' + db.create_table('rattail_vendors', ( + ('uuid', self.gf('rattail.django.rattail.models.core.UUIDField')(max_length=32, primary_key=True)), + ('id', self.gf('django.db.models.fields.CharField')(max_length=15, null=True, blank=True)), + ('name', self.gf('django.db.models.fields.CharField')(max_length=40, null=True, blank=True)), + ('special_discount', self.gf('django.db.models.fields.DecimalField')(null=True, max_digits=5, decimal_places=3, blank=True)), + )) + db.send_create_signal('rattail', ['Vendor']) + + # Adding model 'VendorContact' + db.create_table('rattail_vendor_contacts', ( + ('uuid', self.gf('rattail.django.rattail.models.core.UUIDField')(max_length=32, primary_key=True)), + ('vendor', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['rattail.Vendor'], db_column='vendor_uuid')), + ('person', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['rattail.Person'], db_column='person_uuid')), + ('preference', self.gf('django.db.models.fields.IntegerField')()), + )) + db.send_create_signal('rattail', ['VendorContact']) + # Adding model 'Product' db.create_table('rattail_products', ( ('uuid', self.gf('rattail.django.rattail.models.core.UUIDField')(max_length=32, primary_key=True)), @@ -83,6 +135,8 @@ class Migration(SchemaMigration): ('description2', self.gf('django.db.models.fields.CharField')(max_length=60, null=True, blank=True)), ('size', self.gf('django.db.models.fields.CharField')(max_length=30, null=True, blank=True)), ('unit_of_measure', self.gf('django.db.models.fields.CharField')(max_length=4, null=True, blank=True)), + ('regular_price', self.gf('django.db.models.fields.related.ForeignKey')(blank=True, related_name='+', null=True, db_column='regular_price_uuid', to=orm['rattail.ProductPrice'])), + ('current_price', self.gf('django.db.models.fields.related.ForeignKey')(blank=True, related_name='+', null=True, db_column='current_price_uuid', to=orm['rattail.ProductPrice'])), )) db.send_create_signal('rattail', ['Product']) @@ -101,14 +155,115 @@ class Migration(SchemaMigration): )) db.send_create_signal('rattail', ['ProductPrice']) + # Adding model 'ProductCost' + db.create_table('rattail_product_costs', ( + ('uuid', self.gf('rattail.django.rattail.models.core.UUIDField')(max_length=32, primary_key=True)), + ('product', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['rattail.Product'], db_column='product_uuid')), + ('vendor', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['rattail.Vendor'], db_column='vendor_uuid')), + ('preference', self.gf('django.db.models.fields.IntegerField')()), + ('code', self.gf('django.db.models.fields.CharField')(max_length=15, null=True, blank=True)), + ('case_size', self.gf('django.db.models.fields.IntegerField')(null=True, blank=True)), + ('case_cost', self.gf('django.db.models.fields.DecimalField')(null=True, max_digits=9, decimal_places=5, blank=True)), + ('pack_size', self.gf('django.db.models.fields.IntegerField')(null=True, blank=True)), + ('pack_cost', self.gf('django.db.models.fields.DecimalField')(null=True, max_digits=9, decimal_places=5, blank=True)), + ('unit_cost', self.gf('django.db.models.fields.DecimalField')(null=True, max_digits=9, decimal_places=5, blank=True)), + ('effective', self.gf('django.db.models.fields.DateTimeField')(null=True, blank=True)), + )) + db.send_create_signal('rattail', ['ProductCost']) + + # Adding model 'Employee' + db.create_table('rattail_employees', ( + ('uuid', self.gf('rattail.django.rattail.models.core.UUIDField')(max_length=32, primary_key=True)), + ('id', self.gf('django.db.models.fields.IntegerField')(null=True, blank=True)), + ('person', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['rattail.Person'], db_column='person_uuid')), + ('status', self.gf('django.db.models.fields.IntegerField')()), + ('display_name', self.gf('django.db.models.fields.CharField')(max_length=100, null=True, blank=True)), + )) + db.send_create_signal('rattail', ['Employee']) + + # Adding model 'Customer' + db.create_table('rattail_customers', ( + ('uuid', self.gf('rattail.django.rattail.models.core.UUIDField')(max_length=32, primary_key=True)), + ('id', self.gf('django.db.models.fields.CharField')(max_length=20, null=True, blank=True)), + ('name', self.gf('django.db.models.fields.CharField')(max_length=255, null=True, blank=True)), + ('email_preference', self.gf('django.db.models.fields.IntegerField')(null=True, blank=True)), + )) + db.send_create_signal('rattail', ['Customer']) + + # Adding model 'CustomerPerson' + db.create_table('rattail_customers_people', ( + ('uuid', self.gf('rattail.django.rattail.models.core.UUIDField')(max_length=32, primary_key=True)), + ('customer', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['rattail.Customer'], db_column='customer_uuid')), + ('person', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['rattail.Person'], db_column='person_uuid')), + ('ordinal', self.gf('django.db.models.fields.IntegerField')()), + )) + db.send_create_signal('rattail', ['CustomerPerson']) + + # Adding model 'CustomerGroup' + db.create_table('rattail_customer_groups', ( + ('uuid', self.gf('rattail.django.rattail.models.core.UUIDField')(max_length=32, primary_key=True)), + ('id', self.gf('django.db.models.fields.CharField')(max_length=20, null=True, blank=True)), + ('name', self.gf('django.db.models.fields.CharField')(max_length=255, null=True, blank=True)), + )) + db.send_create_signal('rattail', ['CustomerGroup']) + + # Adding model 'CustomerGroupAssignment' + db.create_table('rattail_customers_groups', ( + ('uuid', self.gf('rattail.django.rattail.models.core.UUIDField')(max_length=32, primary_key=True)), + ('customer', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['rattail.Customer'], db_column='customer_uuid')), + ('group', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['rattail.CustomerGroup'], db_column='group_uuid')), + ('ordinal', self.gf('django.db.models.fields.IntegerField')()), + )) + db.send_create_signal('rattail', ['CustomerGroupAssignment']) + + # Adding model 'LabelProfile' + db.create_table('rattail_label_profiles', ( + ('uuid', self.gf('rattail.django.rattail.models.core.UUIDField')(max_length=32, primary_key=True)), + ('ordinal', self.gf('django.db.models.fields.IntegerField')(null=True, blank=True)), + ('code', self.gf('django.db.models.fields.CharField')(max_length=3, null=True, blank=True)), + ('description', self.gf('django.db.models.fields.CharField')(max_length=50, null=True, blank=True)), + ('printer_spec', self.gf('django.db.models.fields.CharField')(max_length=255, null=True, blank=True)), + ('formatter_spec', self.gf('django.db.models.fields.CharField')(max_length=255, null=True, blank=True)), + ('format', self.gf('django.db.models.fields.TextField')(null=True, blank=True)), + ('visible', self.gf('django.db.models.fields.BooleanField')(default=False)), + )) + db.send_create_signal('rattail', ['LabelProfile']) + def backwards(self, orm): + # Deleting model 'LabelProfile' + db.delete_table('rattail_label_profiles') + + # Deleting model 'CustomerGroupAssignment' + db.delete_table('rattail_customers_groups') + + # Deleting model 'CustomerGroup' + db.delete_table('rattail_customer_groups') + + # Deleting model 'CustomerPerson' + db.delete_table('rattail_customers_people') + + # Deleting model 'Customer' + db.delete_table('rattail_customers') + + # Deleting model 'Employee' + db.delete_table('rattail_employees') + + # Deleting model 'ProductCost' + db.delete_table('rattail_product_costs') + # Deleting model 'ProductPrice' db.delete_table('rattail_product_prices') # Deleting model 'Product' db.delete_table('rattail_products') + # Deleting model 'VendorContact' + db.delete_table('rattail_vendor_contacts') + + # Deleting model 'Vendor' + db.delete_table('rattail_vendors') + # Deleting model 'Brand' db.delete_table('rattail_brands') @@ -124,14 +279,33 @@ class Migration(SchemaMigration): # Deleting model 'Store' db.delete_table('rattail_stores') + # Deleting model 'UserRole' + db.delete_table('rattail_users_roles') + + # Deleting model 'User' + db.delete_table('rattail_users') + + # Deleting model 'Role' + db.delete_table('rattail_roles') + # Deleting model 'EmailAddress' db.delete_table('rattail_email_addresses') # Deleting model 'PhoneNumber' db.delete_table('rattail_phone_numbers') + # Deleting model 'Person' + db.delete_table('rattail_people') + models = { + 'rattail.person': { + 'Meta': {'object_name': 'Person', 'db_table': "'rattail_people'"}, + 'display_name': ('django.db.models.fields.CharField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}), + 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '50', 'null': 'True', 'blank': 'True'}), + 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '50', 'null': 'True', 'blank': 'True'}), + 'uuid': ('rattail.django.rattail.models.core.UUIDField', [], {'max_length': '32', 'primary_key': 'True'}) + }, 'rattail.phonenumber': { 'Meta': {'object_name': 'PhoneNumber', 'db_table': "'rattail_phone_numbers'"}, 'number': ('django.db.models.fields.CharField', [], {'max_length': '20'}), @@ -150,6 +324,25 @@ class Migration(SchemaMigration): 'type': ('django.db.models.fields.CharField', [], {'max_length': '15', 'null': 'True', 'blank': 'True'}), 'uuid': ('rattail.django.rattail.models.core.UUIDField', [], {'max_length': '32', 'primary_key': 'True'}) }, + 'rattail.role': { + 'Meta': {'object_name': 'Role', 'db_table': "'rattail_roles'"}, + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '25'}), + 'uuid': ('rattail.django.rattail.models.core.UUIDField', [], {'max_length': '32', 'primary_key': 'True'}) + }, + 'rattail.user': { + 'Meta': {'object_name': 'User', 'db_table': "'rattail_users'"}, + 'password': ('django.db.models.fields.CharField', [], {'max_length': '60', 'null': 'True', 'blank': 'True'}), + 'person': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['rattail.Person']", 'null': 'True', 'db_column': "'person_uuid'", 'blank': 'True'}), + 'salt': ('django.db.models.fields.CharField', [], {'max_length': '29', 'null': 'True', 'blank': 'True'}), + 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '25'}), + 'uuid': ('rattail.django.rattail.models.core.UUIDField', [], {'max_length': '32', 'primary_key': 'True'}) + }, + 'rattail.userrole': { + 'Meta': {'object_name': 'UserRole', 'db_table': "'rattail_users_roles'"}, + 'role': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['rattail.Role']", 'db_column': "'role_uuid'"}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['rattail.User']", 'db_column': "'user_uuid'"}), + 'uuid': ('rattail.django.rattail.models.core.UUIDField', [], {'max_length': '32', 'primary_key': 'True'}) + }, 'rattail.store': { 'Meta': {'object_name': 'Store', 'db_table': "'rattail_stores'"}, 'id': ('django.db.models.fields.CharField', [], {'max_length': '10', 'null': 'True', 'blank': 'True'}), @@ -181,13 +374,29 @@ class Migration(SchemaMigration): 'name': ('django.db.models.fields.CharField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}), 'uuid': ('rattail.django.rattail.models.core.UUIDField', [], {'max_length': '32', 'primary_key': 'True'}) }, + 'rattail.vendor': { + 'Meta': {'object_name': 'Vendor', 'db_table': "'rattail_vendors'"}, + 'id': ('django.db.models.fields.CharField', [], {'max_length': '15', 'null': 'True', 'blank': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '40', 'null': 'True', 'blank': 'True'}), + 'special_discount': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '5', 'decimal_places': '3', 'blank': 'True'}), + 'uuid': ('rattail.django.rattail.models.core.UUIDField', [], {'max_length': '32', 'primary_key': 'True'}) + }, + 'rattail.vendorcontact': { + 'Meta': {'object_name': 'VendorContact', 'db_table': "'rattail_vendor_contacts'"}, + 'person': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['rattail.Person']", 'db_column': "'person_uuid'"}), + 'preference': ('django.db.models.fields.IntegerField', [], {}), + 'uuid': ('rattail.django.rattail.models.core.UUIDField', [], {'max_length': '32', 'primary_key': 'True'}), + 'vendor': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['rattail.Vendor']", 'db_column': "'vendor_uuid'"}) + }, 'rattail.product': { 'Meta': {'object_name': 'Product', 'db_table': "'rattail_products'"}, 'brand': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['rattail.Brand']", 'null': 'True', 'db_column': "'brand_uuid'", 'blank': 'True'}), 'category': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['rattail.Category']", 'null': 'True', 'db_column': "'category_uuid'", 'blank': 'True'}), + 'current_price': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'+'", 'null': 'True', 'db_column': "'current_price_uuid'", 'to': "orm['rattail.ProductPrice']"}), 'department': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['rattail.Department']", 'null': 'True', 'db_column': "'department_uuid'", 'blank': 'True'}), 'description': ('django.db.models.fields.CharField', [], {'max_length': '60', 'null': 'True', 'blank': 'True'}), 'description2': ('django.db.models.fields.CharField', [], {'max_length': '60', 'null': 'True', 'blank': 'True'}), + 'regular_price': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'+'", 'null': 'True', 'db_column': "'regular_price_uuid'", 'to': "orm['rattail.ProductPrice']"}), 'size': ('django.db.models.fields.CharField', [], {'max_length': '30', 'null': 'True', 'blank': 'True'}), 'subdepartment': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['rattail.Subdepartment']", 'null': 'True', 'db_column': "'subdepartment_uuid'", 'blank': 'True'}), 'unit_of_measure': ('django.db.models.fields.CharField', [], {'max_length': '4', 'null': 'True', 'blank': 'True'}), @@ -207,6 +416,66 @@ class Migration(SchemaMigration): 'type': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), 'uuid': ('rattail.django.rattail.models.core.UUIDField', [], {'max_length': '32', 'primary_key': 'True'}) }, + 'rattail.productcost': { + 'Meta': {'object_name': 'ProductCost', 'db_table': "'rattail_product_costs'"}, + 'case_cost': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '9', 'decimal_places': '5', 'blank': 'True'}), + 'case_size': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), + 'code': ('django.db.models.fields.CharField', [], {'max_length': '15', 'null': 'True', 'blank': 'True'}), + 'effective': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'pack_cost': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '9', 'decimal_places': '5', 'blank': 'True'}), + 'pack_size': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), + 'preference': ('django.db.models.fields.IntegerField', [], {}), + 'product': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['rattail.Product']", 'db_column': "'product_uuid'"}), + 'unit_cost': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '9', 'decimal_places': '5', 'blank': 'True'}), + 'uuid': ('rattail.django.rattail.models.core.UUIDField', [], {'max_length': '32', 'primary_key': 'True'}), + 'vendor': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['rattail.Vendor']", 'db_column': "'vendor_uuid'"}) + }, + 'rattail.employee': { + 'Meta': {'object_name': 'Employee', 'db_table': "'rattail_employees'"}, + 'display_name': ('django.db.models.fields.CharField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}), + 'id': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), + 'person': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['rattail.Person']", 'db_column': "'person_uuid'"}), + 'status': ('django.db.models.fields.IntegerField', [], {}), + 'uuid': ('rattail.django.rattail.models.core.UUIDField', [], {'max_length': '32', 'primary_key': 'True'}) + }, + 'rattail.customer': { + 'Meta': {'object_name': 'Customer', 'db_table': "'rattail_customers'"}, + 'email_preference': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), + 'id': ('django.db.models.fields.CharField', [], {'max_length': '20', 'null': 'True', 'blank': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), + 'uuid': ('rattail.django.rattail.models.core.UUIDField', [], {'max_length': '32', 'primary_key': 'True'}) + }, + 'rattail.customerperson': { + 'Meta': {'object_name': 'CustomerPerson', 'db_table': "'rattail_customers_people'"}, + 'customer': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['rattail.Customer']", 'db_column': "'customer_uuid'"}), + 'ordinal': ('django.db.models.fields.IntegerField', [], {}), + 'person': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['rattail.Person']", 'db_column': "'person_uuid'"}), + 'uuid': ('rattail.django.rattail.models.core.UUIDField', [], {'max_length': '32', 'primary_key': 'True'}) + }, + 'rattail.customergroup': { + 'Meta': {'object_name': 'CustomerGroup', 'db_table': "'rattail_customer_groups'"}, + 'id': ('django.db.models.fields.CharField', [], {'max_length': '20', 'null': 'True', 'blank': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), + 'uuid': ('rattail.django.rattail.models.core.UUIDField', [], {'max_length': '32', 'primary_key': 'True'}) + }, + 'rattail.customergroupassignment': { + 'Meta': {'object_name': 'CustomerGroupAssignment', 'db_table': "'rattail_customers_groups'"}, + 'customer': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['rattail.Customer']", 'db_column': "'customer_uuid'"}), + 'group': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['rattail.CustomerGroup']", 'db_column': "'group_uuid'"}), + 'ordinal': ('django.db.models.fields.IntegerField', [], {}), + 'uuid': ('rattail.django.rattail.models.core.UUIDField', [], {'max_length': '32', 'primary_key': 'True'}) + }, + 'rattail.labelprofile': { + 'Meta': {'object_name': 'LabelProfile', 'db_table': "'rattail_label_profiles'"}, + 'code': ('django.db.models.fields.CharField', [], {'max_length': '3', 'null': 'True', 'blank': 'True'}), + 'description': ('django.db.models.fields.CharField', [], {'max_length': '50', 'null': 'True', 'blank': 'True'}), + 'format': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), + 'formatter_spec': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), + 'ordinal': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), + 'printer_spec': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), + 'uuid': ('rattail.django.rattail.models.core.UUIDField', [], {'max_length': '32', 'primary_key': 'True'}), + 'visible': ('django.db.models.fields.BooleanField', [], {'default': 'False'}) + }, } complete_apps = ['rattail'] diff --git a/rattail/django/rattail/models/__init__.py b/rattail/django/rattail/models/__init__.py index 35a8666..006467b 100644 --- a/rattail/django/rattail/models/__init__.py +++ b/rattail/django/rattail/models/__init__.py @@ -31,6 +31,8 @@ from __future__ import absolute_import from south.modelsinspector import add_introspection_rules from rattail.django.rattail.models.core import * +from rattail.django.rattail.models.contact import * +from rattail.django.rattail.models.auth import * from rattail.django.rattail.models.rattail import * diff --git a/rattail/django/rattail/models/auth.py b/rattail/django/rattail/models/auth.py new file mode 100644 index 0000000..8ad9c79 --- /dev/null +++ b/rattail/django/rattail/models/auth.py @@ -0,0 +1,106 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +################################################################################ +# +# Rattail -- Retail Software Framework +# Copyright © 2010-2012 Lance Edgar +# +# This file is part of Rattail. +# +# Rattail is free software: you can redistribute it and/or modify it under the +# terms of the GNU Affero General Public License as published by the Free +# Software Foundation, either version 3 of the License, or (at your option) +# any later version. +# +# Rattail is distributed in the hope that it will be useful, but WITHOUT ANY +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for +# more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with Rattail. If not, see . +# +################################################################################ + +""" +``rattail.django.rattail.models.auth`` -- Models for 'auth' Extension +""" + +from __future__ import absolute_import + +from django.db import models + +from rattail.django.rattail.models import Model, uuid_field + + +__all__ = ['Role', 'User', 'UserRole'] + + +class Role(Model): + """ + Represents a role within the system; used to manage permissions. + """ + + class Meta(Model.Meta): + db_table = Model.prefix('roles') + + uuid = uuid_field() + name = models.CharField(max_length=25, unique=True) + + def __repr__(self): + return "" % self.name + + def __unicode__(self): + return unicode(self.name or '') + + +class User(Model): + """ + Represents a user of the system. This may or may not correspond to a real + person, i.e. some users may exist solely for automated tasks. + """ + + class Meta(Model.Meta): + db_table = Model.prefix('users') + + uuid = uuid_field() + username = models.CharField(max_length=25, unique=True) + password = models.CharField(max_length=60, blank=True, null=True) + salt = models.CharField(max_length=29, blank=True, null=True) + person = models.ForeignKey('Person', db_column='person_uuid', blank=True, null=True) + + def __repr__(self): + return "" % self.username + + def __unicode__(self): + return unicode(self.username or '') + + @property + def display_name(self): + """ + Returns :attr:`rattail.Person.display_name` if present; otherwise + returns :attr:`username`. + """ + + if self.person and self.person.display_name: + return self.person.display_name + return self.username + + +class UserRole(Model): + """ + Represents the association between a :class:`User` and a :class:`Role`. + """ + + class Meta(Model.Meta): + db_table = Model.prefix('users_roles') + + uuid = uuid_field() + user = models.ForeignKey(User, db_column='user_uuid') + role = models.ForeignKey(Role, db_column='role_uuid') + + def __repr__(self): + return "" % (self.user, self.role) + + def __unicode__(self): + return unicode(self.role or '') diff --git a/rattail/django/rattail/models/contact.py b/rattail/django/rattail/models/contact.py index 078d8e9..11bf429 100644 --- a/rattail/django/rattail/models/contact.py +++ b/rattail/django/rattail/models/contact.py @@ -33,7 +33,8 @@ from django.db import models from rattail.django.rattail.models import Model, uuid_field -__all__ = ['PhoneNumber', 'EmailAddress'] +__all__ = ['PhoneNumber', 'EmailAddress', + 'Person', 'PersonPhoneNumber', 'PersonEmailAddress'] class ContactInfoManager(models.Manager): @@ -68,6 +69,8 @@ class PhoneNumber(ContactInfo): class Meta(ContactInfo.Meta): abstract = True db_table = ContactInfo.prefix('phone_numbers') + verbose_name = "Phone Number" + verbose_name_plural = "Phone Numbers" number = models.CharField(max_length=20) @@ -86,6 +89,8 @@ class EmailAddress(ContactInfo): class Meta(ContactInfo.Meta): abstract = True db_table = ContactInfo.prefix('email_addresses') + verbose_name = "Email Address" + verbose_name_plural = "Email Addresses" address = models.CharField(max_length=255) @@ -94,3 +99,63 @@ class EmailAddress(ContactInfo): def __unicode__(self): return unicode(self.address) + + +class Person(Model): + """ + Represents a real, living and breathing person. (Or, at least was + previously living and breathing, in the case of the deceased.) + """ + + class Meta(Model.Meta): + db_table = Model.prefix('people') + verbose_name_plural = "People" + + uuid = uuid_field() + first_name = models.CharField(max_length=50, blank=True, null=True) + last_name = models.CharField(max_length=50, blank=True, null=True) + display_name = models.CharField(max_length=100, blank=True, null=True, verbose_name="Display Name") + + def __repr__(self): + return "" % self.display_name + + def __unicode__(self): + return unicode(self.display_name or '') + + def save(self, *args, **kwargs): + if not self.display_name: + if self.first_name and self.last_name: + self.display_name = self.first_name + ' ' + self.last_name + elif self.first_name: + self.display_name = self.first_name + elif self.last_name: + self.display_name = self.last_name + super(Person, self).save(*args, **kwargs) + + +class PersonContactInfo(models.Model): + """ + Base class for person contact models (phone number, etc.). + """ + + class Meta: + abstract = True + + store = models.ForeignKey(Person, db_column='parent_uuid') + objects = ContactInfoManager('Person') + + def save(self, *args, **kwargs): + self.parent_type = 'Person' + super(PersonContactInfo, self).save(*args, **kwargs) + + +class PersonPhoneNumber(PhoneNumber, PersonContactInfo): + """ + Represents a phone (or fax) number associated with a :class:`Person`. + """ + + +class PersonEmailAddress(EmailAddress, PersonContactInfo): + """ + Represents an email address associated with a :class:`Person`. + """ diff --git a/rattail/django/rattail/models/rattail.py b/rattail/django/rattail/models/rattail.py index e12a22d..76dd036 100644 --- a/rattail/django/rattail/models/rattail.py +++ b/rattail/django/rattail/models/rattail.py @@ -30,8 +30,12 @@ from __future__ import absolute_import from django.db import models +from edbob.db.extensions.contact.enum import EMAIL_PREFERENCE + import rattail from rattail.gpc import GPC +from rattail.db.extension.enum import EMPLOYEE_STATUS + from rattail.django.rattail.models import Model, uuid_field from rattail.django.rattail.models.contact import ( ContactInfoManager, PhoneNumber, EmailAddress) @@ -40,7 +44,12 @@ from rattail.django.util import enum_to_choices __all__ = ['Store', 'StorePhoneNumber', 'StoreEmailAddress', 'Department', 'Subdepartment', 'Category', 'Brand', - 'Product', 'ProductPrice'] + 'Vendor', 'VendorPhoneNumber', 'VendorEmailAddress', 'VendorContact', + 'Product', 'ProductPrice', 'ProductCost', + 'Employee', 'EmployeePhoneNumber', 'EmployeeEmailAddress', + 'Customer', 'CustomerPhoneNumber', 'CustomerEmailAddress', 'CustomerPerson', + 'CustomerGroup', 'CustomerGroupAssignment', + 'LabelProfile'] class GPCField(models.BigIntegerField): @@ -70,6 +79,7 @@ class Store(Model): class Meta(Model.Meta): db_table = Model.prefix('stores') + verbose_name = "Store" uuid = uuid_field() id = models.CharField(max_length=10, blank=True, null=True, verbose_name="ID") @@ -117,6 +127,7 @@ class Department(Model): class Meta(Model.Meta): db_table = Model.prefix('departments') + verbose_name = "Department" uuid = uuid_field() number = models.IntegerField(blank=True, null=True) @@ -136,6 +147,7 @@ class Subdepartment(Model): class Meta(Model.Meta): db_table = Model.prefix('subdepartments') + verbose_name = "Subdepartment" uuid = uuid_field() number = models.IntegerField(blank=True, null=True) @@ -156,6 +168,7 @@ class Category(Model): class Meta(Model.Meta): db_table = Model.prefix('categories') + verbose_name = "Category" verbose_name_plural = "Categories" uuid = uuid_field() @@ -177,6 +190,7 @@ class Brand(Model): class Meta(Model.Meta): db_table = Model.prefix('brands') + verbose_name = "Brand" uuid = uuid_field() name = models.CharField(max_length=100, blank=True, null=True) @@ -188,6 +202,77 @@ class Brand(Model): return unicode(self.name or '') +class Vendor(Model): + """ + Represents a vendor from which products are purchased by the store. + """ + + class Meta(Model.Meta): + db_table = Model.prefix('vendors') + verbose_name = "Vendor" + + uuid = uuid_field() + id = models.CharField(max_length=15, blank=True, null=True, verbose_name="ID") + name = models.CharField(max_length=40, blank=True, null=True) + special_discount = models.DecimalField(max_digits=5, decimal_places=3, blank=True, null=True, verbose_name="Special Discount") + + def __repr__(self): + return "" % self.name + + def __unicode__(self): + return unicode(self.name or '') + + +class VendorContactInfo(models.Model): + """ + Base class for vendor contact models (phone number, etc.). + """ + + class Meta: + abstract = True + + vendor = models.ForeignKey(Vendor, db_column='parent_uuid') + objects = ContactInfoManager('Vendor') + + def save(self, *args, **kwargs): + self.parent_type = 'Vendor' + super(VendorContactInfo, self).save(*args, **kwargs) + + +class VendorPhoneNumber(PhoneNumber, VendorContactInfo): + """ + Represents a phone (or fax) number associated with a :class:`Vendor`. + """ + + +class VendorEmailAddress(EmailAddress, VendorContactInfo): + """ + Represents an email address associated with a :class:`Vendor`. + """ + + +class VendorContact(Model): + """ + Represents a point of contact (e.g. salesperson) for a vendor, from the + retailer's perspective. + """ + + class Meta(Model.Meta): + db_table = Model.prefix('vendor_contacts') + verbose_name = "Vendor Contact" + + uuid = uuid_field() + vendor = models.ForeignKey(Vendor, db_column='vendor_uuid') + person = models.ForeignKey('Person', db_column='person_uuid') + preference = models.IntegerField() + + def __repr__(self): + return "" % (self.vendor, self.person) + + def __unicode__(self): + return unicode(self.person) + + class Product(Model): """ Represents a product for sale and/or purchase. @@ -195,6 +280,9 @@ class Product(Model): class Meta(Model.Meta): db_table = Model.prefix('products') + verbose_name = "Product" + + UNIT_OF_MEASURE_CHOICES = enum_to_choices(rattail.UNIT_OF_MEASURE) uuid = uuid_field() upc = GPCField(db_index=True, verbose_name="UPC") @@ -205,7 +293,9 @@ class Product(Model): description = models.CharField(max_length=60, blank=True, null=True) description2 = models.CharField(max_length=60, blank=True, null=True, verbose_name="Description Line 2") size = models.CharField(max_length=30, blank=True, null=True) - unit_of_measure = models.CharField(max_length=4, blank=True, null=True, verbose_name="Unit of Measure") + unit_of_measure = models.CharField(max_length=4, choices=UNIT_OF_MEASURE_CHOICES, blank=True, null=True, verbose_name="Unit of Measure") + regular_price = models.ForeignKey('ProductPrice', db_column='regular_price_uuid', related_name='+', blank=True, null=True, verbose_name="Regular Price") + current_price = models.ForeignKey('ProductPrice', db_column='current_price_uuid', related_name='+', blank=True, null=True, verbose_name="Current Price") def __repr__(self): return "" % self.description @@ -221,6 +311,7 @@ class ProductPrice(Model): class Meta(Model.Meta): db_table = Model.prefix('product_prices') + verbose_name = "Product Price" PRICE_TYPE_CHOICES = enum_to_choices(rattail.PRICE_TYPE) @@ -239,5 +330,243 @@ class ProductPrice(Model): return "" % (self.product, self.price) def __unicode__(self): + if self.price is None: + return u'' type = rattail.PRICE_TYPE.get(self.type, "?") return u'$ %0.2f / %d (%s)' % (self.price, self.multiple or 1, type) + + +class ProductCost(Model): + """ + Represents a source from which a product may be obtained via purchase. + """ + + class Meta(Model.Meta): + db_table = Model.prefix('product_costs') + verbose_name = "Product Cost" + + uuid = uuid_field() + product = models.ForeignKey(Product, db_column='product_uuid') + vendor = models.ForeignKey(Vendor, db_column='vendor_uuid') + preference = models.IntegerField() + code = models.CharField(max_length=15, blank=True, null=True) + case_size = models.IntegerField(blank=True, null=True, verbose_name="Case Size") + case_cost = models.DecimalField(max_digits=9, decimal_places=5, blank=True, null=True, verbose_name="Case Cost") + pack_size = models.IntegerField(blank=True, null=True, verbose_name="Pack Size") + pack_cost = models.DecimalField(max_digits=9, decimal_places=5, blank=True, null=True, verbose_name="Pack Cost") + unit_cost = models.DecimalField(max_digits=9, decimal_places=5, blank=True, null=True, verbose_name="Unit Cost") + effective = models.DateTimeField(blank=True, null=True) + + def __repr__(self): + return "" % (self.product, self.vendor) + + def __unicode__(self): + if self.unit_cost is None: + return u'' + return '$ %0.4f (%s)' % (self.unit_cost, self.vendor) + + +class Employee(Model): + """ + Represents an employee within the organization. + """ + + class Meta(Model.Meta): + db_table = Model.prefix('employees') + verbose_name = "Employee" + + EMPLOYEE_STATUS_CHOICES = enum_to_choices(EMPLOYEE_STATUS) + + uuid = uuid_field() + id = models.IntegerField(blank=True, null=True, verbose_name="ID") + person = models.ForeignKey('Person', db_column='person_uuid') + status = models.IntegerField(choices=EMPLOYEE_STATUS_CHOICES) + display_name = models.CharField(max_length=100, blank=True, null=True, verbose_name="Display Name") + + def __repr__(self): + return "" % self.person + + def __unicode__(self): + return unicode(self.display_name or self.person) + + def save(self, *args, **kwargs): + if not self.display_name and self.person: + if self.person.display_name: + self.display_name = self.person.display_name + elif self.person.first_name and self.person.last_name: + self.display_name = self.person.first_name + ' ' + self.person.last_name + elif self.person.first_name: + self.display_name = self.person.first_name + elif self.person.last_name: + self.display_name = self.person.last_name + super(Employee, self).save(*args, **kwargs) + + +class EmployeeContactInfo(models.Model): + """ + Base class for employee contact models (phone number, etc.). + """ + + class Meta: + abstract = True + + employee = models.ForeignKey(Employee, db_column='parent_uuid') + objects = ContactInfoManager('Employee') + + def save(self, *args, **kwargs): + self.parent_type = 'Employee' + super(EmployeeContactInfo, self).save(*args, **kwargs) + + +class EmployeePhoneNumber(PhoneNumber, EmployeeContactInfo): + """ + Represents a phone (or fax) number associated with a :class:`Employee`. + """ + + +class EmployeeEmailAddress(EmailAddress, EmployeeContactInfo): + """ + Represents an email address associated with a :class:`Employee`. + """ + + +class Customer(Model): + """ + Represents a customer account. Customer accounts may consist of more than + one :class:`Person`, in some cases. + """ + + class Meta(Model.Meta): + db_table = Model.prefix('customers') + verbose_name = "Customer" + + EMAIL_PREFERENCE_CHOICES = enum_to_choices(EMAIL_PREFERENCE) + + uuid = uuid_field() + id = models.CharField(max_length=20, null=True, blank=True, verbose_name="ID") + name = models.CharField(max_length=255, null=True, blank=True) + email_preference = models.IntegerField(choices=EMAIL_PREFERENCE_CHOICES, null=True, blank=True, verbose_name="Email Preference") + + def __repr__(self): + return "" % (self.id, self.name) + + def __unicode__(self): + return unicode(self.name or '') + + +class CustomerContactInfo(models.Model): + """ + Base class for customer contact models (phone number, etc.). + """ + + class Meta: + abstract = True + + customer = models.ForeignKey(Customer, db_column='parent_uuid') + objects = ContactInfoManager('Customer') + + def save(self, *args, **kwargs): + self.parent_type = 'Customer' + super(CustomerContactInfo, self).save(*args, **kwargs) + + +class CustomerPhoneNumber(PhoneNumber, CustomerContactInfo): + """ + Represents a phone (or fax) number associated with a :class:`Customer`. + """ + + +class CustomerEmailAddress(EmailAddress, CustomerContactInfo): + """ + Represents an email address associated with a :class:`Customer`. + """ + + +class CustomerPerson(Model): + """ + Represents the association between a :class:`Person` and a customer account + (:class:`Customer`). + """ + + class Meta(Model.Meta): + db_table = Model.prefix('customers_people') + verbose_name = "Customer Person" + + uuid = uuid_field() + customer = models.ForeignKey(Customer, db_column='customer_uuid') + person = models.ForeignKey('Person', db_column='person_uuid') + ordinal = models.IntegerField() + + def __repr__(self): + return "" % self.person + + def __unicode__(self): + return unicode(self.person or '') + + +class CustomerGroup(Model): + """ + Represents an arbitrary group to which :class:`Customer` instances may (or + may not) belong. + """ + + class Meta(Model.Meta): + db_table = Model.prefix('customer_groups') + verbose_name = "Customer Group" + + uuid = uuid_field() + id = models.CharField(max_length=20, blank=True, null=True, verbose_name="ID") + name = models.CharField(max_length=255, blank=True, null=True) + + def __repr__(self): + return "" % (self.id, self.name) + + def __unicode__(self): + return unicode(self.name or '') + + +class CustomerGroupAssignment(Model): + """ + Represents the assignment of a :class:`Customer` to a + :class:`CustomerGroup`. + """ + + class Meta(Model.Meta): + db_table = Model.prefix('customers_groups') + verbose_name = "Customer Group Assignment" + + uuid = uuid_field() + customer = models.ForeignKey(Customer, db_column='customer_uuid') + group = models.ForeignKey(CustomerGroup, db_column='group_uuid') + ordinal = models.IntegerField() + + def __repr__(self): + return "" % (self.customer, self.group) + + def __unicode__(self): + return u'%s, %s' % (self.customer, self.group) + + +class LabelProfile(Model): + """ + Represents a "profile" (collection of settings) for product label printing. + """ + + class Meta(Model.Meta): + db_table = Model.prefix('label_profiles') + verbose_name = "Label Profile" + + uuid = uuid_field() + ordinal = models.IntegerField(blank=True, null=True) + code = models.CharField(max_length=3, blank=True, null=True) + description = models.CharField(max_length=50, blank=True, null=True) + printer_spec = models.CharField(max_length=255, blank=True, null=True, verbose_name="Printer Spec") + formatter_spec = models.CharField(max_length=255, blank=True, null=True, verbose_name="Formatter Spec") + format = models.TextField(blank=True, null=True) + visible = models.BooleanField() + + def __repr__(self): + return "" % self.code + + def __unicode__(self): + return unicode(self.description or '')