Skip to content

Commit 5b0512b

Browse files
author
Robert Segal
committed
Add e2e tests for billing journals
1 parent 359d60e commit 5b0512b

File tree

9 files changed

+384
-12
lines changed

9 files changed

+384
-12
lines changed

e2e_config.test.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
"accounts.seller.id": "SEL-7310-3075",
1212
"accounts.user.id": "USR-9673-3314",
1313
"accounts.user_group.id": "UGR-6822-0561",
14+
"billing.journal.id": "BJO-6562-0928",
1415
"catalog.authorization.id": "AUT-9288-6146",
1516
"catalog.listing.id": "LST-5489-0806",
1617
"catalog.price_list.id": "PRC-7255-3950-0245",
Lines changed: 57 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,5 @@
11
from mpt_api_client.http import AsyncService, Service
2-
from mpt_api_client.http.mixins import (
3-
AsyncCollectionMixin,
4-
AsyncFilesOperationsMixin,
5-
CollectionMixin,
6-
FilesOperationsMixin,
7-
)
2+
from mpt_api_client.http.types import FileTypes
83
from mpt_api_client.models import Model
94

105

@@ -18,21 +13,73 @@ class JournalUploadServiceConfig:
1813
_endpoint = "/public/v1/billing/journals/{journal_id}/upload"
1914
_model_class = JournalUpload
2015
_collection_key = "data"
16+
_upload_file_key = "file"
17+
_upload_data_key = "id"
2118

2219

2320
class JournalUploadService(
24-
FilesOperationsMixin[JournalUpload],
25-
CollectionMixin[JournalUpload],
2621
Service[JournalUpload],
2722
JournalUploadServiceConfig,
2823
):
2924
"""Journal Upload service."""
3025

26+
def upload(self, resource_data: str, file: FileTypes | None = None) -> Model: # noqa: WPS110
27+
"""Upload journal file.
28+
29+
Args:
30+
resource_data: Resource data.
31+
file: File image.
32+
33+
Returns:
34+
Model: Created resource.
35+
"""
36+
files = {}
37+
38+
if file:
39+
files[self._upload_file_key] = file # UNUSED type: ignore[attr-defined]
40+
files[self._upload_data_key] = resource_data # UNUSED type: ignore
41+
42+
response = self.http_client.request( # UNUSED type: ignore[attr-defined]
43+
"post",
44+
self.path, # UNUSED type: ignore[attr-defined]
45+
files=files,
46+
force_multipart=True,
47+
)
48+
49+
return self._model_class.from_response(
50+
response
51+
) # UNUSED type: ignore[attr-defined, no-any-return]
52+
3153

3254
class AsyncJournalUploadService(
33-
AsyncFilesOperationsMixin[JournalUpload],
34-
AsyncCollectionMixin[JournalUpload],
3555
AsyncService[JournalUpload],
3656
JournalUploadServiceConfig,
3757
):
3858
"""Journal Upload service."""
59+
60+
async def upload(self, resource_data: str, file: FileTypes | None = None) -> Model: # noqa: WPS110
61+
"""Upload journal file.
62+
63+
Args:
64+
resource_data: Resource data.
65+
file: File image.
66+
67+
Returns:
68+
Model: Created resource.
69+
"""
70+
files = {}
71+
72+
if file:
73+
files[self._upload_file_key] = file # UNUSED type: ignore[attr-defined]
74+
files[self._upload_data_key] = resource_data # UNUSED type: ignore
75+
76+
response = await self.http_client.request( # UNUSED type: ignore[attr-defined]
77+
"post",
78+
self.path, # UNUSED type: ignore[attr-defined]
79+
files=files,
80+
force_multipart=True,
81+
)
82+
83+
return self._model_class.from_response(
84+
response
85+
) # UNUSED type: ignore[attr-defined, no-any-return]
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{"externalIds": {"vendor": "ext-seeded-billing-sub-vendor-id", "invoice": "INV12345", "reference": "ORD-7924-7691-0805"}, "search": {"source": {"type": "Subscription", "criteria": "id", "value": "SUB-5839-4140-9574"},"order":{"criteria":"order.id","value":"ORD-7924-7691-0805"}, "item": {"criteria": "item.id", "value": "ITM-1767-7355-0001"}}, "period": {"start": "2025-12-22", "end": "2026-12-21"}, "price": {"unitPP": 10, "PPx1": 8.33}, "quantity": 10, "segment": "COM", "description": {"value1": "desc-1", "value2": "desc-2"}}
9.18 KB
Binary file not shown.

