Exemple #1
0
 def save_model(self, request, obj, form, change):
     # Send e-mail for manually generated Invoice upon creation
     if change:
         super(InvoiceAdmin, self).save_model(request, obj, form, change)
         return
     obj.number = get_next_invoice_number(auto=False)
     super(InvoiceAdmin, self).save_model(request, obj, form, change)
     member = obj.subscription.member
     service = get_service_instance()
     config = service.config
     subject, message, sms_text = get_invoice_generated_message(obj)
     if member.email:
         add_event(service, NEW_INVOICE_EVENT, member=member, object_id=obj.id)
         invoice_url = service.url + reverse('billing:invoice_detail', args=(obj.id,))
         html_content = get_mail_content(subject, message, template_name='billing/mails/notice.html',
                                         extra_context={'invoice_url': invoice_url})
         # 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>' % (service.project_name, service.domain)
         msg = EmailMessage(subject, html_content, sender, [member.email])
         msg.content_subtype = "html"
         if msg.send(fail_silently=True):
             obj.reminders_sent = 1
             obj.last_reminder = timezone.now()
     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)
Exemple #2
0
    def save_model(self, request, obj, form, change):
        # Send e-mail for manually generated Invoice upon creation
        super(SubscriptionAdmin, self).save_model(request, obj, form, change)
        if change:
            return

        # Send e-mail only if e-mail is a valid one. It will be agreed that if a client
        # does not have an e-mail. we create a fake e-mail that contains his phone number.
        # So e-mail containing phone number are invalid.
        member = obj.member
        service = get_service_instance()
        config = service.config
        subject, message, sms_text = get_subscription_registered_message(obj)

        # This helps differentiates from fake email accounts created as [email protected]
        if member.email.find(member.phone) < 0:
            add_event(service, SUBSCRIPTION_EVENT, member=member, object_id=obj.id, model=subscription_model_name)
            html_content = get_mail_content(subject, message, template_name='billing/mails/notice.html')
            # 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>' % (service.project_name, service.domain)
            msg = EmailMessage(subject, html_content, sender, [member.email])
            msg.content_subtype = "html"
            Thread(target=lambda m: m.send(), args=(msg,)).start()
        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)
Exemple #3
0
def choose_temp_bundle(request, *args, **kwargs):
    member = request.user
    if kwargs.get('payment_successful', False):
        object_id = request.session.get('object_id')
        if not object_id:
            object_id = kwargs['object_id']
        prepayment = UnitPrepayment.objects.get(pk=object_id)
        now = datetime.now()
        expiry = now + timedelta(days=prepayment.duration)
        prepayment.paid_on = now
        prepayment.expiry = expiry
        prepayment.status = Prepayment.CONFIRMED
        prepayment.save()
        service = get_service_instance()
        sudo_group = Group.objects.get(name=SUDO)
        add_event(service,
                  BUNDLE_PURCHASE,
                  group_id=sudo_group.id,
                  object_id=prepayment.id)
        add_event(service,
                  BUNDLE_PURCHASE,
                  member=member,
                  object_id=prepayment.id)
        if type(prepayment) == UnitPrepayment:
            media = prepayment.get_media()
            timeout = getattr(settings, 'SECURE_LINK_TIMEOUT', 90)
            expires = int(time.time()) + timeout * 60
            if prepayment.amount == media.download_price:
                prepayment.download_link = generate_download_link(
                    media.filename, expires)
                prepayment.save()
        share_payment_and_set_stats(member.customer, prepayment)

    messages.success(request, _("Your bundle was successfully activated."))
Exemple #4
0
def check_stock(request, *args, **kwargs):
    """
    Checks stock of product in order and returns the list of product
    which stock were insufficient stock. Products in that list
    are grabbed from the provider's database and thus carry the
    current available stock.
    """
    order = parse_order_info(request)
    insufficient = []
    for entry in order.entries:
        service = entry.product.provider
        db = service.database
        product_original = entry.product.get_from(db)
        member = service.member
        if product_original.stock < entry.count:
            insufficient.append(product_original)
            try:
                cet = ConsoleEventType.objects.using('umbrella').get(codename=INSUFFICIENT_STOCK_EVENT)
                yesterday = datetime.now() - timedelta(days=1)
                ConsoleEvent.objects.using('umbrella').get(event_type=cet, member=member,
                                                           object_id=product_original.id, created_on__gte=yesterday)
            except ConsoleEvent.DoesNotExist:
                add_event(service, INSUFFICIENT_STOCK_EVENT, member=member, object_id=product_original.id)
    if len(insufficient) > 0:
        response = [product.to_dict() for product in insufficient]
        return HttpResponseRedirect(json.dumps(response), 'content-type: text/json')
Exemple #5
0
def suspend_customers_services():
    """
    This cron task shuts down service and sends notice of Service suspension
    for Invoices which tolerance is exceeded.
    """
    vendor, config, invoicing_config, connection = _init_base_vars()
    now = timezone.now()
    count, total_amount = 0, 0
    deadline = now - timedelta(days=invoicing_config.tolerance)
    invoice_qs = Invoice.objects.filter(due_date__lte=deadline, status=Invoice.OVERDUE)
    print ("%d invoice(s) candidate for service suspension." % invoice_qs.count())
    for invoice in invoice_qs:
        subscription = invoice.subscription
        if not subscription:
            continue
        if getattr(settings, 'IS_IKWEN', False):
            if subscription.version == Service.FREE:
                continue
            _set_actual_vendor(subscription, vendor, config)
        invoice.status = Invoice.EXCEEDED
        invoice.save()
        action = getattr(settings, 'SERVICE_SUSPENSION_ACTION', None)
        if action:
            count += 1
            total_amount += invoice.amount
            action = import_by_path(action)
            try:
                action(subscription)
            except:
                logger.error("Error while processing subscription %s" % str(subscription), exc_info=True)
                continue
            member = subscription.member
            add_event(vendor, SERVICE_SUSPENDED_EVENT, member=member, object_id=invoice.id)
            subject, message, sms_text = get_service_suspension_message(invoice)
            if member.email:
                msg = _get_email_msg(member, subject, message, invoice, vendor, config)
                print ("Sending mail to %s" % member.email)
                try:
                    if msg.send():
                        print ("Mail sent to %s" % member.email)
                    else:
                        print ("Sending mail to %s failed" % member.email)
                        logger.error(u"Notice of suspension for Invoice #%s not sent to %s" % (invoice.number, member.email), exc_info=True)
                except:
                    print ("Sending mail to %s failed" % member.email)
                    logger.error(u"Connexion error on Invoice #%s to %s" % (invoice.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)
    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, SUSPENSION_NOTICES_SENT_EVENT, group_id=sudo_group.id, object_id=report.id)
Exemple #6
0
def submit_order_for_bank_approval(request, order, bank_id, account_number, deal_id=None):
    merchant = get_service_instance()
    bank = Service.objects.get(pk=bank_id)
    payment_mean = PaymentMean.objects.get(slug=bank.project_name_slug)
    order.payment_mean = payment_mean
    entry = order.entries[0]
    product = entry.product
    product.stock -= entry.count
    if product.stock == 0:
        sudo_group = Group.objects.get(name=SUDO)
        add_event(merchant, SOLD_OUT_EVENT, group_id=sudo_group.id, object_id=product.id)
        mark_duplicates(product)
    product.save()
    bank_db = bank.database
    add_database(bank_db)
    try:
        member = Member.objects.using(bank_db).get(pk=order.member.id)
    except Member.DoesNotExist:
        member = order.member
        member.save(using=bank_db)
        group = Group.objects.using(bank_db).get(name=COMMUNITY)
        obj_list, created = UserPermissionList.objects.using(bank_db).get_or_create(user=member)
        obj_list.group_fk_list.append(group.id)
        obj_list.save(using=bank_db)
    account_number_slug = slugify(account_number)
    try:
        BankAccount.objects.using(UMBRELLA).get(slug=account_number_slug)
    except BankAccount.DoesNotExist:
        m = Member.objects.using(UMBRELLA).get(pk=member.id)
        b = Service.objects.using(UMBRELLA).get(pk=bank_id)
        BankAccount.objects.using(UMBRELLA).create(member=m, bank=b, number=account_number, slug=account_number_slug)
    if deal_id:
        if len(order.entries) > 1:
            messages.error(request, _("Terms payment is available only for one single product at a time."))
            return HttpResponseRedirect(reverse('shopping:cart'))
        deal = Deal.objects.using(bank_db).get(pk=deal_id)
    else:
        deal = Deal(bank=bank)
    order.deal = deal
    order.account_number = account_number
    order.status = Order.PENDING_FOR_APPROVAL
    order.save()
    order.save(using=bank_db)
    try:
        del(request.session['object_id'])
    except:
        pass
    subject = _("Order submit for approval")
    send_order_confirmation_email(request, subject, member.full_name, member.email, order)
    bank_profile_original = OperatorProfile.objects.using(bank_db).get(service=bank)
    if bank_profile_original.return_url:
        nvp_dict = {'member': member.full_name, 'email': member.email, 'phone': member.phone,
                    'order_rcc': order.rcc.upper(), 'account_number': account_number,
                    'deal': str(deal), 'merchant': merchant.project_name}
        Thread(target=lambda url, data: requests.post(url, data=data),
               args=(bank_profile_original.return_url, nvp_dict)).start()

    next_url = reverse('shopping:cart', args=(order.id, ))
    return HttpResponseRedirect(next_url)
Exemple #7
0
def suspend_customers_services():
    """
    This cron task shuts down service and sends notice of Service suspension
    for Invoices which tolerance is exceeded.
    """
    service = get_service_instance()
    config = service.config
    now = timezone.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
    deadline = now - timedelta(days=invoicing_config.tolerance)
    invoice_qs = Invoice.objects.filter(due_date__lte=deadline, status=Invoice.OVERDUE)
    logger.debug("%d invoice(s) candidate for service suspension." % invoice_qs.count())
    for invoice in invoice_qs:
        subscription = invoice.subscription
        if subscription.plan.raw_monthly_cost == 0:
            continue
        invoice.status = Invoice.EXCEEDED
        invoice.save()
        count += 1
        total_amount += invoice.amount
        try:
            subscription.is_active = False
            subscription.save()
        except:
            logger.error("Error while processing subscription %s" % str(subscription), exc_info=True)
            continue
        member = subscription.service.member
        add_event(service, SERVICE_SUSPENDED_EVENT, member=member, object_id=invoice.id)
        logger.debug("Event posted to %s's Console" % member.username)
        subject, message, sms_text = get_service_suspension_message(invoice)
        if member.email:
            invoice_url = service.url + reverse('billing:invoice_detail', args=(invoice.id,))
            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"
            logger.debug("Sending mail to %s" % member.email)
            try:
                if msg.send():
                    logger.debug("Mail sent to %s" % member.email)
                else:
                    logger.error(u"Notice of suspension for Invoice #%s not sent to %s" % (invoice.number, member.email), exc_info=True)
            except:
                logger.error(u"Connexion error on Invoice #%s to %s" % (invoice.number, member.email), exc_info=True)
    try:
        connection.close()
    finally:
        pass
Exemple #8
0
def send_invoice_overdue_notices():
    """
    This cron task sends notice of Invoice overdue
    """
    service = get_service_instance()
    config = service.config
    now = timezone.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
    invoice_qs = Invoice.objects.filter(Q(status=Invoice.PENDING) | Q(status=Invoice.OVERDUE),
                                        due_date__lt=now, overdue_notices_sent__lt=3)
    logger.debug("%d invoice(s) candidate for overdue notice." % invoice_qs.count())
    for invoice in invoice_qs:
        subscription = invoice.subscription
        if subscription.plan.raw_monthly_cost == 0:
            continue
        if invoice.last_overdue_notice:
            diff = now - invoice.last_overdue_notice
        else:
            invoice.status = Invoice.OVERDUE
            invoice.save()
        if not invoice.last_overdue_notice or diff.days == invoicing_config.overdue_delay:
            count += 1
            total_amount += invoice.amount
            member = subscription.service.member
            add_event(service, OVERDUE_NOTICE_EVENT, member=member, object_id=invoice.id)
            logger.debug("Event posted to %s's Console" % member.username)
            subject, message, sms_text = get_invoice_overdue_message(invoice)
            if member.email:
                invoice_url = service.url + reverse('billing:invoice_detail', args=(invoice.id,))
                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_overdue_notice = timezone.now()
                logger.debug("Sending mail to %s" % member.email)
                try:
                    if msg.send():
                        logger.debug("Mail sent to %s" % member.email)
                        invoice.overdue_notices_sent += 1
                    else:
                        logger.error(u"Overdue notice for Invoice #%s not sent to %s" % (invoice.number, member.email), exc_info=True)
                except:
                    logger.error(u"Connexion error on Invoice #%s to %s" % (invoice.number, member.email), exc_info=True)
                invoice.save()
    try:
        connection.close()
    finally:
        pass
