01. DADOS GERAIS

Produto:

TOTVS Saúde Planos

Linha de Produto:

Linha Protheus 

Segmento:

Saúde

Módulo:Faturamento
Função:Monitor de Inadimplência
Issue :DSAUBE-26610

02. SITUAÇÃO/REQUISITO

Desenvolver uma rotina que permita aos usuários visualizar os beneficiários inadimplentes, juntamente com os respectivos títulos em aberto. A rotina também deverá identificar os beneficiários que atendem aos critérios estabelecidos pela Resolução Normativa nº 593, possibilitando sua categorização conforme diferentes status.

03. SOLUÇÃO

>> Índice <<

>> O que é o Monitor de Inadimplência? <<

O Monitor de Inadimplência é uma ferramenta desenvolvida para permitir que usuários visualizem, acompanhem e registrem informações sobre beneficiários de planos de saúde que possuem faturas vencidas. O sistema também identifica aqueles que se enquadram na RN nº 593 da ANS, norma que regulamenta o cancelamento de contratos por inadimplência.

> Funcionalidades do Sistema

>> Parâmetros (SX6) <<

A rotina leva em consideração dois parâmetros para retornar os títulos:


>> Estrutura da Interface <<

> Parte Superior: Dados do Beneficiário

> Parte Inferior Esquerda: Títulos em Atraso

> Parte Inferior Direita: Contatos Realizados


>> Passo a Passo das Funcionalidades <<

> Opção de Menu Novo Filtro

  1. Clique no botão Novo Filtro.

  2. Uma janela com um formulário será exibida.

  3. Preencha os dados conforme a necessidade.

  4. Clique em OK.

Quanto menos parâmetros informados, maior pode ser o tempo de processamento devido à quantidade de registros retornados.

> Opção de Menu Atualizar Dados

  1. Clique no botão Atualizar Dados.

  2. O sistema irá recarregar os dados com base nos parâmetros preenchidos anteriormente.

Utilize esta funcionalidade sempre após registrar uma interação manualmente, garantindo a atualização correta dos filtros da RN 593. Sempre que uma interação for inserida manualmente, uma mensagem será exibida no topo da tela como lembrete para atualizar os dados.


> Opção de Menu Enviar Notificação de Inadimplência

  1. Selecione uma ou mais linhas na tabela da esquerda.

  2. Clique no botão Enviar Notificação de Inadimplência.


     3. Clicando em Não! O sistema exibirá uma lista contendo os beneficiários e os clientes que estão com alguma não conformidade no e-mail. No caso abaixo, o e-mail não foi configurado.

 


      4. Ao confirmar a ação clicando em 'Sim', o sistema exibirá uma janela solicitando que o usuário escolha se o envio dos e-mails deve ser feito apenas para o titular ou para o titular e o cliente.


      5. Clicando em uma das opções, o sistema iniciará o processo de envio dos e-mails. 




Toda configuração relacionada ao layout do e-mail, remetente e assunto do e-mail são configurados na rotina Gerenciador de Contas de E-mail, clique no link para acessar a documentação completa DT Gerenciador de Contas de E-mail.

> Opção de Menu Documentação

> Opção de Menu Filtros RN 593

📝 Como funciona?

