def get_currency_or_default(self): if self.request and self.request.user.is_authenticated: client = self.request.user.clients.first() if client: currency = client.currency else: currency = get_default_currency() else: currency = get_default_currency() return currency
def validate(self, attrs): # NOTE(tomo): Validate cycle is unique value = attrs.get('value') option = attrs.get('option') cycle = attrs.get('cycle') cycle_multiplier = attrs.get('cycle_multiplier') currency = attrs.get('currency') if not currency: raise serializers.ValidationError(detail=_('Currency is required')) extra_attrs = {} if value: extra_attrs['value'] = value elif option: extra_attrs['option'] = option else: extra_attrs['value__isnull'] = True extra_attrs['option__isnull'] = True exist_query = ConfigurableOptionCycle.objects if self.instance: # We edit the same instance, exclude it from query exist_query = exist_query.exclude(pk=self.instance.pk) if exist_query.filter(cycle=cycle, cycle_multiplier=cycle_multiplier, currency=currency, **extra_attrs).exists(): raise serializers.ValidationError(detail='Similar cycle already exists') # End cycle unique validation relative_pricing = attrs.get('is_relative_price', False) if relative_pricing: # Check if relative pricing is sent, modify pricing if we have a similar cycle in default currency # or just raise default_currency = get_default_currency() if attrs['currency'] != default_currency: def_cycle = ConfigurableOptionCycle.objects.filter( option=option, cycle=cycle, cycle_multiplier=cycle_multiplier, currency=default_currency ).first() if def_cycle is None: raise serializers.ValidationError(detail=_('Unable to auto calculate prices')) converted_price = utils.convert_currency(price=def_cycle.price, from_currency=def_cycle.currency, to_currency=attrs['currency']) attrs['price'] = utils.cdecimal(converted_price, q='.01') converted_setup_fee = utils.convert_currency(price=def_cycle.setup_fee, from_currency=def_cycle.currency, to_currency=attrs['currency']) attrs['setup_fee'] = utils.cdecimal(converted_setup_fee, q='.01') return attrs
def validate(self, attrs): attrs = super(StaffProductCycleSerializer, self).validate(attrs) cycle = attrs.get('cycle') cycle_multiplier = attrs.get('cycle_multiplier') auto_calculate_price = attrs.get('is_relative_price', False) cycle_currency_code = attrs.get('currency') cycle_product = attrs.get('product') if cycle_product: # do not allow one-time cycles to go with recurring cycles other_cycles = ProductCycle.objects.filter(product=cycle_product) if cycle == CyclePeriods.onetime: for other_cycle in other_cycles: # type: ProductCycle if other_cycle.cycle != CyclePeriods.onetime: raise serializers.ValidationError(detail=_( 'Cannot add one time cycle if the product has a recurring cycle.' )) else: # treat the case when the new cycle is a recurring one for other_cycle in other_cycles: # type: ProductCycle if other_cycle.cycle == CyclePeriods.onetime: raise serializers.ValidationError(detail=_( 'Cannot add recurring cycle if the product has a one time cycle.' )) if auto_calculate_price and cycle_product: # auto calculate prices default_currency = get_default_currency() if default_currency.code != cycle_currency_code: def_cycle = ProductCycle.objects.filter( product=cycle_product, cycle=cycle, cycle_multiplier=cycle_multiplier, currency=default_currency).first() if def_cycle is None: c_msg = _( 'A cycle with {} currency is required to auto calculate price' ).format(default_currency) raise serializers.ValidationError(detail=c_msg) converted_price = utils.convert_currency( price=def_cycle.fixed_price, from_currency=def_cycle.currency, to_currency=cycle_currency_code) attrs['fixed_price'] = utils.cdecimal(converted_price, q='.01') converted_setup_fee = utils.convert_currency( price=def_cycle.setup_fee, from_currency=def_cycle.currency, to_currency=cycle_currency_code) attrs['setup_fee'] = utils.cdecimal(converted_setup_fee, q='.01') return attrs
def create_cart(request) -> FleioCart: cart_session_id = str(uuid4()) cart_data = {} cart_metadata = OrderMetadata.from_request(request).to_json() if request.user.is_authenticated: cart_data['user'] = request.user.pk user_client = request.user.clients.first() if user_client: cart_data['client'] = user_client.pk cart_data['currency'] = user_client.currency.code if cart_data.get('currency') is None: cart_data['currency'] = get_default_currency().code cart_serializer = CartSerializer(data=cart_data) cart_serializer.is_valid(raise_exception=True) cart = cart_serializer.save(metadata=cart_metadata, storage_id=cart_session_id) request.session[CART_SESSION_KEY] = cart_session_id return cart
def create_options(self, request): del request # unused default_currency = get_default_currency() # type: Currency create_options = { 'countries': get_countries(), 'currencies': [currency.code for currency in Currency.objects.all()], 'default_currency': default_currency.code if default_currency else None, 'custom_fields': ClientCustomFieldDefinition().definition, 'max_email_attachment_size': settings.MAX_EMAIL_ATTACHMENT_SIZE, 'email_variables': [ '{}{}{}'.format('{{ ', name, ' }}') for name in self.get_email_variables() ], } return Response(create_options)
def client_credit_post_save_callback(sender, instance: ClientCredit, **kwargs): # if a client credit is created or updated maybe credit is enough to resume client if it was suspended LOG.debug('Client credit post save callback invoked by {}'.format(sender)) client = instance.client billing_settings = client.billing_settings created = kwargs.get('created', False) if created: if billing_settings.client_initial_credit > 0: default_currency = get_default_currency() monetary_amount = MonetaryAmount( value=Decimal(billing_settings.client_initial_credit), currency=default_currency, ) destination_amount = monetary_amount.get_value_in_currency(currency=client.currency) client.add_credit( amount=destination_amount, currency=client.currency ) Journal.objects.create( client_credit=instance, transaction=None, source_currency=default_currency, destination_currency=client.currency, source=JournalSources.staff, destination=JournalSources.credit, source_amount=billing_settings.client_initial_credit, destination_amount=destination_amount ) if billing_settings.auto_resume_client_on_credit_update: client_operations = ClientOperations(client) client_operations.update_usage(skip_collecting=True) if client.status == ClientStatus.suspended: client_operations.evaluate_and_resume_if_enough_credit()
def pay_from_credit_balance(self, request, pk): invoice = self.get_object() if invoice.is_credit_invoice(): # NOTE(tomo): do not allow payment from credit balance if this is a credit invoice return Response( {'detail': _('Unable to pay a credit invoice with credit')}, status=HTTP_409_CONFLICT) if not invoice.is_unpaid(): # NOTE(tomo): only unpaid invoices should be allowed return Response( {'detail': _('Only unpaid invoices can be paid from credit')}, status=HTTP_409_CONFLICT) invoice_has_default_currency = True if invoice.currency.code == get_default_currency( ).code else False if not invoice_has_default_currency: try: credit_balance = invoice.client.credits.get( currency=invoice.currency).amount except ClientCredit.DoesNotExist as e: LOG.error(e) credit_balance = 0 else: credit_balance = invoice.client.uptodate_credit if credit_balance <= 0: return Response({'detail': _('Not enough credit')}, status=HTTP_409_CONFLICT) invoice_balance = invoice.balance # don't allow payment if the remaining credit (only for up to date credit in default currency) will be less # than the minimum specified in client's configuration after paying the invoice if invoice_has_default_currency: min_credit_to_be_left = invoice.client.billing_settings.minim_uptodate_credit_for_invoice_payment not_enough_credit_response = Response(data={ 'detail': _('You should have at least {} {} credit left after making a payment' ).format(min_credit_to_be_left, invoice.client.currency) }, status=HTTP_409_CONFLICT) if credit_balance >= invoice_balance: if credit_balance - invoice_balance < min_credit_to_be_left: return not_enough_credit_response elif min_credit_to_be_left > 0: return not_enough_credit_response amount = 0 if invoice_balance >= credit_balance > 0: amount = credit_balance elif credit_balance > invoice_balance > 0: amount = invoice_balance currency_code = invoice.client.currency.code tasks.invoice_add_payment.delay( invoice.id, amount=amount, currency_code=currency_code, from_credit_balance=True, user_id=request.user.pk, create_todo=invoice.client.billing_settings. create_todo_on_invoice_payment, ) return Response( { 'detail': _('Adding {} {} to invoice'.format(amount, currency_code)) }, status=HTTP_202_ACCEPTED)
def get_domain_registrar_prices(domain: Domain, registrar: Registrar, years=None) -> SimpleNamespace or None: """Get the registrar prices for a domain""" # TODO(tomo): Check if domain is premium if years is None: years = domain.registration_period tld_name = domain.tld.name default_currency = get_default_currency() register_price = None transfer_price = None renew_price = None response = RegistrarPrices.objects.filter( tld_name=tld_name, connector=registrar.connector) if years > 1: # If we need a higher number of years, check if we have the answer cached # otherwise we need to calculate it response = response.filter(Q(years=1) | Q(years=years)) # Prices can be in multiple currencies and with different years. At least for 1 year we should have the price price_currency_match = None for db_price in response: if db_price.currency == default_currency.code: if db_price.years == years: price_currency_match = db_price elif db_price.years == 1 and not price_currency_match: price_currency_match = db_price price_years_match = None if not price_currency_match: for db_price in response: if db_price.years == years: price_years_match = db_price elif db_price.years == 1 and not price_years_match: price_years_match = db_price if price_currency_match: if price_currency_match.years != years: register_price = cdecimal(price_currency_match.register_price * years) renew_price = cdecimal(price_currency_match.renew_price * years) transfer_price = cdecimal(price_currency_match.transfer_price ) # Transfers are on 1 year only else: register_price = cdecimal(price_currency_match.register_price) renew_price = cdecimal(price_currency_match.renew_price) transfer_price = cdecimal(price_currency_match.transfer_price) elif price_years_match: if price_years_match.years != years: pre_register_price = cdecimal( price_years_match.register_price * years) pre_renew_price = cdecimal(price_years_match.renew_price * years) pre_transfer_price = cdecimal(price_years_match.transfer_price ) # Transfers are on 1 year only else: pre_register_price = cdecimal(price_years_match.register_price) pre_renew_price = cdecimal(price_years_match.register_price) pre_transfer_price = cdecimal(price_years_match.register_price) try: tld_currency = Currency.objects.get( code=price_years_match.currency) except Currency.DoesNotExist: LOG.error( 'Registry currency {} does not exist in Fleio'.format( price_years_match.currency)) return None register_price = convert_currency(price=pre_register_price, from_currency=tld_currency, to_currency=default_currency) renew_price = convert_currency(price=pre_renew_price, from_currency=tld_currency, to_currency=default_currency) transfer_price = convert_currency(price=pre_transfer_price, from_currency=tld_currency, to_currency=default_currency) if register_price or renew_price or transfer_price: tld_prices = SimpleNamespace() tld_prices.register_price = cdecimal(register_price) tld_prices.renew_price = cdecimal(renew_price) tld_prices.transfer_price = cdecimal(transfer_price) tld_prices.currency = default_currency.code return tld_prices else: return None
def get_report_currency(): def_c = get_default_currency() if not def_c: return 'USD' else: return def_c.code