Example #1
0
 def lookups(self, request, model_admin):
     return (
         ('active', ugt('active tasks')),
         ('sleeping', ugt('sleeping tasks')),
         ('blocked', ugt('blocked tasks')),
         ('delegated', ugt('delegated tasks')),
         ('completed', ugt('completed tasks')),
         ('trashed', ugt('trashed tasks')),
     )
Example #2
0
    def enviar_filas_disponiveis(self, filas, qrcode):

        button_list = [
            InlineKeyboardButton(
                fila['nome'],
                callback_data='ENTRAR_NA_FILA %(fila)s %(qrcode)s' % {
                    'fila': fila['id'],
                    'qrcode': qrcode.id
                }) for fila in filas
        ]
        reply_markup = InlineKeyboardMarkup(
            self._build_menu(button_list, n_cols=1))
        self.bot.send_message(
            self.user.telegram.chat_id,
            text=ugt("Por favor, selecionar a fila na que deseja entrar:"),
            reply_markup=reply_markup)
Example #3
0
            'connect_timeout': 10,
        },
    },
}


# Internationalization
# https://docs.djangoproject.com/en/2.2/topics/i18n/

LANGUAGE_CODE = 'en-us'

USE_I18N = True
USE_L10N = True

LANGUAGES = (
    ('en', ugt('English')),
    ('ru', ugt('Russian')),
)

LOCALE_PATHS = (
    'locale/',
)

USE_TZ = True
TIME_ZONE = 'UTC'


# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/2.2/howto/static-files/

STATIC_URL = '/static/'
Example #4
0
# Internationalization
# https://docs.djangoproject.com/en/3.1/topics/i18n/

LANGUAGE_CODE = "en-us"

TIME_ZONE = "UTC"

USE_I18N = True

USE_L10N = True

USE_TZ = True

LANGUAGES = (
    ("en", ugt("English")),
    ("ar", ugt("Arabic")),
)

STATICFILES_DIRS = (base_dir_join("static"),)

INSTALLED_APPS += ("drf_yasg",)

# drf_yasg
SWAGGER_SETTINGS = {
    "DEFAULT_INFO": "onlineBenevolent.urls.api_info",
    "REFETCH_SCHEMA_WITH_AUTH": True,
    "SECURITY_DEFINITIONS": {
        "api_key": {"type": "apiKey", "in": "header", "name": "Authorization"}
    },
}
Example #5
0
        "OPTIONS": {
            "connect_timeout": 10
        },
    },
}

# Internationalization
# https://docs.djangoproject.com/en/2.2/topics/i18n/

LANGUAGE_CODE = "en-us"

USE_I18N = True
USE_L10N = True

LANGUAGES = (
    ("en", ugt("English")),
    ("ru", ugt("Russian")),
)

LOCALE_PATHS = ("locale/", )

USE_TZ = True
TIME_ZONE = "UTC"

# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/2.2/howto/static-files/

STATIC_URL = "/static/"

