Exemple #1
0
 def formatted_date(self) -> str:
     return Date(self.date).format_date
Exemple #2
0
 def display_edit_delete(self) -> str:
     return "disabled" if current_user.role == Config.HOTEL and self.date < Date.previous_lock_in() else str()
Exemple #3
0
 def link_goto(self) -> str:
     return url_for("usage_manage", hotel_id=self.hotel.id, date=Date(self.goto_date.data).db_date,
                    timing=self.goto_timing.data)
Exemple #4
0
 def display_next(self) -> str:
     if not self.usages:
         return "disabled"
     end_date = min(self.hotel.contract[1], Date.next_lock_in())
     return "disabled" if (self.date == end_date and self.timing == Config.EVENING) or self.date > end_date \
         else str()
Exemple #5
0
 def validate_filename(self, filename: FileField):
     if self.form_type.data != self.UPLOAD:
         return
     file: FileStorage = filename.data
     if not secure_filename(file.filename):
         raise ValidationError("No file selected for upload")
     file_path = File(current_user.id, "csv").local_path
     file.save(file_path)
     with open(file_path) as csv_file:
         csv_reader = csv.DictReader(csv_file)
         columns = set(csv_reader.fieldnames)
         csv_reader = [row for row in csv_reader]
     if columns != {HDR.DATE, HDR.TIMING, HDR.NO_EVENT, HDR.CLIENT, HDR.MEAL, HDR.TYPE, HDR.BALLROOM, HDR.EVENT}:
         raise ValidationError("Invalid column names in the csv file")
     for row in csv_reader:
         usage = Usage()
         usage.hotel = self.hotel.name
         usage.city = self.hotel.city
         date = Date.from_dd_mmm_yyyy(row[HDR.DATE]).date
         if not date:
             self.add_errors(row, HDR.DATE)
             continue
         usage.set_date(date)
         if row[HDR.TIMING] not in Config.TIMINGS:
             self.add_errors(row, HDR.TIMING)
             continue
         usage.timing = row[HDR.TIMING]
         if row[HDR.NO_EVENT] == HDR.NO_EVENT:
             usage.no_event = True
             self.upload_data.append(usage)
             continue
         if not row[HDR.CLIENT]:
             self.add_errors(row, HDR.CLIENT)
             continue
         usage.client = row[HDR.CLIENT]
         if usage.timing == Config.MORNING:
             if row[HDR.MEAL] not in Config.MORNING_MEALS:
                 self.add_errors(row, HDR.MEAL)
                 continue
             usage.meals = [Config.BREAKFAST, Config.LUNCH] if row[HDR.MEAL] == Config.BREAKFAST_LUNCH \
                 else [row[HDR.MEAL]]
         else:
             if row[HDR.MEAL] not in Config.EVENING_MEALS:
                 self.add_errors(row, HDR.MEAL)
                 continue
             usage.meals = [Config.HI_TEA, Config.DINNER] if row[HDR.MEAL] == Config.HI_TEA_DINNER \
                 else [row[HDR.MEAL]]
         if row[HDR.TYPE] not in Config.EVENTS:
             self.add_errors(row, HDR.TYPE)
             continue
         usage.event_type = row[HDR.TYPE]
         ballrooms = [room.strip() for room in row[HDR.BALLROOM].split(",")]
         if any(room not in self.hotel.ballrooms for room in ballrooms):
             self.add_errors(row, HDR.BALLROOM)
             continue
         usage.ballrooms = ballrooms
         self.hotel.set_ballroom_used(ballrooms)
         usage.event_description = row[HDR.EVENT]
         self.upload_data.append(usage)
     if self.upload_errors:
         raise ValidationError("Field specific errors. Fields with red highlight have errors.")
     if not self.upload_data:
         raise ValidationError("There are no events in the csv file")
     self.upload_data.sort(key=lambda usage_item: usage_item.timing, reverse=True)
     self.upload_data.sort(key=lambda usage_item: usage_item.date)
     if current_user.role != Config.ADMIN:
         self._check_start_period_of_uploaded_file()
     last_date, lock_in, end_date = Date(self.upload_data[-1].date).date, Date.next_lock_in(), self.hotel.contract[1]
     if last_date > lock_in:
         raise ValidationError(f"End period ({Date(last_date).format_date}) cannot be greater than the "
                               f"next lock in period ({Date(lock_in).format_date})")
     if last_date > end_date:
         raise ValidationError(f"End period ({Date(last_date).format_date}) cannot be greater than the "
                               f"contract end date ({Date(end_date).format_date})")
     previous_date = None
     for date, date_usages in itertools.groupby(self.upload_data, key=lambda usage_item: usage_item.date):
         date = Date(date).date
         date_usages = list(date_usages)
         if not any(usage.timing == Config.MORNING for usage in date_usages):
             raise ValidationError(f"Date {Date(date).format_date} does not have {Config.MORNING} events")
         if not any(usage.timing == Config.EVENING for usage in date_usages):
             raise ValidationError(f"Date {Date(date).format_date} does not have {Config.EVENING} events")
         for timing, timing_usages in itertools.groupby(date_usages, key=lambda usage_item: usage_item.timing):
             seen = set()
             for usage in timing_usages:
                 if usage.client in seen:
                     raise ValidationError(f"Duplicate client name {usage.client} for the period "
                                           f"{Date(date).format_date} - {timing}")
                 seen.add(usage.client)
         if previous_date and (date - previous_date).days != 1:
             raise ValidationError(f"There are missing events between {Date(previous_date).format_date} and "
                                   f"{Date(date).format_date}")
         previous_date = date
     return
Exemple #6
0
 def _check_start_period_of_uploaded_file(self):
     first_date, first_timing = Date(self.upload_data[0].date).date, self.upload_data[0].timing
     next_date, next_timing = Usage.get_data_entry_date(self.hotel)
     if (first_date, first_timing) != (next_date, next_timing):
         raise ValidationError(f"Start period ({Date(first_date).format_date} - {first_timing}) does not match with "
                               f"the next data entry period ({Date(next_date).format_date} - {next_timing})")