Пример #1
0
 def test_setup(self):
     call_command('loaddata', 'kc_partners.yaml')
     call_command('loaddata', 'kc_partner_app_retail_config.yaml')
     call_command('loaddata', 'kc_partners.yaml', database=UMBRELLA)
     call_command('loaddata',
                  'kc_partner_app_retail_config.yaml',
                  database=UMBRELLA)
     call_command('loaddata', 'themes.yaml', database=UMBRELLA)
     app = Application.objects.using(UMBRELLA).get(
         pk='56eb6d04b37b3379b531a001')
     theme = Theme.objects.using(UMBRELLA).get(
         pk='588fc0c224123d63bb4fc4e1')
     billing_cycle = 'Quarterly'
     billing_plan = CloudBillingPlan.objects.using(UMBRELLA).get(
         pk='55e7b9b531a003371b6d0cb1')
     member = Member.objects.using(UMBRELLA).get(
         pk='56eb6d04b37b3379b531e014')
     project_name = 'Le Vignon'
     domain = 'levignon.cm'
     business_type = OperatorProfile.PROVIDER
     setup_cost = 45000
     monthly_cost = 13500
     partner = Service.objects.using(UMBRELLA).get(
         pk='56eb6d04b9b531b10537b331')
     item1 = IkwenInvoiceItem(label='Domain name')
     item2 = IkwenInvoiceItem(label='Website cloud_setup',
                              price=billing_plan.setup_cost,
                              amount=setup_cost)
     item3 = IkwenInvoiceItem(label='Shooting of 50 products', amount=50000)
     item4 = IkwenInvoiceItem(label='Publication of 100 products',
                              amount=25000)
     entries = [
         InvoiceEntry(item=item1, short_description=domain),
         InvoiceEntry(item=item2, total=setup_cost),
         InvoiceEntry(item=item3, total=50000),
         InvoiceEntry(item=item4, total=25000)
     ]
     from ikwen_kakocase.kakocase.cloud_setup import deploy
     deploy(app,
            member,
            business_type,
            project_name,
            billing_plan,
            theme,
            monthly_cost,
            entries,
            billing_cycle,
            domain,
            partner_retailer=partner)
     service_partner = Service.objects.get(domain='levignon.cm')
     service_umbrella = Service.objects.using(UMBRELLA).get(
         domain='levignon.cm')
     service_original = Service.objects.using('levignon').get(
         domain='levignon.cm')
     self.assertIsNotNone(service_umbrella.config)
     self.assertIsNotNone(service_partner.config)
     self.assertIsNotNone(service_original.config)
     self.assertIsNotNone(
         InvoicingConfig.objects.using('levignon').all()[0])
Пример #2
0
    def post(self, request, *args, **kwargs):
        form = DeploymentForm(request.POST)
        if form.is_valid():
            app_id = form.cleaned_data.get('app_id')
            project_name = form.cleaned_data.get('project_name')
            billing_cycle = form.cleaned_data.get('billing_cycle')
            billing_plan_id = form.cleaned_data.get('billing_plan_id')
            app = Application.objects.using(UMBRELLA).get(pk=app_id)
            billing_plan = CloudBillingPlan.objects.using(UMBRELLA).get(pk=billing_plan_id)

            customer_id = form.cleaned_data.get('customer_id')
            customer = Member.objects.using(UMBRELLA).get(pk=customer_id)
            setup_cost = form.cleaned_data.get('setup_cost')
            monthly_cost = form.cleaned_data.get('monthly_cost')
            if setup_cost < billing_plan.setup_cost:
                return HttpResponseForbidden("Attempt to set a Setup cost lower than allowed.")
            if monthly_cost < billing_plan.monthly_cost:
                return HttpResponseForbidden("Attempt to set a monthly cost lower than allowed.")

            invoice_entries = []
            website_setup = IkwenInvoiceItem(label='Platform setup', price=billing_plan.setup_cost, amount=setup_cost)
            short_description = "N/A"
            website_setup_entry = InvoiceEntry(item=website_setup, short_description=short_description, total=setup_cost)
            invoice_entries.append(website_setup_entry)
            i = 0
            while True:
                try:
                    label = request.POST['item%d' % i]
                    amount = float(request.POST['amount%d' % i])
                    if not (label and amount):
                        break
                    item = IkwenInvoiceItem(label=label, amount=amount)
                    entry = InvoiceEntry(item=item, total=amount)
                    invoice_entries.append(entry)
                    i += 1
                except:
                    break
            theme = Theme.objects.using(UMBRELLA).get(slug='dreamer')
            theme.display = Theme.COZY
            if getattr(settings, 'DEBUG', False):
                service = deploy(app, customer, project_name, billing_plan,
                                 monthly_cost, theme, billing_cycle, invoice_entries)
            else:
                try:
                    service = deploy(app, customer, project_name, billing_plan,
                                     monthly_cost, theme, billing_cycle, invoice_entries)
                except Exception as e:
                    context = self.get_context_data(**kwargs)
                    context['error'] = e.message
                    return render(request, 'core/cloud_setup/deploy.html', context)
            next_url = reverse('partnership:change_service', args=(service.id, ))
            return HttpResponseRedirect(next_url)
        else:
            context = self.get_context_data(**kwargs)
            context['form'] = form
            return render(request, 'core/cloud_setup/deploy.html', context)
Пример #3
0
 def test_setup(self):
     app = Application.objects.using(UMBRELLA).get(
         pk='56eb6d04b37b3379b531a001')
     billing_cycle = 'Quarterly'
     billing_plan = CloudBillingPlan.objects.using(UMBRELLA).get(
         pk='57e7b9b5371b6d0cb131a001')
     member = Member.objects.using(UMBRELLA).get(
         pk='56eb6d04b37b3379b531e014')
     project_name = 'IT Pro'
     setup_cost = 45000
     monthly_cost = 13500
     item1 = IkwenInvoiceItem(label='Website Cloud Setup',
                              price=billing_plan.setup_cost,
                              amount=setup_cost)
     entries = [
         InvoiceEntry(item=item1),
     ]
     from ikwen.partnership.cloud_setup import deploy
     deploy(app, member, project_name, billing_plan, monthly_cost,
            billing_cycle, entries)
     service_umbrella = Service.objects.get(domain='itpro.ikwen.com')
     service_original = Service.objects.using('itpro').get(
         domain='itpro.ikwen.com')
     self.assertIsNotNone(
         PartnerProfile.objects.get(service=service_umbrella))
     self.assertIsNotNone(
         PartnerProfile.objects.using('itpro').get(
             service=service_original))
     self.assertIsNotNone(InvoicingConfig.objects.using('itpro').all()[0])
