def send_bookkeeper_email(month=None, year=None, emails=None): today = datetime.date.today() # now, make sure that we send out LAST month's invoices if we did # not specify a month or year. today = utils.get_previous_month_date_range(today)[0] month = month or today.month year = year or today.year from corehq.apps.accounting.interface import InvoiceInterface request = HttpRequest() params = urlencode(( ('report_filter_statement_period_use_filter', 'on'), ('report_filter_statement_period_month', month), ('report_filter_statement_period_year', year), )) request.GET = QueryDict(params) request.couch_user = FakeUser( domain="hqadmin", username="******", ) invoice = InvoiceInterface(request) invoice.is_rendered_as_email = True first_of_month = datetime.date(year, month, 1) email_context = { 'month': first_of_month.strftime("%B"), } email_content = render_to_string( 'accounting/bookkeeper_email.html', email_context) email_content_plaintext = render_to_string( 'accounting/bookkeeper_email_plaintext.html', email_context) format_dict = Format.FORMAT_DICT[Format.CSV] excel_attachment = { 'title': 'Invoices_%(period)s.%(extension)s' % { 'period': first_of_month.strftime('%B_%Y'), 'extension': format_dict['extension'], }, 'mimetype': format_dict['mimetype'], 'file_obj': invoice.excel_response, } emails = emails or settings.BOOKKEEPER_CONTACT_EMAILS for email in emails: send_HTML_email( "Invoices for %s" % datetime.date(year, month, 1).strftime("%B %Y"), email, email_content, email_from=settings.DEFAULT_FROM_EMAIL, text_content=email_content_plaintext, file_attachments=[excel_attachment], ) logger.info( "[BILLING] Sent Bookkeeper Invoice Summary for %(month)s " "to %(emails)s." % { 'month': first_of_month.strftime("%B %Y"), 'emails': ", ".join(emails) })
def send_bookkeeper_email(month=None, year=None, emails=None): today = datetime.date.today() # now, make sure that we send out LAST month's invoices if we did # not specify a month or year. today = utils.get_previous_month_date_range(today)[0] month = month or today.month year = year or today.year from corehq.apps.accounting.interface import InvoiceInterface request = HttpRequest() params = urlencode(( ('report_filter_statement_period_use_filter', 'on'), ('report_filter_statement_period_month', month), ('report_filter_statement_period_year', year), )) request.GET = QueryDict(params) request.couch_user = FakeUser( domain="hqadmin", username="******", ) invoice = InvoiceInterface(request) invoice.is_rendered_as_email = True first_of_month = datetime.date(year, month, 1) email_context = { 'month': first_of_month.strftime("%B"), } email_content = render_to_string( 'accounting/bookkeeper_email.html', email_context) email_content_plaintext = render_to_string( 'accounting/bookkeeper_email_plaintext.html', email_context) format_dict = Format.FORMAT_DICT[Format.CSV] excel_attachment = { 'title': 'Invoices_%(period)s.%(extension)s' % { 'period': first_of_month.strftime('%B_%Y'), 'extension': format_dict['extension'], }, 'mimetype': format_dict['mimetype'], 'file_obj': invoice.excel_response, } emails = emails or settings.BOOKKEEPER_CONTACT_EMAILS for email in emails: send_HTML_email( "Invoices for %s" % datetime.date(year, month, 1).strftime(USER_MONTH_FORMAT), email, email_content, email_from=settings.DEFAULT_FROM_EMAIL, text_content=email_content_plaintext, file_attachments=[excel_attachment], ) logger.info( "[BILLING] Sent Bookkeeper Invoice Summary for %(month)s " "to %(emails)s." % { 'month': first_of_month.strftime(USER_MONTH_FORMAT), 'emails': ", ".join(emails) })
def get_daterange_start_end_dates(date_range, start_date=None, end_date=None, days=None): today = datetime.date.today() if date_range == 'since': start_date = start_date end_date = today elif date_range == 'range': start_date = start_date end_date = end_date elif date_range == 'lastmonth': start_date, end_date = get_previous_month_date_range() elif date_range == 'lastyear': last_year = today.year - 1 return datetime.date(last_year, 1, 1), datetime.date(last_year, 12, 31) else: end_date = today days = { 'last7': 7, 'last30': 30, 'lastn': days }.get(date_range) if days is None: raise InvalidDaterangeException start_date = today - datetime.timedelta(days=days) if start_date is None or end_date is None: raise InvalidDaterangeException return start_date, end_date
def get_daterange_start_end_dates(date_range, start_date=None, end_date=None, days=None): today = datetime.date.today() if date_range == 'since': start_date = start_date end_date = today elif date_range == 'range': start_date = start_date end_date = end_date elif date_range == 'lastmonth': start_date, end_date = get_previous_month_date_range() elif date_range == 'lastyear': last_year = today.year - 1 return datetime.date(last_year, 1, 1), datetime.date(last_year, 12, 31) else: end_date = today days = {'last7': 7, 'last30': 30, 'lastn': days}.get(date_range) if days is None: raise InvalidDaterangeException start_date = today - datetime.timedelta(days=days) if start_date is None or end_date is None: raise InvalidDaterangeException return start_date, end_date
def generate_invoices(based_on_date=None, check_existing=False, is_test=False): """ Generates all invoices for the past month. """ today = based_on_date or datetime.date.today() invoice_start, invoice_end = utils.get_previous_month_date_range(today) logger.info("[Billing] Starting up invoices for %(start)s - %(end)s" % { 'start': invoice_start.strftime("%d %B %Y"), 'end': invoice_end.strftime("%d %B %Y"), }) all_domain_ids = [d['id'] for d in Domain.get_all(include_docs=False)] for domain_doc in iter_docs(Domain.get_db(), all_domain_ids): domain = Domain.wrap(domain_doc) if (check_existing and Invoice.objects.filter( subscription__subscriber__domain=domain, date_created__gte=today).count() != 0): pass elif is_test: logger.info("[Billing] Ready to create invoice for domain %s" % domain.name) else: try: invoice_factory = DomainInvoiceFactory( invoice_start, invoice_end, domain) invoice_factory.create_invoices() logger.info("[BILLING] Sent invoices for domain %s" % domain.name) except CreditLineError as e: logger.error( "[BILLING] There was an error utilizing credits for " "domain %s: %s" % (domain.name, e) ) except BillingContactInfoError as e: subject = "[%s] Invoice Generation Issue" % domain.name email_content = render_to_string( 'accounting/invoice_error_email.html', { 'project': domain.name, 'error_msg': 'BillingContactInfoError: %s' % e, } ) send_HTML_email( subject, settings.BILLING_EMAIL, email_content, email_from="Dimagi Billing Bot <%s>" % settings.DEFAULT_FROM_EMAIL ) except InvoiceError as e: logger.error( "[BILLING] Could not create invoice for domain %s: %s" % ( domain.name, e )) except Exception as e: logger.error( "[BILLING] Error occurred while creating invoice for " "domain %s: %s" % (domain.name, e) ) # And finally... if not is_test: send_bookkeeper_email()
def generate_invoices(based_on_date=None, check_existing=False, is_test=False): """ Generates all invoices for the past month. """ today = based_on_date or datetime.date.today() invoice_start, invoice_end = utils.get_previous_month_date_range(today) logger.info( "[Billing] Starting up invoices for %(start)s - %(end)s" % { 'start': invoice_start.strftime("%d %B %Y"), 'end': invoice_end.strftime("%d %B %Y"), }) all_domain_ids = [d['id'] for d in Domain.get_all(include_docs=False)] for domain_doc in iter_docs(Domain.get_db(), all_domain_ids): domain = Domain.wrap(domain_doc) if (check_existing and Invoice.objects.filter(subscription__subscriber__domain=domain, date_created__gte=today).count() != 0): pass elif is_test: logger.info("[Billing] Ready to create invoice for domain %s" % domain.name) else: try: invoice_factory = DomainInvoiceFactory(invoice_start, invoice_end, domain) invoice_factory.create_invoices() logger.info("[BILLING] Sent invoices for domain %s" % domain.name) except CreditLineError as e: logger.error( "[BILLING] There was an error utilizing credits for " "domain %s: %s" % (domain.name, e)) except BillingContactInfoError as e: subject = "[%s] Invoice Generation Issue" % domain.name email_content = render_to_string( 'accounting/invoice_error_email.html', { 'project': domain.name, 'error_msg': 'BillingContactInfoError: %s' % e, }) send_HTML_email(subject, settings.BILLING_EMAIL, email_content, email_from="Dimagi Billing Bot <%s>" % settings.DEFAULT_FROM_EMAIL) except InvoiceError as e: logger.error( "[BILLING] Could not create invoice for domain %s: %s" % (domain.name, e)) except Exception as e: logger.error( "[BILLING] Error occurred while creating invoice for " "domain %s: %s" % (domain.name, e)) # And finally... if not is_test: send_bookkeeper_email()
def get_date_range(self): """Duplicated in reports.config.js""" date_range = self.date_range # allow old report email notifications to represent themselves as a # report config by leaving the default date range up to the report # dispatcher if not date_range: return {} import datetime today = datetime.date.today() if date_range == 'since': start_date = self.start_date end_date = today elif date_range == 'range': start_date = self.start_date end_date = self.end_date elif date_range == 'lastmonth': start_date, end_date = get_previous_month_date_range() else: end_date = today if date_range == 'last7': days = 7 elif date_range == 'last30': days = 30 elif date_range == 'lastn': days = self.days else: raise Exception("Invalid date range") start_date = today - datetime.timedelta(days=days) if start_date is None or end_date is None: # this is due to bad validation. see: http://manage.dimagi.com/default.asp?110906 logging.error('scheduled report %s is in a bad state (no startdate or enddate)' % self._id) return {} dates = { 'startdate': start_date.isoformat(), 'enddate': end_date.isoformat(), } if self.is_configurable_report: filter_slug = self.datespan_slug if filter_slug: return { '%s-start' % filter_slug: start_date.isoformat(), '%s-end' % filter_slug: end_date.isoformat(), filter_slug: '%(startdate)s to %(enddate)s' % dates, } return dates
def generate_invoices(based_on_date=None, check_existing=False, is_test=False): """ Generates all invoices for the past month. """ today = based_on_date or datetime.date.today() invoice_start, invoice_end = utils.get_previous_month_date_range(today) logger.info("[Billing] Starting up invoices for %(start)s - %(end)s" % { 'start': invoice_start.strftime(USER_DATE_FORMAT), 'end': invoice_end.strftime(USER_DATE_FORMAT), }) all_domain_ids = [d['id'] for d in Domain.get_all(include_docs=False)] for domain_doc in iter_docs(Domain.get_db(), all_domain_ids): domain = Domain.wrap(domain_doc) if (check_existing and Invoice.objects.filter( subscription__subscriber__domain=domain, date_created__gte=today).count() != 0): pass elif is_test: logger.info("[Billing] Ready to create invoice for domain %s" % domain.name) else: try: invoice_factory = DomainInvoiceFactory( invoice_start, invoice_end, domain) invoice_factory.create_invoices() logger.info("[BILLING] Sent invoices for domain %s" % domain.name) except CreditLineError as e: logger.error( "[BILLING] There was an error utilizing credits for " "domain %s: %s" % (domain.name, e) ) except BillingContactInfoError as e: logger.info("BillingContactInfoError: %s" % e) except InvoiceError as e: logger.error( "[BILLING] Could not create invoice for domain %s: %s" % ( domain.name, e )) except InvoiceAlreadyCreatedError as e: logger.error( "[BILLING] Invoice already existed for domain %s: %s" % ( domain.name, e )) except Exception as e: logger.error( "[BILLING] Error occurred while creating invoice for " "domain %s: %s" % (domain.name, e) )
def setUp(self): super(TestDomainInvoiceFactory, self).setUp() self.invoice_start, self.invoice_end = get_previous_month_date_range() self.domain = generator.arbitrary_domain() self.account = BillingAccount.get_or_create_account_by_domain( domain=self.domain.name, created_by="TEST")[0] self.community = DefaultProductPlan.get_default_plan_by_domain( self.domain).plan.get_version() generator.arbitrary_commcare_users_for_domain( self.domain.name, self.community.user_limit + 1) self.invoice_factory = DomainInvoiceFactory(self.invoice_start, self.invoice_end, self.domain)
def setUp(self): super(TestDomainInvoiceFactory, self).setUp() self.invoice_start, self.invoice_end = get_previous_month_date_range() self.domain = generator.arbitrary_domain() self.account = BillingAccount.get_or_create_account_by_domain( domain=self.domain.name, created_by="TEST" )[0] self.community = DefaultProductPlan.get_default_plan_by_domain( self.domain).plan.get_version() generator.arbitrary_commcare_users_for_domain( self.domain.name, self.community.user_limit + 1 ) self.invoice_factory = DomainInvoiceFactory( self.invoice_start, self.invoice_end, self.domain )
def setUp(self): super(TestBillingRecord, self).setUp() self.billing_contact = generator.arbitrary_web_user() self.dimagi_user = generator.arbitrary_web_user(is_dimagi=True) self.domain = Domain(name='test') self.domain.save() self.invoice_start, self.invoice_end = get_previous_month_date_range() self.currency = generator.init_default_currency() self.account = generator.billing_account(self.dimagi_user, self.billing_contact) self.subscription, self.subscription_length = generator.generate_domain_subscription_from_date( datetime.date.today(), self.account, self.domain.name ) self.invoice = Invoice( subscription=self.subscription, date_start=self.invoice_start, date_end=self.invoice_end, is_hidden=False, ) self.billing_record = BillingRecord(invoice=self.invoice)
def test_use_prev_billing_account_for_community_invoice(self): """ Make sure that if a billing account was already auto generated for a previous community invoice, that a new one is not created. """ domain = generator.arbitrary_domain() generator.create_excess_community_users(domain) second_invoicing_date = datetime.date.today() second_invoice_start, second_invoice_end = utils.get_previous_month_date_range(second_invoicing_date) first_invoicing_date = second_invoice_start - datetime.timedelta(days=random.randint(0, 365)) tasks.generate_invoices(first_invoicing_date) tasks.generate_invoices(second_invoicing_date) subscriber = Subscriber.objects.get(domain=domain.name) invoices = Invoice.objects.filter(subscription__subscriber=subscriber) self.assertEqual(invoices.count(), 2) invoices = invoices.all() self.assertNotEqual(invoices[0].subscription, invoices[1].subscription) self.assertEqual(invoices[0].subscription.account, invoices[1].subscription.account) for invoice in invoices: self.assertEqual(invoice.subscription.subscriber.domain, domain.name) domain.delete()
def generate_invoices(based_on_date=None): """ Generates all invoices for the past month. """ today = based_on_date or datetime.date.today() invoice_start, invoice_end = utils.get_previous_month_date_range(today) invoiceable_subscriptions = Subscription.objects.filter(date_start__lt=invoice_end, date_end__gt=invoice_start).all() def _create_invoice(sub): invoice_factory = SubscriptionInvoiceFactory(invoice_start, invoice_end, sub) invoice_factory.create() invoiced_orgs = [] orgs = Organization.get_db().view('orgs/by_name', group=True, group_level=1).all() org_names = [o['key'] for o in orgs] for org_name in org_names: try: subscription = invoiceable_subscriptions.get(subscriber__organization=org_name) except ObjectDoesNotExist: continue _create_invoice(subscription) invoiced_orgs.append(org_name) all_domain_ids = [d['id'] for d in Domain.get_all(include_docs=False)] for domain_doc in iter_docs(Domain.get_db(), all_domain_ids): domain_name = domain_doc['name'] domain_org = domain_doc['organization'] try: subscription = invoiceable_subscriptions.get(subscriber__domain=domain_name) except ObjectDoesNotExist: if domain_org not in invoiced_orgs: domain = Domain.wrap(domain_doc) invoice_factory = CommunityInvoiceFactory(invoice_start, invoice_end, domain) invoice_factory.create() continue _create_invoice(subscription)