Exemple #9
0
def submit_cashout_request_for_manual_processing(**kwargs):
    tx = kwargs.get('transaction')
    if tx:
        cashout_request = CashOutRequest.objects.using('wallets').get(
            pk=tx.object_id)
        weblet = Service.objects.using(UMBRELLA).get(pk=tx.service_id)
        wallet = OperatorWallet.objects.using('wallets').get(
            nonrel_id=weblet.id, provider=tx.wallet)
        config = get_config_model().objects.using(UMBRELLA).get(service=weblet)
    else:
        config = kwargs['config']
        wallet = kwargs['wallet']
        cashout_request = kwargs['cashout_request']
        weblet = config.service
    iao = weblet.member
    if getattr(settings, 'TESTING', False):
        IKWEN_SERVICE_ID = getattr(settings, 'IKWEN_ID')
        ikwen_service = Service.objects.get(pk=IKWEN_SERVICE_ID)
    else:
        from ikwen.conf.settings import IKWEN_SERVICE_ID
        ikwen_service = Service.objects.using(UMBRELLA).get(
            pk=IKWEN_SERVICE_ID)
    retailer = weblet.retailer
    if retailer:
        vendor = retailer
    else:
        vendor = ikwen_service
    vendor_config = Config.objects.using(UMBRELLA).get(service=vendor)
    sender = '%s <no-reply@%s>' % (vendor_config.company_name, vendor.domain)

    add_event(vendor,
              CASH_OUT_REQUEST_EVENT,
              member=iao,
              object_id=cashout_request.id)
    subject = _("Cash-out request on %s" % weblet.project_name)
    html_content = get_mail_content(
        subject,
        '',
        template_name='cashout/mails/request_notice.html',
        extra_context={
            'cash_out_request': cashout_request,
            'weblet': weblet,
            'service': vendor,
            'config': vendor_config,
            'iao': iao,
            'wallet': wallet,
            'iao_profile': config
        })
    msg = EmailMessage(subject, html_content, sender, [iao.email])
    msg.bcc = ['*****@*****.**', '*****@*****.**']
    msg.content_subtype = "html"
    Thread(target=lambda m: m.send(), args=(msg, )).start()
    return HttpResponse(
        json.dumps({
            'success': True,
            'manual_processing': True
        }), 'content-type: text/json')
Exemple #10
0
def send_invoice_overdue_notices():
    """
    This cron task sends notice of Invoice overdue
    """
    vendor, config, invoicing_config, connection = _init_base_vars()
    now = timezone.now()
    count, total_amount = 0, 0
    invoice_qs = Invoice.objects.filter(Q(status=Invoice.PENDING) | Q(status=Invoice.OVERDUE),
                                        due_date__lt=now, overdue_notices_sent__lt=3)
    print ("%d invoice(s) candidate for overdue notice." % invoice_qs.count())
    for invoice in invoice_qs:
        subscription = invoice.subscription
        if subscription and getattr(settings, 'IS_IKWEN', False):
            if subscription.version == Service.FREE:
                continue
            _set_actual_vendor(subscription, vendor, config)
        if invoice.last_overdue_notice:
            diff = now - invoice.last_overdue_notice
        else:
            invoice.status = Invoice.OVERDUE
            invoice.save()
        if not invoice.last_overdue_notice or diff.days == invoicing_config.overdue_delay:
            print ("Processing invoice for Service %s" % str(invoice.subscription))
            count += 1
            total_amount += invoice.amount
            member = invoice.subscription.member
            add_event(vendor, OVERDUE_NOTICE_EVENT, member=member, object_id=invoice.id)
            subject, message, sms_text = get_invoice_overdue_message(invoice)
            if member.email:
                msg = _get_email_msg(member, subject, message, invoice, vendor, config)
                invoice.last_overdue_notice = timezone.now()
                print ("Sending mail to %s" % member.email)
                try:
                    if msg.send():
                        print ("Mail sent to %s" % member.email)
                        invoice.overdue_notices_sent += 1
                    else:
                        print ("Sending mail to %s failed" % member.email)
                        logger.error(u"Overdue notice for Invoice #%s not sent to %s" % (invoice.number, member.email), exc_info=True)
                except:
                    print ("Sending mail to %s failed" % member.email)
                    logger.error(u"Connexion error on Invoice #%s to %s" % (invoice.number, member.email), exc_info=True)
                invoice.save()
            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)
    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, OVERDUE_NOTICES_SENT_EVENT, group_id=sudo_group.id, object_id=report.id)
Exemple #11
0
def put_product_in_trash(request, *args, **kwargs):
    # TODO: Implement Trash view itself so that people can view and restore the content of the trash
    config = get_service_instance().config
    selection = request.GET['selection'].split(',')
    deleted = []
    for product_id in selection:
        try:
            product = Product.objects.get(pk=product_id)
            product.in_trash = True
            product.visible = False
            product.save()
            deleted.append(product_id)
            if getattr(settings, 'IS_PROVIDER', False):
                connection = mail.get_connection()
                try:
                    connection.open()
                    connection_opened = True
                except:
                    connection_opened = False
                for retailer_profile in OperatorProfile.objects.filter(business_type=OperatorProfile.RETAILER):
                    member = retailer_profile.service.member
                    service = retailer_profile.service
                    db = service.database
                    add_database_to_settings(db)
                    Product.objects.using(db).get(pk=product_id).delete()
                    ProductCategory.objects.using(db).filter(pk=product.category.id).update(items_count=F('items_count')-1)
                    if product.is_retailed:
                        add_event(service, PROVIDER_REMOVED_PRODUCT_EVENT, member=member, object_id=product_id)
                        if connection_opened:
                            # TODO: Verify what mail looks like after tests once UIs are implemented
                            subject = _("Product taken out by %s" % config.company_name)
                            message = _("Hi %(member_name)s,<br/> The product below was"
                                        "removed by <strong>%(company_name)s.</strong> "
                                        "It won't appear on your website anymore." % {'member_name': member.first_name,
                                                                                      'company_name': config.company_name})
                            html_content = get_mail_content(subject, message,
                                                            template_name='kako/retailer/mails/product_removed.html',
                                                            extra_context={'product': product, 'service': service,
                                                                           'provider_id': config.id})
                            sender = '%s <no-reply@%s.com>' % (service.project_name, service.project_name_slug)
                            msg = EmailMessage(subject, html_content, sender, [member.email])
                            msg.content_subtype = "html"
                            Thread(target=lambda m: m.send(), args=(msg,)).start()

                try:
                    connection.close()
                except:
                    pass
        except Product.DoesNotExist:
            message = "Product %s was not found."
            break
    else:
        message = "%d product(s) moved to trash." % len(selection)
    response = {'message': message, 'deleted': deleted}
    return HttpResponse(json.dumps(response), 'content-type: text/json')
Exemple #12
0
    def save_model(self, request, obj, form, change):
        if obj.status == CashOutRequest.PAID:
            if not obj.reference:
                self.message_user(request, "Reference number missing",
                                  messages.ERROR)
                return
            obj.teller_username = request.user.username
            service = Service.objects.get(pk=obj.service_id)
            wallet = OperatorWallet.objects.using('wallets').get(
                nonrel_id=service.id, provider=obj.provider)
            with transaction.atomic(using='wallets'):
                wallet.balance -= obj.amount_paid
                wallet.save(using='wallets')
                iao = service.member
                if getattr(settings, 'TESTING', False):
                    IKWEN_SERVICE_ID = getattr(settings, 'IKWEN_ID')
                    ikwen_service = Service.objects.get(pk=IKWEN_SERVICE_ID)
                else:
                    from ikwen.conf.settings import IKWEN_SERVICE_ID
                    ikwen_service = Service.objects.get(pk=IKWEN_SERVICE_ID)
                retailer = service.retailer
                if retailer:
                    retailer_config = Config.objects.get(service=retailer)
                    sender = '%s <no-reply@%s>' % (
                        retailer_config.company_name, retailer.domain)
                    event_originator = retailer
                else:
                    sender = 'ikwen <*****@*****.**>'
                    event_originator = ikwen_service

                add_event(event_originator,
                          CASH_OUT_REQUEST_PAID,
                          member=iao,
                          object_id=obj.id)

                subject = _("Money transfer confirmation")
                html_content = get_mail_content(
                    subject,
                    '',
                    template_name='cashout/mails/payment_notice.html',
                    extra_context={
                        'cash_out_request': obj,
                        'business': service,
                        'service': event_originator
                    })
                msg = EmailMessage(subject, html_content, sender, [iao.email])
                msg.content_subtype = "html"
                Thread(target=lambda m: m.send(), args=(msg, )).start()

                set_counters(ikwen_service)
                increment_history_field(ikwen_service, 'cash_out_history',
                                        obj.amount)
                increment_history_field(ikwen_service,
                                        'cash_out_count_history')
        super(CashOutRequestAdmin, self).save_model(request, obj, form, change)
Exemple #13
0
def set_customer_dara(service, referrer, member):
    """
    Binds referrer to member referred.
    :param service: Referred Service
    :param referrer: Member who referred (The Dara)
    :param member: Referred Member
    :return:
    """
    try:
        db = service.database
        add_database(db)
        app = Application.objects.using(db).get(slug=DARAJA)
        dara_service = Service.objects.using(db).get(app=app, member=referrer)
        customer, change = Customer.objects.using(db).get_or_create(member=member)
        if customer.referrer:
            return

        dara_umbrella = Dara.objects.using(UMBRELLA).get(member=referrer)
        if dara_umbrella.level == 1 and dara_umbrella.xp == 1:
            dara_umbrella.xp = 2
            dara_umbrella.raise_bonus_cash(100)
            dara_umbrella.save()

        customer.referrer = dara_service
        customer.save()

        dara_db = dara_service.database
        add_database(dara_db)
        member.save(using=dara_db)
        customer.save(using=dara_db)
        service_mirror = Service.objects.using(dara_db).get(pk=service.id)
        set_counters(service_mirror)
        increment_history_field(service_mirror, 'community_history')

        add_event(service, REFEREE_JOINED_EVENT, member)

        diff = datetime.now() - member.date_joined

        activate(referrer.language)
        sender = "%s via Playground <*****@*****.**>" % member.full_name
        if diff.days > 1:
            subject = _("I'm back on %s !" % service.project_name)
        else:
            subject = _("I just joined %s !" % service.project_name)
        html_content = get_mail_content(subject, template_name='playground/mails/referee_joined.html',
                                        extra_context={'referred_service_name': service.project_name, 'referee': member,
                                                       'dara': dara_umbrella, 'cta_url': 'https://daraja.ikwen.com/'
                                                       })
        msg = EmailMessage(subject, html_content, sender, [referrer.email])
        msg.content_subtype = "html"
        Thread(target=lambda m: m.send(), args=(msg, )).start()
    except:
        logger.error("%s - Error while setting Customer Dara", exc_info=True)
Exemple #14
0
def send_invoice_reminders():
    """
    This cron task sends Invoice reminder notice to the client if unpaid
    """
    vendor, config, invoicing_config, connection = _init_base_vars()
    now = timezone.now()
    count, total_amount = 0, 0
    invoice_qs = Invoice.objects.filter(status=Invoice.PENDING, due_date__gte=now.date(), last_reminder__isnull=False)
    print ("%d invoice(s) candidate for reminder." % invoice_qs.count())
    for invoice in invoice_qs:
        subscription = invoice.subscription
        if getattr(settings, 'IS_IKWEN', False):
            if subscription.version == Service.FREE:
                continue
            _set_actual_vendor(subscription, vendor, config)
        diff = now - invoice.last_reminder
        if diff.days == invoicing_config.reminder_delay:
            print ("Processing invoice for Service %s" % str(invoice.subscription))
            count += 1
            total_amount += invoice.amount
            member = invoice.member
            add_event(vendor, INVOICE_REMINDER_EVENT, member=member, object_id=invoice.id)
            subject, message, sms_text = get_invoice_reminder_message(invoice)
            if member.email:
                msg = _get_email_msg(member, subject, message, invoice, vendor, config)
                invoice.last_reminder = timezone.now()
                print ("Sending mail to %s" % member.email)
                try:
                    if msg.send():
                        print ("Mail sent to %s" % member.email)
                        invoice.reminders_sent += 1
                    else:
                        print ("Sending mail to %s failed" % member.email)
                        logger.error(u"Reminder mail for Invoice #%s not sent to %s" % (invoice.number, member.email), exc_info=True)
                except:
                    print ("Sending mail to %s failed" % member.email)
                    logger.error(u"Connexion error on Invoice #%s to %s" % (invoice.number, member.email), exc_info=True)
                invoice.save()
            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)
    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, REMINDERS_SENT_EVENT, group_id=sudo_group.id, object_id=report.id)
