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')), )
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)
'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/'
# 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"} }, }
"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",
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
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)
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)
) 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",