Skip to content

Commit eb5cc64

Browse files
authored
Merge pull request #11 from nnnLik/feature/request-promo-code
- Introduced PromoOfferRequestTrackingCode class for handling request tracking promo codes. - Implemented request method with detailed type hints and Google-style docstrings. - Added comprehensive test cases for successful requests, error handling, and validation checks in test_promo_offers.py.
2 parents 1c97d34 + 6dd6569 commit eb5cc64

File tree

2 files changed

+228
-2
lines changed

2 files changed

+228
-2
lines changed

admitad/items/promo_offers.py

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,12 @@
11
from admitad.items.base import Item
22

33

4+
__all__ = [
5+
'PromoOffersForCampaign',
6+
'PromoOfferRequestTrackingCode',
7+
]
8+
9+
410
class PromoOffersForCampaign(Item):
511
"""
612
List of the campaign promo offers
@@ -28,3 +34,76 @@ def get(self, _id: int, **kwargs: dict) -> dict:
2834
.set_pagination(**kwargs)
2935
.request(**request_data)
3036
)
37+
38+
39+
class PromoOfferRequestTrackingCode(Item):
40+
"""
41+
Request tracking promo code for website from specific promo offer
42+
"""
43+
44+
SCOPE = 'request_tracking_coupon'
45+
46+
CREATE_URL = Item.prepare_url('tracking_promo_code/request-tracking-coupon')
47+
GET_STATUS_URL = Item.prepare_url('tracking_promo_code/request-status')
48+
49+
def create(
50+
self,
51+
coupon_id: int,
52+
advcampaign_id: int,
53+
website_id: int,
54+
) -> dict:
55+
"""
56+
Args:
57+
coupon_id (int): ID promo offer (coupon)
58+
advcampaign_id (int): ID advertising campaign
59+
website_id (int): ID website
60+
61+
Returns:
62+
dict: Answer with assigned promo code and tracking link
63+
{
64+
"assigned_promo_code": str | None, # promo code or None if request is created
65+
"tracking_link": str | None, # tracking link or None
66+
"request_id": int | None, # request id or None
67+
}
68+
"""
69+
request_data = {
70+
'coupon_id': Item.sanitize_id(coupon_id),
71+
'advcampaign_id': Item.sanitize_id(advcampaign_id),
72+
'website_id': Item.sanitize_id(website_id),
73+
}
74+
75+
return (
76+
self.transport.post()
77+
.set_data(request_data)
78+
.request(url=self.CREATE_URL)
79+
)
80+
81+
def get(self, request_id: int) -> dict:
82+
"""
83+
Args:
84+
request_id: Admitad promocode request id
85+
86+
Returns:
87+
dict: Status of the promocode request
88+
{
89+
"request_id": int,
90+
"promo_offer_id": int,
91+
"website_id": int,
92+
"status": str,
93+
"approved_at": datetime | None,
94+
"declined_at": datetime | None,
95+
"created_at": datetime,
96+
"assigned_promo_code": str | None,
97+
}
98+
"""
99+
request_id = Item.sanitize_id(request_id)
100+
101+
request_data = {
102+
'request_id': request_id,
103+
}
104+
105+
return (
106+
self.transport.get()
107+
.set_data(request_data)
108+
.request(url=self.GET_STATUS_URL)
109+
)

admitad/tests/test_promo_offers.py

Lines changed: 149 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
import unittest
22
import responses
33

4-
from admitad.items import PromoOffersForCampaign
4+
from admitad.exceptions import HttpException
5+
from admitad.items import PromoOffersForCampaign, PromoOfferRequestTrackingCode
56
from admitad.tests.base import BaseTestCase
67

78

89
class PromoOffersForCampaignTestCase(BaseTestCase):
910

10-
def test_get_promo_offers_for_campaign_request(self):
11+
def test_get_promo_offers_for_campaign_request(self) -> None:
1112
with responses.RequestsMock() as resp:
1213
resp.add(
1314
resp.GET,
@@ -24,5 +25,151 @@ def test_get_promo_offers_for_campaign_request(self):
2425
self.assertIn('status', result)
2526

2627

28+
class PromoOfferRequestTrackingCodeTestCase(BaseTestCase):
29+
30+
def test_request_tracking_promo_code_success(self) -> None:
31+
with responses.RequestsMock() as resp:
32+
resp.add(
33+
resp.POST,
34+
PromoOfferRequestTrackingCode.CREATE_URL,
35+
json={
36+
'assigned_promo_code': 'TESTCODE123',
37+
'tracking_link': 'https://ad.admitad.com/g/123abc/'
38+
},
39+
status=200
40+
)
41+
result = self.client.PromoOfferRequestTrackingCode.create(
42+
coupon_id=100,
43+
advcampaign_id=200,
44+
website_id=300
45+
)
46+
47+
self.assertIn('assigned_promo_code', result)
48+
self.assertIn('tracking_link', result)
49+
self.assertEqual(result['assigned_promo_code'], 'TESTCODE123')
50+
51+
def test_request_tracking_promo_code_creates_request(self) -> None:
52+
with responses.RequestsMock() as resp:
53+
resp.add(
54+
resp.POST,
55+
PromoOfferRequestTrackingCode.CREATE_URL,
56+
json={
57+
'assigned_promo_code': None,
58+
'tracking_link': None,
59+
'request_id': 123,
60+
},
61+
status=200
62+
)
63+
result = self.client.PromoOfferRequestTrackingCode.create(
64+
coupon_id=100,
65+
advcampaign_id=200,
66+
website_id=300
67+
)
68+
69+
self.assertIn('assigned_promo_code', result)
70+
self.assertIn('tracking_link', result)
71+
self.assertIsNone(result['assigned_promo_code'])
72+
self.assertIsNone(result['tracking_link'])
73+
self.assertEqual(result['request_id'], 123)
74+
75+
def test_request_tracking_promo_code_no_coupon_error(self) -> None:
76+
with responses.RequestsMock() as resp:
77+
resp.add(
78+
resp.POST,
79+
PromoOfferRequestTrackingCode.CREATE_URL,
80+
json={
81+
'error_code': 'CHECK_PRE_APPROVED_COUPON_ERROR_CODE_NO_COUPON'
82+
},
83+
status=400
84+
)
85+
with self.assertRaises(HttpException):
86+
self.client.PromoOfferRequestTrackingCode.create(
87+
coupon_id=100,
88+
advcampaign_id=200,
89+
website_id=300
90+
)
91+
92+
def test_request_tracking_promo_code_not_connected_error(self) -> None:
93+
with responses.RequestsMock() as resp:
94+
resp.add(
95+
resp.POST,
96+
PromoOfferRequestTrackingCode.CREATE_URL,
97+
json={
98+
'error_code': 'webmaster_not_connected'
99+
},
100+
status=400
101+
)
102+
with self.assertRaises(HttpException):
103+
self.client.PromoOfferRequestTrackingCode.create(
104+
coupon_id=100,
105+
advcampaign_id=200,
106+
website_id=300
107+
)
108+
109+
def test_request_tracking_promo_code_invalid_coupon_id(self) -> None:
110+
with self.assertRaises(ValueError):
111+
self.client.PromoOfferRequestTrackingCode.create(
112+
coupon_id=0, # Invalid ID
113+
advcampaign_id=200,
114+
website_id=300
115+
)
116+
117+
def test_request_tracking_promo_code_invalid_advcampaign_id(self) -> None:
118+
with self.assertRaises(ValueError):
119+
self.client.PromoOfferRequestTrackingCode.create(
120+
coupon_id=100,
121+
advcampaign_id=0,
122+
website_id=300
123+
)
124+
125+
def test_request_tracking_promo_code_invalid_website_id(self) -> None:
126+
with self.assertRaises(ValueError):
127+
self.client.PromoOfferRequestTrackingCode.create(
128+
coupon_id=100,
129+
advcampaign_id=200,
130+
website_id=0,
131+
)
132+
133+
def test_get_tracking_promo_code_request_status_success(self) -> None:
134+
with responses.RequestsMock() as resp:
135+
resp.add(
136+
resp.GET,
137+
PromoOfferRequestTrackingCode.GET_STATUS_URL,
138+
json={
139+
"request_id": 8,
140+
"promo_offer_id": 100,
141+
"website_id": 300,
142+
"status": "approved",
143+
"approved_at": "2023-01-01T12:00:00Z",
144+
"declined_at": None,
145+
"created_at": "2023-01-01T10:00:00Z",
146+
"assigned_promo_code": "TESTCODE123"
147+
},
148+
status=200
149+
)
150+
result = self.client.PromoOfferRequestTrackingCode.get(request_id=8)
151+
152+
self.assertIn('request_id', result)
153+
self.assertIn('status', result)
154+
self.assertEqual(result['request_id'], 8)
155+
self.assertEqual(result['status'], 'approved')
156+
self.assertEqual(result['assigned_promo_code'], 'TESTCODE123')
157+
158+
def test_get_tracking_promo_code_request_status_not_found(self) -> None:
159+
with responses.RequestsMock() as resp:
160+
resp.add(
161+
resp.GET,
162+
PromoOfferRequestTrackingCode.GET_STATUS_URL,
163+
json={"err_code": "PROMO_REQUEST_NOT_FOUND"},
164+
status=404
165+
)
166+
with self.assertRaises(HttpException):
167+
self.client.PromoOfferRequestTrackingCode.get(request_id=999)
168+
169+
def test_get_tracking_promo_code_request_invalid_id(self) -> None:
170+
with self.assertRaises(ValueError):
171+
self.client.PromoOfferRequestTrackingCode.get(request_id=0)
172+
173+
27174
if __name__ == '__main__':
28175
unittest.main()

0 commit comments

Comments
 (0)