Exemple #15
0
    def save_model(self, request, obj, form, change):
        if obj.status == CashOutRequest.PAID:
            if not obj.reference:
                self.message_user(request, "Reference number missing", messages.ERROR)
                return
            obj.teller_username = request.user.username
            charges = obj.amount * obj.rate / 100
            obj.amount_paid = obj.amount * (100 - obj.rate) / 100
            service = Service.objects.get(pk=obj.service_id)
            wallet = OperatorWallet.objects.using('wallets').get(nonrel_id=service.id, provider=obj.provider)
            method = CashOutMethod.objects.get(slug=obj.provider)
            address = CashOutAddress.objects.using(UMBRELLA).get(service=service, method=method)
            with transaction.atomic(using='wallets'):
                queryset = MoMoTransaction.objects.using('wallets') \
                    .filter(service_id=service.id, created_on__gt=obj.paid_on,
                            is_running=False, status=MoMoTransaction.SUCCESS, wallet=obj.provider)
                aggr = queryset.aggregate(Sum('amount'))
                aggr_fees = queryset.aggregate(Sum('fees'))
                aggr_dara_fees = queryset.aggregate(Sum('dara_fees'))
                amount_successful = 0
                if aggr['amount__sum']:
                    amount_successful = aggr['amount__sum'] - aggr_fees['fees__sum'] - aggr_dara_fees['dara_fees__sum']
                wallet.balance = amount_successful
                wallet.save(using='wallets')
                iao = service.member
                if getattr(settings, 'TESTING', False):
                    IKWEN_SERVICE_ID = getattr(settings, 'IKWEN_ID')
                    ikwen_service = Service.objects.get(pk=IKWEN_SERVICE_ID)
                else:
                    from ikwen.conf.settings import IKWEN_SERVICE_ID
                    ikwen_service = Service.objects.get(pk=IKWEN_SERVICE_ID)
                sender = 'ikwen <*****@*****.**>'
                event_originator = ikwen_service

                add_event(event_originator, CASH_OUT_REQUEST_PAID, member=iao, object_id=obj.id)

                subject = _("Money transfer confirmation")
                html_content = get_mail_content(subject, '', template_name='cashout/mails/payment_notice.html',
                                                extra_context={'cash_out_request': obj, 'charges': charges,
                                                               'weblet': service, 'address': address,
                                                               'service': event_originator})
                msg = EmailMessage(subject, html_content, sender, [iao.email])
                msg.bcc = ['*****@*****.**']
                msg.content_subtype = "html"
                Thread(target=lambda m: m.send(), args=(msg,)).start()

                set_counters(ikwen_service)
                increment_history_field(ikwen_service, 'cash_out_history', obj.amount)
                increment_history_field(ikwen_service, 'cash_out_count_history')
        super(CashOutRequestAdmin, self).save_model(request, obj, form, change)
Exemple #16
0
def choose_retail_bundle(request, *args, **kwargs):
    member = request.user
    # if not member.profile.is_vod_operator:
    #     return HttpResponseForbidden("You are not allowed to order retail bundle.")
    # bundle_id = request.POST.get('bundle_id')
    # if bundle_id:
    #     bundle = RetailBundle.objects.get(pk=bundle_id)
    #     status = request.POST.get('status', Prepayment.PENDING)
    #     purchased_quantity = bundle.quantity
    #     prepayment = RetailPrepayment(member=member, amount=bundle.cost, duration=bundle.duration,
    #                                   adult_authorized=bundle.adult_authorized, status=status)
    # else:
    object_id = request.session.get('object_id')
    if not object_id:
        object_id = kwargs['object_id']
    prepayment = RetailPrepayment.objects.get(pk=object_id)
    purchased_quantity = prepayment.balance
    last_retail_prepayment = member.customer.get_last_retail_prepayment()
    if last_retail_prepayment:
        if last_retail_prepayment.days_left > 0:
            balance = last_retail_prepayment.balance + purchased_quantity
        else:
            balance = purchased_quantity
    else:
        balance = purchased_quantity

    if kwargs.get('payment_successful', False):
        prepayment.balance = balance
        prepayment.status = Prepayment.CONFIRMED
        prepayment.paid_on = datetime.now()
        prepayment.save()
        service = get_service_instance()
        sudo_group = Group.objects.get(name=SUDO)
        add_event(service,
                  BUNDLE_PURCHASE,
                  group_id=sudo_group.id,
                  object_id=prepayment.id)
        add_event(service,
                  BUNDLE_PURCHASE,
                  member=request.user,
                  object_id=prepayment.id)
        share_payment_and_set_stats(member.customer, prepayment)

    messages.success(request, _("Your bundle was successfully activated."))
Exemple #17
0
def check_stock_single(request, *args, **kwargs):
    """
    Checks stock of a single product
    """
    product_id = request.GET['product_id']
    qty = int(request.GET['qty'])
    product = Product.objects.get(pk=product_id)
    service = product.provider
    member = service.member
    if product.stock <= qty:
        try:
            cet = ConsoleEventType.objects.using('umbrella').get(codename=LOW_STOCK_EVENT)
            yesterday = datetime.now() - timedelta(days=1)
            ConsoleEvent.objects.using('umbrella').get(event_type=cet, member=member,
                                                       object_id=product.id, created_on__gte=yesterday)
        except ConsoleEvent.DoesNotExist:
            add_event(service, LOW_STOCK_EVENT, member=member, object_id=product.id)
    if product.stock < qty:
        product.stock = product.stock if product.stock >= product.min_order else 0
        return HttpResponse(json.dumps({'insufficient': True, 'available': product.stock}), 'content-type: text/json')
    return HttpResponse(json.dumps({'success': True}), 'content-type: text/json')
Exemple #18
0
def choose_vod_bundle(request, *args, **kwargs):
    config = get_service_instance().config
    member = request.user

    pay_cash = False
    if config.allow_cash_payment:
        pay_cash = request.POST.get('pay_cash') == 'yes'
    if pay_cash:
        bundle_id = request.POST.get('bundle_id')
        bundle = VODBundle.objects.get(pk=bundle_id)
        status = request.POST.get('status', Prepayment.PENDING)
        prepayment = VODPrepayment(member=member,
                                   amount=bundle.cost,
                                   duration=bundle.duration,
                                   adult_authorized=bundle.adult_authorized,
                                   status=status)
        prepayment.save()
    elif kwargs.get('payment_successful', False):
        object_id = request.session.get('object_id')
        if not object_id:
            object_id = kwargs['object_id']
        prepayment = VODPrepayment.objects.get(pk=object_id)
        prepayment.status = Prepayment.CONFIRMED
        prepayment.paid_on = datetime.now()
        prepayment.save()
        service = get_service_instance()
        sudo_group = Group.objects.get(name=SUDO)
        add_event(service,
                  BUNDLE_PURCHASE,
                  group_id=sudo_group.id,
                  object_id=prepayment.id)
        add_event(service,
                  BUNDLE_PURCHASE,
                  member=request.user,
                  object_id=prepayment.id)
        share_payment_and_set_stats(member.customer, prepayment)

    messages.success(request, _("Your bundle was successfully activated."))
Exemple #19
0
def confirm_invoice_payment(request, *args, **kwargs):
    """
    This function has no URL associated with it.
    It serves as ikwen setting "MOMO_AFTER_CHECKOUT"
    """
    from echo.models import Balance
    from echo.utils import LOW_MAIL_LIMIT, notify_for_low_messaging_credit, notify_for_empty_messaging_credit
    tx = kwargs.get('transaction')
    now = datetime.now()
    service = get_service_instance()
    config = service.config
    invoicing_config = get_invoicing_config_instance()
    invoice_id = request.session['object_id']
    amount = request.session['amount']
    invoice = Invoice.objects.select_related('subscription').get(pk=invoice_id)
    invoice.paid += amount
    invoice.status = Invoice.PAID
    if invoicing_config.processing_fees_on_customer:
        invoice.processing_fees = config.ikwen_share_fixed
    invoice.save()
    payment = Payment.objects.create(invoice=invoice, method=Payment.MOBILE_MONEY,
                                     amount=amount, processor_tx_id=tx.processor_tx_id)
    subscription = invoice.subscription
    if invoicing_config.separate_billing_cycle:
        extra_months = request.session['extra_months']
        total_months = invoice.months_count + extra_months
        days = get_days_count(total_months)
    else:
        extra_months = 0
        days = invoice.subscription.product.duration
        total_months = None
    if subscription.status == Service.SUSPENDED:
        invoicing_config = get_invoicing_config_instance()
        days -= invoicing_config.tolerance  # Catch-up days that were offered before service suspension
        expiry = now + timedelta(days=days)
        expiry = expiry.date()
    elif subscription.expiry:
        expiry = subscription.expiry + timedelta(days=days)
    else:
        expiry = now + timedelta(days=days)
        expiry = expiry.date()
    subscription.expiry = expiry
    subscription.status = Service.ACTIVE
    subscription.save()
    mean = request.session['mean']
    share_payment_and_set_stats(invoice, total_months, mean)
    member = request.user
    sudo_group = Group.objects.using(UMBRELLA).get(name=SUDO)
    add_event(service, PAYMENT_CONFIRMATION, member=member, object_id=invoice.id)
    add_event(service, PAYMENT_CONFIRMATION, group_id=sudo_group.id, object_id=invoice.id)

    if invoicing_config.return_url:
        params = {'reference_id': subscription.reference_id, 'invoice_number': invoice.number,
                  'amount_paid': amount, 'processor_tx_id': tx.processor_tx_id, 'extra_months': extra_months}
        Thread(target=notify_event, args=(service, invoicing_config.return_url, params)).start()

    try:
        invoice_pdf_file = generate_pdf_invoice(invoicing_config, invoice)
    except:
        invoice_pdf_file = None

    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:
            notify_for_empty_messaging_credit(service, balance)
        else:
            try:
                currency = Currency.active.default().symbol
            except:
                currency = config.currency_code
            invoice_url = 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, template_name='billing/mails/notice.html',
                                            extra_context={'member_name': member.first_name, 'invoice': invoice,
                                                           'cta': _("View invoice"), 'invoice_url': invoice_url,
                                                           'currency': currency})
            sender = '%s <no-reply@%s>' % (config.company_name, service.domain)
            msg = XEmailMessage(subject, html_content, sender, [member.email])
            msg.content_subtype = "html"
            if invoice_pdf_file:
                msg.attach_file(invoice_pdf_file)
            balance.mail_count -= 1
            balance.save()
            Thread(target=lambda m: m.send(), args=(msg,)).start()
    return HttpResponseRedirect(request.session['return_url'])
Exemple #20
0
def confirm_service_invoice_payment(request, *args, **kwargs):
    """
    This view is run after successful user cashout "MOMO_AFTER_CHECKOUT"
    """
    status = request.GET['status']
    message = request.GET['message']
    operator_tx_id = request.GET['operator_tx_id']
    phone = request.GET['phone']
    tx_id = kwargs['tx_id']
    extra_months = int(kwargs['extra_months'])
    try:
        tx = MoMoTransaction.objects.using(WALLETS_DB_ALIAS).get(pk=tx_id, is_running=True)
        if not getattr(settings, 'DEBUG', False):
            tx_timeout = getattr(settings, 'IKWEN_PAYMENT_GATEWAY_TIMEOUT', 15) * 60
            expiry = tx.created_on + timedelta(seconds=tx_timeout)
            if datetime.now() > expiry:
                return HttpResponse("Transaction %s timed out." % tx_id)

        tx.status = status
        tx.message = 'OK' if status == MoMoTransaction.SUCCESS else message
        tx.processor_tx_id = operator_tx_id
        tx.phone = phone
        tx.is_running = False
        tx.save()
    except:
        raise Http404("Transaction %s not found" % tx_id)
    if status != MoMoTransaction.SUCCESS:
        return HttpResponse("Notification for transaction %s received with status %s" % (tx_id, status))
    invoice_id = tx.object_id
    amount = tx.amount
    signature = tx.task_id

    callback_signature = kwargs.get('signature')
    no_check_signature = request.GET.get('ncs')
    if getattr(settings, 'DEBUG', False):
        if not no_check_signature:
            if callback_signature != signature:
                return HttpResponse('Invalid transaction signature')
    else:
        if callback_signature != signature:
            return HttpResponse('Invalid transaction signature')
    now = datetime.now()
    ikwen_service = get_service_instance()
    invoice = Invoice.objects.get(pk=invoice_id)
    invoice.paid += amount
    invoice.status = Invoice.PAID
    invoice.save()
    payment = Payment.objects.create(invoice=invoice, method=Payment.MOBILE_MONEY,
                                     amount=amount, processor_tx_id=tx.processor_tx_id)
    service = invoice.service
    total_months = invoice.months_count + extra_months
    days = get_days_count(total_months)
    invoicing_config = get_invoicing_config_instance()
    if service.status == Service.SUSPENDED:
        days -= invoicing_config.tolerance  # Catch-up days that were offered before service suspension
        expiry = now + timedelta(days=days)
        expiry = expiry.date()
    elif service.expiry:
        expiry = service.expiry + timedelta(days=days)
    else:
        expiry = now + timedelta(days=days)
        expiry = expiry.date()
    service.expiry = expiry
    service.status = Service.ACTIVE
    if invoice.is_one_off:
        service.version = Service.FULL
        try:
            support_bundle = SupportBundle.objects.get(type=SupportBundle.TECHNICAL, channel=SupportBundle.PHONE, cost=0)
            token = ''.join([random.SystemRandom().choice(string.digits) for i in range(6)])
            support_expiry = now + timedelta(days=support_bundle.duration)
            SupportCode.objects.create(service=service, token=token, bundle=support_bundle,
                                       balance=support_bundle.quantity, expiry=support_expiry)
            logger.debug("Free Support Code created for %s" % service)
        except SupportBundle.DoesNotExist:
            logger.error("Free Support Code not created for %s" % service, exc_info=True)
    service.save()
    mean = tx.wallet
    is_early_payment = False
    if service.app.slug == 'kakocase' or service.app.slug == 'webnode':
        if invoice.due_date <= now.date():
            is_early_payment = True
        refill_tsunami_messaging_bundle(service, is_early_payment)
    share_payment_and_set_stats(invoice, total_months, mean)
    member = service.member
    vendor = service.retailer
    vendor_is_dara = vendor and vendor.app.slug == DARAJA
    if vendor and not vendor_is_dara:
        add_database_to_settings(vendor.database)
        sudo_group = Group.objects.using(vendor.database).get(name=SUDO)
    else:
        vendor = ikwen_service
        sudo_group = Group.objects.using(UMBRELLA).get(name=SUDO)
    add_event(vendor, PAYMENT_CONFIRMATION, member=member, object_id=invoice.id)
    add_event(vendor, PAYMENT_CONFIRMATION, group_id=sudo_group.id, object_id=invoice.id)

    try:
        invoice_pdf_file = generate_pdf_invoice(invoicing_config, invoice)
    except:
        invoice_pdf_file = None

    if member.email:
        activate(member.language)
        invoice_url = 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")