tests/e2e/billing/conftest.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import pathlib
2+
3+
import pytest
4+
5+
6+
@pytest.fixture
7+
def billing_journal_fd():
8+
file_path = pathlib.Path("tests/data/test_billing_journal.xlsx").resolve()
9+
return file_path.open("rb")
10+
11+
12+
@pytest.fixture
13+
def billing_journal_id(e2e_config):
14+
return e2e_config["billing.journal.id"]
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import pytest
2+
3+
4+
@pytest.fixture
5+
def invalid_billing_journal_id():
6+
return "BJO-0000-0000"
7+
8+
9+
@pytest.fixture
10+
def billing_journal_factory(authorization_id):
11+
def factory(
12+
name: str = "E2E Created Billing Journal",
13+
):
14+
return {
15+
"authorization": {"id": authorization_id},
16+
"dueDate": "2026-01-02T19:00:00.000Z",
17+
"externalIds": {},
18+
"name": name,
19+
}
20+
21+
return factory
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
import pytest
2+
3+
from mpt_api_client.exceptions import MPTAPIError
4+
from mpt_api_client.rql.query_builder import RQLQuery
5+
6+
pytestmark = [pytest.mark.flaky]
7+
8+
9+
@pytest.fixture
10+
async def created_billing_journal(async_mpt_vendor, billing_journal_factory):
11+
new_billing_journal_request_data = billing_journal_factory(
12+
name="E2E Created Billing Journal",
13+
)
14+
15+
created_billing_journal = await async_mpt_vendor.billing.journals.create(
16+
new_billing_journal_request_data
17+
)
18+
19+
yield created_billing_journal
20+
21+
try:
22+
await async_mpt_vendor.billing.journals.delete(created_billing_journal.id)
23+
except MPTAPIError as error:
24+
print(f"TEARDOWN - Unable to delete billing journal: {error.title}") # noqa: WPS421
25+
26+
27+
@pytest.fixture
28+
async def submitted_billing_journal(async_mpt_vendor, created_billing_journal, billing_journal_fd):
29+
billing_journal_file_data = created_billing_journal.id
30+
await async_mpt_vendor.billing.journals.submit(created_billing_journal.id)
31+
await async_mpt_vendor.billing.journals.upload(created_billing_journal.id).upload(
32+
resource_data=billing_journal_file_data,
33+
file=billing_journal_fd,
34+
)
35+
36+
return created_billing_journal
37+
38+
39+
@pytest.fixture
40+
async def completed_billing_journal(async_mpt_vendor, submitted_billing_journal):
41+
await async_mpt_vendor.billing.journals.accept(submitted_billing_journal.id)
42+
await async_mpt_vendor.billing.journals.complete(submitted_billing_journal.id)
43+
return submitted_billing_journal
44+
45+
46+
async def test_get_billing_journal_by_id(async_mpt_vendor, billing_journal_id):
47+
result = await async_mpt_vendor.billing.journals.get(billing_journal_id)
48+
49+
assert result is not None
50+
51+
52+
async def test_list_billing_journals(async_mpt_vendor):
53+
limit = 10
54+
55+
result = await async_mpt_vendor.billing.journals.fetch_page(limit=limit)
56+
57+
assert len(result) > 0
58+
59+
60+
async def test_get_billing_journal_by_id_not_found(async_mpt_vendor, invalid_billing_journal_id):
61+
with pytest.raises(MPTAPIError, match=r"404 Not Found"):
62+
await async_mpt_vendor.billing.journals.get(invalid_billing_journal_id)
63+
64+
65+
async def test_filter_billing_journals(async_mpt_vendor, billing_journal_id):
66+
select_fields = ["-value"]
67+
filtered_billing_journals = (
68+
async_mpt_vendor.billing.journals.filter(RQLQuery(id=billing_journal_id))
69+
.filter(RQLQuery(name="E2E Seeded Billing Journal"))
70+
.select(*select_fields)
71+
)
72+
73+
result = [billing_journal async for billing_journal in filtered_billing_journals.iterate()]
74+
75+
assert len(result) == 1
76+
77+
78+
def test_create_billing_journal(created_billing_journal):
79+
result = created_billing_journal
80+
81+
assert result is not None
82+
83+
84+
async def test_update_billing_journal(
85+
async_mpt_vendor, created_billing_journal, billing_journal_factory
86+
):
87+
updated_name = "E2E Updated Billing Journal Name"
88+
updated_billing_journal_data = billing_journal_factory(name=updated_name)
89+
90+
result = await async_mpt_vendor.billing.journals.update(
91+
created_billing_journal.id,
92+
updated_billing_journal_data,
93+
)
94+
95+
assert result.name == updated_name
96+
97+
98+
async def test_delete_billing_journal(async_mpt_vendor, created_billing_journal):
99+
result = created_billing_journal
100+
101+
await async_mpt_vendor.billing.journals.delete(result.id)
102+
103+
104+
async def test_upload_billing_journal(
105+
async_mpt_vendor, created_billing_journal, billing_journal_fd
106+
):
107+
billing_journal_file_data = created_billing_journal.id
108+
109+
result = await async_mpt_vendor.billing.journals.upload(created_billing_journal.id).upload(
110+
resource_data=billing_journal_file_data,
111+
file=billing_journal_fd,
112+
)
113+
114+
assert result is not None
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
import pytest
2+
3+
from mpt_api_client.exceptions import MPTAPIError
4+
from mpt_api_client.rql.query_builder import RQLQuery
5+
6+
pytestmark = [pytest.mark.flaky]
7+
8+
9+
@pytest.fixture
10+
def created_billing_journal(mpt_vendor, billing_journal_factory):
11+
new_billing_journal_request_data = billing_journal_factory(
12+
name="E2E Created Billing Journal",
13+
)
14+
15+
created_billing_journal = mpt_vendor.billing.journals.create(new_billing_journal_request_data)
16+
17+
yield created_billing_journal
18+
19+
try:
20+
mpt_vendor.billing.journals.delete(created_billing_journal.id)
21+
except MPTAPIError as error:
22+
print(f"TEARDOWN - Unable to delete billing journal: {error.title}") # noqa: WPS421
23+
24+
25+
@pytest.fixture
26+
def submitted_billing_journal(mpt_vendor, created_billing_journal, billing_journal_fd):
27+
billing_journal_file_data = created_billing_journal.id
28+
mpt_vendor.billing.journals.submit(created_billing_journal.id)
29+
mpt_vendor.billing.journals.upload(created_billing_journal.id).upload(
30+
resource_data=billing_journal_file_data,
31+
file=billing_journal_fd,
32+
)
33+
34+
return created_billing_journal
35+
36+
37+
@pytest.fixture
38+
def completed_billing_journal(mpt_vendor, submitted_billing_journal):
39+
mpt_vendor.billing.journals.accept(submitted_billing_journal.id)
40+
mpt_vendor.billing.journals.complete(submitted_billing_journal.id)
41+
return submitted_billing_journal
42+
43+
44+
def test_get_billing_journal_by_id(mpt_vendor, billing_journal_id):
45+
result = mpt_vendor.billing.journals.get(billing_journal_id)
46+
47+
assert result is not None
48+
49+
50+
def test_list_billing_journals(mpt_vendor):
51+
limit = 10
52+
53+
result = mpt_vendor.billing.journals.fetch_page(limit=limit)
54+
55+
assert len(result) > 0
56+
57+
58+
def test_get_billing_journal_by_id_not_found(mpt_vendor, invalid_billing_journal_id):
59+
with pytest.raises(MPTAPIError, match=r"404 Not Found"):
60+
mpt_vendor.billing.journals.get(invalid_billing_journal_id)
61+
62+
63+
def test_filter_billing_journals(mpt_vendor, billing_journal_id):
64+
select_fields = ["-value"]
65+
filtered_billing_journals = (
66+
mpt_vendor.billing.journals.filter(RQLQuery(id=billing_journal_id))
67+
.filter(RQLQuery(name="E2E Seeded Billing Journal"))
68+
.select(*select_fields)
69+
)
70+
71+
result = list(filtered_billing_journals.iterate())
72+
73+
assert len(result) == 1
74+
75+
76+
def test_create_billing_journal(created_billing_journal):
77+
result = created_billing_journal
78+
79+
assert result is not None
80+
81+
82+
def test_update_billing_journal(mpt_vendor, created_billing_journal, billing_journal_factory):
83+
updated_name = "E2E Updated Billing Journal Name"
84+
updated_billing_journal_data = billing_journal_factory(name=updated_name)
85+
86+
result = mpt_vendor.billing.journals.update(
87+
created_billing_journal.id,
88+
updated_billing_journal_data,
89+
)
90+
91+
assert result.name == updated_name
92+
93+
94+
def test_delete_billing_journal(mpt_vendor, created_billing_journal):
95+
result = created_billing_journal
96+
97+
mpt_vendor.billing.journals.delete(result.id)
98+
99+
100+
def test_upload_billing_journal(mpt_vendor, created_billing_journal, billing_journal_fd):
101+
billing_journal_file_data = created_billing_journal.id
102+
103+
result = mpt_vendor.billing.journals.upload(created_billing_journal.id).upload(
104+
resource_data=billing_journal_file_data,
105+
file=billing_journal_fd,
106+
)
107+
108+
assert result is not None

0 commit comments

Comments
 (0)