def generate_monthly_bills(billing_range=None, domain_name=None): logging.info("[Billing] Generating Monthly Bills") from corehq.apps.domain.models import Domain if domain_name is not None: domains = [domain_name] else: domains = [domain['key'] for domain in Domain.get_all(include_docs=False)] for domain in domains: HQMonthlyBill.create_bill_for_domain(domain, billing_range=billing_range)
def get_billable_domains(cls): marked_domains = SMSBillable.get_db().view('hqbilling/domains_marked_for_billing', reduce=False).all() prev_month, _ = HQMonthlyBill.get_default_start_end() recent = SMSBillable.get_db().view('hqbilling/domains_with_billables', startkey=[prev_month.year, prev_month.month], group=True, group_level=3).all() recent_counts = defaultdict(int) for r in recent: recent_counts[r['key'][-1]] += r['value'] for m in marked_domains: if m['key'] not in recent_counts.keys(): recent_counts[m['key']] = 0 all_time = SMSBillable.get_db().view('hqbilling/domains_with_billables', group=True, group_level=3).all() all_time_counts = defaultdict(int) for a in all_time: if a['key'][-1] not in recent_counts.keys(): all_time_counts[a['key'][-1]] += a['value'] sorted_recent = sorted(recent_counts.iteritems(), key=operator.itemgetter(1), reverse=True) sorted_all_time = sorted(all_time_counts.iteritems(), key=operator.itemgetter(1), reverse=True) return [Domain.get_by_name(r[0]) for r in sorted_recent if r[0]] + \ [Domain.get_by_name(a[0]) for a in sorted_all_time if a[0]]
def testSMSBilling(self): generate_monthly_bills() last_bill = HQMonthlyBill.get_bills(self.domain.name).first() if last_bill: self.assertEqual(self.tropo_bill.total_billed, last_bill.incoming_sms_billed) self.assertEqual(self.unicel_bill.total_billed + self.mach_bill.total_billed, last_bill.outgoing_sms_billed) else: raise Exception("Monthly Bill not successfully generated.")
def rows(self): rows = [] for domain in self.domains: all_bills = HQMonthlyBill.get_bills(domain.name, start=self.datespan.startdate_param_utc, end=self.datespan.enddate_param_utc ).all() for bill in all_bills: nice_start = bill.billing_period_start.strftime("%B %d, %Y") nice_end = bill.billing_period_end.strftime("%B %d, %Y") rows.append([ domain.name, self._format_client(domain), self.table_cell( bill.billing_period_start, nice_start ), self.table_cell( bill.billing_period_end, nice_end ), self._format_bill_amount(bill.incoming_sms_billed), self._format_bill_amount(bill.outgoing_sms_billed), self._format_bill_amount(bill.incoming_sms_billed+bill.outgoing_sms_billed), bill.currency.currency_code, self.table_cell( int(bill.paid), mark_safe(render_to_string("hqbilling/partials/paid_button.html", { 'payment_status': "yes" if bill.paid else "no", 'bill_id': bill.get_id, 'payment_status_text': "Paid" if bill.paid else "Not Paid", 'button_class': "btn-success paid" if bill.paid else "btn-danger", 'billing_start': nice_start, 'billing_end': nice_end, 'domain': domain.name, })) ), mark_safe('<a href="%s" class="btn btn-primary">View Invoice</a>' % reverse("billing_invoice", kwargs=dict(bill_id=bill.get_id))), mark_safe('<a href="%s" class="btn"><i class="icon icon-list"></i> View Itemized</a>' % reverse("billing_itemized", kwargs=dict(bill_id=bill.get_id))) ]) return rows
def handle(self, *args, **options): if len(args) < 2: raise CommandError("year and month are required") if len(args) > 2: domains = [Domain.get_by_name(args[2])] else: domains = SelectSMSBillableDomainsFilter.get_billable_domains() first_day, last_day = month_span(int(args[0]), int(args[1])) print "\nRecalculating SMS in HQ Bills\n----\n" for domain in domains: bills_for_domain = HQMonthlyBill.get_bills(domain.name, start=first_day.isoformat(), end=last_day.isoformat()).all() print "Found %d SMS Bills for domain %s" % (len(bills_for_domain), domain.name) for bill in bills_for_domain: bill._get_sms_activities(INCOMING) bill._get_sms_activities(OUTGOING) bill.save() sys.stdout.flush() print "\n"
def default_datespan(self): start, end = HQMonthlyBill.get_default_start_end() datespan = DateSpan(start, end, format="%Y-%m-%d", timezone=self.timezone) datespan.is_default = True return datespan
def setUp(self): for domain in Domain.get_all(): domain.delete() start_date, _ = HQMonthlyBill.get_default_start_end() sms_date = start_date + datetime.timedelta(days=7) all_billables = SMSBillable.get_all() # all_billables contains duplicates; only delete each doc once for b_id in set(b._id for b in all_billables): SMSBillable.get_db().delete_doc(b_id) self.domain = Domain() self.domain.name = "domain_with_sms" self.domain.is_active = True self.domain.date_created = sms_date self.domain.save() # Incoming billables self.tropo_bill = TropoSMSBillable() self.tropo_bill.billable_date = sms_date self.tropo_bill.billable_amount = 2 self.tropo_bill.conversion_rate = 1 self.tropo_bill.dimagi_surcharge = 0.002 self.tropo_bill.rate_id = "INCOMING_RATE_TROPO" self.tropo_bill.log_id = "INCOMING_LOG_TROPO" self.tropo_bill.domain = self.domain.name self.tropo_bill.direction = INCOMING self.tropo_bill.phone_number = "+15551234567" self.tropo_bill.tropo_id = "TROPO_ID" self.tropo_bill.save() # Outgoing billables self.mach_bill = MachSMSBillable() self.mach_bill.billable_date = sms_date self.mach_bill.contacted_mach_api = sms_date self.mach_bill.mach_delivered_date = sms_date self.mach_bill.billable_amount = 0.01 self.mach_bill.conversion_rate = 1.2 self.mach_bill.dimagi_surcharge = 0.002 self.mach_bill.rate_id = "OUTGOING_MACH_RATE" self.mach_bill.log_id = "OUTGOING_MACH_LOG" self.mach_bill.domain = self.domain.name self.mach_bill.direction = OUTGOING self.mach_bill.phone_number = "+15551234567" self.mach_bill.mach_delivery_status = "delivered" self.mach_bill.mach_id = "MACH_MESSAGE_ID" self.mach_bill.save() self.unicel_bill = UnicelSMSBillable() self.unicel_bill.billable_date = sms_date self.unicel_bill.billable_amount = 2 self.unicel_bill.conversion_rate = 1 self.unicel_bill.dimagi_surcharge = 0.002 self.unicel_bill.rate_id = "OUTGOING_UNICEL_RATE" self.unicel_bill.log_id = "OUTGOING_UNICEL_LOG" self.unicel_bill.domain = self.domain.name self.unicel_bill.direction = OUTGOING self.unicel_bill.phone_number = "+15551234567" self.unicel_bill.unicel_id = "UNICEL_ID" self.unicel_bill.save()