diff --git a/uk_bin_collection/tests/council_schemas/CannockChaseDistrictCouncil.schema b/uk_bin_collection/tests/council_schemas/CannockChaseDistrictCouncil.schema new file mode 100644 index 0000000000..31805dad36 --- /dev/null +++ b/uk_bin_collection/tests/council_schemas/CannockChaseDistrictCouncil.schema @@ -0,0 +1,39 @@ +{ + "$schema": "http://json-schema.org/draft-06/schema#", + "$ref": "#/definitions/Welcome8", + "definitions": { + "Welcome8": { + "type": "object", + "additionalProperties": false, + "properties": { + "bins": { + "type": "array", + "items": { + "$ref": "#/definitions/Bin" + } + } + }, + "required": [ + "bins" + ], + "title": "Welcome8" + }, + "Bin": { + "type": "object", + "additionalProperties": false, + "properties": { + "type": { + "type": "string" + }, + "collectionDate": { + "type": "string" + } + }, + "required": [ + "collectionDate", + "type" + ], + "title": "Bin" + } + } +} diff --git a/uk_bin_collection/tests/features/validate_council_outputs.feature b/uk_bin_collection/tests/features/validate_council_outputs.feature index bfd77f0643..78fbdef491 100644 --- a/uk_bin_collection/tests/features/validate_council_outputs.feature +++ b/uk_bin_collection/tests/features/validate_council_outputs.feature @@ -20,6 +20,7 @@ Feature: Test each council output matches expected results in /outputs | BroxtoweBoroughCouncil | | BuckinghamshireCouncil | | BuryCouncil | + | CannockChaseDistrictCouncil | | CardiffCouncil | | CastlepointDistrictCouncil | | CharnwoodBoroughCouncil | diff --git a/uk_bin_collection/tests/input.json b/uk_bin_collection/tests/input.json index 2d35915528..075ac10a5d 100644 --- a/uk_bin_collection/tests/input.json +++ b/uk_bin_collection/tests/input.json @@ -110,6 +110,14 @@ "wiki_name": "Bury Council", "wiki_note": "Pass the postcode and house number in their respective arguments, both wrapped in quotes." }, + "CannockChaseDistrictCouncil": { + "SKIP_GET_URL": "SKIP_GET_URL", + "postcode": "WS15 1JA", + "uprn": "200003095389", + "url": "https://www.cannockchasedc.gov.uk/", + "wiki_name": "Cannock Chase District Council", + "wiki_note": "To get the UPRN, you can use [FindMyAddress](https://www.findmyaddress.co.uk/search)" + }, "CrawleyBoroughCouncil": { "SKIP_GET_URL": "SKIP_GET_URL", "uprn": "100061785321", diff --git a/uk_bin_collection/tests/outputs/CannockChaseDistrictCouncil.json b/uk_bin_collection/tests/outputs/CannockChaseDistrictCouncil.json new file mode 100644 index 0000000000..5814b4ecb0 --- /dev/null +++ b/uk_bin_collection/tests/outputs/CannockChaseDistrictCouncil.json @@ -0,0 +1,28 @@ +{ + "bins": [ + { + "type": "Refuse", + "collectionDate": "26/10/2023" + }, + { + "type": "Garden", + "collectionDate": "02/11/2023" + }, + { + "type": "Recycle", + "collectionDate": "02/11/2023" + }, + { + "type": "Refuse", + "collectionDate": "09/11/2023" + }, + { + "type": "Garden", + "collectionDate": "16/11/2023" + }, + { + "type": "Recycle", + "collectionDate": "16/11/2023" + } + ] +} \ No newline at end of file diff --git a/uk_bin_collection/uk_bin_collection/councils/CannockChaseDistrictCouncil.py b/uk_bin_collection/uk_bin_collection/councils/CannockChaseDistrictCouncil.py new file mode 100644 index 0000000000..f5ee9251db --- /dev/null +++ b/uk_bin_collection/uk_bin_collection/councils/CannockChaseDistrictCouncil.py @@ -0,0 +1,58 @@ +from bs4 import BeautifulSoup + +from uk_bin_collection.uk_bin_collection.common import * +from uk_bin_collection.uk_bin_collection.get_bin_data import \ + AbstractGetBinDataClass + + +# import the wonderful Beautiful Soup and the URL grabber +class CouncilClass(AbstractGetBinDataClass): + """ + Concrete classes have to implement all abstract operations of the + base class. They can also override some operations with a default + implementation. + """ + + def parse_data(self, page: str, **kwargs) -> dict: + user_uprn = kwargs.get("uprn") + user_postcode = kwargs.get("postcode") + check_uprn(user_uprn) + check_postcode(user_postcode) + + # Make SOAP Request + response = requests.post( + "https://ccdc.opendata.onl/DynamicCall.dll", + data="Method=CollectionDates&Postcode=" + user_postcode + "&UPRN=" + user_uprn, + headers={ + "Content-Type": "application/x-www-form-urlencoded", + "Referer": "https://ccdc.opendata.onl/CCDC_WasteCollection", + "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36" + } + ) + + # Make a BS4 object + soup = BeautifulSoup(response.text, "xml") + soup.prettify() + + if soup.find("ErrorDescription") and soup.find("ErrorDescription").get_text( + strip=True) == "No results returned": + raise ValueError("No collection data found for provided Postcode & UPRN.") + + data = {"bins": []} + + collections = soup.find_all("Collection") + + for i in range(len(collections)): + dict_data = { + "type": collections[i].Service.get_text().replace("Collection Service", "").strip(), + "collectionDate": datetime.strptime( + collections[i].Date.get_text(), + "%d/%m/%Y %H:%M:%S" + ).strftime(date_format) + } + data["bins"].append(dict_data) + + data["bins"].sort( + key=lambda x: datetime.strptime(x.get("collectionDate"), date_format) + ) + return data