AnthonyBloomer / daftlistings

A library that enables programmatic interaction with daft.ie. Daft.ie has nationwide coverage and contains about 80% of the total available properties in Ireland.
MIT License
171 stars 54 forks source link

Facility SearchType Combos #121

Closed EricNeville closed 3 years ago

EricNeville commented 3 years ago

The facility options available for filtering are heavily dependent on the SearchType. In my local version I have facilities filtering added and functioning but without any checking related to this. I was planning to resolve this issue before pushing it. It will probably make sense to solve this in the same way as whatever ends up being done for the PropertyType SearchType combos issue (https://github.com/AnthonyBloomer/daftlistings/issues/108#issue-849665232), although there are more differences in the available facilities across SearchType than there is in PropertyType. The facilities values by SearchType are as follows:

Buying Facilities:

"value":"alarm"
"value":"gas-fired-central-heating"
"value":"oil-fired-central-heating"
"value":"parking"
"value":"wheelchair-access"
"value":"wired-for-cable-television"

Renting Facilities:

"value":"alarm"
"value":"cable-television"
"value":"dishwasher"
"value":"garden-patio-balcony"
"value":"central-heating"
"value":"internet"
"value":"microwave"
"value":"parking"
"value":"pets-allowed"
"value":"smoking"
"value":"serviced-property"
"value":"dryer"
"value":"washing-machine"
"value":"wheelchair-access"

Share Facilities:

"value":"alarm"
"value":"cable-television"
"value":"dishwasher"
"value":"ensuite"
"value":"garden-patio-balcony"
"value":"central-heating"
"value":"internet"
"value":"microwave"
"value":"parking"
"value":"pets-allowed"
"value":"serviced-property"
"value":"smoking"
"value":"dryer"
"value":"washing-machine"
"value":"wheelchair-access"

New Homes Facilities:

None

Commerical Facilities:

"value":"alarm"
"value":"cat-5-cabling"
"value":"cat-6-data-cabling"
"value":"kitchen-area"
"value":"meeting-rooms"
"value":"reception"
"value":"parking"
"value":"phone-lines"
"value":"toilets"
sdfordham commented 3 years ago

This logic should be in the enum imo. To avoid having to have a separate facilities class for each case, I would suggest something like this:

class FacilityEnum(enum.Enum):
    @property
    def post_value(self):
        return self.value[0]

    @property
    def valid_types(self):
        return self.value[1]

class Facilities(FacilityEnum):
    ALARM = ("alarm", [SearchType.RESIDENTIAL_RENT,
                       SearchType.RESIDENTIAL_SALE,
                       ...])
    CENTRAL_HEATING_GAS = ("gas-fired-central-heating", [SearchType.RESIDENTIAL_RENT,
                                                         SearchType.RESIDENTIAL_SALE,
                                                         ...])
    ...

class Daft:
    ...

    def set_facilities(self, facilities: list[Facilities]):
        for f in facilities:
            if self.section in [s.value for s in f.valid_types]:
                self._add_facility(f.post_value)

There may be a smarter way of doing this @AnthonyBloomer

EricNeville commented 3 years ago

Do you think it should be written to expect a list of facilities as you have above? That seems to make sense from the point of view of someone potentially wanting to search for a few facilities. However up until this point for the sake of consistency with other search parameters I had it adding one facility at a time to the search. For example adding property types works that way too, even though someone might want to add more than one property type to the search.

sdfordham commented 3 years ago

Actually it is possible to overwrite the value property so this is probably better to keep consistent with the other enums:

import enum

class Facilities(enum.Enum):
    def __new__(cls, *args, **kwargs):
        obj = object.__new__(cls)
        obj._value_ = args[0]
        return obj

    def __init__(self, _, valid_types):
        self.valid_types = valid_types

    ALARM = "alarm", [SearchType.RESIDENTIAL_RENT,
                      SearchType.RESIDENTIAL_SALE]

print(Facilities.ALARM.value)
print(Facilities.ALARM.valid_types)

Output:

alarm
[<SearchType.RESIDENTIAL_RENT: 'residential-to-rent'>, <SearchType.RESIDENTIAL_SALE: 'residential-for-sale'>]