-
Notifications
You must be signed in to change notification settings - Fork 2
/
CouponCategory.py
240 lines (218 loc) · 11 KB
/
CouponCategory.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
from typing import Union, List
from Helper import SYMBOLS, formatDateGerman, CouponType, formatPrice
from UtilsCouponsDB import Coupon, CouponSortMode, CouponSortModes
class CouponCategory:
""" Takes a list/dict of given coupons and creates a 'category' container of it containing easily accessible fields with useful information about it. """
def __init__(self, coupons: Union[CouponType, int, dict, List], title: Union[str, None] = None):
self.titleOverride = title
self.coupons = None
self.mainCouponType = None
self.couponTypes = set()
self.displayDescription = False # Display description for this category in bot menu?
self.expireDatetimeLowest = None
self.expireDatetimeHighest = None
self.numberofCouponsTotal = 0
self.numberofCouponsHidden = 0
self.numberofCouponsEatable = 0
self.numberofCouponsEatableWithPrice = 0
self.numberofCouponsNew = 0
self.numberofCouponsWithFriesAndDrink = 0
self.numberofVeggieCoupons = 0
self.totalPrice = 0
if isinstance(coupons, dict):
self.coupons = list(coupons.values())
elif isinstance(coupons, list):
self.coupons = coupons
if self.coupons is not None:
for coupon in self.coupons:
self.updateWithCouponInfo(coupon)
if len(self.couponTypes) == 1:
for first_item in self.couponTypes:
self.mainCouponType = first_item
break
else:
self.mainCouponType = None
else:
self.mainCouponType = coupons
if self.mainCouponType is None:
self.nameSingular = "Coupon"
self.namePlural = "Alle Coupons"
self.namePluralWithoutSymbol = "Alle Coupons"
self.description = "Coupons mehrerer Kategorien"
elif self.mainCouponType == CouponType.APP:
self.nameSingular = "App Coupon"
self.namePlural = "App Coupons"
self.namePluralWithoutSymbol = "App Coupons"
self.description = "Coupons aus der BK App"
elif self.mainCouponType == CouponType.PAPER:
self.nameSingular = "Papiercoupon"
self.namePlural = SYMBOLS.NEWSPAPER + "Papiercoupons"
self.namePluralWithoutSymbol = "Papiercoupons"
self.description = "Coupons der Papier Couponbögen"
elif self.mainCouponType == CouponType.PAPER_UNSAFE:
self.nameSingular = "Papiercoupon (unsafe)"
self.namePlural = SYMBOLS.NEWSPAPER + "Papiercoupons (unsafe)"
self.namePluralWithoutSymbol = "Papiercoupons (unsafe)"
self.description = "Coupons aus der \"Coupons2\" API, die keinem anderen Coupon-Typen zugewiesen werden konnten."
elif self.mainCouponType == CouponType.ONLINE_ONLY:
self.nameSingular = "Online Only"
self.namePlural = "Online only"
self.namePluralWithoutSymbol = "Online Only"
self.description = "Coupons, die mit hoher Wahrscheinlichkeit nur online oder am Terminal bestellbar sind"
elif self.mainCouponType == CouponType.ONLINE_ONLY_STORE_SPECIFIC:
self.nameSingular = "Online only (store specific)"
self.namePlural = "Online only (store specific)"
self.namePluralWithoutSymbol = "Online only (store specific)"
self.description = "Coupons, die nur in bestimmten# Filialen gültig sind"
elif self.mainCouponType == CouponType.SPECIAL:
self.nameSingular = "Special Coupon"
self.namePlural = SYMBOLS.GIFT + "Special Coupons"
self.namePluralWithoutSymbol = "Special Coupons"
self.description = "Diese Coupons sind evtl. nicht in allen Filialen einlösbar!"
elif self.mainCouponType == CouponType.PAYBACK:
self.nameSingular = "Payback Coupon"
self.namePlural = SYMBOLS.PARK + "ayback Coupons"
self.namePluralWithoutSymbol = "Payback Coupons"
self.description = "Payback Papiercoupons"
else:
self.nameSingular = "Unbekannt"
self.namePlural = "Unbekannt"
self.namePluralWithoutSymbol = "Unbekannt"
def getTotalPrice(self) -> float:
return self.totalPrice
def getNumberofCouponsEatableWithPrice(self) -> int:
return self.numberofCouponsEatableWithPrice
def getNumberofCouponsEatableWithoutPrice(self) -> int:
return self.numberofCouponsEatable - self.numberofCouponsEatableWithPrice
def setNumberofCouponsEatableWithPrice(self, newNumber: int):
self.numberofCouponsEatableWithPrice = newNumber
def setTotalPrice(self, newPrice: float):
self.totalPrice = newPrice
def isEatable(self) -> bool:
""" Typically all coupon categories except Payback coupons will return True here as they do contain at least one item that is considered 'eatable'. """
if self.numberofCouponsEatable > 0:
return True
else:
return False
def isVeggie(self):
""" Returns True if all coupons in this categorie are veggie. """
if len(self.couponTypes) == 1 and self.mainCouponType == CouponType.PAYBACK:
# Only Payback coupons in this category -> Technically veggie but logically not ;)
return False
elif self.numberofCouponsTotal > 0 and self.numberofCouponsTotal == self.numberofVeggieCoupons:
return True
else:
return False
def isEligibleForDuplicateRemoval(self):
if self.mainCouponType == CouponType.PAYBACK:
return False
else:
return True
def isEligableForSort(self):
if len(self.getSortModes()) > 1:
return True
else:
return False
def getSortModes(self) -> List:
""" Returns all SortModes which make sense for this set of coupons. """
if self.coupons is None:
return []
sortModes = []
if self.totalPrice > 0:
sortModes.append(CouponSortModes.PRICE)
sortModes.append(CouponSortModes.PRICE_DESCENDING)
if self.numberofCouponsTotal != self.numberofCouponsWithFriesAndDrink:
sortModes.append(CouponSortModes.MENU_PRICE)
if len(self.couponTypes) > 1:
sortModes.append(CouponSortModes.TYPE_MENU_PRICE)
return sortModes
def allowsSortMode(self, sortModeToCheckFor: CouponSortMode) -> bool:
""" Checks if desired sortMode is currently allowed. """
sortModes = self.getSortModes()
for possibleSortMode in sortModes:
if possibleSortMode == sortModeToCheckFor:
return True
return False
def getNextPossibleSortMode(self, sortMode: CouponSortMode) -> CouponSortMode:
possibleSortModes = self.getSortModes()
for possibleSortMode in possibleSortModes:
if possibleSortMode.getSortCode() > sortMode.getSortCode():
return possibleSortMode
# Fallback/Rollover to first sort
return possibleSortModes[0]
def getSortModeCode(self, desiredSortMode: CouponSortMode, fallbackSortMode: CouponSortMode) -> CouponSortMode:
if self.allowsSortMode(desiredSortMode):
return desiredSortMode
else:
return fallbackSortMode
def getCategoryInfoText(self) -> str:
if self.titleOverride is not None:
text = '<b>[{couponCount} Stück] {couponCategoryName}</b>'
couponCategoryName = self.titleOverride
else:
# Auto determine result
if self.mainCouponType == CouponType.APP and self.numberofCouponsTotal == self.numberofCouponsHidden:
# Only hidden App-coupons
text = '<b>[{couponCount} Stück] {couponCategoryName} versteckte</b>'
elif self.numberofCouponsWithFriesAndDrink == 0 and self.numberofCouponsEatable > 0:
text = '<b>[{couponCount} Stück] {couponCategoryName} ohne Menü</b>'
else:
text = '<b>[{couponCount} Stück] {couponCategoryName}</b>'
if self.numberofCouponsTotal == 1:
couponCategoryName = self.nameSingular
else:
couponCategoryName = self.namePluralWithoutSymbol
text = text.format(couponCount=self.numberofCouponsTotal, couponCategoryName=couponCategoryName)
if self.displayDescription and self.description is not None:
text += '\n' + self.description
text += '\n' + self.getExpireDateInfoText()
return text
def getExpireDateInfoText(self) -> str:
if self.expireDatetimeLowest is None or self.expireDatetimeHighest is None:
return "Gültig bis ??"
elif self.expireDatetimeLowest == self.expireDatetimeHighest:
return "Gültig bis " + formatDateGerman(self.expireDatetimeLowest)
else:
return "Gültig bis min " + formatDateGerman(self.expireDatetimeLowest) + " max " + formatDateGerman(self.expireDatetimeHighest)
def getPriceInfoText(self) -> Union[str, None]:
if self.getNumberofCouponsEatableWithPrice() == 0:
return None
text = "<b>Gesamtwert:</b> " + formatPrice(self.getTotalPrice())
if self.getNumberofCouponsEatableWithoutPrice() > 0:
text += "*\n* außer " + str(
self.getNumberofCouponsEatableWithoutPrice()) + " Coupons, deren Preis nicht bekannt ist."
return text
def updateWithCouponInfo(self, couponOrCouponList: Union[Coupon, List[Coupon]]):
""" Updates category with information of given Coupon(s). """
if isinstance(couponOrCouponList, Coupon):
couponList = [couponOrCouponList]
else:
couponList = couponOrCouponList
for coupon in couponList:
self.couponTypes.add(coupon.type)
self.numberofCouponsTotal += 1
if coupon.isHidden:
self.numberofCouponsHidden += 1
if coupon.isEatable():
self.numberofCouponsEatable += 1
if coupon.isNewCoupon():
self.numberofCouponsNew += 1
if coupon.isContainsFriesAndDrink():
self.numberofCouponsWithFriesAndDrink += 1
if coupon.isVeggie():
self.numberofVeggieCoupons += 1
# Update expire-date info
date = coupon.getExpireDatetime()
if self.expireDatetimeLowest is None and self.expireDatetimeHighest is None:
self.expireDatetimeLowest = date
self.expireDatetimeHighest = date
else:
if date < self.expireDatetimeLowest:
self.expireDatetimeLowest = date
elif date > self.expireDatetimeHighest:
self.expireDatetimeHighest = date
if coupon.getPrice() is not None:
self.setTotalPrice(self.getTotalPrice() + coupon.getPrice())
self.setNumberofCouponsEatableWithPrice(self.getNumberofCouponsEatableWithPrice() + 1)
# End of function
return