Exemple #21
0
    def create_user(self, username, password=None, **extra_fields):
        from ikwen.accesscontrol.backends import UMBRELLA
        from ikwen.conf.settings import IKWEN_SERVICE_ID
        if not username:
            raise ValueError('Username must be set')
        try:
            phone = str(extra_fields.get('phone', ''))
            email = extra_fields.get('email', '')
            if phone and phone.startswith('237') and len(
                    phone
            ) == 12:  # When saving ghost contacts '237' is stripped
                phone = phone[3:]
            try:
                member = Member.objects.get(phone=phone, is_ghost=True)
            except:
                try:
                    member = Member.objects.get(email=email, is_ghost=True)
                except:
                    member = Member.objects.get(username=username,
                                                is_ghost=True)
            member.is_ghost = False
            member.username = username
            for key, value in extra_fields.items():
                member.__dict__[key] = value
        except Member.DoesNotExist:
            member = self.model(username=username, **extra_fields)

        member.full_name = u'%s %s' % (member.first_name.split(' ')[0],
                                       member.last_name.split(' ')[0])
        member.tags = slugify(member.first_name + ' ' +
                              member.last_name).replace('-', ' ')
        service_id = getattr(settings, 'IKWEN_SERVICE_ID')
        ikwen_community = Group.objects.using(UMBRELLA).get(name=COMMUNITY)
        member.customer_on_fk_list = [IKWEN_SERVICE_ID]
        member.group_fk_list = [ikwen_community.id]
        service = get_service_instance()
        member.entry_service = service
        if service_id != IKWEN_SERVICE_ID:
            service_community = Group.objects.get(name=COMMUNITY)
            member.customer_on_fk_list.append(service_id)
            member.group_fk_list.append(service_community.id)

        member.set_password(password)
        member.save(using=UMBRELLA)
        member.save(using='default')
        perm_list, created = UserPermissionList.objects.using(
            UMBRELLA).get_or_create(user=member)
        perm_list.group_fk_list.append(ikwen_community.id)
        perm_list.save(using=UMBRELLA)

        from ikwen.accesscontrol.utils import set_member_basic_profile_tags
        set_member_basic_profile_tags(member)

        if service_id != IKWEN_SERVICE_ID:
            # This block is not added above because member must have
            # already been created before we can add an event for that member
            # So, DO NOT MOVE THIS ABOVE
            perm_list, created = UserPermissionList.objects.get_or_create(
                user=member)
            perm_list.group_fk_list.append(service_community.id)
            perm_list.save()
            sudo_group = Group.objects.get(name=SUDO)
            add_event(service,
                      MEMBER_JOINED_IN,
                      group_id=sudo_group.id,
                      object_id=member.id)
            add_event(service,
                      MEMBER_JOINED_IN,
                      member=member,
                      object_id=member.id)

        return member
Exemple #22
0
def send_free_rewards():
    """
    This cron task regularly sends free rewards
    to ikwen member
    """
    ikwen_service = get_service_instance()
    connection = mail.get_connection()
    try:
        connection.open()
    except:
        logger.error(u"Connexion error", exc_info=True)
    t0 = datetime.now()
    member_list = set()
    reward_sent = 0
    mail_sent = 0
    for reward in Reward.objects.select_related('coupon', 'member').filter(
            status=Reward.PREPARED, count__gt=0):
        member = reward.member
        if member in member_list:
            continue
        reward_qs = Reward.objects.filter(member=member,
                                          status=Reward.PREPARED,
                                          count__gt=0)
        reward_count = reward_qs.count()
        last_reward = reward_qs.order_by('-id')[0]
        diff = t0 - last_reward.created_on
        MIN_FOR_SENDING = getattr(settings, 'CR_MIN_FOR_SENDING', 1)
        MAX_NRM_DAYS = getattr(settings, 'CR_MAX_NRM_DAYS',
                               3)  # NRM = No Reward Message
        if reward_count >= MIN_FOR_SENDING or diff.days >= MAX_NRM_DAYS:
            member_list.add(member)
            grouped_rewards = group_rewards_by_service(member)
            reward_sent += 1
            total_coupon = 0
            total_companies = 0
            project_name_list = []
            summary = []
            for service, reward_list in grouped_rewards.items():
                coupons = [
                    '%s: %d' % (reward.coupon.name, reward.count)
                    for reward in reward_list
                ]
                val = service.project_name + ' ' + ','.join(coupons)
                total_coupon += reward.count
                total_companies += 1
                project_name_list.append(service.project_name)
                summary.append(val)
            summary = ' - '.join(summary)
            if last_reward.type == Reward.JOIN:
                add_event(
                    ikwen_service,
                    WELCOME_REWARD_OFFERED,
                    member=member,
                )
            else:
                add_event(
                    ikwen_service,
                    FREE_REWARD_OFFERED,
                    member=member,
                )
            if member.email:
                if member.language:
                    activate(member.language)
                else:
                    activate('en')
                subject = _("%d free coupons are waiting for you" %
                            total_coupon)
                html_content = get_mail_content(
                    subject,
                    '',
                    template_name='rewarding/mails/free_reward.html',
                    extra_context={
                        'member_name': member.first_name,
                        'grouped_rewards': grouped_rewards,
                        'total_coupon': total_coupon,
                        'total_companies': total_companies,
                        'project_names': ', '.join(project_name_list)
                    })
                sender = 'ikwen <*****@*****.**>'
                msg = EmailMessage(subject, html_content, sender,
                                   [member.email])
                msg.content_subtype = "html"
                try:
                    if msg.send():
                        for service, reward_list in grouped_rewards.items():
                            db = service.database
                            add_database(db)
                            service_original = Service.objects.using(db).get(
                                pk=service.id)
                            XEmailObject.objects.using(db).create(
                                to=member.email,
                                subject=subject,
                                body=html_content,
                                type=XEmailObject.REWARDING,
                                status="OK")
                            set_counters(service_original)
                            increment_history_field(service_original,
                                                    'rewarding_email_history')
                        mail_sent += 1
                        logger.debug(u"Free reward sent to %s: %s. %s" %
                                     (member.username, member.email, summary))
                    else:
                        logger.error(
                            u"Free reward set but not sent to %s: %s. %s" %
                            (member.username, member.email, summary),
                            exc_info=True)
                except:
                    logger.error(
                        u"Free reward set but not sent to %s: %s. %s" %
                        (member.username, member.email, summary),
                        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)
    for member in member_list:
        Reward.objects.filter(
            member=member, status=Reward.PREPARED).update(status=Reward.SENT)
    try:
        connection.close()
    finally:
        pass
    duration = datetime.now() - t0
    logger.debug("send_free_rewards() run in %d seconds" % duration.seconds)
