def create_reseller_service(self, request, pk): del pk # unused # TODO - #1019: implement proper creation of service here serializer = StaffCreateServiceSerializer(data=request.data) serializer.is_valid(raise_exception=True) client = self.get_object() reseller_resources = client_reseller_resources(client=client) if reseller_resources is not None: raise ForbiddenException( {'detail': _('Client already has a reseller service')}) reseller_product = Product.objects.get( id=serializer.validated_data['product_id']) reseller_product_cycle = reseller_product.cycles.filter( id=serializer.validated_data['product_cycle_id'])[0] service = Service.objects.create( client=client, product=reseller_product, cycle=reseller_product_cycle, display_name='Reseller service', status=ServiceStatus.active, ) module_factory.get_module_instance(service=service).create( service=service) return Response({'detail': _('Ok')})
def update_usage(self, skip_collecting: bool = False, skip_compute_current: bool = False): if not skip_collecting: usage_settings = UsageSettings( billing_settings=self.billing_settings) # compute total unpaid usage for all services associated with the client LOG.debug('Updating usage for client {}'.format(self.client)) for service in self.client.services.all(): billing_module = module_factory.get_module_instance( service=service) billing_module.collect_usage(service=service, usage_settings=usage_settings) if not skip_compute_current: # compute current client usage self.__client_usage = self.__compute_client_usage() # update uptodate credit for client uptodate_credit = cdecimal( self.client.get_remaining_credit(self.client_usage.unpaid_usage, self.client.currency.code)) self.client.set_uptodate_credit(uptodate_credit=uptodate_credit) self.update_outofcredit_status() # log to summary self.summary.update_uptodate_credit(self.uptodate_credit)
def create_service_for_item(item): try: if not validate_services_limit(): raise APIBadRequest( _('Failed to create service, please contact support'), ) with transaction.atomic(): service = Service.objects.create(client=item.order.client, display_name=item.name, product=item.product, cycle=item.cycle, status=ServiceStatus.pending, next_due_date=utcnow(), plugin_data=item.plugin_data, domain_name=item.domain_name) for config_option in item.configurable_options.all(): service.configurable_options.create( option=config_option.option, option_value=config_option.option_value, quantity=config_option.quantity, has_price=config_option.has_price, taxable=config_option.taxable, price=config_option.price, unit_price=config_option.unit_price, setup_fee=config_option.setup_fee) billing_module = module_factory.get_module_instance( service=service) if not billing_module.initialize(service=service): raise BillingError(_('Failed to initialize service')) except BillingError: # failed to initialize service # TODO: see what action should we take here pass else: item.service = service item.save(update_fields=['service'])
def renew_service(self, service_id, **kwargs): del self, kwargs # unused service = Service.objects.get(pk=service_id) service_module = module_factory.get_module_instance(service=service) result = service_module.renew(service=service) return result
def change_product_service(service_id, product_id, cycle_id, configurable_options): product = Product.objects.get(pk=product_id) cycle = ProductCycle.objects.get(pk=cycle_id) with transaction.atomic(): service = Service.objects.select_for_update().get(pk=service_id) previous_due_date = service.get_previous_due_date() service_module = module_factory.get_module_instance(service=service) # Update configurable options for opt in configurable_options: try: opt['option'] = ConfigurableOption.objects.get(pk=opt['option']) except ConfigurableOption.DoesNotExist: continue existing_opt = service.configurable_options.filter(option=opt['option']).first() if not existing_opt: service.configurable_options.create(**opt) else: if opt['option'].widget == 'yesno' and opt['option_value'] == 'no': service.configurable_options.filter(option=opt['option']).delete() else: service.configurable_options.filter(option=opt['option']).update(**opt) service.product = product service.cycle = cycle service.override_price = None # Disable overridden price if it exists since we upgraded the product service.display_name = product.name service.update_next_invoice_date(previous_due_date=previous_due_date) service.update_next_due_date(previous_due_date=previous_due_date) service.save() # Set configurable options here result = service_module.change_product(service=service) service.task = None service.save(update_fields=['task']) return result
def get_dynamic_price_for_service(service: Service, end_datetime: datetime) -> Decimal: LOG.info('Getting dynamic price for service {}'.format(service)) try: billing_module = module_factory.get_module_instance(service=service) unsettled_usage = billing_module.get_unsettled_usage(service, end_datetime) return cdecimal(unsettled_usage.total_cost) except ModuleNotFoundException: return Decimal(0)
def create_service(self, service_id, **kwargs): del self, kwargs # unused service = Service.objects.get(pk=service_id) service_module = module_factory.get_module_instance(service=service) result = service_module.create(service=service) if result: service.set_active() return service.id
def reset_usage(self): # call reset usage for all services for service in self.client.services.all(): billing_module = module_factory.get_module_instance( service=service) billing_module.reset_usage(service=service) # recalculate usage after reset self.update_usage()
def get_unsettled_periods(client: Client): services_unsettled_periods = [] for service in client.services.all(): billing_module = module_factory.get_module_instance( service=service) service_unsettled_periods = billing_module.get_service_unsettled_periods( service=service) services_unsettled_periods = services_unsettled_periods + service_unsettled_periods return ClientUnsettledHistorySerializer(services_unsettled_periods, many=True).data
def destroy(self, request, *args, **kwargs): service = self.get_object() if service.client.billing_settings.suspend_instead_of_terminate or reseller_suspend_instead_of_terminate( client=service.client, ): if self.request.query_params.get('delete_associated_resources', 'false') == 'true': tasks.suspend_service.delay( service_id=service.id, reason=ServiceSuspendType.SUSPEND_REASON_TERMINATE_DISABLED, suspend_type=ServiceSuspendType.staff, ) return Response( { 'detail': _('Suspend instead of terminate is enabled for the client. Suspending service.') }, status=status.HTTP_202_ACCEPTED ) else: return Response( {'detail': _('Suspend instead of terminate is enabled for the client, service not deleted.')}, status=status.HTTP_403_FORBIDDEN ) else: if self.request.query_params.get('delete_associated_resources', 'false') == 'true': billing_module = module_factory.get_module_instance(service=service) delete_task = billing_module.prepare_delete_task(service=service, user_id=request.user.id) celery.chain( delete_task, tasks.delete_service_from_database.si(service_id=service.id) ).apply_async() return Response( {'detail': _('Delete in progress.')}, status=status.HTTP_202_ACCEPTED ) else: if service.status in [ ServiceStatus.terminated, ServiceStatus.canceled, ServiceStatus.pending, ServiceStatus.fraud ]: tasks.delete_service_from_database.si(service_id=service.id).apply_async() return Response( {'detail': _('Delete in progress.')}, status=status.HTTP_202_ACCEPTED ) else: return Response( { 'detail': _('Cannot delete service with active resources, terminate service first.') }, status=status.HTTP_403_FORBIDDEN )
def get_cloud_summary(self, request, pk): del request, pk # unused client = self.get_object() if client.first_project is None: return Response({}) # TODO - #1020: iterate over all services and get usage summary for all service = client.first_project.service billing_module = module_factory.get_module_instance(service=service) summary = billing_module.get_usage_summary(service=service) return Response(summary)
def reset_usage(self, service: Service) -> bool: LOG.debug('{} reset_usage called for service {}:{}'.format( self.module_name, service.id, service)) for reseller_client in filter_queryset_for_client( queryset=Client.objects, client=service.client).all(): for client_service in reseller_client.services.all(): service_module = module_factory.get_module_instance( service=client_service, reseller_usage=True) service_module.reset_usage() return True
def suspend_service(self, service_id, reason, suspend_type=None, **kwargs): del self, kwargs # unused service = Service.objects.get(pk=service_id) LOG.debug('Suspending service {} for client {} ({})'.format( service_id, service.client.name, service.client.id, )) service_module = module_factory.get_module_instance(service=service) result = service_module.suspend(service=service, reason=reason) if result: service.set_suspended(reason=reason, suspend_type=suspend_type) return result
def get_unpaid_usage(self, service: Service) -> ServiceUsage: LOG.debug('{} get_unpaid_usage called for service {}:{}'.format( self.module_name, service.id, service)) service_usage = ServiceUsage(total_cost=Decimal('0.00')) for reseller_client in filter_queryset_for_client( queryset=Client.objects, client=service.client).all(): for client_service in reseller_client.services.all(): service_module = module_factory.get_module_instance( service=client_service, reseller_usage=True) service_usage = service_usage + service_module.get_unpaid_usage( service=client_service, ) return service_usage
def update_billing_plan(self, request, pk): del pk # unused if not staff_active_features.is_enabled('openstack.plans'): raise APIBadRequest(detail=_('Cannot update os plan because openstack plans feature is disabled')) service = self.get_object() # type: Service if service.status in [ ServiceStatus.terminated, ServiceStatus.canceled, ServiceStatus.fraud ]: raise APIBadRequest(_('Cannot change pricing plan for service in this state.')) new_plan_id = request.data.get('plan') billing_module = module_factory.get_module_instance(service=service) billing_module.change_pricing_plan(service=service, new_plan_id=new_plan_id) return Response({'detail': _('Pricing plan updated')})
def mark_billing_histories_as_invoiced(self, request): """Method called from external module (fleio-whmcs) to mark billing histories as invoiced""" client_external_billing_id = request.data.get('client_external_billing_id', None) if not client_external_billing_id: raise APIBadRequest(_('Client external billing id is required to fulfill this request.')) try: client = Client.objects.get(external_billing_id=client_external_billing_id) except Client.DoesNotExist: raise APIBadRequest(_('Could not find client related to given external billing id.')) for service in client.services.all(): billing_module = module_factory.get_module_instance(service=service) # this will mark unsettled service dynamic usage histories to invoiced billing_module.get_unsettled_usage(service=service, end_datetime=utcnow()) return Response({ 'detail': _('Successfully marked client {} billing histories states as invoiced.').format(client.id) })
def get_estimated_usage(self, service: Service, usage_settings: UsageSettings) -> EstimatedUsage: LOG.debug('{} get_estimated_usage called for service {}:{}'.format( self.module_name, service.id, service)) estimated_usage = EstimatedUsage() for reseller_client in filter_queryset_for_client( queryset=Client.objects, client=service.client).all(): for client_service in reseller_client.services.all(): service_module = module_factory.get_module_instance( service=client_service, reseller_usage=True) estimated_usage = estimated_usage + service_module.get_estimated_usage( service=client_service, usage_settings=usage_settings, ) return estimated_usage
def __compute_client_usage(self) -> ClientUsage: # compute total unpaid usage for all services associated with the client LOG.debug('Computing total usage for client {}'.format(self.client)) total_unpaid_usage = Decimal(0) total_estimated_usage = EstimatedUsage() usage_settings = UsageSettings(billing_settings=self.billing_settings) for service in self.client.services.all(): billing_module = module_factory.get_module_instance( service=service) # get unpaid usage from billing module unpaid_usage = billing_module.get_unpaid_usage(service) total_unpaid_usage += unpaid_usage.total_cost if service.status == ServiceStatus.active: # get unpaid usage from service if service.next_due_date is not None and service.next_due_date < self.reference_datetime: total_unpaid_usage += service.get_fixed_price() # see if we need to get estimated usage from billing module if not service.is_price_overridden: # get estimated usage from billing module estimated_usage = billing_module.get_estimated_usage( service, usage_settings=usage_settings) total_estimated_usage += estimated_usage # add service static price if needed if service.get_fixed_price() > 0: service_fixed_usage = EstimatedUsage.create_for_fixed_price( fixed_price=service.get_fixed_price(), cycle_end_date=service.next_due_date, get_next_end_date=lambda previous_end_date, s=service: s.get_next_due_date(previous_end_date), usage_settings=usage_settings) total_estimated_usage += service_fixed_usage return ClientUsage(total_unpaid_usage, total_estimated_usage)
def accept(self, request: Request, pk) -> Response: del pk # unused order = self.get_object() can_accept = True messages = [] for item in order.items.all(): if item.service: billing_module = module_factory.get_module_instance(service=item.service) can_accept_service, message = billing_module.can_accept_order(service=item.service) can_accept = can_accept and can_accept_service if not can_accept_service: messages.append(message) if can_accept: order_accept.delay(order.id, user_id=request.user.pk) return Response({'detail': 'Accepted'}, status=HTTP_202_ACCEPTED) else: return Response( { 'detail': 'Cannot accept order', 'messages': messages }, status=HTTP_422_UNPROCESSABLE_ENTITY, )
def terminate_client(self, client_id: int, user_id: Optional[int] = None, delete_all_resources: Optional[bool] = False): del self # unused client = Client.objects.get(id=client_id) # type: Client if client.billing_settings.suspend_instead_of_terminate or reseller_suspend_instead_of_terminate( client=client): raise Exception( 'Terminate client called when suspend instead of terminate is true' ) # delete all services for client delete_services_tasks = [] for service in client.services.all(): billing_module = module_factory.get_module_instance(service=service) if delete_all_resources: delete_services_tasks.append( celery.chain( billing_module.prepare_delete_task(service=service, user_id=user_id), service_tasks.delete_service_from_database.si( service_id=service.id))) else: delete_services_tasks.append( service_tasks.delete_service_from_database.si( service_id=service.id)) if len(delete_services_tasks): final_chord = celery.group( delete_services_tasks) | delete_client_from_database.si( client_id=client_id) celery.chain(final_chord).apply_async() else: delete_client_from_database.delay(client_id=client_id)
def terminate_service(self, service_id, cancellation_request_id=None, **kwargs): del self, kwargs # unused service = Service.objects.get(pk=service_id) service_module = module_factory.get_module_instance(service=service) if service.client.billing_settings.suspend_instead_of_terminate or reseller_suspend_instead_of_terminate( client=service.client, ): LOG.info('Suspend instead of terminate is active, will suspend the service {}'.format(service_id)) result = service_module.suspend( service=service, reason=ServiceSuspendType.SUSPEND_REASON_TERMINATE_DISABLED, suspend_type=ServiceSuspendType.staff ) if result: service.set_suspended( reason=ServiceSuspendType.SUSPEND_REASON_TERMINATE_DISABLED, suspend_type=ServiceSuspendType.staff ) else: LOG.info('Service will be terminated: {}'.format(service_id)) service_module.prepare_delete_task(service=service).apply() service.set_terminated(cancellation_request_id=cancellation_request_id) return service.id
def get_client_revenue(client: Client, start_date: datetime.datetime, end_date: datetime.datetime): """Get all client revenue that should be included in the report""" services_report = {} report = { 'client': client.id, 'client_display_name': client.long_name, 'services_report': services_report, 'credit_in': decimal.Decimal('0.00'), 'credit_out': decimal.Decimal('0.00'), 'credit_available': decimal.Decimal('0.00') } client_main_credit_account = client.credits.filter( currency=client.currency).first() if client_main_credit_account: # set the last available credit for the given period last_journal_entry = Journal.objects.filter( Q(date_added__lt=end_date) & (Q(client_credit=client_main_credit_account) | Q(invoice__client=client))).order_by('date_added').last() if (last_journal_entry and last_journal_entry.client_credit_left and last_journal_entry.client_credit_left_currency.code == client_main_credit_account.currency.code): report[ 'credit_available'] = last_journal_entry.client_credit_left else: # TODO(manu): This conditional branch will not work when re-generating for older months if a fleio # installation exists from a longer time (there are no journal entries that report the credit_ # available after that journal entry). To fix this, calculate client_credit_left for each journal # entry since beginning of time in a migration report['credit_available'] = client_main_credit_account.amount # Add each service to the report and it's usage details given by it's billing module # if available. for service in client.services.filter( Q(terminated_at__isnull=True) | Q(terminated_at__lt=end_date)): fixed_monthly_price = cdecimal( service.get_fixed_price(), q='.01') # returns fixed or overriden price services_report[service.id] = { 'service_name': service.display_name, 'service_id': service.id, 'service_type': service.product.product_type, 'service_last_cycle': JournalReport._get_next_due_date(service=service, until_date=end_date), 'entries': [], 'fixed_monthly_price': fixed_monthly_price, # fixed or overriden price 'price_overridden': service.is_price_overridden, 'total_revenue': decimal.Decimal('0.00'), 'total_from_credit': decimal.Decimal('0.00') } # Get the report module for each service if it exists, in order to get a detailed location usage service_module = module_factory.get_module_instance( service=service) services_report[service.id][ 'usage_details'] = service_module.get_service_report( service, start_date, end_date) # Gather journal entries and split out credit and direct service payments through invoices if client_main_credit_account: # All credit entries that need to appear on the report credit_qs = Journal.objects.filter( date_added__gte=start_date, date_added__lt=end_date, client_credit=client_main_credit_account) credit_in_qs = credit_qs.filter(destination=JournalSources.credit, source__in=[ JournalSources.external, JournalSources.transaction ]) credit_in_qs = credit_in_qs.aggregate( dest_amount=Coalesce(models.Sum('destination_amount'), 0)) credit_amount_in = credit_in_qs.get('dest_amount', 0) credit_out_qs = credit_qs.filter(source=JournalSources.credit, destination__in=[ JournalSources.external, JournalSources.transaction ]) credit_out_qs = credit_out_qs.aggregate( source_amount=Coalesce(models.Sum('source_amount'), 0)) credit_amount_out = credit_out_qs.get('source_amount', 0) report['credit_in'] += credit_amount_in report['credit_out'] += credit_amount_out # Revenue from invoices: invoice_journal_qs = Journal.objects.filter( invoice__client=client, date_added__gte=start_date, date_added__lt=end_date).order_by('date_added') invoice_journal_qs = invoice_journal_qs.filter( Q(source=JournalSources.invoice, destination__in=[ JournalSources.external, JournalSources.transaction ]) | Q(destination=JournalSources.invoice, source__in=[ JournalSources.external, JournalSources.transaction, JournalSources.staff, ])).all() for journal_entry in invoice_journal_qs: invoice = journal_entry.invoice items_percent = JournalReport.get_invoice_items_percent( invoice=invoice) for item in invoice.items.all(): if item.service: if item.service.id in services_report: if items_percent[item.id]['percent'] != 0: amount = items_percent[item.id][ 'percent'] / 100 * journal_entry.destination_amount taxamt = items_percent[item.id][ 'taxes_percent'] / 100 * journal_entry.destination_amount amount -= taxamt if journal_entry.destination in [ JournalSources.transaction, JournalSources.external ]: amount = -1 * amount amount = cdecimal(amount, q='.01') taxamt = cdecimal(taxamt, q='.01') services_report[item.service.id]['entries'].append( { 'amount': amount, 'item_type': item.item_type, 'from_credit': False, 'taxes_amount': taxamt, 'taxes_percent': items_percent[item.id]['taxes_percent'], 'source': journal_entry.source, 'date': str(journal_entry.date_added) }) services_report[ item.service.id]['total_revenue'] += amount else: amount = items_percent[item.id][ 'percent'] / 100 * journal_entry.destination_amount taxamt = items_percent[item.id][ 'taxes_percent'] / 100 * journal_entry.destination_amount amount -= taxamt if journal_entry.destination in [ JournalSources.transaction, JournalSources.external ]: amount = -1 * amount amount = cdecimal(amount, q='.01') taxamt = cdecimal(taxamt, q='.01') services_report[item.service.id] = { 'entries': [{ 'amount': amount, 'item_type': item.item_type, 'from_credit': False, 'taxes_amount': taxamt, 'taxes_percent': items_percent[item.id]['taxes_percent'], 'source': journal_entry.source, 'date': str(journal_entry.date_added) }], 'service': item.service.display_name, 'total_revenue': amount, 'total_from_credit': decimal.Decimal('0.00') } # Credit entries for each service cservice_qs = Journal.objects.filter( date_added__gte=start_date, date_added__lt=end_date, client_credit=client_main_credit_account) cservice_qs = cservice_qs.filter( Q(source=JournalSources.credit, destination=JournalSources.invoice) | Q(source=JournalSources.invoice, destination=JournalSources.credit)).all() for journal_entry in cservice_qs: invoice = journal_entry.invoice items_percent = JournalReport.get_invoice_items_percent( invoice=invoice) for item in invoice.items.all(): if item.service: if item.service.id in services_report: if items_percent[item.id]['percent'] != 0: amount = items_percent[item.id][ 'percent'] / 100 * journal_entry.destination_amount taxamt = items_percent[item.id][ 'taxes_percent'] / 100 * journal_entry.destination_amount amount -= taxamt if journal_entry.destination == JournalSources.credit: amount = -1 * amount amount = cdecimal(amount, q='.01') taxamt = cdecimal(taxamt, q='.01') credit_entries = services_report[ item.service.id]['entries'] credit_entries.append({ 'amount': amount, 'item_type': item.item_type, 'from_credit': True, 'taxes_amount': taxamt, 'taxes_percent': items_percent[item.id]['taxes_percent'], 'source': journal_entry.source, 'date': str(journal_entry.date_added) }) services_report[ item.service.id]['total_revenue'] += amount services_report[ item.service.id]['total_from_credit'] += ( amount + taxamt) else: amount = items_percent[item.id][ 'percent'] / 100 * journal_entry.destination_amount taxamt = items_percent[item.id][ 'taxes_percent'] / 100 * journal_entry.destination_amount amount -= taxamt if journal_entry.destination == JournalSources.credit: amount = -1 * amount amount = cdecimal(amount, q='.01') taxamt = cdecimal(taxamt, q='.01') credit_entries = [{ 'amount': amount, 'item_type': item.item_type, 'from_credit': True, 'taxes_amount': taxamt, 'taxes_percent': items_percent[item.id]['taxes_percent'], 'source': journal_entry.source, 'date': str(journal_entry.date_added) }] services_report[item.service.id] = { 'entries': credit_entries, 'service': item.service.display_name, 'total_revenue': decimal.Decimal('0.00'), 'total_from_credit': amount + taxamt } elif item.item_type == BillingItemTypes.credit: if journal_entry.destination == JournalSources.invoice: report['credit_out'] += item.amount else: report['credit_in'] += item.amount # Gether all credit used by services # The credit is split proportional to each service, based on it's usage report client_available_credit = report['credit_available'] total_still_required_cost = decimal.Decimal('0.00') total_required_cost = decimal.Decimal('0.00') total_debt = decimal.Decimal('0.00') total_credit_alloted = decimal.Decimal('0.00') for service_id, service_report in services_report.items(): price_overridden = service_report[ 'price_overridden'] if 'price_overridden' in service_report else False total_revenue = service_report['total_revenue'] if price_overridden: # If pirice is overridden, the service total cost is the fixed price one - entries for it service_required_cost = service_report['fixed_monthly_price'] service_report['service_required_cost'] = cdecimal( service_required_cost, q='.01') cost_still_required = service_required_cost - total_revenue cost_still_required = cdecimal(cost_still_required, q='.01') service_report['cost_still_required'] = cost_still_required else: # Add here logic for dynamic but minimum fixed fixed_monthly_price = (service_report['fixed_monthly_price'] if 'fixed_monthly_price' in service_report else decimal.Decimal('0.00')) usage_details = (service_report['usage_details'] if 'usage_details' in service_report else {}) service_required_cost = ( fixed_monthly_price + usage_details.get('total_cost', decimal.Decimal('0.00'))) cost_still_required = service_required_cost - total_revenue cost_still_required = cdecimal(cost_still_required, q='.01') service_report['service_required_cost'] = cdecimal( service_required_cost, q='.01') service_report['cost_still_required'] = cost_still_required # Create a total amount so we can deduct from credit available and calculate the percentage total_required_cost += service_required_cost total_still_required_cost += cost_still_required # Calculate the percentage, debts, credit alloted of each service services_report, report = JournalReport._calculate_amount_for_services( client=client, services_report=services_report, report=report, total_still_required_cost=total_still_required_cost, client_available_credit=client_available_credit, total_debt=total_debt, total_credit_alloted=total_credit_alloted, end_date=end_date) # Go through each service to get the totals per region revenue_per_location = {} default_location = JournalReport.get_default_location() for service_id, service_report in services_report.items(): # Set an equal percent for each location usage_details = service_report.get('usage_details', {}) if type(usage_details) is dict and usage_details.keys(): # Deal with services that have usage_details location_cost = usage_details.get('location_cost') total_revenue = service_report['alloted_from_credit'] service_location_alloted = JournalReport.get_percent_per_location( location_cost, total_revenue) for location_name, costs in service_location_alloted.items(): if location_name not in revenue_per_location: revenue_per_location[location_name] = decimal.Decimal( '0.00') revenue_per_location[location_name] += costs['alloted'] else: if default_location not in revenue_per_location: revenue_per_location[default_location] = decimal.Decimal( '0.00') total_revenue = service_report['alloted_from_credit'] revenue_per_location[default_location] += total_revenue report['revenue_per_location'] = [{ 'name': name, 'revenue': cdecimal(revenue, q='.01') } for name, revenue in revenue_per_location.items()] return report
def settle_dynamic_price_for_service(service: Service, issue_date: datetime): try: billing_module = module_factory.get_module_instance(service=service) billing_module.settle_usage(service, issue_date) except ModuleNotFoundException: pass