def get_context_data(self, **kwargs): context = super(CCMDashboard, self).get_context_data(**kwargs) service = get_service_instance() CA = service.turnover_history[0] set_counters(service) community_count = Member.objects.filter(is_active=True).count() community_today = calculate_watch_info(service.community_history) community_yesterday = calculate_watch_info(service.community_history, 1) community_last_week = calculate_watch_info(service.community_history, 7) community_last_28_days = calculate_watch_info( service.community_history, 28) community_report = { 'today': community_today, 'yesterday': community_yesterday, 'last_week': community_last_week, 'last_28_days': community_last_28_days } joins = Member.objects.all().order_by('-date_joined')[:5] context['estimated_worth'] = 0 context['community_report'] = community_report context['last_joined'] = joins context['ca'] = CA / community_count return context
def set_logicom_earnings_and_stats(order): delcom = order.delivery_company delcom_original = Service.objects.using(delcom.database).get(pk=delcom.id) delcom_profile_original = delcom_original.config provider = order.get_providers()[0] provider_profile_mirror = Service.objects.using( delcom.database).get(pk=provider.id).config payment_mean_slug = order.payment_mean.slug if payment_mean_slug == DARA_CASH: payment_mean_slug = MTN_MOMO set_counters(delcom_profile_original) increment_history_field(delcom_profile_original, 'items_traded_history', order.items_count) increment_history_field(delcom_profile_original, 'turnover_history', order.delivery_option.cost) increment_history_field(delcom_profile_original, 'orders_count_history') increment_history_field(delcom_profile_original, 'earnings_history', order.delivery_earnings) delcom_profile_original.report_counters_to_umbrella() delcom_original.raise_balance(order.delivery_earnings, payment_mean_slug) set_counters(provider_profile_mirror) increment_history_field(provider_profile_mirror, 'items_traded_history', order.items_count) increment_history_field(provider_profile_mirror, 'turnover_history', order.delivery_option.cost) increment_history_field(provider_profile_mirror, 'orders_count_history') increment_history_field(provider_profile_mirror, 'earnings_history', order.delivery_earnings)
def get_context_data(self, **kwargs): context = super(RetailerDashboard, self).get_context_data(**kwargs) providers = list( OperatorProfile.objects.filter( business_type=OperatorProfile.PROVIDER)) for provider in providers: set_counters(provider) providers_report = { 'today': rank_watch_objects(providers, 'earnings_history'), 'yesterday': rank_watch_objects(providers, 'earnings_history', 1), 'last_week': rank_watch_objects(providers, 'earnings_history', 7), 'last_28_days': rank_watch_objects(providers, 'earnings_history', 28) } customers_today = slice_watch_objects(Customer) customers_yesterday = slice_watch_objects(Customer, 1) customers_last_week = slice_watch_objects(Customer, 7) customers_last_28_days = slice_watch_objects(Customer, 28) customers_report = { 'today': rank_watch_objects(customers_today, 'earnings_history'), 'yesterday': rank_watch_objects(customers_yesterday, 'earnings_history', 1), 'last_week': rank_watch_objects(customers_last_week, 'earnings_history', 7), 'last_28_days': rank_watch_objects(customers_last_28_days, 'earnings_history', 28) } context['providers_report'] = providers_report context['customers_report'] = customers_report return context
def get_context_data(self, **kwargs): context = super(Dashboard, self).get_context_data(**kwargs) service = self.get_service(**kwargs) db = service.database add_database(db) customer_list = slice_watch_objects(Customer, 28, using=db) customers_report = { 'today': rank_watch_objects(customer_list, 'turnover_history'), 'yesterday': rank_watch_objects(customer_list, 'turnover_history', 1), 'last_week': rank_watch_objects(customer_list, 'turnover_history', 7), 'last_28_days': rank_watch_objects(customer_list, 'turnover_history', 28) } context['customers_report'] = customers_report company_list = list(Service.objects.using(db).all()) for company in company_list: set_counters(company) companies_report = { 'today': rank_watch_objects(company_list, 'earnings_history'), 'yesterday': rank_watch_objects(company_list, 'earnings_history', 1), 'last_week': rank_watch_objects(company_list, 'earnings_history', 7), 'last_28_days': rank_watch_objects(company_list, 'earnings_history', 28) } context['companies_report'] = companies_report return context
def group_rewards_by_service(member): """ Goes through all reward prepared for a member, Set those reward actually and groups them by Service in a dictionary object which keys are the Service and values are matching reward_list """ grouped_rewards = {} service_list = [] for service_id in member.customer_on_fk_list: try: service_list.append( Service.objects.get(pk=service_id, status=Service.ACTIVE)) except Service.DoesNotExist: pass for service in service_list: reward_list = [] try: operator = CROperatorProfile.objects.get(service=service, is_active=True) except CROperatorProfile.DoesNotExist: continue if Coupon.objects.filter(service=service, status=Coupon.APPROVED, is_active=True).count() == 0: continue set_counters(operator) for coupon in Coupon.objects.filter(service=service, status=Coupon.APPROVED, is_active=True): try: reward = Reward.objects.get(member=member, coupon=coupon, status=Reward.PREPARED) reward_list.append(reward) cumul, update = CumulatedCoupon.objects.get_or_create( member=member, coupon=coupon) cumul.count += reward.count cumul.save() summary, update = CouponSummary.objects.get_or_create( service=service, member=member) summary.count += reward.count if cumul.count > coupon.heap_size: CouponWinner.objects.create(member=member, coupon=coupon) summary.threshold_reached = True summary.save() history_field = coupon.type.lower() + '_history' increment_history_field(operator, history_field, reward.count) set_counters(coupon) increment_history_field(coupon, 'offered_history', reward.count) except Reward.DoesNotExist: pass increment_history_field(operator, 'push_history') grouped_rewards[service] = reward_list return grouped_rewards
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)
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)
def test_set_counters(self): watch_object = init_watch_object() now = timezone.now() yesterday = now - timedelta(days=1) watch_object.counters_reset_on = now set_counters(watch_object) self.assertEqual(watch_object.val1_history, '18,9,57,23,46') self.assertListEqual(watch_object.val2_history, [18, 9, 57, 23, 46]) watch_object.counters_reset_on = yesterday set_counters(watch_object) self.assertEqual(watch_object.val1_history, '18,9,57,23,46,0') self.assertListEqual(watch_object.val2_history, [18, 9, 57, 23, 46, 0])
def report_counters_to_umbrella(self): try: umbrella_obj = ProductCategory.objects.using(UMBRELLA).get( slug=self.slug) except: umbrella_obj = ProductCategory.objects.using(UMBRELLA).create( name=self.name, slug=self.slug) set_counters(umbrella_obj) increment_history_field(umbrella_obj, 'items_traded_history') increment_history_field(umbrella_obj, 'turnover_history') increment_history_field(umbrella_obj, 'orders_count_history') umbrella_obj.save(using=UMBRELLA)
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)
def set_dara_stats(partner_original, service_partner, invoice, dara_earnings): set_counters(partner_original) increment_history_field(partner_original, 'turnover_history', dara_earnings) increment_history_field(partner_original, 'earnings_history', dara_earnings) increment_history_field(partner_original, 'transaction_count_history') set_counters(service_partner) increment_history_field(service_partner, 'earnings_history', dara_earnings) increment_history_field(service_partner, 'transaction_count_history') ikwen_service = get_service_instance() try: config = ikwen_service.config activate(partner_original.member.language) subject = _("New transaction on %s" % config.company_name) dashboard_url = 'https://daraja.ikwen.com' + reverse( 'daraja:dashboard') html_content = get_mail_content( subject, template_name='daraja/mails/new_transaction.html', extra_context={ 'currency_symbol': config.currency_symbol, 'amount': invoice.amount, 'dara_earnings': dara_earnings, 'tx_date': invoice.updated_on.strftime('%Y-%m-%d'), 'tx_time': invoice.updated_on.strftime('%H:%M:%S'), 'account_balance': partner_original.balance, 'dashboard_url': dashboard_url }) sender = 'ikwen Daraja <*****@*****.**>' msg = XEmailMessage(subject, html_content, sender, [partner_original.member.email]) msg.content_subtype = "html" if getattr(settings, 'UNIT_TESTING', False): msg.send() else: Thread(target=lambda m: m.send(), args=(msg, )).start() except: logger.error("Failed to notify %s Dara after follower purchase." % partner_original, exc_info=True)
def get_context_data(self, **kwargs): context = super(Dashboard, self).get_context_data(**kwargs) service = get_service_instance() set_counters(service) customers = list(Service.objects.all()) for customer in customers: set_counters(customer) customers_report = { 'today': rank_watch_objects(customers, 'earnings_history'), 'yesterday': rank_watch_objects(customers, 'earnings_history', 1), 'last_week': rank_watch_objects(customers, 'earnings_history', 7), 'last_28_days': rank_watch_objects(customers, 'earnings_history', 28) } apps = list(Application.objects.all()) for app in apps: set_counters(app) apps_report = { 'today': rank_watch_objects(apps, 'earnings_history'), 'yesterday': rank_watch_objects(apps, 'earnings_history', 1), 'last_week': rank_watch_objects(apps, 'earnings_history', 7), 'last_28_days': rank_watch_objects(apps, 'earnings_history', 28) } context['customers_report'] = customers_report context['apps_report'] = apps_report return context
def confirm_processing(request, *args, **kwargs): """ This function targets only Logistics Companies and mark a Package as shipped """ package_id = request.GET['package_id'] try: 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 order.status = Order.SHIPPED order.confirmed_on = datetime.now() order.confirmed_by = request.user order.save() except Package.DoesNotExist: response = {'error': _("No Package found with this 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} config = get_service_instance().config set_counters(config) increment_history_field(config, 'orders_count_history') increment_history_field(config, 'items_traded_history', order.items_count) increment_history_field(config, 'earnings_history', order.delivery_earnings) increment_history_field(config, 'turnover_history', order.delivery_option.cost) config.report_counters_to_umbrella() return HttpResponse(json.dumps(response), 'content-type: text/json')
def get_context_data(self, **kwargs): context = super(Dashboard, self).get_context_data(**kwargs) earnings_today = context['earnings_report']['today'] earnings_yesterday = context['earnings_report']['yesterday'] earnings_last_week = context['earnings_report']['last_week'] earnings_last_28_days = context['earnings_report']['last_28_days'] service = get_service_instance() set_counters(service) orders_count_today = calculate_watch_info( service.transaction_count_history) orders_count_yesterday = calculate_watch_info( service.transaction_count_history, 1) orders_count_last_week = calculate_watch_info( service.transaction_count_history, 7) orders_count_last_28_days = calculate_watch_info( service.transaction_count_history, 28) # AEPO stands for Average Earning Per Order aepo_today = earnings_today['total'] / orders_count_today[ 'total'] if orders_count_today['total'] else 0 aepo_yesterday = earnings_yesterday['total'] / orders_count_yesterday['total']\ if orders_count_yesterday and orders_count_yesterday['total'] else 0 aepo_last_week = earnings_last_week['total'] / orders_count_last_week['total']\ if orders_count_last_week and orders_count_last_week['total'] else 0 aepo_last_28_days = earnings_last_28_days['total'] / orders_count_last_28_days['total']\ if orders_count_last_28_days and orders_count_last_28_days['total'] else 0 orders_report = { 'today': { 'count': orders_count_today['total'] if orders_count_today else 0, 'aepo': '%.2f' % aepo_today, # AEPO: Avg Earning Per Order }, 'yesterday': { 'count': orders_count_yesterday['total'] if orders_count_yesterday else 0, 'aepo': '%.2f' % aepo_yesterday, # AEPO: Avg Earning Per Order }, 'last_week': { 'count': orders_count_last_week['total'] if orders_count_last_week else 0, 'aepo': '%.2f' % aepo_last_week, # AEPO: Avg Earning Per Order }, 'last_28_days': { 'count': orders_count_last_28_days['total'] if orders_count_last_28_days else 0, 'aepo': '%.2f' % aepo_last_28_days, # AEPO: Avg Earning Per Order } } customers_today = slice_watch_objects(Customer) customers_yesterday = slice_watch_objects(Customer, 1) customers_last_week = slice_watch_objects(Customer, 7) customers_last_28_days = slice_watch_objects(Customer, 28) customers_report = { 'today': rank_watch_objects(customers_today, 'turnover_history'), 'yesterday': rank_watch_objects(customers_yesterday, 'turnover_history', 1), 'last_week': rank_watch_objects(customers_last_week, 'turnover_history', 7), 'last_28_days': rank_watch_objects(customers_last_28_days, 'turnover_history', 28) } context['orders_report'] = orders_report context['customers_report'] = customers_report return context
def confirm_reservation_payment(request, *args, **kwargs): """ This view is run after successful user cashout "MOMO_AFTER_CHECKOUT" """ tx = kwargs[ 'tx'] # Decoration with @momo_gateway_callback makes 'tx' available in kwargs amount = tx.amount now = datetime.now() # Update reservation status --- Confirm reservation reservation_id = tx.object_id reservation = Reservation.objects.get(pk=reservation_id) reservation.processor_tx_id = tx.processor_tx_id reservation.method = Reservation.MOBILE_MONEY reservation.status = CONFIRMED item = InvoiceItem(label=_("Reservation of %s " % reservation.post), amount=reservation.amount) short_description = reservation.start_on.strftime( "%Y/%m/%d") + ' - ' + reservation.end_on.strftime("%Y/%m/%d") entry = InvoiceEntry(item=item, short_description=short_description, total=reservation.amount, quantity_unit='') reservation.entries = [entry] reservation.save() # Share earnings weblet = get_service_instance(check_cache=False) config = weblet.config ikwen_charges = tx.amount * config.ikwen_share_rate / 100 ikwen_share_rate = config.ikwen_share_fixed tx.fees = ikwen_charges tx.save() amount = (100 - ikwen_share_rate) * amount / 100 weblet.raise_balance(amount, provider=tx.wallet) set_counters(weblet) increment_history_field(weblet, 'turnover_history', amount) increment_history_field(weblet, 'earnings_history', amount) increment_history_field(weblet, 'transaction_count_history') member = reservation.member # Notify customer and staff payer_email = member.email email = config.contact_email if not email: email = weblet.member.email if email or payer_email: subject = _("New reservation of %s done" % reservation.post) try: html_content = get_mail_content( subject, template_name='enfinchezmoi/mails/payment_notice.html', extra_context={ 'currency_symbol': config.currency_symbol, 'post': reservation, 'payer': member, 'tx_date': tx.updated_on.strftime('%Y-%m-%d'), 'tx_time': tx.updated_on.strftime('%H:%M:%S') }) sender = '%s <no-reply@%s>' % (weblet.project_name, weblet.domain) msg = EmailMessage(subject, html_content, sender, [payer_email]) msg.bcc = [email] msg.content_subtype = "html" if getattr(settings, 'UNIT_TESTING', False): msg.send() else: Thread(target=lambda m: m.send(), args=(msg, )).start() except: logger.error("%s - Failed to send notice mail to %s." % (weblet, email), exc_info=True) # if member.email: # activate(member.language) # invoice_url = ikwen_service.url + reverse('billing:invoice_detail', args=(invoice.id,)) # subject, message, sms_text = get_payment_confirmation_message(payment, member) # html_content = get_mail_content(subject, message, service=vendor, template_name='billing/mails/notice.html', # extra_context={'member_name': member.first_name, 'invoice': invoice, # 'cta': _("View invoice"), 'invoice_url': invoice_url, # 'early_payment': is_early_payment}) # sender = '%s <no-reply@%s>' % (vendor.config.company_name, ikwen_service.domain) # msg = XEmailMessage(subject, html_content, sender, [member.email]) # if vendor != ikwen_service and not vendor_is_dara: # msg.service = vendor # if invoice_pdf_file: # msg.attach_file(invoice_pdf_file) # msg.content_subtype = "html" # if getattr(settings, 'UNIT_TESTING', False): # msg.send() # else: # Thread(target=lambda m: m.send(), args=(msg,)).start() return HttpResponse("Notification received")
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
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)
def confirm_invoice_payment(request, *args, **kwargs): tx = kwargs[ 'tx'] # Decoration with @momo_gateway_callback makes 'tx' available in kwargs school = Service.objects.get(pk=tx.service_id) school_config = SchoolConfig.objects.get(service=school) ikwen_charges = tx.amount * school_config.ikwen_share_rate / 100 tx.fees = ikwen_charges tx.save() mean = tx.wallet db = school.database add_database(db) invoice = Invoice.objects.using(db).get(pk=tx.object_id) payment = Payment.objects.using(db).create( invoice=invoice, method=Payment.MOBILE_MONEY, amount=tx.amount, processor_tx_id=tx.processor_tx_id) invoice.paid = tx.amount invoice.status = Invoice.PAID invoice.save() student = invoice.student if not school_config.is_public or (school_config.is_public and not invoice.is_tuition): amount = tx.amount - ikwen_charges school.raise_balance(amount, provider=mean) else: amount = tx.amount student.set_has_new(using=school.database) student.save(using='default') set_counters(school) increment_history_field(school, 'turnover_history', tx.amount) increment_history_field(school, 'earnings_history', amount) increment_history_field(school, 'transaction_count_history') increment_history_field(school, 'transaction_earnings_history', amount) member = invoice.member if member.email: try: currency = Currency.active.default().symbol except: currency = school_config.currency_code invoice_url = school.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>' % (school_config.company_name, school.domain) msg = XEmailMessage(subject, html_content, sender, [member.email]) msg.content_subtype = "html" bcc = [ email.strip() for email in school_config.notification_emails.split(',') if email.strip() ] bcc += [school_config.contact_email, school.member.email] msg.bcc = list(set(bcc)) try: invoicing_config = get_invoicing_config_instance() invoice_pdf_file = generate_pdf_invoice(invoicing_config, invoice) msg.attach_file(invoice_pdf_file) except: pass return HttpResponse( "Notification for transaction %s received with status %s" % (tx.id, tx.status))
def cash_in(self, invoice, request): if not request.user.has_perm('billing.ik_cash_in'): return HttpResponse( json.dumps({'error': "You're not allowed here"})) service = get_service_instance() config = service.config invoicing_config = get_invoicing_config_instance() if invoice.status == Invoice.PAID: return HttpResponse(json.dumps({'error': "Invoice already paid"})) amount = request.GET.get('amount', invoice.amount) try: amount = float(amount) if amount <= 0: raise ValueError() except ValueError: return HttpResponse(json.dumps({'error': "Invalid amount"})) member = invoice.member payment = Payment.objects.create(invoice=invoice, amount=amount, method=Payment.CASH, cashier=request.user) response = {'success': True, 'payment': payment.to_dict()} try: aggr = Payment.objects.filter(invoice=invoice).aggregate( Sum('amount')) amount_paid = aggr['amount__sum'] except IndexError: amount_paid = 0 if invoicing_config.return_url: try: subscription = invoice.subscription extra_months = request.GET.get('extra_months', 0) params = { 'reference_id': subscription.reference_id, 'invoice_number': invoice.number, 'amount_paid': amount, 'extra_months': extra_months } Thread(target=notify_event, args=(service, invoicing_config.return_url, params)).start() except: notice = "%s: Could not notify endpoint %s after cash in" % ( service, invoicing_config.return_url) logger.error(notice, exc_info=True) total = amount + amount_paid invoice.paid += amount if total >= invoice.amount: invoice.status = Invoice.PAID try: subscription = invoice.subscription subscription.status = Subscription.ACTIVE days = get_days_count(invoice.months_count) subscription.expiry += timedelta(days=days) subscription.save() except AttributeError: pass invoice.save() set_counters(service) increment_history_field(service, 'turnover_history', amount) increment_history_field(service, 'earnings_history', amount) increment_history_field(service, 'transaction_earnings_history', amount) increment_history_field(service, 'invoice_earnings_history', amount) increment_history_field(service, 'transaction_count_history') increment_history_field(service, 'invoice_count_history') if member.email: from echo.models import Balance from echo.utils import notify_for_low_messaging_credit, LOW_MAIL_LIMIT, notify_for_empty_messaging_credit balance = Balance.objects.using(WALLETS_DB_ALIAS).get( service_id=service.id) if 0 < balance.mail_count < LOW_MAIL_LIMIT: notify_for_low_messaging_credit(service, balance) if balance.mail_count <= 0 and not getattr(settings, 'UNIT_TESTING', False): notify_for_empty_messaging_credit(service, balance) return HttpResponse(json.dumps(response)) subject, message, sms = get_payment_confirmation_message( payment, member) html_content = get_mail_content( subject, message, template_name='billing/mails/notice.html') sender = '%s <no-reply@%s>' % (config.company_name, service.domain) msg = XEmailMessage(subject, html_content, sender, [member.email]) msg.content_subtype = "html" try: with transaction.atomic(using='wallets'): balance.mail_count -= 1 balance.save() Thread(target=lambda m: m.send(), args=(msg, )).start() except: pass return HttpResponse(json.dumps(response))
def notify_profiles(debug=False): t0 = datetime.now() total_revival, total_mail, total_sms = 0, 0, 0 logger.debug("Starting cyclic revival") today = t0.date() queryset = CyclicRevival.objects.select_related('service')\ .filter(next_run_on=today, hour_of_sending=t0.hour, end_on__gt=today, is_active=True) for revival in queryset: try: refreshed = CyclicRevival.objects.get(pk=revival.id) if refreshed.is_running: continue refreshed.is_running = True refreshed.save() total_revival += 1 except CyclicRevival.DoesNotExist: continue service = revival.service db = service.database add_database(db) balance = Balance.objects.using(WALLETS_DB_ALIAS).get( service_id=service.id) if balance.mail_count == 0 and balance.sms_count == 0: try: notify_for_empty_messaging_credit(service, balance) except: revival.is_running = False revival.save() logger.error( "Failed to notify %s for empty messaging credit." % service, exc_info=True) continue if 0 < balance.mail_count < LOW_MAIL_LIMIT or 0 < balance.sms_count < LOW_SMS_LIMIT: try: notify_for_low_messaging_credit(service, balance) except: revival.is_running = False revival.save() logger.error("Failed to notify %s for low messaging credit." % service, exc_info=True) label = get_sms_label(service.config) notified_empty_mail_credit = False notified_empty_sms_credit = False if debug: member_queryset = Member.objects.using(db).filter( is_superuser=True) else: member_queryset = Member.objects.using(db).all() total = member_queryset.count() try: profile_tag = ProfileTag.objects.using(db).get( pk=revival.profile_tag_id) except ProfileTag.DoesNotExist: revival.delete() continue set_counters(profile_tag) revival_local = CyclicRevival.objects.using(db).get(pk=revival.id) chunks = total / 500 + 1 for i in range(chunks): start = i * 500 finish = (i + 1) * 500 for member in member_queryset.order_by( 'date_joined')[start:finish]: try: profile = MemberProfile.objects.using(db).get( member=member) except MemberProfile.DoesNotExist: continue match = set(profile.tag_fk_list) & {profile_tag.id} if len(match) > 0: if member.email: CyclicTarget.objects.using(db).get_or_create( revival=revival_local, member=member) revival.set_next_run_date() connection = mail.get_connection() try: connection.open() except: logger.error(u"Connexion error", exc_info=True) break logger.debug("Running revival %s for %s" % (revival.mail_subject, revival.service)) for target in revival_local.cyclictarget_set.select_related('member'): member = target.member if member.language: activate(member.language) else: activate('en') subject = revival.mail_subject message = revival.mail_content.replace('$client', member.first_name) sender = '%s <no-reply@%s>' % (service.project_name, service.domain) try: currency = Currency.objects.using(using=db).get(is_base=True) except Currency.DoesNotExist: currency = None product_list = [] if service.app.slug == 'kakocase': product_list = Product.objects.using(db).filter( pk__in=revival.items_fk_list) extra_context = { 'revival': revival, 'currency': currency, 'media_url': getattr(settings, 'CLUSTER_MEDIA_URL') + service.project_name_slug + '/', 'product_list': product_list } try: html_content = get_mail_content( subject, message, template_name='revival/mails/default.html', service=service, extra_context=extra_context) except: logger.error( "Could not render mail for member %s, Cyclic revival on %s" % (member.username, profile_tag), exc_info=True) break msg = XEmailMessage(subject, html_content, sender, [member.email]) msg.content_subtype = "html" msg.type = XEmailObject.REVIVAL if balance.mail_count == 0 and not notified_empty_mail_credit: notify_for_empty_messaging_credit(service, balance) notified_empty_mail_credit = True else: try: with transaction.atomic(using=WALLETS_DB_ALIAS): if not debug: balance.mail_count -= 1 balance.save() if msg.send(): target.revival_count += 1 target.save() total_mail += 1 increment_history_field( profile_tag, 'cyclic_revival_mail_history') else: logger.error( "Cyclic revival with subject %s not sent for member %s" % (subject, member.email), exc_info=True) except: logger.error( "Critical error in revival %s when processing Mail sending for member %s" % (revival.id, member.email), exc_info=True) if revival.sms_text: if balance.sms_count == 0 and not notified_empty_sms_credit: notify_for_empty_messaging_credit(service, balance) notified_empty_sms_credit = True else: sms_text = revival.sms_text.replace( '$client', member.first_name) page_count = count_pages(sms_text) try: with transaction.atomic(using=WALLETS_DB_ALIAS): balance.sms_count -= page_count balance.save() send_sms(recipient=member.phone, text=sms_text, fail_silently=False) total_sms += 1 increment_history_field( profile_tag, 'cyclic_revival_sms_history') SMSObject.objects.create(recipient=member.phone, text=sms_text, label=label) except: logger.error( "Critical error in revival %s when processing SMS sending for member %s" % (revival.id, member.email), exc_info=True) if balance.mail_count == 0 and balance.sms_count == 0: break revival.is_running = False revival.save() try: connection.close() except: pass diff = datetime.now() - t0 logger.debug("%d revivals run. %d mails and %d SMS sent in %s" % (total_revival, total_mail, total_sms, diff))
def confirm_correction_payment(request, *args, **kwargs): 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'] try: tx = MoMoTransaction.objects.using(WALLETS_DB_ALIAS).get(pk=tx_id) 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) except: raise Http404("Transaction %s not found" % tx_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 != tx.task_id: return HttpResponse('Invalid transaction signature') else: if callback_signature != tx.task_id: return HttpResponse('Invalid transaction signature') if status != MoMoTransaction.SUCCESS: return HttpResponse( "Notification for transaction %s received with status %s" % (tx_id, status)) school = get_service_instance() school_config = SchoolConfig.objects.get(service=school) ikwen_charges = tx.amount * school_config.my_kids_share_rate / 100 teacher_earnings = tx.amount * (100 - school_config.my_kids_share_rate) / 100 tx.status = status tx.message = message tx.processor_tx_id = operator_tx_id tx.phone = phone tx.is_running = False tx.fees = ikwen_charges tx.save() # mean = tx.wallet # # amount = tx.amount - ikwen_charges # payment = Payment.objects.get(object_id=tx.object_id) assignment = Assignment.objects.get(title=tx.message.rstrip(' correction')) correction = assignment.assignmentcorrection parent = request.user subject = assignment.subject classroom = assignment.classroom teacher = subject.get_teacher(classroom=classroom) daraja = Application.objects.get(slug=DARAJA) try: dara_weblet = Service.objects.using(UMBRELLA).get( app=daraja, member=teacher.member) dara_db = dara_weblet.database dara_weblet_self = Service.objects.using(dara_db).get( pk=dara_weblet.id) set_counters(dara_weblet_self) increment_history_field(dara_weblet_self, 'turnover_history', teacher_earnings) increment_history_field(dara_weblet_self, 'earnings_history', teacher_earnings) increment_history_field(dara_weblet_self, 'transaction_count_history') # share_payment_and_set_stats(invoice, mean) except: logger.error("The teacher %s doesn't yet have a Dara account" % teacher) foulassi_weblet = get_service_instance() try: currency = Currency.active.default().symbol except: currency = school_config.currency_code body = _( "A student just purchase the correction of %(assignment_title)s in %(subject_name)s" % { 'assignment_title': assignment.title, 'subject_name': subject.name }) member_teacher = teacher.member subject = _("New correction of %s paid" % correction) cta_url = 'https://daraja.ikwen.com' + reverse('daraja:dashboard') html_content = get_mail_content( subject, template_name='foulassi/mails/correction_paid.html', extra_context={ 'teacher': member_teacher.first_name, 'classroom': classroom, 'cta_url': cta_url, 'subject': assignment.subject.name, 'assignment': assignment, 'currency': currency }) sender = '%s <no-reply@%s>' % (school_config.company_name, school.domain) msg = XEmailMessage(subject, html_content, sender, [member_teacher.email]) msg.bcc = ['*****@*****.**', '*****@*****.**'] msg.content_subtype = "html" try: msg.send() except Exception as e: logger.debug(e.message) send_push(foulassi_weblet, member_teacher, subject, body, cta_url) body = _( "You just pay the correction of %(assignment_title)s from %(subject_name)s " % { 'assignment_title': assignment.title, 'subject_name': subject.name }) subject = _("New correction paid") if parent.email: html_content = get_mail_content( subject, template_name='foulassi/mails/correction_paid_parent_notif.html', extra_context={ 'classroom': classroom, 'parent_name': parent.first_name, 'subject': assignment.subject.name, 'assignment': assignment, 'currency': currency }) sender = '%s <no-reply@%s>' % (school_config.company_name, school.domain) msg = XEmailMessage(subject, html_content, sender, [parent.email]) msg.bcc = ['*****@*****.**', '*****@*****.**'] msg.content_subtype = "html" try: msg.send() except Exception as e: logger.debug(e.message) send_push(foulassi_weblet, parent, subject, body, cta_url) return HttpResponse( "Notification for transaction %s received with status %s" % (tx_id, status))
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)
def notify_profiles(debug=False): """ Cron job that revive users by mail. Must be configured to run with a settings file having 'umbrella' as default database. :return: """ t0 = datetime.now() seven_hours_ago = t0 - timedelta(hours=7) total_revival, total_mail = 0, 0 for revival in Revival.objects.select_related('service').exclude( status=COMPLETE, is_active=False): try: refreshed = Revival.objects.get(pk=revival.id) if refreshed.is_running: continue refreshed.is_running = True refreshed.save() total_revival += 1 except Revival.DoesNotExist: continue try: mail_renderer = import_by_path(revival.mail_renderer) kwargs = {} if revival.get_kwargs: get_kwargs = import_by_path(revival.get_kwargs) kwargs = get_kwargs(revival) except: revival.is_running = False revival.save() logger.error("Error when starting revival %s for %s" % (revival.mail_renderer, revival.service), exc_info=True) continue service = revival.service db = service.database add_database(db) balance = Balance.objects.using(WALLETS_DB_ALIAS).get( service_id=service.id) if balance.mail_count == 0: revival.is_running = False revival.save() try: notify_for_empty_messaging_credit(service, balance) except: logger.error( "Failed to notify %s for empty messaging credit." % service, exc_info=True) continue if 0 < balance.mail_count < LOW_MAIL_LIMIT: try: notify_for_low_messaging_credit(service, balance) except: logger.error("Failed to notify %s for low messaging credit." % service, exc_info=True) tk = revival.model_name.split('.') model = get_model(tk[0], tk[1]) try: obj = model._default_manager.using(db).get(pk=revival.object_id) except ObjectDoesNotExist: revival.is_running = False revival.save() continue try: profile_tag = ProfileTag.objects.using(db).get( pk=revival.profile_tag_id) except: revival.is_running = False revival.save() continue if revival.status != PENDING: revival.is_running = False revival.save() continue set_counters(profile_tag) revival_local = Revival.objects.using(db).get(pk=revival.id) if debug: member_queryset = Member.objects.using(db).filter( is_superuser=True) else: member_queryset = Member.objects.using(db).filter( date_joined__lte=seven_hours_ago) total = member_queryset.count() chunks = total / 500 + 1 target_count = 0 for i in range(chunks): start = i * 500 finish = (i + 1) * 500 for member in member_queryset.order_by( 'date_joined')[start:finish]: try: profile = MemberProfile.objects.using(db).get( member=member) except MemberProfile.DoesNotExist: ref_tag = ProfileTag.objects.using(db).get(slug=REFERRAL) profile = MemberProfile.objects.using(db).create( member=member, tag_fk_list=[ref_tag.id]) if revival.profile_tag_id in profile.tag_fk_list: if debug: tag = ProfileTag.objects.using(db).get( pk=revival.profile_tag_id) print "Profiles matching on %s for member %s" % ( tag, member) if member.email: Target.objects.using(db).get_or_create( revival=revival_local, member=member) target_count += 1 if target_count == 0: revival.is_running = False revival.save() continue revival.run_on = datetime.now() revival.status = STARTED revival.total = revival_local.target_set.all().count() revival.save() connection = mail.get_connection() try: connection.open() except: revival.is_running = False revival.save() logger.error(u"Connexion error", exc_info=True) continue logger.debug("Running notify_profiles() %s for %s" % (revival.mail_renderer, revival.service)) for target in revival_local.target_set.select_related('member').filter( notified=False)[:MAX_BATCH_SEND]: if not debug and balance.mail_count == 0: revival.is_running = False revival.save() try: notify_for_empty_messaging_credit(service, balance) except: logger.error( "Failed to notify %s for empty messaging credit." % service, exc_info=True) break member = target.member if member.language: activate(member.language) else: activate('en') if getattr(settings, 'UNIT_TESTING', False): sender, subject, html_content = mail_renderer( target, obj, revival, **kwargs) else: try: sender, subject, html_content = mail_renderer( target, obj, revival, **kwargs) except: logger.error( "Could not render mail for member %s, Revival %s, Obj: %s" % (member.email, revival.mail_renderer, str(obj)), exc_info=True) continue if not html_content: continue if debug: subject = 'Test - ' + subject msg = XEmailMessage(subject, html_content, sender, [member.email]) msg.content_subtype = "html" msg.type = XEmailObject.REVIVAL try: with transaction.atomic(using=WALLETS_DB_ALIAS): if not debug: balance.mail_count -= 1 balance.save() if msg.send(): target.revival_count += 1 target.notified = True target.revived_on = t0 target.save() total_mail += 1 increment_history_field(profile_tag, 'smart_revival_history') else: logger.error("Member %s not notified for Content %s" % (member.email, str(obj)), exc_info=True) except: logger.error("Member %s not notified for Content %s" % (member.email, str(obj)), exc_info=True) revival.progress += 1 revival.save() revival.is_running = False if revival.progress > 0 and revival.progress >= revival.total: revival.status = COMPLETE revival.save() try: connection.close() except: revival.is_running = False revival.save() diff = datetime.now() - t0 logger.debug("notify_profiles() run %d revivals. %d mails sent in %s" % (total_revival, total_mail, diff))
def wrapper(*args, **kwargs): request = args[0] status = request.GET['status'] message = request.GET['message'] operator_tx_id = request.GET['operator_tx_id'] phone = request.GET['phone'] object_id = kwargs.pop('object_id') try: tx = MoMoTransaction.objects.using(WALLETS_DB_ALIAS).get(object_id=object_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) weblet = get_service_instance(check_cache=False) ikwen_charges = tx.amount * weblet.config.ikwen_share_rate / 100 tx.status = status tx.message = 'OK' if status == MoMoTransaction.SUCCESS else message tx.processor_tx_id = operator_tx_id tx.phone = phone tx.fees = ikwen_charges dara_fees = 0 try: from daraja.models import Dara, Follower member = tx.member follower = Follower.objects.select_related().get(member=member) referrer = follower.referrer if not referrer: return dara = Dara.objects.get(member=referrer.member) dara_fees = tx.amount * dara.share_rate / 100 tx.dara_fees = dara_fees tx.dara_id = dara.id except: pass amount = tx.amount - ikwen_charges - dara_fees try: set_counters(weblet) increment_history_field(weblet, 'turnover_history', tx.amount) increment_history_field(weblet, 'earnings_history', amount) increment_history_field(weblet, 'transaction_count_history') except: pass tx.is_running = False tx.save() weblet.raise_balance(amount, tx.wallet) except: raise Http404("Transaction with object_id %s not found" % object_id) if status != MoMoTransaction.SUCCESS: return HttpResponse("Notification for transaction %s received with status %s" % (tx.id, status)) signature = tx.task_id callback_signature = kwargs['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') kwargs['tx'] = tx try: return fn(*args, **kwargs) except: tx.message = traceback.format_exc() tx.save(using='wallets') return HttpResponse('Warning: Failed to run callback')
def confirm_payment(request, *args, **kwargs): 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'] try: tx = MoMoTransaction.objects.using(WALLETS_DB_ALIAS).get(pk=tx_id) 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) except: raise Http404("Transaction %s not found" % tx_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 != tx.task_id: return HttpResponse('Invalid transaction signature') else: if callback_signature != tx.task_id: return HttpResponse('Invalid transaction signature') if status != MoMoTransaction.SUCCESS: return HttpResponse( "Notification for transaction %s received with status %s" % (tx_id, status)) tx.status = status tx.message = message tx.processor_tx_id = operator_tx_id tx.phone = phone tx.is_running = False tx.save() mean = tx.wallet payment = Payment.objects.select_related('member', 'product').get(pk=tx.object_id) payment.status = CONFIRMED payment.processor_tx_id = operator_tx_id payment.save() product = payment.product provider = product.provider payer = payment.member provider_member = provider.member try: callback = import_by_path(product.callback) callback(product, payer) # Callback should send notification email, push, etc. except: logger.error("", exc_info=True) marketplace_weblet = get_service_instance() config = marketplace_weblet.config if provider and provider.project_name_slug != 'ikwen': provider_earnings = tx.amount * (100 - product.ikwen_share_rate) / 100 provider.raise_balance(provider_earnings, provider=mean) daraja = Application.objects.get(slug=DARAJA) dara_weblet = Service.objects.using(UMBRELLA).get( app=daraja, member=provider_member) dara_db = dara_weblet.database dara_weblet_self = Service.objects.using(dara_db).get( pk=dara_weblet.id) set_counters(dara_weblet_self) increment_history_field(dara_weblet_self, 'turnover_history', provider_earnings) increment_history_field(dara_weblet_self, 'earnings_history', provider_earnings) increment_history_field(dara_weblet_self, 'transaction_count_history') activate(provider_member.language) dashboard_url = 'https://daraja.ikwen.com' + reverse( 'daraja:dashboard') subject = _("New transaction on %s" % config.company_name) try: html_content = get_mail_content( subject, template_name='daraja/mails/new_transaction.html', extra_context={ 'currency_symbol': config.currency_symbol, 'amount': tx.amount, 'dara_earnings': provider_earnings, 'tx_date': tx.updated_on.strftime('%Y-%m-%d'), 'tx_time': tx.updated_on.strftime('%H:%M:%S'), 'account_balance': dara_weblet.balance, 'dashboard_url': dashboard_url }) sender = 'ikwen Daraja <*****@*****.**>' msg = EmailMessage(subject, html_content, sender, [provider_member.email]) msg.content_subtype = "html" if getattr(settings, 'UNIT_TESTING', False): msg.send() else: Thread(target=lambda m: m.send(), args=(msg, )).start() except: logger.error("Failed to notify %s Dara after follower purchase." % dara_weblet, exc_info=True) body = _( "%(customer)s just purchased a %(product)s pack for %(currency)s %(amount)s. Please take a look " "and deliver the best service." % { 'customer': payer.full_name, 'product': product, 'currency': config.currency_code, 'amount': intcomma(tx.amount) }) daraja_weblet = Service.objects.using(UMBRELLA).get(slug=DARAJA) send_push(daraja_weblet, provider_member, subject, body, dashboard_url) email = product.email if not email: email = product.provider.config.contact_email if not email: email = product.provider.member.email if email: subject = _("New payment of %s" % product.name) try: html_content = get_mail_content( subject, template_name='marketplace/mails/payment_notice.html', extra_context={ 'currency_symbol': config.currency_symbol, 'product': product, 'payer': payer, 'tx_date': tx.updated_on.strftime('%Y-%m-%d'), 'tx_time': tx.updated_on.strftime('%H:%M:%S') }) sender = 'ikwen MarketPlace <*****@*****.**>' msg = EmailMessage(subject, html_content, sender, [provider_member.email]) msg.content_subtype = "html" if getattr(settings, 'UNIT_TESTING', False): msg.send() else: Thread(target=lambda m: m.send(), args=(msg, )).start() except: logger.error("%s - Failed to send notice mail to %s." % (marketplace_weblet, email), exc_info=True) return HttpResponse("Notification successfully received")
def get_context_data(self, **kwargs): context = super(Dashboard, self).get_context_data(**kwargs) service = get_service_instance() set_counters(service) earnings_today = context['earnings_report']['today'] earnings_yesterday = context['earnings_report']['yesterday'] earnings_last_week = context['earnings_report']['last_week'] earnings_last_28_days = context['earnings_report']['last_28_days'] transaction_count = calculate_watch_info(service.transaction_count_history) transaction_count_yesterday = calculate_watch_info(service.transaction_count_history, 1) transaction_count_last_week = calculate_watch_info(service.transaction_count_history, 7) transaction_count_last_28_days = calculate_watch_info(service.transaction_count_history, 28) # AEPT stands for Average Earning Per Transaction aept_today = earnings_today['total'] / transaction_count['total'] if transaction_count['total'] else 0 aept_yesterday = earnings_yesterday['total'] / transaction_count_yesterday['total']\ if transaction_count_yesterday and transaction_count_yesterday['total'] else 0 aept_last_week = earnings_last_week['total'] / transaction_count_last_week['total']\ if transaction_count_last_week and transaction_count_last_week['total'] else 0 aept_last_28_days = earnings_last_28_days['total'] / transaction_count_last_28_days['total']\ if transaction_count_last_28_days and transaction_count_last_28_days['total'] else 0 transactions_report = { 'today': { 'count': transaction_count['total'] if transaction_count else 0, 'aept': '%.2f' % aept_today, # AEPT: Avg Earning Per Transaction }, 'yesterday': { 'count': transaction_count_yesterday['total'] if transaction_count_yesterday else 0, 'aept': '%.2f' % aept_yesterday, }, 'last_week': { 'count': transaction_count_last_week['total'] if transaction_count_last_week else 0, 'aept': '%.2f' % aept_last_week, }, 'last_28_days': { 'count': transaction_count_last_28_days['total']if transaction_count_last_28_days else 0, 'aept': '%.2f' % aept_last_28_days, } } customers = list(Service.objects.all()) for customer in customers: set_counters(customer) customers_report = { 'today': rank_watch_objects(customers, 'earnings_history'), 'yesterday': rank_watch_objects(customers, 'earnings_history', 1), 'last_week': rank_watch_objects(customers, 'earnings_history', 7), 'last_28_days': rank_watch_objects(customers, 'earnings_history', 28) } apps = list(Application.objects.all()) for app in apps: set_counters(app) apps_report = { 'today': rank_watch_objects(apps, 'earnings_history'), 'yesterday': rank_watch_objects(apps, 'earnings_history', 1), 'last_week': rank_watch_objects(apps, 'earnings_history', 7), 'last_28_days': rank_watch_objects(apps, 'earnings_history', 28) } context['transactions_report'] = transactions_report context['customers_report'] = customers_report context['apps_report'] = apps_report return context
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')
def set_ikwen_earnings_and_stats(order): service = get_service_instance() service_umbrella = Service.objects.using(UMBRELLA).get(pk=service.id) app_umbrella = service_umbrella.app delcom = order.delivery_company service_delcom_umbrella = Service.objects.using(UMBRELLA).get(pk=delcom.id) app_delcom_umbrella = service_delcom_umbrella.app payment_mean_slug = order.payment_mean.slug if payment_mean_slug == DARA_CASH: payment_mean_slug = MTN_MOMO # IKWEN STATS set_counters(service_umbrella) increment_history_field(service_umbrella, 'turnover_history', order.items_cost) increment_history_field(service_umbrella, 'earnings_history', order.ikwen_order_earnings) increment_history_field(service_umbrella, 'transaction_count_history') increment_history_field(service_umbrella, 'transaction_earnings_history', order.ikwen_order_earnings) set_counters(app_umbrella) increment_history_field(app_umbrella, 'turnover_history', order.items_cost) increment_history_field(app_umbrella, 'earnings_history', order.ikwen_order_earnings) increment_history_field(app_umbrella, 'transaction_count_history') increment_history_field(app_umbrella, 'transaction_earnings_history', order.ikwen_order_earnings) set_counters(service_delcom_umbrella) increment_history_field(service_delcom_umbrella, 'turnover_history', order.delivery_option.cost) increment_history_field(service_delcom_umbrella, 'earnings_history', order.ikwen_delivery_earnings) increment_history_field(service_delcom_umbrella, 'transaction_count_history') increment_history_field(service_delcom_umbrella, 'transaction_earnings_history', order.ikwen_delivery_earnings) set_counters(app_delcom_umbrella) increment_history_field(app_delcom_umbrella, 'turnover_history', order.delivery_option.cost) increment_history_field(app_delcom_umbrella, 'earnings_history', order.ikwen_delivery_earnings) increment_history_field(app_delcom_umbrella, 'transaction_count_history') increment_history_field(app_delcom_umbrella, 'transaction_earnings_history', order.ikwen_delivery_earnings) partner = service.retailer if partner: service_partner = get_service_instance(partner.database) app_partner = service_partner.app partner_umbrella = Service.objects.using(UMBRELLA).get(pk=partner.id) partner_app_umbrella = partner_umbrella.app set_counters(service_partner) increment_history_field(service_partner, 'turnover_history', order.items_cost) increment_history_field(service_partner, 'earnings_history', order.eshop_partner_earnings) increment_history_field(service_partner, 'transaction_count_history') increment_history_field(service_partner, 'transaction_earnings_history', order.eshop_partner_earnings) set_counters(app_partner) increment_history_field(app_partner, 'turnover_history', order.items_cost) increment_history_field(app_partner, 'earnings_history', order.eshop_partner_earnings) increment_history_field(app_partner, 'transaction_count_history') increment_history_field(app_partner, 'transaction_earnings_history', order.eshop_partner_earnings) partner.raise_balance(order.eshop_partner_earnings, payment_mean_slug) set_counters(partner_umbrella) increment_history_field(partner_umbrella, 'turnover_history', order.items_cost) increment_history_field(partner_umbrella, 'earnings_history', order.ikwen_order_earnings) increment_history_field(partner_umbrella, 'transaction_count_history') increment_history_field(partner_umbrella, 'transaction_earnings_history', order.ikwen_order_earnings) set_counters(partner_app_umbrella) increment_history_field(partner_app_umbrella, 'turnover_history', order.items_cost) increment_history_field(partner_app_umbrella, 'earnings_history', order.ikwen_order_earnings) increment_history_field(partner_app_umbrella, 'transaction_count_history') increment_history_field(partner_app_umbrella, 'transaction_earnings_history', order.ikwen_order_earnings) delcom_partner = delcom.retailer # Partner who actually created Delivery partner website if delcom_partner: service_delcom_partner = Service.objects.using(delcom_partner.database).get(pk=delcom.id) app_delcom_partner = service_delcom_partner.app delcom_partner_umbrella = Service.objects.using(UMBRELLA).get(pk=delcom_partner.id) delcom_partner_app_umbrella = delcom_partner_umbrella.app set_counters(service_delcom_partner) increment_history_field(service_delcom_partner, 'turnover_history', order.delivery_option.cost) increment_history_field(service_delcom_partner, 'earnings_history', order.logicom_partner_earnings) increment_history_field(service_delcom_partner, 'transaction_count_history') increment_history_field(service_delcom_partner, 'transaction_earnings_history', order.logicom_partner_earnings) set_counters(app_delcom_partner) increment_history_field(app_delcom_partner, 'turnover_history', order.delivery_option.cost) increment_history_field(app_delcom_partner, 'earnings_history', order.logicom_partner_earnings) increment_history_field(app_delcom_partner, 'transaction_count_history') increment_history_field(app_delcom_partner, 'transaction_earnings_history', order.logicom_partner_earnings) delcom_partner.raise_balance(order.logicom_partner_earnings, payment_mean_slug) set_counters(delcom_partner_umbrella) increment_history_field(delcom_partner_umbrella, 'turnover_history', order.delivery_option.cost) increment_history_field(delcom_partner_umbrella, 'earnings_history', order.ikwen_delivery_earnings) increment_history_field(delcom_partner_umbrella, 'transaction_count_history') increment_history_field(delcom_partner_umbrella, 'transaction_earnings_history', order.ikwen_delivery_earnings) set_counters(delcom_partner_app_umbrella) increment_history_field(delcom_partner_app_umbrella, 'turnover_history', order.delivery_option.cost) increment_history_field(delcom_partner_app_umbrella, 'earnings_history', order.ikwen_delivery_earnings) increment_history_field(delcom_partner_app_umbrella, 'transaction_count_history') increment_history_field(delcom_partner_app_umbrella, 'transaction_earnings_history', order.ikwen_delivery_earnings)
def notify_cashout_and_reset_counters(request, transaction, *args, **kwargs): """ Notifies IAO that request to cashout completed successfully and resets wallet balance accordingly :param request: :param transaction: MoMoTransaction object used to process this operation :return: """ cashout_request = CashOutRequest.objects.using('wallets').get( pk=transaction.object_id) cashout_request.status = CashOutRequest.PAID cashout_request.reference = transaction.processor_tx_id charges = cashout_request.amount * cashout_request.rate / 100 cashout_request.amount_paid = cashout_request.amount * ( 100 - cashout_request.rate) / 100 cashout_request.save() weblet = Service.objects.using(UMBRELLA).get(pk=transaction.service_id) wallet = OperatorWallet.objects.using('wallets').get( nonrel_id=weblet.id, provider=transaction.wallet) method = CashOutMethod.objects.using(UMBRELLA).get(slug=transaction.wallet) address = CashOutAddress.objects.using(UMBRELLA).get(service=weblet, method=method) with db_transaction.atomic(using='wallets'): queryset = MoMoTransaction.objects.using('wallets') \ .filter(created_on__gt=cashout_request.paid_on, type=MoMoTransaction.CASH_OUT, status=MoMoTransaction.SUCCESS, wallet=cashout_request.provider) iao = weblet.member if weblet.app.slug == DARAJA: dara = Dara.objects.get(member=iao) queryset = queryset.filter(dara_id=dara.id) if queryset.count() > 0: aggr = queryset.aggregate(Sum('dara_fees')) amount_successful = aggr['dara_fees__sum'] else: amount_successful = 0 else: queryset = queryset.filter(service_id=weblet.id) if queryset.count() > 0: aggr = queryset.aggregate(Sum('amount')) aggr_fees = queryset.aggregate(Sum('fees')) aggr_dara_fees = queryset.aggregate(Sum('dara_fees')) amount_successful = aggr['amount__sum'] - aggr_fees[ 'fees__sum'] - aggr_dara_fees['dara_fees__sum'] else: amount_successful = 0 wallet.balance = amount_successful wallet.save(using='wallets') if getattr(settings, 'TESTING', False): IKWEN_SERVICE_ID = getattr(settings, 'IKWEN_ID') ikwen_service = Service.objects.using(UMBRELLA).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) sender = 'ikwen <*****@*****.**>' event_originator = ikwen_service add_event(event_originator, CASH_OUT_REQUEST_PAID, member=iao, object_id=cashout_request.id) subject = _("Money transfer confirmation") html_content = get_mail_content( subject, '', template_name='cashout/mails/payment_notice.html', extra_context={ 'cash_out_request': cashout_request, 'charges': charges, 'weblet': weblet, 'address': address, 'service': event_originator }) msg = XEmailMessage(subject, html_content, sender, [iao.email]) msg.service = ikwen_service 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', cashout_request.amount) increment_history_field(ikwen_service, 'cash_out_count_history')
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')