Пример #4
0
def product_set_checkout(request, *args, **kwargs):
    product_id = request.POST['product_id']
    product = Product.objects.get(pk=product_id)
    member = request.user
    now = datetime.now()
    expiry = now + timedelta(days=product.duration)
    subscription = Subscription.objects.create(member=member,
                                               product=product,
                                               since=now,
                                               expiry=expiry)
    number = get_next_invoice_number()
    item = InvoiceItem(label=product.name)
    entry = InvoiceEntry(item=item,
                         short_description=product.short_description,
                         total=product.cost)
    months_count = product.duration / 30
    invoice = Invoice.objects.create(subscription=subscription,
                                     amount=product.cost,
                                     number=number,
                                     due_date=now,
                                     last_reminder=now,
                                     is_one_off=product.is_one_off,
                                     entries=[entry],
                                     months_count=months_count)
    amount = invoice.amount
    notification_url = reverse('billing:product_do_checkout',
                               args=(invoice.id, ))
    cancel_url = request.META['HTTP_REFERER']
    return_url = reverse('billing:invoice_detail', args=(invoice.id, ))
    return invoice, amount, notification_url, return_url, cancel_url
Пример #5
0
 def place_invoice(self, request, *args, **kwargs):
     school_name = kwargs['school_name']
     weblet = Service.objects.get(project_name_slug=school_name)
     try:
         db = weblet.database
         add_database(db)
         school = SchoolConfig.objects.using(db).get(service=weblet)
         now = datetime.now()
         due_date = now + timedelta(days=7)
         number = get_next_invoice_number()
         from ikwen.billing.utils import Invoice
         app = Application.objects.using(UMBRELLA).get(slug='foulassi')
         cost = 12000
         item = IkwenInvoiceItem(label='School website', price=cost, amount=cost)
         entry = InvoiceEntry(item=item, total=cost)
         invoice_entries = [entry]
         try:
             Invoice.objects.using(UMBRELLA).get(subscription=weblet, months_count=SCHOOL_WEBSITE_MONTH_COUNT)
         except:
             invoice = Invoice(subscription=weblet, member=weblet.member, amount=cost,
                               months_count=SCHOOL_WEBSITE_MONTH_COUNT, number=number,
                               due_date=due_date, last_reminder=now, entries=invoice_entries, is_one_off=True)
             invoice.save()
         school.has_subscribed_website_service = True
         school.save()
         return HttpResponse(json.dumps({'success': True}, 'content-type: text/json'))
     except:
         return HttpResponse(json.dumps({'error': True}, 'content-type: text/json'))
Пример #6
0
def product_set_checkout(request, *args, **kwargs):
    service = get_service_instance()
    product_id = request.POST['product_id']
    product = Product.objects.get(pk=product_id)
    member = request.user
    now = datetime.now()
    expiry = now + timedelta(days=product.duration)
    subscription = Subscription.objects.create(member=member, product=product, since=now, expiry=expiry)
    number = get_next_invoice_number()
    item = InvoiceItem(label=product.name)
    entry = InvoiceEntry(item=item, short_description=product.short_description, total=product.cost)
    months_count = product.duration / 30
    invoice = Invoice.objects.create(subscription=subscription, amount=product.cost, number=number, due_date=now,
                                     last_reminder=now, is_one_off=True, entries=[entry], months_count=months_count)

    request.session['amount'] = product.cost
    request.session['model_name'] = 'billing.Invoice'
    request.session['object_id'] = invoice.id

    mean = request.GET.get('mean', MTN_MOMO)
    request.session['mean'] = mean
    request.session['notif_url'] = service.url # Orange Money only
    request.session['cancel_url'] = service.url + reverse('billing:pricing') # Orange Money only
    request.session['return_url'] = reverse('billing:invoice_detail', args=(invoice.id, ))
Пример #7
0
def set_my_kids_payment(request, *args, **kwargs):
    school_id = request.POST['school_id']
    student_id = request.POST['student_id']
    cycle = request.POST['my_kids_cycle']
    school = Service.objects.get(pk=school_id)
    student = Student.objects.get(pk=student_id)
    school_config = SchoolConfig.objects.get(service=school)
    Invoice.objects.filter(student=student,
                           is_my_kids=True,
                           status=Invoice.PENDING).delete()
    max_expiry = datetime(day=31, month=8, year=get_school_year() + 1)
    if cycle == Service.YEARLY:
        amount = school_config.my_kids_fees
    elif cycle == Service.QUARTERLY:
        amount = school_config.my_kids_fees_term
    else:
        amount = school_config.my_kids_fees_month
        cycle = Service.MONTHLY
    item = InvoiceItem(label=_("MyKids fees"), amount=amount)
    days = get_billing_cycle_days_count(cycle)
    now = datetime.now()
    expiry = now + timedelta(days=days)
    expiry = min(expiry, max_expiry)
    short_description = now.strftime("%Y/%m/%d") + ' - ' + expiry.strftime(
        "%Y/%m/%d")
    entry = InvoiceEntry(item=item,
                         short_description=short_description,
                         total=amount,
                         quantity_unit='')
    number = get_next_invoice_number()
    member = request.user
    invoice = Invoice.objects.create(number=number,
                                     member=member,
                                     student=student,
                                     school=school,
                                     is_one_off=True,
                                     amount=amount,
                                     my_kids_cycle=cycle,
                                     due_date=now,
                                     entries=[entry],
                                     is_my_kids=True)
    foulassi_weblet = get_service_instance()  # This is Foulassi service itself

    # Transaction is hidden from school if ikwen collects 100%.
    # This is achieved by changing the service_id of transaction
    tx_service_id = school.id if school_config.my_kids_share_rate < 100 else foulassi_weblet.id
    model_name = 'billing.Invoice'
    mean = request.GET.get('mean', MTN_MOMO)
    signature = ''.join([
        random.SystemRandom().choice(string.ascii_letters + string.digits)
        for i in range(16)
    ])
    MoMoTransaction.objects.using(WALLETS_DB_ALIAS).filter(
        object_id=invoice.id).delete()

    tx = MoMoTransaction.objects.using(WALLETS_DB_ALIAS)\
        .create(service_id=tx_service_id, type=MoMoTransaction.CASH_OUT, amount=amount, phone='N/A', model=model_name,
                object_id=invoice.id, task_id=signature, wallet=mean, username=request.user.username, is_running=True)
    notification_url = foulassi_weblet.url + reverse(
        'foulassi:confirm_my_kids_payment', args=(tx.id, signature))
    cancel_url = request.META['HTTP_REFERER']
    return_url = request.META['HTTP_REFERER']
    return invoice, amount, notification_url, return_url, cancel_url
