class Serial(db.Model): __tablename__ = "serials" id = db.Column(db.Integer, primary_key=True) number = db.Column(db.Integer) timestamp = db.Column(db.DateTime(), index=True, default=datetime.utcnow) date = db.Column(db.Date(), default=datetime.utcnow().date) name = db.Column(db.String(300), nullable=True) n = db.Column(db.Boolean) p = db.Column(db.Boolean) # stands for proccessed , which be modified after been processed pdt = db.Column(db.DateTime()) # Fix: adding pulled by feature to tickets pulledBy = db.Column(db.Integer) office_id = db.Column(db.Integer, db.ForeignKey('offices.id')) task_id = db.Column(db.Integer, db.ForeignKey('tasks.id')) def __init__(self, number=100, office_id=1, task_id=1, name=None, n=False, p=False, pulledBy=0): self.number = number self.office_id = office_id self.task_id = task_id self.name = name self.n = n # fixing mass use tickets multi operators conflict self.p = p self.pulledBy = pulledBy @property def task(self): return Task.query.filter_by(id=self.task_id).first() @property def office(self): return Office.query.filter_by(id=self.office_id).first()
class Serial(db.Model, TicketsMixin): __tablename__ = "serials" id = db.Column(db.Integer, primary_key=True) number = db.Column(db.Integer) timestamp = db.Column(db.DateTime(), index=True, default=datetime.utcnow) date = db.Column(db.Date(), default=datetime.utcnow().date) name = db.Column(db.String(300), nullable=True) n = db.Column(db.Boolean) p = db.Column(db.Boolean) # stands for proccessed , which be modified after been processed pdt = db.Column(db.DateTime()) # Fix: adding pulled by feature to tickets pulledBy = db.Column(db.Integer) on_hold = db.Column(db.Boolean, default=False) office_id = db.Column(db.Integer, db.ForeignKey('offices.id')) task_id = db.Column(db.Integer, db.ForeignKey('tasks.id')) def __init__(self, number=100, office_id=1, task_id=1, name=None, n=False, p=False, pulledBy=0): self.number = number self.office_id = office_id self.task_id = task_id self.name = name self.n = n # fixing mass use tickets multi operators conflict self.p = p self.pulledBy = pulledBy @property def task(self): return Task.query.filter_by(id=self.task_id).first() @property def office(self): return Office.query.filter_by(id=self.office_id).first() @property def puller_name(self): return User.get(self.pulledBy).name @classmethod def all_office_tickets(cls, office_id): ''' get tickets of the common task from other offices. Parameters ---------- office_id: int id of the office to retreive tickets for. Returns ------- Query of office tickets unionned with other offices tickets. ''' strict_pulling = Settings.get().strict_pulling office = Office.get(office_id) all_tickets = cls.query.filter(cls.office_id == office_id, cls.number != 100) if not strict_pulling: for task in office.tasks: other_office_tickets = cls.query.filter( and_(cls.task_id == task.id, cls.office_id != office_id)) if other_office_tickets.count(): all_tickets = all_tickets.union(other_office_tickets) return all_tickets.filter(Serial.number != 100)\ .order_by(Serial.p, Serial.timestamp.desc()) @classmethod def all_task_tickets(cls, office_id, task_id): ''' get tickets related to a given task and office. Parameters ---------- office_id: int id of the office that we're querying from. task_id: int id of the task we want to retrieve its tickets. Returns ------- Query of task tickets filterred based on `strict_pulling`. ''' strict_pulling = Settings.get().strict_pulling filter_parameters = {'office_id': office_id, 'task_id': task_id} if not strict_pulling: filter_parameters.pop('office_id') return cls.query.filter_by(**filter_parameters)\ .filter(cls.number != 100)\ .order_by(cls.p, cls.timestamp.desc()) @classmethod def get_last_pulled_ticket(cls, office_id=None): ''' get the last pulled ticket. Parameters ---------- office_id: int office's id to filter last tickets by. Returns ------- Last ticket pulled record. ''' last_ticket = cls.query.filter_by(p=True)\ .filter(cls.number != 100) if office_id: last_ticket = last_ticket.filter_by(office_id=office_id) return last_ticket.order_by(cls.pdt.desc())\ .first() @classmethod def get_waiting_list_tickets(cls, office_id=None, limit=9): ''' get list of waiting tickets to be processed next. Parameters ---------- office_id: int office's id to filter tickets by. limit: int number of ticket to limit the query to. Returns ------- List of waiting list tickets. ''' waiting_tickets = cls.query.filter_by(p=False)\ .filter(cls.number != 100) if office_id: waiting_tickets = waiting_tickets.filter( cls.office_id == office_id) return waiting_tickets.order_by(cls.pdt.desc())\ .limit(limit)\ .all() def pull(self, office_id): ''' Mark a ticket as pulled and do the dues. Parameters ---------- office_id: int id of the office from which the ticket is pulled. ''' self.p = True self.pdt = datetime.utcnow() self.pulledBy = getattr(current_user, 'id', None) self.office_id = office_id db.session.add(self) db.session.commit() def toggle_on_hold(self): ''' Toggle the ticket `on_hold` status. ''' self.on_hold = not self.on_hold db.session.add(self) db.session.commit()
class Serial(db.Model, TicketsMixin, Mixin): __tablename__ = "serials" query_class = SerialQuery STATUS_WAITING = TICKET_WAITING STATUS_PROCESSED = TICKET_PROCESSED STATUS_UNATTENDED = TICKET_UNATTENDED id = db.Column(db.Integer, primary_key=True) number = db.Column(db.Integer) timestamp = db.Column(db.DateTime(), index=True, default=datetime.utcnow) date = db.Column(db.Date(), default=datetime.utcnow().date) name = db.Column(db.String(300), nullable=True) n = db.Column(db.Boolean) p = db.Column(db.Boolean) # stands for proccessed , which be modified after been processed pdt = db.Column(db.DateTime()) # Fix: adding pulled by feature to tickets pulledBy = db.Column(db.Integer) on_hold = db.Column(db.Boolean, default=False) status = db.Column(db.String(10), default=TICKET_PROCESSED) office_id = db.Column(db.Integer, db.ForeignKey('offices.id')) task_id = db.Column(db.Integer, db.ForeignKey('tasks.id')) ORDERS = { TICKET_ORDER_NEWEST_PROCESSED: [p, timestamp.desc()], TICKET_ORDER_NEWEST: [timestamp.desc()], TICKET_ORDER_OLDEST_PROCESSED: [p, timestamp], TICKET_ORDER_OLDEST: [timestamp] } def __init__(self, number=100, office_id=1, task_id=1, name=None, n=False, p=False, pulledBy=0, status=TICKET_WAITING): self.number = number self.office_id = office_id self.task_id = task_id self.name = name self.n = n self.p = p self.pulledBy = pulledBy self.status = status @property def task(self): return Task.query.filter_by(id=self.task_id).first() @property def office(self): return Office.query.filter_by(id=self.office_id).first() @property def puller_name(self): return User.get(self.pulledBy).name @classmethod def all_clean(cls): return cls.query.filter(cls.number != 100) @classmethod def all_office_tickets(cls, office_id, desc=True, order=True): ''' get tickets of the common task from other offices. Parameters ---------- office_id: int id of the office to retreive tickets for. desc: bool if return it in desending oreder, default is True. Returns ------- Query of office tickets unionned with other offices tickets. ''' strict_pulling = Settings.get().strict_pulling office = Office.get(office_id) all_tickets = cls.query.filter(cls.office_id == office_id, cls.number != 100) if not strict_pulling: for task in office.tasks: other_office_tickets = cls.query.filter( and_(cls.task_id == task.id, cls.office_id != office_id)) if other_office_tickets.count(): all_tickets = all_tickets.union(other_office_tickets) all_tickets = all_tickets.filter(Serial.number != 100) if order: all_tickets = all_tickets.order_by( Serial.p, Serial.timestamp.desc() if desc else Serial.timestamp) return all_tickets @classmethod def all_task_tickets(cls, office_id, task_id, order=True): ''' get tickets related to a given task and office. Parameters ---------- office_id: int id of the office that we're querying from. task_id: int id of the task we want to retrieve its tickets. Returns ------- Query of task tickets filterred based on `strict_pulling`. ''' strict_pulling = Settings.get().strict_pulling filter_parameters = {'office_id': office_id, 'task_id': task_id} if not strict_pulling: filter_parameters.pop('office_id') tickets = cls.query.filter_by(**filter_parameters)\ .filter(cls.number != 100)\ if order: return tickets.order_by(cls.p, cls.timestamp.desc()) return tickets @classmethod def get_last_pulled_ticket(cls, office_id=None): ''' get the last pulled ticket. Parameters ---------- office_id: int office's id to filter last tickets by. Returns ------- Last ticket pulled record. ''' last_ticket = cls.query.filter_by(p=True)\ .filter(cls.number != 100) if office_id: last_ticket = last_ticket.filter_by(office_id=office_id) return last_ticket.order_by(cls.pdt.desc())\ .first() @classmethod def get_waiting_list_tickets(cls, office_id=None, limit=9): ''' get list of waiting tickets to be processed next. Parameters ---------- office_id: int office's id to filter tickets by. limit: int number of ticket to limit the query to. Returns ------- List of waiting list tickets. ''' waiting_tickets = cls.query.filter_by(p=False)\ .filter(cls.number != 100) if office_id: waiting_tickets = waiting_tickets.filter( cls.office_id == office_id) return waiting_tickets.order_by(cls.pdt.desc())\ .limit(limit)\ .all() @classmethod def get_processed_tickets(cls, office_id=None, limit=9, offset=0): '''get list of last processed tickets. Parameters ---------- office_id : int, optional office id to filter tickets for, by default None limit : int, optional limit the list of ticket to it, by default 9 ''' processed_tickets = cls.query.filter(cls.p == True, cls.number != 100) if office_id: processed_tickets = processed_tickets.filter( cls.office_id == office_id) return processed_tickets.order_by(cls.pdt.desc())\ .limit(limit)\ .offset(offset)\ .all() @classmethod def get_next_ticket(cls, task_id=None, office_id=None): strict_pulling = Settings.get().strict_pulling single_row = Settings.get().single_row task = Task.get(0 if single_row else task_id) office = Office.get(0 if single_row else office_id) global_pull = not bool(task_id and office_id) next_tickets = Serial.query.filter(Serial.number != 100, Serial.p != True, Serial.on_hold == False) next_ticket = None if not global_pull: next_ticket = next_tickets.filter(Serial.task_id == task.id) if strict_pulling: next_ticket = next_ticket.filter(Serial.office_id == office.id) next_ticket = (next_tickets if global_pull else next_ticket)\ .order_by(Serial.timestamp)\ .first() if single_row: current_ticket = office.tickets\ .order_by(Serial.timestamp.desc())\ .first() next_ticket = Serial( number=getattr(current_ticket, 'number', 100) + 1, office_id=office.id, task_id=task.id) db.session.add(next_ticket) db.session.commit() return next_ticket @classmethod def create_new_ticket(cls, task, office=None, name_or_number=None): '''Create a new registered or printed ticket. Parameters ---------- task: Task instance task to link the ticket to. office: Office instance office to link the ticket to, default is None. name_or_number: str ticket's name or number value. Returns ------- Serial, exception a new ticket printed or registered ticket. ''' from app.printer import assign, printit, printit_ar, print_ticket_cli, print_ticket_cli_ar windows = os.name == 'nt' touch_screen_stings = Touch_store.get() ticket_settings = Printer.get() settings = Settings.get() printed = not touch_screen_stings.n next_number = cls.query.order_by(cls.number.desc()).first().number + 1 office = office or task.least_tickets_office() ticket, exception = None, None if printed: tickets = Serial.all_office_tickets(office.id, desc=False) current_ticket = getattr(tickets.first(), 'number', None) common_arguments = (f'{office.prefix}.{next_number}', f'{office.prefix}{office.name}', tickets.count(), task.name, f'{office.prefix}.{current_ticket}') try: if windows or settings.lp_printing: (print_ticket_cli_ar if ticket_settings.langu == 'ar' else print_ticket_cli)(ticket_settings.name, *common_arguments, language=ticket_settings.langu, windows=windows, unix=not windows) else: printer = assign(ticket_settings.vendor, ticket_settings.product, ticket_settings.in_ep, ticket_settings.out_ep) (printit_ar if ticket_settings.langu == 'ar' else printit)( printer, *common_arguments, lang=ticket_settings.langu, scale=ticket_settings.scale) except Exception as e: exception = e if not exception: ticket = Serial(number=next_number, office_id=office.id, task_id=task.id, name=name_or_number, n=not printed) db.session.add(ticket) db.session.commit() return ticket, exception def pull(self, office_id=None, puller_id=None): ''' Mark a ticket as pulled and do the dues. Parameters ---------- office_id: int id of the office from which the ticket is pulled. ''' self.p = True self.pdt = datetime.utcnow() self.pulledBy = puller_id or getattr(current_user, 'id', None) self.status = TICKET_PROCESSED if office_id: self.office_id = office_id db.session.add(self) db.session.commit() def toggle_on_hold(self): ''' Toggle the ticket `on_hold` status. ''' self.on_hold = not self.on_hold db.session.add(self) db.session.commit()