Exemple #23
0
def deploy(app,
           member,
           business_type,
           project_name,
           billing_plan,
           theme,
           monthly_cost,
           invoice_entries,
           billing_cycle,
           domain=None,
           business_category=None,
           bundle=None,
           partner_retailer=None):
    project_name_slug = slugify(
        project_name)  # Eg: slugify('Cool Shop') = 'cool-shop'
    ikwen_name = project_name_slug.replace('-',
                                           '')  # Eg: cool-shop --> 'coolshop'
    pname = ikwen_name
    i = 0
    while True:
        try:
            Service.objects.using(UMBRELLA).get(project_name_slug=pname)
            i += 1
            pname = "%s%d" % (ikwen_name, i)
        except Service.DoesNotExist:
            ikwen_name = pname
            break
    api_signature = generate_random_key(30, alpha_num=True)
    while True:
        try:
            Service.objects.using(UMBRELLA).get(api_signature=api_signature)
            api_signature = generate_random_key(30, alpha_num=True)
        except Service.DoesNotExist:
            break
    database = ikwen_name
    domain = 'go.' + pname + '.ikwen.com'
    domain_type = Service.SUB
    is_naked_domain = False
    url = 'http://go.ikwen.com/' + pname
    if getattr(settings, 'IS_UMBRELLA', False):
        admin_url = url + '/ikwen' + reverse('ikwen:staff_router')
    else:  # This is a deployment performed by a partner retailer
        admin_url = url + reverse('ikwen:staff_router')
    is_pro_version = billing_plan.is_pro_version
    now = datetime.now()
    expiry = now + timedelta(days=15)

    # Create a copy of template application in the Cloud folder
    app_folder = CLOUD_HOME + '000Tpl/AppSkeleton'
    website_home_folder = CLOUD_FOLDER + ikwen_name
    media_root = CLUSTER_MEDIA_ROOT + ikwen_name + '/'
    media_url = CLUSTER_MEDIA_URL + ikwen_name + '/'
    default_images_folder = CLOUD_FOLDER + '000Tpl/images/000Default'
    theme_images_folder = CLOUD_FOLDER + '000Tpl/images/%s/%s' % (
        theme.template.slug, theme.slug)
    if os.path.exists(theme_images_folder):
        if os.path.exists(media_root):
            shutil.rmtree(media_root)
        shutil.copytree(theme_images_folder, media_root)
        logger.debug("Media folder '%s' successfully created from '%s'" %
                     (media_root, theme_images_folder))
    elif os.path.exists(default_images_folder):
        if os.path.exists(media_root):
            shutil.rmtree(media_root)
        shutil.copytree(default_images_folder, media_root)
        logger.debug("Media folder '%s' successfully created from '%s'" %
                     (media_root, default_images_folder))
    elif not os.path.exists(media_root):
        os.makedirs(media_root)
        logger.debug("Media folder '%s' successfully created empty" %
                     media_root)
    favicons_folder = media_root + 'icons'
    if not os.path.exists(favicons_folder):
        os.makedirs(favicons_folder)
    if os.path.exists(website_home_folder):
        shutil.rmtree(website_home_folder)
    shutil.copytree(app_folder, website_home_folder)
    logger.debug("Service folder '%s' successfully created" %
                 website_home_folder)

    can_manage_delivery_options = False
    if business_type == OperatorProfile.PROVIDER:
        settings_template = 'kakocase/cloud_setup/settings.provider.html'
        can_manage_delivery_options = True
    elif business_type == OperatorProfile.RETAILER:
        settings_template = 'kakocase/cloud_setup/settings.retailer.html'
    elif business_type == OperatorProfile.LOGISTICS:
        settings_template = 'kakocase/cloud_setup/settings.delivery.html'
        auth_code = ikwen_name[:4] + now.strftime('%S')
    elif business_type == OperatorProfile.BANK:
        settings_template = 'kakocase/cloud_setup/settings.bank.html'

    service = Service(member=member,
                      app=app,
                      project_name=project_name,
                      project_name_slug=ikwen_name,
                      domain=domain,
                      database=database,
                      url=url,
                      domain_type=domain_type,
                      expiry=expiry,
                      admin_url=admin_url,
                      billing_plan=billing_plan,
                      billing_cycle=billing_cycle,
                      monthly_cost=monthly_cost,
                      version=Service.TRIAL,
                      retailer=partner_retailer,
                      api_signature=api_signature,
                      home_folder=website_home_folder,
                      settings_template=settings_template)
    service.save(using=UMBRELLA)
    logger.debug("Service %s successfully created" % pname)

    if business_type == OperatorProfile.RETAILER:
        # Copy Categories image to local media folder as the Retailer is allowed to change them
        pass

    # Re-create settings.py file as well as apache.conf file for the newly created project
    secret_key = generate_django_secret_key()
    if is_naked_domain:
        allowed_hosts = '"%s", "www.%s"' % (domain, domain)
    else:
        allowed_hosts = '"go.ikwen.com"'
    settings_tpl = get_template(settings_template)
    settings_context = Context({
        'secret_key': secret_key,
        'ikwen_name': ikwen_name,
        'service': service,
        'static_root': STATIC_ROOT,
        'static_url': STATIC_URL,
        'media_root': media_root,
        'media_url': media_url,
        'allowed_hosts': allowed_hosts,
        'debug': getattr(settings, 'DEBUG', False)
    })
    settings_file = website_home_folder + '/conf/settings.py'
    fh = open(settings_file, 'w')
    fh.write(settings_tpl.render(settings_context))
    fh.close()
    logger.debug("Settings file '%s' successfully created" % settings_file)

    # Import template database and set it up
    if business_type == OperatorProfile.BANK:
        db_folder = CLOUD_FOLDER + '000Tpl/DB/CashFlex'
    else:
        db_folder = CLOUD_FOLDER + '000Tpl/DB/000Default'
        theme_db_folder = CLOUD_FOLDER + '000Tpl/DB/%s/%s' % (
            theme.template.slug, theme.slug)
        if os.path.exists(theme_db_folder):
            db_folder = theme_db_folder

    host = getattr(settings, 'DATABASES')['default'].get('HOST', '127.0.0.1')
    subprocess.call(
        ['mongorestore', '--host', host, '-d', database, db_folder])
    logger.debug("Database %s successfully created on host %s from %s" %
                 (database, host, db_folder))

    add_database_to_settings(database)
    for group in Group.objects.using(database).all():
        try:
            gpl = GroupPermissionList.objects.using(database).get(group=group)
            group.delete()
            group.save(using=database
                       )  # Recreate the group in the service DB with a new id.
            gpl.group = group  # And update GroupPermissionList object with the newly re-created group
            gpl.save(using=database)
        except GroupPermissionList.DoesNotExist:
            group.delete()
            group.save(using=database
                       )  # Re-create the group in the service DB with anyway.
    new_sudo_group = Group.objects.using(database).get(name=SUDO)

    for s in member.get_services():
        db = s.database
        add_database_to_settings(db)
        collaborates_on_fk_list = member.collaborates_on_fk_list + [service.id]
        customer_on_fk_list = member.customer_on_fk_list + [service.id]
        group_fk_list = member.group_fk_list + [new_sudo_group.id]
        Member.objects.using(db).filter(pk=member.id).update(
            collaborates_on_fk_list=collaborates_on_fk_list,
            customer_on_fk_list=customer_on_fk_list,
            group_fk_list=group_fk_list)

    member.collaborates_on_fk_list = collaborates_on_fk_list
    member.customer_on_fk_list = customer_on_fk_list
    member.group_fk_list = group_fk_list

    member.is_iao = True
    member.save(using=UMBRELLA)

    member.is_bao = True
    member.is_staff = True
    member.is_superuser = True

    app.save(using=database)
    member.save(using=database)
    logger.debug("Member %s access rights successfully set for service %s" %
                 (member.username, pname))

    from ikwen.billing.mtnmomo.views import MTN_MOMO
    from ikwen.billing.orangemoney.views import ORANGE_MONEY
    # Copy payment means to local database
    for mean in PaymentMean.objects.using(UMBRELLA).all():
        if mean.slug == 'paypal':
            mean.action_url_name = 'shopping:paypal_set_checkout'
        if mean.slug == MTN_MOMO:
            mean.is_main = True
            mean.is_active = True
        elif mean.slug == ORANGE_MONEY:
            mean.is_main = False
            mean.is_active = True
        else:
            mean.is_main = False
            mean.is_active = False
        mean.save(using=database)
        logger.debug("PaymentMean %s created in database: %s" %
                     (mean.slug, database))

    # Copy themes to local database
    for template in Template.objects.using(UMBRELLA).all():
        template.save(using=database)
    for th in Theme.objects.using(UMBRELLA).all():
        th.save(using=database)
    logger.debug("Template and theme successfully bound for service: %s" %
                 pname)

    FlatPage.objects.using(database).get_or_create(
        url=FlatPage.AGREEMENT,
        title=FlatPage.AGREEMENT.capitalize(),
        content=_('Agreement goes here'))
    FlatPage.objects.using(database).get_or_create(
        url=FlatPage.LEGAL_MENTIONS,
        title=FlatPage.LEGAL_MENTIONS.capitalize(),
        content=_('Legal mentions go here'))

    # Add member to SUDO Group
    obj_list, created = UserPermissionList.objects.using(
        database).get_or_create(user=member)
    obj_list.group_fk_list.append(new_sudo_group.id)
    obj_list.save(using=database)
    logger.debug("Member %s successfully added to sudo group for service: %s" %
                 (member.username, pname))

    # Create wallets
    wallet = OperatorWallet.objects.using('wallets').create(
        nonrel_id=service.id, provider=MTN_MOMO)
    OperatorWallet.objects.using('wallets').create(nonrel_id=service.id,
                                                   provider=ORANGE_MONEY)
    mail_signature = "%s<br>" \
                     "<a href='%s'>%s</a>" % (project_name, 'http://' + domain, domain)
    invitation_message = _(
        "Hey $client<br>"
        "We are inviting you to join our awesome community on ikwen.")
    config = OperatorProfile(
        service=service,
        rel_id=wallet.id,
        media_url=media_url,
        ikwen_share_fixed=billing_plan.tx_share_fixed,
        ikwen_share_rate=billing_plan.tx_share_rate,
        can_manage_delivery_options=can_manage_delivery_options,
        business_type=business_type,
        is_pro_version=is_pro_version,
        theme=theme,
        currency_code='XAF',
        currency_symbol='XAF',
        signature=mail_signature,
        max_products=billing_plan.max_objects,
        decimal_precision=0,
        company_name=project_name,
        contact_email=member.email,
        contact_phone=member.phone,
        business_category=business_category,
        bundle=bundle,
        sms_api_script_url=SMS_API_URL,
        invitation_message=invitation_message)
    config.save(using=UMBRELLA)
    base_config = config.get_base_config()
    base_config.save(using=UMBRELLA)
    from daraja.models import DARAJA
    if partner_retailer:
        partner_retailer.save(using=database)
        try:
            if partner_retailer.app.slug == DARAJA:
                partner_db = partner_retailer.database
                add_database_to_settings(partner_db)
                ikwen_service_partner = Service.objects.using(partner_db).get(
                    project_name_slug='ikwen')
                set_counters(ikwen_service_partner)
                increment_history_field(ikwen_service_partner,
                                        'community_history')
        except:
            logger.error(
                "Could not set Followers count upon Service deployment",
                exc_info=True)

    if bundle:  # Tsunami bundle
        from echo.models import Balance
        token = ''.join(
            [random.SystemRandom().choice(string.digits) for i in range(6)])
        expiry = now + timedelta(days=bundle.support_bundle.duration)
        SupportCode.objects.using(UMBRELLA).create(
            service=service,
            bundle=bundle.support_bundle,
            token=token,
            expiry=expiry)
        Balance.objects.using('wallets').create(service_id=service.id)

    service.save(using=database)
    if business_type == OperatorProfile.LOGISTICS:
        config.auth_code = auth_code

    theme.save(using=database
               )  # Causes theme to be routed to the newly created database
    if business_category:
        business_category.save(using=database)
    config.save(using=database)

    InvoicingConfig.objects.using(database).create()
    logger.debug("Configuration successfully added for service: %s" % pname)

    # Copy samples to local database
    for product in Product.objects.using(database).all():
        product.provider = service
        product.save(using=database)
    logger.debug("Sample products successfully copied to database %s" %
                 database)

    # Create delivery options: Pick-up in store and Free home delivery
    DeliveryOption.objects.using(database).create(
        company=service,
        type=DeliveryOption.PICK_UP_IN_STORE,
        name=_("Pick up in store"),
        slug='pick-up-in-store',
        short_description=_("2H after order"),
        cost=0,
        max_delay=2)
    DeliveryOption.objects.using(database).create(
        company=service,
        type=DeliveryOption.HOME_DELIVERY,
        name=_("Home delivery"),
        slug='home-delivery',
        short_description=_("Max. 72H after order"),
        cost=500,
        max_delay=72)

    # Apache Server cloud_setup
    go_apache_tpl = get_template('core/cloud_setup/apache.conf.local.html')
    apache_context = Context({
        'is_naked_domain': is_naked_domain,
        'domain': domain,
        'home_folder': website_home_folder,
        'ikwen_name': ikwen_name
    })
    if is_naked_domain:
        apache_tpl = get_template('kakocase/cloud_setup/apache.conf.html')
        fh = open(website_home_folder + '/apache.conf', 'w')
        fh.write(apache_tpl.render(apache_context))
        fh.close()
    fh = open(website_home_folder + '/go_apache.conf', 'w')
    fh.write(go_apache_tpl.render(apache_context))
    fh.close()

    vhost = '/etc/apache2/sites-enabled/go_ikwen/' + pname + '.conf'
    subprocess.call(
        ['sudo', 'ln', '-sf', website_home_folder + '/go_apache.conf', vhost])
    if is_naked_domain:
        vhost = '/etc/apache2/sites-enabled/' + domain + '.conf'
        subprocess.call(
            ['sudo', 'ln', '-sf', website_home_folder + '/apache.conf', vhost])
    logger.debug("Apache Virtual Host '%s' successfully created" % vhost)

    # Send notification and Invoice to customer
    number = get_next_invoice_number()
    now = datetime.now()
    invoice_total = 0
    for entry in invoice_entries:
        invoice_total += entry.item.amount * entry.quantity
    invoice = Invoice(subscription=service,
                      member=member,
                      amount=invoice_total,
                      number=number,
                      due_date=expiry,
                      last_reminder=now,
                      reminders_sent=1,
                      is_one_off=True,
                      entries=invoice_entries,
                      months_count=billing_plan.setup_months_count)
    invoice.save(using=UMBRELLA)
    vendor = get_service_instance()

    if member != vendor.member:
        add_event(vendor,
                  SERVICE_DEPLOYED,
                  member=member,
                  object_id=invoice.id)
    if partner_retailer and partner_retailer.app.slug != DARAJA:
        partner_profile = PartnerProfile.objects.using(UMBRELLA).get(
            service=partner_retailer)
        try:
            Member.objects.get(pk=member.id)
        except Member.DoesNotExist:
            member.is_iao = False
            member.is_bao = False
            member.is_staff = False
            member.is_superuser = False
            member.save(using='default')
        service.save(using='default')
        config.save(using='default')
        sender = '%s <no-reply@%s>' % (partner_profile.company_name,
                                       partner_retailer.domain)
        sudo_group = Group.objects.get(name=SUDO)
        ikwen_sudo_gp = Group.objects.using(UMBRELLA).get(name=SUDO)
        add_event(vendor,
                  SERVICE_DEPLOYED,
                  group_id=ikwen_sudo_gp.id,
                  object_id=invoice.id)
    elif partner_retailer and partner_retailer.app.slug == DARAJA:
        try:
            dara_member = partner_retailer.member
            dara = Dara.objects.get(member=dara_member)
            dara_earnings = invoice_total * dara.share_rate / 100
            phone = member.phone
            if len(phone) == 9 and not phone.startswith('237'):
                member.phone = '237' + member.phone

            template_name = 'daraja/mails/remind_referrer.html'
            activate(dara_member.language)
            subject = _("Congratulations ! %s CFA is waiting for you." %
                        intcomma(dara_earnings))
            try:
                extra_context = {
                    'referee': member,
                    'amount': dara_earnings,
                    'invoice_total': intcomma(invoice_total),
                    'deployed_service': service,
                    'dara_name': dara_member.full_name
                }
                html_content = get_mail_content(subject,
                                                template_name=template_name,
                                                extra_context=extra_context)
                sender = 'ikwen Daraja <*****@*****.**>'
                msg = EmailMessage(subject, html_content, sender,
                                   [dara_member.email])
                msg.content_subtype = "html"
                Thread(target=lambda m: m.send(), args=(msg, )).start()
            except:
                logger.error(
                    "Failed to notify %s Dara after follower deployed Kakocase website."
                    % dara_member.full_name,
                    exc_info=True)
        except Dara.DoesNotExist:
            logging.error("%s - Customer %s has not been referred" %
                          (service.project_name, member.username))
    else:
        sender = 'ikwen Tsunami <*****@*****.**>'
        sudo_group = Group.objects.using(UMBRELLA).get(name=SUDO)
    add_event(vendor,
              SERVICE_DEPLOYED,
              group_id=sudo_group.id,
              object_id=invoice.id)
    invoice_url = 'http://www.ikwen.com' + reverse('billing:invoice_detail',
                                                   args=(invoice.id, ))
    activate(member.language)
    subject = _("Your website %s was created" % project_name)
    html_content = get_mail_content(
        subject,
        template_name='core/mails/service_deployed.html',
        extra_context={
            'service_activated': service,
            'invoice': invoice,
            'member': member,
            'invoice_url': invoice_url
        })
    msg = EmailMessage(subject, html_content, sender, [member.email])
    bcc = ['*****@*****.**', '*****@*****.**']
    if vendor.config.contact_email:
        bcc.append(vendor.config.contact_email)
    msg.bcc = list(set(bcc))
    msg.content_subtype = "html"
    Thread(target=lambda m: m.send(), args=(msg, )).start()
    logger.debug("Notice email submitted to %s" % member.email)
    Thread(target=reload_server).start()
    logger.debug("Apache Scheduled to reload in 5s")
    return service
