Coverage for statistic/order.py: 97%
124 statements
« prev ^ index » next coverage.py v7.8.0, created at 2025-05-25 10:23 +0000
« prev ^ index » next coverage.py v7.8.0, created at 2025-05-25 10:23 +0000
1"""Order class for managing and processing orders.
2This class provides methods to handle order data, including
3calculating start and finish times, checking for specific conditions,
4and converting data types. It also maintains a count of the total
5number of orders created.
6"""
7from pprint import pprint
8# from data_drive.data_sql import get_newest_list_beton_or_lista
9import re
10import datetime
11from src.settings import Settings
14class Order:
16 count_ordres = 0
18 def __init__(
19 self, date_order, metres, times, firm, name, uwagi, przebieg, tel, wenz, pompa_dzwig
20 ):
22 self.date_order = date_order
23 self.metres = self.convert_to_float(metres)
24 self.times = times
25 self.firm = self.convert_to_string(firm)
26 self.name = self.convert_to_string(name)
27 self.uwagi = self.convert_to_string(uwagi)
28 self.przebieg = self.convert_to_string(przebieg)
29 self.tel = self.convert_to_string(self.tel_to_string(tel))
30 self.wenz = wenz
31 self.list_of_loads = []
32 self.cancellation = self.get_cancellation()
33 self.pompa_dzwig = self.check_pompa_dzwig(pompa_dzwig, self.metres)
35 self.list_of_courses = self.get_list_courses()
36 self.start_time = self.get_start_time()
37 self.finish_time = self.get_finish_time_and_form_list_times_of_loads()
38 self.it_is_zaprawa = self.check_zaprawa()
39 self.it_is_concret = self.check_concret()
40 self.reszta = self.get_reszta()
42 Order.count_ordres += 1
44 def tel_to_string(self, data):
45 """converts the phone number to a string and removes any unwanted characters.
47 Args:
48 data (any): the phone number from cell tel to be converted
49 Returns:
50 str: the converted phone number
51 """
52 if data:
53 if isinstance(data, float):
54 return str(int(data)).strip()
55 elif isinstance(data, int):
56 return str(data).strip()
57 elif isinstance(data, str):
58 return data.strip()
59 else:
60 return ""
61 else:
62 return ""
64 def convert_to_float(self, data):
65 """converts the data to a float.
66 If the data is None, it returns 0. If the data is a string, it tries to convert it to a float.
67 If the data is a float or int, it returns the data as a float.
68 If the data is a string that cannot be converted to a float, it returns 0.
70 Args:
71 data (any): raw data to be converted
73 Returns:
74 int or float: the converted data
75 """
76 if data:
77 if isinstance(data, float):
78 return abs(round(data, 1))
79 elif isinstance(data, int):
80 return abs(float(round(data, 1)))
81 else:
82 return 0.0
83 else:
84 return 0.0
86 def convert_to_string(self, data):
87 """converts the data to a string.
88 If the data is None, it returns an empty string.
89 If the data is a string, it strips any unwanted characters.
91 Args:
92 data (any): dta from cell to be converted
94 Returns:
95 str: the converted data
96 """
97 if not data:
98 return ""
99 try:
100 data = str(data)
101 data = re.sub(r"\s+", " ", data)
102 data = data.strip()
103 return data
104 except (TypeError, ValueError):
105 return ""
107 def get_list_courses(self):
108 """forms a list of courses based on the number of metres.
109 The list is formed by dividing the number of metres by 8.
111 Returns:
112 list: list of courses
113 """
115 if self.metres == 0:
116 return [0,]
118 # The number of courses equivalent to 8
119 base_value = int(self.metres // 8)
121 # A remainder of less than 8 meters
122 remainder = self.metres % 8
124 # Initializing a list with values equal to 8 meters
125 result = [
126 8.0,
127 ] * base_value
129 # if remainder less then 2 metrs
130 if remainder != 0 and base_value > 0 and remainder < 2:
131 # The lasct element is adjusted to be 1 less, and added this 1 metr to remainder
132 result[-1] -= 1
133 remainder += 1
135 result = result + [
136 round(remainder, 2),
137 ]
139 elif remainder != 0 and base_value > 0 and remainder >= 2:
140 # if remainder greater or equal 2 metrs, just added like a last element of list
141 result = result + [
142 round(remainder, 2),
143 ]
145 elif remainder != 0 and base_value == 0:
146 result = [
147 round(remainder, 2),
148 ]
150 return result
152 def get_start_time(self):
153 """calculates the start time of the order.
154 The start time is calculated by subtracting 30 minutes from the order time.
156 Returns:
157 datetime: the start time of the order
158 """
159 date_order = datetime.datetime.strptime(
160 self.date_order, "%d.%m.%Y").date()
161 data_time_order = datetime.datetime.combine(date_order, self.times)
163 return data_time_order - datetime.timedelta(minutes=Settings.travel_to_the_construction)
165 def get_finish_time_and_form_list_times_of_loads(self):
166 """calculates the finish time of the order.
167 The finish time is calculated by adding the shipping duration to the start time.
168 The shipping duration is calculated based on the number of courses and the type of pump or crane.
170 Returns:
171 datetime: the finish time of the order
172 """
173 shipping_duration = 0
175 if self.list_of_courses[0]:
176 self.list_of_loads += [self.start_time,]
177 else:
178 self.list_of_loads = []
180 for cours in self.list_of_courses[:-1]:
181 if self.pompa_dzwig: # if it's pompa
182 shipping_duration += cours * Settings.unloading_time_for_pomp
183 self.list_of_loads += [self.list_of_loads[-1] + datetime.timedelta(
184 minutes=cours * Settings.unloading_time_for_pomp),]
185 else:
186 shipping_duration += cours * Settings.unloading_time_for_crane # if it's crane
187 self.list_of_loads += [self.list_of_loads[-1] + datetime.timedelta(
188 minutes=cours * Settings.unloading_time_for_crane),]
190 return self.start_time + datetime.timedelta(minutes=shipping_duration)
192 def check_pompa_dzwig(self, pompa_dzwig, metres):
193 """ checks if the order is for a pump or crane.
194 If the order is for a pump, it returns True.
195 If the order is for a crane, it returns False.
197 Args:
198 pompa_dgwig (str): string keep infomation from excel about using pomp or
199 "" - if no use pomp
200 metres (float): the number of metres in the order
202 Returns:
203 bool: True if the order is for a pump, False if it's for a crane
204 """
205 if pompa_dzwig: # if it's pompa
206 data =self.convert_to_string(pompa_dzwig)
207 data = data.strip()
208 # todo remove in settings '501' "pompogrusz"
209 if data == '501':
210 return False
211 elif "pompogrusz" in data.lower() and metres <= 5.5:
212 self.cancellation = True
213 return True
214 return True
216 elif not pompa_dzwig and metres > 50:
217 return True
219 return False
221 def check_zaprawa(self):
222 """checks if the order is for zaprawa.
223 If the order is for zaprawa, it returns True.
225 Returns:
226 bool: True if the order is for zaprawa, False otherwise
227 """
228 if (
229 self.list_of_courses[0] < Settings.amount_of_zaprawa
230 and self.times < Settings.time_of_end_upload_zaprawa
231 and not re.search(Settings.names_dry_concret, self.name)
232 ):
233 return True
234 return False
236 def check_concret(self):
237 """checks if the order is for concret.
238 If the order is for concret, it returns True, not dry concret
240 Returns:
241 bool: True if the order is for concret, False otherwise
242 """
244 if re.search(Settings.names_dry_concret, self.name):
245 return False
246 return True
248 def get_reszta(self):
249 reszta = []
250 metres = self.metres
252 for cours in self.list_of_courses:
253 reszta.append(metres - cours)
254 metres -= cours
256 return reszta
258 def get_cancellation(self):
259 concat_uwagi = self.uwagi + self.przebieg
261 if "odwo" in concat_uwagi.lower():
262 return True
264 return False
267 @classmethod
268 def how_many(cls):
269 """Prints the current population."""
270 print("We have {:d} orders.".format(cls.count_ordres))
271 return "We have {:d} orders.".format(cls.count_ordres)
274if __name__ == "__main__":
275 pass
277 # # pprint(get_newest_list_beton_or_lista("beton", "03.02.2025")[5])
279 # # bud = Order(*get_newest_list_beton_or_lista("beton", "03.02.2025")[5])
280 # # bud1 = Order(*get_newest_list_beton_or_lista("beton", "03.02.2025")[9])
281 # # bud2 = Order(*get_newest_list_beton_or_lista("beton", "03.02.2025")[3])
282 # orders = {}
283 # count = 1
284 # date_order = "07.02.2025"
285 # for item in get_newest_list_beton_or_lista("beton", date_order, 'zawod'):
286 # orders[f"{count}bud"] = Order(date_order, *item)
287 # count += 1
289 # pprint(orders)
291 # df_bud = []
292 # for key_bud in orders.keys():
293 # bud = orders[key_bud]
294 # pprint(
295 # (
296 # bud.name,
297 # bud.metres,
298 # bud.times,
299 # bud.start_time,
300 # bud.finish_time,
301 # bud.list_of_loads,
302 # bud.it_is_zaprawa,
303 # bud.it_is_concret,
304 # bud.list_of_courses,
305 # bud.date_order,
306 # bud.count_ordres,
307 # )
308 # )
309 # df_bud.append({
310 # "name": bud.name,
311 # "metr": bud.metres,
312 # "time": bud.times,
313 # "start_time": bud.start_time,
314 # "finish_time": bud.finish_time,
315 # "list_of_loads": bud.list_of_loads,
316 # "it_is_zaprawa": bud.it_is_zaprawa,
317 # "it_is_concret": bud.it_is_concret,
318 # "list_of_courses": bud.list_of_courses,
319 # "date_order": bud.date_order,
320 # "date_order": bud.date_order,
321 # })