Пример #8
0
    def post(self, request, *args, **kwargs):
        form = DeploymentForm(request.POST)
        if form.is_valid():
            app_id = form.cleaned_data.get('app_id')
            project_name = form.cleaned_data.get('project_name')
            business_type = form.cleaned_data.get('business_type')
            billing_cycle = form.cleaned_data.get('billing_cycle')
            billing_plan_id = form.cleaned_data.get('billing_plan_id')
            domain = form.cleaned_data.get('domain')
            theme_id = form.cleaned_data.get('theme_id')
            partner_id = form.cleaned_data.get('partner_id')
            app = Application.objects.using(UMBRELLA).get(pk=app_id)
            theme = Theme.objects.using(UMBRELLA).get(pk=theme_id)
            billing_plan = CloudBillingPlan.objects.using(UMBRELLA).get(
                pk=billing_plan_id)

            is_ikwen = getattr(settings, 'IS_IKWEN', False)
            if not is_ikwen or (is_ikwen and request.user.is_staff):
                customer_id = form.cleaned_data.get('customer_id')
                customer = Member.objects.using(UMBRELLA).get(pk=customer_id)
                setup_cost = form.cleaned_data.get('setup_cost')
                monthly_cost = form.cleaned_data.get('monthly_cost')
                if setup_cost < billing_plan.setup_cost:
                    return HttpResponseForbidden(
                        "Attempt to set a Setup cost lower than allowed.")
                if monthly_cost < billing_plan.monthly_cost:
                    return HttpResponseForbidden(
                        "Attempt to set a monthly cost lower than allowed.")
            else:
                # User self-deploying his website
                customer = Member.objects.using(UMBRELLA).get(
                    pk=request.user.id)
                setup_cost = billing_plan.setup_cost
                monthly_cost = billing_plan.monthly_cost

            partner = Service.objects.using(UMBRELLA).get(
                pk=partner_id) if partner_id else None
            invoice_entries = []
            domain_name = IkwenInvoiceItem(label='Domain name')
            domain_name_entry = InvoiceEntry(item=domain_name,
                                             short_description=domain)
            invoice_entries.append(domain_name_entry)
            website_setup = IkwenInvoiceItem(label='Website setup',
                                             price=billing_plan.setup_cost,
                                             amount=setup_cost)
            short_description = "%d products" % billing_plan.max_objects
            website_setup_entry = InvoiceEntry(
                item=website_setup,
                short_description=short_description,
                total=setup_cost)
            invoice_entries.append(website_setup_entry)
            i = 0
            while True:
                try:
                    label = request.POST['item%d' % i]
                    amount = float(request.POST['amount%d' % i])
                    if not (label and amount):
                        break
                    item = IkwenInvoiceItem(label=label, amount=amount)
                    entry = InvoiceEntry(item=item, total=amount)
                    invoice_entries.append(entry)
                    i += 1
                except:
                    break
            if getattr(settings, 'DEBUG', False):
                service = deploy(app,
                                 customer,
                                 business_type,
                                 project_name,
                                 billing_plan,
                                 theme,
                                 monthly_cost,
                                 invoice_entries,
                                 billing_cycle,
                                 domain,
                                 partner_retailer=partner)
            else:
                try:
                    service = deploy(app,
                                     customer,
                                     business_type,
                                     project_name,
                                     billing_plan,
                                     theme,
                                     monthly_cost,
                                     invoice_entries,
                                     billing_cycle,
                                     domain,
                                     partner_retailer=partner)
                except Exception as e:
                    context = self.get_context_data(**kwargs)
                    context['error'] = e.message
                    return render(request, 'shavida/cloud_setup/deploy.html',
                                  context)
            if is_ikwen:
                if request.user.is_staff:
                    next_url = reverse('partnership:change_service',
                                       args=(service.id, ))
                else:
                    next_url = reverse('ikwen:console')
            else:
                next_url = reverse('change_service', args=(service.id, ))
            return HttpResponseRedirect(next_url)
        else:
            context = self.get_context_data(**kwargs)
            context['form'] = form
            return render(request, 'shavida/cloud_setup/deploy.html', context)
Пример #9
0
def confirm_reservation_payment(request, *args, **kwargs):
    """
    This view is run after successful user cashout "MOMO_AFTER_CHECKOUT"
    """
    tx = kwargs[
        'tx']  # Decoration with @momo_gateway_callback makes 'tx' available in kwargs
    amount = tx.amount
    now = datetime.now()

    # Update reservation status --- Confirm reservation
    reservation_id = tx.object_id
    reservation = Reservation.objects.get(pk=reservation_id)
    reservation.processor_tx_id = tx.processor_tx_id
    reservation.method = Reservation.MOBILE_MONEY
    reservation.status = CONFIRMED
    item = InvoiceItem(label=_("Reservation of %s " % reservation.post),
                       amount=reservation.amount)
    short_description = reservation.start_on.strftime(
        "%Y/%m/%d") + ' - ' + reservation.end_on.strftime("%Y/%m/%d")
    entry = InvoiceEntry(item=item,
                         short_description=short_description,
                         total=reservation.amount,
                         quantity_unit='')
    reservation.entries = [entry]
    reservation.save()

    # Share earnings
    weblet = get_service_instance(check_cache=False)
    config = weblet.config
    ikwen_charges = tx.amount * config.ikwen_share_rate / 100
    ikwen_share_rate = config.ikwen_share_fixed
    tx.fees = ikwen_charges
    tx.save()
    amount = (100 - ikwen_share_rate) * amount / 100
    weblet.raise_balance(amount, provider=tx.wallet)
    set_counters(weblet)
    increment_history_field(weblet, 'turnover_history', amount)
    increment_history_field(weblet, 'earnings_history', amount)
    increment_history_field(weblet, 'transaction_count_history')

    member = reservation.member

    # Notify customer and staff

    payer_email = member.email
    email = config.contact_email
    if not email:
        email = weblet.member.email
    if email or payer_email:
        subject = _("New reservation of %s done" % reservation.post)
        try:
            html_content = get_mail_content(
                subject,
                template_name='enfinchezmoi/mails/payment_notice.html',
                extra_context={
                    'currency_symbol': config.currency_symbol,
                    'post': reservation,
                    'payer': member,
                    'tx_date': tx.updated_on.strftime('%Y-%m-%d'),
                    'tx_time': tx.updated_on.strftime('%H:%M:%S')
                })
            sender = '%s <no-reply@%s>' % (weblet.project_name, weblet.domain)
            msg = EmailMessage(subject, html_content, sender, [payer_email])
            msg.bcc = [email]
            msg.content_subtype = "html"
            if getattr(settings, 'UNIT_TESTING', False):
                msg.send()
            else:
                Thread(target=lambda m: m.send(), args=(msg, )).start()
        except:
            logger.error("%s - Failed to send notice mail to %s." %
                         (weblet, email),
                         exc_info=True)

    # if member.email:
    #     activate(member.language)
    #     invoice_url = ikwen_service.url + reverse('billing:invoice_detail', args=(invoice.id,))
    #     subject, message, sms_text = get_payment_confirmation_message(payment, member)
    #     html_content = get_mail_content(subject, message, service=vendor, template_name='billing/mails/notice.html',
    #                                     extra_context={'member_name': member.first_name, 'invoice': invoice,
    #                                                    'cta': _("View invoice"), 'invoice_url': invoice_url,
    #                                                    'early_payment': is_early_payment})
    #     sender = '%s <no-reply@%s>' % (vendor.config.company_name, ikwen_service.domain)
    #     msg = XEmailMessage(subject, html_content, sender, [member.email])
    #     if vendor != ikwen_service and not vendor_is_dara:
    #         msg.service = vendor
    #     if invoice_pdf_file:
    #         msg.attach_file(invoice_pdf_file)
    #     msg.content_subtype = "html"
    #     if getattr(settings, 'UNIT_TESTING', False):
    #         msg.send()
    #     else:
    #         Thread(target=lambda m: m.send(), args=(msg,)).start()
    return HttpResponse("Notification received")
