Example #1
0
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()
Example #2
0
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()
Example #3
0
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()