def update_invoice_details(self): """Generate a new invoice and link it to this order.""" for validator in [ validators.OrderInStatusValidator( allowed_statuses=(OrderStatus.quote_accepted, )), ]: validator.set_instance(self) validator() self.invoice = Invoice.objects.create_from_order(self) self.save(update_fields=('invoice', ))
def mark_as_paid(self, by, payments_data): """ Mark an order as "Paid". :param by: the adviser who created the record :param payments_data: list of payments data. Each item should at least contain `amount`, `received_on` and `method` e.g. [ { 'amount': 1000, 'method': 'bacs', 'received_on': ... }, { 'amount': 1001, 'method': 'manual', 'received_on': ... } ] """ for order_validator in [ validators.OrderInStatusValidator( allowed_statuses=(OrderStatus.quote_accepted, ), ), ]: order_validator.set_instance(self) order_validator() for payment_validator in [ReconcilablePaymentsValidator()]: payment_validator.set_order(self) payment_validator(data=payments_data) for data in payments_data: Payment.objects.create_from_order(self, by, data) self.status = OrderStatus.paid max_received_on = max(item['received_on'] for item in payments_data) self.paid_on = datetime.combine(date=max_received_on, time=time(tzinfo=utc)) self.save() # send signal order_paid.send(sender=self.__class__, order=self)
def generate_quote(self, by, commit=True): """ Generate a new quote and assign it to the current order. The status of the order changes to "Quote awaiting acceptance". :returns: a quote for this order :param by: who made the action :param commit: if False, the changes will not be saved. Useful for previewing a quote :raises rest_framework.exceptions.ValidationError: in case of validation error :raises datahub.omis.core.exceptions.Conflict: in case of errors with the state of the current order :raises RuntimeError: after trying max_retries times without being able to generate a valid value for the quote reference """ for validator in [ validators.OrderDetailsFilledInValidator(), validators.NoOtherActiveQuoteExistsValidator(), validators.OrderInStatusValidator( allowed_statuses=(OrderStatus.draft, ), ), ]: validator.set_instance(self) validator() self.quote = Quote.objects.create_from_order(order=self, by=by, commit=commit) self.status = OrderStatus.quote_awaiting_acceptance populate_billing_data(self) if commit: self.save() # send signal quote_generated.send(sender=self.__class__, order=self) return self.quote
def accept_quote(self, by): """ Accept quote and change the status of the order to "Quote accepted". :param by: the contact who is accepting the quote """ for validator in [ validators.OrderInStatusValidator(allowed_statuses=( OrderStatus.quote_awaiting_acceptance, ), ), ]: validator.set_instance(self) validator() self.quote.accept(by) self.status = OrderStatus.quote_accepted self.save() # this has to come after saving so that we use the most up-to-date pricing values self.update_invoice_details() # send signal quote_accepted.send(sender=self.__class__, order=self)
def complete(self, by): """ Complete an order. :param by: the adviser who marked the order as complete """ for order_validator in [ validators.OrderInStatusValidator( allowed_statuses=(OrderStatus.paid, ), ), ]: order_validator.set_instance(self) order_validator() for complete_validator in [validators.CompletableOrderValidator()]: complete_validator.set_order(self) complete_validator() self.status = OrderStatus.complete self.completed_on = now() self.completed_by = by self.save() # send signal order_completed.send(sender=self.__class__, order=self)
def reopen(self, by): """ Cancel quote and reopen order if possible. The status of the order changes back to "Draft". :param by: the adviser who is cancelling the quote """ for validator in [ validators.OrderInStatusValidator(allowed_statuses=( OrderStatus.quote_awaiting_acceptance, OrderStatus.quote_accepted, ), ), ]: validator.set_instance(self) validator() if self.quote: self.quote.cancel(by) self.status = OrderStatus.draft self.save() # send signal quote_cancelled.send(sender=self.__class__, order=self, by=by)