Пример #10
0
def send_expiry_reminders():
    """
    This cron task simply sends the Invoice *invoicing_gap* days before Subscription *expiry*
    """
    ikwen_service = get_service_instance()
    now = datetime.now()
    invoicing_config = InvoicingConfig.objects.all()[0]
    connection = mail.get_connection()
    try:
        connection.open()
    except:
        logger.error(u"Connexion error", exc_info=True)

    reminder_date_time = now + timedelta(days=invoicing_config.gap)

    for invoicing_config in InvoicingConfig.objects.exclude(
            service=ikwen_service):
        service = invoicing_config.service
        if service.status != Service.ACTIVE or invoicing_config.pull_invoice:
            continue
        db = service.database
        add_database(db)
        config = service.basic_config
        subscription_qs = Subscription.objects.using(db)\
            .selected_related('member, product').filter(status=Subscription.ACTIVE,
                                                        monthly_cost__gt=0, expiry=reminder_date_time.date())
        count, total_amount = 0, 0
        for subscription in subscription_qs:
            member = subscription.member
            number = get_next_invoice_number()
            months_count = get_billing_cycle_months_count(
                subscription.billing_cycle)
            amount = subscription.monthly_cost * months_count

            path_before = getattr(settings, 'BILLING_BEFORE_NEW_INVOICE', None)
            if path_before:
                before_new_invoice = import_by_path(path_before)
                val = before_new_invoice(subscription)
                if val is not None:  # Returning a not None value cancels the generation of a new Invoice for this Service
                    continue

            short_description = subscription.product.short_description
            item = InvoiceItem(label=_('Subscription'), amount=amount)
            entry = InvoiceEntry(item=item,
                                 short_description=short_description,
                                 quantity=months_count,
                                 total=amount)
            invoice = Invoice.objects.create(member=member,
                                             subscription=subscription,
                                             amount=amount,
                                             number=number,
                                             due_date=subscription.expiry,
                                             months_count=months_count,
                                             entries=[entry])
            count += 1
            total_amount += amount

            subject, message, sms_text = get_invoice_generated_message(invoice)
            balance, update = Balance.objects.using(
                WALLETS_DB_ALIAS).get_or_create(service_id=service.id)
            if member.email:
                if 0 < balance.mail_count < LOW_MAIL_LIMIT:
                    notify_for_low_messaging_credit(service, balance)
                if balance.mail_count <= 0 and not getattr(
                        settings, 'UNIT_TESTING', False):
                    notify_for_empty_messaging_credit(service, balance)
                else:
                    invoice_url = service.url + reverse(
                        'billing:invoice_detail', args=(invoice.id, ))
                    html_content = get_mail_content(
                        subject,
                        message,
                        service=service,
                        template_name='billing/mails/notice.html',
                        extra_context={
                            'invoice_url': invoice_url,
                            'cta': _("Pay now"),
                            'currency': config.currency_symbol
                        })
                    # Sender is simulated as being no-reply@company_name_slug.com to avoid the mail
                    # to be delivered to Spams because of origin check.
                    sender = '%s <no-reply@%s>' % (config.company_name,
                                                   service.domain)
                    msg = XEmailMessage(subject, html_content, sender,
                                        [member.email])
                    msg.content_subtype = "html"
                    msg.service = service
                    invoice.last_reminder = timezone.now()
                    try:
                        with transaction.atomic(using=WALLETS_DB_ALIAS):
                            if msg.send():
                                balance.mail_count -= 1
                                balance.save()
                                logger.debug(
                                    "1st Invoice reminder for %s sent to %s" %
                                    (subscription, member.email))
                            else:
                                logger.error(
                                    u"Invoice #%s generated but mail not sent to %s"
                                    % (number, member.email),
                                    exc_info=True)
                    except:
                        logger.error(u"Connexion error on Invoice #%s to %s" %
                                     (number, member.email),
                                     exc_info=True)

            if sms_text and member.phone:
                if 0 < balance.sms_count < LOW_SMS_LIMIT:
                    notify_for_low_messaging_credit(service, balance)
                if balance.sms_count <= 0 and not getattr(
                        settings, 'UNIT_TESTING', False):
                    notify_for_empty_messaging_credit(service, balance)
                    continue
                try:
                    with transaction.atomic(using=WALLETS_DB_ALIAS):
                        balance.sms_count -= 1
                        balance.save()
                        phone = member.phone if len(
                            member.phone) > 9 else '237' + member.phone
                        send_sms(phone, sms_text, fail_silently=False)
                except:
                    logger.error(u"SMS for invoice #%s not sent to %s" %
                                 (number, member.email),
                                 exc_info=True)

            path_after = getattr(settings, 'BILLING_AFTER_NEW_INVOICE', None)
            if path_after:
                after_new_invoice = import_by_path(path_after)
                after_new_invoice(invoice)

        if count > 0:
            report = SendingReport.objects.using(db).create(
                count=count, total_amount=total_amount)
            sudo_group = Group.objects.using(db).get(name=SUDO)
            add_event(ikwen_service,
                      INVOICES_SENT_EVENT,
                      group_id=sudo_group.id,
                      object_id=report.id)
    try:
        connection.close()
    except:
        pass