Exemple #24
0
def reward_member(service, member, type, **kwargs):
    """
    Rewards a Member on a Service according the the type
    of reward.

    :param service: Service on which the member is interacting
    :param member: Member actually concerned
    :param type: Type of reward. Can be Reward.JOIN, Reward.PAYMENT or Reward.MANUAL
    :param kwargs: kwargs must be provided depending on type.

        # Reward.PAYMENT, following kwargs are expected:
            *amount*: amount actually paid by Member
            *object_id*: ID of the object paid
            *model_name*: Django style model name. *Eg: trade.Order*

        # Reward.MANUAL, following kwargs are expected:
            *coupon*: Coupon being donated to the Member
            *count*: number of coupon given

    :return: A tuple (list of JoinRewardPack or PaymentRewardPack, total_coupon_count)
    """
    now = datetime.now()
    try:
        # All rewarding actions are run only if
        # Operator has an active profile.
        CROperatorProfile.objects.using(UMBRELLA).get(service=service,
                                                      is_active=True)
    except CROperatorProfile.DoesNotExist:
        return None, 0
    reward_pack = None
    reward_pack_list = []
    coupon_count = 0
    service = Service.objects.using(UMBRELLA).get(pk=service.id)
    member = Member.objects.using(UMBRELLA).get(pk=member.id)
    profile, update = CRProfile.objects.get_or_create(member=member)
    coupon_summary, update = CouponSummary.objects.using(
        UMBRELLA).get_or_create(service=service, member=member)
    if type == Reward.JOIN:
        for coupon in Coupon.objects.using(UMBRELLA).filter(service=service):
            try:
                reward_pack = JoinRewardPack.objects.using(UMBRELLA).select_related('service', 'coupon')\
                    .get(service=service, coupon=coupon)
                if reward_pack.count > 0:
                    reward_pack_list.append(reward_pack)
                    cumul, update = CumulatedCoupon.objects.using(
                        UMBRELLA).get_or_create(member=member, coupon=coupon)
                    cumul.count += reward_pack.count
                    cumul.save()
                    Reward.objects.using(UMBRELLA).create(
                        service=service,
                        member=member,
                        coupon=coupon,
                        count=reward_pack.count,
                        type=Reward.JOIN,
                        status=Reward.SENT)
                    coupon_summary.count += reward_pack.count
                    coupon_count += reward_pack.count
                    if cumul.count >= coupon.heap_size:
                        CouponWinner.objects.using(UMBRELLA).create(
                            member=member, coupon=coupon)
                        coupon_summary.threshold_reached = True
                    profile.coupon_score += reward_pack.count * coupon.coefficient
            except JoinRewardPack.DoesNotExist:
                continue
        else:
            profile.reward_score = CRProfile.FREE_REWARD
        if reward_pack:
            add_event(service, WELCOME_REWARD_OFFERED, member)
    elif type == Reward.REFERRAL:
        for coupon in Coupon.objects.using(UMBRELLA).filter(service=service):
            try:
                reward_pack = ReferralRewardPack.objects.using(UMBRELLA).select_related('service', 'coupon')\
                    .get(service=service, coupon=coupon)
                if reward_pack.count > 0:
                    reward_pack_list.append(reward_pack)
                    cumul, update = CumulatedCoupon.objects.using(
                        UMBRELLA).get_or_create(member=member, coupon=coupon)
                    cumul.count += reward_pack.count
                    cumul.save()
                    Reward.objects.using(UMBRELLA).create(
                        service=service,
                        member=member,
                        coupon=coupon,
                        count=reward_pack.count,
                        type=Reward.REFERRAL,
                        status=Reward.SENT)
                    coupon_summary.count += reward_pack.count
                    if cumul.count >= coupon.heap_size:
                        CouponWinner.objects.using(UMBRELLA).create(
                            member=member, coupon=coupon)
                        coupon_summary.threshold_reached = True
                    profile.coupon_score += reward_pack.count * coupon.coefficient
                    coupon_count += reward_pack.count
            except ReferralRewardPack.DoesNotExist:
                continue
        else:
            profile.reward_score = CRProfile.FREE_REWARD
        if reward_pack:
            add_event(service, REFERRAL_REWARD_OFFERED, member)
    elif type == Reward.PAYMENT:
        amount = kwargs.pop('amount')
        object_id = kwargs.pop('object_id', None)
        model_name = kwargs.pop('model_name', None)
        for coupon in Coupon.objects.using(UMBRELLA).filter(service=service):
            try:
                reward_pack = PaymentRewardPack.objects.using(UMBRELLA).select_related('service', 'coupon')\
                    .get(service=service, coupon=coupon, floor__lt=amount, ceiling__gte=amount)
                if reward_pack.count > 0:
                    reward_pack_list.append(reward_pack)
                    cumul, update = CumulatedCoupon.objects.using(
                        UMBRELLA).get_or_create(member=member, coupon=coupon)
                    cumul.count += reward_pack.count
                    cumul.save()
                    Reward.objects.using(UMBRELLA).create(
                        service=service,
                        member=member,
                        coupon=coupon,
                        count=reward_pack.count,
                        type=Reward.PAYMENT,
                        status=Reward.SENT,
                        object_id=object_id,
                        amount=amount)
                    coupon_summary.count += reward_pack.count
                    if cumul.count >= coupon.heap_size:
                        CouponWinner.objects.using(UMBRELLA).create(
                            member=member, coupon=coupon)
                        coupon_summary.threshold_reached = True
                    coupon_summary.save()
                    profile.coupon_score += reward_pack.count * coupon.coefficient
                    coupon_count += reward_pack.count
            except PaymentRewardPack.DoesNotExist:
                continue
        else:
            profile.reward_score = CRProfile.PAYMENT_REWARD
        if reward_pack:
            add_event(service,
                      PAYMENT_REWARD_OFFERED,
                      member,
                      object_id=object_id,
                      model=model_name)
    elif type == Reward.MANUAL:
        coupon = kwargs.pop('coupon')
        count = kwargs.pop('count')
        cumul, update = CumulatedCoupon.objects.using(UMBRELLA).get_or_create(
            member=member, coupon=coupon)
        cumul.count += count
        cumul.save()
        Reward.objects.using(UMBRELLA).create(service=service,
                                              member=member,
                                              coupon=coupon,
                                              count=count,
                                              type=Reward.MANUAL,
                                              status=Reward.SENT)
        coupon_summary.count += count
        if cumul.count >= coupon.heap_size:
            CouponWinner.objects.using(UMBRELLA).create(member=member,
                                                        coupon=coupon)
            coupon_summary.threshold_reached = True
        coupon_summary.save()
        profile.coupon_score += count * coupon.coefficient
        profile.reward_score = CRProfile.MANUAL_REWARD
        add_event(service, MANUAL_REWARD_OFFERED, member)
    profile.save()
    coupon_summary.save()
    return reward_pack_list, coupon_count
Exemple #25
0
def deploy(member):
    app = Application.objects.get(slug=DARAJA)
    daraja_service = Service.objects.get(project_name_slug=DARAJA)
    project_name_slug = slugify(member.username)
    ikwen_name = project_name_slug.replace('-', '')
    pname = ikwen_name
    i = 0
    while True:
        try:
            Service.objects.using(UMBRELLA).get(project_name_slug=pname)
            i += 1
            pname = "%s%d" % (ikwen_name, i)
        except Service.DoesNotExist:
            ikwen_name = pname
            break
    api_signature = generate_random_key(30, alpha_num=True)
    while True:
        try:
            Service.objects.using(UMBRELLA).get(api_signature=api_signature)
            api_signature = generate_random_key(30)
        except Service.DoesNotExist:
            break
    database = ikwen_name
    domain = 'go.' + pname + '.ikwen.com'
    now = datetime.now()
    expiry = now + timedelta(days=15)

    service = Service(member=member,
                      app=app,
                      project_name=member.full_name,
                      project_name_slug=ikwen_name,
                      domain=domain,
                      database=database,
                      expiry=expiry,
                      monthly_cost=0,
                      version=Service.FREE,
                      api_signature=api_signature)
    service.save(using=UMBRELLA)
    logger.debug("Service %s successfully created" % pname)

    # Import template database and set it up
    db_folder = DARAJA_CLOUD_FOLDER + '000Tpl/DB/000Default'
    host = getattr(settings, 'DATABASES')['default'].get('HOST', '127.0.0.1')
    subprocess.call(
        ['mongorestore', '--host', host, '-d', database, db_folder])
    logger.debug("Database %s successfully created on host %s from %s." %
                 (database, host, db_folder))

    add_database_to_settings(database)

    for s in member.get_services():
        db = s.database
        add_database_to_settings(db)
        collaborates_on_fk_list = member.collaborates_on_fk_list + [
            daraja_service.id
        ]
        customer_on_fk_list = member.customer_on_fk_list + [daraja_service.id]
        Member.objects.using(db).filter(pk=member.id).update(
            collaborates_on_fk_list=collaborates_on_fk_list,
            customer_on_fk_list=customer_on_fk_list)

    member.collaborates_on_fk_list = collaborates_on_fk_list
    member.customer_on_fk_list = customer_on_fk_list

    member.is_iao = True
    member.save(using=UMBRELLA)

    member.is_bao = True
    member.is_staff = True
    member.is_superuser = True

    app.save(using=database)
    member.save(using=database)
    logger.debug("Member %s access rights successfully set for service %s" %
                 (member.username, pname))

    # Add member to SUDO Group
    obj_list, created = UserPermissionList.objects.using(
        database).get_or_create(user=member)
    obj_list.save(using=database)
    logger.debug("Member %s successfully added to sudo group for service: %s" %
                 (member.username, pname))
    config = Config(service=service,
                    cash_out_rate=DARAJA_IKWEN_SHARE_RATE,
                    currency_code='XAF',
                    currency_symbol='XAF',
                    decimal_precision=0,
                    company_name=ikwen_name,
                    contact_email=member.email,
                    contact_phone=member.phone,
                    sms_api_script_url=SMS_API_URL)
    config.save(using=UMBRELLA)
    service.save(using=database)

    # Send notification and Invoice to customer
    vendor = get_service_instance()
    add_event(vendor, SERVICE_DEPLOYED, member=member)
    sender = 'ikwen Daraja <*****@*****.**>'
    sudo_group = Group.objects.using(UMBRELLA).get(name=SUDO)
    add_event(vendor, SERVICE_DEPLOYED, group_id=sudo_group.id)
    subject = _("Welcome to the business network.")
    registered_company_list_url = vendor.url + reverse(
        'daraja:registered_company_list')
    html_content = get_mail_content(
        subject,
        template_name='daraja/mails/service_deployed.html',
        extra_context={
            'registered_company_list_url': registered_company_list_url,
            'member': member
        })
    msg = EmailMessage(subject, html_content, sender, [member.email])
    bcc = ['*****@*****.**']
    msg.bcc = list(set(bcc))
    msg.content_subtype = "html"
    Thread(target=lambda m: m.send(), args=(msg, )).start()
    logger.debug("Notice email submitted to %s" % member.email)
    return service