STATICFILES_FINDERS = (
    "django.contrib.staticfiles.finders.FileSystemFinder",
Example #6
0
class Posto(models.Model):

    INATIVO = 0
    EM_PAUSA = 1
    ESPERANDO_CLIENTE = 2
    CLIENTE_CHAMADO = 3
    ATENDENDO = 4

    ESTADOS = (
        (INATIVO, ugt('Inativo')),
        (EM_PAUSA, ugt('Em pausa')),
        (ESPERANDO_CLIENTE, ugt('Esperando cliente')),
        (CLIENTE_CHAMADO, ugt('Cliente chamado')),
        (ATENDENDO, ugt('Atendendo')),
    )

    ESTADOS_DICT = dict(ESTADOS)

    nome = models.CharField(
        max_length=100,
        verbose_name=_('Nome'),
    )

    local = models.ForeignKey(Local,
                              verbose_name=_('Local'),
                              on_delete=models.CASCADE,
                              related_name='postos')

    fila = models.ForeignKey(
        Fila,
        verbose_name=_('Fila'),
        on_delete=models.PROTECT,
        related_name='postos',
    )

    funcionario = models.OneToOneField(Funcionario,
                                       verbose_name=_('Funcionario'),
                                       on_delete=models.PROTECT,
                                       null=True,
                                       blank=True,
                                       editable=False)

    turno_em_atencao = models.OneToOneField(
        Turno,
        verbose_name=_('Turno em atencao'),
        on_delete=models.PROTECT,
        null=True,
        blank=True,
    )

    estado = models.IntegerField(
        choices=ESTADOS,
        default=INATIVO,
    )

    class Meta:
        verbose_name = _("Posto")
        verbose_name_plural = _("Postos")
        permissions = (('atender_clientes',
                        'Pode ocupar um posto e atender os clientes.'), )

    def __str__(self):
        return '%s.%s' % (self.fila, self.nome)

    def notificar(self):
        if self.funcionario:
            self.funcionario.get_grupo().send({
                'text':
                json.dumps({
                    'message': 'POSTO',
                    'data': {
                        'posto': self.to_dict(),
                    }
                })
            })

    def get_grupo(self):
        return Group('posto-%s' % self.pk)

    def ocupar(self, funcionario):
        self.funcionario = funcionario
        self.estado = Posto.EM_PAUSA
        self.save()
        self.notificar()
        self.fila.notificar_turnos_ativos()

    def chamar_seguinte(self):
        self.estado = Posto.ESPERANDO_CLIENTE
        self.save()
        self.notificar()
        self.fila.avancar()

    def cancelar_chamado(self):
        self.estado = Posto.EM_PAUSA
        self.save()
        self.notificar()

    def chamar_cliente(self, turno):
        self.estado = Posto.CLIENTE_CHAMADO
        self.turno_em_atencao = turno
        self.save()
        turno.chamar_cliente()
        self.notificar()

    def atender(self):
        self.estado = Posto.ATENDENDO
        self.save()
        self.turno_em_atencao.atender()
        self.notificar()

    def indicar_ausencia(self):
        self.turno_em_atencao.indicar_ausencia()
        self.estado = Posto.EM_PAUSA
        self.turno_em_atencao = None
        self.save()
        self.notificar()

    def finalizar_atencao(self):
        self.turno_em_atencao.finalizar_atencao()
        self.estado = Posto.EM_PAUSA
        self.turno_em_atencao = None
        self.save()
        self.notificar()

    def desocupar(self):
        self.estado = Posto.INATIVO
        self.notificar()
        self.funcionario = None
        self.save()
        self.fila.notificar_turnos_ativos()

    def texto_estado(self):
        return Posto.ESTADOS_DICT[self.estado]

    def to_dict(self):
        posto_dict = model_to_dict(self)
        posto_dict['local'] = model_to_dict(self.local)
        posto_dict['fila'] = model_to_dict(self.fila)
        if self.turno_em_atencao:
            posto_dict['turno_em_atencao'] = model_to_dict(
                self.turno_em_atencao)
            posto_dict['turno_em_atencao']['cliente'] = {
                'name': self.turno_em_atencao.cliente.get_nome()
            }
        posto_dict['texto_estado'] = self.texto_estado()
        posto_dict['estado'] = self.estado
        posto_dict['funcionario'] = {'name': self.funcionario.username}
        return posto_dict
Example #7
0
class Turno(models.Model):

    objects = models.Manager()
    ativos = TurnoAtivoManager()
    na_fila = TurnoNaFilaManager()
    com_espera_gerada = TurnoComEsperaGeradaManager()

    INICIAL = 0
    NA_FILA = 1
    CANCELADO = 2
    CLIENTE_CHAMADO = 3
    NO_ATENDIMENTO = 4
    AUSENTE = 5
    ATENDIDO = 6

    ESTADOS_ATIVOS = [
        NA_FILA,
        CLIENTE_CHAMADO,
        NO_ATENDIMENTO,
    ]

    ESTADOS_ESPERA_GERADA = [
        AUSENTE,
        ATENDIDO,
    ]

    ESTADOS = (
        (INICIAL, ugt('Inicial')),
        (NA_FILA, ugt('Na Fila')),
        (CANCELADO, ugt('Cancelado')),
        (CLIENTE_CHAMADO, ugt('Ir no posto')),
        (NO_ATENDIMENTO, ugt('No Atendimento')),
        (AUSENTE, ugt('Ausente')),
        (ATENDIDO, ugt('Atendido')),
    )

    ESTADOS_DICT = dict(ESTADOS)

    fila = models.ForeignKey(
        Fila,
        verbose_name=_('Fila'),
        on_delete=models.PROTECT,
        related_name='turnos',
    )

    cliente = models.ForeignKey(
        Cliente,
        verbose_name=_('Cliente'),
        on_delete=models.PROTECT,
        related_name='turnos',
    )

    creation_date = models.DateTimeField(auto_now_add=True)

    last_modification = models.DateTimeField(auto_now=True)

    estado = models.IntegerField(choices=ESTADOS, default=NA_FILA)

    inicio_espera_date = models.DateTimeField(null=True, editable=False)
    fim_espera_date = models.DateTimeField(null=True, editable=False)

    def save(self, *args, **kwargs):
        if self.is_cliente_chamado() and self.inicio_espera_date is None:
            self.inicio_espera_date = TZ.now()
        if self.is_atendido() or self.is_ausente():
            if self.fim_espera_date is None:
                self.fim_espera_date = TZ.now()
        return super(Turno, self).save(*args, **kwargs)

    def is_atendido(self):
        return self.estado == Turno.ATENDIDO

    def is_ausente(self):
        return self.estado == Turno.AUSENTE

    def is_na_fila(self):
        return self.estado == Turno.NA_FILA

    def is_cliente_chamado(self):
        return self.estado == Turno.CLIENTE_CHAMADO

    def is_no_atendimento(self):
        return self.estado == Turno.NO_ATENDIMENTO

    def get_grupo(self):
        return PersistedGroup('turno-%s' % self.pk)

    def cancelar(self):
        self.estado = Turno.CANCELADO
        self.save()
        tg = self.get_grupo()
        fg = self.fila.get_grupo()
        for channel in [x for x in tg.channels]:
            tg.discard(channel)
            fg.discard(channel)
        self.notificar()

    def finalizar_atencao(self):
        self.estado = Turno.ATENDIDO
        self.save()
        self.notificar()

    def indicar_ausencia(self):
        self.estado = Turno.AUSENTE
        self.save()
        self.notificar()

    def atender(self):
        self.estado = Turno.NO_ATENDIMENTO
        self.save()
        self.notificar()

    def chamar_cliente(self):
        self.estado = Turno.CLIENTE_CHAMADO
        self.save()
        self.notificar()

    def get_posicao(self):
        if self.estado != Turno.NA_FILA:
            return 0
        i = 0
        for x in Turno.na_fila.filter(
                fila=self.fila).order_by('creation_date'):
            i = i + 1
            if self.pk == x.pk:
                break
        return i

    def estimar_tempo_espera(self):
        posicao = self.get_posicao()
        postos_ativos = max(
            [self.fila.postos.exclude(estado=Posto.INATIVO).count(), 1])
        return self.fila.media_espera * posicao / postos_ativos

    def estimar_tempo_espera_minutos(self):
        return int(self.estimar_tempo_espera() / 60)

    def texto_estado(self):
        return Turno.ESTADOS_DICT[self.estado]

    def to_dict(self):
        turno_dict = model_to_dict(self)
        turno_dict['fila'] = model_to_dict(self.fila)
        turno_dict['fila']['local'] = model_to_dict(self.fila.local)
        turno_dict['posicao'] = self.get_posicao()
        turno_dict['espera_estimada'] = self.estimar_tempo_espera_minutos()
        turno_dict['texto_estado'] = self.texto_estado()
        turno_dict['creation_date'] = str(self.creation_date)
        try:
            turno_dict['posto'] = model_to_dict(self.posto)
        except Posto.DoesNotExist:
            pass
        return turno_dict

    def notificar(self):
        if self.cliente:
            self.cliente.enviar_turno_ativo(self)
Example #8
0
    def enviar_turno(self, turno):

        if turno.is_na_fila():
            button_list = [
                InlineKeyboardButton(ugt('Sair da fila'),
                                     callback_data='SAIR_DA_FILA %(turno)s' % {
                                         'turno': turno.id,
                                     }),
                InlineKeyboardButton(ugt('Atualizar'),
                                     callback_data='GET_ESTADO')
            ]
            reply_markup = InlineKeyboardMarkup(
                self._build_menu(button_list, n_cols=1))
            self.bot.send_message(
                self.user.telegram.chat_id,
                text=ugt(
                    "Você esta na %(posicao)s° posição da fila %(fila)s.\nO tempo de espera aproximado é de %(espera)s minutos"
                    % {
                        'posicao': turno.get_posicao(),
                        'fila': turno.fila.nome,
                        'espera': turno.estimar_tempo_espera_minutos(),
                    }),
                reply_markup=reply_markup)
        elif turno.is_cliente_chamado():
            button_list = [
                InlineKeyboardButton(ugt('Sair da fila'),
                                     callback_data='SAIR_DA_FILA %(turno)s' % {
                                         'turno': turno.id,
                                     }),
                InlineKeyboardButton(ugt('Atualizar'),
                                     callback_data='GET_ESTADO')
            ]
            reply_markup = InlineKeyboardMarkup(
                self._build_menu(button_list, n_cols=1))
            self.bot.send_message(
                self.user.telegram.chat_id,
                text=ugt(
                    "Você foi chamado!\nPor favor ir no posto %(posto)s." %
                    {'posto': turno.posto.nome}),
                reply_markup=reply_markup)
        elif turno.is_no_atendimento():
            button_list = [
                InlineKeyboardButton(ugt('Atualizar'),
                                     callback_data='GET_ESTADO')
            ]
            reply_markup = InlineKeyboardMarkup(
                self._build_menu(button_list, n_cols=1))
            self.bot.send_message(
                self.user.telegram.chat_id,
                text=ugt("Você esta no atendimento do %(posto)s." %
                         {'posto': turno.posto.nome}),
                reply_markup=reply_markup)
        else:
            button_list = [
                InlineKeyboardButton(ugt('Entrar em outra fila'),
                                     callback_data='GET_ESTADO')
            ]
            reply_markup = InlineKeyboardMarkup(
                self._build_menu(button_list, n_cols=1))
            self.bot.send_message(
                self.user.telegram.chat_id,
                text=ugt("Seu turno ficou com estado %(estado)s" %
                         {'estado': turno.texto_estado()}),
                reply_markup=reply_markup)
Example #9
0
)

ROOT_URLCONF = "server.urls"

WSGI_APPLICATION = "server.wsgi.application"


# Internationalization
# https://docs.djangoproject.com/en/2.2/topics/i18n/

LANGUAGE_CODE = "en-us"

USE_I18N = True
USE_L10N = True

LANGUAGES = (("en", ugt("English")),)

LOCALE_PATHS = ("locale/",)

USE_TZ = True
TIME_ZONE = "UTC"


# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/2.2/howto/static-files/

STATIC_URL = "/static/"

STATICFILES_FINDERS = (
    "django.contrib.staticfiles.finders.FileSystemFinder",
    "django.contrib.staticfiles.finders.AppDirectoriesFinder",