Пример #11
0
def pull_invoice(request, *args, **kwargs):
    api_signature = request.POST.get('api_signature')
    try:
        service = Service.objects.get(api_signature=api_signature)
    except:
        notice = "Invalid API Signature."
        response = {'error': notice}
        return HttpResponse(json.dumps(response))

    db = service.database
    add_database(db)
    invoicing_config, update = InvoicingConfig.objects.using(db).get_or_create(
        service=service)
    if not invoicing_config.pull_invoice:
        notice = "Cannot import when not explicitly configured to do so. You must activate " \
                 "'pull_invoice' in your platform configuration for import to work."
        response = {'error': notice}
        return HttpResponse(json.dumps(response))

    lang = request.POST.get('lang', "en")
    activate(lang)
    missing = []
    errors = []
    do_pull = True
    try:
        number = request.POST['invoice_number'].strip()
        try:
            Invoice.objects.using(db).get(number=number)
            errors.append(
                "Invoice with number '%s' already exists. Invoice numbers must be unique."
                % number)
            do_pull = False
        except Invoice.DoesNotExist:
            pass
    except KeyError:
        missing.append('invoice_number')
        do_pull = False
    try:
        reference_id = request.POST['reference_id']
    except KeyError:
        reference_id = None
        missing.append('reference_id')
        do_pull = False
    try:
        amount = request.POST['amount']
        amount = float(amount)
    except KeyError:
        missing.append('amount')
        do_pull = False
    except ValueError:
        errors.append("Invalid amount '%s'. Expected valid float or int.")
        do_pull = False
    try:
        due_date = request.POST['due_date']
        time.strptime(due_date, '%Y-%m-%d')
    except KeyError:
        missing.append('due_date')
        do_pull = False
    except ValueError:
        errors.append(
            "Invalid due_date '%s'. Expected valid date in the format 'YYYY-mm-dd'."
        )
        do_pull = False
    try:
        quantity = request.POST['quantity']
    except KeyError:
        missing.append('quantity')
        do_pull = False
    except ValueError:
        errors.append("Invalid quantity '%s'. Expected valid int.")
        do_pull = False
    quantity_unit = request.POST.get('quantity_unit', _("Month(s)"))
    currency_code = request.POST.get('currency_code', 'XAF')
    if reference_id:
        try:
            subscription = Subscription.objects.using(db).select_related(
                'member', 'product').get(reference_id=reference_id)
        except Subscription.DoesNotExist:
            do_pull = False
            notice = "reference_id '%s' not found." % reference_id
            errors.append(notice)
    if not do_pull:
        response = {'error': '\n'.join(errors)}
        if missing:
            response[
                'missing'] = 'Following parameters are missing: ' + ', '.join(
                    missing)
        return HttpResponse(json.dumps(response))

    product = subscription.product
    if product:
        short_description = product.name
    else:
        short_description = request.POST.get('short_description', '---')
    invoice_entries = []
    item = InvoiceItem(label=_('Subscription'), amount=amount)
    entry = InvoiceEntry(item=item,
                         short_description=short_description,
                         quantity=quantity,
                         quantity_unit=quantity_unit,
                         total=amount)
    invoice_entries.append(entry)
    invoice = Invoice.objects.using(db).create(number=number,
                                               member=subscription.member,
                                               subscription=subscription,
                                               amount=amount,
                                               months_count=quantity,
                                               due_date=due_date,
                                               entries=invoice_entries)
    config = service.config
    member = subscription.member
    if member.email:
        with transaction.atomic(using=WALLETS_DB_ALIAS):
            from echo.models import Balance
            from echo.utils import notify_for_low_messaging_credit, LOW_MAIL_LIMIT, notify_for_empty_messaging_credit
            balance, update = Balance.objects.using(
                WALLETS_DB_ALIAS).get_or_create(service_id=service.id)
            if 0 < balance.mail_count < LOW_MAIL_LIMIT:
                notify_for_low_messaging_credit(service, balance)
            if balance.mail_count <= 0:
                notify_for_empty_messaging_credit(service, balance)
                response = {
                    'success': True,
                    'warning': "Email not set due to empty mail credit"
                }
                return HttpResponse(json.dumps(response))
            subject, message, sms_text = get_invoice_generated_message(invoice)
            try:
                currency = Currency.objects.using(db).get(
                    code=currency_code).symbol
            except:
                try:
                    currency = Currency.active.default().symbol
                except:
                    currency = currency_code

            invoice_url = service.url + reverse('billing:invoice_detail',
                                                args=(invoice.id, ))
            html_content = get_mail_content(
                subject,
                template_name='billing/mails/notice.html',
                service=service,
                extra_context={
                    'invoice': invoice,
                    'member_name': member.first_name,
                    'invoice_url': invoice_url,
                    'cta': _("Pay now"),
                    'currency': currency
                })
            sender = '%s <no-reply@%s>' % (config.company_name, service.domain)
            msg = XEmailMessage(subject, html_content, sender, [member.email])
            msg.content_subtype = "html"
            balance.mail_count -= 1
            balance.save()
            if getattr(settings, 'UNIT_TESTING', False):
                msg.send()
            else:
                Thread(target=lambda m: m.send(), args=(msg, )).start()
    response = {'success': True, 'invoice_id': invoice.id}
    return HttpResponse(json.dumps(response))
Пример #12
0
def send_invoices():
    """
    This cron task simply sends the Invoice *invoicing_gap* days before Subscription *expiry*
    """
    vendor, config, invoicing_config, connection = _init_base_vars()
    now = timezone.now()
    count, total_amount = 0, 0
    reminder_date_time = now + timedelta(days=invoicing_config.gap)
    subscription_qs = Subscription.objects.filter(status=Subscription.ACTIVE,
                                                  monthly_cost__gt=0, expiry__lt=reminder_date_time.date())
    logger.debug("%d Service candidate for invoice issuance." % subscription_qs.count())
    for subscription in subscription_qs:
        if getattr(settings, 'IS_IKWEN', False):
            if subscription.version == Service.FREE:
                continue
        try:
            pending_invoice = Invoice.objects.get(subscription=subscription, status=Invoice.PENDING)
            logger.debug("%s found for %s. Skipping" % (pending_invoice, subscription))
            continue  # Continue if a Pending invoice for this Subscription is found
        except Invoice.DoesNotExist:
            pass
        member = subscription.member
        number = get_next_invoice_number()
        months_count = None
        if config.__dict__.get('separate_billing_cycle', True):
            months_count = get_billing_cycle_months_count(subscription.billing_cycle)
            amount = subscription.monthly_cost * months_count
        else:
            amount = subscription.product.cost

        path_before = getattr(settings, 'BILLING_BEFORE_NEW_INVOICE', None)
        if path_before:
            before_new_invoice = import_by_path(path_before)
            val = before_new_invoice(subscription)
            if val is not None:  # Returning a not None value cancels the generation of a new Invoice for this Service
                continue

        entries = []
        if type(subscription) is Service:
            from daraja.models import DARAJA
            partner = subscription.retailer
            if partner and partner.app.slug != DARAJA:
                retail_config = ApplicationRetailConfig.objects.get(partner=partner, app=subscription.app)
                ikwen_price = retail_config.ikwen_monthly_cost
            else:
                ikwen_price = subscription.monthly_cost
            hosting = IkwenInvoiceItem(label=_('Website hosting'), price=ikwen_price, amount=subscription.monthly_cost)
            short_description = _("Project %s" % subscription.domain)
            entry = InvoiceEntry(item=hosting, short_description=short_description, quantity=months_count, total=amount)
            entries = [entry]
            try:
                cr_op_profile = CROperatorProfile.objects.get(service=subscription, is_active=True)
                if cr_op_profile.monthly_cost > 0:
                    plan = cr_op_profile.plan
                    cr_monthly_cost = cr_op_profile.monthly_cost
                    cr_item = IkwenInvoiceItem(label=_('Continuous Rewarding'), price=cr_monthly_cost, amount=cr_monthly_cost)
                    short_description = plan.name
                    cr_amount = months_count * cr_monthly_cost
                    amount += cr_amount
                    entry = InvoiceEntry(item=cr_item, short_description=short_description, quantity=months_count, total=cr_amount)
                    entries.append(entry)
            except CROperatorProfile.DoesNotExist:
                pass
        invoice = Invoice.objects.create(subscription=subscription, member=subscription.member, amount=amount,
                                         number=number, due_date=subscription.expiry, months_count=months_count,
                                         entries=entries, last_reminder=now)
        count += 1
        total_amount += amount
        add_event(vendor, NEW_INVOICE_EVENT, member=member, object_id=invoice.id)

        paid_by_wallet_debit = False
        if getattr(settings, 'IS_IKWEN', False) and subscription.balance >= invoice.amount:
            pay_with_wallet_balance(invoice)
            paid_by_wallet_debit = True
            logger.debug("Invoice for %s paid by wallet debit" % subscription.domain)

        subject, message, sms_text = get_invoice_generated_message(invoice)

        if member.email:
            activate(member.language)
            invoice_url = 'http://ikwen.com' + reverse('billing:invoice_detail', args=(invoice.id,))
            if paid_by_wallet_debit:
                subject = _("Thanks for your payment")
                invoice_url = 'http://ikwen.com' + reverse('billing:invoice_detail', args=(invoice.id,))
                context = {'wallet_debit': True, 'invoice': invoice, 'config': config,
                           'member_name': member.first_name, 'invoice_url': invoice_url, 'cta': _("View invoice")}
                html_content = get_mail_content(subject, '', template_name='billing/mails/wallet_debit_notice.html',
                                                extra_context=context)
            else:
                context = {'invoice_url': invoice_url, 'cta': _("Pay now"), 'currency': config.currency_symbol,
                           'service': vendor, 'config': config, 'logo': config.logo,
                           'project_name': vendor.project_name, 'company_name': config.company_name,
                           'member_name': member.first_name, 'invoice': invoice}
                html_content = get_mail_content(subject, message, template_name='billing/mails/notice.html',
                                                extra_context=context)
            # Sender is simulated as being no-reply@company_name_slug.com to avoid the mail
            # to be delivered to Spams because of origin check.
            sender = '%s <no-reply@%s>' % (config.company_name, vendor.domain)
            msg = EmailMessage(subject, html_content, sender, [member.email])
            try:
                invoice_pdf_file = generate_pdf_invoice(invoicing_config, invoice)
                msg.attach_file(invoice_pdf_file)
            except:
                pass
            if paid_by_wallet_debit:
                msg.bcc = ['*****@*****.**']
            msg.content_subtype = "html"
            invoice.last_reminder = timezone.now()
            try:
                if msg.send():
                    logger.debug("1st Invoice reminder for %s sent to %s" % (subscription.domain, member.email))
                    if not paid_by_wallet_debit:
                        invoice.reminders_sent = 1
                        invoice.save()
                else:
                    logger.error(u"Invoice #%s generated but mail not sent to %s" % (number, member.email),
                                 exc_info=True)
            except:
                logger.error(u"Connexion error on Invoice #%s to %s" % (number, member.email), exc_info=True)

        if sms_text:
            if member.phone:
                if config.sms_sending_method == Config.HTTP_API:
                    send_sms(member.phone, sms_text)
                else:
                    QueuedSMS.objects.create(recipient=member.phone, text=sms_text)

        path_after = getattr(settings, 'BILLING_AFTER_NEW_INVOICE', None)
        if path_after:
            after_new_invoice = import_by_path(path_after)
            after_new_invoice(invoice)

    try:
        connection.close()
    finally:
        if count > 0:
            report = SendingReport.objects.create(count=count, total_amount=total_amount)
            sudo_group = Group.objects.get(name=SUDO)
            add_event(vendor, INVOICES_SENT_EVENT, group_id=sudo_group.id, object_id=report.id)
