Ejemplo n.º 1
0
 def get_context_data(self, **kwargs):
     context = super(ServiceDetail, self).get_context_data(**kwargs)
     invoicing_config = get_invoicing_config_instance(UMBRELLA)
     service_id = kwargs.get('service_id')
     if not service_id:
         service_id = getattr(settings, 'IKWEN_SERVICE_ID')
     srvce = Service.objects.using(UMBRELLA).get(pk=service_id)
     invoice = Invoice.get_last(srvce)
     now = datetime.now()
     if invoice:
         srvce.last_payment = invoice.created_on
     if not srvce.version or srvce.version == Service.FREE:
         srvce.expiry = None
     else:
         srvce.next_invoice_on = srvce.expiry - timedelta(
             days=invoicing_config.gap)
         if srvce.expiry < now.date():
             srvce.expired = True
         if now.date() > srvce.next_invoice_on:
             days = get_billing_cycle_days_count(srvce.billing_cycle)
             srvce.next_invoice_on = srvce.next_invoice_on + timedelta(
                 days=days)
         srvce.next_invoice_amount = srvce.monthly_cost * get_billing_cycle_months_count(
             srvce.billing_cycle)
         srvce.pending_invoice_count = Invoice.objects.filter(
             subscription=srvce, status=Invoice.PENDING).count()
     try:
         support_code = SupportCode.objects.using(UMBRELLA).filter(
             service=srvce).order_by('-id')[0]
     except IndexError:
         support_code = None
     if support_code and support_code.expiry < now:
         support_code.expired = True
     from echo.models import Balance
     echo_balance, update = Balance.objects.using('wallets').get_or_create(
         service_id=srvce.id)
     context[
         'srvce'] = srvce  # Service named srvce in context to avoid collision with service from template_context_processors
     context['support_code'] = support_code
     context['echo_balance'] = echo_balance
     context['billing_cycles'] = Service.BILLING_CYCLES_CHOICES
     return context
Ejemplo n.º 2
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
Ejemplo n.º 3
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
Ejemplo n.º 4
0
def deploy(app,
           member,
           project_name,
           billing_plan,
           monthly_cost,
           theme,
           billing_cycle,
           invoice_entries,
           is_pro_version=False):
    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)
    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 = ikwen_name + '.ikwen.com'
    domain_type = Service.SUB
    is_naked_domain = False
    admin_url = domain + '/ikwen' + reverse('ikwen:staff_router')
    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'
    if 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 + 'favicons'
    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)

    settings_template = 'partnership/cloud_setup/settings.html'

    service = Service(member=member,
                      app=app,
                      project_name=project_name,
                      project_name_slug=ikwen_name,
                      domain=domain,
                      database=database,
                      url='http://' + domain,
                      domain_type=domain_type,
                      expiry=expiry,
                      admin_url='http://' + admin_url,
                      api_signature=api_signature,
                      billing_cycle=billing_cycle,
                      monthly_cost=monthly_cost,
                      version=Service.TRIAL,
                      home_folder=website_home_folder,
                      settings_template=settings_template)
    service.save(using=UMBRELLA)

    # Re-create settings.py file as well as apache.conf file for the newly created project
    secret_key = generate_django_secret_key()
    allowed_hosts = '"%s", "www.%s"' % (domain, domain)
    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
    host = getattr(settings, 'DATABASES')['default'].get('HOST', '127.0.0.1')
    subprocess.call([
        'mongorestore', '--host', host, '-d', database,
        CLOUD_FOLDER + '000Tpl/DB/000Default'
    ])
    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))

    # 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
        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)

    # Create Module Blog
    module_blog = Module.objects.using(UMBRELLA).get(slug='module_blog')
    module_blog.is_active = True
    module_blog.save(using=database)
    logger.debug("Module Blog created for service: %s" % pname)

    FlatPage.objects.using(database).create(
        url=FlatPage.AGREEMENT, title=FlatPage.AGREEMENT.capitalize())
    FlatPage.objects.using(database).create(
        url=FlatPage.LEGAL_MENTIONS,
        title=FlatPage.LEGAL_MENTIONS.capitalize().replace('-', ' '))

    # 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)

    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)
    config = PartnerProfile(service=service,
                            is_pro_version=is_pro_version,
                            theme=theme,
                            currency_code='XAF',
                            currency_symbol='XAF',
                            signature=mail_signature,
                            company_name=project_name,
                            contact_email=member.email,
                            contact_phone=member.phone)
    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)

    InvoicingConfig.objects.using(database).create()

    # Apache Server cloud_setup
    if getattr(settings, 'LOCAL_DEV', False):
        apache_tpl = get_template(
            'partnership/cloud_setup/apache.conf.local.html')
    else:
        apache_tpl = get_template('partnership/cloud_setup/apache.conf.html')
    apache_context = Context({
        'is_naked_domain': is_naked_domain,
        'domain': domain,
        'ikwen_name': ikwen_name
    })
    fh = open(website_home_folder + '/apache.conf', 'w')
    fh.write(apache_tpl.render(apache_context))
    fh.close()

    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,
                      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()
    sudo_group = Group.objects.using(UMBRELLA).get(name=SUDO)
    add_event(vendor, SERVICE_DEPLOYED, member=member, object_id=invoice.id)
    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, ))
    sender = 'ikwen <*****@*****.**>'
    subject = _("Your retailer platform was created")
    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])
    msg.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
