mss-python 0.1.0__tar.gz

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.
@@ -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,81 @@
1
+ Metadata-Version: 2.1
2
+ Name: mss-python
3
+ Version: 0.1.0
4
+ Summary: MSS API wrapper for Python projects
5
+ Home-page: https://github.com/bookingsuedtirol/mss-python
6
+ Requires-Python: >=3.7, <4
7
+ Description-Content-Type: text/markdown
8
+ License-File: LICENSE
9
+
10
+ # mss-python
11
+
12
+ MSS API client for Python projects
13
+
14
+ <!-- ## Dependencies
15
+
16
+ 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. -->
17
+
18
+ ## Available methods
19
+
20
+ - [x] getHotelList
21
+ - [x] getHotelListByFilter
22
+ - [x] getSpecialList
23
+ - [x] getRoomList
24
+ - [x] getWidgetConfig
25
+ - [x] getBooking
26
+ - [x] cancelBooking
27
+ - [x] prepareBooking
28
+ - [x] getAvailability
29
+ - [x] getRoomAvailability
30
+ - [x] getDayAvailability
31
+ - [x] getPriceList
32
+ - [x] createInquiry
33
+ - [x] getLocationList
34
+ - [x] getThemeList
35
+ - [x] getMasterpackagesList
36
+ - [x] notifyMasterpackages
37
+ - [x] getLastMinuteQuotation
38
+ - [x] validateCoupon
39
+ - [x] getHotelPictures
40
+ - [x] getHotelPictureGroups
41
+ - [x] getOptionalServices
42
+
43
+
44
+ ## Example Execution
45
+
46
+ `cd ./examples/simple`
47
+
48
+ `python3 main.py`
49
+
50
+ or
51
+
52
+ `python3 -m main`
53
+
54
+ <!-- -
55
+
56
+ TODO
57
+
58
+ - [x] getInquiry - how to find booking IDs?
59
+
60
+
61
+ - [x] getUserSources
62
+
63
+ -->
64
+
65
+ <!-- Warning: Only the methods with a ✓ next to them have been tested so far.
66
+
67
+ ## Before running examples/tests
68
+
69
+ Set the environment variables with:
70
+
71
+ ```Bash
72
+ export $(make env)
73
+ ```
74
+
75
+ ## Examples
76
+
77
+ Run `make simple` or `make advanced`
78
+
79
+ ## Tests
80
+
81
+ Run `make test` -->
@@ -0,0 +1,72 @@
1
+ # mss-python
2
+
3
+ MSS API client for Python projects
4
+
5
+ <!-- ## Dependencies
6
+
7
+ 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. -->
8
+
9
+ ## Available methods
10
+
11
+ - [x] getHotelList
12
+ - [x] getHotelListByFilter
13
+ - [x] getSpecialList
14
+ - [x] getRoomList
15
+ - [x] getWidgetConfig
16
+ - [x] getBooking
17
+ - [x] cancelBooking
18
+ - [x] prepareBooking
19
+ - [x] getAvailability
20
+ - [x] getRoomAvailability
21
+ - [x] getDayAvailability
22
+ - [x] getPriceList
23
+ - [x] createInquiry
24
+ - [x] getLocationList
25
+ - [x] getThemeList
26
+ - [x] getMasterpackagesList
27
+ - [x] notifyMasterpackages
28
+ - [x] getLastMinuteQuotation
29
+ - [x] validateCoupon
30
+ - [x] getHotelPictures
31
+ - [x] getHotelPictureGroups
32
+ - [x] getOptionalServices
33
+
34
+
35
+ ## Example Execution
36
+
37
+ `cd ./examples/simple`
38
+
39
+ `python3 main.py`
40
+
41
+ or
42
+
43
+ `python3 -m main`
44
+
45
+ <!-- -
46
+
47
+ TODO
48
+
49
+ - [x] getInquiry - how to find booking IDs?
50
+
51
+
52
+ - [x] getUserSources
53
+
54
+ -->
55
+
56
+ <!-- Warning: Only the methods with a ✓ next to them have been tested so far.
57
+
58
+ ## Before running examples/tests
59
+
60
+ Set the environment variables with:
61
+
62
+ ```Bash
63
+ export $(make env)
64
+ ```
65
+
66
+ ## Examples
67
+
68
+ Run `make simple` or `make advanced`
69
+
70
+ ## Tests
71
+
72
+ Run `make test` -->
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,170 @@
1
+ """A setuptools based setup module.
2
+
3
+ See:
4
+ https://packaging.python.org/guides/distributing-packages-using-setuptools/
5
+ https://github.com/pypa/sampleproject
6
+ """
7
+
8
+ # Always prefer setuptools over distutils
9
+ from setuptools import setup, find_packages
10
+ import pathlib
11
+
12
+ here = pathlib.Path(__file__).parent.resolve()
13
+
14
+ # Get the long description from the README file
15
+ long_description = (here / "README.md").read_text(encoding="utf-8")
16
+
17
+ # Arguments marked as "Required" below must be included for upload to PyPI.
18
+ # Fields marked as "Optional" may be commented out.
19
+
20
+ setup(
21
+ # This is the name of your project. The first time you publish this
22
+ # package, this name will be registered for you. It will determine how
23
+ # users can install this project, e.g.:
24
+ #
25
+ # $ pip install sampleproject
26
+ #
27
+ # And where it will live on PyPI: https://pypi.org/project/sampleproject/
28
+ #
29
+ # There are some restrictions on what makes a valid project name
30
+ # specification here:
31
+ # https://packaging.python.org/specifications/core-metadata/#name
32
+ name="mss-python", # Required
33
+ # Versions should comply with PEP 440:
34
+ # https://www.python.org/dev/peps/pep-0440/
35
+ #
36
+ # For a discussion on single-sourcing the version across setup.py and the
37
+ # project code, see
38
+ # https://packaging.python.org/guides/single-sourcing-package-version/
39
+ version="0.1.0", # Required
40
+ # This is a one-line description or tagline of what your project does. This
41
+ # corresponds to the "Summary" metadata field:
42
+ # https://packaging.python.org/specifications/core-metadata/#summary
43
+ description="MSS API wrapper for Python projects", # Optional
44
+ # This is an optional longer description of your project that represents
45
+ # the body of text which users will see when they visit PyPI.
46
+ #
47
+ # Often, this is the same as your README, so you can just read it in from
48
+ # that file directly (as we have already done above)
49
+ #
50
+ # This field corresponds to the "Description" metadata field:
51
+ # https://packaging.python.org/specifications/core-metadata/#description-optional
52
+ long_description=long_description, # Optional
53
+ # Denotes that our long_description is in Markdown; valid values are
54
+ # text/plain, text/x-rst, and text/markdown
55
+ #
56
+ # Optional if long_description is written in reStructuredText (rst) but
57
+ # required for plain-text or Markdown; if unspecified, "applications should
58
+ # attempt to render [the long_description] as text/x-rst; charset=UTF-8 and
59
+ # fall back to text/plain if it is not valid rst" (see link below)
60
+ #
61
+ # This field corresponds to the "Description-Content-Type" metadata field:
62
+ # https://packaging.python.org/specifications/core-metadata/#description-content-type-optional
63
+ long_description_content_type="text/markdown", # Optional (see note above)
64
+ # This should be a valid link to your project's main homepage.
65
+ #
66
+ # This field corresponds to the "Home-Page" metadata field:
67
+ # https://packaging.python.org/specifications/core-metadata/#home-page-optional
68
+ url="https://github.com/bookingsuedtirol/mss-python", # Optional
69
+ # This should be your name or the name of the organization which owns the
70
+ # project.
71
+ # author="Rubin", # Optional
72
+ # This should be a valid email address corresponding to the author listed
73
+ # above.
74
+ # author_email="author@example.com", # Optional
75
+ # Classifiers help users find your project by categorizing it.
76
+ #
77
+ # For a list of valid classifiers, see https://pypi.org/classifiers/
78
+ # classifiers=[ # Optional
79
+ # # How mature is this project? Common values are
80
+ # # 3 - Alpha
81
+ # # 4 - Beta
82
+ # # 5 - Production/Stable
83
+ # "Development Status :: 3 - Alpha",
84
+ # # Indicate who your project is intended for
85
+ # "Intended Audience :: Developers",
86
+ # "Topic :: Software Development :: Build Tools",
87
+ # # Pick your license as you wish
88
+ # "License :: OSI Approved :: MIT License",
89
+ # # Specify the Python versions you support here. In particular, ensure
90
+ # # that you indicate you support Python 3. These classifiers are *not*
91
+ # # checked by 'pip install'. See instead 'python_requires' below.
92
+ # "Programming Language :: Python :: 3",
93
+ # "Programming Language :: Python :: 3.7",
94
+ # "Programming Language :: Python :: 3.8",
95
+ # "Programming Language :: Python :: 3.9",
96
+ # "Programming Language :: Python :: 3.10",
97
+ # "Programming Language :: Python :: 3 :: Only",
98
+ # ],
99
+ # This field adds keywords for your project which will appear on the
100
+ # project page. What does your project relate to?
101
+ #
102
+ # Note that this is a list of additional keywords, separated
103
+ # by commas, to be used to assist searching for the distribution in a
104
+ # larger catalog.
105
+ # keywords="sample, setuptools, development", # Optional
106
+ # When your source code is in a subdirectory under the project root, e.g.
107
+ # `src/`, it is necessary to specify the `package_dir` argument.
108
+ package_dir={"": "src"}, # Optional
109
+ # You can just specify package directories manually here if your project is
110
+ # simple. Or you can use find_packages().
111
+ #
112
+ # Alternatively, if you just want to distribute a single Python file, use
113
+ # the `py_modules` argument instead as follows, which will expect a file
114
+ # called `my_module.py` to exist:
115
+ #
116
+ # py_modules=["my_module"],
117
+ #
118
+ packages=find_packages(where="src"), # Required
119
+ # Specify which Python versions you support. In contrast to the
120
+ # 'Programming Language' classifiers above, 'pip install' will check this
121
+ # and refuse to install the project if the version does not match. See
122
+ # https://packaging.python.org/guides/distributing-packages-using-setuptools/#python-requires
123
+ python_requires=">=3.7, <4",
124
+ # This field lists other packages that your project depends on to run.
125
+ # Any package you put here will be installed by pip when your project is
126
+ # installed, so they must be valid existing projects.
127
+ #
128
+ # For an analysis of "install_requires" vs pip's requirements files see:
129
+ # https://packaging.python.org/discussions/install-requires-vs-requirements/
130
+ # install_requires=["peppercorn"], # Optional
131
+ # List additional groups of dependencies here (e.g. development
132
+ # dependencies). Users will be able to install these using the "extras"
133
+ # syntax, for example:
134
+ #
135
+ # $ pip install sampleproject[dev]
136
+ #
137
+ # Similar to `install_requires` above, these must be valid existing
138
+ # projects.
139
+ # extras_require={ # Optional
140
+ # "dev": ["check-manifest"],
141
+ # "test": ["coverage"],
142
+ # },
143
+ # If there are data files included in your packages that need to be
144
+ # installed, specify them here.
145
+ # package_data={ # Optional
146
+ # "sample": ["package_data.dat"],
147
+ # },
148
+ # Entry points. The following would provide a command called `sample` which
149
+ # executes the function `main` from this package when invoked:
150
+ # entry_points={ # Optional
151
+ # "console_scripts": [
152
+ # "sample=sample:main",
153
+ # ],
154
+ # },
155
+ # List additional URLs that are relevant to your project as a dict.
156
+ #
157
+ # This field corresponds to the "Project-URL" metadata fields:
158
+ # https://packaging.python.org/specifications/core-metadata/#project-url-multiple-use
159
+ #
160
+ # Examples listed include a pattern for specifying where the package tracks
161
+ # issues, where the source is hosted, where to say thanks to the package
162
+ # maintainers, and where to support the project financially. The key is
163
+ # what's used to render the link text on PyPI.
164
+ # project_urls={ # Optional
165
+ # "Bug Reports": "https://github.com/pypa/sampleproject/issues",
166
+ # "Funding": "https://donate.pypi.org",
167
+ # "Say Thanks!": "http://saythanks.io/to/example",
168
+ # "Source": "https://github.com/pypa/sampleproject/",
169
+ # },
170
+ )
@@ -0,0 +1,81 @@
1
+ Metadata-Version: 2.1
2
+ Name: mss-python
3
+ Version: 0.1.0
4
+ Summary: MSS API wrapper for Python projects
5
+ Home-page: https://github.com/bookingsuedtirol/mss-python
6
+ Requires-Python: >=3.7, <4
7
+ Description-Content-Type: text/markdown
8
+ License-File: LICENSE
9
+
10
+ # mss-python
11
+
12
+ MSS API client for Python projects
13
+
14
+ <!-- ## Dependencies
15
+
16
+ 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. -->
17
+
18
+ ## Available methods
19
+
20
+ - [x] getHotelList
21
+ - [x] getHotelListByFilter
22
+ - [x] getSpecialList
23
+ - [x] getRoomList
24
+ - [x] getWidgetConfig
25
+ - [x] getBooking
26
+ - [x] cancelBooking
27
+ - [x] prepareBooking
28
+ - [x] getAvailability
29
+ - [x] getRoomAvailability
30
+ - [x] getDayAvailability
31
+ - [x] getPriceList
32
+ - [x] createInquiry
33
+ - [x] getLocationList
34
+ - [x] getThemeList
35
+ - [x] getMasterpackagesList
36
+ - [x] notifyMasterpackages
37
+ - [x] getLastMinuteQuotation
38
+ - [x] validateCoupon
39
+ - [x] getHotelPictures
40
+ - [x] getHotelPictureGroups
41
+ - [x] getOptionalServices
42
+
43
+
44
+ ## Example Execution
45
+
46
+ `cd ./examples/simple`
47
+
48
+ `python3 main.py`
49
+
50
+ or
51
+
52
+ `python3 -m main`
53
+
54
+ <!-- -
55
+
56
+ TODO
57
+
58
+ - [x] getInquiry - how to find booking IDs?
59
+
60
+
61
+ - [x] getUserSources
62
+
63
+ -->
64
+
65
+ <!-- Warning: Only the methods with a ✓ next to them have been tested so far.
66
+
67
+ ## Before running examples/tests
68
+
69
+ Set the environment variables with:
70
+
71
+ ```Bash
72
+ export $(make env)
73
+ ```
74
+
75
+ ## Examples
76
+
77
+ Run `make simple` or `make advanced`
78
+
79
+ ## Tests
80
+
81
+ Run `make test` -->
@@ -0,0 +1,10 @@
1
+ LICENSE
2
+ README.md
3
+ setup.py
4
+ src/mss_python.egg-info/PKG-INFO
5
+ src/mss_python.egg-info/SOURCES.txt
6
+ src/mss_python.egg-info/dependency_links.txt
7
+ src/mss_python.egg-info/top_level.txt
8
+ src/request/__init__.py
9
+ src/request/methods.py
10
+ src/request/types_mss.py
@@ -0,0 +1 @@
1
+ request
File without changes
@@ -0,0 +1,49 @@
1
+ from __future__ import annotations
2
+ import xml.etree.ElementTree as ET
3
+ from request.types_mss import * # might need change
4
+
5
+
6
+ class MethodName(Enum):
7
+ GetHotelList = "getHotelList"
8
+ GetHotelListByFilter = "getHotelListByFilter"
9
+ GetSpecialList = "getSpecialList"
10
+ GetRoomList = "getRoomList"
11
+ GetWidgetConfig = "getWidgetConfig"
12
+ GetPriceList = "getPriceList"
13
+ GetAvailability = "getAvailability"
14
+ GetRoomAvailability = "getRoomAvailability"
15
+ GetDayAvailability = "getDayAvailability"
16
+ PrepareBooking = "prepareBooking"
17
+ GetBooking = "getBooking"
18
+ CancelBooking = "cancelBooking"
19
+ CreateInquiry = "createInquiry"
20
+ GetInquiry = "getInquiry"
21
+ GetUserSources = "getUserSources"
22
+ GetLocationList = "getLocationList"
23
+ GetMasterpackagesList = "getMasterpackagesList"
24
+ NotifyMasterpackages = "notifyMasterpackages"
25
+ GetThemeList = "getThemeList"
26
+ GetLastminuteQuotations = "getLastminuteQuotations"
27
+ GetHotelPictures = "getHotelPictures"
28
+ GetHotelPictureGroups = "getHotelPictureGroups"
29
+ GetOptionalServices = "getOptionalServices"
30
+ ValidateCoupon = "validateCoupon"
31
+
32
+
33
+ class Method:
34
+ def __init__(self, name: MethodName):
35
+ self.name = name
36
+
37
+ def get_base_xml(self, cred: Credentials, lang: Search) -> Root:
38
+ """
39
+ Returns an XML (ElementTree) with the mandatory elements needed for the request.
40
+
41
+ cred: XML Credentials Element (username, password, source)
42
+
43
+ lang: XML Search Element with the language element defined
44
+ """
45
+
46
+ header = Header(cred, self.name)
47
+ req = Request(lang)
48
+ root = Root(header, req)
49
+ return root
@@ -0,0 +1,834 @@
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
+ from methods import MethodName
8
+
9
+
10
+ def get_child_xml(value, field, root):
11
+ field = field.replace("___", "-")
12
+ match value:
13
+ case None:
14
+ return
15
+ case int() | float():
16
+ ET.SubElement(root, field).text = str(value)
17
+ case str():
18
+ if field == "tag":
19
+ return
20
+ ET.SubElement(root, field).text = value
21
+ case list():
22
+ for x in value:
23
+ get_child_xml(x, field, root)
24
+ case Enum():
25
+ ET.SubElement(root, field).text = str(value.value)
26
+ case _:
27
+ root.append(value.to_xml())
28
+
29
+
30
+ class BaseType(ABC):
31
+ def __init__(self, tag):
32
+ self.tag = tag
33
+
34
+ def to_xml(self) -> ET.Element:
35
+ root = ET.Element(self.tag)
36
+ # root.append(self.search.to_xml())
37
+
38
+ for field, value in vars(self).items():
39
+ get_child_xml(value, field, root)
40
+
41
+ return root
42
+
43
+
44
+ @dataclass()
45
+ class Root(BaseType):
46
+ header: Header
47
+ request: Request
48
+ version: str = "2.0"
49
+
50
+ def __post_init__(self):
51
+ super().__init__("root")
52
+
53
+
54
+ @dataclass()
55
+ class Header(BaseType):
56
+ credentials: Credentials
57
+ method: MethodName
58
+ # method: str
59
+ paging: Paging | None = field(default=None)
60
+
61
+ def __post_init__(self):
62
+ super().__init__("header")
63
+
64
+
65
+ @dataclass()
66
+ class Credentials(BaseType):
67
+ user: str
68
+ password: str
69
+ source: str
70
+
71
+ def __post_init__(self):
72
+ super().__init__("credentials")
73
+
74
+
75
+ @dataclass()
76
+ class Paging:
77
+ start: int
78
+ limit: int
79
+
80
+
81
+ @dataclass
82
+ class Request(BaseType):
83
+ search: Search
84
+ options: Options | None = field(default=None)
85
+
86
+ order: Order | None = field(default=None)
87
+
88
+ data: Data | None = field(default=None)
89
+
90
+ logging: Logging | None = field(default=None)
91
+
92
+ def __post_init__(self):
93
+ super().__init__("request")
94
+
95
+
96
+ @dataclass
97
+ class Search(BaseType):
98
+ lang: list # Literal["de", "it", "en", "es", "fr", "ru", "da"]
99
+ result_id: str | None = field(default=None)
100
+
101
+ agent: str | None = field(default=None)
102
+
103
+ id: list | None = field(default=None) # number[]
104
+
105
+ search_hotel: SearchHotel | None = field(default=None)
106
+
107
+ search_location: SearchLocation | None = field(default=None)
108
+
109
+ search_distance: SearchDistance | None = field(default=None)
110
+
111
+ search_offer: SearchOffer | None = field(default=None)
112
+
113
+ search_lts: SearchLts | None = field(default=None)
114
+
115
+ search_special: SearchSpecial | None = field(default=None)
116
+
117
+ search_availability: SearchAvailability | None = field(default=None)
118
+
119
+ search_pricelist: SearchPriceList | None = field(default=None)
120
+
121
+ in_: int | None = field(default=None) # number[]
122
+
123
+ id_ofchannel: Literal["hgv", "lts", "esy"] | None = field(default=None)
124
+
125
+ transaction_id: str | None = field(default=None)
126
+
127
+ booking_id: str | None = field(default=None)
128
+
129
+ guest_email: str | None = field(default=None)
130
+
131
+ pic_group_id: int | None = field(default=None)
132
+
133
+ id_apt: int | None = field(default=None)
134
+
135
+ root_id: list | None = field(default=None) # list of ints
136
+
137
+ pic_type: PictureType | None = field(default=None)
138
+
139
+ select___avail: HotelFilters | None = field(default=None)
140
+ select___rooms: HotelFilters | None = field(default=None)
141
+ select___price: HotelFilters | None = field(default=None)
142
+ avail_alert: Literal[0, 1] | None = field(default=None)
143
+ rooms_alert: Literal[0, 1] | None = field(default=None)
144
+ price_alert: Literal[0, 1] | None = field(default=None)
145
+
146
+ coupon_code: str | None = field(default=None)
147
+ total_price: int | None = field(default=None)
148
+ arrival: str | None = field(default=None)
149
+ departure: str | None = field(default=None)
150
+ coupon_type: Literal["promotion", "voucher"] | None = field(default=None)
151
+
152
+ def __post_init__(self):
153
+ super().__init__("search")
154
+
155
+
156
+ class HotelFilters(Enum):
157
+ OTA = "ota"
158
+ EASI_CHANNEL = "easiChannel"
159
+ ROTER_HAHN = "10ec953a9d700b9598580a52d3dcef6c"
160
+ HOTEL_PARTNER = "2d9038f6a34c23280669f73ff531683c"
161
+ FIVE_STELLE = "30fb54af1d0d231b01b778647cfd967c"
162
+ ASA_LIGHT = "51c761e7b7b87dbeafe25a9b"
163
+ ASA_HOTEL = "51c761e7b7b87dc3afe15afa"
164
+ ROOM_CLOUD = "65ee9db4c37baedc1032cbd72c8caaaf"
165
+ GS_DATAPROVIDER = "66461e9d7c481e44e632051c3d040a2b"
166
+ HGV_TEST_CLIENT = "95f6a058-45ca-49df-874f-86f41e0bb29f"
167
+ HGV_CLIENT_FOR_TRENTINO = "a47a9dd543e55f8b3ee7ce4cc88b6d57"
168
+ HOTEL_NET_SOLUTIONS = "a57f0615b226609ae409c421ff118a8a"
169
+ BEDDY = "a8513684c7683fd457f82818f5f15bbf"
170
+ PCS_PHOENIX_XENUS = "AE1D2D8776B3FC1C;XENUS"
171
+ AIDA = "AIbD6vqHlYHA17DA"
172
+ AE_SMO = "ba098f2c86b942e58b6e7a89448f4063"
173
+ MTS_ONLINE = "bdcec66dfe4e8ef9f5c7e71e4835204c"
174
+ LTS_BOZEN = "be6bc64c94bbc062bcebfb40b4f93304"
175
+ BOOKING_EXPERT = "BookingE47acfb09170e8"
176
+ CASABLANCA = "CasaifeDZQQDaqvlblanca"
177
+ APARTMENT4HOLIDAY = "ceaeed03a0711eec46582b689d16dc0b"
178
+ CIAOBNB = "CiaoK2VAvAkFlCTcbnb"
179
+ EASI_SUITE = "Easy68e9nMxChannel"
180
+ EASI_SUITE_2 = "Easy68e9nMxChannel2"
181
+ SCIDOO = "f0bdfb926c2a8d066a9d2ea3e632471c"
182
+ ERICSOFT = "fcfb97bb1a8e608e5971928ac2032a68"
183
+ HOTEL_SPIDER = "HoteltihPrvo8kMpbSpider"
184
+ IPER_BOOKING = "iperbooking"
185
+ KROSS_BOOKING = "Kross2XklTsfhbBooking"
186
+ MM_ONE = "MMwRNWBeSQiABuONE"
187
+ PASSEPARTOUT = "passPGkPyHnw3IbApartout"
188
+ SEEKDA = "SEEK8XLyALKEzmpyp2DA"
189
+ SIMPLE_BOOKING = "Simple89sKiOdS9PUcbooking"
190
+ ANEXIS = "SiPaCbW2I921EpMedia"
191
+ SMART_PRICING = "SmartqpukLfH5Kl1price"
192
+ TEST_YANOVIS = "travelsuite"
193
+ VERTICAL_BOOKING = "VertiexDH0x8XV7Booking"
194
+ ALPINE_BITS_CERTIFICATION = "VwnIjABCertification78czDK6"
195
+ WUBOOK = "Wub0Na0CxWovxdVook"
196
+
197
+
198
+ class PictureType(Enum):
199
+ Hotel = "hotel"
200
+ Gallery = "gallery"
201
+ Profile = "profile"
202
+ Roomgroup = "roomgroup"
203
+ Pricelist = "pricelist"
204
+ Special = "special"
205
+
206
+
207
+ @dataclass
208
+ class Options(BaseType):
209
+ hotel_details: HotelDetails | None = field(default=None)
210
+ offer_details: OfferDetails | None = field(default=None)
211
+
212
+ picture_date: str | None = field(default=None) # Date
213
+ lts_bookable: Literal[0, 1, 2] | None = field(default=None) # number, 0|1|2
214
+
215
+ base_price: int | None = field(default=None) # number, 0|1
216
+
217
+ # field is in easychannel but not in nodejs
218
+ only_available: Literal[0, 1] | None = field(default=None) # 0 | 1
219
+
220
+ # below fields are in nodejs but not in easychannel.it?
221
+ room_details: RoomDetails | None = field(default=None)
222
+ special_details: SpecialDetails | None = field(default=None)
223
+ # pricelist_details: PriceListDetails | None = field(default=None)
224
+
225
+ get_availability: Literal[0, 1] | None = field(default=None) # 0 | 1
226
+ get_restrictions: Literal[0, 1] | None = field(default=None) # 0 | 1
227
+ get_roomdetails: int | None = field(default=None) # 0 | 1
228
+ get_masterpackages: Literal[0, 1] | None = field(default=None)
229
+
230
+ location_details: Literal[0, 1] | None = field(default=None)
231
+ theme_details: Literal[0, 1] | None = field(default=None)
232
+
233
+ service_details: ServiceDetails | None = field(default=None)
234
+
235
+ def __post_init__(self):
236
+ super().__init__("options")
237
+
238
+
239
+ class ServiceDetails(IntFlag):
240
+ Headlines = 8
241
+ Pictures = 32
242
+ Descriptions = 256
243
+
244
+
245
+ class HotelDetails(IntFlag):
246
+ BasicInfo = 1
247
+ Themes = 2
248
+ HotelFacilities = 4
249
+ ShortDescription = 8
250
+ FullDescription = 16
251
+ GeographicInformation = 32
252
+ Coordinates = 64
253
+ Address = 128
254
+ Contacts = 256
255
+ PaymentOptionsForOnlineBooking = 512
256
+ PaymentOptionsAtHotel = 1024 #
257
+ Logo = 2048
258
+ HeaderImages = 4096
259
+ Gallery = 8192
260
+ HotelMatching = 16384
261
+ GeographicalInformationAsText = 32768
262
+ HotelReviews = 65536 # different name in GO
263
+ DetailedHotelFacilities = 131072
264
+ SalesPoint = 524288
265
+ LtsSpecificParameters = 262144
266
+ CouponServiceData = 16777216
267
+ CheckInOut = 1048576
268
+ SourceData = 2097152
269
+ AccountData = 67108864
270
+ RoomTypes = 134217728
271
+ # Payment provider missing?
272
+
273
+
274
+ class OfferDetails(IntFlag):
275
+ BasicInfo = 1
276
+ RoomCode = 4
277
+ RoomTitle = 8
278
+ PriceDetails = 16
279
+ RoomImages = 32
280
+ RoomFacilitiesFilter = 64
281
+ RoomDescription = 256
282
+ IncludedServices = 1024
283
+ AdditionalServices = 2048
284
+ RoomFacilitiesDetails = 4096
285
+ PriceImages = 8192
286
+ Themes = 16384
287
+ RoomFeatures = 32768
288
+ CancelPolicies = 262144
289
+ PaymentTerms = 1048576
290
+
291
+
292
+ class RoomDetails(IntFlag):
293
+ BasicInfo = 4
294
+ Title = 8
295
+ RoomImages = 32
296
+ RoomFacilitiesFilter = 64
297
+ RoomDescription = 256
298
+ RoomFacilitiesDetails = 4096
299
+ RoomFeatures = 32768
300
+ RoomNumbers = 65536
301
+
302
+
303
+ class SpecialDetails(IntFlag):
304
+ BasicInfo = 1
305
+ Title = 2
306
+ Descriptions = 4
307
+ Seasons = 8
308
+ Images = 16
309
+ Themes = 32
310
+ IncludedServices = 64
311
+
312
+
313
+ @dataclass
314
+ class Order(BaseType):
315
+ dir: Direction | None = field(default=None)
316
+ field: Field | None = field(default=None)
317
+
318
+ def __post_init__(self):
319
+ super().__init__("order")
320
+
321
+
322
+ class Field(Enum):
323
+ ValidityStart = "valid_start"
324
+ ValidityEnd = "valid_end"
325
+ Random = "rand"
326
+ Stars = "stars"
327
+ Name = "name"
328
+
329
+
330
+ class Direction(Enum):
331
+ Ascending = "asc"
332
+ Descending = "desc"
333
+
334
+
335
+ @dataclass
336
+ class Data(BaseType):
337
+ guest: Guest | None = field(default=None)
338
+ company: Company | None = field(default=None)
339
+ payment: Payment | None = field(default=None)
340
+ note: str | None = field(default=None)
341
+ details: Details | None = field(default=None)
342
+ form: Form | None = field(default=None)
343
+ tracking: Tracking | None = field(default=None)
344
+ # insurance: Ins
345
+ storno_reason: StornoReason | None = field(default=None)
346
+ storno_reason_text: str | None = field(default=None)
347
+
348
+ special: list | None = field(default=None) # list of specials
349
+
350
+ def __post_init__(self):
351
+ super().__init__("data")
352
+
353
+
354
+ @dataclass
355
+ class Special(BaseType):
356
+ offer_id: int
357
+ action: Literal["update", "delete"]
358
+ time_modified: str # ISO 8601 Date
359
+ reset_participants: Literal[0, 1] | None = field(default=None)
360
+
361
+ def __post_init__(self):
362
+ super().__init__("special")
363
+
364
+
365
+ class StornoReason(Enum):
366
+ Unknown = 0
367
+ GuestNotAvailable = 1
368
+ AccomodationRequestedToCancel = 2
369
+ GuestAnotherDestination = 3
370
+ GuestAnotherAccomodation = 4
371
+ Other = 99
372
+
373
+
374
+ @dataclass
375
+ class Logging(BaseType):
376
+ step: str | None = field(default=None)
377
+
378
+ def __post_init__(self):
379
+ super().__init__("logging")
380
+
381
+
382
+ class Step(Enum):
383
+ Search = "search"
384
+ SearchOffer = "search_offer"
385
+ SearchDetails = "search_details"
386
+ View = "view"
387
+ ViewOffer = "view_offer"
388
+ Step1 = "step_1"
389
+ Step2 = "step_2"
390
+ Step3 = "step_3"
391
+ Step4 = "step_4"
392
+
393
+
394
+ @dataclass
395
+ class SearchHotel(BaseType):
396
+ name: str | None = field(default=None)
397
+ type: HotelType | None = field(default=None)
398
+ stars: Stars | None = field(default=None)
399
+ feature: HotelFeature | None = field(default=None)
400
+ theme: HotelTheme | None = field(default=None)
401
+
402
+ def __post_init__(self):
403
+ super().__init__("search_hotel")
404
+
405
+
406
+ class HotelType(Enum):
407
+ Hotel = "1"
408
+ SkiSchool = "2"
409
+ Residence = "4"
410
+ Appartment = "16"
411
+ FarmVacation = "32"
412
+ MountainInn = "64"
413
+ CampingSite = "128"
414
+ HolidayHome = "256"
415
+ YouthHostel = "512"
416
+ Guesthouse = "1024"
417
+ Refuge = "2048"
418
+ Garni = "4096"
419
+ Inn = "8192"
420
+
421
+
422
+ class HotelFeature(Enum):
423
+ Garage = "1"
424
+ Elevator = "2"
425
+ Restaurant = "4"
426
+ Gym = "8"
427
+ Wellness = "16"
428
+ Spa = "32"
429
+ Breakfast = "64"
430
+ Buffet = "128"
431
+ OutdoorPool = "256"
432
+ IndoorPool = "512"
433
+ Bar = "1024"
434
+ BarrierFree = "2048"
435
+ Wlan = "4096"
436
+ ShuttleService = "8192"
437
+ Childcare = "16384"
438
+ SmallPetsAllowed = "32768"
439
+ BeautyFarm = "65536"
440
+ CentralLocation = "262144"
441
+ CoveredParking = "524288"
442
+ OpenParking = "1048576"
443
+ Massages = "2097152"
444
+ Sauna = "4194304"
445
+ SteamBath = "8388608"
446
+ PublicBar = "16777216"
447
+ DogsAllowed = "33554432"
448
+
449
+
450
+ class HotelTheme(Enum):
451
+ Family = "1"
452
+ Wellness = "2"
453
+ Hiking = "4"
454
+ Motorcycle = "8"
455
+ Bike = "16"
456
+ Golf = "32"
457
+ Riding = "64"
458
+ Romantic = "128"
459
+ Ski = "256"
460
+ Meeting = "512"
461
+ CrossCountrySkiing = "1024"
462
+ Culture = "2048"
463
+ Snowshoeing = "4096"
464
+
465
+
466
+ @dataclass
467
+ class SearchLocation(BaseType):
468
+ location: list | None = field(default=None) # number[], Location ID
469
+ location_lts: list | None = field(default=None) # string[], LTS Location RID
470
+
471
+ def __post_init__(self):
472
+ super().__init__("search_location")
473
+
474
+
475
+ @dataclass
476
+ class SearchDistance:
477
+ latitude: float # number
478
+ longitude: float # number
479
+ radius: int # number
480
+
481
+
482
+ @dataclass
483
+ class SearchOffer(BaseType):
484
+ arrival: str | None = field(default=None) # Date YYYY-MM-DD
485
+ departure: str | None = field(default=None) # Date YYYY-MM-DD
486
+ service: Board | None = field(default=None)
487
+ room: list | None = field(default=None) # Room[]
488
+ feature: RoomFeature | None = field(default=None)
489
+ channel_id: list | None = field(default=None) # string[]
490
+ typ: SearchOfferType | None = field(default=None)
491
+ rateplan: Rateplan | None = field(default=None)
492
+
493
+ # features from easychange missing?
494
+
495
+ def __post_init__(self):
496
+ super().__init__("search_offer")
497
+
498
+
499
+ class SearchOfferType(Enum):
500
+ DefaultPricelist = "10"
501
+ PeopleAge = "20"
502
+ PeopleNumber = "21"
503
+ Staying = "22"
504
+ BookingDate = "23"
505
+ Weekday = "24"
506
+ NoReference = "25"
507
+ SpecialPeopleAge = "50"
508
+ SpecialPeopleNumber = "51"
509
+ SpecialStaying = "52"
510
+ SpecialBookingDate = "53"
511
+ SpecialWeekday = "54"
512
+ SpecialNoReference = "55"
513
+
514
+
515
+ class Board(Enum):
516
+ Without = 1
517
+ Breakfast = 2
518
+ HalfBoard = 3
519
+ FullBoard = 4
520
+ AllInclusive = 5
521
+
522
+
523
+ class RoomFeature(IntFlag):
524
+ Balcony = 1
525
+ Terrace = 2
526
+ MiniBar = 4
527
+ Safe = 8
528
+ TV = 16
529
+ Satellite = 32
530
+ Wlan = 64
531
+ Internet = 128
532
+ BarrierFree = 512
533
+
534
+
535
+ @dataclass
536
+ class SearchLts(BaseType):
537
+ A0Ene: int | None = field(default=None) # number
538
+ A0MTV: int | None = field(default=None) # number
539
+ A0Rep: int | None = field(default=None) # number
540
+
541
+ def __post_init__(self):
542
+ super().__init__("search_lts")
543
+
544
+
545
+ @dataclass
546
+ class SearchSpecial(BaseType):
547
+ offer_id: list | None = field(default=None) # number[]
548
+ date_from: str | None = field(default=None) # Date YYYY-MM-DD
549
+ date_to: str | None = field(default=None) # Date YYYY-MM-DD
550
+ theme: list | None = field(default=None) # array of SpecialTheme
551
+ validity: Validity | None = field(default=None)
552
+ typ: SearchSpecialType | None = field(default=None)
553
+ premium: SearchSpecialPremium | None = field(default=None)
554
+
555
+ poi_id: list | None = field(default=None)
556
+ poi_cat: list | None = field(default=None)
557
+ status: Literal[0, 1] | None = field(default=None)
558
+
559
+ def __post_init__(self):
560
+ super().__init__("search_special")
561
+
562
+
563
+ class SearchSpecialType(Enum):
564
+ PriceLists = 0
565
+ Packages = 1
566
+ Specials = 2
567
+ ShortLongStays = 4
568
+
569
+
570
+ class SearchSpecialPremium(IntFlag):
571
+ FamilyHotelsPremium = 2
572
+ VinumHotelsPremium = 4
573
+ SüdtirolBalancePremium = 8
574
+ VitalpinaDurchatmen = 16
575
+ VitalpinaWohlfühlen = 32
576
+ VitalpinaErnährung = 64
577
+ VitalpinaAktiv = 128
578
+ VitalpinaPremium = 256
579
+ BikehotelsMountainbike = 512
580
+ BikehotelsBikeTouringEBike = 1024
581
+ BikehotelsRoadbike = 2048
582
+ BikehotelsPremium = 4096
583
+ ArchitectureDays = 8192
584
+ VinumHotels = 16384
585
+ FamilyHotels = 32768
586
+ FamilyHotelsNatureDetective = 65536
587
+ FamilyHotelsNatureDetectiveWinter = 131072
588
+
589
+
590
+ class SpecialTheme(Enum):
591
+ ThemeIDHiking = 1
592
+ ThemeIDCyclingMountainbike = 2
593
+ ThemeIDFamily = 3
594
+ ThemeIDWellnessHealth = 4
595
+ ThemeIDFoodAndDrink = 5
596
+ ThemeIDGolf = 6
597
+ ThemeIDCulture = 7
598
+ ThemeIDMotorsport = 8
599
+ ThemeIDCarFreeHolidays = 9
600
+ ThemeIDSkiSnowboard = 10
601
+ ThemeIDSummerActivities = 11
602
+ ThemeIDEvents = 12
603
+ ThemeIDChristmasMarkets = 13
604
+ ThemeIDActiveWinter = 14
605
+ ThemeIDVitalpina = 15
606
+ ThemeIDVitalpinaBreathe = 16
607
+ ThemeIDBikeHotelsEBike = 17
608
+ ThemeIDBikeHotelsFreeride = 18
609
+ ThemeIDBikeHotelsMountainbike = 20
610
+ ThemeIDBikeHotelsBikeTours = 21
611
+ ThemeIDBikeHotelsRacingBike = 22
612
+ ThemeIDFamilyHotels = 23
613
+ ThemeIDFamilyHotelsNatureDetective = 24
614
+ ThemeIDFamilyHotel = 26
615
+ ThemeIDNatureDetectivSummer = 27
616
+ ThemeIDNatureDetectivWinter = 28
617
+ ThemeIDEcologicHoliday = 79
618
+ ThemeIDHorseBackRiding = 80
619
+ ThemeIDLuxuryHoliday = 81
620
+ ThemeIDPetsFriendlyHoliday = 82
621
+ ThemeIDRoadBike = 83
622
+ ThemeIDRomanticHoliday = 84
623
+ ThemeIDWine = 85
624
+ ThemeIDBicycleTouring = 86
625
+ ThemeIDEBike = 87
626
+
627
+ ##These values were theme_bit
628
+ # Hiking = 1
629
+ # Cycling = 2
630
+ # Family = 4
631
+ # Wellness = 8
632
+ # Food = 16
633
+ # Golf = 32
634
+ # Culture = 64
635
+ # Motorsport = 128
636
+ # CarFree = 256
637
+ # SkiSnowboard = 512
638
+ # SummerActivities = 1024
639
+ # Events = 2048
640
+ # ChristmasMarkets = 4096
641
+ # ActiveWinter = 8192
642
+ # Vitalpina = 16384
643
+ # VitalpinaBreathe = 32768
644
+ # BikeHotelsEBike = 65536
645
+ # BikeHotelsFreeride = 131072
646
+ # BikeHotelsMountainbike = 524288
647
+ # BikeHotelsBikeTours = 1048576
648
+ # BikeHotelsRacingBike = 2097152
649
+ # FamilyHotels = 4194304
650
+ # FamilyHotelsNatureDetective = 8388608
651
+ # FamilyHotel = 33554432
652
+ # FamilyHotelsNatureDetectiveSummer = 67108864
653
+ # FamilyHotelsNatureDetectiveWinter = 134217728
654
+
655
+
656
+ @dataclass
657
+ class SearchAvailability(BaseType):
658
+ date_from: str # Date YYYY-MM-DD
659
+ date_to: str # Date YYYY-MM-DD
660
+ offer_id: list | None = field(default=None) # number[]
661
+ room_id: list | None = field(default=None) # number[]
662
+ duration: int | None = field(default=None)
663
+ room: Room | None = field(default=None)
664
+
665
+ def __post_init__(self):
666
+ super().__init__("search_availability")
667
+
668
+
669
+ @dataclass
670
+ class SearchPriceList(BaseType):
671
+ date_from: str | None = field(default=None) # Date YYYY-MM-DD
672
+ date_to: str | None = field(default=None) # Date YYYY-MM-DD
673
+ service: Board | None = field(default=None)
674
+ room_id: list | None = field(default=None) # number[]
675
+ typ: SearchSpecialType | None = field(default=None)
676
+
677
+ def __post_init__(self):
678
+ super().__init__("search_pricelist")
679
+
680
+
681
+ @dataclass
682
+ class Guest(BaseType):
683
+ firstname: str
684
+ lastname: str
685
+ email: str
686
+ gender: str | None = field(default=None)
687
+ prefix: str | None = field(default=None)
688
+ phone: str | None = field(default=None)
689
+ address: Address | None = field(default=None)
690
+ newsletter: Literal[0, 1] | None = field(default=None) # 0 | 1
691
+
692
+ def __post_init__(self):
693
+ super().__init__("guest")
694
+
695
+
696
+ @dataclass
697
+ class Company(BaseType):
698
+ name: str | None = field(default=None)
699
+ taxnumber: str | None = field(default=None)
700
+ recipient_code: str | None = field(default=None)
701
+ address: Address | None = field(default=None)
702
+
703
+ def __post_init__(self):
704
+ super().__init__("company")
705
+
706
+
707
+ @dataclass
708
+ class Payment(BaseType):
709
+ method: PaymentMethod | None = field(default=None)
710
+ invoice: Literal[0, 1] | None = field(default=None) # 0 | 1
711
+
712
+ def __post_init__(self):
713
+ super().__init__("payment")
714
+
715
+
716
+ class PaymentMethod(IntFlag):
717
+ CreditCardDeposit = 1
718
+ CreditCardAsSecurity = 2
719
+ CreditCardPayment = 8
720
+ BankTransferDeposit = 4
721
+ BankTransferPayment = 16
722
+ AccommodationPayment = 32
723
+
724
+
725
+ @dataclass
726
+ class Details(BaseType):
727
+ extr_price: list | None = field(default=None) # ExtraPrice[]
728
+
729
+ def __post_init__(self):
730
+ super().__init__("Details")
731
+
732
+
733
+ @dataclass
734
+ class ExtraPrice(BaseType):
735
+ price_id: int | None = field(default=None) # number
736
+ price_amount: int | None = field(default=None) # number
737
+
738
+ def __post_init__(self):
739
+ super().__init__("extra_price")
740
+
741
+
742
+ @dataclass
743
+ class Form(BaseType):
744
+ url_success: str | None = field(default=None)
745
+ url_failure: str | None = field(default=None)
746
+
747
+ def __post_init__(self):
748
+ super().__init__("form")
749
+
750
+
751
+ @dataclass
752
+ class Tracking(BaseType):
753
+ partner: str | None = field(default=None)
754
+ media: str | None = field(default=None)
755
+ campaign: str | None = field(default=None)
756
+ companyinfo: str | None = field(default=None)
757
+
758
+ def __post_init__(self):
759
+ super().__init__("tracking")
760
+
761
+
762
+ @dataclass
763
+ class Stars(BaseType):
764
+ min: Literal[1, 2, 3, 3.5, 4, 4.5, 5] | None = field(
765
+ default=None
766
+ ) # number, min can be 1, values are 1, 2, 3, 3.5, 4, 4.5, 5
767
+ max: Literal[1, 2, 3, 3.5, 4, 4.5, 5] | None = field(
768
+ default=None
769
+ ) # number, max can be 5
770
+
771
+ def __post_init__(self):
772
+ super().__init__("stars")
773
+
774
+
775
+ @dataclass
776
+ class Address(BaseType):
777
+ street: str | None = field(default=None)
778
+ zipcode: str | None = field(default=None)
779
+ city: str | None = field(default=None)
780
+ country: str | None = field(default=None)
781
+
782
+ def __post_init__(self):
783
+ super().__init__("address")
784
+
785
+
786
+ @dataclass
787
+ class Room(BaseType):
788
+ room_seq: int | None = field(default=None) # number
789
+ person: list | None = field(
790
+ default=None
791
+ ) # number[], 1..n Persons and their age (store only age inside tags)
792
+ offer_id: int | None = field(default=None) # number
793
+ room_id: int | None = field(default=None) # number
794
+ service: Board | None = field(default=None)
795
+ room_type: RoomType | None = field(default=None)
796
+
797
+ def __post_init__(self):
798
+ super().__init__("room")
799
+
800
+
801
+ class RoomType(Enum):
802
+ All = 0
803
+ Room = 1
804
+ Apartment = 2
805
+ Campsite = 4
806
+
807
+
808
+ @dataclass
809
+ class Rateplan(BaseType):
810
+ code: str # | None = field(default=None)
811
+ source: str # | None = field(default=None)
812
+
813
+ def __post_init__(self):
814
+ super().__init__("rateplan")
815
+
816
+
817
+ @dataclass
818
+ class Validity(BaseType):
819
+ valid: Literal[0, 1] # 0 | 1
820
+ offers: Literal[0, 1] | None = field(default=None) # 0 | 1
821
+ arrival: str | None = field(default=None) # Date YYYY-MM-DD
822
+ departure: str | None = field(default=None) # Date YYYY-MM-DD
823
+ service: Board | None = field(default=None)
824
+ room: list | None = field(default=None) # Room[]
825
+
826
+ def __post_init__(self):
827
+ super().__init__("validity")
828
+
829
+
830
+ def getHotelList_base_xml(root: Root, header: Header):
831
+ xml = '<?xml version="1.0" encoding="utf-8"?>'
832
+ xml += root.version
833
+ xml += header.credentials
834
+ return xml