Пример #13
0
def send_invoices():
    """
    This cron task simply sends the Invoice *invoicing_gap* days before Subscription *expiry*
    """
    service = get_service_instance()
    config = service.config
    now = datetime.now()
    invoicing_config = InvoicingConfig.objects.all()[0]
    connection = mail.get_connection()
    try:
        connection.open()
    except:
        logger.error(u"Connexion error", exc_info=True)
    count, total_amount = 0, 0
    reminder_date_time = now + timedelta(days=invoicing_config.gap)
    subscription_qs = Subscription.objects.filter(monthly_cost__gt=0, expiry=reminder_date_time.date())
    logger.debug("%d CR Operators candidate for invoice issuance." % subscription_qs.count())
    for subscription in subscription_qs:
        if subscription.plan.raw_monthly_cost == 0:
            continue
        cr_service = subscription.service
        member = cr_service.member
        number = get_next_invoice_number()
        months_count = get_billing_cycle_months_count(subscription.billing_cycle)
        amount = subscription.monthly_cost * months_count

        ikwen_price = subscription.monthly_cost
        hosting = IkwenInvoiceItem(label=_('Website hosting'), price=ikwen_price, amount=subscription.monthly_cost)
        short_description = _("Continuous Rewarding Program for %s" % cr_service.domain)
        entry = InvoiceEntry(item=hosting, short_description=short_description, quantity=months_count, total=amount)
        entries = [entry]
        invoice = Invoice.objects.create(subscription=subscription, amount=amount, number=number,
                                         due_date=subscription.expiry, months_count=months_count, entries=entries)
        count += 1
        total_amount += amount
        add_event(service, NEW_INVOICE_EVENT, member=member, object_id=invoice.id)

        paid_by_wallet_debit = False
        if cr_service.balance >= invoice.amount:
            pay_with_wallet_balance(invoice)
            paid_by_wallet_debit = True
            logger.debug("CR Invoice for %s paid by wallet debit" % cr_service.domain)

        subject, message, sms_text = get_invoice_generated_message(invoice)

        if member.email:
            invoice_url = service.url + reverse('billing:invoice_detail', args=(invoice.id,))
            if paid_by_wallet_debit:
                subject = _("Thanks for your payment")
                invoice_url = service.url + reverse('billing:invoice_detail', args=(invoice.id,))
                context = {'wallet_debit': True, 'invoice': invoice, 'config': config,
                           'invoice_url': invoice_url, 'cta': _("View invoice")}
                html_content = get_mail_content(subject, '', template_name='billing/mails/notice.html',
                                                extra_context=context)
            else:
                html_content = get_mail_content(subject, message, template_name='billing/mails/notice.html',
                                                extra_context={'invoice_url': invoice_url, 'cta': _("Pay now")})
            # Sender is simulated as being no-reply@company_name_slug.com to avoid the mail
            # to be delivered to Spams because of origin check.
            sender = '%s <no-reply@%s>' % (config.company_name, service.domain)
            msg = EmailMessage(subject, html_content, sender, [member.email])
            msg.content_subtype = "html"
            invoice.last_reminder = timezone.now()
            try:
                if msg.send():
                    logger.debug("1st Invoice reminder for %s sent to %s" % (cr_service.domain, member.email))
                    if not paid_by_wallet_debit:
                        invoice.reminders_sent = 1
                        invoice.save()
                else:
                    logger.error(u"Invoice #%s generated but mail not sent to %s" % (number, member.email),
                                 exc_info=True)
            except:
                logger.error(u"Connexion error on Invoice #%s to %s" % (number, member.email), exc_info=True)

        path_after = getattr(settings, 'BILLING_AFTER_NEW_INVOICE', None)
        if path_after:
            after_new_invoice = import_by_path(path_after)
            after_new_invoice(invoice)

    try:
        connection.close()
    finally:
        pass
