From 9f153b273f50b124ef924c073b32997ebcf8e24b Mon Sep 17 00:00:00 2001 From: victor-yghor Date: Sat, 14 Jun 2025 18:19:37 -0300 Subject: [PATCH 01/26] put the acessarServicos.feature --- .../sbpc/botpcd/service/AttendanceService.kt | 17 ++-- .../sbpc/botpcd/service/PWDFlowService.kt | 5 +- .../ufrpe/sbpc/botpcd/acessarServicos.feature | 90 +++++++++++++++++++ .../sbpc/botpcd/mudarStatusAtendente.feature | 3 +- 4 files changed, 105 insertions(+), 10 deletions(-) create mode 100644 src/test/resources/ufrpe/sbpc/botpcd/acessarServicos.feature diff --git a/src/main/kotlin/ufrpe/sbpc/botpcd/service/AttendanceService.kt b/src/main/kotlin/ufrpe/sbpc/botpcd/service/AttendanceService.kt index e1b0acd..8c0645a 100644 --- a/src/main/kotlin/ufrpe/sbpc/botpcd/service/AttendanceService.kt +++ b/src/main/kotlin/ufrpe/sbpc/botpcd/service/AttendanceService.kt @@ -31,7 +31,16 @@ class AttendanceService( private val committeeMemberRepository: CommitteeMemberRepository, private val messageExchangeRepository: MessageExchangeRepository, ) { + val awaitServiceMessage = "No momento não há atendentes disponíveis. Por favor, aguarde na fila de espera e retornaremos assim que possível." + fun sendWaitListMessage(botNumber: String, pwd: PWD) { + whatsappService.sendMessage( + botNumber, + pwd.phoneNumber, + awaitServiceMessage + ) + } val logger: Logger = LoggerFactory.getLogger(AttendanceService::class.java) + fun sendServices(botNumber: String, pwd: PWD) { whatsappService.sendMessage(botNumber, pwd.phoneNumber, createSendServicesMessage(pwd.disabilities.first(), pwd)) } @@ -168,12 +177,4 @@ $message """.trimIndent() ) } - -fun sendWaitListMessage(botNumber: String, pwd: PWD) { - whatsappService.sendMessage( - botNumber, - pwd.phoneNumber, - "No momento não há atendentes disponíveis. Por favor, aguarde na fila de espera e retornaremos assim que possível." - ) -} } diff --git a/src/main/kotlin/ufrpe/sbpc/botpcd/service/PWDFlowService.kt b/src/main/kotlin/ufrpe/sbpc/botpcd/service/PWDFlowService.kt index d0c298a..c30ef5f 100644 --- a/src/main/kotlin/ufrpe/sbpc/botpcd/service/PWDFlowService.kt +++ b/src/main/kotlin/ufrpe/sbpc/botpcd/service/PWDFlowService.kt @@ -34,7 +34,10 @@ class PWDFlowService( attendanceService.sendServices(botNumber, pwd) } isChoosingService(lastBotMessage, pwd) -> { - if (isValidService(message, disability)) { + val requestAttendancePWD = attendanceRepository.findRequestAttendanceOfPwd(pwd) + if(requestAttendancePWD != null) { + attendanceService.directToAvailableAttendant(botNumber, pwd, requestAttendancePWD.serviceType) + } else if (isValidService(message, disability)) { val service = ServiceType.getServicesByDisability(disability)[message.toInt() - 1] attendanceService.startAttendance(pwd = pwd, botNumber = botNumber, service = service) } else { diff --git a/src/test/resources/ufrpe/sbpc/botpcd/acessarServicos.feature b/src/test/resources/ufrpe/sbpc/botpcd/acessarServicos.feature new file mode 100644 index 0000000..4ab45e7 --- /dev/null +++ b/src/test/resources/ufrpe/sbpc/botpcd/acessarServicos.feature @@ -0,0 +1,90 @@ +# language: pt +Funcionalidade: Acessar serviços de assistência + Como um PCD, quero poder acessar os serviços que estão disponíveis para o meu tipo de deficiência, para que eu consiga aproveitar o evento da SBPC. + + Esquema do Cenário Listar serviços de acordo com meu tipo de deficiência + Quando PCD com a deficiência de "" mandar qualquer mensagem + Entao PCD receberá mensagem de opcções de serviço "" de acordo com a deficiência "" + + Exemplos: + | adjetivo_da_deficiencia | opcções_de_serviço | + | um pessoa surda | informações em Libras,atividade com interpretação em Libras | + | mobilidade reduzida | ajuda na mobilidade,transporte para deslocamento no evento | + | deficiente físico | ajuda na mobilidade,ajuda com alimentação e higiene,transporte para deslocamento no evento | + | uma pessoa cega | ajuda na mobilidade,programação com audiodescrição | + | neurodivergente | suporte para pessoas neurodivergentes | + | uma pessoa surdocega | guia-intérprete | + + Esquema do Cenário Direcionar para o atendente(monitor ou membro da comissão) + Dado bot enviou a mensagem de opção de serviço + E existe atendente disponível para o "" + Quando PCD envia a mensagem "" + Entao bot vai direcionar para o disponível no momento + + Exemplos: + | servico_desejado | tipo_de_atendente | + | Informações em Libras | monitor | + | Intérprete de Libras | membro da comissão | + | Assistência mobilidade | monitor | + | carro | membro da comissão | + | Higiene e Nutrição | membro da comissão | + | Audiodescrição | membro da comissão | + | Apoio Neurodivergente | monitor | + | Guia-intérprete | membro da comissão | + + Regra: PCD precisa receber mensagem informando que ele está na fila de espera + Cenário de Fundo: PCD recebeu a mensagem "" + E não tem atendente disponível + + Esquema do Cenário: PCD entra na fila de espera + Quando PCD envia mensagem "" + Entao PCD receberá mensagem "No momento não há atendentes disponíveis. Por favor, aguarde na fila de espera e retornaremos assim que possível." + Exemplos: + | servico_desejado | | + | Informações em Libras | monitor | + | Intérprete de Libras | membro da comissão | + | Assistência mobilidade | monitor | + | carro | membro da comissão | + | Higiene e Nutrição | membro da comissão | + | Audiodescrição | membro da comissão | + | Apoio Neurodivergente | monitor | + | Guia-intérprete | membro da comissão | + + Cenário: PCD está na fila de espera e manda mensagem novamente + Dado PCD possuia serviço requisitado que ainda não foi iniciado + Quando PCD mandar qualquer mensagem + Então PCD receberá mensagem "No momento não há atendentes disponíveis. Por favor, aguarde na fila de espera e retornaremos assim que possível." + + + Cenário: Bot direciona mensagem do PCD para o atendente correto + Dado Atendente aceitou o atendimento do PCD + Quando pcd envia qualquer mensagem para o bot + Então o Atendente deve receber a mensagem do PCD contendo o nome do PCD + E nemhum outro Atendente ou PCD deve receber a mesma mensagem + + Cenário: Bot direciona mensagem do atendente para o PCD correto + Dado que o Atendente aceitou o atendimento do PCD + Quando atendente envia uma mensagem para o bot + Então PCD deve receber a mensagem do Atendente contendo nome do atendente + E nemhum outro PCD ou Atendente deve receber a mesma mensagem + + Cenario: Avisar que o atendimento foi encerrado + Dado atendente estava em atendimento com um pcd + Quando atendente encerrou o atendimento + Entao pcd receberá mensagem "Atendimento Encerrado" + + Esquema do Cenário: Atendete quando entra no estado disponível é direcionado para o pcd + Dado pcd que solicitou estava na fila de espera + Quando atendente do muda para o estado disponível + Entao atendente do será direcionado para o pcd + + Exemplos: + | tipo_de_servico | tipo_de_atendente | + | Libras | MONITOR | + | LibrasInterpreter | COMMITTEE_MEMBER | + | Mobility | MONITOR | + | AudioDescription | COMMITTEE_MEMBER | + | NeurodivergentSupport | MONITOR | + | GuideInterpreter | COMMITTEE_MEMBER | + | HygieneAndNutrition | COMMITTEE_MEMBER | + | Car | COMMITTEE_MEMBER | diff --git a/src/test/resources/ufrpe/sbpc/botpcd/mudarStatusAtendente.feature b/src/test/resources/ufrpe/sbpc/botpcd/mudarStatusAtendente.feature index e9d7bad..9efd43f 100644 --- a/src/test/resources/ufrpe/sbpc/botpcd/mudarStatusAtendente.feature +++ b/src/test/resources/ufrpe/sbpc/botpcd/mudarStatusAtendente.feature @@ -43,4 +43,5 @@ Funcionalidade: Mudar status do Atendente (Monitor ou Membro da Comissão) | Membro da Comissão | AVAILABLE | "1" | UNAVAILABLE | *BotPCD:*\n Seu status foi atualizado para Indisponível. | | Membro da Comissão | UNAVAILABLE | "1" | AVAILABLE | *BotPCD:*\n Seu status foi atualizado para Disponível. | | Membro da Comissão | BUSY | "1" | AVAILABLE | *BotPCD:*\n Atendimento encerrado. Seu status foi atualizado para Disponível. | - | Membro da Comissão | BUSY | "2" | UNAVAILABLE | *BotPCD:*\n Atendimento encerrado. Seu status foi atualizado para Indisponível. | \ No newline at end of file + | Membro da Comissão | BUSY | "2" | UNAVAILABLE | *BotPCD:*\n Atendimento encerrado. Seu status foi atualizado para Indisponível. | + | Membro da Comissão | BUSY | "cancelar" | BUSY | *BotPCD:*\n Você continua em atendimento. | \ No newline at end of file From 4dce5e5c3fdc1a7b22312dfd85ae90819a86ba7e Mon Sep 17 00:00:00 2001 From: victor-yghor Date: Sat, 14 Jun 2025 19:14:33 -0300 Subject: [PATCH 02/26] improve the testes --- .../kotlin/ufrpe/sbpc/botpcd/entity/PWD.kt | 2 +- .../ufrpe/sbpc/botpcd/StepDefinitions.kt | 28 +++++++++++++++++-- .../ufrpe/sbpc/botpcd/acessarServicos.feature | 14 +++++----- .../ufrpe/sbpc/botpcd/registerPCD.feature | 2 +- 4 files changed, 34 insertions(+), 12 deletions(-) diff --git a/src/main/kotlin/ufrpe/sbpc/botpcd/entity/PWD.kt b/src/main/kotlin/ufrpe/sbpc/botpcd/entity/PWD.kt index e082ed4..c8657f4 100644 --- a/src/main/kotlin/ufrpe/sbpc/botpcd/entity/PWD.kt +++ b/src/main/kotlin/ufrpe/sbpc/botpcd/entity/PWD.kt @@ -27,5 +27,5 @@ class PWD( @CollectionTable(name = "tb_pwd_disabilities", joinColumns = [JoinColumn(name = "pwd_id")]) @Column(name = "disability") @Enumerated(EnumType.STRING) - var disabilities: MutableSet = mutableSetOf() + var disabilities: Set = setOf() ): User(name = name, phoneNumber = phoneNumber) \ No newline at end of file diff --git a/src/test/kotlin/ufrpe/sbpc/botpcd/StepDefinitions.kt b/src/test/kotlin/ufrpe/sbpc/botpcd/StepDefinitions.kt index 42e8ef6..c0f82db 100644 --- a/src/test/kotlin/ufrpe/sbpc/botpcd/StepDefinitions.kt +++ b/src/test/kotlin/ufrpe/sbpc/botpcd/StepDefinitions.kt @@ -52,6 +52,9 @@ class StepDefinitions( private val numberUserNotRegister: String = "558187654321" private val currentTestAttendantPhoneNumber: String = "5581999999901" // Número fixo para o atendente em teste private val pwdInAttendancePhoneNumberForAttendantChangeStatus = "558179654321" + private val pwdAcessarServicesPhoneNumber = "551965741234" + private val possibleItialsMessages = mutableListOf("Oi", "Olá", "Bom dia", "Boa noite", "Boa Tarde", "teste") + val logger: Logger = LoggerFactory.getLogger(StepDefinitions::class.java) @Dado("usuário recebeu mensagem {string}") @@ -92,6 +95,25 @@ class StepDefinitions( userSendMessage(mensagemEnviada, numberUserNotRegister) } + @Quando("PCD {string} mandar qualquer mensagem") + fun `PCD mandar qualquer mensagem`(adjetivoPCD: String) { + val message = possibleItialsMessages.random() + val pwd = createIfNotExistsPWDWithDisability(adjetivoPCD, pwdAcessarServicesPhoneNumber) + userSendMessage(message, pwd.phoneNumber) + } + + fun createIfNotExistsPWDWithDisability(adjetivoPCD: String, pwdPhoneNumber: String): PWD { + var pwd = pwdRepository.findByPhoneNumber(pwdPhoneNumber) + val disability = Disability.getByAdjective(adjetivoPCD) + if(pwd == null) { + return pwdRepository.save(PWD(name=adjetivoPCD, phoneNumber = pwdPhoneNumber, disabilities = mutableSetOf(disability))) + } + if(pwd.disabilities.first() != disability) { + pwd.disabilities = mutableSetOf(disability) + pwdRepository.save(pwd) + } + return pwd + } @Entao("bot registrará que usuário tem ou possui {string}") fun `bot registra deficiencia do usuário`(deficienciaAdjtivo: String) { val pwd = pwdRepository.findByPhoneNumberWithDisabilities(numberUserNotRegister)!! @@ -124,10 +146,10 @@ class StepDefinitions( ) } - @Entao("bot enviará opcções de serviço {string} de acordo com a deficiência {string} do pcd") + @Entao("{string} PCD receberá mensagem de opcções de serviço {string}") fun `bot enviará opcçoes de seviço de acordo com a deficiência do pcd`( - opcoesDeServico: String, - tipoDeDeficiencia: String + tipoDeDeficiencia: String, + opcoesDeServico: String ) { val ultimaMensagem = messageExchangeRepository.lastExchangeMessage( toPhoneNumber = numberUserNotRegister, diff --git a/src/test/resources/ufrpe/sbpc/botpcd/acessarServicos.feature b/src/test/resources/ufrpe/sbpc/botpcd/acessarServicos.feature index 4ab45e7..14e3ddc 100644 --- a/src/test/resources/ufrpe/sbpc/botpcd/acessarServicos.feature +++ b/src/test/resources/ufrpe/sbpc/botpcd/acessarServicos.feature @@ -3,8 +3,8 @@ Funcionalidade: Acessar serviços de assistência Como um PCD, quero poder acessar os serviços que estão disponíveis para o meu tipo de deficiência, para que eu consiga aproveitar o evento da SBPC. Esquema do Cenário Listar serviços de acordo com meu tipo de deficiência - Quando PCD com a deficiência de "" mandar qualquer mensagem - Entao PCD receberá mensagem de opcções de serviço "" de acordo com a deficiência "" + Quando PCD "" mandar qualquer mensagem + Entao "" PCD receberá mensagem de opcções de serviço "" Exemplos: | adjetivo_da_deficiencia | opcções_de_serviço | @@ -16,10 +16,10 @@ Funcionalidade: Acessar serviços de assistência | uma pessoa surdocega | guia-intérprete | Esquema do Cenário Direcionar para o atendente(monitor ou membro da comissão) - Dado bot enviou a mensagem de opção de serviço - E existe atendente disponível para o "" - Quando PCD envia a mensagem "" - Entao bot vai direcionar para o disponível no momento + Dado "" recebeu mensagem de opcções de serviço + E atendente que se chama "" está disponível para o "" + Quando "" PCD envia a mensagem "" + Entao "" PCD receberá mensagem O monitor "" irá realizar seu atendimento Exemplos: | servico_desejado | tipo_de_atendente | @@ -33,7 +33,7 @@ Funcionalidade: Acessar serviços de assistência | Guia-intérprete | membro da comissão | Regra: PCD precisa receber mensagem informando que ele está na fila de espera - Cenário de Fundo: PCD recebeu a mensagem "" + Cenário de Fundo: Dado que PCD recebeu a mensagem "" E não tem atendente disponível Esquema do Cenário: PCD entra na fila de espera diff --git a/src/test/resources/ufrpe/sbpc/botpcd/registerPCD.feature b/src/test/resources/ufrpe/sbpc/botpcd/registerPCD.feature index ac08283..963ff57 100644 --- a/src/test/resources/ufrpe/sbpc/botpcd/registerPCD.feature +++ b/src/test/resources/ufrpe/sbpc/botpcd/registerPCD.feature @@ -78,7 +78,7 @@ Olá, qual sua deficiência? E usuário possui deficiência cadastrada de "" Quando usuário envia mensagem "João Victor" Entao A penúltima mensagem recebida pelo usuário será "Cadastro realizado." - E bot enviará opcções de serviço "" de acordo com a deficiência "" do pcd + E "" PCD receberá mensagem de opcções de serviço "" E bot salvará o nome do usuário "João Victor" Exemplos: From 5f272a3869b0d6cbcf2623056d3c1dcbc72764ec Mon Sep 17 00:00:00 2001 From: victor-yghor Date: Sat, 14 Jun 2025 19:33:39 -0300 Subject: [PATCH 03/26] Consertar o bug da fila de espera --- .../kotlin/ufrpe/sbpc/botpcd/service/PWDFlowService.kt | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/main/kotlin/ufrpe/sbpc/botpcd/service/PWDFlowService.kt b/src/main/kotlin/ufrpe/sbpc/botpcd/service/PWDFlowService.kt index c30ef5f..f095a64 100644 --- a/src/main/kotlin/ufrpe/sbpc/botpcd/service/PWDFlowService.kt +++ b/src/main/kotlin/ufrpe/sbpc/botpcd/service/PWDFlowService.kt @@ -27,17 +27,18 @@ class PWDFlowService( ) { val disability = pwd.disabilities.first() val attendance = attendanceRepository.findStartedAttendanceOfPwd(pwd) + val requestAttendancePWD = attendanceRepository.findRequestAttendanceOfPwd(pwd) when { + requestAttendancePWD != null -> { + attendanceService.sendWaitListMessage(botNumber, pwd) + } isRegisteringName(lastBotMessage, pwd) -> { registerPWDService.registerName(pwd, message) whatsappService.sendMessage(botNumber, phoneNumber, "Cadastro realizado.") attendanceService.sendServices(botNumber, pwd) } isChoosingService(lastBotMessage, pwd) -> { - val requestAttendancePWD = attendanceRepository.findRequestAttendanceOfPwd(pwd) - if(requestAttendancePWD != null) { - attendanceService.directToAvailableAttendant(botNumber, pwd, requestAttendancePWD.serviceType) - } else if (isValidService(message, disability)) { + if (isValidService(message, disability)) { val service = ServiceType.getServicesByDisability(disability)[message.toInt() - 1] attendanceService.startAttendance(pwd = pwd, botNumber = botNumber, service = service) } else { From 22467e6fe86ad585aff03b03b371a23402af7c7a Mon Sep 17 00:00:00 2001 From: "Emmanuel N. C. Brito" Date: Sat, 14 Jun 2025 19:58:46 -0300 Subject: [PATCH 04/26] Add restriction to send message if receive a user message in less than 24 hours --- .../sbpc/botpcd/service/WhatsappService.kt | 27 +++++++++++++------ 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/src/main/kotlin/ufrpe/sbpc/botpcd/service/WhatsappService.kt b/src/main/kotlin/ufrpe/sbpc/botpcd/service/WhatsappService.kt index ae299bf..e9b6522 100644 --- a/src/main/kotlin/ufrpe/sbpc/botpcd/service/WhatsappService.kt +++ b/src/main/kotlin/ufrpe/sbpc/botpcd/service/WhatsappService.kt @@ -1,10 +1,11 @@ package ufrpe.sbpc.botpcd.service +import java.time.LocalDateTime +import org.springframework.stereotype.Service import com.whatsapp.api.domain.messages.Message +import ufrpe.sbpc.botpcd.entity.MessageExchange import com.whatsapp.api.domain.messages.TextMessage import com.whatsapp.api.impl.WhatsappBusinessCloudApi -import org.springframework.stereotype.Service -import ufrpe.sbpc.botpcd.entity.MessageExchange import ufrpe.sbpc.botpcd.repository.MessageExchangeRepository @@ -13,17 +14,27 @@ class WhatsappService( private val cloudApi: WhatsappBusinessCloudApi, private val messageExchangeRepository: MessageExchangeRepository ) { - fun sendMessage(botNumber: String, destinyNumberID: String, msg: String, author: String = "") { - val msg = if (author != "") "*${author}:*\n ${msg}" else msg + fun sendMessage(botNumber: String, destinyNumberID: String, msg: String, author: String = "") { + val text = if (author != "") "*${author}:*\n ${msg}" else msg val message = Message.MessageBuilder.builder() .setTo(destinyNumberID) - .buildTextMessage(TextMessage().setBody(msg)) - cloudApi.sendMessage(botNumber, message) + .buildTextMessage(TextMessage().setBody(text)) - messageExchangeRepository.save(MessageExchange(fromPhoneNumber = botNumber, toPhoneNumber = destinyNumberID, message = msg)) - } + val lastMessageTime = messageExchangeRepository.lastExchangeMessage( + fromPhoneNumber = destinyNumberID, + toPhoneNumber = botNumber + )?.createAt ?: LocalDateTime.now().minusHours(25) + if (LocalDateTime.now().minusHours(24) < lastMessageTime) { + cloudApi.sendMessage(botNumber, message) + + messageExchangeRepository.save(MessageExchange( + fromPhoneNumber = botNumber, + toPhoneNumber = destinyNumberID, + message = text)) + } + } } From c1cce57666d32dc198ff78c30645aa04c580d176 Mon Sep 17 00:00:00 2001 From: victor-yghor Date: Sat, 14 Jun 2025 21:10:51 -0300 Subject: [PATCH 05/26] Redirect when the committee member is avaliable --- .../ufrpe/sbpc/botpcd/entity/ServiceType.kt | 7 +- .../botpcd/repository/AttendanceRepository.kt | 3 +- .../sbpc/botpcd/service/AttendanceService.kt | 175 ++++++++++++++++- .../botpcd/service/AttendantFlowService.kt | 7 +- .../botpcd/service/AttendantStatusService.kt | 177 ------------------ .../botpcd/service/FirstContactService.kt | 1 - .../ufrpe/sbpc/botpcd/service/QueueService.kt | 3 +- .../ufrpe/sbpc/botpcd/StepDefinitions.kt | 8 +- 8 files changed, 189 insertions(+), 192 deletions(-) delete mode 100644 src/main/kotlin/ufrpe/sbpc/botpcd/service/AttendantStatusService.kt diff --git a/src/main/kotlin/ufrpe/sbpc/botpcd/entity/ServiceType.kt b/src/main/kotlin/ufrpe/sbpc/botpcd/entity/ServiceType.kt index 93b54a4..605c0b9 100644 --- a/src/main/kotlin/ufrpe/sbpc/botpcd/entity/ServiceType.kt +++ b/src/main/kotlin/ufrpe/sbpc/botpcd/entity/ServiceType.kt @@ -68,7 +68,12 @@ sealed class ServiceType( .mapNotNull { it.objectInstance } .filter { disability in it.disability } } - + fun getServiceByMonitorAssistanceType(monitorAssistanceType: MonitorAssistanceType): ServiceType { + return ServiceType::class.sealedSubclasses + .mapNotNull { it.objectInstance } + .filterIsInstance() + .first { it.monitorAssistanceType == monitorAssistanceType } as ServiceType + } } } interface MonitorServiceType { diff --git a/src/main/kotlin/ufrpe/sbpc/botpcd/repository/AttendanceRepository.kt b/src/main/kotlin/ufrpe/sbpc/botpcd/repository/AttendanceRepository.kt index af58f5b..66a2cf8 100644 --- a/src/main/kotlin/ufrpe/sbpc/botpcd/repository/AttendanceRepository.kt +++ b/src/main/kotlin/ufrpe/sbpc/botpcd/repository/AttendanceRepository.kt @@ -13,7 +13,8 @@ import java.time.LocalDateTime interface AttendanceRepository : JpaRepository { @Query("SELECT COUNT(att) FROM Attendance att WHERE att.serviceType = :serviceType AND att.startDateTime IS NULL") fun countRequestAttendanceOfService(serviceType: ServiceType): Long - + @Query("SELECT att FROM Attendance att WHERE att.startDateTime IS NULL AND att.attendantType = 'COMMITTEE_MEMBER'") + fun findPendingCommitteeMemberAttendances(): List @Query("SELECT att from Attendance att where att.serviceType = :serviceType AND att.startDateTime is null order by att.requestDateTime asc") fun findRequestAttendanceOfService(serviceType: ServiceType) : Attendance? diff --git a/src/main/kotlin/ufrpe/sbpc/botpcd/service/AttendanceService.kt b/src/main/kotlin/ufrpe/sbpc/botpcd/service/AttendanceService.kt index 8c0645a..065a6c1 100644 --- a/src/main/kotlin/ufrpe/sbpc/botpcd/service/AttendanceService.kt +++ b/src/main/kotlin/ufrpe/sbpc/botpcd/service/AttendanceService.kt @@ -3,6 +3,7 @@ package ufrpe.sbpc.botpcd.service import org.slf4j.Logger import org.slf4j.LoggerFactory import org.springframework.stereotype.Service +import org.springframework.transaction.annotation.Transactional import ufrpe.sbpc.botpcd.entity.* import ufrpe.sbpc.botpcd.entity.Attendance import ufrpe.sbpc.botpcd.entity.Attendant @@ -26,11 +27,179 @@ class AttendanceService( private val queryService: QueueService, private val attendanceRepository: AttendanceRepository, private val whatsappService: WhatsappService, - private val attendantStatusService: AttendantStatusService, private val monitorRepository: MonitorRepository, private val committeeMemberRepository: CommitteeMemberRepository, private val messageExchangeRepository: MessageExchangeRepository, ) { + @Transactional + fun setMonitorStatus(monitor: Monitor, status: UserStatus) { + monitor.status = status + monitorRepository.save(monitor) + } + + @Transactional + fun setCommitteeMemberStatus(member: CommitteeMember, status: UserStatus) { + member.status = status + committeeMemberRepository.save(member) + } + + private fun updateAttendantStatus(botNumber: String, attendant: Attendant, newStatus: UserStatus) { + when (attendant) { + is Monitor -> { + setMonitorStatus(attendant, newStatus) + if(newStatus == UserStatus.AVAILABLE) { + val serviceType = ServiceType.getServiceByMonitorAssistanceType(attendant.assistanceType) + attendanceRepository.findRequestAttendanceOfService(serviceType)?.let{requestAttendance -> + directToAvailableAttendant(botNumber, requestAttendance.pwd, serviceType) + } + } + } + is CommitteeMember -> { + setCommitteeMemberStatus(attendant, newStatus) + if(newStatus == UserStatus.AVAILABLE) { + attendanceRepository.findPendingCommitteeMemberAttendances().firstOrNull()?.let { attendance -> + directToAvailableAttendant(botNumber, attendance.pwd, attendance.serviceType) + } + } + } + } + } + fun createOptionsWithCancel(options: List, header: String = "", author: String = ""): String { + var msg = createOptions(options, header, author) + return "${msg}- Escreva \"cancelar\" para sair do menu" + } + val changeStatusTextOptionsFor = mapOf( + "AVAILABLE" to createOptionsWithCancel( + listOf("Ficar Indisponível"), + "Você está *Disponível* no momento", "BotPCD" + ), + "UNAVAILABLE" to createOptionsWithCancel( + listOf("Ficar Disponível"), + "Você está *Indisponível* no momento", "BotPCD" + ), + "BUSY" to createOptionsWithCancel( + listOf( + "Encerrar atendimento e Ficar Disponível", + "Encerrar atendimento e Ficar Indisponível" + ), + "Você está *em atendimento*", "BotPCD" + ) + ) + + fun sendStatusChanger(attendant: Attendant, botPhoneNumber: String) { + val userPhoneNumber = attendant.phoneNumber + val messageToSend = when (attendant.status) { + UserStatus.AVAILABLE -> changeStatusTextOptionsFor[UserStatus.AVAILABLE.toString()] + UserStatus.UNAVAILABLE -> changeStatusTextOptionsFor[UserStatus.UNAVAILABLE.toString()] + UserStatus.BUSY -> changeStatusTextOptionsFor[UserStatus.BUSY.toString()] + } + whatsappService.sendMessage(botPhoneNumber, userPhoneNumber, messageToSend ?: "") + } + + @Transactional + fun processStatusChangeResponse(botNumber: String, attendant: Attendant, userResponse: String, botPhoneNumber: String) { + var confirmationMessage: String? = null + val userPhoneNumber = attendant.phoneNumber + + when (attendant.status) { + UserStatus.AVAILABLE -> { + when (userResponse.lowercase()) { + "1" -> { + updateAttendantStatus(botNumber, attendant, UserStatus.UNAVAILABLE) + confirmationMessage = "Seu status foi atualizado para Indisponível." + } + + "cancelar" -> { + confirmationMessage = "Você continua Disponível." + } + + else -> { + confirmationMessage = "Opção inválida. Seu status permanece Disponível." + } + } + } + + UserStatus.UNAVAILABLE -> { + when (userResponse.lowercase()) { + "1" -> { + updateAttendantStatus(botNumber, attendant, UserStatus.AVAILABLE) + confirmationMessage = "Seu status foi atualizado para Disponível." + } + + "cancelar" -> { + confirmationMessage = "Você continua Indisponível." + } + + else -> { + confirmationMessage = "Opção inválida. Seu status permanece Indisponível." + } + } + } + + UserStatus.BUSY -> { + val attendance = attendanceRepository.findStartedAttendanceOfAttendant(attendant) + if (attendance != null) { + when (userResponse.lowercase()) { + "1" -> { + updateAttendantStatus(botNumber, attendant, UserStatus.AVAILABLE) + whatsappService.sendMessage( + botPhoneNumber, + attendance.pwd.phoneNumber, + "Atendimento encerrado", + "BotPCD" + ) + confirmationMessage = "Atendimento encerrado. Seu status foi atualizado para Disponível." + finishAttendance(attendance) + } + "2" -> { + updateAttendantStatus(botNumber, attendant, UserStatus.UNAVAILABLE) + whatsappService.sendMessage( + botPhoneNumber, + attendance.pwd.phoneNumber, + "Atendimento encerrado", + "BotPCD" + ) + confirmationMessage = "Atendimento encerrado. Seu status foi atualizado para Indisponível." + finishAttendance(attendance) + } + + "cancelar" -> { + confirmationMessage = "Você continua em atendimento." + } + + else -> { + confirmationMessage = "Opção inválida. Seu status permanece Ocupado." + } + } + } else { + logger.warn("Atendente está ocupado ${attendant.name} sem atendimento") + } + } + } + + confirmationMessage?.let { + whatsappService.sendMessage(botPhoneNumber, userPhoneNumber, it, "BotPCD") + } + } + + fun findAvailableMonitors(): List { + return monitorRepository.findByStatus(UserStatus.AVAILABLE) + } + + fun findAvailableCommitteeMembers(): List { + return committeeMemberRepository.findByStatus(UserStatus.AVAILABLE) + } + + fun findAvailableMonitorsByType(assistanceType: MonitorAssistanceType): List { + val availableMonitors = findAvailableMonitors() + return availableMonitors.filter { it.assistanceType == assistanceType } + } + fun finishAttendance(attendance: Attendance) { + attendance.apply { + endDateTime = LocalDateTime.now() + } + attendanceRepository.save(attendance) + } val awaitServiceMessage = "No momento não há atendentes disponíveis. Por favor, aguarde na fila de espera e retornaremos assim que possível." fun sendWaitListMessage(botNumber: String, pwd: PWD) { whatsappService.sendMessage( @@ -58,10 +227,10 @@ class AttendanceService( fun makeAttendantBusy(attendant: Attendant) { when (attendant) { is Monitor -> { - attendantStatusService.setMonitorStatus(attendant, UserStatus.BUSY) + setMonitorStatus(attendant, UserStatus.BUSY) } is CommitteeMember -> { - attendantStatusService.setCommitteeMemberStatus(attendant, UserStatus.BUSY) + setCommitteeMemberStatus(attendant, UserStatus.BUSY) } } } diff --git a/src/main/kotlin/ufrpe/sbpc/botpcd/service/AttendantFlowService.kt b/src/main/kotlin/ufrpe/sbpc/botpcd/service/AttendantFlowService.kt index 02ef2b0..b21f9cc 100644 --- a/src/main/kotlin/ufrpe/sbpc/botpcd/service/AttendantFlowService.kt +++ b/src/main/kotlin/ufrpe/sbpc/botpcd/service/AttendantFlowService.kt @@ -7,16 +7,15 @@ import ufrpe.sbpc.botpcd.repository.AttendanceRepository @Service class AttendantFlowService( - private val attendantStatusService: AttendantStatusService, private val attendanceRepository: AttendanceRepository, private val attendanceService: AttendanceService ) { val botPcdRegex = Regex("^\\s*bot\\s*pcd\\s*$", RegexOption.IGNORE_CASE) fun redirect(botNumber: String, lastBotMessageText: String?, attendant: Attendant, message: String) { if (botPcdRegex.matches(message)) { - attendantStatusService.sendStatusChanger(attendant, botNumber) - } else if (lastBotMessageText in attendantStatusService.changeStatusTextOptionsFor.values) { - attendantStatusService.processStatusChangeResponse(attendant, message, botNumber) + attendanceService.sendStatusChanger(attendant, botNumber) + } else if (lastBotMessageText in attendanceService.changeStatusTextOptionsFor.values) { + attendanceService.processStatusChangeResponse(botNumber, attendant, message, botNumber) } else { attendanceRepository.findStartedAttendanceOfAttendant(attendant)?.let { attendance -> attendanceService.redirectMessageToPwd(botNumber, message, attendance.pwd, attendant) diff --git a/src/main/kotlin/ufrpe/sbpc/botpcd/service/AttendantStatusService.kt b/src/main/kotlin/ufrpe/sbpc/botpcd/service/AttendantStatusService.kt deleted file mode 100644 index 89fb08d..0000000 --- a/src/main/kotlin/ufrpe/sbpc/botpcd/service/AttendantStatusService.kt +++ /dev/null @@ -1,177 +0,0 @@ -package ufrpe.sbpc.botpcd.service - -import org.slf4j.Logger -import org.slf4j.LoggerFactory -import org.springframework.stereotype.Service -import ufrpe.sbpc.botpcd.entity.* -import ufrpe.sbpc.botpcd.repository.MonitorRepository -import ufrpe.sbpc.botpcd.repository.AttendanceRepository -import ufrpe.sbpc.botpcd.repository.CommitteeMemberRepository -import org.springframework.transaction.annotation.Transactional -import ufrpe.sbpc.botpcd.util.createOptions -import java.time.LocalDateTime - -@Service -class AttendantStatusService( - private val whatsappService: WhatsappService, - private val monitorRepository: MonitorRepository, - private val attendanceRepository: AttendanceRepository, - private val committeeMemberRepository: CommitteeMemberRepository -) { - val logger: Logger = LoggerFactory.getLogger(AttendantStatusService::class.java) - - @Transactional - fun setMonitorStatus(monitor: Monitor, status: UserStatus) { - monitor.status = status - monitorRepository.save(monitor) - } - - @Transactional - fun setCommitteeMemberStatus(member: CommitteeMember, status: UserStatus) { - member.status = status - committeeMemberRepository.save(member) - } - - private fun updateAttendantStatus(attendant: Attendant, newStatus: UserStatus) { - when (attendant) { - is Monitor -> setMonitorStatus(attendant, newStatus) - is CommitteeMember -> setCommitteeMemberStatus(attendant, newStatus) - } - } - fun createOptionsWithCancel(options: List, header: String = "", author: String = ""): String { - var msg = createOptions(options, header, author) - return "${msg}- Escreva \"cancelar\" para sair do menu" - } - val changeStatusTextOptionsFor = mapOf( - "AVAILABLE" to createOptionsWithCancel( - listOf("Ficar Indisponível"), - "Você está *Disponível* no momento", "BotPCD" - ), - "UNAVAILABLE" to createOptionsWithCancel( - listOf("Ficar Disponível"), - "Você está *Indisponível* no momento", "BotPCD" - ), - "BUSY" to createOptionsWithCancel( - listOf( - "Encerrar atendimento e Ficar Disponível", - "Encerrar atendimento e Ficar Indisponível" - ), - "Você está *em atendimento*", "BotPCD" - ) - ) - - fun sendStatusChanger(attendant: Attendant, botPhoneNumber: String) { - val userPhoneNumber = attendant.phoneNumber - val messageToSend = when (attendant.status) { - UserStatus.AVAILABLE -> changeStatusTextOptionsFor[UserStatus.AVAILABLE.toString()] - UserStatus.UNAVAILABLE -> changeStatusTextOptionsFor[UserStatus.UNAVAILABLE.toString()] - UserStatus.BUSY -> changeStatusTextOptionsFor[UserStatus.BUSY.toString()] - } - whatsappService.sendMessage(botPhoneNumber, userPhoneNumber, messageToSend ?: "") - } - - @Transactional - fun processStatusChangeResponse(attendant: Attendant, userResponse: String, botPhoneNumber: String) { - var confirmationMessage: String? = null - val userPhoneNumber = attendant.phoneNumber - - when (attendant.status) { - UserStatus.AVAILABLE -> { - when (userResponse.lowercase()) { - "1" -> { - updateAttendantStatus(attendant, UserStatus.UNAVAILABLE) - confirmationMessage = "Seu status foi atualizado para Indisponível." - } - - "cancelar" -> { - confirmationMessage = "Você continua Disponível." - } - - else -> { - confirmationMessage = "Opção inválida. Seu status permanece Disponível." - } - } - } - - UserStatus.UNAVAILABLE -> { - when (userResponse.lowercase()) { - "1" -> { - updateAttendantStatus(attendant, UserStatus.AVAILABLE) - confirmationMessage = "Seu status foi atualizado para Disponível." - } - - "cancelar" -> { - confirmationMessage = "Você continua Indisponível." - } - - else -> { - confirmationMessage = "Opção inválida. Seu status permanece Indisponível." - } - } - } - - UserStatus.BUSY -> { - val attendance = attendanceRepository.findStartedAttendanceOfAttendant(attendant) - if (attendance != null) { - when (userResponse.lowercase()) { - "1" -> { - updateAttendantStatus(attendant, UserStatus.AVAILABLE) - whatsappService.sendMessage( - botPhoneNumber, - attendance.pwd.phoneNumber, - "Atendimento encerrado", - "BotPCD" - ) - confirmationMessage = "Atendimento encerrado. Seu status foi atualizado para Disponível." - finishAttendance(attendance) - } - "2" -> { - updateAttendantStatus(attendant, UserStatus.UNAVAILABLE) - whatsappService.sendMessage( - botPhoneNumber, - attendance.pwd.phoneNumber, - "Atendimento encerrado", - "BotPCD" - ) - confirmationMessage = "Atendimento encerrado. Seu status foi atualizado para Indisponível." - finishAttendance(attendance) - } - - "cancelar" -> { - confirmationMessage = "Você continua em atendimento." - } - - else -> { - confirmationMessage = "Opção inválida. Seu status permanece Ocupado." - } - } - } else { - logger.warn("Atendente está ocupado ${attendant.name} sem atendimento") - } - } - } - - confirmationMessage?.let { - whatsappService.sendMessage(botPhoneNumber, userPhoneNumber, it, "BotPCD") - } - } - - fun findAvailableMonitors(): List { - return monitorRepository.findByStatus(UserStatus.AVAILABLE) - } - - fun findAvailableCommitteeMembers(): List { - return committeeMemberRepository.findByStatus(UserStatus.AVAILABLE) - } - - fun findAvailableMonitorsByType(assistanceType: MonitorAssistanceType): List { - val availableMonitors = findAvailableMonitors() - return availableMonitors.filter { it.assistanceType == assistanceType } - } - fun finishAttendance(attendance: Attendance) { - attendance.apply { - endDateTime = LocalDateTime.now() - } - attendanceRepository.save(attendance) - } -} diff --git a/src/main/kotlin/ufrpe/sbpc/botpcd/service/FirstContactService.kt b/src/main/kotlin/ufrpe/sbpc/botpcd/service/FirstContactService.kt index 3fd8080..c5334bb 100644 --- a/src/main/kotlin/ufrpe/sbpc/botpcd/service/FirstContactService.kt +++ b/src/main/kotlin/ufrpe/sbpc/botpcd/service/FirstContactService.kt @@ -27,7 +27,6 @@ class FirstContactService( private val whatsappService: WhatsappService, private val attendanceService: AttendanceService, private val messageExchangeRepository: MessageExchangeRepository, - private val attendantStatusService: AttendantStatusService, private val attendanceRepository: AttendanceRepository, private val monitorRepository: MonitorRepository, private val committeeMemberRepository: CommitteeMemberRepository, diff --git a/src/main/kotlin/ufrpe/sbpc/botpcd/service/QueueService.kt b/src/main/kotlin/ufrpe/sbpc/botpcd/service/QueueService.kt index abee750..0552fa7 100644 --- a/src/main/kotlin/ufrpe/sbpc/botpcd/service/QueueService.kt +++ b/src/main/kotlin/ufrpe/sbpc/botpcd/service/QueueService.kt @@ -1,5 +1,6 @@ package ufrpe.sbpc.botpcd.service +import jakarta.transaction.Transactional import java.time.LocalDateTime import ufrpe.sbpc.botpcd.entity.PWD import ufrpe.sbpc.botpcd.entity.Attendance @@ -18,7 +19,7 @@ class QueueService(private val attendanceRepository: AttendanceRepository){ fun len(service: ServiceType): Long { return attendanceRepository.countRequestAttendanceOfService(service) } - + @Transactional fun pop(service: ServiceType): Attendance? { val firstAtt = attendanceRepository.findRequestAttendanceOfService(service) diff --git a/src/test/kotlin/ufrpe/sbpc/botpcd/StepDefinitions.kt b/src/test/kotlin/ufrpe/sbpc/botpcd/StepDefinitions.kt index c0f82db..f64e35a 100644 --- a/src/test/kotlin/ufrpe/sbpc/botpcd/StepDefinitions.kt +++ b/src/test/kotlin/ufrpe/sbpc/botpcd/StepDefinitions.kt @@ -32,7 +32,7 @@ import ufrpe.sbpc.botpcd.repository.CommitteeMemberRepository import ufrpe.sbpc.botpcd.repository.MessageExchangeRepository import ufrpe.sbpc.botpcd.repository.MonitorRepository import ufrpe.sbpc.botpcd.repository.PWDRepository -import ufrpe.sbpc.botpcd.service.AttendantStatusService +import ufrpe.sbpc.botpcd.service.AttendanceService import java.io.File import java.time.LocalDateTime // import java.math.BigInteger // Não é mais necessário para os steps de atendente @@ -45,7 +45,7 @@ class StepDefinitions( val monitorRepository: MonitorRepository, val committeeMemberRepository: CommitteeMemberRepository, val attendantRepository: AttendantRepository, - val attendantStatusService: AttendantStatusService, + val attendanceService: AttendanceService, val attendanceRepository: AttendanceRepository ) { private var currentBotNumber: String = "15556557522" @@ -270,8 +270,8 @@ class StepDefinitions( statusAntigoStr: String ) { val statusAntigo = UserStatus.valueOf(statusAntigoStr.uppercase()) - val expectedMessageContent = attendantStatusService.changeStatusTextOptionsFor[statusAntigo.name] - ?: throw IllegalArgumentException("Mensagem de opção não encontrada para status $statusAntigoStr no AttendantStatusService.changeStatusTextOptionsFor. Chaves disponíveis: ${attendantStatusService.changeStatusTextOptionsFor.keys}") + val expectedMessageContent = attendanceService.changeStatusTextOptionsFor[statusAntigo.name] + ?: throw IllegalArgumentException("Mensagem de opção não encontrada para status $statusAntigoStr no attendanceService.changeStatusTextOptionsFor. Chaves disponíveis: ${attendanceService.changeStatusTextOptionsFor.keys}") mockUserRecievedMessage(currentTestAttendantPhoneNumber, expectedMessageContent) } From 0d6684892b3199e545346fc1cb675ad3be0e34c2 Mon Sep 17 00:00:00 2001 From: victor-yghor Date: Sat, 14 Jun 2025 22:09:10 -0300 Subject: [PATCH 06/26] Implement Unit Tests --- .../sbpc/botpcd/entity/MessageExchange.kt | 3 +- .../sbpc/botpcd/service/WhatsappService.kt | 5 ++ .../ufrpe/sbpc/botpcd/WhatsappServiceTest.kt | 86 +++++++++++++++++++ 3 files changed, 92 insertions(+), 2 deletions(-) create mode 100644 src/test/kotlin/ufrpe/sbpc/botpcd/WhatsappServiceTest.kt diff --git a/src/main/kotlin/ufrpe/sbpc/botpcd/entity/MessageExchange.kt b/src/main/kotlin/ufrpe/sbpc/botpcd/entity/MessageExchange.kt index 0df1e70..ff0ff7a 100644 --- a/src/main/kotlin/ufrpe/sbpc/botpcd/entity/MessageExchange.kt +++ b/src/main/kotlin/ufrpe/sbpc/botpcd/entity/MessageExchange.kt @@ -18,6 +18,5 @@ class MessageExchange( @Column(columnDefinition = "TEXT") var message: String ) { - @CreationTimestamp - lateinit var createAt: LocalDateTime + var createAt: LocalDateTime = LocalDateTime.now() } \ No newline at end of file diff --git a/src/main/kotlin/ufrpe/sbpc/botpcd/service/WhatsappService.kt b/src/main/kotlin/ufrpe/sbpc/botpcd/service/WhatsappService.kt index e9b6522..aa9123b 100644 --- a/src/main/kotlin/ufrpe/sbpc/botpcd/service/WhatsappService.kt +++ b/src/main/kotlin/ufrpe/sbpc/botpcd/service/WhatsappService.kt @@ -6,7 +6,9 @@ import com.whatsapp.api.domain.messages.Message import ufrpe.sbpc.botpcd.entity.MessageExchange import com.whatsapp.api.domain.messages.TextMessage import com.whatsapp.api.impl.WhatsappBusinessCloudApi +import org.slf4j.LoggerFactory import ufrpe.sbpc.botpcd.repository.MessageExchangeRepository +import kotlin.math.log @Service @@ -14,6 +16,7 @@ class WhatsappService( private val cloudApi: WhatsappBusinessCloudApi, private val messageExchangeRepository: MessageExchangeRepository ) { + private val logger = LoggerFactory.getLogger(WhatsappService::class.java) fun sendMessage(botNumber: String, destinyNumberID: String, msg: String, author: String = "") { val text = if (author != "") "*${author}:*\n ${msg}" else msg @@ -33,6 +36,8 @@ class WhatsappService( fromPhoneNumber = botNumber, toPhoneNumber = destinyNumberID, message = text)) + } else { + logger.warn("Teve uma tentativa de enviar a mensagem ${message} para o número ${destinyNumberID}, mas ele não tinha mandando mensagem.") } } } diff --git a/src/test/kotlin/ufrpe/sbpc/botpcd/WhatsappServiceTest.kt b/src/test/kotlin/ufrpe/sbpc/botpcd/WhatsappServiceTest.kt new file mode 100644 index 0000000..88c7c1c --- /dev/null +++ b/src/test/kotlin/ufrpe/sbpc/botpcd/WhatsappServiceTest.kt @@ -0,0 +1,86 @@ +package ufrpe.sbpc.botpcd.service + +import com.whatsapp.api.impl.WhatsappBusinessCloudApi +import org.junit.jupiter.api.Assertions.assertEquals +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.extension.ExtendWith +import org.mockito.ArgumentCaptor +import org.mockito.Mockito.* +import org.mockito.junit.jupiter.MockitoExtension +import ufrpe.sbpc.botpcd.entity.MessageExchange +import ufrpe.sbpc.botpcd.repository.MessageExchangeRepository +import java.time.LocalDateTime + + +@ExtendWith(MockitoExtension::class) +class WhatsappServiceTest { + + private val cloudApi = mock(WhatsappBusinessCloudApi::class.java) + private val messageRepo = mock(MessageExchangeRepository::class.java) + private val service = WhatsappService(cloudApi, messageRepo) + private val userNumber = "551297652348" + private val botNumber = "558812389418" + private val sampleMessage = "Olá" + + @Test + fun `envia mensagem quando a ultima foi ha menos de 24h`() { + `when`( + messageRepo.lastExchangeMessage( + botNumber, + userNumber + ) + ).thenReturn( + MessageExchange( + fromPhoneNumber = userNumber, + toPhoneNumber = botNumber, + message = sampleMessage + ) + ) + service.sendMessage(botNumber, userNumber, sampleMessage) + verify(cloudApi).sendMessage(eq(botNumber), any()) + verify(messageRepo).save(any(MessageExchange::class.java)) + } + + @Test + fun `nao envia mensagem quando a ultima foi ha mais de 24h`() { + `when`( + messageRepo.lastExchangeMessage( + botNumber, + userNumber + ) + ).thenReturn( + MessageExchange( + fromPhoneNumber = userNumber, + toPhoneNumber = botNumber, + message = sampleMessage + ).apply { + createAt = LocalDateTime.now().minusHours(25) + } + ) + service.sendMessage(botNumber, userNumber, "Test message") + verify(cloudApi, never()).sendMessage(eq(userNumber), any()) + verify(messageRepo, never()).save(any(MessageExchange::class.java)) + } + + @Test + fun `envia mensagem com autor definido`() { + `when`( + messageRepo.lastExchangeMessage( + botNumber, + userNumber + ) + ).thenReturn( + MessageExchange( + fromPhoneNumber = userNumber, + toPhoneNumber = botNumber, + message = sampleMessage + ).apply { + createAt = LocalDateTime.now() + } + ) + service.sendMessage(botNumber, userNumber, "Test message", "AutorX") + val captor = ArgumentCaptor.forClass(MessageExchange::class.java) + verify(messageRepo).save(captor.capture()) + assertEquals("*AutorX:*\n Test message", captor.value.message) + } +} \ No newline at end of file From f28464616a7b38eb9d98211d5a420ff466aed98c Mon Sep 17 00:00:00 2001 From: victor-yghor Date: Sun, 15 Jun 2025 11:06:28 -0300 Subject: [PATCH 07/26] =?UTF-8?q?Melhorar=20esquema=20de=20cen=C3=A1rio=20?= =?UTF-8?q?direcionar=20para=20o=20atendente(monitor=20ou=20membro=20da=20?= =?UTF-8?q?comiss=C3=A3o)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ufrpe/sbpc/botpcd/acessarServicos.feature | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/test/resources/ufrpe/sbpc/botpcd/acessarServicos.feature b/src/test/resources/ufrpe/sbpc/botpcd/acessarServicos.feature index 14e3ddc..808bf96 100644 --- a/src/test/resources/ufrpe/sbpc/botpcd/acessarServicos.feature +++ b/src/test/resources/ufrpe/sbpc/botpcd/acessarServicos.feature @@ -15,24 +15,24 @@ Funcionalidade: Acessar serviços de assistência | neurodivergente | suporte para pessoas neurodivergentes | | uma pessoa surdocega | guia-intérprete | - Esquema do Cenário Direcionar para o atendente(monitor ou membro da comissão) - Dado "" recebeu mensagem de opcções de serviço + Esquema do Cenário: Direcionar para o atendente(monitor ou membro da comissão) + Dado que "" PCD recebeu mensagem de opcções de serviço E atendente que se chama "" está disponível para o "" - Quando "" PCD envia a mensagem "" - Entao "" PCD receberá mensagem O monitor "" irá realizar seu atendimento + Quando "" PCD envia a mensagem "" + Entao "" PCD receberá mensagem "O irá realizar seu atendimento." Exemplos: - | servico_desejado | tipo_de_atendente | - | Informações em Libras | monitor | - | Intérprete de Libras | membro da comissão | - | Assistência mobilidade | monitor | - | carro | membro da comissão | - | Higiene e Nutrição | membro da comissão | - | Audiodescrição | membro da comissão | - | Apoio Neurodivergente | monitor | - | Guia-intérprete | membro da comissão | + | adjetivo_da_deficiencia | nome_do_atendente | servico_desejado | numero_servico_desejado | tipo_de_atendente | + | um pessoa surda | Ana Monitor | informações em Libras | 1 | monitor | + | um pessoa surda | João Comissão | atividade com interpretação em Libras | 2 | membro da comissão | + | mobilidade reduzida | Pedro Monitor | ajuda na mobilidade | 1 | monitor | + | deficiente físico | Carla Comissão | transporte para deslocamento no evento | 3 | membro da comissão | + | deficiente físico | Bia Comissão | ajuda com alimentação e higiene | 2 | membro da comissão | + | uma pessoa cega | Lucas Comissão | programação com audiodescrição | 2 | membro da comissão | + | neurodivergente | Fábio Monitor | suporte para pessoas neurodivergentes | 1 | monitor | + | uma pessoa surdocega | Maria Comissão | guia-intérprete | 1 | membro da comissão | - Regra: PCD precisa receber mensagem informando que ele está na fila de espera + Regra: PCD precisa receber mensagem informando que ele está na fila de espera Cenário de Fundo: Dado que PCD recebeu a mensagem "" E não tem atendente disponível From da2be7ef0491f8e7b2cbabcb7faf6f62adb3c1e8 Mon Sep 17 00:00:00 2001 From: victor-yghor Date: Fri, 20 Jun 2025 00:26:54 -0300 Subject: [PATCH 08/26] =?UTF-8?q?finish=20the=20Direcionar=20para=20o=20at?= =?UTF-8?q?endnete=20cen=C3=A1rio=20teste?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ufrpe/sbpc/botpcd/entity/ServiceType.kt | 5 + .../ufrpe/sbpc/botpcd/StepDefinitions.kt | 108 +++++++++++++++++- .../ufrpe/sbpc/botpcd/acessarServicos.feature | 8 +- 3 files changed, 112 insertions(+), 9 deletions(-) diff --git a/src/main/kotlin/ufrpe/sbpc/botpcd/entity/ServiceType.kt b/src/main/kotlin/ufrpe/sbpc/botpcd/entity/ServiceType.kt index 605c0b9..3ae7376 100644 --- a/src/main/kotlin/ufrpe/sbpc/botpcd/entity/ServiceType.kt +++ b/src/main/kotlin/ufrpe/sbpc/botpcd/entity/ServiceType.kt @@ -74,6 +74,11 @@ sealed class ServiceType( .filterIsInstance() .first { it.monitorAssistanceType == monitorAssistanceType } as ServiceType } + fun getByDescription(description: String): ServiceType { + return ServiceType::class.sealedSubclasses + .mapNotNull { it.objectInstance } + .first { it.description == description } as ServiceType + } } } interface MonitorServiceType { diff --git a/src/test/kotlin/ufrpe/sbpc/botpcd/StepDefinitions.kt b/src/test/kotlin/ufrpe/sbpc/botpcd/StepDefinitions.kt index f64e35a..1e76ad5 100644 --- a/src/test/kotlin/ufrpe/sbpc/botpcd/StepDefinitions.kt +++ b/src/test/kotlin/ufrpe/sbpc/botpcd/StepDefinitions.kt @@ -2,16 +2,14 @@ package ufrpe.sbpc.botpcd import com.whatsapp.api.domain.webhook.Value import com.whatsapp.api.domain.webhook.WebHook +import io.cucumber.java.After import io.cucumber.java.pt.Dado import io.cucumber.java.pt.Entao import io.cucumber.java.pt.Quando -import org.springframework.transaction.annotation.Transactional import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.Assertions.assertNull import org.slf4j.Logger import org.slf4j.LoggerFactory -import org.springframework.context.annotation.Scope -import org.springframework.stereotype.Component import org.springframework.test.web.servlet.MockMvc import org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post import org.springframework.test.web.servlet.result.MockMvcResultMatchers.status @@ -22,6 +20,7 @@ import ufrpe.sbpc.botpcd.entity.Disability import ufrpe.sbpc.botpcd.entity.MessageExchange import ufrpe.sbpc.botpcd.entity.Monitor import ufrpe.sbpc.botpcd.entity.MonitorAssistanceType +import ufrpe.sbpc.botpcd.entity.MonitorServiceType import ufrpe.sbpc.botpcd.entity.PWD import ufrpe.sbpc.botpcd.entity.Provider import ufrpe.sbpc.botpcd.entity.ServiceType @@ -46,7 +45,7 @@ class StepDefinitions( val committeeMemberRepository: CommitteeMemberRepository, val attendantRepository: AttendantRepository, val attendanceService: AttendanceService, - val attendanceRepository: AttendanceRepository + val attendanceRepository: AttendanceRepository, ) { private var currentBotNumber: String = "15556557522" private val numberUserNotRegister: String = "558187654321" @@ -72,6 +71,98 @@ class StepDefinitions( // Implementar lógica para garantir que o PCD está cadastrado no sistema // Ex: pwdRepository.save(PWD(name = "PCD Teste Completo", phoneNumber = numberUserNotRegister, disabilities = mutableSetOf(Disability.DEAFNESS))) } + @Dado("que não tem atendente disponível") + fun `que não tem atendente disponível`() { + + } + @Dado("que {string} PCD recebeu mensagem de opcções de serviço") + fun `pcd recebue mensagem de opção de serviço`(adjetivoPCD: String) { + // ver se existe ou crirar um pcd com adjetivoPCD + val pwd = createPWDIfNotExists(phoneNumber = pwdAcessarServicesPhoneNumber, Disability.getByAdjective(adjetivoPCD)) + val servicesText = attendanceService.createSendServicesMessage(pwd.disabilities.first(), pwd) + messageExchangeRepository.save( + MessageExchange( + fromPhoneNumber = currentBotNumber, + toPhoneNumber = pwdAcessarServicesPhoneNumber, + message = servicesText + ) + ) + // pegar no proprio código qual seria a mensagem de serviço + } + @After + fun cleanup() { + // Esta linha deleta os dados em uma ordem que evita erros de chave estrangeira + listOf(attendanceRepository, messageExchangeRepository, monitorRepository, committeeMemberRepository, pwdRepository, attendantRepository).forEach { it.deleteAllInBatch() } + } + + /** + * Cria um atendente (Monitor ou Membro da Comissão) com o nome especificado, + * define seu status como DISPONÍVEL e garante que ele seja elegível para + * o serviço desejado. Também simula uma mensagem recente do atendente para + * que o sistema o considere ativo. + */ + @Dado("atendente que se chama {string} está disponível para o {string}") + fun `atendente está disponível`(nomeAtendente: String, servicoDesejado: String) { + // Gera um número de telefone único para o atendente para evitar conflitos + attendantRepository.findByPhoneNumber(currentTestAttendantPhoneNumber)?.let { attendantRepository.delete(it) } + val serviceType = ServiceType.getByDescription(servicoDesejado) + val tipoAtendente = if (nomeAtendente.contains("Monitor", ignoreCase = true)) "monitor" else "membro da comissão" + val attendant: Attendant = when (tipoAtendente) { + "monitor" -> { + val monitorService = serviceType as? MonitorServiceType + ?: throw IllegalArgumentException("Serviço '$servicoDesejado' não é compatível com Monitor") + monitorRepository.save( + Monitor( + name = nomeAtendente, + phoneNumber = currentTestAttendantPhoneNumber, + status = UserStatus.AVAILABLE, + assistanceType = monitorService.monitorAssistanceType + ) + ) + } + "membro da comissão" -> { + committeeMemberRepository.save( + CommitteeMember( + name = nomeAtendente, + phoneNumber = currentTestAttendantPhoneNumber, + status = UserStatus.AVAILABLE + ) + ) + } + else -> throw IllegalArgumentException("Tipo de atendente desconhecido: $tipoAtendente") + } + messageExchangeRepository.save( + MessageExchange( + fromPhoneNumber = currentTestAttendantPhoneNumber, + toPhoneNumber = currentBotNumber, + message = "teste " + ) + ) + // Simula que o atendente enviou uma mensagem recentemente para ser considerado ativo + mockUserRecievedMessage(attendant.phoneNumber, "Estou online") + } + + /** + * Simula o envio de uma mensagem pelo PCD para selecionar um serviço. + * O número do serviço corresponde à opção na lista de serviços recebida. + */ + @Quando("{string} PCD envia a mensagem {string}") + fun `pcd envia mensagem de serviço`(adjetivoPCD: String, numeroServico: String) { + // O adjetivoPCD é usado para contexto, o número de telefone identifica o usuário + val pwd = createPWDIfNotExists(phoneNumber = pwdAcessarServicesPhoneNumber, Disability.getByAdjective(adjetivoPCD)) + userSendMessage(numeroServico, pwd.phoneNumber) + } + + /** + * Verifica se o PCD recebeu a mensagem correta informando qual atendente + * irá realizar o seu atendimento. + */ + @Entao("{string} PCD receberá mensagem {string}") + fun `pcd recebe mensagem de direcionamento`(adjetivoPCD: String, mensagemEsperada: String) { + // O adjetivoPCD é usado para contexto, a verificação é feita pelo número de telefone + testarUltimaMensagemRecebidaDoUsuario(mensagemEsperada, pwdAcessarServicesPhoneNumber) + + } @Dado("usuário não cadastrado") fun `usuário não cadastrado`() { @@ -287,7 +378,14 @@ class StepDefinitions( assertTrue(attendant != null, "Atendente com número $currentTestAttendantPhoneNumber não encontrado no banco de dados.") assertEquals(statusNovoEsperado, attendant!!.status, "Status do atendente não foi atualizado corretamente para $statusNovoEsperado. Estava ${attendant.status}.") } - + fun createPWDIfNotExists(phoneNumber: String, disability: Disability): PWD { + var pwd = pwdRepository.findByPhoneNumber(phoneNumber) + if(pwd == null) { + return pwdRepository.save(PWD(phoneNumber = phoneNumber, disabilities = mutableSetOf(disability))) + } else { + return pwd + } + } fun mockUserRecievedMessage(userNumber: String, message: String) { messageExchangeRepository.save( MessageExchange( diff --git a/src/test/resources/ufrpe/sbpc/botpcd/acessarServicos.feature b/src/test/resources/ufrpe/sbpc/botpcd/acessarServicos.feature index 808bf96..dd76a05 100644 --- a/src/test/resources/ufrpe/sbpc/botpcd/acessarServicos.feature +++ b/src/test/resources/ufrpe/sbpc/botpcd/acessarServicos.feature @@ -25,16 +25,16 @@ Funcionalidade: Acessar serviços de assistência | adjetivo_da_deficiencia | nome_do_atendente | servico_desejado | numero_servico_desejado | tipo_de_atendente | | um pessoa surda | Ana Monitor | informações em Libras | 1 | monitor | | um pessoa surda | João Comissão | atividade com interpretação em Libras | 2 | membro da comissão | - | mobilidade reduzida | Pedro Monitor | ajuda na mobilidade | 1 | monitor | - | deficiente físico | Carla Comissão | transporte para deslocamento no evento | 3 | membro da comissão | + | mobilidade reduzida | Pedro Monitor | ajuda na mobilidade | 3 | monitor | + | deficiente físico | Carla Comissão | transporte para deslocamento no evento | 1 | membro da comissão | | deficiente físico | Bia Comissão | ajuda com alimentação e higiene | 2 | membro da comissão | - | uma pessoa cega | Lucas Comissão | programação com audiodescrição | 2 | membro da comissão | + | uma pessoa cega | Lucas Comissão | programação com audiodescrição | 1 | membro da comissão | | neurodivergente | Fábio Monitor | suporte para pessoas neurodivergentes | 1 | monitor | | uma pessoa surdocega | Maria Comissão | guia-intérprete | 1 | membro da comissão | Regra: PCD precisa receber mensagem informando que ele está na fila de espera Cenário de Fundo: Dado que PCD recebeu a mensagem "" - E não tem atendente disponível + E não que tem atendente disponível Esquema do Cenário: PCD entra na fila de espera Quando PCD envia mensagem "" From 6bda5203ad88d442a3f27568aafd552333745bb9 Mon Sep 17 00:00:00 2001 From: victor-yghor Date: Fri, 20 Jun 2025 00:28:56 -0300 Subject: [PATCH 09/26] add another condition to the bot send a message --- src/test/resources/ufrpe/sbpc/botpcd/acessarServicos.feature | 1 + 1 file changed, 1 insertion(+) diff --git a/src/test/resources/ufrpe/sbpc/botpcd/acessarServicos.feature b/src/test/resources/ufrpe/sbpc/botpcd/acessarServicos.feature index dd76a05..e2ebc6c 100644 --- a/src/test/resources/ufrpe/sbpc/botpcd/acessarServicos.feature +++ b/src/test/resources/ufrpe/sbpc/botpcd/acessarServicos.feature @@ -18,6 +18,7 @@ Funcionalidade: Acessar serviços de assistência Esquema do Cenário: Direcionar para o atendente(monitor ou membro da comissão) Dado que "" PCD recebeu mensagem de opcções de serviço E atendente que se chama "" está disponível para o "" + E atendente enviou uma mensagem nas ultimas 24 horas para o bot Quando "" PCD envia a mensagem "" Entao "" PCD receberá mensagem "O irá realizar seu atendimento." From bca6285f4c967d1d3b6ccc6d0f13c5e4cb3268e2 Mon Sep 17 00:00:00 2001 From: victor-yghor Date: Fri, 20 Jun 2025 22:02:57 -0300 Subject: [PATCH 10/26] =?UTF-8?q?improve=20the=20esquema=20do=20cen=C3=A1r?= =?UTF-8?q?io=20direionar=20para=20o=20atendente?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- data/myDB.mv.db | Bin 0 -> 20480 bytes data/myDB.trace.db | 38 ++++++++++++++++++ .../ufrpe/sbpc/botpcd/StepDefinitions.kt | 17 ++++---- .../ufrpe/sbpc/botpcd/acessarServicos.feature | 2 +- 4 files changed, 49 insertions(+), 8 deletions(-) create mode 100644 data/myDB.mv.db create mode 100644 data/myDB.trace.db diff --git a/data/myDB.mv.db b/data/myDB.mv.db new file mode 100644 index 0000000000000000000000000000000000000000..333882272d375526f875f45e53c1f8fc63b7d2f5 GIT binary patch literal 20480 zcmeI4O>g5w7{~2)`$Bo!3s+=HcS|K>&5S3G?Gq{Oszq&CHQCkPs);>rt0s1oIHl!; z(BAfl#FZmQZtw*-BE$#a&L`l`OQ>qq-n+$-)N`Kmter2_OL^fCP{L5M*>Iy z2_OL^fCP{L5W4)n4rYf)sT6rK6$Z&pdDi{*(7hjoFChE?dp1tYl5;A$~=cR1)`{LZ3 zm%p>ljdg2`Fww~(b_y%f3&@`;V_@UO#C?eY{tH8&B4m>m}-61a@E#U8>qIf z+EBI8d@j1uJ9tNRFw*L6y=|Vr@W;pS7Cum~7d@G``XV0ybl6xj(5IH7-H{%7Uxk#i z+XD!2`g`j6Fi(q};?Se&YVm*p z?fEFP*4A{g@wlFkGz)gcvP%6j_kk=ZQrihb(_Ofelh#Q ztaZm)=)&}R$LV}^3j-I`G2PW{x}Hiu}60QFk*aK#`Od9}P834=|^Te^;*d_fhK>za>tpEKh^gq-FRsCP+`hTMI ze-xxd>wlhPV-4wR{a;g3(oeHnk^SQ&)dqlHpyqs4+4)+*smjjcH7Yy*59-Vxs+#q< zaz6S)2xBR*sWNnB5Imjz)3#vWhVemk&u+;Np~|Pa?1#|*>W8rLTE5Z`k;bGkf0i+Q z!(5m&dQg>lW=xu~kET2tu5YKS?6hf<=3-FHIBSM=>JRqq9-`$|KNq`|9=2h)ELD8 literal 0 HcmV?d00001 diff --git a/data/myDB.trace.db b/data/myDB.trace.db new file mode 100644 index 0000000..299120b --- /dev/null +++ b/data/myDB.trace.db @@ -0,0 +1,38 @@ +2025-05-20 12:36:33.423212Z jdbc[3]: exception +java.sql.SQLClientInfoException: Client info name 'ApplicationName' not supported. + at org.h2.jdbc.JdbcConnection.setClientInfo(JdbcConnection.java:1624) + at com.intellij.database.remote.jdbc.impl.RemoteConnectionImpl.setClientInfo(RemoteConnectionImpl.java:468) + at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103) + at java.base/java.lang.reflect.Method.invoke(Method.java:580) + at java.rmi/sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:360) + at java.rmi/sun.rmi.transport.Transport$1.run(Transport.java:200) + at java.rmi/sun.rmi.transport.Transport$1.run(Transport.java:197) + at java.base/java.security.AccessController.doPrivileged(AccessController.java:714) + at java.rmi/sun.rmi.transport.Transport.serviceCall(Transport.java:196) + at java.rmi/sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:598) + at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:844) + at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(TCPTransport.java:721) + at java.base/java.security.AccessController.doPrivileged(AccessController.java:400) + at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:720) + at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144) + at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642) + at java.base/java.lang.Thread.run(Thread.java:1583) +2025-05-20 12:36:34.044132Z jdbc[3]: exception +java.sql.SQLClientInfoException: Client info name 'ApplicationName' not supported. + at org.h2.jdbc.JdbcConnection.setClientInfo(JdbcConnection.java:1624) + at com.intellij.database.remote.jdbc.impl.RemoteConnectionImpl.setClientInfo(RemoteConnectionImpl.java:468) + at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103) + at java.base/java.lang.reflect.Method.invoke(Method.java:580) + at java.rmi/sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:360) + at java.rmi/sun.rmi.transport.Transport$1.run(Transport.java:200) + at java.rmi/sun.rmi.transport.Transport$1.run(Transport.java:197) + at java.base/java.security.AccessController.doPrivileged(AccessController.java:714) + at java.rmi/sun.rmi.transport.Transport.serviceCall(Transport.java:196) + at java.rmi/sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:598) + at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:844) + at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(TCPTransport.java:721) + at java.base/java.security.AccessController.doPrivileged(AccessController.java:400) + at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:720) + at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144) + at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642) + at java.base/java.lang.Thread.run(Thread.java:1583) diff --git a/src/test/kotlin/ufrpe/sbpc/botpcd/StepDefinitions.kt b/src/test/kotlin/ufrpe/sbpc/botpcd/StepDefinitions.kt index 1e76ad5..a1d7dc0 100644 --- a/src/test/kotlin/ufrpe/sbpc/botpcd/StepDefinitions.kt +++ b/src/test/kotlin/ufrpe/sbpc/botpcd/StepDefinitions.kt @@ -94,6 +94,16 @@ class StepDefinitions( // Esta linha deleta os dados em uma ordem que evita erros de chave estrangeira listOf(attendanceRepository, messageExchangeRepository, monitorRepository, committeeMemberRepository, pwdRepository, attendantRepository).forEach { it.deleteAllInBatch() } } + @Dado("atendente que se chama {string} enviou uma mensagem nas ultimas 24 horas para o bot") + fun `atendente enviou uma mensagem nas ultimas 24 horas`(nomeAtendente: String) { + messageExchangeRepository.save( + MessageExchange( + fromPhoneNumber = currentTestAttendantPhoneNumber, + toPhoneNumber = currentBotNumber, + message = "teste " + ) + ) + } /** * Cria um atendente (Monitor ou Membro da Comissão) com o nome especificado, @@ -131,13 +141,6 @@ class StepDefinitions( } else -> throw IllegalArgumentException("Tipo de atendente desconhecido: $tipoAtendente") } - messageExchangeRepository.save( - MessageExchange( - fromPhoneNumber = currentTestAttendantPhoneNumber, - toPhoneNumber = currentBotNumber, - message = "teste " - ) - ) // Simula que o atendente enviou uma mensagem recentemente para ser considerado ativo mockUserRecievedMessage(attendant.phoneNumber, "Estou online") } diff --git a/src/test/resources/ufrpe/sbpc/botpcd/acessarServicos.feature b/src/test/resources/ufrpe/sbpc/botpcd/acessarServicos.feature index e2ebc6c..f7deb4e 100644 --- a/src/test/resources/ufrpe/sbpc/botpcd/acessarServicos.feature +++ b/src/test/resources/ufrpe/sbpc/botpcd/acessarServicos.feature @@ -18,7 +18,7 @@ Funcionalidade: Acessar serviços de assistência Esquema do Cenário: Direcionar para o atendente(monitor ou membro da comissão) Dado que "" PCD recebeu mensagem de opcções de serviço E atendente que se chama "" está disponível para o "" - E atendente enviou uma mensagem nas ultimas 24 horas para o bot + E atendente que se chama "" enviou uma mensagem nas ultimas 24 horas para o bot Quando "" PCD envia a mensagem "" Entao "" PCD receberá mensagem "O irá realizar seu atendimento." From 5767dfa22458291406b2e2fc8b68825fba74e6a8 Mon Sep 17 00:00:00 2001 From: victor-yghor Date: Fri, 20 Jun 2025 22:32:05 -0300 Subject: [PATCH 11/26] =?UTF-8?q?improve=20the=20cen=C3=A1rios?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ufrpe/sbpc/botpcd/acessarServicos.feature | 57 +++++++++++++------ 1 file changed, 39 insertions(+), 18 deletions(-) diff --git a/src/test/resources/ufrpe/sbpc/botpcd/acessarServicos.feature b/src/test/resources/ufrpe/sbpc/botpcd/acessarServicos.feature index f7deb4e..dbb909f 100644 --- a/src/test/resources/ufrpe/sbpc/botpcd/acessarServicos.feature +++ b/src/test/resources/ufrpe/sbpc/botpcd/acessarServicos.feature @@ -24,32 +24,53 @@ Funcionalidade: Acessar serviços de assistência Exemplos: | adjetivo_da_deficiencia | nome_do_atendente | servico_desejado | numero_servico_desejado | tipo_de_atendente | + # Deficiência Auditiva | um pessoa surda | Ana Monitor | informações em Libras | 1 | monitor | | um pessoa surda | João Comissão | atividade com interpretação em Libras | 2 | membro da comissão | - | mobilidade reduzida | Pedro Monitor | ajuda na mobilidade | 3 | monitor | - | deficiente físico | Carla Comissão | transporte para deslocamento no evento | 1 | membro da comissão | + # Mobilidade Reduzida + | mobilidade reduzida | Pedro Monitor | ajuda na mobilidade | 1 | monitor | + | mobilidade reduzida | Bia Comissão | ajuda com alimentação e higiene | 2 | membro da comissão | + | mobilidade reduzida | Carla Comissão | transporte para deslocamento no evento | 3 | membro da comissão | + # Deficiência Física + | deficiente físico | Pedro Monitor | ajuda na mobilidade | 1 | monitor | | deficiente físico | Bia Comissão | ajuda com alimentação e higiene | 2 | membro da comissão | - | uma pessoa cega | Lucas Comissão | programação com audiodescrição | 1 | membro da comissão | + | deficiente físico | Carla Comissão | transporte para deslocamento no evento | 3 | membro da comissão | + # Deficiência Visual + | uma pessoa cega | Pedro Monitor | ajuda na mobilidade | 1 | monitor | + | uma pessoa cega | Lucas Comissão | programação com audiodescrição | 2 | membro da comissão | + # Neurodivergente | neurodivergente | Fábio Monitor | suporte para pessoas neurodivergentes | 1 | monitor | + # Surdocegueira | uma pessoa surdocega | Maria Comissão | guia-intérprete | 1 | membro da comissão | + Regra: PCD precisa receber mensagem informando que ele está na fila de espera - Cenário de Fundo: Dado que PCD recebeu a mensagem "" - E não que tem atendente disponível + Esquema do Cenário: PCD entra na fila de espera ao solicitar um serviço + Dado que "" PCD recebeu mensagem de opcções de serviço + E que nenhum atendente para o "" está disponível + Quando "" PCD envia a mensagem "" + Entao "" PCD receberá mensagem "No momento não há atendentes disponíveis. Por favor, aguarde na fila de espera e retornaremos assim que possível." - Esquema do Cenário: PCD entra na fila de espera - Quando PCD envia mensagem "" - Entao PCD receberá mensagem "No momento não há atendentes disponíveis. Por favor, aguarde na fila de espera e retornaremos assim que possível." - Exemplos: - | servico_desejado | | - | Informações em Libras | monitor | - | Intérprete de Libras | membro da comissão | - | Assistência mobilidade | monitor | - | carro | membro da comissão | - | Higiene e Nutrição | membro da comissão | - | Audiodescrição | membro da comissão | - | Apoio Neurodivergente | monitor | - | Guia-intérprete | membro da comissão | + Exemplos: + | adjetivo_da_deficiencia | servico_desejado | numero_servico_desejado | + # Deficiência Auditiva + | um pessoa surda | informações em Libras | 1 | + | um pessoa surda | atividade com interpretação em Libras | 2 | + # Mobilidade Reduzida + | mobilidade reduzida | ajuda na mobilidade | 1 | + | mobilidade reduzida | ajuda com alimentação e higiene | 2 | + | mobilidade reduzida | transporte para deslocamento no evento | 3 | + # Deficiência Física + | deficiente físico | ajuda na mobilidade | 1 | + | deficiente físico | ajuda com alimentação e higiene | 2 | + | deficiente físico | transporte para deslocamento no evento | 3 | + # Deficiência Visual + | uma pessoa cega | ajuda na mobilidade | 1 | + | uma pessoa cega | programação com audiodescrição | 2 | + # Neurodivergente + | neurodivergente | suporte para pessoas neurodivergentes | 1 | + # Surdocegueira + | uma pessoa surdocega | guia-intérprete | 1 | Cenário: PCD está na fila de espera e manda mensagem novamente Dado PCD possuia serviço requisitado que ainda não foi iniciado From 89c5f0fd7608e9f52a9d628c0d11ded7f6113a76 Mon Sep 17 00:00:00 2001 From: victor-yghor Date: Fri, 20 Jun 2025 22:38:45 -0300 Subject: [PATCH 12/26] improve the aceptan testes --- .../ufrpe/sbpc/botpcd/acessarServicos.feature | 39 ++++++++++++------- 1 file changed, 25 insertions(+), 14 deletions(-) diff --git a/src/test/resources/ufrpe/sbpc/botpcd/acessarServicos.feature b/src/test/resources/ufrpe/sbpc/botpcd/acessarServicos.feature index dbb909f..5fdb127 100644 --- a/src/test/resources/ufrpe/sbpc/botpcd/acessarServicos.feature +++ b/src/test/resources/ufrpe/sbpc/botpcd/acessarServicos.feature @@ -95,18 +95,29 @@ Funcionalidade: Acessar serviços de assistência Quando atendente encerrou o atendimento Entao pcd receberá mensagem "Atendimento Encerrado" - Esquema do Cenário: Atendete quando entra no estado disponível é direcionado para o pcd - Dado pcd que solicitou estava na fila de espera - Quando atendente do muda para o estado disponível - Entao atendente do será direcionado para o pcd + Esquema do Cenário: Atendente disponível é direcionado para PCD na fila de espera + Dado que "" PCD solicitou o serviço "" e está na fila de espera + E que o atendente "" do tipo "" estava indisponível + Quando o atendente "" fica disponível + Entao "" PCD receberá mensagem "O irá realizar seu atendimento." - Exemplos: - | tipo_de_servico | tipo_de_atendente | - | Libras | MONITOR | - | LibrasInterpreter | COMMITTEE_MEMBER | - | Mobility | MONITOR | - | AudioDescription | COMMITTEE_MEMBER | - | NeurodivergentSupport | MONITOR | - | GuideInterpreter | COMMITTEE_MEMBER | - | HygieneAndNutrition | COMMITTEE_MEMBER | - | Car | COMMITTEE_MEMBER | + Exemplos: + | adjetivo_da_deficiencia | servico_desejado | nome_do_atendente | tipo_de_atendente | + # Deficiência Auditiva + | um pessoa surda | informações em Libras | Ana Monitor | monitor | + | um pessoa surda | atividade com interpretação em Libras | João Comissão | membro da comissão | + # Mobilidade Reduzida + | mobilidade reduzida | ajuda na mobilidade | Pedro Monitor | monitor | + | mobilidade reduzida | ajuda com alimentação e higiene | Bia Comissão | membro da comissão | + | mobilidade reduzida | transporte para deslocamento no evento | Carla Comissão | membro da comissão | + # Deficiência Física + | deficiente físico | ajuda na mobilidade | Pedro Monitor | monitor | + | deficiente físico | ajuda com alimentação e higiene | Bia Comissão | membro da comissão | + | deficiente físico | transporte para deslocamento no evento | Carla Comissão | membro da comissão | + # Deficiência Visual + | uma pessoa cega | ajuda na mobilidade | Pedro Monitor | monitor | + | uma pessoa cega | programação com audiodescrição | Lucas Comissão | membro da comissão | + # Neurodivergente + | neurodivergente | suporte para pessoas neurodivergentes | Fábio Monitor | monitor | + # Surdocegueira + | uma pessoa surdocega | guia-intérprete | Maria Comissão | membro da comissão | From c65a2f9ba4f372d7d99c2b1b8a7b6e409d037486 Mon Sep 17 00:00:00 2001 From: "Emmanuel N. C. Brito" Date: Sun, 22 Jun 2025 07:03:01 -0300 Subject: [PATCH 13/26] Add step for: nenhum atendente disponivel --- src/test/kotlin/ufrpe/sbpc/botpcd/StepDefinitions.kt | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/test/kotlin/ufrpe/sbpc/botpcd/StepDefinitions.kt b/src/test/kotlin/ufrpe/sbpc/botpcd/StepDefinitions.kt index a1d7dc0..4c5a73f 100644 --- a/src/test/kotlin/ufrpe/sbpc/botpcd/StepDefinitions.kt +++ b/src/test/kotlin/ufrpe/sbpc/botpcd/StepDefinitions.kt @@ -56,7 +56,12 @@ class StepDefinitions( val logger: Logger = LoggerFactory.getLogger(StepDefinitions::class.java) - @Dado("usuário recebeu mensagem {string}") + @Dado("que nenhum atendente para o {string} está disponível") + fun nenhumAtendenteDisponivel(servicoDescricao: String) { + // repositorio comeca vazio, nao precisa fazer nada + } + + @Dado("usuário recebeu mensagem {string}") fun `usuário recebeu mensagem`(message: String) { mockUserRecievedMessage(numberUserNotRegister, message) } @@ -467,4 +472,4 @@ fun String.getBotNumber(): String { fun String.getMessageBody(): String { return this.getChange().messages[0].text.body -} \ No newline at end of file +} From 2d4a82fb198da523f7f4937bb23d53299feb7f99 Mon Sep 17 00:00:00 2001 From: "Emmanuel N. C. Brito" Date: Sun, 22 Jun 2025 07:31:04 -0300 Subject: [PATCH 14/26] Add step for: pcd possui atendimento nao iniciado --- .../ufrpe/sbpc/botpcd/StepDefinitions.kt | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/src/test/kotlin/ufrpe/sbpc/botpcd/StepDefinitions.kt b/src/test/kotlin/ufrpe/sbpc/botpcd/StepDefinitions.kt index 4c5a73f..2e35671 100644 --- a/src/test/kotlin/ufrpe/sbpc/botpcd/StepDefinitions.kt +++ b/src/test/kotlin/ufrpe/sbpc/botpcd/StepDefinitions.kt @@ -56,6 +56,39 @@ class StepDefinitions( val logger: Logger = LoggerFactory.getLogger(StepDefinitions::class.java) + @Dado("PCD possuia serviço requisitado que ainda não foi iniciado") + fun pcdPossuiServicoRequisitadoNaoIniciado() { + val phone = "81999999999" + val service = ServiceType.NeurodivergentSupport + val disabilities = service.disability + + // Reutiliza ou cria o PCD com deficiências compatíveis com o serviço + val pcd = pwdRepository.findByPhoneNumber(phone) ?: pwdRepository.save( + PWD( + name = "PCD Teste", + phoneNumber = phone, + disabilities = disabilities + ) + ) + + // Evita criar duplicata se já existir + val existente = attendanceRepository.findRequestAttendanceOfPwd(pcd) + if (existente == null) { + attendanceRepository.save( + Attendance( + pwd = pcd, + serviceType = service, + attendantType = service.attendantType, + attendant = null, + endDateTime = null, + startDateTime = null, + serviceLocation = null, + monitorArrivalDateTime = null + ) + ) + } + } + @Dado("que nenhum atendente para o {string} está disponível") fun nenhumAtendenteDisponivel(servicoDescricao: String) { // repositorio comeca vazio, nao precisa fazer nada From a26dc23aa939ab5e23ac34ade0e44c68532cada3 Mon Sep 17 00:00:00 2001 From: "Emmanuel N. C. Brito" Date: Sun, 22 Jun 2025 11:24:20 -0300 Subject: [PATCH 15/26] Add step for: pcd solicitou servico e esta na fila de espera --- .../ufrpe/sbpc/botpcd/StepDefinitions.kt | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/src/test/kotlin/ufrpe/sbpc/botpcd/StepDefinitions.kt b/src/test/kotlin/ufrpe/sbpc/botpcd/StepDefinitions.kt index 2e35671..75bab39 100644 --- a/src/test/kotlin/ufrpe/sbpc/botpcd/StepDefinitions.kt +++ b/src/test/kotlin/ufrpe/sbpc/botpcd/StepDefinitions.kt @@ -56,6 +56,40 @@ class StepDefinitions( val logger: Logger = LoggerFactory.getLogger(StepDefinitions::class.java) + @Dado("que {string} PCD solicitou o serviço {string} e está na fila de espera") + fun pcdSolicitouServicoFila(adjetivoDeficiencia: String, servicoDescricao: String) { + val service = ServiceType.getByDescription(servicoDescricao) + + // Usa o método do enum para buscar pela forma textual do adjetivo + val disability = Disability.getByAdjective(adjetivoDeficiencia) + val phone = "81999999999" + + // Cria ou reutiliza o PCD + val pcd = pwdRepository.findByPhoneNumber(phone) ?: pwdRepository.save( + PWD( + name = "PCD $adjetivoDeficiencia", + phoneNumber = phone, + disabilities = setOf(disability) + ) + ) + + // Garante que existe uma solicitação em espera (não iniciada) + if (attendanceRepository.findRequestAttendanceOfPwd(pcd) == null) { + attendanceRepository.save( + Attendance( + pwd = pcd, + serviceType = service, + attendantType = service.attendantType, + attendant = null, + endDateTime = null, + startDateTime = null, + serviceLocation = null, + monitorArrivalDateTime = null + ) + ) + } + } + @Dado("PCD possuia serviço requisitado que ainda não foi iniciado") fun pcdPossuiServicoRequisitadoNaoIniciado() { val phone = "81999999999" From 6a370505bec40646379360a5e8242c4bd88ca063 Mon Sep 17 00:00:00 2001 From: "Emmanuel N. C. Brito" Date: Sun, 22 Jun 2025 11:46:39 -0300 Subject: [PATCH 16/26] in-progress: Add step for: atendente do tipo esta indisponivel --- .../ufrpe/sbpc/botpcd/StepDefinitions.kt | 49 +++++++++++++++++-- 1 file changed, 45 insertions(+), 4 deletions(-) diff --git a/src/test/kotlin/ufrpe/sbpc/botpcd/StepDefinitions.kt b/src/test/kotlin/ufrpe/sbpc/botpcd/StepDefinitions.kt index 75bab39..fbab34f 100644 --- a/src/test/kotlin/ufrpe/sbpc/botpcd/StepDefinitions.kt +++ b/src/test/kotlin/ufrpe/sbpc/botpcd/StepDefinitions.kt @@ -22,9 +22,9 @@ import ufrpe.sbpc.botpcd.entity.Monitor import ufrpe.sbpc.botpcd.entity.MonitorAssistanceType import ufrpe.sbpc.botpcd.entity.MonitorServiceType import ufrpe.sbpc.botpcd.entity.PWD -import ufrpe.sbpc.botpcd.entity.Provider import ufrpe.sbpc.botpcd.entity.ServiceType import ufrpe.sbpc.botpcd.entity.UserStatus +import ufrpe.sbpc.botpcd.entity.Provider import ufrpe.sbpc.botpcd.repository.AttendanceRepository import ufrpe.sbpc.botpcd.repository.AttendantRepository import ufrpe.sbpc.botpcd.repository.CommitteeMemberRepository @@ -39,13 +39,14 @@ import kotlin.test.assertTrue class StepDefinitions( private val mockMvc: MockMvc, + val provider: Provider, val pwdRepository: PWDRepository, - val messageExchangeRepository: MessageExchangeRepository, val monitorRepository: MonitorRepository, - val committeeMemberRepository: CommitteeMemberRepository, - val attendantRepository: AttendantRepository, val attendanceService: AttendanceService, + val attendantRepository: AttendantRepository, val attendanceRepository: AttendanceRepository, + val messageExchangeRepository: MessageExchangeRepository, + val committeeMemberRepository: CommitteeMemberRepository, ) { private var currentBotNumber: String = "15556557522" private val numberUserNotRegister: String = "558187654321" @@ -56,6 +57,46 @@ class StepDefinitions( val logger: Logger = LoggerFactory.getLogger(StepDefinitions::class.java) + @Dado("que o atendente {string} do tipo {string} estava indisponível") + fun atendenteIndisponivel(nome: String, tipo: String) { + val phone = "9999-${nome.replace(" ", "_")}" + val tipo = when (tipo.lowercase()) { + "monitor" -> provider.MONITOR + "membro da comissão" -> provider.COMMITTEE_MEMBER + else -> throw IllegalArgumentException("Tipo de atendente desconhecido: $tipo") + } + + when (tipo) { + provider.MONITOR -> { + val monitor = monitorRepository.findByPhoneNumber(phone) + ?: monitorRepository.save( + Monitor( + name = nome, + phoneNumber = phone, + status = UserStatus.UNAVAILABLE, + assistanceType = MonitorAssistanceType.NEURODIVERGENT_SUPPORT_MONITOR // ou escolha correta + ) + ) + monitor.status = UserStatus.UNAVAILABLE + monitorRepository.save(monitor) + } + + provider.COMMITTEE_MEMBER -> { + val member = attendantRepository.findByPhoneNumber(phone) + ?: attendantRepository.save( + CommitteeMember( + name = nome, + phoneNumber = phone, + status = UserStatus.UNAVAILABLE, + provider = provider + ) + ) + member.status = UserStatus.UNAVAILABLE + attendantRepository.save(member) + } + } + } + @Dado("que {string} PCD solicitou o serviço {string} e está na fila de espera") fun pcdSolicitouServicoFila(adjetivoDeficiencia: String, servicoDescricao: String) { val service = ServiceType.getByDescription(servicoDescricao) From 96aa41f20cc155dfc439d1413aca14212256dee9 Mon Sep 17 00:00:00 2001 From: "Emmanuel N. C. Brito" Date: Sun, 22 Jun 2025 18:48:48 -0300 Subject: [PATCH 17/26] Complete step: Atendente do tipo esta indisponivel --- .../ufrpe/sbpc/botpcd/StepDefinitions.kt | 73 +++++++++---------- 1 file changed, 35 insertions(+), 38 deletions(-) diff --git a/src/test/kotlin/ufrpe/sbpc/botpcd/StepDefinitions.kt b/src/test/kotlin/ufrpe/sbpc/botpcd/StepDefinitions.kt index fbab34f..21b9e81 100644 --- a/src/test/kotlin/ufrpe/sbpc/botpcd/StepDefinitions.kt +++ b/src/test/kotlin/ufrpe/sbpc/botpcd/StepDefinitions.kt @@ -39,7 +39,6 @@ import kotlin.test.assertTrue class StepDefinitions( private val mockMvc: MockMvc, - val provider: Provider, val pwdRepository: PWDRepository, val monitorRepository: MonitorRepository, val attendanceService: AttendanceService, @@ -58,43 +57,41 @@ class StepDefinitions( val logger: Logger = LoggerFactory.getLogger(StepDefinitions::class.java) @Dado("que o atendente {string} do tipo {string} estava indisponível") - fun atendenteIndisponivel(nome: String, tipo: String) { - val phone = "9999-${nome.replace(" ", "_")}" - val tipo = when (tipo.lowercase()) { - "monitor" -> provider.MONITOR - "membro da comissão" -> provider.COMMITTEE_MEMBER - else -> throw IllegalArgumentException("Tipo de atendente desconhecido: $tipo") - } - - when (tipo) { - provider.MONITOR -> { - val monitor = monitorRepository.findByPhoneNumber(phone) - ?: monitorRepository.save( - Monitor( - name = nome, - phoneNumber = phone, - status = UserStatus.UNAVAILABLE, - assistanceType = MonitorAssistanceType.NEURODIVERGENT_SUPPORT_MONITOR // ou escolha correta - ) - ) - monitor.status = UserStatus.UNAVAILABLE - monitorRepository.save(monitor) - } - - provider.COMMITTEE_MEMBER -> { - val member = attendantRepository.findByPhoneNumber(phone) - ?: attendantRepository.save( - CommitteeMember( - name = nome, - phoneNumber = phone, - status = UserStatus.UNAVAILABLE, - provider = provider - ) - ) - member.status = UserStatus.UNAVAILABLE - attendantRepository.save(member) - } - } + fun atendenteIndisponivel(nome: String, tipoDeAtendente: String) { + val phone = "9999-${nome.replace(" ", "_")}" + + // Mapeia diretamente o texto para o enum + val provider = when (tipoDeAtendente.lowercase()) { + "monitor" -> Provider.MONITOR + "membro da comissão" -> Provider.COMMITTEE_MEMBER + else -> throw IllegalArgumentException("Tipo de atendente desconhecido: $tipoDeAtendente") + } + + // Cria ou atualiza o atendente indisponível diretamente + if (provider == Provider.MONITOR) { + val monitor = monitorRepository.findByPhoneNumber(phone) + ?: monitorRepository.save( + Monitor( + name = nome, + phoneNumber = phone, + status = UserStatus.UNAVAILABLE, + assistanceType = MonitorAssistanceType.NEURODIVERGENT_SUPPORT_MONITOR // ou ajuste se quiser + ) + ) + monitor.status = UserStatus.UNAVAILABLE + monitorRepository.save(monitor) + } else if (provider == Provider.COMMITTEE_MEMBER) { + val member = attendantRepository.findByPhoneNumber(phone) + ?: attendantRepository.save( + CommitteeMember( + name = nome, + phoneNumber = phone, + status = UserStatus.UNAVAILABLE, + ) + ) + member.status = UserStatus.UNAVAILABLE + attendantRepository.save(member) + } } @Dado("que {string} PCD solicitou o serviço {string} e está na fila de espera") From cbe7ea86dba60bf262afe0344eb69a9dd9c0cf6b Mon Sep 17 00:00:00 2001 From: "Emmanuel N. C. Brito" Date: Sun, 22 Jun 2025 18:58:22 -0300 Subject: [PATCH 18/26] [AVALIAR] Add IA step sugestion: quanto atendente especifico fica disponivel --- .../ufrpe/sbpc/botpcd/StepDefinitions.kt | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/src/test/kotlin/ufrpe/sbpc/botpcd/StepDefinitions.kt b/src/test/kotlin/ufrpe/sbpc/botpcd/StepDefinitions.kt index 21b9e81..9f4e3a5 100644 --- a/src/test/kotlin/ufrpe/sbpc/botpcd/StepDefinitions.kt +++ b/src/test/kotlin/ufrpe/sbpc/botpcd/StepDefinitions.kt @@ -94,6 +94,30 @@ class StepDefinitions( } } + @Quando("o atendente {string} fica disponível") + fun atendenteFicaDisponivel(nome: String) { + val phone = "9999-${nome.replace(" ", "_")}" + + // Tenta encontrar no repositório de monitores + val monitor = monitorRepository.findByPhoneNumber(phone) + if (monitor != null) { + monitor.status = UserStatus.AVAILABLE + monitorRepository.save(monitor) + return + } + + // Se não encontrar no repositório de monitores, procura no de membros da comissão + val member = attendantRepository.findByPhoneNumber(phone) + if (member != null) { + member.status = UserStatus.AVAILABLE + attendantRepository.save(member) + return + } + + // Se não encontrou em nenhum dos dois + throw IllegalArgumentException("Atendente '$nome' não encontrado.") + } + @Dado("que {string} PCD solicitou o serviço {string} e está na fila de espera") fun pcdSolicitouServicoFila(adjetivoDeficiencia: String, servicoDescricao: String) { val service = ServiceType.getByDescription(servicoDescricao) From dc64e8c6dfa401a7e6e78542a8c05810a91b226e Mon Sep 17 00:00:00 2001 From: "Emmanuel N. C. Brito" Date: Sun, 22 Jun 2025 19:12:54 -0300 Subject: [PATCH 19/26] Fix test not have number identifier --- .../ufrpe/sbpc/botpcd/acessarServicos.feature | 31 ++++++++++--------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/src/test/resources/ufrpe/sbpc/botpcd/acessarServicos.feature b/src/test/resources/ufrpe/sbpc/botpcd/acessarServicos.feature index 5fdb127..783ee9a 100644 --- a/src/test/resources/ufrpe/sbpc/botpcd/acessarServicos.feature +++ b/src/test/resources/ufrpe/sbpc/botpcd/acessarServicos.feature @@ -97,27 +97,28 @@ Funcionalidade: Acessar serviços de assistência Esquema do Cenário: Atendente disponível é direcionado para PCD na fila de espera Dado que "" PCD solicitou o serviço "" e está na fila de espera - E que o atendente "" do tipo "" estava indisponível - Quando o atendente "" fica disponível + E que o atendente "" de "" do tipo "" estava indisponível + Quando o atendente "" de "" fica disponível Entao "" PCD receberá mensagem "O irá realizar seu atendimento." Exemplos: - | adjetivo_da_deficiencia | servico_desejado | nome_do_atendente | tipo_de_atendente | + | adjetivo_da_deficiencia | servico_desejado | nome_do_atendente | tipo_de_atendente | numero_atendente | # Deficiência Auditiva - | um pessoa surda | informações em Libras | Ana Monitor | monitor | - | um pessoa surda | atividade com interpretação em Libras | João Comissão | membro da comissão | + | um pessoa surda | informações em Libras | Ana Monitor | monitor | (00)00000-0001 | + | um pessoa surda | atividade com interpretação em Libras | João Comissão | membro da comissão | (00)00000-0002 | # Mobilidade Reduzida - | mobilidade reduzida | ajuda na mobilidade | Pedro Monitor | monitor | - | mobilidade reduzida | ajuda com alimentação e higiene | Bia Comissão | membro da comissão | - | mobilidade reduzida | transporte para deslocamento no evento | Carla Comissão | membro da comissão | + | mobilidade reduzida | ajuda na mobilidade | Pedro Monitor | monitor | (00)00000-0003 | + | mobilidade reduzida | ajuda com alimentação e higiene | Bia Comissão | membro da comissão | (00)00000-0004 | + | mobilidade reduzida | transporte para deslocamento no evento | Carla Comissão | membro da comissão | (00)00000-0005 | # Deficiência Física - | deficiente físico | ajuda na mobilidade | Pedro Monitor | monitor | - | deficiente físico | ajuda com alimentação e higiene | Bia Comissão | membro da comissão | - | deficiente físico | transporte para deslocamento no evento | Carla Comissão | membro da comissão | + | deficiente físico | ajuda na mobilidade | Pedro Monitor | monitor | (00)00000-0006 | + | deficiente físico | ajuda com alimentação e higiene | Bia Comissão | membro da comissão | (00)00000-0007 | + | deficiente físico | transporte para deslocamento no evento | Carla Comissão | membro da comissão | (00)00000-0008 | # Deficiência Visual - | uma pessoa cega | ajuda na mobilidade | Pedro Monitor | monitor | - | uma pessoa cega | programação com audiodescrição | Lucas Comissão | membro da comissão | + | uma pessoa cega | ajuda na mobilidade | Pedro Monitor | monitor | (00)00000-0009 | + | uma pessoa cega | programação com audiodescrição | Lucas Comissão | membro da comissão | (00)00000-0010 | # Neurodivergente - | neurodivergente | suporte para pessoas neurodivergentes | Fábio Monitor | monitor | + | neurodivergente | suporte para pessoas neurodivergentes | Fábio Monitor | monitor | (00)00000-0011 | # Surdocegueira - | uma pessoa surdocega | guia-intérprete | Maria Comissão | membro da comissão | + | uma pessoa surdocega | guia-intérprete | Maria Comissão | membro da comissão | (00)00000-0012 | + From a5f3629e86fc23821e598e4425fa06dd1b873d9e Mon Sep 17 00:00:00 2001 From: "Emmanuel N. C. Brito" Date: Sun, 22 Jun 2025 19:18:10 -0300 Subject: [PATCH 20/26] Redo step with number: atendente de numero, nome e tipo esta indisponivel --- .../ufrpe/sbpc/botpcd/StepDefinitions.kt | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/src/test/kotlin/ufrpe/sbpc/botpcd/StepDefinitions.kt b/src/test/kotlin/ufrpe/sbpc/botpcd/StepDefinitions.kt index 9f4e3a5..b60da5c 100644 --- a/src/test/kotlin/ufrpe/sbpc/botpcd/StepDefinitions.kt +++ b/src/test/kotlin/ufrpe/sbpc/botpcd/StepDefinitions.kt @@ -56,24 +56,22 @@ class StepDefinitions( val logger: Logger = LoggerFactory.getLogger(StepDefinitions::class.java) - @Dado("que o atendente {string} do tipo {string} estava indisponível") - fun atendenteIndisponivel(nome: String, tipoDeAtendente: String) { - val phone = "9999-${nome.replace(" ", "_")}" - // Mapeia diretamente o texto para o enum + @Dado("que o atendente {string} de {string} do tipo {string} estava indisponível") + fun atendenteIndisponivel(nome: String, numero: String, tipoDeAtendente: String) { + val provider = when (tipoDeAtendente.lowercase()) { "monitor" -> Provider.MONITOR "membro da comissão" -> Provider.COMMITTEE_MEMBER else -> throw IllegalArgumentException("Tipo de atendente desconhecido: $tipoDeAtendente") } - // Cria ou atualiza o atendente indisponível diretamente if (provider == Provider.MONITOR) { - val monitor = monitorRepository.findByPhoneNumber(phone) + val monitor = monitorRepository.findByPhoneNumber(numero) ?: monitorRepository.save( Monitor( name = nome, - phoneNumber = phone, + phoneNumber = numero, status = UserStatus.UNAVAILABLE, assistanceType = MonitorAssistanceType.NEURODIVERGENT_SUPPORT_MONITOR // ou ajuste se quiser ) @@ -81,12 +79,12 @@ class StepDefinitions( monitor.status = UserStatus.UNAVAILABLE monitorRepository.save(monitor) } else if (provider == Provider.COMMITTEE_MEMBER) { - val member = attendantRepository.findByPhoneNumber(phone) + val member = attendantRepository.findByPhoneNumber(numero) ?: attendantRepository.save( CommitteeMember( name = nome, - phoneNumber = phone, - status = UserStatus.UNAVAILABLE, + phoneNumber = numero, + status = UserStatus.UNAVAILABLE ) ) member.status = UserStatus.UNAVAILABLE From 3b111ef2dd0c9fb392607ebfbf4bfb481e45700f Mon Sep 17 00:00:00 2001 From: "Emmanuel N. C. Brito" Date: Sun, 22 Jun 2025 19:21:09 -0300 Subject: [PATCH 21/26] Redo step with number: Atendente de nome e numero esta disponivel --- .../ufrpe/sbpc/botpcd/StepDefinitions.kt | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/src/test/kotlin/ufrpe/sbpc/botpcd/StepDefinitions.kt b/src/test/kotlin/ufrpe/sbpc/botpcd/StepDefinitions.kt index b60da5c..2eac443 100644 --- a/src/test/kotlin/ufrpe/sbpc/botpcd/StepDefinitions.kt +++ b/src/test/kotlin/ufrpe/sbpc/botpcd/StepDefinitions.kt @@ -92,28 +92,26 @@ class StepDefinitions( } } - @Quando("o atendente {string} fica disponível") - fun atendenteFicaDisponivel(nome: String) { - val phone = "9999-${nome.replace(" ", "_")}" - - // Tenta encontrar no repositório de monitores - val monitor = monitorRepository.findByPhoneNumber(phone) + @Quando("o atendente {string} de {string} fica disponível") + fun atendenteFicaDisponivel(nome: String, numero: String) { + // Tenta encontrar o atendente no repositório de monitores + val monitor = monitorRepository.findByPhoneNumber(numero) if (monitor != null) { monitor.status = UserStatus.AVAILABLE monitorRepository.save(monitor) return } - // Se não encontrar no repositório de monitores, procura no de membros da comissão - val member = attendantRepository.findByPhoneNumber(phone) + // Tenta encontrar o atendente no repositório de membros da comissão + val member = attendantRepository.findByPhoneNumber(numero) if (member != null) { member.status = UserStatus.AVAILABLE attendantRepository.save(member) return } - // Se não encontrou em nenhum dos dois - throw IllegalArgumentException("Atendente '$nome' não encontrado.") + // Se não encontrar nenhum atendente + throw IllegalArgumentException("Atendente '$nome' com número '$numero' não encontrado.") } @Dado("que {string} PCD solicitou o serviço {string} e está na fila de espera") From a3ba2c0584346b6ddd4dbaf9cca50b91059c3d66 Mon Sep 17 00:00:00 2001 From: victor-yghor Date: Mon, 23 Jun 2025 12:01:09 -0300 Subject: [PATCH 22/26] Add ausent tests of cucumber Co-authored-by: Emmanuel N. C. Brito --- .../ufrpe/sbpc/botpcd/entity/ServiceType.kt | 7 +- .../botpcd/repository/AttendantRepository.kt | 1 + .../botpcd/repository/MonitorRepository.kt | 1 + .../ufrpe/sbpc/botpcd/StepDefinitions.kt | 172 +++++++++++++++++- .../ufrpe/sbpc/botpcd/acessarServicos.feature | 74 ++++---- 5 files changed, 214 insertions(+), 41 deletions(-) diff --git a/src/main/kotlin/ufrpe/sbpc/botpcd/entity/ServiceType.kt b/src/main/kotlin/ufrpe/sbpc/botpcd/entity/ServiceType.kt index 3ae7376..2be6e87 100644 --- a/src/main/kotlin/ufrpe/sbpc/botpcd/entity/ServiceType.kt +++ b/src/main/kotlin/ufrpe/sbpc/botpcd/entity/ServiceType.kt @@ -51,7 +51,7 @@ sealed class ServiceType( object HygieneAndNutrition : ServiceType( attendantType = Provider.COMMITTEE_MEMBER, - disability = mutableSetOf(Disability.MOBILITY_IMPAIRED, Disability.PHYSICAL_DISABILITY), + disability = mutableSetOf(Disability.PHYSICAL_DISABILITY), description = "ajuda com alimentação e higiene" ) @@ -66,7 +66,7 @@ sealed class ServiceType( fun getServicesByDisability(disability: Disability): List { return ServiceType::class.sealedSubclasses .mapNotNull { it.objectInstance } - .filter { disability in it.disability } + .filter { disability in it.disability }.sortedBy { it.description.getAlphabeticOrder() } } fun getServiceByMonitorAssistanceType(monitorAssistanceType: MonitorAssistanceType): ServiceType { return ServiceType::class.sealedSubclasses @@ -81,6 +81,9 @@ sealed class ServiceType( } } } + +fun String.getAlphabeticOrder() = this.replace("[^a-zA-Z]".toRegex(), "").slice(0..9).reduce {prev, curr -> prev + curr.code} + interface MonitorServiceType { val monitorAssistanceType: MonitorAssistanceType } \ No newline at end of file diff --git a/src/main/kotlin/ufrpe/sbpc/botpcd/repository/AttendantRepository.kt b/src/main/kotlin/ufrpe/sbpc/botpcd/repository/AttendantRepository.kt index 52dcd10..b88cbbd 100644 --- a/src/main/kotlin/ufrpe/sbpc/botpcd/repository/AttendantRepository.kt +++ b/src/main/kotlin/ufrpe/sbpc/botpcd/repository/AttendantRepository.kt @@ -5,4 +5,5 @@ import ufrpe.sbpc.botpcd.entity.Attendant interface AttendantRepository: JpaRepository { fun findByPhoneNumber(phone: String): Attendant? + fun findByName(name: String): Attendant? } \ No newline at end of file diff --git a/src/main/kotlin/ufrpe/sbpc/botpcd/repository/MonitorRepository.kt b/src/main/kotlin/ufrpe/sbpc/botpcd/repository/MonitorRepository.kt index dfe6ec1..1ca4f61 100644 --- a/src/main/kotlin/ufrpe/sbpc/botpcd/repository/MonitorRepository.kt +++ b/src/main/kotlin/ufrpe/sbpc/botpcd/repository/MonitorRepository.kt @@ -8,6 +8,7 @@ import ufrpe.sbpc.botpcd.entity.UserStatus interface MonitorRepository : JpaRepository{ fun findByPhoneNumber(phoneNumber: String): Monitor? + fun findByName(phoneName: String): Monitor? fun findByStatus(status: UserStatus): List @Query("SELECT m from Monitor m where m.status = :status and m.assistanceType = :assistanceType") fun findAvailableMonitor(status: UserStatus, assistanceType: MonitorAssistanceType): List diff --git a/src/test/kotlin/ufrpe/sbpc/botpcd/StepDefinitions.kt b/src/test/kotlin/ufrpe/sbpc/botpcd/StepDefinitions.kt index 2eac443..f77398d 100644 --- a/src/test/kotlin/ufrpe/sbpc/botpcd/StepDefinitions.kt +++ b/src/test/kotlin/ufrpe/sbpc/botpcd/StepDefinitions.kt @@ -34,8 +34,11 @@ import ufrpe.sbpc.botpcd.repository.PWDRepository import ufrpe.sbpc.botpcd.service.AttendanceService import java.io.File import java.time.LocalDateTime +import kotlin.assert +import kotlin.test.assertFalse // import java.math.BigInteger // Não é mais necessário para os steps de atendente import kotlin.test.assertTrue +import kotlin.text.contains class StepDefinitions( private val mockMvc: MockMvc, @@ -55,9 +58,160 @@ class StepDefinitions( private val possibleItialsMessages = mutableListOf("Oi", "Olá", "Bom dia", "Boa noite", "Boa Tarde", "teste") val logger: Logger = LoggerFactory.getLogger(StepDefinitions::class.java) + @Dado("que o atendente {string} de telefone {string} enviou mensagem nas últimas 24 horas") + fun `atendente enviou mensagem recente`(nomeAtendente: String, telefoneAtendente: String) { + monitorRepository.save( + Monitor( + name = nomeAtendente, + phoneNumber = telefoneAtendente, + status = UserStatus.AVAILABLE, + assistanceType = MonitorAssistanceType.NEURODIVERGENT_SUPPORT_MONITOR + ) + ) + userSendMessage("Olá, estou ativo.", telefoneAtendente) + } + + @Dado("que o PCD {string} de telefone {string} enviou mensagem nas últimas 24 horas") + fun `pcd enviou mensagem recente`(nomePcd: String, telefonePcd: String) { + pwdRepository.save( + PWD( + name = nomePcd, + phoneNumber = telefonePcd, + disabilities = setOf(Disability.NEURODIVERGENT) + ) + ) + userSendMessage("Olá, estou ativo.", telefonePcd) + } + + @Dado( + "que o atendente {string} de telefone {string} está em atendimento com o PCD {string} de telefone {string}" + ) + fun atendenteEmAtendimentoComPCD( + nomeAtendente: String, + telefoneAtendente: String, + nomePcd: String, + telefonePcd: String + ) { + val pcd = pwdRepository.findByPhoneNumber(telefonePcd)!! + val monitor = monitorRepository.findByPhoneNumber(telefoneAtendente) + val attendance = Attendance( + serviceType = ServiceType.NeurodivergentSupport, + pwd = pcd, + attendant = monitor, + attendantType = Provider.MONITOR, + startDateTime = LocalDateTime.now() + ) + attendanceRepository.save(attendance) + } + + @Dado( + "que o PCD {string} de telefone {string} não está em atendimento com {string}" + ) + fun pcdNaoEstaEmAtendimentoCom(nomePcd: String, telefonePcd: String, nomeAtendente: String) { + val pcd = pwdRepository.findByPhoneNumber(telefonePcd)!! + attendanceRepository.deleteAllByPwd(pcd) + } + + @Quando("o atendente {string} de telefone {string} envia a mensagem {string}") + fun atendenteEnviaMensagem(nomeAtendente: String, telefoneAtendente: String, mensagem: String) { + userSendMessage(mensagem, telefoneAtendente) + } + + @Entao("o PCD {string} de telefone {string} deve receber a mensagem {string} do atendente {string}") + fun pcdDeveReceberMensagemDoAtendente( + nomePcd: String, + telefonePcd: String, + mensagem: String, + nomeAtendente: String + ) { + val telefoneAtendente = monitorRepository.findByName(nomeAtendente)!!.phoneNumber + val ultimaMensagem = messageExchangeRepository.lastExchangeMessage( + toPhoneNumber = telefonePcd, + fromPhoneNumber = telefoneAtendente + ) + + assert(ultimaMensagem != null && ultimaMensagem!!.message.contains(mensagem)) { + "O PCD $nomePcd não recebeu a mensagem esperada \"$mensagem\" do atendente $nomeAtendente." + } + } + + @Entao("o PCD {string} de telefone {string} não deve receber nenhuma nova mensagem de {string}") + fun pcdNaoDeveReceberMensagem(nomePcd: String, telefonePcd: String, nomeAtendete: String) { + val attendant = attendantRepository.findByName(nomeAtendete) + val lastMessage = messageExchangeRepository.lastExchangeMessage( + toPhoneNumber = telefonePcd, + fromPhoneNumber = currentBotNumber// Ou ajuste conforme sua lógica para buscar todas + )!!.message + + assertFalse (lastMessage!!contains(attendant)) + } + + @Quando("o atendente {string} de telefone {string} encerra o atendimento") + fun atendenteEncerraAtendimento(nomeAtendente: String, telefoneAtendente: String) { + userSendMessage("botpcd", telefoneAtendente) + userSendMessage("1", telefoneAtendente) + } + @Entao("o PCD {string} de telefone {string} deve receber a mensagem {string} do bot") + fun pcdDeveReceberMensagem(nomePcd: String, telefonePcd: String, mensagem: String) { + val ultimaMensagem = messageExchangeRepository.lastExchangeMessage( + toPhoneNumber = telefonePcd, + fromPhoneNumber = currentBotNumber + )?.message + + assert(ultimaMensagem != null && ultimaMensagem.contains(mensagem)) { + "O PCD $nomePcd não recebeu a mensagem esperada \"$mensagem\"." + } + } + + + @Dado( + "que o atendente {string} de telefone {string} está disponível, mas não em atendimento" + ) + fun atendenteDisponivelNaoEmAtendimento(nomeAtendente: String, telefoneAtendente: String) { + monitorRepository.findByPhoneNumber(telefoneAtendente) ?: monitorRepository.save( + Monitor( + name = nomeAtendente, + phoneNumber = telefoneAtendente, + status = UserStatus.AVAILABLE, + assistanceType = MonitorAssistanceType.NEURODIVERGENT_SUPPORT_MONITOR // Tipo genérico + ) + ) + } + + @Quando("o PCD {string} de telefone {string} envia a mensagem {string}") + fun pcdEnviaMensagem(nomePcd: String, telefonePcd: String, mensagem: String) { + // O nome do PCD é usado apenas para clareza no teste. + userSendMessage(mensagem, telefonePcd) + } + + @Entao("o atendente {string} de telefone {string} deve receber a mensagem {string} do PCD {string}") + fun atendenteDeveReceberMensagem( + nomeAtendente: String, + telefoneAtendente: String, + mensagem: String, + nomePcd: String + ) { + // O nome do atendente é para clareza no teste. + val mensagemEsperada = """ + *${nomePcd}*: + $mensagem + """.trimIndent() - @Dado("que o atendente {string} de {string} do tipo {string} estava indisponível") + testarUltimaMensagemRecebidaDoUsuario(mensagemEsperada, telefoneAtendente) + } + + @Entao("o atendente {string} de telefone {string} não deve receber nenhuma nova mensagem do pcd {string}") + fun atendenteNaoDeveReceberMensagem(nomeAtendente: String, telefoneAtendente: String, nomePCD: String) { + val lastMensage = messageExchangeRepository.lastExchangeMessage( + toPhoneNumber = telefoneAtendente, + fromPhoneNumber = currentBotNumber + )!!.message + + assertFalse(lastMensage.contains(nomePCD)) + } + + @Dado("que o atendente {string} de {string} do tipo {string} estava indisponível") fun atendenteIndisponivel(nome: String, numero: String, tipoDeAtendente: String) { val provider = when (tipoDeAtendente.lowercase()) { @@ -147,18 +301,17 @@ class StepDefinitions( ) } } - + @Dado("PCD possuia serviço requisitado que ainda não foi iniciado") fun pcdPossuiServicoRequisitadoNaoIniciado() { - val phone = "81999999999" val service = ServiceType.NeurodivergentSupport val disabilities = service.disability // Reutiliza ou cria o PCD com deficiências compatíveis com o serviço - val pcd = pwdRepository.findByPhoneNumber(phone) ?: pwdRepository.save( + val pcd = pwdRepository.findByPhoneNumber(pwdAcessarServicesPhoneNumber) ?: pwdRepository.save( PWD( name = "PCD Teste", - phoneNumber = phone, + phoneNumber = pwdAcessarServicesPhoneNumber, disabilities = disabilities ) ) @@ -416,6 +569,15 @@ class StepDefinitions( else -> throw IllegalArgumentException("Tipo de atendente desconhecido: $tipoAtendente") } } + @Quando("PCD mandar qualquer mensagem") + fun `PCD mandar qualquer mensagem`() { + val message = possibleItialsMessages.random() + userSendMessage(message, pwdAcessarServicesPhoneNumber) + } + @Entao("PCD receberá mensagem {string}") + fun `PCD recebera mensagem`(mensagemEsperada: String) { + testarUltimaMensagemRecebidaDoUsuario(mensagemEsperada, pwdAcessarServicesPhoneNumber) + } @Dado("que sou um {string} com status inicial {string}") fun `que sou um tipo_de_atendente com status inicial`( tipoAtendente: String, diff --git a/src/test/resources/ufrpe/sbpc/botpcd/acessarServicos.feature b/src/test/resources/ufrpe/sbpc/botpcd/acessarServicos.feature index 783ee9a..226394e 100644 --- a/src/test/resources/ufrpe/sbpc/botpcd/acessarServicos.feature +++ b/src/test/resources/ufrpe/sbpc/botpcd/acessarServicos.feature @@ -25,15 +25,14 @@ Funcionalidade: Acessar serviços de assistência Exemplos: | adjetivo_da_deficiencia | nome_do_atendente | servico_desejado | numero_servico_desejado | tipo_de_atendente | # Deficiência Auditiva - | um pessoa surda | Ana Monitor | informações em Libras | 1 | monitor | - | um pessoa surda | João Comissão | atividade com interpretação em Libras | 2 | membro da comissão | + | um pessoa surda | João Comissão | atividade com interpretação em Libras | 1 | membro da comissão | + | um pessoa surda | Ana Monitor | informações em Libras | 2 | monitor | # Mobilidade Reduzida | mobilidade reduzida | Pedro Monitor | ajuda na mobilidade | 1 | monitor | - | mobilidade reduzida | Bia Comissão | ajuda com alimentação e higiene | 2 | membro da comissão | - | mobilidade reduzida | Carla Comissão | transporte para deslocamento no evento | 3 | membro da comissão | + | mobilidade reduzida | Carla Comissão | transporte para deslocamento no evento | 2 | membro da comissão | # Deficiência Física - | deficiente físico | Pedro Monitor | ajuda na mobilidade | 1 | monitor | - | deficiente físico | Bia Comissão | ajuda com alimentação e higiene | 2 | membro da comissão | + | deficiente físico | Bia Comissão | ajuda com alimentação e higiene | 1 | membro da comissão | + | deficiente físico | Pedro Monitor | ajuda na mobilidade | 2 | monitor | | deficiente físico | Carla Comissão | transporte para deslocamento no evento | 3 | membro da comissão | # Deficiência Visual | uma pessoa cega | Pedro Monitor | ajuda na mobilidade | 1 | monitor | @@ -52,48 +51,56 @@ Funcionalidade: Acessar serviços de assistência Entao "" PCD receberá mensagem "No momento não há atendentes disponíveis. Por favor, aguarde na fila de espera e retornaremos assim que possível." Exemplos: - | adjetivo_da_deficiencia | servico_desejado | numero_servico_desejado | + | adjetivo_da_deficiencia | nome_do_atendente | servico_desejado | numero_servico_desejado | # Deficiência Auditiva - | um pessoa surda | informações em Libras | 1 | - | um pessoa surda | atividade com interpretação em Libras | 2 | + | um pessoa surda | João Comissão | atividade com interpretação em Libras | 1 | + | um pessoa surda | Ana Monitor | informações em Libras | 2 | # Mobilidade Reduzida - | mobilidade reduzida | ajuda na mobilidade | 1 | - | mobilidade reduzida | ajuda com alimentação e higiene | 2 | - | mobilidade reduzida | transporte para deslocamento no evento | 3 | + | mobilidade reduzida | Pedro Monitor | ajuda na mobilidade | 1 | + | mobilidade reduzida | Carla Comissão | transporte para deslocamento no evento | 2 | # Deficiência Física - | deficiente físico | ajuda na mobilidade | 1 | - | deficiente físico | ajuda com alimentação e higiene | 2 | - | deficiente físico | transporte para deslocamento no evento | 3 | + | deficiente físico | Bia Comissão | ajuda com alimentação e higiene | 1 | + | deficiente físico | Pedro Monitor | ajuda na mobilidade | 2 | + | deficiente físico | Carla Comissão | transporte para deslocamento no evento | 3 | # Deficiência Visual - | uma pessoa cega | ajuda na mobilidade | 1 | - | uma pessoa cega | programação com audiodescrição | 2 | + | uma pessoa cega | Pedro Monitor | ajuda na mobilidade | 1 | + | uma pessoa cega | Lucas Comissão | programação com audiodescrição | 2 | # Neurodivergente - | neurodivergente | suporte para pessoas neurodivergentes | 1 | + | neurodivergente | Fábio Monitor | suporte para pessoas neurodivergentes | 1 | # Surdocegueira - | uma pessoa surdocega | guia-intérprete | 1 | + | uma pessoa surdocega | Maria Comissão | guia-intérprete | 1 | + Cenário: PCD está na fila de espera e manda mensagem novamente Dado PCD possuia serviço requisitado que ainda não foi iniciado Quando PCD mandar qualquer mensagem Então PCD receberá mensagem "No momento não há atendentes disponíveis. Por favor, aguarde na fila de espera e retornaremos assim que possível." + Regra: Bot envia mensagem apenas para o usuário que mandaram mensagem nas últimas 24 horas + + Cenário de Fundo: que o atendente "Carlos" de telefone "558100000001" enviou mensagem nas últimas 24 horas + E que o PCD "João" de telefone "558100000002" enviou mensagem nas últimas 24 horas + E que o atendente "Ana" de telefone "558100000003" enviou mensagem nas últimas 24 horas + E que o PCD "Maria" de telefone "558100000004" enviou mensagem nas útlimas 24 horas - Cenário: Bot direciona mensagem do PCD para o atendente correto - Dado Atendente aceitou o atendimento do PCD - Quando pcd envia qualquer mensagem para o bot - Então o Atendente deve receber a mensagem do PCD contendo o nome do PCD - E nemhum outro Atendente ou PCD deve receber a mesma mensagem + Cenário: Bot direciona mensagem do PCD para o atendente correto + Dado que o atendente "Carlos" de telefone "558100000001" está em atendimento com o PCD "João" de telefone "558100000002" + E que o atendente "Ana" de telefone "558100000003" está disponível, mas não em atendimento + Quando o PCD "João" de telefone "558100000002" envia a mensagem "Onde fica o banheiro mais próximo?" + Então o atendente "Carlos" de telefone "558100000001" deve receber a mensagem "Onde fica o banheiro mais próximo?" do PCD "João" + E o atendente "Ana" de telefone "558100000003" não deve receber nenhuma nova mensagem do pcd "João" - Cenário: Bot direciona mensagem do atendente para o PCD correto - Dado que o Atendente aceitou o atendimento do PCD - Quando atendente envia uma mensagem para o bot - Então PCD deve receber a mensagem do Atendente contendo nome do atendente - E nemhum outro PCD ou Atendente deve receber a mesma mensagem + Cenário: Bot direciona mensagem do atendente para o PCD correto em um atendimento ativo + Dado que o atendente "Carlos" de telefone "558100000001" está em atendimento com o PCD "João" de telefone "558100000002" + E que o PCD "Maria" de telefone "558100000004" não está em atendimento com "Carlos" + Quando o atendente "Carlos" de telefone "558100000001" envia a mensagem "Estou a caminho para ajudar." + Então o PCD "João" de telefone "558100000002" deve receber a mensagem "Estou a caminho para ajudar." do atendente "Carlos" + E o PCD "Maria" de telefone "558100000004" não deve receber nenhuma nova mensagem de "Carlos" - Cenario: Avisar que o atendimento foi encerrado - Dado atendente estava em atendimento com um pcd - Quando atendente encerrou o atendimento - Entao pcd receberá mensagem "Atendimento Encerrado" + Cenário: Atendente encerra o atendimento e PCD é notificado + Dado que o atendente "Carlos" de telefone "558100000001" está em atendimento com o PCD "João" de telefone "558100000002" + Quando o atendente "Carlos" de telefone "558100000001" encerra o atendimento + Então o PCD "João" de telefone "558100000002" deve receber a mensagem "Atendimento encerrado" do bot Esquema do Cenário: Atendente disponível é direcionado para PCD na fila de espera Dado que "" PCD solicitou o serviço "" e está na fila de espera @@ -108,7 +115,6 @@ Funcionalidade: Acessar serviços de assistência | um pessoa surda | atividade com interpretação em Libras | João Comissão | membro da comissão | (00)00000-0002 | # Mobilidade Reduzida | mobilidade reduzida | ajuda na mobilidade | Pedro Monitor | monitor | (00)00000-0003 | - | mobilidade reduzida | ajuda com alimentação e higiene | Bia Comissão | membro da comissão | (00)00000-0004 | | mobilidade reduzida | transporte para deslocamento no evento | Carla Comissão | membro da comissão | (00)00000-0005 | # Deficiência Física | deficiente físico | ajuda na mobilidade | Pedro Monitor | monitor | (00)00000-0006 | From 43b04e9645e4422b3ca364a39445c444b4c3924a Mon Sep 17 00:00:00 2001 From: victor-yghor Date: Tue, 24 Jun 2025 10:14:03 -0300 Subject: [PATCH 23/26] Solve the problem with redirect messages --- .../botpcd/repository/AttendanceRepository.kt | 6 +- .../sbpc/botpcd/service/PWDFlowService.kt | 16 +- .../ufrpe/sbpc/botpcd/StepDefinitions.kt | 368 ++++++++++-------- .../ufrpe/sbpc/botpcd/acessarServicos.feature | 5 +- 4 files changed, 226 insertions(+), 169 deletions(-) diff --git a/src/main/kotlin/ufrpe/sbpc/botpcd/repository/AttendanceRepository.kt b/src/main/kotlin/ufrpe/sbpc/botpcd/repository/AttendanceRepository.kt index 66a2cf8..5437e4e 100644 --- a/src/main/kotlin/ufrpe/sbpc/botpcd/repository/AttendanceRepository.kt +++ b/src/main/kotlin/ufrpe/sbpc/botpcd/repository/AttendanceRepository.kt @@ -5,9 +5,9 @@ import org.springframework.data.jpa.repository.Modifying import org.springframework.data.jpa.repository.Query import org.springframework.data.repository.query.Param import ufrpe.sbpc.botpcd.entity.Attendance -import ufrpe.sbpc.botpcd.entity.ServiceType import ufrpe.sbpc.botpcd.entity.Attendant import ufrpe.sbpc.botpcd.entity.PWD +import ufrpe.sbpc.botpcd.entity.ServiceType import java.time.LocalDateTime interface AttendanceRepository : JpaRepository { @@ -38,4 +38,8 @@ interface AttendanceRepository : JpaRepository { @Modifying(flushAutomatically = true, clearAutomatically = true) // Modificação aqui @Query("DELETE FROM Attendance a WHERE a.pwd = :pwd") fun deleteAllByPwd(@Param("pwd") pwd: PWD) + + @Modifying(flushAutomatically = true, clearAutomatically = true) // Modificação aqui + @Query("DELETE FROM Attendance a WHERE a.attendant = :att") + fun deleteAllByAttendant(@Param("att") att: Attendant) } diff --git a/src/main/kotlin/ufrpe/sbpc/botpcd/service/PWDFlowService.kt b/src/main/kotlin/ufrpe/sbpc/botpcd/service/PWDFlowService.kt index f095a64..b125744 100644 --- a/src/main/kotlin/ufrpe/sbpc/botpcd/service/PWDFlowService.kt +++ b/src/main/kotlin/ufrpe/sbpc/botpcd/service/PWDFlowService.kt @@ -37,14 +37,6 @@ class PWDFlowService( whatsappService.sendMessage(botNumber, phoneNumber, "Cadastro realizado.") attendanceService.sendServices(botNumber, pwd) } - isChoosingService(lastBotMessage, pwd) -> { - if (isValidService(message, disability)) { - val service = ServiceType.getServicesByDisability(disability)[message.toInt() - 1] - attendanceService.startAttendance(pwd = pwd, botNumber = botNumber, service = service) - } else { - attendanceService.sendServices(botNumber, pwd) - } - } attendance != null -> { if (attendance.attendant == null) { logger?.error("Atendimento com id ${attendance.id} foi iniciado com atendente Nulo!") @@ -57,6 +49,14 @@ class PWDFlowService( ) } } + isChoosingService(lastBotMessage, pwd) -> { + if (isValidService(message, disability)) { + val service = ServiceType.getServicesByDisability(disability)[message.toInt() - 1] + attendanceService.startAttendance(pwd = pwd, botNumber = botNumber, service = service) + } else { + attendanceService.sendServices(botNumber, pwd) + } + } else -> { attendanceService.sendServices(botNumber = botNumber, pwd = pwd) } diff --git a/src/test/kotlin/ufrpe/sbpc/botpcd/StepDefinitions.kt b/src/test/kotlin/ufrpe/sbpc/botpcd/StepDefinitions.kt index f77398d..47a99d2 100644 --- a/src/test/kotlin/ufrpe/sbpc/botpcd/StepDefinitions.kt +++ b/src/test/kotlin/ufrpe/sbpc/botpcd/StepDefinitions.kt @@ -13,6 +13,7 @@ import org.slf4j.LoggerFactory import org.springframework.test.web.servlet.MockMvc import org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post import org.springframework.test.web.servlet.result.MockMvcResultMatchers.status +import org.springframework.transaction.annotation.Transactional import ufrpe.sbpc.botpcd.entity.Attendance import ufrpe.sbpc.botpcd.entity.Attendant import ufrpe.sbpc.botpcd.entity.CommitteeMember @@ -40,6 +41,7 @@ import kotlin.test.assertFalse import kotlin.test.assertTrue import kotlin.text.contains +@Transactional class StepDefinitions( private val mockMvc: MockMvc, val pwdRepository: PWDRepository, @@ -58,6 +60,7 @@ class StepDefinitions( private val possibleItialsMessages = mutableListOf("Oi", "Olá", "Bom dia", "Boa noite", "Boa Tarde", "teste") val logger: Logger = LoggerFactory.getLogger(StepDefinitions::class.java) + @Dado("que o atendente {string} de telefone {string} enviou mensagem nas últimas 24 horas") fun `atendente enviou mensagem recente`(nomeAtendente: String, telefoneAtendente: String) { monitorRepository.save( @@ -143,7 +146,7 @@ class StepDefinitions( fromPhoneNumber = currentBotNumber// Ou ajuste conforme sua lógica para buscar todas )!!.message - assertFalse (lastMessage!!contains(attendant)) + assertFalse(lastMessage!!.contains(attendant?.name!!)) } @Quando("o atendente {string} de telefone {string} encerra o atendimento") @@ -169,14 +172,9 @@ class StepDefinitions( "que o atendente {string} de telefone {string} está disponível, mas não em atendimento" ) fun atendenteDisponivelNaoEmAtendimento(nomeAtendente: String, telefoneAtendente: String) { - monitorRepository.findByPhoneNumber(telefoneAtendente) ?: monitorRepository.save( - Monitor( - name = nomeAtendente, - phoneNumber = telefoneAtendente, - status = UserStatus.AVAILABLE, - assistanceType = MonitorAssistanceType.NEURODIVERGENT_SUPPORT_MONITOR // Tipo genérico - ) - ) + val monitor = monitorRepository.findByPhoneNumber(telefoneAtendente)!! + monitorRepository.save(monitor.apply { status = UserStatus.AVAILABLE }) + attendanceRepository.deleteAllByAttendant(monitor) } @Quando("o PCD {string} de telefone {string} envia a mensagem {string}") @@ -206,140 +204,141 @@ class StepDefinitions( val lastMensage = messageExchangeRepository.lastExchangeMessage( toPhoneNumber = telefoneAtendente, fromPhoneNumber = currentBotNumber - )!!.message - - assertFalse(lastMensage.contains(nomePCD)) + )?.message + if(lastMensage != null) { + assertFalse(lastMensage.contains(nomePCD)) + } } @Dado("que o atendente {string} de {string} do tipo {string} estava indisponível") - fun atendenteIndisponivel(nome: String, numero: String, tipoDeAtendente: String) { - - val provider = when (tipoDeAtendente.lowercase()) { - "monitor" -> Provider.MONITOR - "membro da comissão" -> Provider.COMMITTEE_MEMBER - else -> throw IllegalArgumentException("Tipo de atendente desconhecido: $tipoDeAtendente") - } - - if (provider == Provider.MONITOR) { - val monitor = monitorRepository.findByPhoneNumber(numero) - ?: monitorRepository.save( - Monitor( - name = nome, - phoneNumber = numero, - status = UserStatus.UNAVAILABLE, - assistanceType = MonitorAssistanceType.NEURODIVERGENT_SUPPORT_MONITOR // ou ajuste se quiser - ) - ) - monitor.status = UserStatus.UNAVAILABLE - monitorRepository.save(monitor) - } else if (provider == Provider.COMMITTEE_MEMBER) { - val member = attendantRepository.findByPhoneNumber(numero) - ?: attendantRepository.save( - CommitteeMember( - name = nome, - phoneNumber = numero, - status = UserStatus.UNAVAILABLE - ) - ) - member.status = UserStatus.UNAVAILABLE - attendantRepository.save(member) - } - } - - @Quando("o atendente {string} de {string} fica disponível") - fun atendenteFicaDisponivel(nome: String, numero: String) { - // Tenta encontrar o atendente no repositório de monitores - val monitor = monitorRepository.findByPhoneNumber(numero) - if (monitor != null) { - monitor.status = UserStatus.AVAILABLE - monitorRepository.save(monitor) - return - } - - // Tenta encontrar o atendente no repositório de membros da comissão - val member = attendantRepository.findByPhoneNumber(numero) - if (member != null) { - member.status = UserStatus.AVAILABLE - attendantRepository.save(member) - return - } - - // Se não encontrar nenhum atendente - throw IllegalArgumentException("Atendente '$nome' com número '$numero' não encontrado.") - } - - @Dado("que {string} PCD solicitou o serviço {string} e está na fila de espera") - fun pcdSolicitouServicoFila(adjetivoDeficiencia: String, servicoDescricao: String) { - val service = ServiceType.getByDescription(servicoDescricao) - - // Usa o método do enum para buscar pela forma textual do adjetivo - val disability = Disability.getByAdjective(adjetivoDeficiencia) - val phone = "81999999999" - - // Cria ou reutiliza o PCD - val pcd = pwdRepository.findByPhoneNumber(phone) ?: pwdRepository.save( - PWD( - name = "PCD $adjetivoDeficiencia", - phoneNumber = phone, - disabilities = setOf(disability) - ) - ) - - // Garante que existe uma solicitação em espera (não iniciada) - if (attendanceRepository.findRequestAttendanceOfPwd(pcd) == null) { - attendanceRepository.save( - Attendance( - pwd = pcd, - serviceType = service, - attendantType = service.attendantType, - attendant = null, - endDateTime = null, - startDateTime = null, - serviceLocation = null, - monitorArrivalDateTime = null - ) - ) - } - } - - @Dado("PCD possuia serviço requisitado que ainda não foi iniciado") - fun pcdPossuiServicoRequisitadoNaoIniciado() { - val service = ServiceType.NeurodivergentSupport - val disabilities = service.disability - - // Reutiliza ou cria o PCD com deficiências compatíveis com o serviço - val pcd = pwdRepository.findByPhoneNumber(pwdAcessarServicesPhoneNumber) ?: pwdRepository.save( - PWD( - name = "PCD Teste", - phoneNumber = pwdAcessarServicesPhoneNumber, - disabilities = disabilities - ) - ) - - // Evita criar duplicata se já existir - val existente = attendanceRepository.findRequestAttendanceOfPwd(pcd) - if (existente == null) { - attendanceRepository.save( - Attendance( - pwd = pcd, - serviceType = service, - attendantType = service.attendantType, - attendant = null, - endDateTime = null, - startDateTime = null, - serviceLocation = null, - monitorArrivalDateTime = null - ) - ) - } - } - - @Dado("que nenhum atendente para o {string} está disponível") - fun nenhumAtendenteDisponivel(servicoDescricao: String) { - // repositorio comeca vazio, nao precisa fazer nada - } - - @Dado("usuário recebeu mensagem {string}") + fun atendenteIndisponivel(nome: String, numero: String, tipoDeAtendente: String) { + + val provider = when (tipoDeAtendente.lowercase()) { + "monitor" -> Provider.MONITOR + "membro da comissão" -> Provider.COMMITTEE_MEMBER + else -> throw IllegalArgumentException("Tipo de atendente desconhecido: $tipoDeAtendente") + } + + if (provider == Provider.MONITOR) { + val monitor = monitorRepository.findByPhoneNumber(numero) + ?: monitorRepository.save( + Monitor( + name = nome, + phoneNumber = numero, + status = UserStatus.UNAVAILABLE, + assistanceType = MonitorAssistanceType.NEURODIVERGENT_SUPPORT_MONITOR // ou ajuste se quiser + ) + ) + monitor.status = UserStatus.UNAVAILABLE + monitorRepository.save(monitor) + } else if (provider == Provider.COMMITTEE_MEMBER) { + val member = attendantRepository.findByPhoneNumber(numero) + ?: attendantRepository.save( + CommitteeMember( + name = nome, + phoneNumber = numero, + status = UserStatus.UNAVAILABLE + ) + ) + member.status = UserStatus.UNAVAILABLE + attendantRepository.save(member) + } + } + + @Quando("o atendente {string} de {string} fica disponível") + fun atendenteFicaDisponivel(nome: String, numero: String) { + // Tenta encontrar o atendente no repositório de monitores + val monitor = monitorRepository.findByPhoneNumber(numero) + if (monitor != null) { + monitor.status = UserStatus.AVAILABLE + monitorRepository.save(monitor) + return + } + + // Tenta encontrar o atendente no repositório de membros da comissão + val member = attendantRepository.findByPhoneNumber(numero) + if (member != null) { + member.status = UserStatus.AVAILABLE + attendantRepository.save(member) + return + } + + // Se não encontrar nenhum atendente + throw IllegalArgumentException("Atendente '$nome' com número '$numero' não encontrado.") + } + + @Dado("que {string} PCD solicitou o serviço {string} e está na fila de espera") + fun pcdSolicitouServicoFila(adjetivoDeficiencia: String, servicoDescricao: String) { + val service = ServiceType.getByDescription(servicoDescricao) + + // Usa o método do enum para buscar pela forma textual do adjetivo + val disability = Disability.getByAdjective(adjetivoDeficiencia) + val phone = "81999999999" + + // Cria ou reutiliza o PCD + val pcd = pwdRepository.findByPhoneNumber(phone) ?: pwdRepository.save( + PWD( + name = "PCD $adjetivoDeficiencia", + phoneNumber = phone, + disabilities = setOf(disability) + ) + ) + + // Garante que existe uma solicitação em espera (não iniciada) + if (attendanceRepository.findRequestAttendanceOfPwd(pcd) == null) { + attendanceRepository.save( + Attendance( + pwd = pcd, + serviceType = service, + attendantType = service.attendantType, + attendant = null, + endDateTime = null, + startDateTime = null, + serviceLocation = null, + monitorArrivalDateTime = null + ) + ) + } + } + + @Dado("PCD possuia serviço requisitado que ainda não foi iniciado") + fun pcdPossuiServicoRequisitadoNaoIniciado() { + val service = ServiceType.NeurodivergentSupport + val disabilities = service.disability + + // Reutiliza ou cria o PCD com deficiências compatíveis com o serviço + val pcd = pwdRepository.findByPhoneNumber(pwdAcessarServicesPhoneNumber) ?: pwdRepository.save( + PWD( + name = "PCD Teste", + phoneNumber = pwdAcessarServicesPhoneNumber, + disabilities = disabilities + ) + ) + + // Evita criar duplicata se já existir + val existente = attendanceRepository.findRequestAttendanceOfPwd(pcd) + if (existente == null) { + attendanceRepository.save( + Attendance( + pwd = pcd, + serviceType = service, + attendantType = service.attendantType, + attendant = null, + endDateTime = null, + startDateTime = null, + serviceLocation = null, + monitorArrivalDateTime = null + ) + ) + } + } + + @Dado("que nenhum atendente para o {string} está disponível") + fun nenhumAtendenteDisponivel(servicoDescricao: String) { + // repositorio comeca vazio, nao precisa fazer nada + } + + @Dado("usuário recebeu mensagem {string}") fun `usuário recebeu mensagem`(message: String) { mockUserRecievedMessage(numberUserNotRegister, message) } @@ -354,14 +353,17 @@ class StepDefinitions( // Implementar lógica para garantir que o PCD está cadastrado no sistema // Ex: pwdRepository.save(PWD(name = "PCD Teste Completo", phoneNumber = numberUserNotRegister, disabilities = mutableSetOf(Disability.DEAFNESS))) } + @Dado("que não tem atendente disponível") fun `que não tem atendente disponível`() { } + @Dado("que {string} PCD recebeu mensagem de opcções de serviço") fun `pcd recebue mensagem de opção de serviço`(adjetivoPCD: String) { // ver se existe ou crirar um pcd com adjetivoPCD - val pwd = createPWDIfNotExists(phoneNumber = pwdAcessarServicesPhoneNumber, Disability.getByAdjective(adjetivoPCD)) + val pwd = + createPWDIfNotExists(phoneNumber = pwdAcessarServicesPhoneNumber, Disability.getByAdjective(adjetivoPCD)) val servicesText = attendanceService.createSendServicesMessage(pwd.disabilities.first(), pwd) messageExchangeRepository.save( MessageExchange( @@ -372,11 +374,20 @@ class StepDefinitions( ) // pegar no proprio código qual seria a mensagem de serviço } + @After fun cleanup() { // Esta linha deleta os dados em uma ordem que evita erros de chave estrangeira - listOf(attendanceRepository, messageExchangeRepository, monitorRepository, committeeMemberRepository, pwdRepository, attendantRepository).forEach { it.deleteAllInBatch() } + listOf( + attendanceRepository, + messageExchangeRepository, + monitorRepository, + committeeMemberRepository, + pwdRepository, + attendantRepository + ).forEach { it.deleteAllInBatch() } } + @Dado("atendente que se chama {string} enviou uma mensagem nas ultimas 24 horas para o bot") fun `atendente enviou uma mensagem nas ultimas 24 horas`(nomeAtendente: String) { messageExchangeRepository.save( @@ -399,7 +410,8 @@ class StepDefinitions( // Gera um número de telefone único para o atendente para evitar conflitos attendantRepository.findByPhoneNumber(currentTestAttendantPhoneNumber)?.let { attendantRepository.delete(it) } val serviceType = ServiceType.getByDescription(servicoDesejado) - val tipoAtendente = if (nomeAtendente.contains("Monitor", ignoreCase = true)) "monitor" else "membro da comissão" + val tipoAtendente = + if (nomeAtendente.contains("Monitor", ignoreCase = true)) "monitor" else "membro da comissão" val attendant: Attendant = when (tipoAtendente) { "monitor" -> { val monitorService = serviceType as? MonitorServiceType @@ -413,6 +425,7 @@ class StepDefinitions( ) ) } + "membro da comissão" -> { committeeMemberRepository.save( CommitteeMember( @@ -422,6 +435,7 @@ class StepDefinitions( ) ) } + else -> throw IllegalArgumentException("Tipo de atendente desconhecido: $tipoAtendente") } // Simula que o atendente enviou uma mensagem recentemente para ser considerado ativo @@ -435,7 +449,8 @@ class StepDefinitions( @Quando("{string} PCD envia a mensagem {string}") fun `pcd envia mensagem de serviço`(adjetivoPCD: String, numeroServico: String) { // O adjetivoPCD é usado para contexto, o número de telefone identifica o usuário - val pwd = createPWDIfNotExists(phoneNumber = pwdAcessarServicesPhoneNumber, Disability.getByAdjective(adjetivoPCD)) + val pwd = + createPWDIfNotExists(phoneNumber = pwdAcessarServicesPhoneNumber, Disability.getByAdjective(adjetivoPCD)) userSendMessage(numeroServico, pwd.phoneNumber) } @@ -482,15 +497,22 @@ class StepDefinitions( fun createIfNotExistsPWDWithDisability(adjetivoPCD: String, pwdPhoneNumber: String): PWD { var pwd = pwdRepository.findByPhoneNumber(pwdPhoneNumber) val disability = Disability.getByAdjective(adjetivoPCD) - if(pwd == null) { - return pwdRepository.save(PWD(name=adjetivoPCD, phoneNumber = pwdPhoneNumber, disabilities = mutableSetOf(disability))) + if (pwd == null) { + return pwdRepository.save( + PWD( + name = adjetivoPCD, + phoneNumber = pwdPhoneNumber, + disabilities = mutableSetOf(disability) + ) + ) } - if(pwd.disabilities.first() != disability) { + if (pwd.disabilities.first() != disability) { pwd.disabilities = mutableSetOf(disability) pwdRepository.save(pwd) } return pwd } + @Entao("bot registrará que usuário tem ou possui {string}") fun `bot registra deficiencia do usuário`(deficienciaAdjtivo: String) { val pwd = pwdRepository.findByPhoneNumberWithDisabilities(numberUserNotRegister)!! @@ -558,6 +580,7 @@ class StepDefinitions( ) monitorRepository.save(monitor) } + "membro da comissão" -> { val committeeMember = CommitteeMember( name = "Comissão Teste $phoneNumber", @@ -566,18 +589,22 @@ class StepDefinitions( ) committeeMemberRepository.save(committeeMember) } + else -> throw IllegalArgumentException("Tipo de atendente desconhecido: $tipoAtendente") } } + @Quando("PCD mandar qualquer mensagem") fun `PCD mandar qualquer mensagem`() { val message = possibleItialsMessages.random() userSendMessage(message, pwdAcessarServicesPhoneNumber) } + @Entao("PCD receberá mensagem {string}") fun `PCD recebera mensagem`(mensagemEsperada: String) { testarUltimaMensagemRecebidaDoUsuario(mensagemEsperada, pwdAcessarServicesPhoneNumber) } + @Dado("que sou um {string} com status inicial {string}") fun `que sou um tipo_de_atendente com status inicial`( tipoAtendente: String, @@ -587,11 +614,14 @@ class StepDefinitions( val attendant = createAttendant(currentTestAttendantPhoneNumber, tipoAtendente, status) if (status == UserStatus.BUSY) { // Limpar PWD existente com este número para evitar conflitos - val pwd = pwdRepository.findByPhoneNumber(pwdInAttendancePhoneNumberForAttendantChangeStatus) ?: pwdRepository.save(PWD( - name = "PCD em Atendimento Teste", - phoneNumber = pwdInAttendancePhoneNumberForAttendantChangeStatus, - disabilities = mutableSetOf(Disability.MOBILITY_IMPAIRED) // Deficiência padrão para o teste - )) + val pwd = pwdRepository.findByPhoneNumber(pwdInAttendancePhoneNumberForAttendantChangeStatus) + ?: pwdRepository.save( + PWD( + name = "PCD em Atendimento Teste", + phoneNumber = pwdInAttendancePhoneNumberForAttendantChangeStatus, + disabilities = mutableSetOf(Disability.MOBILITY_IMPAIRED) // Deficiência padrão para o teste + ) + ) // Determinar o tipo de serviço e provedor com base no tipo de atendente val serviceType: ServiceType @@ -616,6 +646,7 @@ class StepDefinitions( attendanceRepository.save(attendance) } } + @Quando("o {string} envia a mensagem {string}") fun `o tipo_de_atendente envia a mensagem`( tipoAtendente: String, @@ -641,9 +672,11 @@ class StepDefinitions( "Monitor" -> { assertTrue(attendant is Monitor, "Atendente $phoneNumber não é um Monitor.") } + "Membro da Comissão" -> { assertTrue(attendant is CommitteeMember, "Atendente $phoneNumber não é um Membro da Comissão.") } + else -> { throw Exception("Foi passado um tipo inválido nos testes: $tipoAtendente") } @@ -670,17 +703,26 @@ class StepDefinitions( val statusNovoEsperado = UserStatus.valueOf(statusNovoEsperadoStr.uppercase()) checkIfHasCorrectAttendantType(currentTestAttendantPhoneNumber, tipoAtendente) val attendant = attendantRepository.findByPhoneNumber(currentTestAttendantPhoneNumber) - assertTrue(attendant != null, "Atendente com número $currentTestAttendantPhoneNumber não encontrado no banco de dados.") - assertEquals(statusNovoEsperado, attendant!!.status, "Status do atendente não foi atualizado corretamente para $statusNovoEsperado. Estava ${attendant.status}.") + assertTrue( + attendant != null, + "Atendente com número $currentTestAttendantPhoneNumber não encontrado no banco de dados." + ) + assertEquals( + statusNovoEsperado, + attendant!!.status, + "Status do atendente não foi atualizado corretamente para $statusNovoEsperado. Estava ${attendant.status}." + ) } + fun createPWDIfNotExists(phoneNumber: String, disability: Disability): PWD { var pwd = pwdRepository.findByPhoneNumber(phoneNumber) - if(pwd == null) { + if (pwd == null) { return pwdRepository.save(PWD(phoneNumber = phoneNumber, disabilities = mutableSetOf(disability))) } else { return pwd } } + fun mockUserRecievedMessage(userNumber: String, message: String) { messageExchangeRepository.save( MessageExchange( @@ -696,14 +738,24 @@ class StepDefinitions( toPhoneNumber = userPhoneNumber, fromPhoneNumber = currentBotNumber )?.message - assertEquals(mensagemEsperada.trimIndent(), actualMessage?.trimIndent(), "A última mensagem recebida pelo usuário não foi a esperada.") + assertTrue( + actualMessage?.trimIndent()!!.contains(mensagemEsperada.trimIndent()), + "A última mensagem recebida pelo usuário não foi a esperada." + ) } fun testarPenultimaMensagemRecebidaDoUsuario(mensagemEsperada: String, userPhoneNumber: String) { val messageList = - messageExchangeRepository.listExchangeMessage(toPhoneNumber = userPhoneNumber, fromPhoneNumber = currentBotNumber) + messageExchangeRepository.listExchangeMessage( + toPhoneNumber = userPhoneNumber, + fromPhoneNumber = currentBotNumber + ) assertTrue(messageList.size >= 2, "Não há mensagens suficientes para verificar a penúltima.") - assertEquals(mensagemEsperada.trimIndent(), messageList[messageList.lastIndex - 1].message.trimIndent(), "A penúltima mensagem recebida pelo usuário não foi a esperada.") + assertEquals( + mensagemEsperada.trimIndent(), + messageList[messageList.lastIndex - 1].message.trimIndent(), + "A penúltima mensagem recebida pelo usuário não foi a esperada." + ) } private fun userSendMessage(mensagemEnviada: String, userPhoneNumber: String) { diff --git a/src/test/resources/ufrpe/sbpc/botpcd/acessarServicos.feature b/src/test/resources/ufrpe/sbpc/botpcd/acessarServicos.feature index 226394e..b92ac36 100644 --- a/src/test/resources/ufrpe/sbpc/botpcd/acessarServicos.feature +++ b/src/test/resources/ufrpe/sbpc/botpcd/acessarServicos.feature @@ -78,10 +78,11 @@ Funcionalidade: Acessar serviços de assistência Regra: Bot envia mensagem apenas para o usuário que mandaram mensagem nas últimas 24 horas - Cenário de Fundo: que o atendente "Carlos" de telefone "558100000001" enviou mensagem nas últimas 24 horas + Cenário de Fundo: + Dado que o atendente "Carlos" de telefone "558100000001" enviou mensagem nas últimas 24 horas E que o PCD "João" de telefone "558100000002" enviou mensagem nas últimas 24 horas E que o atendente "Ana" de telefone "558100000003" enviou mensagem nas últimas 24 horas - E que o PCD "Maria" de telefone "558100000004" enviou mensagem nas útlimas 24 horas + E que o PCD "Maria" de telefone "558100000004" enviou mensagem nas últimas 24 horas Cenário: Bot direciona mensagem do PCD para o atendente correto Dado que o atendente "Carlos" de telefone "558100000001" está em atendimento com o PCD "João" de telefone "558100000002" From 8da04510e72622f10d1767cf8cc86a69cd107ed8 Mon Sep 17 00:00:00 2001 From: victor-yghor Date: Tue, 24 Jun 2025 11:59:32 -0300 Subject: [PATCH 24/26] Solve the problem when the monitor or commite member is avaliable --- .../ufrpe/sbpc/botpcd/StepDefinitions.kt | 75 ++++++------------- .../ufrpe/sbpc/botpcd/acessarServicos.feature | 74 ++++++++---------- 2 files changed, 53 insertions(+), 96 deletions(-) diff --git a/src/test/kotlin/ufrpe/sbpc/botpcd/StepDefinitions.kt b/src/test/kotlin/ufrpe/sbpc/botpcd/StepDefinitions.kt index 47a99d2..9ca74bc 100644 --- a/src/test/kotlin/ufrpe/sbpc/botpcd/StepDefinitions.kt +++ b/src/test/kotlin/ufrpe/sbpc/botpcd/StepDefinitions.kt @@ -132,7 +132,6 @@ class StepDefinitions( toPhoneNumber = telefonePcd, fromPhoneNumber = telefoneAtendente ) - assert(ultimaMensagem != null && ultimaMensagem!!.message.contains(mensagem)) { "O PCD $nomePcd não recebeu a mensagem esperada \"$mensagem\" do atendente $nomeAtendente." } @@ -210,27 +209,23 @@ class StepDefinitions( } } - @Dado("que o atendente {string} de {string} do tipo {string} estava indisponível") - fun atendenteIndisponivel(nome: String, numero: String, tipoDeAtendente: String) { - + @Dado("que o atendente {string} de {string} do tipo {string} que presta serviço {string} estava indisponível") + fun atendenteIndisponivel(nome: String, numero: String, tipoDeAtendente: String, tipoServico: String) { + val service = ServiceType.getByDescription(tipoServico) val provider = when (tipoDeAtendente.lowercase()) { "monitor" -> Provider.MONITOR "membro da comissão" -> Provider.COMMITTEE_MEMBER else -> throw IllegalArgumentException("Tipo de atendente desconhecido: $tipoDeAtendente") } - if (provider == Provider.MONITOR) { - val monitor = monitorRepository.findByPhoneNumber(numero) - ?: monitorRepository.save( + val monitor = monitorRepository.save( Monitor( name = nome, phoneNumber = numero, status = UserStatus.UNAVAILABLE, - assistanceType = MonitorAssistanceType.NEURODIVERGENT_SUPPORT_MONITOR // ou ajuste se quiser + assistanceType = (service as MonitorServiceType).monitorAssistanceType // ou ajuste se quiser ) ) - monitor.status = UserStatus.UNAVAILABLE - monitorRepository.save(monitor) } else if (provider == Provider.COMMITTEE_MEMBER) { val member = attendantRepository.findByPhoneNumber(numero) ?: attendantRepository.save( @@ -247,58 +242,25 @@ class StepDefinitions( @Quando("o atendente {string} de {string} fica disponível") fun atendenteFicaDisponivel(nome: String, numero: String) { - // Tenta encontrar o atendente no repositório de monitores - val monitor = monitorRepository.findByPhoneNumber(numero) - if (monitor != null) { - monitor.status = UserStatus.AVAILABLE - monitorRepository.save(monitor) - return - } - - // Tenta encontrar o atendente no repositório de membros da comissão - val member = attendantRepository.findByPhoneNumber(numero) - if (member != null) { - member.status = UserStatus.AVAILABLE - attendantRepository.save(member) - return - } - - // Se não encontrar nenhum atendente - throw IllegalArgumentException("Atendente '$nome' com número '$numero' não encontrado.") + userSendMessage(userPhoneNumber = numero, mensagemEnviada = "Bot PCD") + userSendMessage(userPhoneNumber = numero, mensagemEnviada = "1") } - @Dado("que {string} PCD solicitou o serviço {string} e está na fila de espera") - fun pcdSolicitouServicoFila(adjetivoDeficiencia: String, servicoDescricao: String) { + @Dado("que {string} PCD de número {string} solicitou o serviço {string} e está na fila de espera") + fun pcdSolicitouServicoFila(adjetivoDeficiencia: String, numeroPcd: String, servicoDescricao: String) { val service = ServiceType.getByDescription(servicoDescricao) - - // Usa o método do enum para buscar pela forma textual do adjetivo val disability = Disability.getByAdjective(adjetivoDeficiencia) - val phone = "81999999999" - // Cria ou reutiliza o PCD - val pcd = pwdRepository.findByPhoneNumber(phone) ?: pwdRepository.save( + // Cria ou reutiliza o PCD com o número informado + val pcd = pwdRepository.save( PWD( name = "PCD $adjetivoDeficiencia", - phoneNumber = phone, + phoneNumber = numeroPcd, disabilities = setOf(disability) ) ) - - // Garante que existe uma solicitação em espera (não iniciada) - if (attendanceRepository.findRequestAttendanceOfPwd(pcd) == null) { - attendanceRepository.save( - Attendance( - pwd = pcd, - serviceType = service, - attendantType = service.attendantType, - attendant = null, - endDateTime = null, - startDateTime = null, - serviceLocation = null, - monitorArrivalDateTime = null - ) - ) - } + userSendMessage(mensagemEnviada = "Oi", numeroPcd) + userSendMessage((ServiceType.getServicesByDisability(disability).indexOfFirst { it.description == servicoDescricao } + 1).toString(), numeroPcd) } @Dado("PCD possuia serviço requisitado que ainda não foi iniciado") @@ -464,7 +426,14 @@ class StepDefinitions( testarUltimaMensagemRecebidaDoUsuario(mensagemEsperada, pwdAcessarServicesPhoneNumber) } - + @Entao("{string} PCD de número {string} receberá mensagem {string}") + fun `pcd com adjetivo e numero recebe mensagem`( + adjetivoDeficiencia: String, + numeroPcd: String, + mensagemEsperada: String + ) { + testarUltimaMensagemRecebidaDoUsuario(mensagemEsperada, numeroPcd) + } @Dado("usuário não cadastrado") fun `usuário não cadastrado`() { pwdRepository.findByPhoneNumber(numberUserNotRegister)?.let { pwdRepository.delete(it) } diff --git a/src/test/resources/ufrpe/sbpc/botpcd/acessarServicos.feature b/src/test/resources/ufrpe/sbpc/botpcd/acessarServicos.feature index b92ac36..ee1bb61 100644 --- a/src/test/resources/ufrpe/sbpc/botpcd/acessarServicos.feature +++ b/src/test/resources/ufrpe/sbpc/botpcd/acessarServicos.feature @@ -51,24 +51,18 @@ Funcionalidade: Acessar serviços de assistência Entao "" PCD receberá mensagem "No momento não há atendentes disponíveis. Por favor, aguarde na fila de espera e retornaremos assim que possível." Exemplos: - | adjetivo_da_deficiencia | nome_do_atendente | servico_desejado | numero_servico_desejado | - # Deficiência Auditiva - | um pessoa surda | João Comissão | atividade com interpretação em Libras | 1 | - | um pessoa surda | Ana Monitor | informações em Libras | 2 | - # Mobilidade Reduzida - | mobilidade reduzida | Pedro Monitor | ajuda na mobilidade | 1 | - | mobilidade reduzida | Carla Comissão | transporte para deslocamento no evento | 2 | - # Deficiência Física - | deficiente físico | Bia Comissão | ajuda com alimentação e higiene | 1 | - | deficiente físico | Pedro Monitor | ajuda na mobilidade | 2 | - | deficiente físico | Carla Comissão | transporte para deslocamento no evento | 3 | - # Deficiência Visual - | uma pessoa cega | Pedro Monitor | ajuda na mobilidade | 1 | - | uma pessoa cega | Lucas Comissão | programação com audiodescrição | 2 | - # Neurodivergente - | neurodivergente | Fábio Monitor | suporte para pessoas neurodivergentes | 1 | - # Surdocegueira - | uma pessoa surdocega | Maria Comissão | guia-intérprete | 1 | + | adjetivo_da_deficiencia | servico_desejado | numero_servico_desejado | + | um pessoa surda | atividade com interpretação em Libras | 1 | + | um pessoa surda | informações em Libras | 2 | + | mobilidade reduzida | ajuda na mobilidade | 1 | + | mobilidade reduzida | transporte para deslocamento no evento | 2 | + | deficiente físico | ajuda com alimentação e higiene | 1 | + | deficiente físico | ajuda na mobilidade | 2 | + | deficiente físico | transporte para deslocamento no evento | 3 | + | uma pessoa cega | ajuda na mobilidade | 1 | + | uma pessoa cega | programação com audiodescrição | 2 | + | neurodivergente | suporte para pessoas neurodivergentes | 1 | + | uma pessoa surdocega | guia-intérprete | 1 | Cenário: PCD está na fila de espera e manda mensagem novamente @@ -103,29 +97,23 @@ Funcionalidade: Acessar serviços de assistência Quando o atendente "Carlos" de telefone "558100000001" encerra o atendimento Então o PCD "João" de telefone "558100000002" deve receber a mensagem "Atendimento encerrado" do bot + Regra: Um atendente fica disponível é redirecionado para um pcd na fila de espera Esquema do Cenário: Atendente disponível é direcionado para PCD na fila de espera - Dado que "" PCD solicitou o serviço "" e está na fila de espera - E que o atendente "" de "" do tipo "" estava indisponível - Quando o atendente "" de "" fica disponível - Entao "" PCD receberá mensagem "O irá realizar seu atendimento." - - Exemplos: - | adjetivo_da_deficiencia | servico_desejado | nome_do_atendente | tipo_de_atendente | numero_atendente | - # Deficiência Auditiva - | um pessoa surda | informações em Libras | Ana Monitor | monitor | (00)00000-0001 | - | um pessoa surda | atividade com interpretação em Libras | João Comissão | membro da comissão | (00)00000-0002 | - # Mobilidade Reduzida - | mobilidade reduzida | ajuda na mobilidade | Pedro Monitor | monitor | (00)00000-0003 | - | mobilidade reduzida | transporte para deslocamento no evento | Carla Comissão | membro da comissão | (00)00000-0005 | - # Deficiência Física - | deficiente físico | ajuda na mobilidade | Pedro Monitor | monitor | (00)00000-0006 | - | deficiente físico | ajuda com alimentação e higiene | Bia Comissão | membro da comissão | (00)00000-0007 | - | deficiente físico | transporte para deslocamento no evento | Carla Comissão | membro da comissão | (00)00000-0008 | - # Deficiência Visual - | uma pessoa cega | ajuda na mobilidade | Pedro Monitor | monitor | (00)00000-0009 | - | uma pessoa cega | programação com audiodescrição | Lucas Comissão | membro da comissão | (00)00000-0010 | - # Neurodivergente - | neurodivergente | suporte para pessoas neurodivergentes | Fábio Monitor | monitor | (00)00000-0011 | - # Surdocegueira - | uma pessoa surdocega | guia-intérprete | Maria Comissão | membro da comissão | (00)00000-0012 | - + Dado que "" PCD de número "" solicitou o serviço "" e está na fila de espera + E que o atendente "" de "" do tipo "" que presta serviço "" estava indisponível + Quando o atendente "" de "" fica disponível + Então "" PCD de número "" receberá mensagem "O irá realizar seu atendimento." + + Exemplos: + | adjetivo_da_deficiencia | numero_pcd | servico_desejado | nome_do_atendente | tipo_de_atendente | numero_atendente | + | um pessoa surda | 558100000021 | informações em Libras | Sara Monitor | monitor | 558100000031 | + | um pessoa surda | 558100000022 | atividade com interpretação em Libras | João Comissão | membro da comissão | 558100000002 | + | mobilidade reduzida | 558100000023 | ajuda na mobilidade | Joana Monitor | monitor | 558100000033 | + | mobilidade reduzida | 558100000024 | transporte para deslocamento no evento | Carla Comissão | membro da comissão | 558100000005 | + | deficiente físico | 558100000025 | ajuda na mobilidade | Pedro Monitor | monitor | 558100000006 | + | deficiente físico | 558100000026 | ajuda com alimentação e higiene | Bia Comissão | membro da comissão | 558100000007 | + | deficiente físico | 558100000027 | transporte para deslocamento no evento | Carla Comissão | membro da comissão | 558100000008 | + | uma pessoa cega | 558100000028 | ajuda na mobilidade | Pedro Monitor | monitor | 558100000009 | + | uma pessoa cega | 558100000029 | programação com audiodescrição | Lucas Comissão | membro da comissão | 558100000010 | + | neurodivergente | 558100000030 | suporte para pessoas neurodivergentes | Fábio Monitor | monitor | 558100000011 | + | uma pessoa surdocega | 558100000031 | guia-intérprete | Maria Comissão | membro da comissão | 558100000012 | \ No newline at end of file From 8e193fd38a34472d459542e1063b7cffe42a258e Mon Sep 17 00:00:00 2001 From: victor-yghor Date: Tue, 24 Jun 2025 19:29:32 -0300 Subject: [PATCH 25/26] =?UTF-8?q?Fix=20tests=20acessar=20servi=C3=A7os=20d?= =?UTF-8?q?e=20assit=C3=AAncia?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../sbpc/botpcd/service/AttendanceService.kt | 24 +++++++++---------- .../ufrpe/sbpc/botpcd/StepDefinitions.kt | 12 +++------- 2 files changed, 14 insertions(+), 22 deletions(-) diff --git a/src/main/kotlin/ufrpe/sbpc/botpcd/service/AttendanceService.kt b/src/main/kotlin/ufrpe/sbpc/botpcd/service/AttendanceService.kt index 065a6c1..a836fbb 100644 --- a/src/main/kotlin/ufrpe/sbpc/botpcd/service/AttendanceService.kt +++ b/src/main/kotlin/ufrpe/sbpc/botpcd/service/AttendanceService.kt @@ -18,7 +18,6 @@ import ufrpe.sbpc.botpcd.repository.AttendanceRepository import ufrpe.sbpc.botpcd.repository.CommitteeMemberRepository import ufrpe.sbpc.botpcd.repository.MessageExchangeRepository import ufrpe.sbpc.botpcd.repository.MonitorRepository -import ufrpe.sbpc.botpcd.service.QueueService import ufrpe.sbpc.botpcd.util.createOptions import java.time.LocalDateTime @@ -142,23 +141,13 @@ class AttendanceService( when (userResponse.lowercase()) { "1" -> { updateAttendantStatus(botNumber, attendant, UserStatus.AVAILABLE) - whatsappService.sendMessage( - botPhoneNumber, - attendance.pwd.phoneNumber, - "Atendimento encerrado", - "BotPCD" - ) + sendFinishedAttendanceMessage(botPhoneNumber, attendance) confirmationMessage = "Atendimento encerrado. Seu status foi atualizado para Disponível." finishAttendance(attendance) } "2" -> { updateAttendantStatus(botNumber, attendant, UserStatus.UNAVAILABLE) - whatsappService.sendMessage( - botPhoneNumber, - attendance.pwd.phoneNumber, - "Atendimento encerrado", - "BotPCD" - ) + sendFinishedAttendanceMessage(botPhoneNumber, attendance) confirmationMessage = "Atendimento encerrado. Seu status foi atualizado para Indisponível." finishAttendance(attendance) } @@ -182,6 +171,15 @@ class AttendanceService( } } + private fun sendFinishedAttendanceMessage(botPhoneNumber: String, attendance: Attendance) { + whatsappService.sendMessage( + botPhoneNumber, + attendance.pwd.phoneNumber, + "Atendimento encerrado", + "BotPCD" + ) + } + fun findAvailableMonitors(): List { return monitorRepository.findByStatus(UserStatus.AVAILABLE) } diff --git a/src/test/kotlin/ufrpe/sbpc/botpcd/StepDefinitions.kt b/src/test/kotlin/ufrpe/sbpc/botpcd/StepDefinitions.kt index 9ca74bc..7026a35 100644 --- a/src/test/kotlin/ufrpe/sbpc/botpcd/StepDefinitions.kt +++ b/src/test/kotlin/ufrpe/sbpc/botpcd/StepDefinitions.kt @@ -97,14 +97,8 @@ class StepDefinitions( ) { val pcd = pwdRepository.findByPhoneNumber(telefonePcd)!! val monitor = monitorRepository.findByPhoneNumber(telefoneAtendente) - val attendance = Attendance( - serviceType = ServiceType.NeurodivergentSupport, - pwd = pcd, - attendant = monitor, - attendantType = Provider.MONITOR, - startDateTime = LocalDateTime.now() - ) - attendanceRepository.save(attendance) + userSendMessage("oi", telefonePcd) + userSendMessage("1", telefonePcd) } @Dado( @@ -130,7 +124,7 @@ class StepDefinitions( val telefoneAtendente = monitorRepository.findByName(nomeAtendente)!!.phoneNumber val ultimaMensagem = messageExchangeRepository.lastExchangeMessage( toPhoneNumber = telefonePcd, - fromPhoneNumber = telefoneAtendente + fromPhoneNumber = currentBotNumber ) assert(ultimaMensagem != null && ultimaMensagem!!.message.contains(mensagem)) { "O PCD $nomePcd não recebeu a mensagem esperada \"$mensagem\" do atendente $nomeAtendente." From 196f0ba93024bc138ed9034b4d6270e7237bcebc Mon Sep 17 00:00:00 2001 From: victor-yghor Date: Tue, 24 Jun 2025 20:44:54 -0300 Subject: [PATCH 26/26] solve type and put in git ignore --- .gitignore | 2 +- src/test/kotlin/ufrpe/sbpc/botpcd/StepDefinitions.kt | 5 ++--- .../resources/ufrpe/sbpc/botpcd/acessarServicos.feature | 8 ++++---- src/test/resources/ufrpe/sbpc/botpcd/registerPCD.feature | 4 ++-- 4 files changed, 9 insertions(+), 10 deletions(-) diff --git a/.gitignore b/.gitignore index f4a93c7..5875f4e 100644 --- a/.gitignore +++ b/.gitignore @@ -34,7 +34,7 @@ out/ /dist/ /nbdist/ /.nb-gradle/ - +data/ ### VS Code ### .vscode/ diff --git a/src/test/kotlin/ufrpe/sbpc/botpcd/StepDefinitions.kt b/src/test/kotlin/ufrpe/sbpc/botpcd/StepDefinitions.kt index 7026a35..90d91c0 100644 --- a/src/test/kotlin/ufrpe/sbpc/botpcd/StepDefinitions.kt +++ b/src/test/kotlin/ufrpe/sbpc/botpcd/StepDefinitions.kt @@ -160,7 +160,6 @@ class StepDefinitions( } } - @Dado( "que o atendente {string} de telefone {string} está disponível, mas não em atendimento" ) @@ -315,7 +314,7 @@ class StepDefinitions( } - @Dado("que {string} PCD recebeu mensagem de opcções de serviço") + @Dado("que {string} PCD recebeu mensagem de opções de serviço") fun `pcd recebue mensagem de opção de serviço`(adjetivoPCD: String) { // ver se existe ou crirar um pcd com adjetivoPCD val pwd = @@ -508,7 +507,7 @@ class StepDefinitions( ) } - @Entao("{string} PCD receberá mensagem de opcções de serviço {string}") + @Entao("{string} PCD receberá mensagem de opções de serviço {string}") fun `bot enviará opcçoes de seviço de acordo com a deficiência do pcd`( tipoDeDeficiencia: String, opcoesDeServico: String diff --git a/src/test/resources/ufrpe/sbpc/botpcd/acessarServicos.feature b/src/test/resources/ufrpe/sbpc/botpcd/acessarServicos.feature index ee1bb61..85abda4 100644 --- a/src/test/resources/ufrpe/sbpc/botpcd/acessarServicos.feature +++ b/src/test/resources/ufrpe/sbpc/botpcd/acessarServicos.feature @@ -4,10 +4,10 @@ Funcionalidade: Acessar serviços de assistência Esquema do Cenário Listar serviços de acordo com meu tipo de deficiência Quando PCD "" mandar qualquer mensagem - Entao "" PCD receberá mensagem de opcções de serviço "" + Entao "" PCD receberá mensagem de opções de serviço "" Exemplos: - | adjetivo_da_deficiencia | opcções_de_serviço | + | adjetivo_da_deficiencia | opções_de_serviço | | um pessoa surda | informações em Libras,atividade com interpretação em Libras | | mobilidade reduzida | ajuda na mobilidade,transporte para deslocamento no evento | | deficiente físico | ajuda na mobilidade,ajuda com alimentação e higiene,transporte para deslocamento no evento | @@ -16,7 +16,7 @@ Funcionalidade: Acessar serviços de assistência | uma pessoa surdocega | guia-intérprete | Esquema do Cenário: Direcionar para o atendente(monitor ou membro da comissão) - Dado que "" PCD recebeu mensagem de opcções de serviço + Dado que "" PCD recebeu mensagem de opções de serviço E atendente que se chama "" está disponível para o "" E atendente que se chama "" enviou uma mensagem nas ultimas 24 horas para o bot Quando "" PCD envia a mensagem "" @@ -45,7 +45,7 @@ Funcionalidade: Acessar serviços de assistência Regra: PCD precisa receber mensagem informando que ele está na fila de espera Esquema do Cenário: PCD entra na fila de espera ao solicitar um serviço - Dado que "" PCD recebeu mensagem de opcções de serviço + Dado que "" PCD recebeu mensagem de opções de serviço E que nenhum atendente para o "" está disponível Quando "" PCD envia a mensagem "" Entao "" PCD receberá mensagem "No momento não há atendentes disponíveis. Por favor, aguarde na fila de espera e retornaremos assim que possível." diff --git a/src/test/resources/ufrpe/sbpc/botpcd/registerPCD.feature b/src/test/resources/ufrpe/sbpc/botpcd/registerPCD.feature index 963ff57..e8c1dff 100644 --- a/src/test/resources/ufrpe/sbpc/botpcd/registerPCD.feature +++ b/src/test/resources/ufrpe/sbpc/botpcd/registerPCD.feature @@ -78,11 +78,11 @@ Olá, qual sua deficiência? E usuário possui deficiência cadastrada de "" Quando usuário envia mensagem "João Victor" Entao A penúltima mensagem recebida pelo usuário será "Cadastro realizado." - E "" PCD receberá mensagem de opcções de serviço "" + E "" PCD receberá mensagem de opções de serviço "" E bot salvará o nome do usuário "João Victor" Exemplos: - | adjetivo_da_deficiencia | opcções_de_serviço | + | adjetivo_da_deficiencia | opções_de_serviço | | um pessoa surda | informações em Libras,atividade com interpretação em Libras | | mobilidade reduzida | ajuda na mobilidade,transporte para deslocamento no evento | | deficiente físico | ajuda na mobilidade,ajuda com alimentação e higiene,transporte para deslocamento no evento |