def test_post_proforma_with_proforma_entries(self): customer = CustomerFactory.create() provider = ProviderFactory.create() SubscriptionFactory.create() url = reverse('proforma-list') provider_url = build_absolute_test_url(reverse('provider-detail', [provider.pk])) customer_url = build_absolute_test_url(reverse('customer-detail', [customer.pk])) data = { 'provider': provider_url, 'customer': customer_url, 'series': None, 'number': None, 'currency': text_type('RON'), 'transaction_xe_rate': 1, 'proforma_entries': [{ "description": text_type("Page views"), "unit_price": 10.0, "quantity": 20 }] } response = self.client.post(url, data=json.dumps(data), content_type='application/json') assert response.status_code == status.HTTP_201_CREATED
def test_post_invoice_without_invoice_entries(authenticated_api_client, customer, provider): SubscriptionFactory.create() url = reverse('invoice-list') provider_url = build_absolute_test_url( reverse('provider-detail', [provider.pk])) customer_url = build_absolute_test_url( reverse('customer-detail', [customer.pk])) request_data = { 'provider': provider_url, 'customer': customer_url, 'series': None, 'number': None, 'currency': 'RON', 'invoice_entries': [] } response = authenticated_api_client.post(url, data=request_data, format='json') assert response.status_code == status.HTTP_201_CREATED, response.data invoice = Invoice.objects.get(id=response.data['id']) invoice_definition.check_response(invoice, response.data, request_data)
def test_get_subscription_list(self): customer = CustomerFactory.create() SubscriptionFactory.create_batch(settings.API_PAGE_SIZE * 2, customer=customer) url = reverse('subscription-list', kwargs={'customer_pk': customer.pk}) response = self.client.get(url) full_url = None for field in response.data: full_url = field.get('url', None) if full_url: break if full_url: domain = full_url.split('/')[2] full_url = full_url.split(domain)[0] + domain + url assert response.status_code == status.HTTP_200_OK assert response['link'] == \ ('<' + full_url + '?page=2>; rel="next", ' + '<' + full_url + '?page=1>; rel="first", ' + '<' + full_url + '?page=2> rel="last"') response = self.client.get(url + '?page=2') assert response.status_code == status.HTTP_200_OK assert response['link'] == \ ('<' + full_url + '>; rel="prev", ' + '<' + full_url + '?page=1>; rel="first", ' + '<' + full_url + '?page=2> rel="last"') for subscription_data in response.data: subscription = Subscription.objects.get(id=subscription_data['id']) assert subscription_data == spec_subscription(subscription)
def test_post_invoice_with_invoice_entries_without_transaction_xe_rate( transaction_currency, authenticated_api_client ): customer = CustomerFactory.create() provider = ProviderFactory.create() SubscriptionFactory.create() url = reverse('invoice-list') provider_url = build_absolute_test_url(reverse('provider-detail', [provider.pk])) customer_url = build_absolute_test_url(reverse('customer-detail', [customer.pk])) request_data = { 'provider': provider_url, 'customer': customer_url, 'series': None, 'number': None, 'currency': 'RON', 'transaction_currency': transaction_currency, 'invoice_entries': [{ "description": "Page views", "unit_price": 10.0, "quantity": 20}] } response = authenticated_api_client.post(url, data=request_data, format='json') assert response.status_code == status.HTTP_201_CREATED, response.data invoice = Invoice.objects.get(id=response.data['id']) invoice_definition.check_response(invoice, response.data, request_data) assert response.data['invoice_entries'] # content already checked in previous assert
def test_post_proforma_without_proforma_entries(self): customer = CustomerFactory.create() provider = ProviderFactory.create() SubscriptionFactory.create() url = reverse('proforma-list') provider_url = build_absolute_test_url(reverse('provider-detail', [provider.pk])) customer_url = build_absolute_test_url(reverse('customer-detail', [customer.pk])) data = { 'provider': provider_url, 'customer': customer_url, 'currency': text_type('RON'), 'proforma_entries': [] } response = self.client.post(url, data=data) assert response.status_code == status.HTTP_201_CREATED, response.data proforma = get_object_or_None(Proforma, id=response.data["id"]) assert proforma assert response.data == { "id": response.data["id"], "series": "ProformaSeries", "number": None, "provider": provider_url, "customer": customer_url, "archived_provider": '{}', "archived_customer": '{}', "due_date": None, "issue_date": None, "paid_date": None, "cancel_date": None, "sales_tax_name": "VAT", "sales_tax_percent": "1.00", "currency": text_type("RON"), "transaction_currency": proforma.transaction_currency, "transaction_xe_rate": (str(proforma.transaction_xe_rate) if proforma.transaction_xe_rate else None), "transaction_xe_date": proforma.transaction_xe_date, "pdf_url": None, "state": "draft", "invoice": None, "proforma_entries": [], "total": 0, "total_in_transaction_currency": 0, "transactions": [] }
def test_get_subscription_list_reference_filter(self): customer = CustomerFactory.create() subscriptions = SubscriptionFactory.create_batch(3, customer=customer) url = reverse('subscription-list', kwargs={'customer_pk': customer.pk}) references = [subscription.reference for subscription in subscriptions] reference = '?reference=' + references[0] response = self.client.get(url + reference) assert len(response.data) == 1 assert response.status_code == status.HTTP_200_OK reference = '?reference=' + ','.join(references) response = self.client.get(url + reference) assert len(response.data) == 3 assert response.status_code == status.HTTP_200_OK reference = '?reference=' + ','.join(references[:-1]) + ',invalid' response = self.client.get(url + reference) assert len(response.data) == 2 assert response.status_code == status.HTTP_200_OK for subscription_data in response.data: subscription = Subscription.objects.get(id=subscription_data['id']) assert subscription_data == spec_subscription(subscription)
def test_create_subscription_mf_units_log_with_sub_canceled_before(self): subscription = SubscriptionFactory.create( state=Subscription.STATES.CANCELED, start_date=datetime.date(2016, 1, 1), cancel_date=datetime.date(2016, 12, 31)) metered_feature = MeteredFeatureFactory.create() subscription.plan.metered_features.add(metered_feature) url = reverse('mf-log-units', kwargs={ 'subscription_pk': subscription.pk, 'customer_pk': subscription.customer.pk, 'mf_product_code': metered_feature.product_code }) date = str(datetime.date.today()) response = self.client.patch(url, json.dumps({ "count": 150, "date": date, "update_type": "absolute" }), content_type='application/json') assert response.status_code == status.HTTP_400_BAD_REQUEST assert response.data == {"detail": "Date is out of bounds."}
def test_create_subscription_mf_units_log_with_invalid_date(self): subscription = SubscriptionFactory.create() metered_feature = MeteredFeatureFactory.create() subscription.plan.metered_features.add(metered_feature) subscription.activate() subscription.save() url = reverse('mf-log-units', kwargs={ 'subscription_pk': subscription.pk, 'customer_pk': subscription.customer.pk, 'mf_product_code': metered_feature.product_code }) response = self.client.patch(url, json.dumps({ "count": 150, "date": "2008-12-24", "update_type": "absolute" }), content_type='application/json') assert response.status_code == status.HTTP_400_BAD_REQUEST assert response.data == {'detail': 'Date is out of bounds.'}
def test_create_subscription_mf_units_log_with_insufficient_data(self): subscription = SubscriptionFactory.create() metered_feature = MeteredFeatureFactory.create() subscription.plan.metered_features.add(metered_feature) subscription.activate() subscription.save() url = reverse('mf-log-units', kwargs={ 'subscription_pk': subscription.pk, 'customer_pk': subscription.customer.pk, 'mf_product_code': metered_feature.product_code }) data = {"count": 150, "date": "2008-12-24", "update_type": "absolute"} for field in data: data_copy = data.copy() data_copy.pop(field) response = self.client.patch(url, json.dumps(data_copy), content_type='application/json') assert response.status_code == status.HTTP_400_BAD_REQUEST assert response.data == {field: ['This field is required.']}
def test_activate_subscription(self): subscription = SubscriptionFactory.create() url = reverse('sub-activate', kwargs={'subscription_pk': subscription.pk, 'customer_pk': subscription.customer.pk}) response = self.client.post(url, content_type='application/json') assert response.status_code == status.HTTP_200_OK, response.data assert response.data == {'state': 'active'}
def test_get_subscription_detail(self): subscription = SubscriptionFactory.create() url = reverse('subscription-detail', kwargs={'subscription_pk': subscription.pk, 'customer_pk': subscription.customer.pk}) response = self.client.get(url) assert response.status_code == status.HTTP_200_OK, response.data assert response.data == spec_subscription(subscription, detail=True)
def setUp(self): # Setup simple subscription self.plan = PlanFactory.create(interval=Plan.INTERVALS.MONTH, interval_count=1, generate_after=120, enabled=True, amount=Decimal('200.00'), trial_period_days=0) self.subscription = SubscriptionFactory.create(plan=self.plan, start_date=self.date) self.subscription.activate() self.subscription.save()
def test_reactivate_subscription(self): subscription = SubscriptionFactory.create() subscription.activate() subscription.cancel(when=Subscription.CANCEL_OPTIONS.NOW) subscription.save() url = reverse('sub-reactivate', kwargs={'subscription_pk': subscription.pk, 'customer_pk': subscription.customer.pk}) response = self.client.post(url, content_type='application/json') assert response.status_code == status.HTTP_200_OK, response.data assert response.data == {'state': Subscription.STATES.ACTIVE}
def test_end_subscription(self): subscription = SubscriptionFactory.create() subscription.activate() subscription.save() url = reverse('sub-cancel', kwargs={'subscription_pk': subscription.pk, 'customer_pk': subscription.customer.pk}) response = self.client.post(url, json.dumps({ "when": "now"}), content_type='application/json') assert response.status_code == status.HTTP_200_OK, response.data assert response.data == {'state': 'canceled'}
def test_end_subscription_from_terminal_state(self): subscription = SubscriptionFactory.create() url = reverse('sub-cancel', kwargs={'subscription_pk': subscription.pk, 'customer_pk': subscription.customer.pk}) response = self.client.post(url, json.dumps({ "when": "now"}), content_type='application/json') assert response.status_code == status.HTTP_400_BAD_REQUEST assert response.data == { 'error': u'Cannot cancel subscription from inactive state.' }
def test_create_subscription_mf_units_log_with_ended_sub(self): subscription = SubscriptionFactory.create(state=Subscription.STATES.ENDED) metered_feature = MeteredFeatureFactory.create() subscription.plan.metered_features.add(metered_feature) url = reverse('mf-log-units', kwargs={'subscription_pk': subscription.pk, 'customer_pk': subscription.customer.pk, 'mf_product_code': metered_feature.product_code}) response = self.client.patch(url) assert response.status_code == status.HTTP_403_FORBIDDEN assert response.data == {'detail': 'Subscription is ended.'}
def test_create_subscription_mf_units_log_with_unexisting_mf(self): subscription = SubscriptionFactory.create() subscription.activate() subscription.save() url = reverse('mf-log-units', kwargs={'subscription_pk': subscription.pk, 'customer_pk': subscription.customer.pk, 'mf_product_code': '1234'}) response = self.client.patch(url) assert response.status_code == status.HTTP_404_NOT_FOUND assert response.data == {'detail': 'Metered Feature Not found.'}
def test_activate_subscription_from_terminal_state(self): subscription = SubscriptionFactory.create() subscription.activate() subscription.cancel(when=Subscription.CANCEL_OPTIONS.NOW) subscription.save() url = reverse('sub-activate', kwargs={'subscription_pk': subscription.pk, 'customer_pk': subscription.customer.pk}) response = self.client.post(url, content_type='application/json') assert response.status_code == status.HTTP_400_BAD_REQUEST assert response.data == { 'error': u'Cannot activate subscription from canceled state.' }
def test_create_subscription_mf_units_log_sub_canceled_at_end_of_month(self): subscription = SubscriptionFactory.create(state=Subscription.STATES.CANCELED, start_date=datetime.date(2022, 5, 2), cancel_date=datetime.date(2022, 5, 31)) metered_feature = MeteredFeatureFactory.create() subscription.plan.metered_features.add(metered_feature) subscription.activate() subscription.save() url = reverse('mf-log-units', kwargs={'subscription_pk': subscription.pk, 'customer_pk': subscription.customer.pk, 'mf_product_code': metered_feature.product_code}) date = str(datetime.date.today()) response = self.client.patch(url, json.dumps({ "consumed_units": '150.0000', "date": date, "update_type": "absolute" }), content_type='application/json') assert response.status_code == status.HTTP_200_OK, response.data assert response.data == { "consumed_units": '150.0000', 'annotation': None, 'start_datetime': '2022-05-02T00:00:00Z', 'end_datetime': '2022-05-31T23:59:59Z', } # A successive request response = self.client.patch(url, json.dumps({ "consumed_units": 29, "date": date, "update_type": "relative" }), content_type='application/json') assert response.status_code == status.HTTP_200_OK, response.data assert response.data == { "consumed_units": '179.0000', 'annotation': None, 'start_datetime': '2022-05-02T00:00:00Z', 'end_datetime': '2022-05-31T23:59:59Z', }
def test_cancel_subscription(self): subscription = SubscriptionFactory.create() subscription.activate() subscription.save() url = reverse('sub-cancel', kwargs={'subscription_pk': subscription.pk, 'customer_pk': subscription.customer.pk}) response = self.client.post(url, json.dumps({ "when": "end_of_billing_cycle"}), content_type='application/json') assert response.status_code == status.HTTP_200_OK, response.data assert response.data == {'state': Subscription.STATES.CANCELED} subscription = Subscription.objects.get(pk=subscription.pk) assert subscription.state == Subscription.STATES.CANCELED assert subscription.cancel_date == datetime.date(2017, 2, 28)
def test_create_subscription_mf_units_log_sub_canceled_at_end_of_month( self): subscription = SubscriptionFactory.create( state=Subscription.STATES.CANCELED, start_date=datetime.date(2016, 1, 1), cancel_date=datetime.date(2017, 1, 31)) metered_feature = MeteredFeatureFactory.create() subscription.plan.metered_features.add(metered_feature) subscription.activate() subscription.save() url = reverse('mf-log-units', kwargs={ 'subscription_pk': subscription.pk, 'customer_pk': subscription.customer.pk, 'mf_product_code': metered_feature.product_code }) date = str(datetime.date.today()) response = self.client.patch(url, json.dumps({ "count": 150, "date": date, "update_type": "absolute" }), content_type='application/json') assert response.status_code == status.HTTP_200_OK assert response.data == {'count': 150} response = self.client.patch(url, json.dumps({ "count": 29, "date": date, "update_type": "relative" }), content_type='application/json') assert response.status_code == status.HTTP_200_OK assert response.data == {'count': 179}
def test_create_subscription_mf_units_log_with_insufficient_data(self): subscription = SubscriptionFactory.create() metered_feature = MeteredFeatureFactory.create() subscription.plan.metered_features.add(metered_feature) subscription.activate() subscription.save() url = reverse('mf-log-units', kwargs={'subscription_pk': subscription.pk, 'customer_pk': subscription.customer.pk, 'mf_product_code': metered_feature.product_code}) data = {} response = self.client.patch(url, json.dumps(data), content_type='application/json') assert response.status_code == status.HTTP_400_BAD_REQUEST assert response.data == { "consumed_units": ['This field is required.'], 'date': ['This field is required.'], 'update_type': ['This field is required.']}
def test_create_subscription_mf_units_log_with_annotation(self): subscription = SubscriptionFactory.create() metered_feature = MeteredFeatureFactory.create() subscription.plan.metered_features.add(metered_feature) subscription.activate() subscription.save() url = reverse('mf-log-units', kwargs={'subscription_pk': subscription.pk, 'customer_pk': subscription.customer.pk, 'mf_product_code': metered_feature.product_code}) date = str(datetime.date.today()) response = self.client.patch(url, json.dumps({ "consumed_units": '150.0000', "date": date, "update_type": "absolute", "annotation": "test", }), content_type='application/json') assert response.status_code == status.HTTP_200_OK, response.data assert response.data == { "consumed_units": '150.0000', 'annotation': "test", 'start_datetime': '2022-05-02T00:00:00Z', 'end_datetime': '2022-05-31T23:59:59Z', } # A successive relative patch request response = self.client.patch(url, json.dumps({ "consumed_units": 29, "date": date, "update_type": "relative", "annotation": "test", }), content_type='application/json') assert response.status_code == status.HTTP_200_OK, response.data assert response.data == { "consumed_units": '179.0000', 'annotation': "test", 'start_datetime': '2022-05-02T00:00:00Z', 'end_datetime': '2022-05-31T23:59:59Z', } # A third patch request on a different annotation response = self.client.patch(url, json.dumps({ "consumed_units": 42, "date": date, "update_type": "relative", "annotation": "different", }), content_type='application/json') assert response.status_code == status.HTTP_200_OK, response.data assert response.data == { "consumed_units": '42.0000', 'annotation': "different", 'start_datetime': '2022-05-02T00:00:00Z', 'end_datetime': '2022-05-31T23:59:59Z', } # A fourth patch request with no annotation response = self.client.patch(url, json.dumps({ "consumed_units": 99, "date": date, "update_type": "absolute", }), content_type='application/json') assert response.status_code == status.HTTP_200_OK, response.data assert response.data == { "consumed_units": '99.0000', 'annotation': None, 'start_datetime': '2022-05-02T00:00:00Z', 'end_datetime': '2022-05-31T23:59:59Z', } # A fifth GET request for all buckets response = self.client.get(url) assert response.status_code == status.HTTP_200_OK, response.data assert response.data == [ OrderedDict([ ('consumed_units', '99.0000'), ('start_datetime', '2022-05-02T00:00:00Z'), ('end_datetime', '2022-05-31T23:59:59Z'), ('annotation', None) ]), OrderedDict([ ('consumed_units', '42.0000'), ('start_datetime', '2022-05-02T00:00:00Z'), ('end_datetime', '2022-05-31T23:59:59Z'), ('annotation', 'different') ]), OrderedDict([ ('consumed_units', '179.0000'), ('start_datetime', '2022-05-02T00:00:00Z'), ('end_datetime', '2022-05-31T23:59:59Z'), ('annotation', 'test') ]), ]
def test_create_subscription_mf_units_log_with_end_log(self): subscription = SubscriptionFactory.create( start_date=datetime.date(2022, 5, 2), ) metered_feature = MeteredFeatureFactory.create() subscription.plan.metered_features.add(metered_feature) subscription.activate() subscription.save() url = reverse('mf-log-units', kwargs={'subscription_pk': subscription.pk, 'customer_pk': subscription.customer.pk, 'mf_product_code': metered_feature.product_code}) date = str(datetime.date.today()) response = self.client.patch(url, json.dumps({ "consumed_units": '150.0000', "date": date, "update_type": "absolute", }), content_type='application/json') assert response.status_code == status.HTTP_200_OK, response.data assert response.data == { "consumed_units": '150.0000', 'annotation': None, 'start_datetime': '2022-05-02T00:00:00Z', 'end_datetime': '2022-05-31T23:59:59Z', } # A second relative patch request with end bucket response = self.client.patch(url, json.dumps({ "consumed_units": 29, "date": date, "update_type": "relative", "end_log": True, }), content_type='application/json') assert response.status_code == status.HTTP_200_OK, response.data assert response.data == { "consumed_units": '179.0000', 'annotation': None, 'start_datetime': '2022-05-02T00:00:00Z', 'end_datetime': '2022-05-15T00:00:00Z', } # A third patch request matching a new bucket in the same month response = self.client.patch(url, json.dumps({ "consumed_units": 50, "date": str(datetime.date.today() + datetime.timedelta(days=1)), "update_type": "absolute", "end_log": True, }), content_type='application/json') assert response.status_code == status.HTTP_200_OK, response.data assert response.data == { "consumed_units": '50.0000', 'annotation': None, 'start_datetime': '2022-05-15T00:00:01Z', 'end_datetime': '2022-05-31T23:59:59Z', } # A fourth GET request for all buckets response = self.client.get(url) assert response.status_code == status.HTTP_200_OK, response.data assert response.data == [ OrderedDict( [('consumed_units', '179.0000'), ('start_datetime', '2022-05-02T00:00:00Z'), ('end_datetime', '2022-05-15T00:00:00Z'), ('annotation', None)] ), OrderedDict( [('consumed_units', '50.0000'), ('start_datetime', '2022-05-15T00:00:01Z'), ('end_datetime', '2022-05-31T23:59:59Z'), ('annotation', None)] ), ]