| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127 |
- from django.conf import settings
- from django.db import models
- from django.utils.translation import ugettext_lazy as _
-
- from oscar.apps.partner.wrappers import get_partner_wrapper
-
-
- class AbstractPartner(models.Model):
- u"""Fulfillment partner"""
- name = models.CharField(max_length=128, unique=True)
-
- # A partner can have users assigned to it. These can be used
- # to provide authentication for webservices etc.
- users = models.ManyToManyField('auth.User', related_name="partners", null=True)
-
- class Meta:
- verbose_name_plural = 'Fulfillment partners'
- abstract = True
- permissions = (
- ("can_edit_stock_records", "Can edit stock records"),
- ("can_view_stock_records", "Can view stock records"),
- ("can_edit_product_range", "Can edit product range"),
- ("can_view_product_range", "Can view product range"),
- ("can_edit_order_lines", "Can edit order lines"),
- ("can_view_order_lines", "Can view order lines"),
- )
-
- def __unicode__(self):
- return self.name
-
-
- class AbstractStockRecord(models.Model):
- u"""
- A basic stock record.
-
- This links a product to a partner, together with price and availability
- information. Most projects will need to subclass this object to add custom
- fields such as lead_time, report_code, min_quantity.
- """
- product = models.OneToOneField('product.Item')
- partner = models.ForeignKey('partner.Partner')
- partner_sku = models.CharField(_("Partner SKU"), max_length=128, blank=True)
-
- # Price info:
- # We deliberately don't store tax information to allow each project
- # to subclass this model and put its own fields for convey tax.
- price_currency = models.CharField(max_length=12, default=settings.OSCAR_DEFAULT_CURRENCY)
-
- # This is the base price for calculations - tax should be applied
- # by the appropriate method. We don't store it here as its calculation is
- # highly domain-specific. It is NULLable because some items don't have a fixed
- # price.
- price_excl_tax = models.DecimalField(decimal_places=2, max_digits=12, blank=True, null=True)
-
- # Retail price for this item
- price_retail = models.DecimalField(decimal_places=2, max_digits=12, blank=True, null=True)
-
- # Cost price is optional as not all partner supply it
- cost_price = models.DecimalField(decimal_places=2, max_digits=12, blank=True, null=True)
-
- # Stock level information
- num_in_stock = models.IntegerField(default=0, blank=True, null=True)
- num_allocated = models.IntegerField(default=0, blank=True, null=True)
-
- # Date information
- date_created = models.DateTimeField(auto_now_add=True)
- date_updated = models.DateTimeField(auto_now=True, db_index=True)
-
- class Meta:
- abstract = True
-
- def decrement_num_in_stock(self, delta):
- """
- Decrement an item's stock level
- """
- if self.num_in_stock >= delta:
- self.num_in_stock -= delta
- self.num_allocated += delta
- self.save()
-
- def set_discount_price(self, price):
- """
- A setter method for setting a new price.
-
- This is called from within the "discount" app, which is responsible
- for applying fixed-discount offers to products. We use a setter method
- so that this behaviour can be customised in projects.
- """
- self.price_excl_tax = price
- self.save()
-
- # Price retrieval methods - these default to no tax being applicable
- # These are intended to be overridden.
-
- @property
- def availability(self):
- u"""Return an item's availability as a string"""
- return get_partner_wrapper(self.partner.name).availability(self)
-
- @property
- def dispatch_date(self):
- u"""
- Returns the estimated dispatch date for a line
- """
- return get_partner_wrapper(self.partner.name).dispatch_date(self)
-
- @property
- def price_incl_tax(self):
- """
- Return a product's price including tax.
-
- This defaults to the price_excl_tax as tax calculations are
- domain specific. This class needs to be subclassed and tax logic
- added to this method.
- """
- return self.price_excl_tax + self.price_tax
-
- @property
- def price_tax(self):
- u"""Return a product's tax value"""
- return 0
-
- def __unicode__(self):
- if self.partner_sku:
- return "%s (%s): %s" % (self.partner.name, self.partner_sku, self.product.title)
- else:
- return "%s: %s" % (self.partner.name, self.product.title)
|