class Invoice(models.Model): guid = models.CharField(max_length=50) object_type = models.ForeignKey(ContentType, blank=True, null=True) object_id = models.IntegerField(default=0, blank=True, null=True) _object = generic.GenericForeignKey('object_type', 'object_id') title = models.CharField(max_length=200, blank=True, null=True) #user creator = models.ForeignKey(User, related_name="invoice_creator", null=True, on_delete=models.SET_NULL) creator_username = models.CharField(max_length=50, null=True) owner = models.ForeignKey(User, related_name="invoice_owner", null=True, on_delete=models.SET_NULL) owner_username = models.CharField(max_length=50, null=True) #dates create_dt = models.DateTimeField(auto_now_add=True) due_date = models.DateTimeField() update_dt = models.DateTimeField(auto_now=True) tender_date = models.DateTimeField(null=True) arrival_date_time = models.DateTimeField(blank=True, null=True) #payment status status_detail = models.CharField(max_length=50, choices=(('estimate', _('Estimate')), ('tendered', _('Tendered'))), default='estimate') status = models.BooleanField(default=True) estimate = models.BooleanField(default=1) payments_credits = models.DecimalField(max_digits=15, decimal_places=2, blank=True, default=0) balance = models.DecimalField(max_digits=15, decimal_places=2, blank=True, default=0) total = models.DecimalField(max_digits=15, decimal_places=2, blank=True) #discount info discount_code = models.CharField(_('Discount Code'), max_length=100, blank=True, null=True) discount_amount = models.DecimalField(_('Discount Amount'), max_digits=10, decimal_places=2, default=0) #other variance = models.DecimalField(max_digits=10, decimal_places=4, default=0) variance_notes = models.TextField(max_length=1000, blank=True, null=True) receipt = models.BooleanField(default=0) gift = models.BooleanField(default=0) greeting = models.CharField(max_length=500, blank=True, null=True) instructions = models.CharField(max_length=500, blank=True, null=True) po = models.CharField(max_length=50, blank=True) terms = models.CharField(max_length=50, blank=True) disclaimer = models.CharField(max_length=150, blank=True, null=True) admin_notes = models.TextField(blank=True, null=True) fob = models.CharField(max_length=50, blank=True, null=True) project = models.CharField(max_length=50, blank=True, null=True) other = models.CharField(max_length=120, blank=True, null=True) message = models.CharField(max_length=150, blank=True, null=True) subtotal = models.DecimalField(max_digits=15, decimal_places=2, blank=True) tax_exempt = models.BooleanField(default=1) tax_exemptid = models.CharField(max_length=50, blank=True, null=True) tax_rate = models.FloatField(blank=True, default=0) taxable = models.BooleanField(default=0) tax = models.DecimalField(max_digits=6, decimal_places=4, default=0) #bill/ ship bill_to = models.CharField(max_length=120, blank=True) bill_to_first_name = models.CharField(max_length=100, blank=True, null=True) bill_to_last_name = models.CharField(max_length=100, blank=True, null=True) bill_to_company = models.CharField(max_length=100, blank=True, null=True) bill_to_address = models.CharField(max_length=250, blank=True, null=True) bill_to_city = models.CharField(max_length=50, blank=True, null=True) bill_to_state = models.CharField(max_length=50, blank=True, null=True) bill_to_zip_code = models.CharField(max_length=20, blank=True, null=True) bill_to_country = models.CharField(max_length=50, blank=True, null=True) bill_to_phone = models.CharField(max_length=50, blank=True, null=True) bill_to_fax = models.CharField(max_length=50, blank=True, null=True) bill_to_email = models.CharField(max_length=100, blank=True, null=True) ship_to = models.CharField(max_length=120, blank=True) ship_to_first_name = models.CharField(max_length=50, blank=True) ship_to_last_name = models.CharField(max_length=50, blank=True) ship_to_company = models.CharField(max_length=100, blank=True) ship_to_address = models.CharField(max_length=250, blank=True) ship_to_city = models.CharField(max_length=50, blank=True) ship_to_state = models.CharField(max_length=50, blank=True) ship_to_zip_code = models.CharField(max_length=20, blank=True) ship_to_country = models.CharField(max_length=50, blank=True) ship_to_phone = models.CharField(max_length=50, blank=True, null=True) ship_to_fax = models.CharField(max_length=50, blank=True, null=True) ship_to_email = models.CharField(max_length=100, blank=True, null=True) ship_to_address_type = models.CharField(max_length=50, blank=True, null=True) ship_date = models.DateTimeField() ship_via = models.CharField(max_length=50, blank=True) shipping = models.DecimalField(max_digits=6, decimal_places=2, default=0) shipping_surcharge = models.DecimalField(max_digits=6, decimal_places=2, default=0) box_and_packing = models.DecimalField(max_digits=6, decimal_places=2, default=0) objects = InvoiceManager() class Meta: permissions = (("view_invoice", "Can view invoice"), ) def set_creator(self, user): """ Sets creator fields. """ self.creator = user self.creator_username = user.username def set_owner(self, user): """ Sets owner fields. """ self.owner = user self.owner_username = user.username def bill_to_user(self, user): """ This method populates all of the ship to fields via info in user and user.profile object. """ self.bill_to = '%s %s' % (user.first_name, user.last_name) self.bill_to = self.bill_to.strip() self.bill_to_first_name = user.first_name self.bill_to_last_name = user.last_name self.bill_to_email = user.email if hasattr(user, 'profile'): self.bill_to_company = user.profile.company self.bill_to_address = user.profile.address self.bill_to_city = user.profile.city self.bill_to_state = user.profile.state self.bill_to_zip_code = user.profile.zipcode self.bill_to_country = user.profile.country self.bill_to_phone = user.profile.phone self.bill_to_fax = user.profile.fax def ship_to_user(self, user): """ This method populates all of the ship to fields via info in user and user.profile object. """ self.bill_to = '%s %s' % (user.first_name, user.last_name) self.ship_to = self.ship_to.strip() self.ship_to_first_name = user.first_name self.ship_to_last_name = user.last_name self.ship_to_email = user.email if hasattr(user, 'profile'): self.ship_to_company = user.profile.company self.ship_to_address = user.profile.address self.ship_to_city = user.profile.city self.ship_to_state = user.profile.state self.ship_to_zip_code = user.profile.zipcode self.ship_to_country = user.profile.country self.ship_to_phone = user.profile.phone self.ship_to_fax = user.profile.fax self.ship_to_address_type = user.profile.address_type def split_title(self): if ": " in self.title: split_title = ': '.join(self.title.split(': ')[1:]) return u'%s' % split_title return self.title @models.permalink def get_absolute_url(self): return ('invoice.view', [self.id]) def save(self, user=None): """ Set guid, creator and owner if any of these fields are missing. """ self.guid = self.guid or uuid.uuid1().get_hex() if hasattr(user, 'pk'): self.set_creator(user) self.set_owner(user) super(Invoice, self).save() def get_object(self): _object = None try: _object = self._object except: pass return _object @property def is_tendered(self): boo = False if self.id > 0: if self.status_detail.lower() == 'tendered': boo = True return boo def tender(self, user): """ mark it as tendered if we have records """ if not self.is_tendered: # make accounting entry make_acct_entries(user, self, self.total) self.estimate = False self.status_detail = 'tendered' self.status = 1 self.tender_date = datetime.now() self.save() return True # if this invoice allows view by user2_compare def allow_view_by(self, user2_compare, guid=''): if user2_compare.profile.is_superuser: return True if has_perm(user2_compare, 'invoices.view_invoice'): return True if self.guid == guid: return True if user2_compare.is_authenticated(): if user2_compare in [self.creator, self.owner]: return self.status return False def allow_payment_by(self, user2_compare, guid=''): return self.allow_view_by(user2_compare, guid) # if this invoice allows edit by user2_compare def allow_edit_by(self, user2_compare, guid=''): boo = False if user2_compare.is_superuser: boo = True else: if user2_compare and user2_compare.id > 0: if has_perm(user2_compare, 'invoices.change_invoice'): return True if self.creator == user2_compare or \ self.owner == user2_compare: if self.status == 1: # user can only edit a non-tendered invoice if not self.is_tendered: boo = True else: if self.guid and self.guid == guid: # for anonymous user if self.status == 1 and not self.is_tendered: boo = True return boo def make_payment(self, user, amount): """ Updates the invoice balance by adding accounting entries. """ if self.is_tendered and self.balance > 0: self.balance -= amount self.payments_credits += amount self.save() # Make the accounting entries here make_acct_entries(user, self, amount) return True return False def void_payment(self, user, amount): self.balance += amount self.payments_credits -= amount self.save() # only void approved and non-zero payments for payment in self.payment_set.filter( status_detail='approved', amount__gt=0): payment.status_detail = 'void' payment.save() # reverse accounting entries make_acct_entries_reversing(user, self, amount)
class Invoice(models.Model): guid = models.CharField(max_length=50) object_type = models.ForeignKey(ContentType, blank=True, null=True, on_delete=models.CASCADE) object_id = models.IntegerField(default=0, blank=True, null=True) _object = GenericForeignKey('object_type', 'object_id') title = models.CharField(max_length=200, blank=True, null=True) creator = models.ForeignKey(User, related_name="invoice_creator", null=True, on_delete=models.SET_NULL) creator_username = models.CharField(max_length=150, null=True) owner = models.ForeignKey(User, related_name="invoice_owner", null=True, on_delete=models.SET_NULL) owner_username = models.CharField(max_length=150, null=True) entity = models.ForeignKey(Entity, blank=True, null=True, default=None, on_delete=models.SET_NULL, related_name="invoices") create_dt = models.DateTimeField(auto_now_add=True) due_date = models.DateTimeField() update_dt = models.DateTimeField(auto_now=True) tender_date = models.DateTimeField(null=True) void_date = models.DateTimeField(null=True) voided_by = models.ForeignKey(User, related_name="invoice_voided_by", null=True, on_delete=models.SET_NULL) void_reason = models.TextField(_('Reason to void'), max_length=200, blank=True, default='') arrival_date_time = models.DateTimeField(blank=True, null=True) is_void = models.BooleanField(default=False) status_detail = models.CharField(max_length=50, choices=STATUS_DETAIL_CHOICES, default='estimate') status = models.BooleanField(default=True) payments_credits = models.DecimalField(max_digits=15, decimal_places=2, blank=True, default=0) balance = models.DecimalField(max_digits=15, decimal_places=2, blank=True, default=0) total = models.DecimalField(max_digits=15, decimal_places=2, blank=True) discount_code = models.CharField(_('Discount Code'), max_length=100, blank=True, null=True) discount_amount = models.DecimalField(_('Discount Amount'), max_digits=10, decimal_places=2, default=0) variance = models.DecimalField(max_digits=10, decimal_places=2, default=0) variance_notes = models.TextField(max_length=1000, blank=True, null=True) receipt = models.BooleanField(default=False) gift = models.BooleanField(default=False) greeting = models.CharField(max_length=500, blank=True, null=True) instructions = models.CharField(max_length=500, blank=True, null=True) po = models.CharField(max_length=50, blank=True) terms = models.CharField(max_length=50, blank=True) disclaimer = models.CharField(max_length=150, blank=True, null=True) admin_notes = models.TextField(blank=True, null=True) fob = models.CharField(max_length=50, blank=True, null=True) project = models.CharField(max_length=50, blank=True, null=True) other = models.CharField(max_length=120, blank=True, null=True) message = models.CharField(max_length=150, blank=True, null=True) subtotal = models.DecimalField(max_digits=15, decimal_places=2, blank=True) gratuity = models.DecimalField(blank=True, default=0, max_digits=6, decimal_places=4) tax_exempt = models.BooleanField(default=True) tax_exemptid = models.CharField(max_length=50, blank=True, null=True) tax_rate = models.FloatField(blank=True, default=0) taxable = models.BooleanField(default=False) tax = models.DecimalField(max_digits=15, decimal_places=4, default=0) bill_to = models.CharField(max_length=120, blank=True) bill_to_first_name = models.CharField(max_length=100, blank=True, null=True) bill_to_last_name = models.CharField(max_length=100, blank=True, null=True) bill_to_company = models.CharField(max_length=100, blank=True, null=True) bill_to_address = models.CharField(max_length=250, blank=True, null=True) bill_to_city = models.CharField(max_length=50, blank=True, null=True) bill_to_state = models.CharField(max_length=50, blank=True, null=True) bill_to_zip_code = models.CharField(max_length=20, blank=True, null=True) bill_to_country = models.CharField(max_length=255, blank=True, null=True) bill_to_phone = models.CharField(max_length=50, blank=True, null=True) bill_to_fax = models.CharField(max_length=50, blank=True, null=True) bill_to_email = models.CharField(max_length=100, blank=True, null=True) ship_to = models.CharField(max_length=120, blank=True) ship_to_first_name = models.CharField(max_length=50, blank=True) ship_to_last_name = models.CharField(max_length=50, blank=True) ship_to_company = models.CharField(max_length=100, blank=True) ship_to_address = models.CharField(max_length=250, blank=True) ship_to_city = models.CharField(max_length=50, blank=True) ship_to_state = models.CharField(max_length=50, blank=True) ship_to_zip_code = models.CharField(max_length=20, blank=True) ship_to_country = models.CharField(max_length=255, blank=True) ship_to_phone = models.CharField(max_length=50, blank=True, null=True) ship_to_fax = models.CharField(max_length=50, blank=True, null=True) ship_to_email = models.CharField(max_length=100, blank=True, null=True) ship_to_address_type = models.CharField(max_length=50, blank=True, null=True) ship_date = models.DateTimeField() ship_via = models.CharField(max_length=50, blank=True) shipping = models.DecimalField(max_digits=6, decimal_places=2, default=0) shipping_surcharge = models.DecimalField(max_digits=6, decimal_places=2, default=0) box_and_packing = models.DecimalField(max_digits=6, decimal_places=2, default=0) objects = InvoiceManager() class Meta: # permissions = (("view_invoice", _("Can view invoice")), ) app_label = 'invoices' def __str__(self): return "Invoice %s" % self.pk def set_creator(self, user): """ Sets creator fields. """ self.creator = user self.creator_username = user.username def set_owner(self, user): """ Sets owner fields. """ self.owner = user self.owner_username = user.username def bill_to_user(self, user): """ This method populates all of the bill to fields via info in user and user.profile object. """ self.bill_to = '%s %s' % (user.first_name, user.last_name) self.bill_to = self.bill_to.strip() self.bill_to_first_name = user.first_name self.bill_to_last_name = user.last_name self.bill_to_email = user.email if hasattr(user, 'profile'): profile = user.profile self.bill_to_company = profile.company self.bill_to_phone = profile.phone self.bill_to_fax = profile.fax if profile.is_billing_address or not profile.is_billing_address_2: self.bill_to_address = profile.address self.bill_to_city = profile.city self.bill_to_state = profile.state self.bill_to_zip_code = profile.zipcode self.bill_to_country = profile.country else: self.bill_to_address = profile.address_2 self.bill_to_city = profile.city_2 self.bill_to_state = profile.state_2 self.bill_to_zip_code = profile.zipcode_2 self.bill_to_country = profile.country_2 def ship_to_user(self, user): """ This method populates all of the ship to fields via info in user and user.profile object. """ self.ship_to = '%s %s' % (user.first_name, user.last_name) self.ship_to = self.ship_to.strip() self.ship_to_first_name = user.first_name self.ship_to_last_name = user.last_name self.ship_to_email = user.email if hasattr(user, 'profile'): profile = user.profile self.ship_to_company = profile.company self.ship_to_phone = profile.phone self.ship_to_fax = profile.fax self.ship_to_address_type = profile.address_type if profile.is_billing_address or not profile.is_billing_address_2: self.ship_to_address = profile.address self.ship_to_city = profile.city self.ship_to_state = profile.state self.ship_to_zip_code = profile.zipcode self.ship_to_country = profile.country else: self.ship_to_address = profile.address_2 self.ship_to_city = profile.city_2 self.ship_to_state = profile.state_2 self.ship_to_zip_code = profile.zipcode_2 self.ship_to_country = profile.country_2 def split_title(self): if ": " in self.title: split_title = ': '.join(self.title.split(': ')[1:]) return u'%s' % split_title return self.title def get_absolute_url(self): return reverse('invoice.view', args=[self.id]) def get_absolute_url_with_guid(self): return reverse('invoice.view', args=[self.id, self.guid]) def get_discount_url(self): from tendenci.apps.discounts.models import Discount if self.discount_code: try: discount = Discount.objects.get( discount_code=self.discount_code) return discount.get_absolute_url except Discount.DoesNotExist: return '' return '' def save(self, user=None): """ Set guid, creator and owner if any of these fields are missing. """ self.guid = self.guid or uuid.uuid4().hex if hasattr(user, 'pk') and not user.is_anonymous: self.set_creator(user) self.set_owner(user) # assign entity if not self.entity_id and self.object_type: self.entity = self.get_entity() self.verifydata() super(Invoice, self).save() def verifydata(self): # verify each field for field in Invoice._meta.fields: value = getattr(self, field.name) if field.max_length and value and len(value) > field.max_length: value = value[:field.max_length] setattr(self, field.name, value) def delete(self, *args, **kwargs): """ Invoices are never deleted. Per Ed Schipul 06/05/2013 """ pass def get_entity(self): """ Discover the entity for this invoice. Note that - the entity we're looking for is the entity from the object's group, not the object's entity field. """ entity = None obj = self.get_object() if obj: # an object is associated with a group which ties to an entity group = None if hasattr(obj, 'group'): group = getattr(obj, 'group') if group: entity = group.entity if not entity: entity = getattr(obj, 'entity', None) or Entity.objects.first() return entity def get_object(self): _object = None try: _object = self._object except: pass # exclude the soft deleted object - when an object is soft deleted, # its slug is appended with "@ + object.pk", which causes error on # resolving url (on invoice search and detail pages) because "@" # is not valid in the slug url pattern. if _object and hasattr(_object, 'status') and (not _object.status): _object = None return _object @property def use_third_party_payment(self): obj = self.get_object() if hasattr(obj, 'use_third_party_payment'): return getattr(obj, 'use_third_party_payment') return False @property def external_payment_link(self): obj = self.get_object() if hasattr(obj, 'external_payment_link'): return getattr(obj, 'external_payment_link') return '' def get_donation_amount(self): obj = self.get_object() if obj and hasattr(obj, 'donation_amount'): return obj.donation_amount return None def get_status(self): """ Return status (string) Use status_detail and is_voide attribute """ if self.is_void: return u'void' return self.status_detail @property def graguity_in_percentage(self): return '{:.1%}'.format(self.gratuity) @property def is_tendered(self): boo = False if self.id > 0: if self.status_detail.lower() == 'tendered': boo = True return boo def tender(self, user): """ mark it as tendered if we have records """ if not self.is_tendered: # make accounting entry make_acct_entries(user, self, self.total) self.status_detail = 'tendered' self.status = 1 self.tender_date = datetime.now() self.save() return True # if this invoice allows view by user2_compare def allow_view_by(self, user2_compare, guid=''): if user2_compare.profile.is_superuser: return True if has_perm(user2_compare, 'invoices.view_invoice'): return True if not get_setting("module", "invoices", "disallow_private_urls"): if self.guid == guid: return True obj = self.get_object() if obj and hasattr(obj, 'allow_adjust_invoice_by'): # example: chapter leaders can view/adjust invoices for their chapter memberships. if obj.allow_adjust_invoice_by(user2_compare): return True if user2_compare.is_authenticated: if user2_compare in [self.creator, self.owner] or \ user2_compare.email == self.bill_to_email: return self.status return False def allow_payment_by(self, user2_compare, guid=''): return self.allow_view_by(user2_compare, guid) # if this invoice allows edit by user2_compare def allow_edit_by(self, user2_compare): if not user2_compare.is_authenticated: return False if user2_compare.is_superuser: return True else: if user2_compare and user2_compare.id > 0: if has_perm(user2_compare, 'invoices.change_invoice'): return True obj = self.get_object() if obj and hasattr(obj, 'allow_adjust_invoice_by'): # example: chapter leaders can view/adjust invoices for their chapter memberships. if obj.allow_adjust_invoice_by(user2_compare): return True # if self.creator == user2_compare or \ # self.owner == user2_compare or \ # self.bill_to_email == user2_compare.email: # if self.status: # # user can only edit a non-tendered invoice # if not self.is_tendered: # return True # else: # if self.guid and self.guid == guid: # for anonymous user # if self.status and not self.is_tendered: # return True return False def make_payment(self, user, amount): """ Updates the invoice balance by adding accounting entries. """ if self.is_tendered and self.balance > 0: self.balance -= amount self.payments_credits += amount self.save() # Make the accounting entries here make_acct_entries(user, self, amount) return True return False def void_payment(self, user, amount): self.balance += amount self.payments_credits -= amount self.save() # only void approved and non-zero payments for payment in self.payment_set.filter(status_detail='approved', amount__gt=0): payment.status_detail = 'void' payment.save() # reverse accounting entries make_acct_entries_reversing(user, self, amount) def void(self, user=None): """ Voids invoice. This means the debt is no longer owed. """ if not self.is_void: self.is_void = True self.void_date = datetime.now() self.voided_by = user # set balance to 0 self.balance = 0 self.save() # reverse accounting entries if self.subtotal > 0: make_acct_entries_initial_reversing(user, self, self.subtotal) # def unvoid(self): # """ # Remove 'void' from invoice. This means the invoice is active again. # """ # if self.is_void: # self.is_void = False # self.save() def get_first_approved_payment(self): """ Returns first approved payment in ascending order """ [payment ] = self.payment_set.filter(status_detail='approved')[:1] or [None] return payment
class Invoice(models.Model): guid = models.CharField(max_length=50) object_type = models.ForeignKey(ContentType, blank=True, null=True) object_id = models.IntegerField(default=0, blank=True, null=True) _object = generic.GenericForeignKey('object_type', 'object_id') title = models.CharField(max_length=150, blank=True, null=True) #user creator = models.ForeignKey(User, related_name="invoice_creator", null=True) creator_username = models.CharField(max_length=50, null=True) owner = models.ForeignKey(User, related_name="invoice_owner", null=True) owner_username = models.CharField(max_length=50, null=True) #dates create_dt = models.DateTimeField(auto_now_add=True) due_date = models.DateTimeField() update_dt = models.DateTimeField(auto_now=True) tender_date = models.DateTimeField(null=True) arrival_date_time = models.DateTimeField(blank=True, null=True) #payment status status_detail = models.CharField(max_length=50, default='estimate') status = models.BooleanField(default=True) estimate = models.BooleanField(default=1) payments_credits = models.DecimalField(max_digits=15, decimal_places=2, blank=True, default=0) balance = models.DecimalField(max_digits=15, decimal_places=2, blank=True, default=0) total = models.DecimalField(max_digits=15, decimal_places=2, blank=True) #other variance = models.DecimalField(max_digits=10, decimal_places=4, default=0) variance_notes = models.TextField(max_length=1000, blank=True, null=True) receipt = models.BooleanField(default=0) gift = models.BooleanField(default=0) greeting = models.CharField(max_length=500, blank=True, null=True) instructions = models.CharField(max_length=500, blank=True, null=True) po = models.CharField(max_length=50, blank=True) terms = models.CharField(max_length=50, blank=True) disclaimer = models.CharField(max_length=150, blank=True, null=True) admin_notes = models.TextField(blank=True, null=True) fob = models.CharField(max_length=50, blank=True, null=True) project = models.CharField(max_length=50, blank=True, null=True) other = models.CharField(max_length=120, blank=True, null=True) message = models.CharField(max_length=150, blank=True, null=True) subtotal = models.DecimalField(max_digits=15, decimal_places=2, blank=True) tax_exempt = models.BooleanField(default=1) tax_exemptid = models.CharField(max_length=50, blank=True, null=True) tax_rate = models.FloatField(blank=True, default=0) taxable = models.BooleanField(default=0) tax = models.DecimalField(max_digits=6, decimal_places=4, default=0) #bill/ ship bill_to = models.CharField(max_length=120, blank=True) bill_to_first_name = models.CharField(max_length=100, blank=True, null=True) bill_to_last_name = models.CharField(max_length=100, blank=True, null=True) bill_to_company = models.CharField(max_length=50, blank=True, null=True) bill_to_address = models.CharField(max_length=100, blank=True, null=True) bill_to_city = models.CharField(max_length=50, blank=True, null=True) bill_to_state = models.CharField(max_length=50, blank=True, null=True) bill_to_zip_code = models.CharField(max_length=20, blank=True, null=True) bill_to_country = models.CharField(max_length=50, blank=True, null=True) bill_to_phone = models.CharField(max_length=50, blank=True, null=True) bill_to_fax = models.CharField(max_length=50, blank=True, null=True) bill_to_email = models.CharField(max_length=100, blank=True, null=True) ship_to = models.CharField(max_length=120, blank=True) ship_to_first_name = models.CharField(max_length=50, blank=True) ship_to_last_name = models.CharField(max_length=50, blank=True) ship_to_company = models.CharField(max_length=50, blank=True) ship_to_address = models.CharField(max_length=100, blank=True) ship_to_city = models.CharField(max_length=50, blank=True) ship_to_state = models.CharField(max_length=50, blank=True) ship_to_zip_code = models.CharField(max_length=20, blank=True) ship_to_country = models.CharField(max_length=50, blank=True) ship_to_phone = models.CharField(max_length=50, blank=True, null=True) ship_to_fax = models.CharField(max_length=50, blank=True, null=True) ship_to_email = models.CharField(max_length=100, blank=True, null=True) ship_to_address_type = models.CharField(max_length=50, blank=True, null=True) ship_date = models.DateTimeField() ship_via = models.CharField(max_length=50, blank=True) shipping = models.DecimalField(max_digits=6, decimal_places=2, default=0) shipping_surcharge = models.DecimalField(max_digits=6, decimal_places=2, default=0) box_and_packing = models.DecimalField(max_digits=6, decimal_places=2, default=0) objects = InvoiceManager() class Meta: permissions = (("view_invoice", "Can view invoice"), ) def __unicode__(self): return u'%s' % (self.title) def split_title(self): split_title = ': '.join(self.title.split(': ')[1:]) return u'%s' % split_title # def past_due(self): # if self.object_type == 'registration': # event_date = @models.permalink def get_absolute_url(self): return ('invoice.view', [self.id]) def save(self, user=None): if not self.id: self.guid = str(uuid.uuid1()) if user and user.id: self.creator = user self.creator_username = user.username if user and user.id: self.owner = user self.owner_username = user.username super(Invoice, self).save() def get_object(self): _object = None try: _object = self._object except: pass return _object @property def is_tendered(self): boo = False if self.id > 0: if self.status_detail.lower() == 'tendered': boo = True return boo def tender(self, user): from tendenci.apps.accountings.utils import make_acct_entries """ mark it as tendered if we have records """ if not self.is_tendered: # make accounting entry make_acct_entries(user, self, self.total) self.estimate = False self.status_detail = 'tendered' self.status = 1 self.tender_date = datetime.now() self.save() return True # if this invoice allows view by user2_compare def allow_view_by(self, user2_compare, guid=''): if user2_compare.profile.is_superuser: return True if has_perm(user2_compare, 'invoices.view_invoice'): return True if self.guid == guid: return True if user2_compare.is_authenticated(): if user2_compare in [self.creator, self.owner]: return self.status return False def allow_payment_by(self, user2_compare, guid=''): return self.allow_view_by(user2_compare, guid) # if this invoice allows edit by user2_compare def allow_edit_by(self, user2_compare, guid=''): boo = False if user2_compare.is_superuser: boo = True else: if user2_compare and user2_compare.id > 0: if has_perm(user2_compare, 'invoices.change_invoice'): return True if self.creator == user2_compare or self.owner == user2_compare: if self.status == 1: # user can only edit a non-tendered invoice if not self.is_tendered: boo = True else: if self.guid and self.guid == guid: # for anonymous user if self.status == 1 and not self.is_tendered: boo = True return boo # this function is to make accounting entries def make_payment(self, user, amount): from tendenci.apps.accountings.utils import make_acct_entries if self.is_tendered: self.balance -= amount self.payments_credits += amount self.save() # Make the accounting entries here make_acct_entries(user, self, amount)