Ejemplo n.º 5
0
def deploy(app,
           member,
           project_name,
           billing_plan,
           setup_cost,
           monthly_cost,
           invoice_entries,
           billing_cycle,
           domain=None,
           provider=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
    database = ikwen_name
    if not domain:
        domain = ikwen_name + '.kakocase.com'
    admin_url = domain + '/ikwen/dashboard'
    domain_type = Service.SUB if '.kakocase.com' in domain else Service.MAIN
    is_pro_version = billing_plan.is_pro_version
    now = datetime.now()
    expiry = now + timedelta(days=15)
    service = Service(member=member,
                      app=app,
                      project_name=project_name,
                      project_name_slug=ikwen_name,
                      domain=domain,
                      database=database,
                      url='http://' + domain,
                      domain_type=domain_type,
                      expiry=expiry,
                      admin_url='http://' + admin_url,
                      billing_plan=billing_plan,
                      billing_cycle=billing_cycle,
                      monthly_cost=monthly_cost,
                      version=Service.TRIAL,
                      retailer=partner_retailer)
    service.save(using=UMBRELLA)

    # Create a copy of template application in the Cloud folder
    app_folder = CLOUD_FOLDER + '000Tpl/AppSkeleton'
    website_home_folder = CLOUD_FOLDER + ikwen_name
    media_root = MEDIA_ROOT + ikwen_name + '/'
    if not os.path.exists(media_root):
        os.makedirs(media_root)
    media_url = MEDIA_URL + ikwen_name + '/'
    if os.path.exists(website_home_folder):
        shutil.rmtree(website_home_folder)
    shutil.copytree(app_folder, website_home_folder)

    # Re-create settings.py file as well as apache.conf file for the newly created project
    secret_key = generate_django_secret_key()
    api_signature = generate_random_key(20)
    allowed_hosts = '%s, www.%s' % (domain, domain)
    settings_tpl = get_template('billing/cloud_setup/settings.html')
    settings_context = Context({
        'secret_key': secret_key,
        'database': database,
        'service': service,
        'static_root': STATIC_ROOT,
        'static_url': STATIC_URL,
        'media_root': media_root,
        'media_url': media_url,
        'app_folder': app_folder,
        'allowed_hosts': allowed_hosts,
        'debug': getattr(settings, 'DEBUG', False)
    })
    fh = open(website_home_folder + '/conf/settings.py', 'w')
    fh.write(settings_tpl.render(settings_context))
    fh.close()

    if service.id not in member.collaborates_on_fk_list:
        member.collaborates_on_fk_list.append(service.id)
    if service not in member.customer_on_fk_list:
        member.customer_on.append(service.id)

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

    # Import template database and set it up
    subprocess.call(
        ['mongorestore', '-d', database, CLOUD_FOLDER + '000Tpl/DB'])
    add_database_to_settings(database)

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

    app.save(using=database)
    member.save(using=database)

    # 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
            if is_pro_version:
                mean.is_active = True
            else:
                mean.is_active = False
        mean.save(using=database)

    FlatPage.objects.using(database).create(url=FlatPage.AGREEMENT,
                                            title=FlatPage.AGREEMENT)
    FlatPage.objects.using(database).create(url=FlatPage.LEGAL_MENTIONS,
                                            title=FlatPage.LEGAL_MENTIONS)
    for group in Group.objects.using(database).all():
        try:
            gpl = GroupPermissionList.objects.get(group=group)
            group.id = None
            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.id = None
            group.save(using=database
                       )  # Re-create the group in the service DB with anyway.

    # Add member to SUDO Group
    sudo_group = Group.objects.using(database).get(name=SUDO)
    obj_list, created = UserPermissionList.objects.using(
        database).get_or_create(user=member)
    obj_list.group_fk_list.append(sudo_group.id)
    obj_list.save(using=database)

    mail_signature = "%s<br>" \
                     "<a href='%s'>%s</a>" % (project_name, 'http://' + domain, domain)
    config = OperatorProfile(service=service,
                             api_signature=api_signature,
                             ikwen_share_fixed=billing_plan.tx_share_fixed,
                             ikwen_share_rate=billing_plan.tx_share_rate,
                             is_pro_version=is_pro_version,
                             signature=mail_signature,
                             max_customers=billing_plan.max_objects)
    config.save(using=UMBRELLA)
    base_config = config.get_base_config()
    base_config.save(using=UMBRELLA)
    if partner_retailer:
        partner_retailer.save(using=database)
    service.save(using=database)

    config.save(using=database)
    InvoicingConfig.objects.using(database).create()

    # Apache Server setup
    if getattr(settings, 'LOCAL_DEV'):
        apache_tpl = get_template('core/cloud_setup/apache.conf.local.html')
    else:
        apache_tpl = get_template('core/cloud_setup/apache.conf.html')
    apache_context = Context({'ikwen_name': ikwen_name})
    fh = open(website_home_folder + '/apache.conf', 'w')
    fh.write(apache_tpl.render(apache_context))
    fh.close()

    subprocess.call([
        'sudo', 'ln', '-sf', website_home_folder + '/apache.conf',
        '/etc/apache2/sites-enabled/' + domain + '.conf'
    ])
    subprocess.call(['sudo', 'service', 'apache2', 'reload'])

    # 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,
                      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()
    add_event(vendor, NEW_INVOICE_EVENT, member=member, object_id=invoice.id)
    if partner_retailer:
        partner_profile = PartnerProfile.objects.using(UMBRELLA).get(
            service=partner_retailer)
        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)
    else:
        sender = 'IKWEN <*****@*****.**>'
    invoice_url = 'http://www.ikwen.com' + reverse('billing:invoice_detail',
                                                   args=(invoice.id, ))
    subject = _("Your Web Billing 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])
    msg.content_subtype = "html"
    Thread(target=lambda m: m.send(), args=(msg, )).start()
    return service