Пример #14
0
    def post(self, request, *args, **kwargs):
        form = DeploymentForm(request.POST)
        if form.is_valid():
            project_name = form.cleaned_data.get('project_name')
            billing_plan_id = form.cleaned_data.get('billing_plan_id')
            partner_id = request.COOKIES.get('referrer')
            webnode = Application.objects.get(slug='webnode')
            template_list = list(Template.objects.filter(app=webnode))
            try:
                theme = Theme.objects.using(UMBRELLA).get(template__in=template_list, slug=self.DEFAULT_THEME)
            except:
                theme = None
                logger.error("Foulassi deployment: %s webnode theme not found" % self.DEFAULT_THEME)
            billing_plan = CloudBillingPlan.objects.using(UMBRELLA).get(pk=billing_plan_id)

            is_ikwen = getattr(settings, 'IS_IKWEN', False)
            if not is_ikwen or (is_ikwen and request.user.is_staff):
                customer_id = form.cleaned_data.get('customer_id')
                if not customer_id:
                    customer_id = request.user.id
                customer = Member.objects.using(UMBRELLA).get(pk=customer_id)
                setup_cost = form.cleaned_data.get('setup_cost')
                monthly_cost = form.cleaned_data.get('monthly_cost')
                if setup_cost < billing_plan.setup_cost:
                    return HttpResponseForbidden("Attempt to set a Setup cost lower than allowed.")
                if monthly_cost < billing_plan.monthly_cost:
                    return HttpResponseForbidden("Attempt to set a monthly cost lower than allowed.")
            else:
                # User self-deploying his website
                customer = Member.objects.using(UMBRELLA).get(pk=request.user.id)
                setup_cost = billing_plan.setup_cost
                monthly_cost = billing_plan.monthly_cost

            try:
                partner = Service.objects.using(UMBRELLA).get(pk=partner_id) if partner_id else None
            except:
                partner = None

            invoice_entries = []
            website_setup = IkwenInvoiceItem(label=_('ScolarFleet deployment'), price=billing_plan.setup_cost, amount=setup_cost)
            website_setup_entry = InvoiceEntry(item=website_setup, short_description=project_name, quantity=12, total=setup_cost)
            invoice_entries.append(website_setup_entry)
            if theme and theme.cost > 0:
                theme_item = IkwenInvoiceItem(label=_('Website theme'), price=theme.cost, amount=theme.cost)
                theme_entry = InvoiceEntry(item=theme_item, short_description=theme.name, total=theme.cost)
                invoice_entries.append(theme_entry)
            if getattr(settings, 'DEBUG', False):
                service = deploy(customer, project_name, billing_plan, theme, monthly_cost, invoice_entries, partner)
            else:
                try:
                    service = deploy(customer, project_name, billing_plan, theme, monthly_cost, invoice_entries, partner)
                except Exception as e:
                    logger.error("Foulassi deployment failed for %s" % project_name, exc_info=True)
                    context = self.get_context_data(**kwargs)
                    context['errors'] = e.message
                    return render(request, 'foulassi/cloud_setup/deploy.html', context)
            if is_ikwen:
                if request.user.is_staff:
                    next_url = reverse('partnership:change_service', args=(service.id,))
                else:
                    next_url = reverse('foulassi:successful_deployment', args=(service.ikwen_name,))
            else:
                next_url = reverse('change_service', args=(service.id,))
            return HttpResponseRedirect(next_url)
        else:
            context = self.get_context_data(**kwargs)
            context['errors'] = form.errors
            return render(request, 'foulassi/cloud_setup/deploy.html', context)
Пример #15
0
 def after_save(self, request, obj, *args, **kwargs):
     object_id = kwargs.get('object_id')
     if object_id:
         return
     number = get_next_invoice_number()
     months_count = get_billing_cycle_months_count(obj.billing_cycle)
     try:
         amount = float(request.POST.get('amount'))
     except:
         amount = obj.monthly_cost * months_count
     product = obj.product
     if product:
         short_description = product.name
     else:
         short_description = request.POST.get('short_description', '---')
     obj.details = short_description
     obj.save()
     invoice_entries = []
     item = InvoiceItem(label=_('Subscription'), amount=amount)
     entry = InvoiceEntry(item=item,
                          short_description=short_description,
                          quantity=months_count,
                          total=amount)
     invoice_entries.append(entry)
     invoice = Invoice.objects.create(number=number,
                                      subscription=obj,
                                      amount=amount,
                                      months_count=months_count,
                                      due_date=obj.expiry,
                                      entries=invoice_entries,
                                      is_one_off=True)
     email = request.POST.get('email')
     member_id = request.POST.get('member_id')
     if member_id:
         member = Member.objects.get(pk=member_id) if member_id else None
     elif email:
         try:
             member = Member.objects.filter(email=email)[0]
         except:
             member = Member.objects.create_user(email,
                                                 DEFAULT_GHOST_PWD,
                                                 email=email,
                                                 is_ghost=True)
     else:
         return
     obj.member = member
     obj.save()
     service = get_service_instance()
     config = service.config
     with transaction.atomic(using=WALLETS_DB_ALIAS):
         from echo.models import Balance
         from echo.utils import notify_for_low_messaging_credit, LOW_MAIL_LIMIT, notify_for_empty_messaging_credit
         balance, update = Balance.objects.using(
             WALLETS_DB_ALIAS).get_or_create(service_id=service.id)
         if 0 < balance.mail_count < LOW_MAIL_LIMIT:
             try:
                 notify_for_low_messaging_credit(service, balance)
             except:
                 logger.error(
                     "Failed to notify %s for low messaging credit." %
                     service,
                     exc_info=True)
         if balance.mail_count == 0 and not getattr(settings,
                                                    'UNIT_TESTING', False):
             try:
                 notify_for_empty_messaging_credit(service, balance)
             except:
                 logger.error(
                     "Failed to notify %s for empty messaging credit." %
                     service,
                     exc_info=True)
             return
         if product:
             subject = _("Your invoice for subscription to %s" %
                         product.name)
         else:
             if short_description != '---':
                 subject = _("Your invoice for " + short_description)
             else:
                 subject = _("Your invoice for subscription")
         try:
             currency = currencies(request)['CURRENCY'].symbol
         except:
             currency = config.currency_symbol
         invoice_url = service.url + reverse('billing:invoice_detail',
                                             args=(invoice.id, ))
         html_content = get_mail_content(
             subject,
             template_name='billing/mails/notice.html',
             extra_context={
                 'invoice': invoice,
                 'member_name': member.first_name,
                 'invoice_url': invoice_url,
                 'cta': _("Pay now"),
                 'currency': currency
             })
         sender = '%s <no-reply@%s>' % (config.company_name, service.domain)
         msg = XEmailMessage(subject, html_content, sender, [email])
         msg.content_subtype = "html"
         balance.mail_count -= 1
         balance.save()
         if getattr(settings, 'UNIT_TESTING', False):
             msg.send()
         else:
             Thread(target=lambda m: m.send(), args=(msg, )).start()