✅ Premissas para atender a RN 593:

  1. Cobrança no nível da família (BA3_COBNIV == '1)

  2. Data-base do contrato >= 01/12/2024 (BA3_DATBAS)

  3. Dois ou mais títulos em atraso, sendo um com 50 dias ou mais

🔽 Filtros Disponíveis





A data de digitação é usada porque em algumas situações há o atraso na atualização do status de internação no sistema (BE4_DATPRO). Isso evita o risco de enviar cobrança a beneficiários internados.



📚 Clique no link para mais informações sobre a RN 593: Resolução Normativa 593 - ANS


>> Seção Contatos Realizados <<

A seção de Contatos Realizados é onde ficam registradas todas as interações com o cliente, seja quando a empresa entra em contato com o beneficiário ou quando o beneficiário entra em contato com a empresa.

Essa seção é extremamente importante, pois influencia diretamente a análise dos beneficiários que se enquadram na RN 593. Com base nas informações inseridas nessa área, o sistema determina em qual filtro da RN 593 o beneficiário será exibido.

Os dados podem ser inseridos manualmente, através da inserção direta utilizando ReckLock ou através de métodos desenvolvidos especificamente para a gravação dos dados de contatos realizados conforme o item 12. Inserção de Dados na Tabela de Contatos Realizados (BRZ) deste documento.

Manualmente é possível incluir, alterar, visualizar e excluir um registro.


  1. Para incluir um registro, clique no botão incluir e insira os dados referentes ao contato realizado.

Campos disponíveis:

📩 Cont. Conf ? (BRZ_CNFCON)

      > 0 – Recebimento não confirmado

      > 1 – Recebimento confirmado

📅 Data do Contato (BRZ_DATCON)

Hora do Contato (BRZ_HORCON)

🗓️ Data de Criação (BRZ_DATCRI)

🕒 Hora de Criação (BRZ_HORCRI)

>> Criação de Botões Customizados <<

Através do Ponto de entrada PLMON001, é possível criar botões na rotina, permitindo a criação de quantos botões forem necessários com as funcionalidades desejadas.

> É necessário retornar um array bidimensional.


function PLMON001()
     LOCAL aMenu := {}
     AADD(aMenu, {"Teste Botão 1", {||U_botao1()}})
     AADD(aMenu, {"Teste Botão 2", {||U_botao2()}})
return aMenu

>> Ponto de Entrada do Status de Contato <<

Através do Ponto de entrada PLMON002, é possível criar status relacionados à tabela de contatos realizados (BRZ).

Function PLMON002()
   LOCAL aStatus := {}
   AADD(aStatus, {"BRZ_DATCON < dDataBase .AND. BRZ_CNFCON == '0'", "BLUE", "Data anterior a hoje"})
RETURN aStatus




📚 Para mais informações sobre como utilizar ponto de entrada em MVC, consulte o documento: https://tdn.totvs.com/display/public/framework/AdvPl+utilizando+MVC

>> Recuperar Seleção de Beneficiários <<

 

Sintaxe

DelinquencyInterface:getSelecBeneficiaries()

Retorno

Nome

Tipo

Descrição

oJson

Json

Retorna um objeto json com a seguinte estrutura



oJSelecBeneficiaries := delinquency.monitor.DelinquencyInterface():getSelecBeneficiaries()

//O objeto retorna os seguintes atributos

//dados do beneficiário
//oJSelecBeneficiaries[nPosicao]["beneficiarie"]["register"] - Matrícula completa do beneficiário
//oJSelecBeneficiaries[nPosicao]["beneficiarie"]["name"    ] - Nome do beneficiário
//oJSelecBeneficiaries[nPosicao]["beneficiarie"]["email"]    - E-mail do beneficiário

//dados do cliente
//oJSelecBeneficiaries[nPosicao]["client"]["code" ] - Código do cliente e loja
//oJSelecBeneficiaries[nPosicao]["client"]["name" ] - Nome do cliente
//oJSelecBeneficiaries[nPosicao]["client"]["email"] - e-mail do cliente

    

>> Inserção de Dados na Tabela de Contatos Realizados (BRZ) <<

Dependendo da quantidade de contatos que precisam ser registrados — como no caso do envio de e-mails em massa para diversos beneficiários, onde é necessário gerar um registro de contato para cada envio —, é comum que customizações precisem lidar com essa geração em larga escala.

Para facilitar esse processo, criamos uma solução simplificada que exige apenas os dados dinâmicos obrigatórios a serem gravados. Essa abordagem reduz a complexidade e torna o processo mais ágil.

Utilizamos um conjunto de métodos desenvolvidos com foco em objetividade e performance, tendo como base a classe FWBulk, que permite inserções em massa com alta eficiência.


//Instancia a classe de serviços
oMonitorService := totvs.protheus.health.delinquency.monitor.DelinquencyService():New()

// Cria o objeto bulk
oMonitorService:createBulkContact()

For nSendMail := 1 To 100

	//Nesse momento os dados são gravados em um objeto mas serão efetivamente gravados na tabela quando somar 1000 registros inseridos no objeto
	//ou a cada execução do método flushBulkContact
   self:oMonitorService:insertDataBulkContact("00010001123456011", "01", "E-mail enviado para o beneficiário")
Next

//efetua a gravação dos dados contidos no objeto na tabela BRZ
oMonitorService:flushBulkContact()


Sintaxe

DelinquencyService:insertDataBulkContact(< cBenefRegister >, < cTypeContact >, < cDescriptionContact >)

Parâmetros

Nome

Tipo

Descrição

Obrigatório

cBenefRegister CaracterMatrícula do beneficiário que será registrada no campo Matrícula (BRZ_MATRIC).X
cTypeContact CaracterCódigo do tipo de contato, conforme a tabela genérica SX5 (código TY), que será registrado no campo Origem Cont. (BRZ_ORICON).X
cDescriptionContact CaracterDescrição do contato que será registrada no campo  Motivo (BRZ_MOTIVO).X

Retorno

Nome

Tipo

Descrição

lRet

booleano

true - Em caso de sucesso.

false - Em caso de erro.

Ambos os métodos retornam true em caso de sucesso e false em caso de falha. Quando ocorre um erro, o sistema registra os detalhes no arquivo de log monitorInadimplencia.log, localizado no diretório logpls.


Os campos abaixo serão gravados da seguinte forma a cada inserção de dados no objeto através do método insertDataBulkContact:

Cont. Conf? (BRZ_CNFCON) - Por padrão será gravado com o valor 0 (Recebimento não confirmado).

Data Contato (BRZ_DATCON) - Irá gravar a data em que o registro foi gerado. 

Hora Contato (BRZ_HORCON) - Irá gravar a hora em que o registro foi gerado. 

Data Criação (BRZ_DATCRI) - Irá gravar a data em que o registro foi gerado. 

Hora Criação (BRZ_HORCRI) -  Irá gravar a hora em que o registro foi gerado. 


>> Consultar Tabelas Temporárias <<

Os dois grids (beneficiários e títulos) utilizam tabelas temporárias. Para ter acesso utilizando a sintaxe ADVPL, use o alias BENEINAD (beneficiários) e BENEFINA (títulos).

cMatricula := BENEINAD->(BA1_CODINT + BA1_CODEMP + BA1_MATRIC + BA1_TIPREG + BA1_DIGITO)
cTitulo    := BENEFINA->E1_NUM 


Os campos disponíveis na tabela temporária BENEINAD são:

Os campos disponíveis na tabela temporária BENEFINA são:

Em casos em que os dados das tabelas temporárias precisem ser utilizadas diretamente em uma query, em um join com outra tabela do sistema por exemplo, se faz necessário informar o nome real da tabela no banco de dados, pois o alias não funciona para tabelas temporárias. Dessa forma, disponibilizamos dois métodos que basicamente retornam o nome real das tabelas temporárias de beneficiário e do financeiro naquele momento (o nome muda dinamicamente a cada execução da rotina ou atualização da tela).

Sintaxe (tabela beneficiários BENEINAD)

DelinquencyService:realNameBeneficiaries()


Retorno

Nome

Tipo

Descrição

cAlias

Caracter

Retorna o nome real da tabela temporária de beneficiários no banco de dados.

cRealTable := totvs.protheus.health.delinquency.monitor.DelinquencyService():realNameBeneficiaries()
oExecQuery := FWExecStatement():New()

//não é necessário utilizar o campo D_E_L_E_T_ pois a temporária possui apenas registros ativos
cSQL := " SELECT *"
cSQL += " FROM " + cRealTable

oExecQuery:SetQuery( cSQL )

cAliasTemp := oExecQuery:OpenAlias()


Sintaxe (tabela de Titulos BENEFINA)

DelinquencyService:realNameInvoices()

Retorno

Nome

Tipo

Descrição

cAlias

Caracter

Retorna o nome real da tabela temporária dos dados financeiros no banco de dados

cRealTable := totvs.protheus.health.delinquency.monitor.DelinquencyService():realNameInvoices()
oExecQuery := FWExecStatement():New()

//não é necessário utilizar o campo D_E_L_E_T_ pois a temporária possui apenas registros ativos
cSQL := " SELECT *"
cSQL += " FROM " + cRealTable

oExecQuery:SetQuery( cSQL )

cAliasTemp := oExecQuery:OpenAlias()

cTitulo := (cAliasTemp)->E1_NUM

>> Ambiente Com Banco de Dados Oracle <<

O monitor de inadimplência utiliza tabelas temporárias para armazenar tanto os dados dos beneficiários quanto os títulos em aberto. No entanto, o banco de dados Oracle possui uma particularidade: os dados inseridos em uma tabela temporária durante uma seção não ficam visíveis em outras sessões.

Por esse motivo, quando for necessário acessar os dados para depuração ou implementar pontos de entrada, deve-se configurar o parâmetro MV_DEBMONT como true (.T.). Quando esse parâmetro está ativado — e somente no Oracle — são criadas duas tabelas físicas:

Essas tabelas são recriadas sempre que a rotina é encerrada e reaberta. Além disso, qualquer novo filtro ou atualização também provoca a exclusão e recriação das tabelas com os dados atualizados.

  • O uso dessa funcionalidade pode impactar negativamente a performance da rotina, portanto, deve ser utilizado com cautela.

  • Essas tabelas são cópias das tabelas temporárias geradas no momento da execução da rotina. Portanto, qualquer alteração feita diretamente nelas não será refletida nas tabelas temporárias utilizadas internamente pela seção criada pelo programa para manipulação dos dados.

04. DEMAIS INFORMAÇÕES

Atualização do Dicionário de Dados

Inclusões na tabela SX2 (Tabela):

TabelaBRZ
ModoCompartilhado
Modo UnidadeExclusivo
Modo EmpresaExclusivo
Chave ÚnicaBRZ_FILIAL+BRZ_MATRIC+DTOS(BRZ_DATCRI)+BRZ_HORCRI
Nome 

Contatos Realizados


Inclusão no Arquivo SIX (índices):

Índice

Ordem

Chave

Descrição

BRZ1BRZ_FILIAL+BRZ_MATRIC+DTOS(BRZ_DATCRI)+BRZ_HORCRIFilial + Matrícula + Data criação registro + Hora criação registro
BRZ2BRZ_FILIAL+BRZ_MATRIC+DTOS(BRZ_DATCON)Filial + Matrícula + Data do contato
BRZ3BRZ_FILIAL+DTOS(BRZ_DATCON) Filial + Data do contato
BRZ4BRZ_FILIAL+DTOS(BRZ_DATCRI)Filial + Data criação registro


Inclusão de itens no Arquivo SX3 (campos da tabela):

Campo

Tipo

Tamanho

Decimal

Titulo

Descrição

Picture

Validação

Relação

F3

Trigger

Usado

Obrigatório

Exibe Browser

Visual

Contexto

CBox

Inicializa Browse (INIBRW)

Help

BRZ_FILIALCaracter80

Filial    

Filial do Sistema




SimNãoNão



Filial do Sistema  

BRZ_CNFCONCaracter10

Cont. Conf ?  

Confirma contato?
Pertence("01")"0"

SimSimSimAlteraReal0=Recebimento Não Confirmado;1=Recebimento Confirmado

Indica se o recebimento do contato foi confirmado, conforme o meio de comunicação utilizado.

BRZ_DATCONData80

Data Contato

Data de contato




SimSimSimAlteraReal

Data em que o contato com o beneficiário foi realizado.

BRZ_HORCONCaracter  50

Hora Contato

Hora de contato99:99VAZIO() .OR. validateTimeFormat(M->BRZ_HORCON)


SimSimSimAlteraReal

Hora em que o contato foi realizado.

BRZ_ORICONCaracter20

Origem cont.

Origem do contato99VAZIO() .OR. ExistCpo("SX5","TY"+M->BRZ_ORICON)
TY    SSimSimSimAlteraReal

Origem do contato.

BRZ_ORIDESCaracter300

Desc. Origem

Descrição origem

If( !EMPTY(M->BRZ_ORICON), FWGetSX5( "TY", M->BRZ_ORICON)[1][4], "")

SimNãoSimVisualVirtual
If( !EMPTY(M->BRZ_ORICON), FWGetSX5( "TY", M->BRZ_ORICON)[1][4], "") 

Descrição da origem.

BRZ_MATRICCaracter170

Matrícula

Matrícula beneficiário

BENEINAD->(BA1_CODINT + BA1_CODEMP + BA1_MATRIC + BA1_TIPREG + BA1_DIGITO)

SimNãoNãoVisualReal
BENEINAD->(BA1_CODINT + BA1_CODEMP + BA1_MATRIC + BA1_TIPREG + BA1_DIGITO)

Matrícula completa do beneficiário.

BRZ_NOMUSRCaracter700

Beneficiário

Nome beneficiário

If( !EMPTY(M->BRZ_MATRIC), POSICIONE("BA1",2,XFILIAL("BA1")+M->BRZ_MATRIC, "BA1_NOMUSR"), "")

SimNãoNãoVisualReal
BENEINAD->BA1_NOMUSR

Nome do beneficiário.

BRZ_MOTIVOMemo2540

Mot. Contato

Motivo do contato




SimSimNãoAltera Real

Motivo do contato.

BRZ_DATCRIData80

Data Criação

Data de criação

dDataBase

SimNãoSimVisualReal

Data de criação do registro.

BRZ_HORCRICaracter80

Hora Criação

Hora criação

TIME()

SimNãoSimVisual Real

Hora de criação do registro.


Inclusão no arquivo SX1 (Pergunte):

Grupo

Ordem

Pergunta

Tipo

Tamanho

Decimal

Valid

Modo de Entrada

Variável

Def. 1

Def. 2

Def. 3

Def. 4

Cons. Padrão

Picture

MONINAD01Vencimento a partir de:Data80
GetMV_PAR01   





MONINAD02Operadora:Caracter40Vazio() .OR. ExistCpo('BA0', MV_PAR02, 1)GetMV_PAR02



B89PLS@!
MONINAD03Empresa:Caracter40Vazio() .OR. ExistCpo("BG9",MV_PAR02+MV_PAR03,1)GetMV_PAR03



EMPIND@!
MONINAD04Contrato:Caracter120Vazio() .Or. ExistCpo("BT5",MV_PAR02+MV_PAR03+MV_PAR04,1)GetMV_PAR04



CONIND999999999999
MONINAD05SubContrato:Caracter90Vazio() .OR. ExistCpo("BQC",MV_PAR02+MV_PAR03+MV_PAR04+"001"+MV_PAR05,1)GetMV_PAR05



SUBIND999999999


Inclusão no arquivo SX6 (Parâmetros do Sistema):

Variável

Tipo

Descrição

Conteúdo

MV_DEBMONTLógicoAtiva a criação de tabelas temporárias de suporte para a rotina monitor de inadimplência apenas para  banco de dados oracle.F.


Inclusão no Arquivo SX7 (gatilhos):

Campo

Sequencial

Regra

Contra Domínio

Tipo

Seek

BRZ_ORICON001IF(LEN(FWGetSX5( "TY", M->BRZ_ORICON)) == 0, "", FWGetSX5( "TY", M->BRZ_ORICON)[1][4])BRZ_ORIDESP2 - Não


Inclusão no arquivo SX9 (Relacionamento):

Domínio

Contra domínio

E. Domínio

E. C. Domínio

Propriedade

L. Domínio

L. C. Domínio

BA1BRZBA1_CODINT+BA1_CODEMP+BA1_MATRIC+BA1_TIPREG+BA1_DIGITOBRZ_MATRICS1N
SX5BRZX5_TABELA+X5_CHAVE'TY'+BRZ_ORICONS1N


Inclusão no arquivo SXB (Consulta Padrão):

> Consulta padrão EMPIND:

Alias

Tipo

Sequencial

Coluna

Descrição

Contem

EMPIND101DBGrupo/EmpresaBG9
EMPIND20101Operadora + Código
EMPIND20202Descrição
EMPIND40101OperadoraBG9->BG9_CODINT
EMPIND40102CódigoBG9->BG9_CODIGO
EMPIND40103DescriçãoBG9->BG9_DESCRI
EMPIND40204OperadoraBG9->BG9_CODINT
EMPIND40205CódigoBG9->BG9_CODIGO
EMPIND40206DescriçãoBG9->BG9_DESCRI
EMPIND501

BG9->BG9_CODIGO
EMPIND601

BG9->BG9_CODINT == MV_PAR02


> Consulta padrão CONIND:

Alias

Tipo

Sequencial

Coluna

Descrição

Contem

CONIND101DBContratosBT5
CONIND20101Número do Contrato  
CONIND40101Número do Contrato  BT5_NUMCON
CONIND40103DescriçãoPosicione("BG9",1,xFilial("BG9")+BT5->(BT5_CODINT+BT5_CODIGO),"BG9_DESCRI")
CONIND50101
BT5->BT5_NUMCON
CONIND601

BT5->BT5_CODINT == MV_PAR02 .And. BT5->BT5_CODIGO == MV_PAR03
CONIND40102Código EmpresaPosicione("BG9",1,xFilial("BG9")+BT5->(BT5_CODINT+BT5_CODIGO),"BG9_CODIGO")


> Consulta padrão SUBIND:

Alias

Tipo

Sequencial

Coluna

Descrição

Contem

SUBIND101DBSubContratosBQC
SUBIND20101Número SubContrato 
SUBIND40101Número SubContrato BRC->BQC_SUBCON
SUBIND40102Versão SubContratoBRC->BQC_VERSUB
SUBIND40103DescriçãoBRC->BQC_DESCRI
SUBIND501

BQC->BQC_SUBCON
SUBIND601

BQC->BQC_CODIGO == MV_PAR02 + MV_PAR03 .and. BQC->BQC_NUMCON == MV_PAR04

>> Importante

05. ASSUNTOS RELACIONADOS