Exemple #26
0
def after_order_confirmation(order, update_stock=True):
    member = order.member
    service = get_service_instance()
    config = service.config
    delcom = order.delivery_option.company
    delcom_db = delcom.database
    add_database(delcom_db)
    delcom_profile_original = OperatorProfile.objects.using(delcom_db).get(pk=delcom.config.id)
    dara, dara_service_original, provider_mirror = None, None, None
    sudo_group = Group.objects.get(name=SUDO)
    customer = member.customer
    referrer = customer.referrer
    referrer_share_rate = 0

    # Test if the customer has been referred
    if referrer:
        referrer_db = referrer.database
        add_database(referrer_db)
        try:
            dara = Dara.objects.get(member=referrer.member)
        except Dara.DoesNotExist:
            logging.error("%s - Dara %s not found" % (service.project_name, member.username))
        try:
            dara_service_original = Service.objects.using(referrer_db).get(pk=referrer.id)
        except Dara.DoesNotExist:
            logging.error("%s - Dara service not found in %s database for %s" % (service.project_name, referrer_db, referrer.project_name))
        try:
            provider_mirror = Service.objects.using(referrer_db).get(pk=service.id)
        except Service.DoesNotExist:
            logging.error("%s - Provider Service not found in %s database for %s" % (service.project_name, referrer_db, referrer.project_name))

    packages_info = order.split_into_packages(dara)

    if delcom != service and delcom_profile_original.payment_delay == OperatorProfile.STRAIGHT:
        set_logicom_earnings_and_stats(order)

    for provider_db in packages_info.keys():
        package = packages_info[provider_db]['package']
        provider_earnings = package.provider_earnings
        raw_provider_revenue = package.provider_revenue
        provider_revenue = raw_provider_revenue
        if package.provider == delcom:
            provider_revenue += order.delivery_option.cost + order.delivery_option.packing_cost
            provider_earnings += order.delivery_earnings
        else:
            provider_revenue += order.delivery_option.packing_cost
            provider_earnings += order.delivery_option.packing_cost * (100 - config.ikwen_share_rate) / 100
        provider_profile_umbrella = packages_info[provider_db]['provider_profile']
        provider_profile_original = provider_profile_umbrella.get_from(provider_db)
        provider_original = provider_profile_original.service

        if delcom == service:
            provider_original.raise_balance(provider_earnings, provider=order.payment_mean.slug)
        else:
            if delcom_profile_original.return_url:
                nvp_dict = package.get_nvp_api_dict()
                Thread(target=lambda url, data: requests.post(url, data=data),
                       args=(delcom_profile_original.return_url, nvp_dict)).start()
            if provider_profile_original.payment_delay == OperatorProfile.STRAIGHT:
                if package.provider_earnings > 0:
                    provider_original.raise_balance(provider_earnings, provider=order.payment_mean.slug)
        if provider_profile_original.return_url:
            nvp_dict = package.get_nvp_api_dict()
            Thread(target=lambda url, data: requests.post(url, data=data),
                   args=(provider_profile_original.return_url, nvp_dict)).start()

    set_counters(config)
    increment_history_field(config, 'orders_count_history')
    increment_history_field(config, 'items_traded_history', order.items_count)
    increment_history_field(config, 'turnover_history', provider_revenue)
    increment_history_field(config, 'earnings_history', provider_earnings)

    set_counters(customer)
    customer.last_payment_on = datetime.now()
    increment_history_field(customer, 'orders_count_history')
    increment_history_field(customer, 'items_purchased_history', order.items_count)
    increment_history_field(customer, 'turnover_history', provider_revenue)
    increment_history_field(customer, 'earnings_history', provider_earnings)

    # Test whether the referrer (of the current customer) is a Dara
    if dara:
        referrer_share_rate = dara.share_rate
        send_dara_notification_email(dara_service_original, order)

        set_counters(dara)
        dara.last_transaction_on = datetime.now()

        increment_history_field(dara, 'orders_count_history')
        increment_history_field(dara, 'items_traded_history', order.items_count)
        increment_history_field(dara, 'turnover_history', provider_revenue)
        increment_history_field(dara, 'earnings_history', provider_earnings)

        if dara_service_original:
            set_counters(dara_service_original)
            increment_history_field(dara_service_original, 'transaction_count_history')
            increment_history_field(dara_service_original, 'turnover_history', raw_provider_revenue)
            increment_history_field(dara_service_original, 'earnings_history', order.referrer_earnings)

        if dara_service_original:
            set_counters(provider_mirror)
            increment_history_field(provider_mirror, 'transaction_count_history')
            increment_history_field(provider_mirror, 'turnover_history', raw_provider_revenue)
            increment_history_field(provider_mirror, 'earnings_history', order.referrer_earnings)

        try:
            member_ref = Member.objects.using(referrer_db).get(pk=member.id)
        except Member.DoesNotExist:
            member.save(using=referrer_db)
            member_ref = Member.objects.using(referrer_db).get(pk=member.id)
            member.customer.save(using=referrer_db)
        customer_ref = member_ref.customer
        set_counters(customer_ref)
        customer_ref.last_payment_on = datetime.now()
        increment_history_field(customer_ref, 'orders_count_history')
        increment_history_field(customer_ref, 'items_purchased_history', order.items_count)
        increment_history_field(customer_ref, 'turnover_history', raw_provider_revenue)
        increment_history_field(customer_ref, 'earnings_history', order.retailer_earnings)

        dara_umbrella = Dara.objects.using(UMBRELLA).get(member=dara.member)
        if dara_umbrella.level == 1 and dara_umbrella.xp == 2:
            dara_umbrella.xp = 3
            dara_umbrella.raise_bonus_cash(200)
            dara_umbrella.save()

    category_list = []

    # Adding a 100 bonus in dara account to have buy online
    try:
        dara_as_buyer = Dara.objects.using(UMBRELLA).get(member=member)
        if dara_as_buyer.level == 1 and dara_as_buyer.xp == 0:
            dara_as_buyer.xp = 1
            dara_as_buyer.raise_bonus_cash(100)
            dara_as_buyer.save()
    except Dara.DoesNotExist:
        logging.error("The customer is not yet a Dara")

    for entry in order.entries:
        product = Product.objects.get(pk=entry.product.id)
        provider_service = product.provider
        provider_profile_umbrella = OperatorProfile.objects.using(UMBRELLA).get(service=provider_service)
        category = product.category

        turnover = entry.count * product.retail_price
        set_counters(category)
        provider_earnings = turnover * (100 - referrer_share_rate - provider_profile_umbrella.ikwen_share_rate) / 100
        increment_history_field(category, 'earnings_history', provider_earnings)
        increment_history_field(category, 'turnover_history', turnover)
        increment_history_field(category, 'items_traded_history', entry.count)
        if category not in category_list:
            increment_history_field(category, 'orders_count_history')
            category_list.append(category)

        if update_stock:
            product.stock -= entry.count
            if product.stock == 0:
                add_event(service, SOLD_OUT_EVENT, group_id=sudo_group.id, object_id=product.id)
                mark_duplicates(product)
        product.save()
        set_counters(product)
        increment_history_field(product, 'units_sold_history', entry.count)

    add_event(service, NEW_ORDER_EVENT, group_id=sudo_group.id, object_id=order.id)
Exemple #27
0
def deploy(member,
           project_name,
           billing_plan,
           theme,
           monthly_cost,
           invoice_entries,
           partner_retailer=None):
    app = Application.objects.using(UMBRELLA).get(slug='foulassi')
    project_name_slug = slugify(
        project_name)  # Eg: slugify('Great School') = 'great-school'
    ikwen_name = project_name_slug.replace(
        '-', '')  # Eg: great-school --> 'greatschool'
    pname = ikwen_name
    i = 0
    while True:
        try:
            Service.objects.using(UMBRELLA).get(project_name_slug=pname)
            i += 1
            pname = "%s%d" % (ikwen_name, i)
        except Service.DoesNotExist:
            ikwen_name = pname
            break
    api_signature = generate_random_key(30, alpha_num=True)
    while True:
        try:
            Service.objects.using(UMBRELLA).get(api_signature=api_signature)
            api_signature = generate_random_key(30, alpha_num=True)
        except Service.DoesNotExist:
            break
    database = ikwen_name
    domain = 'go.' + pname + '.ikwen.com'
    domain_type = Service.SUB
    is_naked_domain = False
    url = 'http://go.ikwen.com/' + pname
    admin_url = url + '/ikwen/staffRouter/'
    now = datetime.now()
    expiry = now + timedelta(days=60)

    # Create a copy of template application in the Cloud folder
    app_folder = CLOUD_HOME + '000Tpl/AppSkeleton'
    website_home_folder = CLOUD_FOLDER + ikwen_name
    media_root = CLUSTER_MEDIA_ROOT + ikwen_name + '/'
    media_url = CLUSTER_MEDIA_URL + ikwen_name + '/'
    images_folder = CLOUD_FOLDER + '000Tpl/images/000Default'
    if theme:
        theme_images_folder = CLOUD_FOLDER + '000Tpl/images/%s/%s' % (
            theme.template.slug, theme.slug)
        if os.path.exists(theme_images_folder):
            images_folder = theme_images_folder
    if os.path.exists(images_folder):
        if os.path.exists(media_root):
            shutil.rmtree(media_root)
        shutil.copytree(images_folder, media_root)
        logger.debug("Media folder '%s' successfully created from '%s'" %
                     (media_root, images_folder))
    elif not os.path.exists(media_root):
        os.makedirs(media_root)
        logger.debug("Media folder '%s' successfully created empty" %
                     media_root)
    icons_folder = media_root + 'icons'
    if not os.path.exists(icons_folder):
        os.makedirs(icons_folder)
    if os.path.exists(website_home_folder):
        shutil.rmtree(website_home_folder)
    shutil.copytree(app_folder, website_home_folder)
    logger.debug("Service folder '%s' successfully created" %
                 website_home_folder)

    settings_template = 'foulassi/cloud_setup/settings.html'

    service = Service(member=member,
                      app=app,
                      project_name=project_name,
                      project_name_slug=ikwen_name,
                      domain=domain,
                      database=database,
                      url=url,
                      domain_type=domain_type,
                      expiry=expiry,
                      admin_url=admin_url,
                      billing_plan=billing_plan,
                      billing_cycle=Service.YEARLY,
                      monthly_cost=monthly_cost,
                      version=Service.TRIAL,
                      api_signature=api_signature,
                      home_folder=website_home_folder,
                      settings_template=settings_template,
                      retailer=partner_retailer)
    service.save(using=UMBRELLA)
    logger.debug("Service %s successfully created" % pname)

    # Re-create settings.py file as well as apache.conf file for the newly created project
    secret_key = generate_django_secret_key()
    allowed_hosts = '"go.ikwen.com"'
    settings_tpl = get_template(settings_template)
    settings_context = Context({
        'secret_key': secret_key,
        'ikwen_name': ikwen_name,
        'service': service,
        'static_root': STATIC_ROOT,
        'static_url': STATIC_URL,
        'media_root': media_root,
        'media_url': media_url,
        'allowed_hosts': allowed_hosts,
        'debug': getattr(settings, 'DEBUG', False)
    })
    settings_file = website_home_folder + '/conf/settings.py'
    fh = open(settings_file, 'w')
    fh.write(settings_tpl.render(settings_context))
    fh.close()
    logger.debug("Settings file '%s' successfully created" % settings_file)

    # Import template database and set it up
    db_folder = CLOUD_FOLDER + '000Tpl/DB/000Default'
    if theme:
        theme_db_folder = CLOUD_FOLDER + '000Tpl/DB/%s/%s' % (
            theme.template.slug, theme.slug)
        if os.path.exists(theme_db_folder):
            db_folder = theme_db_folder

    host = getattr(settings, 'DATABASES')['default'].get('HOST', '127.0.0.1')
    from ikwen.core.log import ikwen_error_log_filename
    eh = open(ikwen_error_log_filename, 'a')
    subprocess.call(
        ['mongorestore', '--host', host, '-d', database, db_folder], stderr=eh)
    logger.debug("Database %s successfully created on host %s from %s" %
                 (database, host, db_folder))

    add_database_to_settings(database)
    for group in Group.objects.using(database).all():
        try:
            gpl = GroupPermissionList.objects.using(database).get(group=group)
            group.delete()
            group.save(using=database
                       )  # Recreate the group in the service DB with a new id.
            gpl.group = group  # And update GroupPermissionList object with the newly re-created group
            gpl.save(using=database)
        except GroupPermissionList.DoesNotExist:
            group.delete()
            group.save(using=database
                       )  # Re-create the group in the service DB with anyway.
    new_sudo_group = Group.objects.using(database).get(name=SUDO)

    for s in member.get_services():
        db = s.database
        add_database_to_settings(db)
        collaborates_on_fk_list = member.collaborates_on_fk_list + [service.id]
        customer_on_fk_list = member.customer_on_fk_list + [service.id]
        group_fk_list = member.group_fk_list + [new_sudo_group.id]
        Member.objects.using(db).filter(pk=member.id).update(
            collaborates_on_fk_list=collaborates_on_fk_list,
            customer_on_fk_list=customer_on_fk_list,
            group_fk_list=group_fk_list)

    member.collaborates_on_fk_list = collaborates_on_fk_list
    member.customer_on_fk_list = customer_on_fk_list
    member.group_fk_list = group_fk_list

    member.is_iao = True
    member.save(using=UMBRELLA)

    member.is_bao = True
    member.is_staff = True
    member.is_superuser = True

    app.save(using=database)
    member.save(using=database)
    logger.debug("Member %s access rights successfully set for service %s" %
                 (member.username, pname))

    from ikwen.billing.mtnmomo.views import MTN_MOMO
    # Copy payment means to local database
    for mean in PaymentMean.objects.using(UMBRELLA).all():
        if mean.slug == MTN_MOMO:
            mean.is_main = True
            mean.is_active = True
        else:
            mean.is_main = False
            mean.is_active = True
        mean.save(using=database)
        logger.debug("PaymentMean %s created in database: %s" %
                     (mean.slug, database))

    # Copy themes to local database
    webnode = Application.objects.using(UMBRELLA).get(slug='webnode')
    template_list = list(Template.objects.using(UMBRELLA).filter(app=webnode))
    for template in template_list:
        template.save(using=database)
    for th in Theme.objects.using(UMBRELLA).filter(template__in=template_list):
        th.save(using=database)
    logger.debug("Templates and themes successfully saved for service: %s" %
                 pname)

    FlatPage.objects.using(database).get_or_create(url=FlatPage.AGREEMENT,
                                                   title=FlatPage.AGREEMENT)
    FlatPage.objects.using(database).get_or_create(
        url=FlatPage.LEGAL_MENTIONS, title=FlatPage.LEGAL_MENTIONS)

    # Add member to SUDO Group
    obj_list, created = UserPermissionList.objects.using(
        database).get_or_create(user=member)
    obj_list.group_fk_list.append(new_sudo_group.id)
    obj_list.save(using=database)
    logger.debug("Member %s successfully added to sudo group for service: %s" %
                 (member.username, pname))

    mail_signature = "%s<br>" \
                     "<a href='%s'>%s</a>" % (project_name, 'http://' + domain, domain)
    config = SchoolConfig(service=service,
                          ikwen_share_rate=billing_plan.tx_share_rate,
                          theme=theme,
                          currency_code='XAF',
                          currency_symbol='XAF',
                          decimal_precision=0,
                          signature=mail_signature,
                          company_name=project_name,
                          contact_email=member.email,
                          contact_phone=member.phone,
                          sms_api_script_url=SMS_API_URL,
                          back_to_school_date=back_to_school_date)
    config.save(using=UMBRELLA)
    base_config = config.get_base_config()
    base_config.save(using=UMBRELLA)

    service.save(using=database)
    theme.save(using=database
               )  # Causes theme to be routed to the newly created database
    config.save(using=database)
    logger.debug("Configuration successfully added for service: %s" % pname)

    # Apache Server cloud_setup
    go_apache_tpl = get_template('foulassi/cloud_setup/apache.conf.local.html')
    apache_context = Context({
        'is_naked_domain': is_naked_domain,
        'domain': domain,
        'ikwen_name': ikwen_name
    })
    fh = open(website_home_folder + '/go_apache.conf', 'w')
    fh.write(go_apache_tpl.render(apache_context))
    fh.close()

    vhost = '/etc/apache2/sites-enabled/go_ikwen/' + pname + '.conf'
    subprocess.call(
        ['sudo', 'ln', '-sf', website_home_folder + '/go_apache.conf', vhost])
    logger.debug("Apache Virtual Host '%s' successfully created" % vhost)

    # Send notification and Invoice to customer
    number = get_next_invoice_number()
    now = datetime.now()
    invoice_total = 0
    for entry in invoice_entries:
        invoice_total += entry.total
    invoice = Invoice(subscription=service,
                      member=member,
                      amount=invoice_total,
                      number=number,
                      due_date=expiry,
                      last_reminder=now,
                      reminders_sent=1,
                      is_one_off=True,
                      entries=invoice_entries,
                      months_count=billing_plan.setup_months_count)
    invoice.save(using=UMBRELLA)
    vendor = get_service_instance()

    from daraja.models import DARAJA
    if member != vendor.member:
        add_event(vendor,
                  SERVICE_DEPLOYED,
                  member=member,
                  object_id=invoice.id)
    if partner_retailer and partner_retailer.app.slug != DARAJA:
        partner_profile = PartnerProfile.objects.using(UMBRELLA).get(
            service=partner_retailer)
        try:
            Member.objects.get(pk=member.id)
        except Member.DoesNotExist:
            member.is_iao = False
            member.is_bao = False
            member.is_staff = False
            member.is_superuser = False
            member.save(using='default')
        service.save(using='default')
        config.save(using='default')
        sender = '%s <no-reply@%s>' % (partner_profile.company_name,
                                       partner_retailer.domain)
        sudo_group = Group.objects.get(name=SUDO)
        ikwen_sudo_gp = Group.objects.using(UMBRELLA).get(name=SUDO)
        add_event(vendor,
                  SERVICE_DEPLOYED,
                  group_id=ikwen_sudo_gp.id,
                  object_id=invoice.id)
    else:
        sender = 'ikwen Foulassi <*****@*****.**>'
        sudo_group = Group.objects.using(UMBRELLA).get(name=SUDO)
    add_event(vendor,
              SERVICE_DEPLOYED,
              group_id=sudo_group.id,
              object_id=invoice.id)
    invoice_url = 'http://www.ikwen.com' + reverse('billing:invoice_detail',
                                                   args=(invoice.id, ))
    subject = _("Your platform %s was created" % project_name)
    html_content = get_mail_content(
        subject,
        template_name='core/mails/service_deployed.html',
        extra_context={
            'service_activated': service,
            'invoice': invoice,
            'member': member,
            'invoice_url': invoice_url
        })
    msg = EmailMessage(subject, html_content, sender, [member.email])
    bcc = ['*****@*****.**', '*****@*****.**']
    if vendor.config.contact_email:
        bcc.append(vendor.config.contact_email)
    msg.bcc = list(set(bcc))
    msg.content_subtype = "html"
    Thread(target=lambda m: m.send(), args=(msg, )).start()
    logger.debug("Notice email submitted to %s" % member.email)
    Thread(target=reload_server).start()
    logger.debug("Apache Scheduled to reload in 5s")
    return service