Пример #16
0
    def post(self, request, *args, **kwargs):
        form = DeploymentForm(request.POST)
        if form.is_valid():
            project_name = form.cleaned_data.get('project_name')
            # try:
            #     service = Service.objects.using(UMBRELLA).get(project_name=project_name)
            # except:
            #     pass
            app_id = form.cleaned_data.get('app_id')
            business_type = form.cleaned_data.get('business_type')
            business_category_id = form.cleaned_data.get(
                'business_category_id')
            bundle_id = form.cleaned_data.get('bundle_id')
            domain = form.cleaned_data.get('domain')
            theme_id = form.cleaned_data.get('theme_id')
            partner_id = request.COOKIES.get('referrer')
            app = Application.objects.using(UMBRELLA).get(pk=app_id)
            theme = Theme.objects.using(UMBRELLA).get(pk=theme_id)
            business_category = BusinessCategory.objects.using(UMBRELLA).get(
                pk=business_category_id)
            bundle = TsunamiBundle.objects.using(UMBRELLA).get(pk=bundle_id)
            billing_plan = bundle.billing_plan
            billing_cycle = get_months_count_billing_cycle(
                billing_plan.setup_months_count)

            customer = Member.objects.using(UMBRELLA).get(pk=request.user.id)
            setup_cost = billing_plan.setup_cost
            monthly_cost = billing_plan.monthly_cost

            try:
                partner = Service.objects.using(UMBRELLA).get(
                    pk=partner_id) if partner_id else None
            except:
                partner = None

            invoice_entries = []
            domain_name = IkwenInvoiceItem(label='Domain name')
            domain_name_entry = InvoiceEntry(item=domain_name,
                                             short_description=domain)
            invoice_entries.append(domain_name_entry)
            website_setup = IkwenInvoiceItem(label='Website setup',
                                             price=billing_plan.setup_cost,
                                             amount=setup_cost)
            short_description = "%d products" % billing_plan.max_objects
            website_setup_entry = InvoiceEntry(
                item=website_setup,
                short_description=short_description,
                total=setup_cost)
            invoice_entries.append(website_setup_entry)
            if theme.cost > 0:
                theme_item = IkwenInvoiceItem(label='Website theme',
                                              price=theme.cost,
                                              amount=theme.cost)
                theme_entry = InvoiceEntry(item=theme_item,
                                           short_description=theme.name,
                                           total=theme.cost)
                invoice_entries.append(theme_entry)
            i = 0
            while True:
                try:
                    label = request.POST['item%d' % i]
                    amount = float(request.POST['amount%d' % i])
                    if not (label and amount):
                        break
                    item = IkwenInvoiceItem(label=label, amount=amount)
                    entry = InvoiceEntry(item=item, total=amount)
                    invoice_entries.append(entry)
                    i += 1
                except:
                    break
            if getattr(settings, 'DEBUG', False):
                service = deploy(app,
                                 customer,
                                 business_type,
                                 project_name,
                                 billing_plan,
                                 theme,
                                 monthly_cost,
                                 invoice_entries,
                                 billing_cycle,
                                 domain,
                                 business_category,
                                 bundle,
                                 partner_retailer=partner)
            else:
                try:
                    service = deploy(app,
                                     customer,
                                     business_type,
                                     project_name,
                                     billing_plan,
                                     theme,
                                     monthly_cost,
                                     invoice_entries,
                                     billing_cycle,
                                     domain,
                                     business_category,
                                     bundle,
                                     partner_retailer=partner)
                except Exception as e:
                    context = self.get_context_data(**kwargs)
                    context['error'] = e.message
                    return render(request, 'kakocase/tsunami/go.html', context)
            next_url = reverse('kakocase:successful_deployment',
                               args=(service.id, ))
            return HttpResponseRedirect(next_url)
        else:
            context = self.get_context_data(**kwargs)
            context['form'] = form
            return render(request, 'kakocase/tsunami/go.html', context)
Пример #17
0
    def test_pay_one_off_invoice_with_service_having_retailer(self):
        """
        Walks all through the payment from choosing the payment mean,
        setting checkout, confirm payment and having its Service expiry extended.
        If the Service is deployed through a partner. Share earnings accordingly
        """
        call_command('loaddata', 'billing_invoices.yaml')
        call_command('loaddata', 'partners.yaml')
        call_command('loaddata',
                     'ikwen_members.yaml',
                     database='test_kc_partner_jumbo')
        call_command('loaddata',
                     'setup_data.yaml',
                     database='test_kc_partner_jumbo')
        call_command('loaddata',
                     'partners.yaml',
                     database='test_kc_partner_jumbo')
        call_command('loaddata', 'partner_app_retail_config.yaml')
        call_command('loaddata',
                     'partner_app_retail_config.yaml',
                     database='test_kc_partner_jumbo')
        now = datetime.now()
        partner = Service.objects.get(pk='56eb6d04b9b531b10537b331')
        Service.objects.filter(pk='56eb6d04b37b3379b531b102').update(
            expiry=now.date(), retailer=partner)
        item1 = IkwenInvoiceItem(label='item1', amount=10000, price=7000)
        item2 = IkwenInvoiceItem(label='item2', amount=4000, price=0)
        entries = [
            InvoiceEntry(item=item1),
            InvoiceEntry(item=item2, quantity=2)
        ]
        Invoice.objects.filter(pk='56eb6d04b37b3379d531e012').update(
            is_one_off=True, amount=18000, entries=entries)
        self.client.login(username='******', password='******')
        response = self.client.post(reverse('billing:momo_set_checkout'),
                                    {'product_id': '56eb6d04b37b3379d531e012'})
        json_resp = json.loads(response.content)
        notification_url = json_resp['notification_url']
        response = self.client.get(notification_url,
                                   data={
                                       'status': 'Success',
                                       'phone': '655003321',
                                       'message': 'OK',
                                       'operator_tx_id': 'OP_TX_1'
                                   })
        self.assertEqual(response.status_code, 200)
        s = Service.objects.get(pk='56eb6d04b37b3379b531b102')
        new_expiry = now + timedelta(days=30)
        self.assertEqual(s.expiry, new_expiry.date())

        cache.clear()
        service = Service.objects.get(pk='56eb6d04b37b3379b531b102')
        self.assertEqual(service.turnover_history, [18000])
        self.assertEqual(service.invoice_earnings_history, [7000])
        self.assertEqual(service.earnings_history, [7000])
        self.assertEqual(service.invoice_count_history, [1])

        app = service.app
        self.assertEqual(app.turnover_history, [18000])
        self.assertEqual(app.invoice_earnings_history, [7000])
        self.assertEqual(app.earnings_history, [7000])
        self.assertEqual(app.invoice_count_history, [1])

        partner = Service.objects.get(pk='56eb6d04b9b531b10537b331')
        self.assertEqual(partner.turnover_history, [18000])
        self.assertEqual(partner.invoice_earnings_history, [7000])
        self.assertEqual(partner.earnings_history, [7000])
        self.assertEqual(partner.invoice_count_history, [1])

        partner_app = partner.app
        self.assertEqual(partner_app.turnover_history, [18000])
        self.assertEqual(partner_app.invoice_earnings_history, [7000])
        self.assertEqual(partner_app.earnings_history, [7000])
        self.assertEqual(partner_app.invoice_count_history, [1])

        service_mirror = Service.objects.using('test_kc_partner_jumbo').get(
            pk='56eb6d04b37b3379b531b102')
        self.assertEqual(service_mirror.invoice_earnings_history, [11000])
        self.assertEqual(service_mirror.earnings_history, [11000])
        self.assertEqual(service_mirror.invoice_count_history, [1])

        app_mirror = service_mirror.app
        self.assertEqual(app_mirror.invoice_earnings_history, [11000])
        self.assertEqual(app_mirror.earnings_history, [11000])
        self.assertEqual(app_mirror.invoice_count_history, [1])

        partner_wallet = OperatorWallet.objects.using('wallets').get(
            nonrel_id='56eb6d04b9b531b10537b331')
        self.assertEqual(partner_wallet.balance, 11000)