{"action":"created","issue":{"url":"https://api.github.com/repos/windingtree/wiki/issues/25","repository_url":"https://api.github.com/repos/windingtree/wiki","labels_url":"https://api.github.com/repos/windingtree/wiki/issues/25/labels{/name}","comments_url":"https://api.github.com/repos/windingtree/wiki/issues/25/comments","events_url":"https://api.github.com/repos/windingtree/wiki/issues/25/events","html_url":"https://github.com/windingtree/wiki/issues/25","id":329811307,"node_id":"MDU6SXNzdWUzMjk4MTEzMDc=","number":25,"title":"Proposal: Pricing data format","user":{"login":"JirkaChadima","id":375483,"node_id":"MDQ6VXNlcjM3NTQ4Mw==","avatar_url":"https://avatars3.githubusercontent.com/u/375483?v=4","gravatar_id":"","url":"https://api.github.com/users/JirkaChadima","html_url":"https://github.com/JirkaChadima","followers_url":"https://api.github.com/users/JirkaChadima/followers","following_url":"https://api.github.com/users/JirkaChadima/following{/other_user}","gists_url":"https://api.github.com/users/JirkaChadima/gists{/gist_id}","starred_url":"https://api.github.com/users/JirkaChadima/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/JirkaChadima/subscriptions","organizations_url":"https://api.github.com/users/JirkaChadima/orgs","repos_url":"https://api.github.com/users/JirkaChadima/repos","events_url":"https://api.github.com/users/JirkaChadima/events{/privacy}","received_events_url":"https://api.github.com/users/JirkaChadima/received_events","type":"User","site_admin":false},"labels":[{"id":954005440,"node_id":"MDU6TGFiZWw5NTQwMDU0NDA=","url":"https://api.github.com/repos/windingtree/wiki/labels/data-format","name":"data-format","color":"2b74b5","default":false}],"state":"closed","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":12,"created_at":"2018-06-06T10:38:27Z","updated_at":"2018-06-15T13:08:52Z","closed_at":"2018-06-15T13:08:52Z","author_association":"MEMBER","body":"**This is being ported and evolving on [Swaggerhub](https://app.swaggerhub.com/apis/windingtree/WTHotelDefinitions/), the current version is there.**\r\n\r\nThe goal of this issue is to reach a consensus on a shape of pricing data (rate plans, rates). This is not meant as an exhaustive standard, but a first version we can later build on. We are trying to go simple and flexible here, so there are probably some additional information missing, but we should cover the most common use cases pretty well.\r\n\r\nAs with #22, #23 I was comparing available existing standards and APIs and tried to compile everything together in a reasonable way. Comparison is [here](https://docs.google.com/spreadsheets/d/1dqQVvF7IIkurIMSMENbB04Fe2HOxbvI9DgYxnhPoGv8/edit?usp=sharing).\r\n\r\n- [UnitType.sol](https://github.com/windingtree/wt-contracts/blob/master/contracts/hotel/UnitType.sol)\r\n- [RoomRanger's API](https://github.com/windingtree/rr-channel-api/blob/master/swagger.yaml), https://github.com/windingtree/rr-json-formats\r\n- other [existing apis](https://github.com/windingtree/internal-documents/blob/master/existing-api-summary.md)\r\n- [HTNG](http://www.htng.org/?page=technical_specs)\r\n- [SynXis/Sabre](https://developer.sabre.com/sabre_hospitality/apis/soap_apis/hotel/channel_connect/ari)\r\n- [siteminder](https://siteminder.atlassian.net/wiki/spaces/PMSXCHANGEV2/overview)\r\n- sciant input - not public\r\n- OXI - https://docs.oracle.com/cd/E91116_01/docs/User%20Manual.pdf, https://docs.oracle.com/cd/E91116_01/docs/Communication%20Vendor%20Specification.pdf\r\n- Booking.com (basically OTA implementation) - https://connect.booking.com/user_guide/site/en-US/user_guide.html?lang=en\r\n\r\n---\r\n# Example data\r\n\r\n```\r\n{\r\n  \"ratePlans\": {\r\n    \"some-unique-rate-id\": {\r\n      \"id\": \"some-unique-rate-id\",\r\n      \"name\": \"Rate for summer - bungalows\",\r\n      \"description\": \"Bungalows for summer season of 2018\",\r\n      \"updatedAt\": \"ISO8601 time of last update\",\r\n      \"roomTypeIds\": [\r\n        \"room-type-reference\",\r\n        \"another-reference\"\r\n      ],\r\n      \"currency\": \"EUR\",\r\n      \"availableForReservation\": {\r\n        \"start\": \"ISO8601\",\r\n        \"end\": \"ISO8601\"\r\n      },\r\n      \"availableForTravel\": {\r\n        \"start\": \"ISO8601\",\r\n        \"end\": \"ISO8601\"\r\n      },\r\n      \"pricing\": {\r\n        \"base\": {\r\n          \"maxOccupancyLimit\": 3,\r\n          \"rates\": [\r\n            {\r\n              \"ageCategory\": \"adult\",\r\n              \"amount\": 100,\r\n              \"lengthOfStay\": 1\r\n            },\r\n            {\r\n              \"ageCategory\": \"child\",\r\n              \"amount\": 50,\r\n              \"lengthOfStay\": 1\r\n            },\r\n            {\r\n              \"ageCategory\": \"adult\",\r\n              \"amount\": 90,\r\n              \"lengthOfStay\": 2\r\n            },\r\n            {\r\n              \"ageCategory\": \"child\",\r\n              \"amount\": 40,\r\n              \"lengthOfStay\": 2\r\n            }\r\n          ]\r\n        },\r\n        \"additional\": {\r\n          \"maxOccupancyLimit\": 3,\r\n          \"rates\": [\r\n            {\r\n              \"ageCategory\": \"adult\",\r\n              \"amount\": 30,\r\n              \"lengthOfStay\": 1\r\n            },\r\n            {\r\n              \"ageCategory\": \"child\",\r\n              \"amount\": 20,\r\n              \"lengthOfStay\": 1\r\n            },\r\n            {\r\n              \"ageCategory\": \"adult\",\r\n              \"amount\": 25,\r\n              \"lengthOfStay\": 2\r\n            },\r\n            {\r\n              \"ageCategory\": \"child\",\r\n              \"amount\": 15,\r\n              \"lengthOfStay\": 2\r\n            }\r\n          ]\r\n        }\r\n      },\r\n      \"restrictions\": {\r\n        \"bookingCutOff\": {\r\n          \"min\": 0,\r\n          \"max\": 30\r\n        },\r\n        \"lengthOfStay\": {\r\n          \"min\": 1,\r\n          \"max\": 28\r\n        }\r\n      }\r\n    }\r\n  }\r\n}\r\n```\r\n\r\n**Notes**\r\n\r\n- ~~`status` - some rate plans might not be active at all times, for example when the whole hotel is bookied for a conference, it makes sense to only deactivate rate plans and not drop them~~\r\n- `availableForReservation` - Between these dates, people can make bookings based on this rate plan.\r\n- `availableForTravel` - I can actually book a room between these dates with this rate plan.\r\n- `ageCategory` - we should define an enum for this such as `kids under 3`, `people over 60` etc. Or extend this to min/max applicable age\r\n- `lengthOfStay` - Maybe it could be optional, 1 should be considered as default. It represents a possibly lower price when you stay for more days\r\n- `restrictions.bookingCutOff` - how many days before stay date you can actually make a booking\r\n- ~~`blocked*Days` - which days hold some kind of restriction. The array may contain english days of week. If a day is not present, there's no restriction on given day. We shall explicitly name this blocked/restricted or something like that, to make explicit that if a day is mentioned here, something special is happenning with it.~~\r\n- We're not yet dealing with cancellation terms. It seems no concensus on its representation exists.\r\n- Price detection algorithm could look like this\r\n```\r\n- pick the right ratePlan(s) based on availableForTravel field and provided booking dates\r\n- check restrictions and drop rate plans that the booking doesn't meet\r\n- for every rate plan as rp_i\r\n  - for every person as p_j\r\n      j < under baseOccupancyLimit, use base rates, use additional rates otherwise\r\n      is a rate for given lengthOfStay provided?\r\n          yes - use it\r\n          no - use the one with lengthOfStay=1 or missing lengthOfStay\r\n      pick a rate based on guest's age\r\n      multiply the rate by length of stay\r\n  - store the final price for rp_i\r\n- compare all final prices and pick the cheapest\r\n```\r\n\r\n\r\n**Questions**\r\n- Does it make sense? Are we missing some important piece of information?\r\n- Do we actually need to keep track of related inventory? Maybe that should be a part of other data type (availability), that would glue everything together.\r\n- Where should we put this in our data hierarchy? My assumption is that this data changes frequently."},"comment":{"url":"https://api.github.com/repos/windingtree/wiki/issues/comments/397614680","html_url":"https://github.com/windingtree/wiki/issues/25#issuecomment-397614680","issue_url":"https://api.github.com/repos/windingtree/wiki/issues/25","id":397614680,"node_id":"MDEyOklzc3VlQ29tbWVudDM5NzYxNDY4MA==","user":{"login":"JirkaChadima","id":375483,"node_id":"MDQ6VXNlcjM3NTQ4Mw==","avatar_url":"https://avatars3.githubusercontent.com/u/375483?v=4","gravatar_id":"","url":"https://api.github.com/users/JirkaChadima","html_url":"https://github.com/JirkaChadima","followers_url":"https://api.github.com/users/JirkaChadima/followers","following_url":"https://api.github.com/users/JirkaChadima/following{/other_user}","gists_url":"https://api.github.com/users/JirkaChadima/gists{/gist_id}","starred_url":"https://api.github.com/users/JirkaChadima/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/JirkaChadima/subscriptions","organizations_url":"https://api.github.com/users/JirkaChadima/orgs","repos_url":"https://api.github.com/users/JirkaChadima/repos","events_url":"https://api.github.com/users/JirkaChadima/events{/privacy}","received_events_url":"https://api.github.com/users/JirkaChadima/received_events","type":"User","site_admin":false},"created_at":"2018-06-15T13:08:52Z","updated_at":"2018-06-15T13:08:52Z","author_association":"MEMBER","body":"Closing this for now, we will improve the data spec as a whole."}}
{"actor":{"display_login":"JirkaChadima"}}