def test_package_creation_increases_price_from_old_package_if_it_is_more_expensive_in_the_end_of_the_month( self): old_component_price = 15 new_component_price = old_component_price - 5 start_date = timezone.datetime(2014, 2, 20, tzinfo=pytz.UTC) package_change_date = timezone.datetime(2014, 2, 28, tzinfo=pytz.UTC) end_of_the_month = core_utils.month_end(package_change_date) with freeze_time(start_date): old_package = fixtures.create_package( component_price=old_component_price) customer = old_package.tenant.service_project_link.project.customer tenant = old_package.tenant with freeze_time(package_change_date): old_package.delete() new_template = fixtures.create_package_template( component_price=new_component_price) new_package = packages_factories.OpenStackPackageFactory( template=new_template, tenant=tenant, ) old_components_price = old_package.template.price * ( (package_change_date - start_date).days + 1) second_component_usage_days = utils.get_full_days( package_change_date, end_of_the_month) - 1 new_components_price = new_package.template.price * second_component_usage_days expected_price = old_components_price + new_components_price # assert self.assertEqual(models.Invoice.objects.count(), 1) self.assertEqual(Decimal(expected_price), models.Invoice.objects.first().price)
def test_package_creation_does_not_increase_price_for_cheaper_1_day_long_old_package_in_the_same_day( self): old_component_price = 10 new_component_price = old_component_price + 5 start_date = timezone.datetime(2014, 2, 26, tzinfo=pytz.UTC) package_change_date = start_date end_of_the_month = core_utils.month_end(package_change_date) with freeze_time(start_date): old_package = fixtures.create_package( component_price=old_component_price) customer = old_package.tenant.service_project_link.project.customer with freeze_time(package_change_date): old_package.delete() new_template = fixtures.create_package_template( component_price=new_component_price) new_package = packages_factories.OpenStackPackageFactory( template=new_template, tenant__service_project_link__project__customer=customer, ) old_components_price = old_package.template.price * ( package_change_date - start_date).days second_component_usage_days = utils.get_full_days( package_change_date, end_of_the_month) new_components_price = new_package.template.price * second_component_usage_days expected_price = old_components_price + new_components_price # assert self.assertEqual(models.Invoice.objects.count(), 1) self.assertEqual(Decimal(expected_price), models.Invoice.objects.first().price)
def register_offering(self, offering, start=None): if start is None: start = timezone.now() end = core_utils.month_end(start) OfferingItem.objects.create( offering=offering, unit_price=offering.unit_price, unit=offering.unit, invoice=self, start=start, end=end, )
def test_existing_invoice_is_updated_on_offering_creation(self): start_date = timezone.datetime(2014, 2, 27, tzinfo=pytz.UTC) end_date = core_utils.month_end(start_date) usage_days = utils.get_full_days(start_date, end_date) with freeze_time(start_date): invoice = factories.InvoiceFactory(customer=self.fixture.customer) offering = self.fixture.offering offering.state = offering.States.OK offering.save() self.assertEqual(models.Invoice.objects.count(), 1) self.assertTrue( invoice.offering_items.filter(offering=offering).exists()) expected_price = offering.unit_price * usage_days self.assertEqual(invoice.price, Decimal(expected_price))
def test_invoice_price_is_not_changed_after_a_while_if_offering_is_deleted( self): start_date = timezone.datetime(2014, 2, 27, tzinfo=pytz.UTC) end_date = core_utils.month_end(start_date) usage_days = utils.get_full_days(start_date, end_date) with freeze_time(start_date): offering = self.fixture.offering offering.state = offering.States.OK offering.save() self.assertEqual(models.Invoice.objects.count(), 1) invoice = models.Invoice.objects.first() with freeze_time(end_date): offering.delete() expected_price = offering.unit_price * usage_days self.assertEqual(invoice.price, Decimal(expected_price))
def test_existing_invoice_is_update_on_offering_creation_if_it_has_package_item_for_same_customer( self): start_date = timezone.datetime(2014, 2, 27, tzinfo=pytz.UTC) end_date = core_utils.month_end(start_date) usage_days = utils.get_full_days(start_date, end_date) with freeze_time(start_date): packages_factories.OpenStackPackageFactory( tenant__service_project_link__project__customer=self.fixture. customer) self.assertEqual(models.Invoice.objects.count(), 1) invoice = models.Invoice.objects.first() components_price = invoice.price offering = self.fixture.offering offering.state = offering.States.OK offering.save() self.assertEqual(models.Invoice.objects.count(), 1) self.assertTrue( invoice.offering_items.filter(offering=offering).exists()) expected_price = offering.unit_price * usage_days + components_price self.assertEqual(invoice.price, Decimal(expected_price))
def get_covered_period(self, invoice_item): first_day = self.get_first_day(invoice_item) last_day = core_utils.month_end(first_day) return '%s-%s' % (self.format_date(first_day), self.format_date(last_day))
def get_last_day_of_month(self, invoice_item): first_day = self.get_first_day(invoice_item) last_day = core_utils.month_end(first_day) return self.format_date(last_day)
def consumed_in_month(self): """ How many resources were (or will be) consumed until end of the month """ month_end = core_utils.month_end( datetime.date(self.price_estimate.year, self.price_estimate.month, 1)) return self._get_consumed(month_end)
def test_new_invoice_is_created_in_new_month_after_half_month_of_usage( self): """ Tests that invoices are created and updated according to the current state of customer's package. Steps: - Test that invoice has been created; - Check price of it in the end of the month; - Ensure that a new invoice has been generated in the new month; - Assert that end date of newly created openstack item set to the date of package deletion. :return: """ self.client.force_authenticate(user=self.fixture.staff) middle_of_the_month = datetime(2017, 1, 15, tzinfo=pytz.UTC) with freeze_time(middle_of_the_month): payload = self.get_package_create_payload() response = self.client.post(self.url, data=payload) self.assertEqual(response.status_code, status.HTTP_201_CREATED, response.data) self.assertEqual(models.Invoice.objects.count(), 1) template = package_models.PackageTemplate.objects.first() price_per_day = template.price end_of_the_month = datetime(2017, 1, 31, 23, 59, 59, tzinfo=pytz.UTC) expected_price = utils.get_full_days(middle_of_the_month, end_of_the_month) * price_per_day with freeze_time(end_of_the_month): invoice = models.Invoice.objects.first() self.assertEqual(invoice.price, expected_price) beginning_of_the_new_month = datetime(2017, 2, 1, tzinfo=pytz.UTC) task_triggering_date = datetime(2017, 2, 2, 23, 59, 59, tzinfo=pytz.UTC) end_of_the_new_month = core_utils.month_end(beginning_of_the_new_month) expected_price = utils.get_full_days( beginning_of_the_new_month, end_of_the_new_month) * price_per_day with freeze_time(task_triggering_date): tasks.create_monthly_invoices() self.assertEqual(models.Invoice.objects.count(), 2) invoice.refresh_from_db() second_invoice = models.Invoice.objects.exclude( pk=invoice.pk).first() self.assertEqual(second_invoice.price, expected_price) self.assertEqual(invoice.state, models.Invoice.States.CREATED) self.assertEqual(invoice.invoice_date, datetime.now().date()) self.assertEqual(second_invoice.state, models.Invoice.States.PENDING) self.assertIsNone(second_invoice.invoice_date) package_deletion_date = datetime(2017, 2, 20, tzinfo=pytz.UTC) expected_price = (package_deletion_date - beginning_of_the_new_month).days * price_per_day with freeze_time(package_deletion_date): package = package_models.OpenStackPackage.objects.first() package.delete() week_after_deletion = datetime(2017, 2, 27, tzinfo=pytz.UTC) with freeze_time(week_after_deletion): second_invoice.refresh_from_db() self.assertEqual(expected_price, second_invoice.price) openstack_item = second_invoice.openstack_items.first() self.assertEqual(openstack_item.end.date(), package_deletion_date.date())
def get_current_month_end(): return core_utils.month_end(timezone.now())
def register(self, sources, invoice, start): """ For each source create invoice item and register it in invoice. """ end = core_utils.month_end(start) for source in sources: self._create_item(source, invoice, start=start, end=end)