mss-python 0.0.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- mss_python/__init__.py +0 -0
- mss_python/client.py +111 -0
- mss_python/request/method_names.py +28 -0
- mss_python/request/methods.py +23 -0
- mss_python/request/types_mss.py +835 -0
- mss_python-0.0.0.dist-info/LICENSE +21 -0
- mss_python-0.0.0.dist-info/METADATA +99 -0
- mss_python-0.0.0.dist-info/RECORD +10 -0
- mss_python-0.0.0.dist-info/WHEEL +5 -0
- mss_python-0.0.0.dist-info/top_level.txt +1 -0
mss_python/__init__.py
ADDED
|
File without changes
|
mss_python/client.py
ADDED
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import requests
|
|
2
|
+
import xmltodict
|
|
3
|
+
import xml.etree.ElementTree as ET
|
|
4
|
+
|
|
5
|
+
from .request.methods import Method
|
|
6
|
+
from .request.types_mss import Root, BaseType, Credentials, Search, MethodName, Literal
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
# maybe recursion should be used instead of doing if checks?
|
|
10
|
+
def change_structure(root: Root, child: BaseType):
|
|
11
|
+
if child.tag == "root":
|
|
12
|
+
return child
|
|
13
|
+
|
|
14
|
+
if child.tag == "request":
|
|
15
|
+
root.request = child
|
|
16
|
+
|
|
17
|
+
elif child.tag == "search":
|
|
18
|
+
root.request.search = child
|
|
19
|
+
|
|
20
|
+
elif child.tag == "order":
|
|
21
|
+
root.request.order = child
|
|
22
|
+
|
|
23
|
+
elif child.tag == "options":
|
|
24
|
+
root.request.options = child
|
|
25
|
+
|
|
26
|
+
elif child.tag == "logging":
|
|
27
|
+
root.request.logging = child
|
|
28
|
+
|
|
29
|
+
elif child.tag == "header":
|
|
30
|
+
root.header = child
|
|
31
|
+
|
|
32
|
+
return root
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
class Client:
|
|
36
|
+
def __init__(
|
|
37
|
+
self, cred: Credentials, lang: list, elements: list | None = None
|
|
38
|
+
) -> None:
|
|
39
|
+
self.cred = cred
|
|
40
|
+
self.lang = Search(lang)
|
|
41
|
+
|
|
42
|
+
def request(
|
|
43
|
+
self,
|
|
44
|
+
url: str,
|
|
45
|
+
method_name: MethodName,
|
|
46
|
+
data: BaseType | None = None,
|
|
47
|
+
_print: Literal[True, False] = False,
|
|
48
|
+
) -> dict:
|
|
49
|
+
"""
|
|
50
|
+
Makes a post request to the given URL with the specified data and method name.
|
|
51
|
+
|
|
52
|
+
data: ElementTree with the data required in the XML
|
|
53
|
+
url: Service URL
|
|
54
|
+
method: Method to be executed by the service
|
|
55
|
+
"""
|
|
56
|
+
|
|
57
|
+
method = Method(method_name)
|
|
58
|
+
|
|
59
|
+
root = method.get_base_xml(self.cred, self.lang)
|
|
60
|
+
|
|
61
|
+
if data is None:
|
|
62
|
+
root = change_structure(root, data)
|
|
63
|
+
|
|
64
|
+
if _print is True:
|
|
65
|
+
print(ET.tostring(root.request.to_xml(), encoding="unicode"))
|
|
66
|
+
|
|
67
|
+
response = requests.post(
|
|
68
|
+
url,
|
|
69
|
+
data=ET.tostring(root.to_xml(), encoding="unicode"),
|
|
70
|
+
headers={"Content-Type": "application/xml"},
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
responseRoot = xmltodict.parse(response.content)
|
|
74
|
+
error = responseRoot["root"]["header"]["error"]
|
|
75
|
+
if int(error["code"]) > 0:
|
|
76
|
+
raise Exception(
|
|
77
|
+
f'MSS returned an error: code {error["code"]}, message: "{error["message"]}"'
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
return refine_response(responseRoot["root"], method_name)
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def refine_response(resp: dict, meth: MethodName) -> dict:
|
|
84
|
+
if meth == MethodName.GetHotelList:
|
|
85
|
+
return refine_getHotelList(resp)
|
|
86
|
+
|
|
87
|
+
return resp
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
def refine_getHotelList(resp: dict) -> dict:
|
|
91
|
+
if resp["result"] is None:
|
|
92
|
+
return resp
|
|
93
|
+
elif "hotel" not in resp["result"] or resp["result"]["hotel"] is None:
|
|
94
|
+
return resp
|
|
95
|
+
elif resp["result"]["hotel"] is list:
|
|
96
|
+
resp["result"]["hotel"] = [resp["result"]["hotel"]]
|
|
97
|
+
|
|
98
|
+
for hotel in resp["result"]["hotel"]:
|
|
99
|
+
ensure_list_value(hotel, "pictures", "picture")
|
|
100
|
+
ensure_list_value(hotel, "gallery", "picture")
|
|
101
|
+
ensure_list_value(hotel, "feature_view", "feature")
|
|
102
|
+
ensure_list_value(hotel, "pos", "id_pos")
|
|
103
|
+
|
|
104
|
+
return resp
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
def ensure_list_value(hotel: dict, parent_fld: str, child_fld: str) -> None:
|
|
108
|
+
if parent_fld not in hotel:
|
|
109
|
+
hotel[parent_fld] = {child_fld: []}
|
|
110
|
+
elif hotel[parent_fld][child_fld] is list:
|
|
111
|
+
hotel[parent_fld][child_fld] = [hotel[parent_fld][child_fld]]
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
from enum import Enum
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class MethodName(Enum):
|
|
5
|
+
GetHotelList = "getHotelList"
|
|
6
|
+
GetHotelListByFilter = "getHotelListByFilter"
|
|
7
|
+
GetSpecialList = "getSpecialList"
|
|
8
|
+
GetRoomList = "getRoomList"
|
|
9
|
+
GetWidgetConfig = "getWidgetConfig"
|
|
10
|
+
GetPriceList = "getPriceList"
|
|
11
|
+
GetAvailability = "getAvailability"
|
|
12
|
+
GetRoomAvailability = "getRoomAvailability"
|
|
13
|
+
GetDayAvailability = "getDayAvailability"
|
|
14
|
+
PrepareBooking = "prepareBooking"
|
|
15
|
+
GetBooking = "getBooking"
|
|
16
|
+
CancelBooking = "cancelBooking"
|
|
17
|
+
CreateInquiry = "createInquiry"
|
|
18
|
+
GetInquiry = "getInquiry"
|
|
19
|
+
GetUserSources = "getUserSources"
|
|
20
|
+
GetLocationList = "getLocationList"
|
|
21
|
+
GetMasterpackagesList = "getMasterpackagesList"
|
|
22
|
+
NotifyMasterpackages = "notifyMasterpackages"
|
|
23
|
+
GetThemeList = "getThemeList"
|
|
24
|
+
GetLastminuteQuotations = "getLastminuteQuotations"
|
|
25
|
+
GetHotelPictures = "getHotelPictures"
|
|
26
|
+
GetHotelPictureGroups = "getHotelPictureGroups"
|
|
27
|
+
GetOptionalServices = "getOptionalServices"
|
|
28
|
+
ValidateCoupon = "validateCoupon"
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from .method_names import MethodName
|
|
4
|
+
from .types_mss import Credentials, Search, Root, Header, Request
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class Method:
|
|
8
|
+
def __init__(self, name: MethodName):
|
|
9
|
+
self.name = name
|
|
10
|
+
|
|
11
|
+
def get_base_xml(self, cred: Credentials, lang: Search) -> Root:
|
|
12
|
+
"""
|
|
13
|
+
Returns an XML (ElementTree) with the mandatory elements needed for the request.
|
|
14
|
+
|
|
15
|
+
cred: XML Credentials Element (username, password, source)
|
|
16
|
+
|
|
17
|
+
lang: XML Search Element with the language element defined
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
header = Header(cred, self.name)
|
|
21
|
+
req = Request(lang)
|
|
22
|
+
root = Root(header, req)
|
|
23
|
+
return root
|
|
@@ -0,0 +1,835 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
from dataclasses import dataclass, field
|
|
3
|
+
from enum import Enum, IntFlag
|
|
4
|
+
from typing import Literal
|
|
5
|
+
import xml.etree.ElementTree as ET
|
|
6
|
+
from abc import ABC
|
|
7
|
+
|
|
8
|
+
from .method_names import MethodName
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def get_child_xml(value, field, root):
|
|
12
|
+
field = field.replace("___", "-")
|
|
13
|
+
match value:
|
|
14
|
+
case None:
|
|
15
|
+
return
|
|
16
|
+
case int() | float():
|
|
17
|
+
ET.SubElement(root, field).text = str(value)
|
|
18
|
+
case str():
|
|
19
|
+
if field == "tag":
|
|
20
|
+
return
|
|
21
|
+
ET.SubElement(root, field).text = value
|
|
22
|
+
case list():
|
|
23
|
+
for x in value:
|
|
24
|
+
get_child_xml(x, field, root)
|
|
25
|
+
case Enum():
|
|
26
|
+
ET.SubElement(root, field).text = str(value.value)
|
|
27
|
+
case _:
|
|
28
|
+
root.append(value.to_xml())
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class BaseType(ABC):
|
|
32
|
+
def __init__(self, tag):
|
|
33
|
+
self.tag = tag
|
|
34
|
+
|
|
35
|
+
def to_xml(self) -> ET.Element:
|
|
36
|
+
root = ET.Element(self.tag)
|
|
37
|
+
# root.append(self.search.to_xml())
|
|
38
|
+
|
|
39
|
+
for field_, value in vars(self).items():
|
|
40
|
+
get_child_xml(value, field_, root)
|
|
41
|
+
|
|
42
|
+
return root
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
@dataclass()
|
|
46
|
+
class Root(BaseType):
|
|
47
|
+
header: Header
|
|
48
|
+
request: Request
|
|
49
|
+
version: str = "2.0"
|
|
50
|
+
|
|
51
|
+
def __post_init__(self):
|
|
52
|
+
super().__init__("root")
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
@dataclass()
|
|
56
|
+
class Header(BaseType):
|
|
57
|
+
credentials: Credentials
|
|
58
|
+
method: MethodName
|
|
59
|
+
# method: str
|
|
60
|
+
paging: Paging | None = field(default=None)
|
|
61
|
+
|
|
62
|
+
def __post_init__(self):
|
|
63
|
+
super().__init__("header")
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
@dataclass()
|
|
67
|
+
class Credentials(BaseType):
|
|
68
|
+
user: str
|
|
69
|
+
password: str
|
|
70
|
+
source: str
|
|
71
|
+
|
|
72
|
+
def __post_init__(self):
|
|
73
|
+
super().__init__("credentials")
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
@dataclass()
|
|
77
|
+
class Paging:
|
|
78
|
+
start: int
|
|
79
|
+
limit: int
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
@dataclass
|
|
83
|
+
class Request(BaseType):
|
|
84
|
+
search: Search
|
|
85
|
+
options: Options | None = field(default=None)
|
|
86
|
+
|
|
87
|
+
order: Order | None = field(default=None)
|
|
88
|
+
|
|
89
|
+
data: Data | None = field(default=None)
|
|
90
|
+
|
|
91
|
+
logging: Logging | None = field(default=None)
|
|
92
|
+
|
|
93
|
+
def __post_init__(self):
|
|
94
|
+
super().__init__("request")
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
@dataclass
|
|
98
|
+
class Search(BaseType):
|
|
99
|
+
lang: list # Literal["de", "it", "en", "es", "fr", "ru", "da"]
|
|
100
|
+
result_id: str | None = field(default=None)
|
|
101
|
+
|
|
102
|
+
agent: str | None = field(default=None)
|
|
103
|
+
|
|
104
|
+
id: list | None = field(default=None) # number[]
|
|
105
|
+
|
|
106
|
+
search_hotel: SearchHotel | None = field(default=None)
|
|
107
|
+
|
|
108
|
+
search_location: SearchLocation | None = field(default=None)
|
|
109
|
+
|
|
110
|
+
search_distance: SearchDistance | None = field(default=None)
|
|
111
|
+
|
|
112
|
+
search_offer: SearchOffer | None = field(default=None)
|
|
113
|
+
|
|
114
|
+
search_lts: SearchLts | None = field(default=None)
|
|
115
|
+
|
|
116
|
+
search_special: SearchSpecial | None = field(default=None)
|
|
117
|
+
|
|
118
|
+
search_availability: SearchAvailability | None = field(default=None)
|
|
119
|
+
|
|
120
|
+
search_pricelist: SearchPriceList | None = field(default=None)
|
|
121
|
+
|
|
122
|
+
in_: int | None = field(default=None) # number[]
|
|
123
|
+
|
|
124
|
+
id_ofchannel: Literal["hgv", "lts", "esy"] | None = field(default=None)
|
|
125
|
+
|
|
126
|
+
transaction_id: str | None = field(default=None)
|
|
127
|
+
|
|
128
|
+
booking_id: str | None = field(default=None)
|
|
129
|
+
|
|
130
|
+
guest_email: str | None = field(default=None)
|
|
131
|
+
|
|
132
|
+
pic_group_id: int | None = field(default=None)
|
|
133
|
+
|
|
134
|
+
id_apt: int | None = field(default=None)
|
|
135
|
+
|
|
136
|
+
root_id: list | None = field(default=None) # list of ints
|
|
137
|
+
|
|
138
|
+
pic_type: PictureType | None = field(default=None)
|
|
139
|
+
|
|
140
|
+
select___avail: HotelFilters | None = field(default=None)
|
|
141
|
+
select___rooms: HotelFilters | None = field(default=None)
|
|
142
|
+
select___price: HotelFilters | None = field(default=None)
|
|
143
|
+
avail_alert: Literal[0, 1] | None = field(default=None)
|
|
144
|
+
rooms_alert: Literal[0, 1] | None = field(default=None)
|
|
145
|
+
price_alert: Literal[0, 1] | None = field(default=None)
|
|
146
|
+
|
|
147
|
+
coupon_code: str | None = field(default=None)
|
|
148
|
+
total_price: int | None = field(default=None)
|
|
149
|
+
arrival: str | None = field(default=None)
|
|
150
|
+
departure: str | None = field(default=None)
|
|
151
|
+
coupon_type: Literal["promotion", "voucher"] | None = field(default=None)
|
|
152
|
+
|
|
153
|
+
def __post_init__(self):
|
|
154
|
+
super().__init__("search")
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
class HotelFilters(Enum):
|
|
158
|
+
OTA = "ota"
|
|
159
|
+
EASI_CHANNEL = "easiChannel"
|
|
160
|
+
ROTER_HAHN = "10ec953a9d700b9598580a52d3dcef6c"
|
|
161
|
+
HOTEL_PARTNER = "2d9038f6a34c23280669f73ff531683c"
|
|
162
|
+
FIVE_STELLE = "30fb54af1d0d231b01b778647cfd967c"
|
|
163
|
+
ASA_LIGHT = "51c761e7b7b87dbeafe25a9b"
|
|
164
|
+
ASA_HOTEL = "51c761e7b7b87dc3afe15afa"
|
|
165
|
+
ROOM_CLOUD = "65ee9db4c37baedc1032cbd72c8caaaf"
|
|
166
|
+
GS_DATAPROVIDER = "66461e9d7c481e44e632051c3d040a2b"
|
|
167
|
+
HGV_TEST_CLIENT = "95f6a058-45ca-49df-874f-86f41e0bb29f"
|
|
168
|
+
HGV_CLIENT_FOR_TRENTINO = "a47a9dd543e55f8b3ee7ce4cc88b6d57"
|
|
169
|
+
HOTEL_NET_SOLUTIONS = "a57f0615b226609ae409c421ff118a8a"
|
|
170
|
+
BEDDY = "a8513684c7683fd457f82818f5f15bbf"
|
|
171
|
+
PCS_PHOENIX_XENUS = "AE1D2D8776B3FC1C;XENUS"
|
|
172
|
+
AIDA = "AIbD6vqHlYHA17DA"
|
|
173
|
+
AE_SMO = "ba098f2c86b942e58b6e7a89448f4063"
|
|
174
|
+
MTS_ONLINE = "bdcec66dfe4e8ef9f5c7e71e4835204c"
|
|
175
|
+
LTS_BOZEN = "be6bc64c94bbc062bcebfb40b4f93304"
|
|
176
|
+
BOOKING_EXPERT = "BookingE47acfb09170e8"
|
|
177
|
+
CASABLANCA = "CasaifeDZQQDaqvlblanca"
|
|
178
|
+
APARTMENT4HOLIDAY = "ceaeed03a0711eec46582b689d16dc0b"
|
|
179
|
+
CIAOBNB = "CiaoK2VAvAkFlCTcbnb"
|
|
180
|
+
EASI_SUITE = "Easy68e9nMxChannel"
|
|
181
|
+
EASI_SUITE_2 = "Easy68e9nMxChannel2"
|
|
182
|
+
SCIDOO = "f0bdfb926c2a8d066a9d2ea3e632471c"
|
|
183
|
+
ERICSOFT = "fcfb97bb1a8e608e5971928ac2032a68"
|
|
184
|
+
HOTEL_SPIDER = "HoteltihPrvo8kMpbSpider"
|
|
185
|
+
IPER_BOOKING = "iperbooking"
|
|
186
|
+
KROSS_BOOKING = "Kross2XklTsfhbBooking"
|
|
187
|
+
MM_ONE = "MMwRNWBeSQiABuONE"
|
|
188
|
+
PASSEPARTOUT = "passPGkPyHnw3IbApartout"
|
|
189
|
+
SEEKDA = "SEEK8XLyALKEzmpyp2DA"
|
|
190
|
+
SIMPLE_BOOKING = "Simple89sKiOdS9PUcbooking"
|
|
191
|
+
ANEXIS = "SiPaCbW2I921EpMedia"
|
|
192
|
+
SMART_PRICING = "SmartqpukLfH5Kl1price"
|
|
193
|
+
TEST_YANOVIS = "travelsuite"
|
|
194
|
+
VERTICAL_BOOKING = "VertiexDH0x8XV7Booking"
|
|
195
|
+
ALPINE_BITS_CERTIFICATION = "VwnIjABCertification78czDK6"
|
|
196
|
+
WUBOOK = "Wub0Na0CxWovxdVook"
|
|
197
|
+
|
|
198
|
+
|
|
199
|
+
class PictureType(Enum):
|
|
200
|
+
Hotel = "hotel"
|
|
201
|
+
Gallery = "gallery"
|
|
202
|
+
Profile = "profile"
|
|
203
|
+
Roomgroup = "roomgroup"
|
|
204
|
+
Pricelist = "pricelist"
|
|
205
|
+
Special = "special"
|
|
206
|
+
|
|
207
|
+
|
|
208
|
+
@dataclass
|
|
209
|
+
class Options(BaseType):
|
|
210
|
+
hotel_details: HotelDetails | None = field(default=None)
|
|
211
|
+
offer_details: OfferDetails | None = field(default=None)
|
|
212
|
+
|
|
213
|
+
picture_date: str | None = field(default=None) # Date
|
|
214
|
+
lts_bookable: Literal[0, 1, 2] | None = field(default=None) # number, 0|1|2
|
|
215
|
+
|
|
216
|
+
base_price: int | None = field(default=None) # number, 0|1
|
|
217
|
+
|
|
218
|
+
# field is in easychannel but not in nodejs
|
|
219
|
+
only_available: Literal[0, 1] | None = field(default=None) # 0 | 1
|
|
220
|
+
|
|
221
|
+
# below fields are in nodejs but not in easychannel.it?
|
|
222
|
+
room_details: RoomDetails | None = field(default=None)
|
|
223
|
+
special_details: SpecialDetails | None = field(default=None)
|
|
224
|
+
# pricelist_details: PriceListDetails | None = field(default=None)
|
|
225
|
+
|
|
226
|
+
get_availability: Literal[0, 1] | None = field(default=None) # 0 | 1
|
|
227
|
+
get_restrictions: Literal[0, 1] | None = field(default=None) # 0 | 1
|
|
228
|
+
get_roomdetails: int | None = field(default=None) # 0 | 1
|
|
229
|
+
get_masterpackages: Literal[0, 1] | None = field(default=None)
|
|
230
|
+
|
|
231
|
+
location_details: Literal[0, 1] | None = field(default=None)
|
|
232
|
+
theme_details: Literal[0, 1] | None = field(default=None)
|
|
233
|
+
|
|
234
|
+
service_details: ServiceDetails | None = field(default=None)
|
|
235
|
+
|
|
236
|
+
def __post_init__(self):
|
|
237
|
+
super().__init__("options")
|
|
238
|
+
|
|
239
|
+
|
|
240
|
+
class ServiceDetails(IntFlag):
|
|
241
|
+
Headlines = 8
|
|
242
|
+
Pictures = 32
|
|
243
|
+
Descriptions = 256
|
|
244
|
+
|
|
245
|
+
|
|
246
|
+
class HotelDetails(IntFlag):
|
|
247
|
+
BasicInfo = 1
|
|
248
|
+
Themes = 2
|
|
249
|
+
HotelFacilities = 4
|
|
250
|
+
ShortDescription = 8
|
|
251
|
+
FullDescription = 16
|
|
252
|
+
GeographicInformation = 32
|
|
253
|
+
Coordinates = 64
|
|
254
|
+
Address = 128
|
|
255
|
+
Contacts = 256
|
|
256
|
+
PaymentOptionsForOnlineBooking = 512
|
|
257
|
+
PaymentOptionsAtHotel = 1024 #
|
|
258
|
+
Logo = 2048
|
|
259
|
+
HeaderImages = 4096
|
|
260
|
+
Gallery = 8192
|
|
261
|
+
HotelMatching = 16384
|
|
262
|
+
GeographicalInformationAsText = 32768
|
|
263
|
+
HotelReviews = 65536 # different name in GO
|
|
264
|
+
DetailedHotelFacilities = 131072
|
|
265
|
+
SalesPoint = 524288
|
|
266
|
+
LtsSpecificParameters = 262144
|
|
267
|
+
CouponServiceData = 16777216
|
|
268
|
+
CheckInOut = 1048576
|
|
269
|
+
SourceData = 2097152
|
|
270
|
+
AccountData = 67108864
|
|
271
|
+
RoomTypes = 134217728
|
|
272
|
+
# Payment provider missing?
|
|
273
|
+
|
|
274
|
+
|
|
275
|
+
class OfferDetails(IntFlag):
|
|
276
|
+
BasicInfo = 1
|
|
277
|
+
RoomCode = 4
|
|
278
|
+
RoomTitle = 8
|
|
279
|
+
PriceDetails = 16
|
|
280
|
+
RoomImages = 32
|
|
281
|
+
RoomFacilitiesFilter = 64
|
|
282
|
+
RoomDescription = 256
|
|
283
|
+
IncludedServices = 1024
|
|
284
|
+
AdditionalServices = 2048
|
|
285
|
+
RoomFacilitiesDetails = 4096
|
|
286
|
+
PriceImages = 8192
|
|
287
|
+
Themes = 16384
|
|
288
|
+
RoomFeatures = 32768
|
|
289
|
+
CancelPolicies = 262144
|
|
290
|
+
PaymentTerms = 1048576
|
|
291
|
+
|
|
292
|
+
|
|
293
|
+
class RoomDetails(IntFlag):
|
|
294
|
+
BasicInfo = 4
|
|
295
|
+
Title = 8
|
|
296
|
+
RoomImages = 32
|
|
297
|
+
RoomFacilitiesFilter = 64
|
|
298
|
+
RoomDescription = 256
|
|
299
|
+
RoomFacilitiesDetails = 4096
|
|
300
|
+
RoomFeatures = 32768
|
|
301
|
+
RoomNumbers = 65536
|
|
302
|
+
|
|
303
|
+
|
|
304
|
+
class SpecialDetails(IntFlag):
|
|
305
|
+
BasicInfo = 1
|
|
306
|
+
Title = 2
|
|
307
|
+
Descriptions = 4
|
|
308
|
+
Seasons = 8
|
|
309
|
+
Images = 16
|
|
310
|
+
Themes = 32
|
|
311
|
+
IncludedServices = 64
|
|
312
|
+
|
|
313
|
+
|
|
314
|
+
@dataclass
|
|
315
|
+
class Order(BaseType):
|
|
316
|
+
dir: Direction | None = field(default=None)
|
|
317
|
+
field: Field | None = field(default=None)
|
|
318
|
+
|
|
319
|
+
def __post_init__(self):
|
|
320
|
+
super().__init__("order")
|
|
321
|
+
|
|
322
|
+
|
|
323
|
+
class Field(Enum):
|
|
324
|
+
ValidityStart = "valid_start"
|
|
325
|
+
ValidityEnd = "valid_end"
|
|
326
|
+
Random = "rand"
|
|
327
|
+
Stars = "stars"
|
|
328
|
+
Name = "name"
|
|
329
|
+
|
|
330
|
+
|
|
331
|
+
class Direction(Enum):
|
|
332
|
+
Ascending = "asc"
|
|
333
|
+
Descending = "desc"
|
|
334
|
+
|
|
335
|
+
|
|
336
|
+
@dataclass
|
|
337
|
+
class Data(BaseType):
|
|
338
|
+
guest: Guest | None = field(default=None)
|
|
339
|
+
company: Company | None = field(default=None)
|
|
340
|
+
payment: Payment | None = field(default=None)
|
|
341
|
+
note: str | None = field(default=None)
|
|
342
|
+
details: Details | None = field(default=None)
|
|
343
|
+
form: Form | None = field(default=None)
|
|
344
|
+
tracking: Tracking | None = field(default=None)
|
|
345
|
+
# insurance: Ins
|
|
346
|
+
storno_reason: StornoReason | None = field(default=None)
|
|
347
|
+
storno_reason_text: str | None = field(default=None)
|
|
348
|
+
|
|
349
|
+
special: list | None = field(default=None) # list of specials
|
|
350
|
+
|
|
351
|
+
def __post_init__(self):
|
|
352
|
+
super().__init__("data")
|
|
353
|
+
|
|
354
|
+
|
|
355
|
+
@dataclass
|
|
356
|
+
class Special(BaseType):
|
|
357
|
+
offer_id: int
|
|
358
|
+
action: Literal["update", "delete"]
|
|
359
|
+
time_modified: str # ISO 8601 Date
|
|
360
|
+
reset_participants: Literal[0, 1] | None = field(default=None)
|
|
361
|
+
|
|
362
|
+
def __post_init__(self):
|
|
363
|
+
super().__init__("special")
|
|
364
|
+
|
|
365
|
+
|
|
366
|
+
class StornoReason(Enum):
|
|
367
|
+
Unknown = 0
|
|
368
|
+
GuestNotAvailable = 1
|
|
369
|
+
AccomodationRequestedToCancel = 2
|
|
370
|
+
GuestAnotherDestination = 3
|
|
371
|
+
GuestAnotherAccomodation = 4
|
|
372
|
+
Other = 99
|
|
373
|
+
|
|
374
|
+
|
|
375
|
+
@dataclass
|
|
376
|
+
class Logging(BaseType):
|
|
377
|
+
step: str | None = field(default=None)
|
|
378
|
+
|
|
379
|
+
def __post_init__(self):
|
|
380
|
+
super().__init__("logging")
|
|
381
|
+
|
|
382
|
+
|
|
383
|
+
class Step(Enum):
|
|
384
|
+
Search = "search"
|
|
385
|
+
SearchOffer = "search_offer"
|
|
386
|
+
SearchDetails = "search_details"
|
|
387
|
+
View = "view"
|
|
388
|
+
ViewOffer = "view_offer"
|
|
389
|
+
Step1 = "step_1"
|
|
390
|
+
Step2 = "step_2"
|
|
391
|
+
Step3 = "step_3"
|
|
392
|
+
Step4 = "step_4"
|
|
393
|
+
|
|
394
|
+
|
|
395
|
+
@dataclass
|
|
396
|
+
class SearchHotel(BaseType):
|
|
397
|
+
name: str | None = field(default=None)
|
|
398
|
+
type: HotelType | None = field(default=None)
|
|
399
|
+
stars: Stars | None = field(default=None)
|
|
400
|
+
feature: HotelFeature | None = field(default=None)
|
|
401
|
+
theme: HotelTheme | None = field(default=None)
|
|
402
|
+
|
|
403
|
+
def __post_init__(self):
|
|
404
|
+
super().__init__("search_hotel")
|
|
405
|
+
|
|
406
|
+
|
|
407
|
+
class HotelType(Enum):
|
|
408
|
+
Hotel = "1"
|
|
409
|
+
SkiSchool = "2"
|
|
410
|
+
Residence = "4"
|
|
411
|
+
Appartment = "16"
|
|
412
|
+
FarmVacation = "32"
|
|
413
|
+
MountainInn = "64"
|
|
414
|
+
CampingSite = "128"
|
|
415
|
+
HolidayHome = "256"
|
|
416
|
+
YouthHostel = "512"
|
|
417
|
+
Guesthouse = "1024"
|
|
418
|
+
Refuge = "2048"
|
|
419
|
+
Garni = "4096"
|
|
420
|
+
Inn = "8192"
|
|
421
|
+
|
|
422
|
+
|
|
423
|
+
class HotelFeature(Enum):
|
|
424
|
+
Garage = "1"
|
|
425
|
+
Elevator = "2"
|
|
426
|
+
Restaurant = "4"
|
|
427
|
+
Gym = "8"
|
|
428
|
+
Wellness = "16"
|
|
429
|
+
Spa = "32"
|
|
430
|
+
Breakfast = "64"
|
|
431
|
+
Buffet = "128"
|
|
432
|
+
OutdoorPool = "256"
|
|
433
|
+
IndoorPool = "512"
|
|
434
|
+
Bar = "1024"
|
|
435
|
+
BarrierFree = "2048"
|
|
436
|
+
Wlan = "4096"
|
|
437
|
+
ShuttleService = "8192"
|
|
438
|
+
Childcare = "16384"
|
|
439
|
+
SmallPetsAllowed = "32768"
|
|
440
|
+
BeautyFarm = "65536"
|
|
441
|
+
CentralLocation = "262144"
|
|
442
|
+
CoveredParking = "524288"
|
|
443
|
+
OpenParking = "1048576"
|
|
444
|
+
Massages = "2097152"
|
|
445
|
+
Sauna = "4194304"
|
|
446
|
+
SteamBath = "8388608"
|
|
447
|
+
PublicBar = "16777216"
|
|
448
|
+
DogsAllowed = "33554432"
|
|
449
|
+
|
|
450
|
+
|
|
451
|
+
class HotelTheme(Enum):
|
|
452
|
+
Family = "1"
|
|
453
|
+
Wellness = "2"
|
|
454
|
+
Hiking = "4"
|
|
455
|
+
Motorcycle = "8"
|
|
456
|
+
Bike = "16"
|
|
457
|
+
Golf = "32"
|
|
458
|
+
Riding = "64"
|
|
459
|
+
Romantic = "128"
|
|
460
|
+
Ski = "256"
|
|
461
|
+
Meeting = "512"
|
|
462
|
+
CrossCountrySkiing = "1024"
|
|
463
|
+
Culture = "2048"
|
|
464
|
+
Snowshoeing = "4096"
|
|
465
|
+
|
|
466
|
+
|
|
467
|
+
@dataclass
|
|
468
|
+
class SearchLocation(BaseType):
|
|
469
|
+
location: list | None = field(default=None) # number[], Location ID
|
|
470
|
+
location_lts: list | None = field(default=None) # string[], LTS Location RID
|
|
471
|
+
|
|
472
|
+
def __post_init__(self):
|
|
473
|
+
super().__init__("search_location")
|
|
474
|
+
|
|
475
|
+
|
|
476
|
+
@dataclass
|
|
477
|
+
class SearchDistance:
|
|
478
|
+
latitude: float # number
|
|
479
|
+
longitude: float # number
|
|
480
|
+
radius: int # number
|
|
481
|
+
|
|
482
|
+
|
|
483
|
+
@dataclass
|
|
484
|
+
class SearchOffer(BaseType):
|
|
485
|
+
arrival: str | None = field(default=None) # Date YYYY-MM-DD
|
|
486
|
+
departure: str | None = field(default=None) # Date YYYY-MM-DD
|
|
487
|
+
service: Board | None = field(default=None)
|
|
488
|
+
room: list | None = field(default=None) # Room[]
|
|
489
|
+
feature: RoomFeature | None = field(default=None)
|
|
490
|
+
channel_id: list | None = field(default=None) # string[]
|
|
491
|
+
typ: SearchOfferType | None = field(default=None)
|
|
492
|
+
rateplan: Rateplan | None = field(default=None)
|
|
493
|
+
|
|
494
|
+
# features from easychange missing?
|
|
495
|
+
|
|
496
|
+
def __post_init__(self):
|
|
497
|
+
super().__init__("search_offer")
|
|
498
|
+
|
|
499
|
+
|
|
500
|
+
class SearchOfferType(Enum):
|
|
501
|
+
DefaultPricelist = "10"
|
|
502
|
+
PeopleAge = "20"
|
|
503
|
+
PeopleNumber = "21"
|
|
504
|
+
Staying = "22"
|
|
505
|
+
BookingDate = "23"
|
|
506
|
+
Weekday = "24"
|
|
507
|
+
NoReference = "25"
|
|
508
|
+
SpecialPeopleAge = "50"
|
|
509
|
+
SpecialPeopleNumber = "51"
|
|
510
|
+
SpecialStaying = "52"
|
|
511
|
+
SpecialBookingDate = "53"
|
|
512
|
+
SpecialWeekday = "54"
|
|
513
|
+
SpecialNoReference = "55"
|
|
514
|
+
|
|
515
|
+
|
|
516
|
+
class Board(Enum):
|
|
517
|
+
Without = 1
|
|
518
|
+
Breakfast = 2
|
|
519
|
+
HalfBoard = 3
|
|
520
|
+
FullBoard = 4
|
|
521
|
+
AllInclusive = 5
|
|
522
|
+
|
|
523
|
+
|
|
524
|
+
class RoomFeature(IntFlag):
|
|
525
|
+
Balcony = 1
|
|
526
|
+
Terrace = 2
|
|
527
|
+
MiniBar = 4
|
|
528
|
+
Safe = 8
|
|
529
|
+
TV = 16
|
|
530
|
+
Satellite = 32
|
|
531
|
+
Wlan = 64
|
|
532
|
+
Internet = 128
|
|
533
|
+
BarrierFree = 512
|
|
534
|
+
|
|
535
|
+
|
|
536
|
+
@dataclass
|
|
537
|
+
class SearchLts(BaseType):
|
|
538
|
+
A0Ene: int | None = field(default=None) # number
|
|
539
|
+
A0MTV: int | None = field(default=None) # number
|
|
540
|
+
A0Rep: int | None = field(default=None) # number
|
|
541
|
+
|
|
542
|
+
def __post_init__(self):
|
|
543
|
+
super().__init__("search_lts")
|
|
544
|
+
|
|
545
|
+
|
|
546
|
+
@dataclass
|
|
547
|
+
class SearchSpecial(BaseType):
|
|
548
|
+
offer_id: list | None = field(default=None) # number[]
|
|
549
|
+
date_from: str | None = field(default=None) # Date YYYY-MM-DD
|
|
550
|
+
date_to: str | None = field(default=None) # Date YYYY-MM-DD
|
|
551
|
+
theme: list | None = field(default=None) # array of SpecialTheme
|
|
552
|
+
validity: Validity | None = field(default=None)
|
|
553
|
+
typ: SearchSpecialType | None = field(default=None)
|
|
554
|
+
premium: SearchSpecialPremium | None = field(default=None)
|
|
555
|
+
|
|
556
|
+
poi_id: list | None = field(default=None)
|
|
557
|
+
poi_cat: list | None = field(default=None)
|
|
558
|
+
status: Literal[0, 1] | None = field(default=None)
|
|
559
|
+
|
|
560
|
+
def __post_init__(self):
|
|
561
|
+
super().__init__("search_special")
|
|
562
|
+
|
|
563
|
+
|
|
564
|
+
class SearchSpecialType(Enum):
|
|
565
|
+
PriceLists = 0
|
|
566
|
+
Packages = 1
|
|
567
|
+
Specials = 2
|
|
568
|
+
ShortLongStays = 4
|
|
569
|
+
|
|
570
|
+
|
|
571
|
+
class SearchSpecialPremium(IntFlag):
|
|
572
|
+
FamilyHotelsPremium = 2
|
|
573
|
+
VinumHotelsPremium = 4
|
|
574
|
+
SüdtirolBalancePremium = 8
|
|
575
|
+
VitalpinaDurchatmen = 16
|
|
576
|
+
VitalpinaWohlfühlen = 32
|
|
577
|
+
VitalpinaErnährung = 64
|
|
578
|
+
VitalpinaAktiv = 128
|
|
579
|
+
VitalpinaPremium = 256
|
|
580
|
+
BikehotelsMountainbike = 512
|
|
581
|
+
BikehotelsBikeTouringEBike = 1024
|
|
582
|
+
BikehotelsRoadbike = 2048
|
|
583
|
+
BikehotelsPremium = 4096
|
|
584
|
+
ArchitectureDays = 8192
|
|
585
|
+
VinumHotels = 16384
|
|
586
|
+
FamilyHotels = 32768
|
|
587
|
+
FamilyHotelsNatureDetective = 65536
|
|
588
|
+
FamilyHotelsNatureDetectiveWinter = 131072
|
|
589
|
+
|
|
590
|
+
|
|
591
|
+
class SpecialTheme(Enum):
|
|
592
|
+
ThemeIDHiking = 1
|
|
593
|
+
ThemeIDCyclingMountainbike = 2
|
|
594
|
+
ThemeIDFamily = 3
|
|
595
|
+
ThemeIDWellnessHealth = 4
|
|
596
|
+
ThemeIDFoodAndDrink = 5
|
|
597
|
+
ThemeIDGolf = 6
|
|
598
|
+
ThemeIDCulture = 7
|
|
599
|
+
ThemeIDMotorsport = 8
|
|
600
|
+
ThemeIDCarFreeHolidays = 9
|
|
601
|
+
ThemeIDSkiSnowboard = 10
|
|
602
|
+
ThemeIDSummerActivities = 11
|
|
603
|
+
ThemeIDEvents = 12
|
|
604
|
+
ThemeIDChristmasMarkets = 13
|
|
605
|
+
ThemeIDActiveWinter = 14
|
|
606
|
+
ThemeIDVitalpina = 15
|
|
607
|
+
ThemeIDVitalpinaBreathe = 16
|
|
608
|
+
ThemeIDBikeHotelsEBike = 17
|
|
609
|
+
ThemeIDBikeHotelsFreeride = 18
|
|
610
|
+
ThemeIDBikeHotelsMountainbike = 20
|
|
611
|
+
ThemeIDBikeHotelsBikeTours = 21
|
|
612
|
+
ThemeIDBikeHotelsRacingBike = 22
|
|
613
|
+
ThemeIDFamilyHotels = 23
|
|
614
|
+
ThemeIDFamilyHotelsNatureDetective = 24
|
|
615
|
+
ThemeIDFamilyHotel = 26
|
|
616
|
+
ThemeIDNatureDetectivSummer = 27
|
|
617
|
+
ThemeIDNatureDetectivWinter = 28
|
|
618
|
+
ThemeIDEcologicHoliday = 79
|
|
619
|
+
ThemeIDHorseBackRiding = 80
|
|
620
|
+
ThemeIDLuxuryHoliday = 81
|
|
621
|
+
ThemeIDPetsFriendlyHoliday = 82
|
|
622
|
+
ThemeIDRoadBike = 83
|
|
623
|
+
ThemeIDRomanticHoliday = 84
|
|
624
|
+
ThemeIDWine = 85
|
|
625
|
+
ThemeIDBicycleTouring = 86
|
|
626
|
+
ThemeIDEBike = 87
|
|
627
|
+
|
|
628
|
+
## These values were theme_bit
|
|
629
|
+
# Hiking = 1
|
|
630
|
+
# Cycling = 2
|
|
631
|
+
# Family = 4
|
|
632
|
+
# Wellness = 8
|
|
633
|
+
# Food = 16
|
|
634
|
+
# Golf = 32
|
|
635
|
+
# Culture = 64
|
|
636
|
+
# Motorsport = 128
|
|
637
|
+
# CarFree = 256
|
|
638
|
+
# SkiSnowboard = 512
|
|
639
|
+
# SummerActivities = 1024
|
|
640
|
+
# Events = 2048
|
|
641
|
+
# ChristmasMarkets = 4096
|
|
642
|
+
# ActiveWinter = 8192
|
|
643
|
+
# Vitalpina = 16384
|
|
644
|
+
# VitalpinaBreathe = 32768
|
|
645
|
+
# BikeHotelsEBike = 65536
|
|
646
|
+
# BikeHotelsFreeride = 131072
|
|
647
|
+
# BikeHotelsMountainbike = 524288
|
|
648
|
+
# BikeHotelsBikeTours = 1048576
|
|
649
|
+
# BikeHotelsRacingBike = 2097152
|
|
650
|
+
# FamilyHotels = 4194304
|
|
651
|
+
# FamilyHotelsNatureDetective = 8388608
|
|
652
|
+
# FamilyHotel = 33554432
|
|
653
|
+
# FamilyHotelsNatureDetectiveSummer = 67108864
|
|
654
|
+
# FamilyHotelsNatureDetectiveWinter = 134217728
|
|
655
|
+
|
|
656
|
+
|
|
657
|
+
@dataclass
|
|
658
|
+
class SearchAvailability(BaseType):
|
|
659
|
+
date_from: str # Date YYYY-MM-DD
|
|
660
|
+
date_to: str # Date YYYY-MM-DD
|
|
661
|
+
offer_id: list | None = field(default=None) # number[]
|
|
662
|
+
room_id: list | None = field(default=None) # number[]
|
|
663
|
+
duration: int | None = field(default=None)
|
|
664
|
+
room: Room | None = field(default=None)
|
|
665
|
+
|
|
666
|
+
def __post_init__(self):
|
|
667
|
+
super().__init__("search_availability")
|
|
668
|
+
|
|
669
|
+
|
|
670
|
+
@dataclass
|
|
671
|
+
class SearchPriceList(BaseType):
|
|
672
|
+
date_from: str | None = field(default=None) # Date YYYY-MM-DD
|
|
673
|
+
date_to: str | None = field(default=None) # Date YYYY-MM-DD
|
|
674
|
+
service: Board | None = field(default=None)
|
|
675
|
+
room_id: list | None = field(default=None) # number[]
|
|
676
|
+
typ: SearchSpecialType | None = field(default=None)
|
|
677
|
+
|
|
678
|
+
def __post_init__(self):
|
|
679
|
+
super().__init__("search_pricelist")
|
|
680
|
+
|
|
681
|
+
|
|
682
|
+
@dataclass
|
|
683
|
+
class Guest(BaseType):
|
|
684
|
+
firstname: str
|
|
685
|
+
lastname: str
|
|
686
|
+
email: str
|
|
687
|
+
gender: str | None = field(default=None)
|
|
688
|
+
prefix: str | None = field(default=None)
|
|
689
|
+
phone: str | None = field(default=None)
|
|
690
|
+
address: Address | None = field(default=None)
|
|
691
|
+
newsletter: Literal[0, 1] | None = field(default=None) # 0 | 1
|
|
692
|
+
|
|
693
|
+
def __post_init__(self):
|
|
694
|
+
super().__init__("guest")
|
|
695
|
+
|
|
696
|
+
|
|
697
|
+
@dataclass
|
|
698
|
+
class Company(BaseType):
|
|
699
|
+
name: str | None = field(default=None)
|
|
700
|
+
taxnumber: str | None = field(default=None)
|
|
701
|
+
recipient_code: str | None = field(default=None)
|
|
702
|
+
address: Address | None = field(default=None)
|
|
703
|
+
|
|
704
|
+
def __post_init__(self):
|
|
705
|
+
super().__init__("company")
|
|
706
|
+
|
|
707
|
+
|
|
708
|
+
@dataclass
|
|
709
|
+
class Payment(BaseType):
|
|
710
|
+
method: PaymentMethod | None = field(default=None)
|
|
711
|
+
invoice: Literal[0, 1] | None = field(default=None) # 0 | 1
|
|
712
|
+
|
|
713
|
+
def __post_init__(self):
|
|
714
|
+
super().__init__("payment")
|
|
715
|
+
|
|
716
|
+
|
|
717
|
+
class PaymentMethod(IntFlag):
|
|
718
|
+
CreditCardDeposit = 1
|
|
719
|
+
CreditCardAsSecurity = 2
|
|
720
|
+
CreditCardPayment = 8
|
|
721
|
+
BankTransferDeposit = 4
|
|
722
|
+
BankTransferPayment = 16
|
|
723
|
+
AccommodationPayment = 32
|
|
724
|
+
|
|
725
|
+
|
|
726
|
+
@dataclass
|
|
727
|
+
class Details(BaseType):
|
|
728
|
+
extr_price: list | None = field(default=None) # ExtraPrice[]
|
|
729
|
+
|
|
730
|
+
def __post_init__(self):
|
|
731
|
+
super().__init__("Details")
|
|
732
|
+
|
|
733
|
+
|
|
734
|
+
@dataclass
|
|
735
|
+
class ExtraPrice(BaseType):
|
|
736
|
+
price_id: int | None = field(default=None) # number
|
|
737
|
+
price_amount: int | None = field(default=None) # number
|
|
738
|
+
|
|
739
|
+
def __post_init__(self):
|
|
740
|
+
super().__init__("extra_price")
|
|
741
|
+
|
|
742
|
+
|
|
743
|
+
@dataclass
|
|
744
|
+
class Form(BaseType):
|
|
745
|
+
url_success: str | None = field(default=None)
|
|
746
|
+
url_failure: str | None = field(default=None)
|
|
747
|
+
|
|
748
|
+
def __post_init__(self):
|
|
749
|
+
super().__init__("form")
|
|
750
|
+
|
|
751
|
+
|
|
752
|
+
@dataclass
|
|
753
|
+
class Tracking(BaseType):
|
|
754
|
+
partner: str | None = field(default=None)
|
|
755
|
+
media: str | None = field(default=None)
|
|
756
|
+
campaign: str | None = field(default=None)
|
|
757
|
+
companyinfo: str | None = field(default=None)
|
|
758
|
+
|
|
759
|
+
def __post_init__(self):
|
|
760
|
+
super().__init__("tracking")
|
|
761
|
+
|
|
762
|
+
|
|
763
|
+
@dataclass
|
|
764
|
+
class Stars(BaseType):
|
|
765
|
+
min: Literal[1, 2, 3, 3.5, 4, 4.5, 5] | None = field(
|
|
766
|
+
default=None
|
|
767
|
+
) # number, min can be 1, values are 1, 2, 3, 3.5, 4, 4.5, 5
|
|
768
|
+
max: Literal[1, 2, 3, 3.5, 4, 4.5, 5] | None = field(
|
|
769
|
+
default=None
|
|
770
|
+
) # number, max can be 5
|
|
771
|
+
|
|
772
|
+
def __post_init__(self):
|
|
773
|
+
super().__init__("stars")
|
|
774
|
+
|
|
775
|
+
|
|
776
|
+
@dataclass
|
|
777
|
+
class Address(BaseType):
|
|
778
|
+
street: str | None = field(default=None)
|
|
779
|
+
zipcode: str | None = field(default=None)
|
|
780
|
+
city: str | None = field(default=None)
|
|
781
|
+
country: str | None = field(default=None)
|
|
782
|
+
|
|
783
|
+
def __post_init__(self):
|
|
784
|
+
super().__init__("address")
|
|
785
|
+
|
|
786
|
+
|
|
787
|
+
@dataclass
|
|
788
|
+
class Room(BaseType):
|
|
789
|
+
room_seq: int | None = field(default=None) # number
|
|
790
|
+
person: list | None = field(
|
|
791
|
+
default=None
|
|
792
|
+
) # number[], 1..n Persons and their age (store only age inside tags)
|
|
793
|
+
offer_id: int | None = field(default=None) # number
|
|
794
|
+
room_id: int | None = field(default=None) # number
|
|
795
|
+
service: Board | None = field(default=None)
|
|
796
|
+
room_type: RoomType | None = field(default=None)
|
|
797
|
+
|
|
798
|
+
def __post_init__(self):
|
|
799
|
+
super().__init__("room")
|
|
800
|
+
|
|
801
|
+
|
|
802
|
+
class RoomType(Enum):
|
|
803
|
+
All = 0
|
|
804
|
+
Room = 1
|
|
805
|
+
Apartment = 2
|
|
806
|
+
Campsite = 4
|
|
807
|
+
|
|
808
|
+
|
|
809
|
+
@dataclass
|
|
810
|
+
class Rateplan(BaseType):
|
|
811
|
+
code: str # | None = field(default=None)
|
|
812
|
+
source: str # | None = field(default=None)
|
|
813
|
+
|
|
814
|
+
def __post_init__(self):
|
|
815
|
+
super().__init__("rateplan")
|
|
816
|
+
|
|
817
|
+
|
|
818
|
+
@dataclass
|
|
819
|
+
class Validity(BaseType):
|
|
820
|
+
valid: Literal[0, 1] # 0 | 1
|
|
821
|
+
offers: Literal[0, 1] | None = field(default=None) # 0 | 1
|
|
822
|
+
arrival: str | None = field(default=None) # Date YYYY-MM-DD
|
|
823
|
+
departure: str | None = field(default=None) # Date YYYY-MM-DD
|
|
824
|
+
service: Board | None = field(default=None)
|
|
825
|
+
room: list | None = field(default=None) # Room[]
|
|
826
|
+
|
|
827
|
+
def __post_init__(self):
|
|
828
|
+
super().__init__("validity")
|
|
829
|
+
|
|
830
|
+
|
|
831
|
+
def getHotelList_base_xml(root: Root, header: Header):
|
|
832
|
+
xml = '<?xml version="1.0" encoding="utf-8"?>'
|
|
833
|
+
xml += root.version
|
|
834
|
+
xml += header.credentials
|
|
835
|
+
return xml
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 Booking Südtirol
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: mss-python
|
|
3
|
+
Version: 0.0.0
|
|
4
|
+
Summary: MSS API wrapper for Python projects
|
|
5
|
+
Author-email: HGV <development@hgv.it>
|
|
6
|
+
License: MIT License
|
|
7
|
+
|
|
8
|
+
Copyright (c) 2024 Booking Südtirol
|
|
9
|
+
|
|
10
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
11
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
12
|
+
in the Software without restriction, including without limitation the rights
|
|
13
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
14
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
15
|
+
furnished to do so, subject to the following conditions:
|
|
16
|
+
|
|
17
|
+
The above copyright notice and this permission notice shall be included in all
|
|
18
|
+
copies or substantial portions of the Software.
|
|
19
|
+
|
|
20
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
21
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
22
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
23
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
24
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
25
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
26
|
+
SOFTWARE.
|
|
27
|
+
|
|
28
|
+
Project-URL: Repository, https://github.com/bookingsuedtirol/mss-python
|
|
29
|
+
Requires-Python: <4,>=3.7
|
|
30
|
+
Description-Content-Type: text/markdown
|
|
31
|
+
License-File: LICENSE
|
|
32
|
+
|
|
33
|
+
# mss-python
|
|
34
|
+
|
|
35
|
+
MSS API client for Python projects
|
|
36
|
+
|
|
37
|
+
<!-- ## Dependencies
|
|
38
|
+
|
|
39
|
+
This library requires an IANA Time Zone database to be present on the operating system (because it uses https://pkg.go.dev/time#LoadLocation). This database comes pre-installed with many Linux distros. If it’s unavailable (such as on Windows), https://pkg.go.dev/time/tzdata can be imported in the main program (which uses mss-go) instead. -->
|
|
40
|
+
|
|
41
|
+
## Available methods
|
|
42
|
+
|
|
43
|
+
- [x] getHotelList
|
|
44
|
+
- [x] getHotelListByFilter
|
|
45
|
+
- [x] getSpecialList
|
|
46
|
+
- [x] getRoomList
|
|
47
|
+
- [x] getWidgetConfig
|
|
48
|
+
- [x] getBooking
|
|
49
|
+
- [x] cancelBooking
|
|
50
|
+
- [x] prepareBooking
|
|
51
|
+
- [x] getAvailability
|
|
52
|
+
- [x] getRoomAvailability
|
|
53
|
+
- [x] getDayAvailability
|
|
54
|
+
- [x] getPriceList
|
|
55
|
+
- [x] createInquiry
|
|
56
|
+
- [x] getLocationList
|
|
57
|
+
- [x] getThemeList
|
|
58
|
+
- [x] getMasterpackagesList
|
|
59
|
+
- [x] notifyMasterpackages
|
|
60
|
+
- [x] getLastMinuteQuotation
|
|
61
|
+
- [x] validateCoupon
|
|
62
|
+
- [x] getHotelPictures
|
|
63
|
+
- [x] getHotelPictureGroups
|
|
64
|
+
- [x] getOptionalServices
|
|
65
|
+
|
|
66
|
+
## Example Execution
|
|
67
|
+
|
|
68
|
+
`pip install -r requirements.txt`
|
|
69
|
+
|
|
70
|
+
`python3 -m examples.simple.main`
|
|
71
|
+
|
|
72
|
+
<!-- -
|
|
73
|
+
|
|
74
|
+
TODO
|
|
75
|
+
|
|
76
|
+
- [x] getInquiry - how to find booking IDs?
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
- [x] getUserSources
|
|
80
|
+
|
|
81
|
+
-->
|
|
82
|
+
|
|
83
|
+
<!-- Warning: Only the methods with a ✓ next to them have been tested so far.
|
|
84
|
+
|
|
85
|
+
## Before running examples/tests
|
|
86
|
+
|
|
87
|
+
Set the environment variables with:
|
|
88
|
+
|
|
89
|
+
```Bash
|
|
90
|
+
export $(make env)
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
## Examples
|
|
94
|
+
|
|
95
|
+
Run `make simple` or `make advanced`
|
|
96
|
+
|
|
97
|
+
## Tests
|
|
98
|
+
|
|
99
|
+
Run `make test` -->
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
mss_python/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
|
+
mss_python/client.py,sha256=DEMAGATE08MW42Ldtepk95RV6funmyyuFbN9XFhiwPk,3202
|
|
3
|
+
mss_python/request/method_names.py,sha256=DP22Tra-F86FP-6771q7bDwuX6ojPCidFPzztl4UThI,1030
|
|
4
|
+
mss_python/request/methods.py,sha256=pu_U6z8ANktuv0r3P6MmLKW66fwRhiDCp261vNxqrYE,664
|
|
5
|
+
mss_python/request/types_mss.py,sha256=Xq9YYA5-f_j2Gt7bCcHSC6qEzHs0hswpoXm2IGB9SdA,22354
|
|
6
|
+
mss_python-0.0.0.dist-info/LICENSE,sha256=SxLvAIuAvi2G5v6pRCopG3gAH9SLL_-xACJ0QBz_Blw,1074
|
|
7
|
+
mss_python-0.0.0.dist-info/METADATA,sha256=OFmG42saDCkDqNSpQmhaiqb-jqJIZI33sfkYqccFjVE,2939
|
|
8
|
+
mss_python-0.0.0.dist-info/WHEEL,sha256=Mdi9PDNwEZptOjTlUcAth7XJDFtKrHYaQMPulZeBCiQ,91
|
|
9
|
+
mss_python-0.0.0.dist-info/top_level.txt,sha256=-5Wm4NpowVgq9ImH61vhAiBQFoE21fg4r-7Pn7mOYyE,11
|
|
10
|
+
mss_python-0.0.0.dist-info/RECORD,,
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
mss_python
|