def clean_amount(self): from cc3.cyclos import backends available_balance = backends.get_account_status( self.user.username).accountStatus.availableBalance if self.cleaned_data['amount'] > available_balance: raise forms.ValidationError( _(u'You do not have sufficient credit.')) return self.cleaned_data['amount']
def clean_amount(self): from cc3.cyclos import backends # NB need to use availableBalance here really - as overdrafts are # possible. available_balance = backends.get_account_status( self.user.username).accountStatus.availableBalance if self.cleaned_data['amount'] > available_balance: raise forms.ValidationError( _(u'You do not have sufficient credit to complete the payment') ) return self.cleaned_data['amount']
def _classify_balances(self): """ Given a couple of accepted dates and a queryset of all registered ``BusinessProfiles``, retrieves the balance for each business and classifies as currently debtors or creditors. This method is called during the class instantiation. """ # only process businesses with account holder, IBAN, BIC, Mandate and # signature date filled in businesses_to_classify = self.businesses.exclude( iban__isnull=True).exclude(bic_code__isnull=True).exclude( mandate_id__isnull=True).exclude( signature_date__isnull=True).exclude(iban='').exclude( bic_code='').exclude(account_holder='') for business in businesses_to_classify: # ignore in case of exceptions available_balance = None try: available_balance = backends.get_account_status( business.profile.user.username).accountStatus.balance except MemberNotFoundException: LOG.error(u'Member not found (in Cyclos): {0}'.format( business.profile.user.username)) # Store the business and its balance in the correspondent group. # if current balance, ignore business if not available_balance: continue # Cast `available_balance` to `int` and deduct the amount of euros. euros = getattr(settings, 'CC3_CURRENCY_CONVERSION', 100) balance = Decimal(available_balance / euros).quantize( Decimal(10)**-2) if balance > 0: self.credit_transactions[business] = balance self.total_credit_transactions += balance else: # Balances must always be positive. balance = -balance if not business.latest_payment_date: self.debit_transactions['FRST'][business] = balance else: self.debit_transactions['RCUR'][business] = balance self.total_debit_transactions_rcur += balance self.total_debit_transactions += balance business.latest_payment_date = self.date_to business.save()
def validate_amount(self, attrs, source): amount = attrs[source] sender = self.context['user'] available_balance = backends.get_account_status( sender.username).accountStatus.availableBalance if amount > available_balance: raise serializers.ValidationError( _(u'You do not have sufficient credit to complete the payment') ) # TODO: Update to validate integer for systems with integer currencies return attrs
class BulkPurchaseAdminForm(forms.ModelForm): model = BulkPurchase def clean(self): from .utils import get_current_draw from cc3.cyclos import backends # from cc3.cyclos.models import User cd = self.cleaned_data current_draw = get_current_draw() if current_draw is None: raise forms.ValidationError(_(u"There is no current draw, bulk " u"purchases are not available")) if cd['num_tickets'] <= 0: raise forms.ValidationError(_(u"Please enter a number greater than " u"1")) is_business = False try: business_cc3_profile = cd['purchased_by'].get_profile() is_business = business_cc3_profile.is_business_profile() except Exception, e: pass if not is_business: raise forms.ValidationError(_(u"Admin users can only make bulk " u"ticket purchases for Businesses")) # validate user has enough credit available_balance = backends.get_account_status( cd['purchased_by'].username).accountStatus.availableBalance ticket_cost = cd['num_tickets'] * current_draw.ticket_price if ticket_cost > available_balance: raise forms.ValidationError( _(u"You don't have enough credit")) # not currently validating max tickets in draw, so no point doing this: # if cd['num_tickets'] > current_draw.remaining_tickets: # raise forms.ValidationError(_(u"Only {0} tickets left # for draw".format(current_draw.remaining_tickets))) return cd
def balance(request): _balance = upper_credit_limit = lower_credit_limit = None has_account = False if request.user.is_authenticated(): if not request.user.is_superuser: try: # http://www.cyclos.org/wiki/index.php/Web_services#Model_data_details account_status = backends.get_account_status( request.user.username).accountStatus _balance = account_status.balance upper_credit_limit = account_status.upperCreditLimit lower_credit_limit = account_status.creditLimit has_account = True except MemberNotFoundException: LOG.info(u"Member '{0}' not present in Cyclos backend".format( request.user)) has_account = False _balance = None # except ExpatError: # LOG.info(u"Member '{0}' not present in Cyclos backend".format( # request.user)) # has_account = False # _balance = None except ExpatError as e: messages.add_message( request, messages.WARNING, _("Unable to get account " "details at present")) LOG.info(u"Exception {0}".format(e)) has_account = False _balance = None if upper_credit_limit: upper_credit_limit = int(upper_credit_limit) if lower_credit_limit: lower_credit_limit = int(lower_credit_limit) return { 'balance': _balance, 'has_account': has_account, 'upper_credit_limit': upper_credit_limit, 'lower_credit_limit': lower_credit_limit }
def check_user_can_buy_tickets(num_tickets, user, draw=None, check_balance=True): """Check whether a user can buy the requested number of tickets in draw If draw is None, default to the "current" draw """ if not draw: draw = get_current_draw() if not draw: raise TicketException(_(u"There is no Draw in progress")) num_can_buy = draw.max_tickets_user_can_buy(user) if num_can_buy <= 0: raise TicketException( _(u"You have already bought the maximum of {0} tickets".format( draw.max_tickets_per_person))) if num_can_buy < num_tickets: per_person = draw.max_tickets_per_person if num_can_buy < per_person: raise TicketException( _(u"You already have {0} ticket(s), you can buy a maximum of " u"{1} ticket(s) more".format( (per_person-num_can_buy), num_can_buy))) raise TicketException( _(u"You can buy a maximum of {0} tickets".format(num_can_buy))) available_balance = backends.get_account_status( user.username).accountStatus.availableBalance if check_balance: ticket_cost = num_tickets * draw.ticket_price if ticket_cost > available_balance: raise TicketException( _(u"You don't have enough credit")) return True
def reset_balance(self): """ Resets the current user Positoos balance to zero. Taking into account the ``accountStatus.balance`` of the user, it makes a payment from or to the system for a similar amount, turning the balance equal to zero. """ # Getting settings - defaulting to Positoos values if settings missing. debit_transfer_type_id = getattr(settings, 'SEPA_EXPORT_DEBIT_TRANSFER_TYPE_ID', 39) debit_transfer_description = getattr( settings, 'SEPA_EXPORT_DEBIT_TRANSFER_DESCRIPTION', "Bijschrijving na automatisch incasso") credit_transfer_type_id = getattr( settings, 'SEPA_EXPORT_CREDIT_TRANSFER_TYPE_ID', 36) credit_transfer_description = getattr( settings, 'SEPA_EXPORT_CREDIT_TRANSFER_DESCRIPTION', "Afschrijving na automatisch incasso") vat_rate = getattr(settings, 'VAT_RATE', 21) try: balance = backends.get_account_status( self.profile.user.username).accountStatus.balance except MemberNotFoundException: LOG.error(u'Member not found (in Cyclos): {0}'.format( self.profile.user.username)) return False LOG.info(u"Resetting balance for user {0}, current balance {1}".format( self.profile.user.username, balance)) if balance == 0: LOG.info(u"Not resetting balance, no transaction required as " u"balance is already 0") return True try: if balance > 0: # Positive balance. Move the cash from user to the system. # From Organisatie rekening (member) to Reserve account # (system), # Transfer type ID 36. # Transfer Type 'Take out of circulation'. LOG.info(u"Credit transfer, ID: {0}, {1}".format( credit_transfer_type_id, credit_transfer_description)) backends.to_system_payment( self.profile.user.username, balance, credit_transfer_description, transfer_type_id=credit_transfer_type_id) LOG.info( _(u'Monthly balance for business {0} reconciled. {1} ' u'Positoos recovered by Cyclos system'.format( self.profile.user.username, balance))) # biz a/c b # Create euro invoice from Positoos BV (marked unpaid). today = datetime.date.today() currency, created = Currency.objects.get_or_create( code='EUR', defaults={ 'name': 'Euro', 'symbol': '€' }) nr_days_due = getattr(settings, "SEPA_EXPORT_CREDIT_INVOICE_DAYS_DUE", 15) sender, created = User.objects.get_or_create(username=getattr( settings, "CC3_BANK_USER", "Positoos Reserve")) to_be_paid_status = PaymentStatus.objects.filter( is_active=True, is_paid=False) if not to_be_paid_status: LOG.error(u"Payment status with 'is_active' True and " u"'is_paid' False is not defined") return False to_be_paid_status = to_be_paid_status[0] invoice_description = credit_transfer_description invoice_type = "SEPA export" invoice = Invoice.objects.create( from_user=sender, to_user=self.profile.user, inv_date=today, due_date=today + datetime.timedelta(days=nr_days_due), currency=currency, payment_status=to_be_paid_status, automatic_invoice=True, admin_comment=u"Automatic invoice of type {0}".format( invoice_type)) InvoiceLine.objects.create(invoice=invoice, description=invoice_description, quantity=1, amount=balance, tax_rate=vat_rate) else: # Negative balance. Move some cash from system to user. # From Reserve account (system) to Organisatie rekening # (member). # Transfer type ID 39. # Transfer Type 'Acquiring Positoos'. LOG.info(u"Debit transfer, ID: {0}, {1}".format( debit_transfer_type_id, debit_transfer_description)) backends.from_system_payment( self.profile.user.username, -balance, debit_transfer_description, transfer_type_id=debit_transfer_type_id) LOG.info( _(u'Monthly balance for business {0} reconciled. {1} ' u'Positoos paid by Cyclos system'.format( self.profile.user.username, balance))) except TransactionException, e: LOG.error(u'Unable to perform balance reset. The transaction ' u'failed: {0}\nSure the user is a business?'.format(e)) return False
def reset_balance(self): """ Resets the current user Positoos balance to zero. Taking into account the ``accountStatus.balance`` of the user, it makes a payment from or to the system for a similar amount, turning the balance equal to zero. """ # Getting settings - defaulting to Positoos values if settings missing. debit_transfer_type_id = getattr(settings, 'SEPA_EXPORT_DEBIT_TRANSFER_TYPE_ID', 39) debit_transfer_description = getattr( settings, 'SEPA_EXPORT_DEBIT_TRANSFER_DESCRIPTION', "Bijschrijving na automatisch incasso") credit_transfer_type_id = getattr( settings, 'SEPA_EXPORT_CREDIT_TRANSFER_TYPE_ID', 36) credit_transfer_description = getattr( settings, 'SEPA_EXPORT_CREDIT_TRANSFER_DESCRIPTION', "Afschrijving na automatisch incasso") to_date = datetime.date.today() from_date = last_month_first_of_month() div_by = Decimal("100.00") try: balance = backends.get_account_status( self.profile.user.username).accountStatus.balance transactions = backends.transactions( username=self.profile.user.username, from_date=from_date, to_date=to_date) except MemberNotFoundException: LOG.error(u'Member not found (in Cyclos): {0}'.format( self.profile.user.username)) return False LOG.info(u"Resetting balance for user {0}, current balance {1}".format( self.profile.user.username, balance)) if balance == 0: LOG.info(u"Not resetting balance, no transaction required as " u"balance is already 0") return True invoice_description = self.invoice_description( from_date, to_date, transactions, reset_transfer_descriptions=[ debit_transfer_description, credit_transfer_description ]) try: if balance > 0: # Positive balance. Move the cash from user to the system. # From Organisatie rekening (member) to Reserve account # (system), # Transfer type ID 36. # Transfer Type 'Take out of circulation'. LOG.info(u"Credit transfer, ID: {0}, {1}".format( credit_transfer_type_id, credit_transfer_description)) backends.to_system_payment( self.profile.user.username, balance, credit_transfer_description, transfer_type_id=credit_transfer_type_id) LOG.info( _(u'Monthly balance for business {0} reconciled. {1} ' u'Positoos recovered by Cyclos system'.format( self.profile.user.username, balance))) self.create_invoice((balance / div_by) * Decimal("-1.00"), invoice_description) else: # Negative balance. Move some cash from system to user. # From Reserve account (system) to Organisatie rekening # (member). # Transfer type ID 39. # Transfer Type 'Acquiring Positoos'. LOG.info(u"Debit transfer, ID: {0}, {1}".format( debit_transfer_type_id, debit_transfer_description)) backends.from_system_payment( self.profile.user.username, -balance, debit_transfer_description, transfer_type_id=debit_transfer_type_id) LOG.info( _(u'Monthly balance for business {0} reconciled. {1} ' u'Positoos paid by Cyclos system'.format( self.profile.user.username, balance))) self.create_invoice((balance / div_by) * Decimal("-1.00"), invoice_description) except TransactionException, e: LOG.error(u'Unable to perform balance reset. The transaction ' u'failed: {0}\nSure the user is a business?'.format(e)) return False
def test_account_status(self): sender = get_username() email = sender + '@example.com' member = backends.new(sender, 'Sender', email, 'Test Business', USER_GROUP_ID) self.assertIsNotNone(member) receiver = get_username() member = backends.new(receiver, 'Receiver', receiver + '@example.com', 'Test Business', USER_GROUP_ID) self.assertIsNotNone(member) # test initial account status status = backends.get_account_status(sender) self.assertEqual(status.accountStatus.balance, Decimal('0')) self.assertEqual(status.accountStatus.availableBalance, Decimal('0')) self.assertEqual(status.accountStatus.reservedAmount, Decimal('0')) self.assertEqual(status.accountStatus.creditLimit, Decimal('0')) self.assertIsNone(status.accountStatus.upperCreditLimit) status = backends.get_account_status(receiver) self.assertEqual(status.accountStatus.balance, Decimal('0')) self.assertEqual(status.accountStatus.availableBalance, Decimal('0')) self.assertEqual(status.accountStatus.reservedAmount, Decimal('0')) self.assertEqual(status.accountStatus.creditLimit, Decimal('0')) self.assertIsNone(status.accountStatus.upperCreditLimit) # set credit limit limit = 10000.0 self._set_credit_limit(email, limit) status = backends.get_account_status(sender) self.assertEqual(status.accountStatus.balance, Decimal('0')) self.assertEqual(status.accountStatus.availableBalance, Decimal(limit)) self.assertEqual(status.accountStatus.reservedAmount, Decimal('0')) self.assertEqual(status.accountStatus.creditLimit, Decimal(limit)) self.assertIsNone(status.accountStatus.upperCreditLimit) # transact amount = 10.00 description = 'a test transaction' transaction = backends.user_payment(sender, receiver, amount, description) self.assertIsNotNone(transaction) status = backends.get_account_status(sender) self.assertEqual(status.accountStatus.balance, Decimal(amount * -1.0)) self.assertEqual(status.accountStatus.availableBalance, Decimal(limit - amount)) self.assertEqual(status.accountStatus.reservedAmount, Decimal('0')) self.assertEqual(status.accountStatus.creditLimit, Decimal(limit)) self.assertIsNone(status.accountStatus.upperCreditLimit) status = backends.get_account_status(receiver) self.assertEqual(status.accountStatus.balance, Decimal(amount)) self.assertEqual(status.accountStatus.availableBalance, Decimal(amount)) self.assertEqual(status.accountStatus.reservedAmount, Decimal('0')) self.assertEqual(status.accountStatus.creditLimit, Decimal('0')) self.assertIsNone(status.accountStatus.upperCreditLimit)