Exemple #28
0
def confirm_shipping(request, *args, **kwargs):
    order_id = request.GET.get('order_id')
    package_id = request.GET.get('package_id')
    try:
        if package_id:
            package = Package.objects.get(pk=package_id)
            package.status = Order.SHIPPED
            package.confirmed_on = datetime.now()
            package.confirmed_by = request.user
            package.save()
            order = package.order
        else:
            order = Order.objects.get(pk=order_id)
        order.status = Order.SHIPPED
        order.confirmed_on = datetime.now()
        order.confirmed_by = request.user
        order.save()
    except Order.DoesNotExist:
        response = {'error': _("No Order found with this ID: %s" % order_id)}
        return HttpResponse(json.dumps(response), 'content-type: text/json')
    except Package.DoesNotExist:
        response = {
            'error': _("No Package found with this ID: %s" % package_id)
        }
        return HttpResponse(json.dumps(response), 'content-type: text/json')
    except:
        response = {'error': _("Unknow error occured")}
        return HttpResponse(json.dumps(response), 'content-type: text/json')
    else:
        response = {'success': True}

    delivery_company = order.delivery_option.company
    # Set provider balance for those with payment_delay=UPON_CONFIRMATION.
    # Those with payment_delay=STRAIGHT had their balance set in confirm_checkout()
    for package in order.package_set.all():
        provider_service_umbrella = Service.objects.using(UMBRELLA).get(
            pk=package.provider.id)
        if delivery_company.id != provider_service_umbrella.id:
            provider_profile_umbrella = provider_service_umbrella.config
            if provider_profile_umbrella.payment_delay == OperatorProfile.UPON_CONFIRMATION:
                provider_db = provider_service_umbrella.database
                add_database_to_settings(provider_db)
                provider_original = Service.objects.using(provider_db).get(
                    pk=package.provider.id)
                provider_original.raise_balance(package.provider_earnings,
                                                order.payment_mean.slug)

    if getattr(settings, 'IS_PROVIDER', False):
        service = get_service_instance()
        retailer_service = order.retailer
        if retailer_service != service:
            retailer_earnings = order.retailer_earnings
            if delivery_company == retailer_service:
                retailer_earnings += order.delivery_earnings

            retailer_profile = retailer_service.config
            retailer_db = retailer_service.database
            add_database_to_settings(retailer_db)
            retailer_profile_original = OperatorProfile.objects.using(
                retailer_db).get(pk=retailer_profile.id)

            set_counters(retailer_profile_original)
            increment_history_field(retailer_profile_original,
                                    'earnings_history', retailer_earnings)
            retailer_profile.report_counters_to_umbrella()
            retailer_profile_original.raise_balance(retailer_earnings,
                                                    order.payment_mean.slug)

        if order.delivery_option.type == DeliveryOption.HOME_DELIVERY:
            if order.member:
                add_event(service,
                          ORDER_SHIPPED_EVENT,
                          member=order.member,
                          object_id=order.id)
            subject = _("Your order was shipped")
        else:
            if order.member:
                add_event(service,
                          ORDER_PACKAGED_EVENT,
                          member=order.member,
                          object_id=order.id)
            subject = _("Your order is packaged and ready")

        if order.aotc:
            buyer_name = order.anonymous_buyer.name
            email = order.anonymous_buyer.email
        else:
            member = order.member
            buyer_name = member.full_name
            email = member.email

        html_content = get_mail_content(
            subject,
            '',
            template_name='shopping/mails/order_notice.html',
            extra_context={
                'rcc': order.rcc.upper(),
                'buyer_name': buyer_name,
                'order': order
            })
        sender = '%s <no-reply@%s>' % (service.project_name, service.domain)
        msg = EmailMessage(subject, html_content, sender, [email])
        msg.content_subtype = "html"
        Thread(target=lambda m: m.send(), args=(msg, )).start()

    return HttpResponse(json.dumps(response), 'content-type: text/json')
Exemple #29
0
    def save_formset(self, request, form, formset, change):
        instances = formset.save(commit=False)
        total_amount = 0
        instance = None
        for instance in instances:
            if isinstance(instance, Payment):
                total_amount += instance.amount
                if instance.cashier:
                    # Instances with non null cashier are those that previously existed.
                    # setting them to None allows to ignore them at the end of the loop
                    # since we want to undertake action only for newly added Payment
                    instance = None
                    continue
                instance.cashier = request.user
                instance.save()
        if instance:
            # TODO: Check if the last payment is newly added
            # Notice email is sent only for the last saved Payment,
            # this is why this code is not run within the "for" loop above
            member = instance.invoice.subscription.member
            service = get_service_instance()
            config = service.config
            invoice = instance.invoice
            s = invoice.service
            days = get_days_count(invoice.months_count)
            if s.status == Service.SUSPENDED:
                invoicing_config = get_invoicing_config_instance()
                days -= invoicing_config.tolerance  # Catch-up days that were offered before service suspension
                expiry = datetime.now() + timedelta(days=days)
                expiry = expiry.date()
            elif s.expiry:
                expiry = s.expiry + timedelta(days=days)
            else:
                expiry = datetime.now() + timedelta(days=days)
                expiry = expiry.date()
            s.expiry = expiry
            s.status = Service.ACTIVE
            if invoice.is_one_off:
                s.version = Service.FULL
            s.save()
            share_payment_and_set_stats(invoice, invoice.months_count)

            if s.retailer:
                db = s.retailer.database
                Service.objects.using(db).filter(pk=s.id).update(
                    expiry=s.expiry, status=s.status, version=s.version)

            sudo_group = Group.objects.using(UMBRELLA).get(name=SUDO)
            add_event(service,
                      PAYMENT_CONFIRMATION,
                      group_id=sudo_group.id,
                      object_id=invoice.id)
            add_event(service,
                      PAYMENT_CONFIRMATION,
                      member=member,
                      object_id=invoice.id)
            subject, message, sms_text = get_payment_confirmation_message(
                instance, member)
            if member.email:
                try:
                    currency = Currency.active.default().symbol
                except:
                    currency = config.currency_code
                invoice_url = service.url + reverse('billing:invoice_detail',
                                                    args=(invoice.id, ))
                subject, message, sms_text = get_payment_confirmation_message(
                    instance, member)
                html_content = get_mail_content(
                    subject,
                    message,
                    template_name='billing/mails/notice.html',
                    extra_context={
                        'member_name': member.first_name,
                        'invoice': invoice,
                        'cta': _("View invoice"),
                        'invoice_url': invoice_url,
                        'currency': currency
                    })
                sender = '%s <no-reply@%s>' % (config.company_name,
                                               service.domain)
                msg = EmailMessage(subject, html_content, sender,
                                   [member.email])
                msg.content_subtype = "html"
                Thread(target=lambda m: m.send(), args=(msg, )).start()
            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)
            if total_amount >= invoice.amount:
                invoice.status = AbstractInvoice.PAID
                invoice.save()
Exemple #30
0
def after_order_confirmation(order, media_order=None, update_stock=True):
    member = order.member
    service = get_service_instance()
    config = service.config
    delcom = order.delivery_option.company
    delcom_db = delcom.database
    add_database(delcom_db)
    sudo_group = Group.objects.get(name=SUDO)
    customer = member.customer
    packages_info = order.split_into_packages()

    for provider_db in packages_info.keys():
        package = packages_info[provider_db]['package']
        provider_earnings = package.provider_earnings
        raw_provider_revenue = package.provider_revenue
        provider_revenue = raw_provider_revenue
        if package.provider == delcom:
            provider_revenue += order.delivery_option.cost + order.delivery_option.packing_cost
            provider_earnings += order.delivery_earnings
        else:
            provider_revenue += order.delivery_option.packing_cost
            provider_earnings += order.delivery_option.packing_cost * (100 - config.ikwen_share_rate) / 100
        provider_profile_umbrella = packages_info[provider_db]['provider_profile']
        provider_profile_original = provider_profile_umbrella.get_from(provider_db)

        if provider_profile_original.return_url:
            nvp_dict = package.get_nvp_api_dict()
            Thread(target=lambda url, data: requests.post(url, data=data),
                   args=(provider_profile_original.return_url, nvp_dict)).start()

    if media_order:
        provider_revenue += media_order.total_cost
        provider_earnings += media_order.total_cost

    set_counters(config)
    increment_history_field(config, 'orders_count_history')
    increment_history_field(config, 'items_traded_history', order.items_count)
    increment_history_field(config, 'turnover_history', provider_revenue)
    increment_history_field(config, 'earnings_history', provider_earnings)

    set_counters(customer)
    customer.last_payment_on = datetime.now()
    increment_history_field(customer, 'orders_count_history')
    increment_history_field(customer, 'items_purchased_history', order.items_count)
    increment_history_field(customer, 'turnover_history', provider_revenue)
    increment_history_field(customer, 'earnings_history', provider_earnings)

    category_list = []
    for entry in order.entries:
        product = Product.objects.get(pk=entry.product.id)
        category = product.category

        turnover = entry.count * product.retail_price
        set_counters(category)
        provider_earnings = turnover
        increment_history_field(category, 'earnings_history', provider_earnings)
        increment_history_field(category, 'turnover_history', turnover)
        increment_history_field(category, 'items_traded_history', entry.count)
        if category not in category_list:
            increment_history_field(category, 'orders_count_history')
            category_list.append(category)

        if update_stock:
            product.stock -= entry.count
            if product.stock == 0:
                add_event(service, SOLD_OUT_EVENT, group_id=sudo_group.id, object_id=product.id)
                mark_duplicates(product)
        product.save()
        set_counters(product)
        increment_history_field(product, 'units_sold_history', entry.count)

    for album in media_order.album_list:
        set_counters(album)
        increment_history_field(album, 'earnings_history', album.cost)
        increment_history_field(album, 'turnover_history', album.cost)
        increment_history_field(album, 'units_sold_history')

    for song in media_order.song_list:
        if song.cost == 0:
            continue
        set_counters(song)
        increment_history_field(song, 'earnings_history', song.cost)
        increment_history_field(song, 'turnover_history', song.cost)
        increment_history_field(song, 'units_sold_history')