Árvore de páginas

Você está vendo a versão antiga da página. Ver a versão atual.

Comparar com o atual Ver Histórico da Página

« Anterior Versão 35 Atual »

01. DADOS GERAIS

Produto:

TOTVS CRM Automação da Força de Vendas

Linha de Produto:

Linha TOTVS CRM SFA

Módulo:Venda
Função:Pedido
Ticket:
Requisito/Story/Issue:


02. ESCOPO FUNCIONAL

Atualmente, o sistema não possui maneira de realizar distribuição de cotas levando em consideração o histórico de vendas dos usuários associados às cotas.

Agora, deverá ser possível adicionar um novo saldo de cotas de forma a distribuí-lo de maneira proporcional aos valor das vendas em um período determinado de X dias.

Ao realizar a distribuição de cotas proporcional ao histórico de vendas, será possível informar um saldo mínimo que os profissionais deverão conter, garantido que mesmo que profissionais que não contenham vendas em seu histórico recebam uma quantidade mínima de cota.

Atualmente, o sistema não permite visualizar os registros de cota de maneira agrupada, por exemplo, registros de cotas por profissional visualizadas sob a perspectiva de supervisor.

Agora, o sistema deverá possibilitar a configuração de visualização de registros de cota de maneira agrupada, de forma a permitir que seja possível adicionar/deduzir saldos de cota a partir de uma seleção de um agrupamento.

Por exemplo, adicionar saldos de todos os produtos de todos os profissionais cujo supervisor seja o Alberto Silva.

Para isso, o sistema deverá receber as seguintes atualizações

02.01 Criação de novas telas de cota

O sistema contará com novo fluxo de telas de cota, cuja primeira tela será listagem de todos os registros de cotas existentes, exibindo os seus nomes, vigências e se estão ativos/inativos. Além disso, permitirá realizar a visualização do modelo de configuração das cotas, a clonagem dela e a edição de seus registros de controle.

Ao clicar em adicionar/editar configurações, o sistema disponibilizará uma tela com os seguintes atributos:

  • Situação: Ativo/Inativo
  • Descrição: descrição da cota
  • Vigência inicio/fim: datas entre as quais a cota será considerada vigente
  • Modelo de cota: seleção de quais serão as entidades de variação de cotas, por exemplo, pode ser selecionada que a cota será distribuída por produto por profissional, ou por produto, por profissional por filial.
    • Ao selecionar os modelos de cota, deverão ser selecionados quais serão os registros referentes àquela entidade que fará parte da primeira criação da cota. Por exemplo, se profissional, então deverá ser selecionado quais profissionais farão parte daquela cota vigente
    • As opções serão: profissional, produto, filial
  • Agrupadores de cota: seleção de quais serão as perspectivas de agrupamento que o sistema deverá criar para a facilitação do controle/manutenção de cotas vigentes
    • As opções serão: profissional, produto, supervisor, filial

Ao clicar em clonar, o sistema disponibilizará a oportunidade de criar uma nova cota, com os mesmos modelos/agrupamentos da anterior, podendo escolher o que fazer com o saldo disponível, entre:

  • Copiar os saldos iniciais da cota anterior como saldo inicial da nova cota
  • Copiar o saldo disponível da cota anterior como saldo inicial da nova cota
  • Determinar um novo saldo inicial fixo, copiando apenas o modelo de configuração da cota anterior

Ao clicar em editar, caso a configuração da cota estiver finalizada e existir agrupamentos configurados, o sistema deverá exibir tela de agrupadores de cota que conterão os seguintes atributos:

  • Listagem de todos os agrupadores vinculados aos registros criados ao finalizar a configuração, por exemplo, todos os supervisores referentes aos usuários selecionados nos filtros dos modelos de cota.
    • A lista conterá, de maneira agrupada (soma), os dados de saldo inicial, saldo disponível, saldo processado e saldo a processar.
    • A lista conterá botão para visualizar controles de cota, abrindo a tela de controles de cota, já filtrado pelos registros associados ao agrupador do contexto
  • Botão para adicionar/deduzir saldo, abrindo modal previamente filtrada com os registros referentes àquele agrupador, onde será possível informar saldo a ser adicionado/deduzido e selecionar a lógica de distribuição, entre:
    • Dividir igualmente
    • Proporcional ao valor do histórico de vendas, que quando selecionado, solicitará o preenchimento de:
      • Dias de histórico: dias retroativos aos quais a aplicação deverá usar de filtro para determinar a proporcionalidade de vendas associadas às entidades selecionadas no filtro de cotas de destino
      • Saldo mínimo: valor mínimo que o sistema deve respeitar ao realizar a distribuição de cotas, garantido que mesmo que profissionais que não contenham vendas em seu histórico recebam uma quantidade mínima de cotas
  • Botão para visualizar controles de maneira geral, sem filtros.

Ao clicar nos botões de visualização de controles de cota, o sistema deverá exibir tela contendo os seguintes atributos:

  • Listagem de controles de cota, contendo informações de situação do controle, saldo inicial, saldo disponível, saldo processado e saldo a processar referentes às variações do modelo de cota configurado
    • Botão para realizar transferência de saldo de cota, onde o sistema abrirá modal informando saldo disponível para transferência, solicitando do usuário as seguintes informações:
      • Saldo a ser transferido
      • Modelo de distribuição 
      • Filtro de controles de cota de destino
    • Botão para visualizar movimentações de cota referentes ao controle, para fins de auditoria, contendo todas as alterações de cota, desde sua criação, informando as datas, origens e vínculos das movimentações associadas a pedidos quando criado automaticamente e a usuários quando alterados manualmente

02.02 Protótipo

O protótipo referente ao fluxo de utilização encontra-se presente no seguinte link: https://www.figma.com/proto/PzhfjrWWkjlAhgTXP4Y1GX/Cota-no-SFA?node-id=2-12&t=UC7pzpNZYr75N7GQ-0&scaling=min-zoom&content-scaling=fixed&page-id=0%3A1

03. ESCOPO TÉCNICO

03.01 Criação de tabela cotaconfiguracao e cotaconfigvinculos

Contexto / Gatilho:

  • Pelo Tools, opção 3

Lógica:

  • O sistema deverá realizar a criação da tabela cotaconfiguracao, com os seguintes campos:
idcotaconfiguracao: PK
idcota: FK para tabela cota, not-null
sglconfiguracao: varchar(20), nullable
valor: varchar(80), nullable
  • O sistema deverá realizar a criação da tabela cotaconfigvinculos, com os seguintes campos:
idcotaconfigvinculos: PK
idcotaconfiguracao: FK para tabela cotaconfiguracao, not-null
idusuario: FK para tabela usuario, nullable
idproduto: FK para tabela produto, nullable
idfilial: FK para tabela local, nullable
idsupervisor: FK para tabela usuario, nullable
sgllogicavinculo: varchar(20), nullable

03.02 Endereçamento do usuário para nova tela de cota, se implementada no projeto cliente

Contexto / Gatilho:

  • No ambiente Web, ao clicar sobre o menu Cadastro → Venda → Cota

Lógica:

  • Caso o repositório do cliente tiver implementação da tela de listagem de cotas remodelada (utilizar serviços para obter a informação)

    • O sistema deve encaminhar o usuário para nova tela de listagem de cotas, desenvolvida a partir deste épico
  • As novas telas de cota deverão ser desenvolvida em projeto cliente (pedidoengine)

03.03.01 Tela de listagem de cotas

Contexto / Gatilho:

  • No ambiente Web, ao clicar sobre o menu Cadastro → Venda → Cota, considerando a condição da seção 03.01.01

Lógica:

  • O sistema deve disponibilizar tela referenciando-se com o protótipo a seguir:

  • O sistema deve encaminhar o usuário para a nova tela de listagem de cotas, que deverá conter os seguintes elementos visuais:
  • "Cota": Título da página
  • SlickGrid contendo as seguintes colunas:
      • "Descrição": campo textual, editável, representando o valor da coluna cota.descricao
      • "Inicio Vigência": Campo de data, editável, representando o valor da coluna cota.datainiciovigencia
      • "Fim Vigência": Campo de data, editável, representando o valor da coluna cota.datafimvigência
      • "Situação": Texto, editável exibindo Ativo/Inativo quando o campo cota.idnativo estiver com respectivos valores 1/0. Ao editar o campo, o tipo do campo vira check-box marcada/desmarcada quando o campo cota.idnativo estiver com respectivos valores 1/0
      • "Configuração": ícone clicável, que quando clicado, encaminha o usuário para a tela de "Configurações de cota", passando como contexto o identificador da cota selecionada (cota.idcota)
        • Quando o campo cota.idnfinalizado = 0, o ícone deve ser exibido como 
        • Caso contrário, o ícone deve ser exibido como 
      • "Clonar": ícone clicável, já existente na tela de cota do CORE.
        • Quando clicado, deve executar a mesma lógica que executa atualmente, copiando todos os dados das tabelas cota, controlecota, cotaconfiguracao
          • Todos os dados devem ser clonados, com exceção dos seguintes campos que podem ser informados a partir da modal de clonagem, sendo estes:
            • cota.descricao
            • cota.datainiciovigencia
            • cota.datafimvigencia
            • controlecota.saldoinicial
            • controlecota.saldodisponivel
      • "Editar": ícone clicável
        • Deve ser exibido somente quando o campo cota.idnfinalizado = 0
        • Quando clicado,
          • Caso houver agrupamentos selecionados na tela de configurações de cota.

            /* select count(*) from cotaconfiguracao where idcota = ? and sglconfiguracao = 'agrup' */
            • O sistema deve enviar o usuário para a tela de "Agrupadores de cota"
          • Caso contrário, deve enviar o usuário para a tela de "Controles de cota"
    • A grid deverá ter recurso de adicionar novo registro, disponibilizando botão "Adicionar" que, quando clicado, encaminhará o usuário para tela de "Configurações de cota"
    • A grid deve ter botão "Gravar", para permitir persistir os campos editáveis alterados
      • Caso o usuário deseje cancelar a alteração de um registro não gravado, poderá clicar em botão "Cancelar alteração"
    • A pesquisa rápida deve considerar os campos cota.descricao
    • A pesquisa avançada deverá disponibilizar os seguintes campos:
      • "Descrição": campo texto.
        • Quando preenchido buscará pelo campo cota.descricao



03.03.02 Tela de configuração de cotas

Contexto / Gatilho:

Lógica:

  • O sistema deve encaminhar o usuário para a tela de configuração de cotas, exibindo elementos visuais referenciando-se com o protótipo a seguir:

  • A tela deverá conter os seguintes elementos visuais:
  • "Configurações de Cota": Título da página
  • Corpo da página
    • "Situação": Campo de entrada do tipo radio button, com duas opções: Ativo / Inativo. Ativo por padrão.
      • A informação preenchida deve ser persistida no campo cota.idnativo, sendo (1: Ativo) e (0: Inativo)
    • "Descrição": Campo de entrada, do tipo textual, obrigatório. Limitado a 80 caracteres.
      • A informação preenchida deve ser persistida no campo cota.descricao
    • "Vigência de" e "Vigência até": campos de entrada, do tipo data, obrigatórios.
      • As informações preenchidas devem ser persistidas, respectivamente, nos campos cota.datainiciovigencia e cota.datafimvigencia
    • "Modelo de Cota": título de grupo de elementos, que contém os seguintes elementos:
      • "Defina qual será o modelo de controle de cota": Texto fixo
      • Lista de elementos, sendo:
          • Modelo de cota: Combo-box com as seguintes opções:
              • Profissional (valor persistência: usuario)
              • Produto (valor persistência: produto)
              • Filial (valor persistência: filial)
            • As opções não devem aparecer caso já tenham sido selecionada em elementos da lista
              • Por exemplo: Se no primeiro elemento, o usuário selecionar "Profissional", as opções do próximo elemento da lista serão apenas "Produto" e "Filial"
            • A informação preenchida deve ser persistida no campo cotaconfiguracao.valor, onde cotaconfiguracao.sglconfiguracao = 'modelo'
          • "Selecionar": Botão que, quando clicado, abre modal de seleção múltipla para a entidade selecionada em questão
            • O botão somente deve ser visível quando houver Modelo de cota selecionado
            • Quando confirmadas as seleções da modal, o sistema deverá exibir texto `${contagem de registros selecionados} registros selecionados` ao lado do botão "Selecionar"
              • Caso nenhum registro estiver selecionado, exibir "Nenhum registro selecionado"
          • Remover modelo: Ícone que, quando clicado, deve remover o item da lista de modelos selecionados
            • O ícone não deve aparecer para o primeiro elemento da lista
        • O último elemento da lista deve ser sempre um registro cujo elemento [Modelo de cota] não tenha sido selecionado.
          • Assim que o modelo for selecionado, deve ser inserido mais um elemento vazio ao fim da lista, para garantir a regra acima.
    • "Agrupamentos de cota": título de grupo de elementos, que contém os seguintes elementos:
      • "Defina sob quais perspectivas a visualização/manutenção de cotas será feito": Texto fixo
      • Lista de elementos, sendo:
        • Agrupamento de cota: Combo-box com as seguintes opções:
            • ${Lista de modelos selecionados no campo Modelo de cota
            • Caso a entidade Profissional tenha sido selecionada na lista de modelos selecionados no campo Modelo de cota, o sistema deve exibir a opção:
              • Supervisor (valor persistência: supervisor)
              • Filial (caso não esteja na lista de modelos selecionados no campo Modelo de cota) (valor persistência: filial)
            • Caso a entidade Produto sido selecionada na lista de modelos selecionados no campo Modelo de cota, o sistema deve exibir a opção:
              • Filial (caso não esteja na lista de modelos selecionados no campo Modelo de cota) (valor persistência: filial)
          • A informação preenchida no campo deve ser persistida na tabela cotaconfiguracao, onde:

            {
            	idcota: registro de cota referente ao contexto da tela
            	sglconfiguracao: 'agrup'
            	valor: valor referente ao campo selecionado
            }
        • "Selecionar vínculos": botão que, quando clicado, deve abrir modal para seleção de opções de vínculos.
          • A modal de seleção de vínculos deve exibir os seguintes elementos:
            • "Vínculos": título da modal
            • "Pesquisa rápida": Campo de entrada textual, para pesquisar sobre a descrição dos Enums de vínculos que serão exibidos
            • Grid de seleção múltipla, contendo as seguintes colunas:
              • Check-box de seleção dos registros
              • "Descrição": Coluna que deverá exibir a descrição dos Enums de vínculos que serão exibidos
            • Botões de ação, sendo:
              • Cancelar: quando clicado, fecha a modal
              • Confirmar: quando clicado, grava em memória os objetos para persistência na tabela cotaconfigvinculos, onde:

                {
                	idcotaconfiguracao: referência da configuração de agrupamento referente à modal
                	sgllogicavinculo: valor do Enum do registro selecionado
                }
          • O botão somente deve ser exibido quando o campo Agrupamento de cota estiver selecionado com a opção "Filial", e quando aberta, deverá exibir os seguintes Enums:

            { Descrição: "Filtrar somente filiais vinculadas aos produtos", valor para persistência: produtofilial } // mostrado apenas quando produto foi selecionado no campo de Modelos de cota
            { Descrição: "Filtrar somente filiais vinculadas aos profissionais", valor para persistência: usuariofilial } // mostrado apenas quando usuario foi selecionado no campo de Modelos de cota
  • Botões de ação, sendo:
    • "Gravar": persiste os dados nas tabelas cota, cotaconfig e cotaconfigvinculos, conforme descrito nas regras acima.
    • "Finalizar": 
      • Além de persistir os dados nas tabelas cota, cotaconfig e cotaconfigvinculos, conforme descrito nas regras acima, 
        • O sistema deve realizar a persistência da tabela controlecota, de forma a criar os registros de controle conforme os modelos que foram selecionados.


          • Para isso, o sistema deve realizar um cross join de todas as seleções de modelos do campo Selecionar, como exemplifica a seguinte sentença SQL:

            Nesse exemplo, consideram-se as entidades produto e usuario como modelos selecionados
            
            CONSULTA_1
            /* 
            select p.idproduto, p.idusuario, null as idlocalfilial from produto p
            cross join usuario u
            where p.idproduto in (:lista_produtos_vinculados) 
            and u.idusuario in (:lista_usuarios_vinculados)
            */
          • Com as combinações das entidades em memória, o sistema deve inserir registros na tabela controlecota, como exemplifica a seguinte sentença SQL:

            insert into controlecota (idnativo,saldodisponivel,saldoinicio,idcota,idusuario,idproduto,idlocalfilial)
            values (
            	select 1,0,0,:identificador_cota_contexto, idusuario, idproduto, idlocalfilial from CONSULTA_1
            )
          • Visto que o processo pode levar um tempo considerável, é importante existir um feedback visual, como barra de progresso, ou no mínino um GIF de carregando com a mensagem: "Por favor, aguarde. Esse processo pode levar alguns minutos"
    • "Voltar": retorna à página anterior

03.03.02 Tela de agrupamentos de cotas

Contexto / Gatilho:

  • No ambiente Web, na tela de listagem de cotas, ao clicar sobre o botão  "Editar", caso na tela de configuração de cota existir algum agrupamento selecionado.

    /* select count(*) from cotaconfiguracao where idcota = ? and sglconfiguracao = 'agrup' */
    • OU

      • Ao clicar sobre o botão "Visualizar movimentos"

Lógica:

  • O sistema deve encaminhar o usuário para a tela de agrupamentos de cotas, exibindo elementos visuais referenciando-se com o protótipo a seguir:

  • A tela deverá conter os seguintes elementos visuais:
  • `Agrupadores de cota - ${cota.descricao} (cota.datainiciovigencia - cota.datafimvigencia)`
  • Conteúdo da página
    • `${Nome do agrupamento de cota}` Abas de agrupamento
      • As abas que devem ser mostradas na tela devem ser consultadas pela SQL a seguir:

        /* 
        	select valor from cotaconfiguracao where sglconfiguracao = 'agrup'
        */
        Valores possíveis: produto, usuario, filial, supervisor
        Valores para exibição na tela, respectivamente: Produto, Profissional, Filial, Supervisor
      • Conteúdo da aba
        • Cabeçalho de pesquisa:
          • "Pesquisa rápida": Campo de entrada textual
          • Botões de ação:
            • Pesquisar: Quando clicado, dispara a requisição de pesquisa de registros da entidade agrupadora, filtrando a informação digitada no campo de pesquisa rápida, comparando com:
              • produto.descricao quando produto
              • usuario.nome quando usuario
              • local.descricao quando filial
              • usuario.nome quando supervisor
            • Limpar: Limpa os valores dos campos de pesquisa
        • Botão de ação referente à grid de informações de agrupadores de cota, sendo:
          • "Alterar saldos": Quando clicado, executa a lógica referente à função de alteração de saldo, passando como contexto os identificadores dos registros selecionados
        • Grid de informações de agrupadores de controle de cota, contendo as seguintes colunas:
            • `${Nome do agrupamento, recebendo o mesmo nome da aba}`: Campo textual, somente leitura, exibindo os valores dos seguintes campos:
              • produto.descricao quando produto
              • usuario.nome quando usuario
              • local.descricao quando filial
              • usuario.nome quando supervisor
            • "% Cota": Campo numérico, somente leitura, exibindo o percentual relativo de quanto a coluna Saldo disponível representa do saldo total disponível da cota, sendo:

              % cota = ${Coluna Saldo disponível} / ${/* select sum(saldodisponivel) from controlecota where idcota = (?) and idnativo = 1 */} * 100


              • "Saldo inicial": Campo numérico, somente leitura, exibindo o conteúdo do campo controlecota.saldoinicio somado de todas as contas de flex que possuem vínculo com o agrupador, sendo:

                CONSULTA_CONTROLECOTA_VINCULADO_AGRUPADOR
                
                Se agrupador = produto
                	/* select * from controlecota where idproduto in (?) and idnativo = 1 */
                Se agrupador = usuario
                 	/* select * from controlecota where idusuario in (?) and idnativo = 1 */ 
                Se agrupador = supervisor
                 	/* select * from controlecota where idusuario in (select idusuario from usuariohierarquia where idusuariosuperior in (?)) and idnativo = 1 */ 
                Se agrupador = filial
                	/*
                	select * from controlecota where 
                	// Se (select sgllogicavinculo from cotaconfigvinculos ccv 
                		inner join cotaconfiguracao cc on cc.idcotaconfiguracao = ccv.idcotaconfiguracao
                		where idcota = (?)) contiver o valor "produtofilial" 	
                	// então
                	idlocalfilial in (select idlocalfilial from produtofilial where idproduto in (?))
                	// Se (select sgllogicavinculo from cotaconfigvinculos ccv 
                		inner join cotaconfiguracao cc on cc.idcotaconfiguracao = ccv.idcotaconfiguracao
                		where idcota = (?)) contiver o valor "usuariofilial" 	
                	// então
                	and idlocalfilial in (select idlocalfilial from usuariofilial where idusuario in (?))
                	*/
                • Projetar para o campo controlecota.saldoinicio
            • "Saldo disponível": Campo numérico, somente leitura, exibindo o conteúdo do campo controlecota.saldodisponivel somado de todos os controles de cota que possuem vínculo com o agrupador, sendo a mesma lógica de consulta CONSULTA_CONTROLECOTA_VINCULADO_AGRUPADOR, projetada para o campo controlecota.saldodisponivel
            • "Saldo processado": Campo numérico, somente leitura, exibindo o somatório de todas as movimentações ativas e processadas com relação aos controles de cota que possuem vínculo com o agrupador, sendo:

              /*
              	select sum(valor) from controlecotamovimento ccm where ccm.idcontrolecota in (CONSULTA_CONTROLECOTA_VINCULADO_AGRUPADOR -> idcontrolecota) and ccm.idnativo = 1 and ccm.idnprocessado = 1
              /*
            • "Saldo a processar": Campo numérico, somente leitura, exibindo o somatório de todas as movimentações ativas e não-processadas com relação aos controles de cota que possuem vínculo com o agrupador, sendo:

              /*
              	select sum(valor) from controlecotamovimento ccm where ccm.idcontrolecota in (CONSULTA_CONTROLECOTA_VINCULADO_AGRUPADOR -> idcontrolecota) and ccm.idnativo = 1 and ccm.idnprocessado = 0
              /*
            • "Editar": Botão que quando clicado, deve encaminhar o usuário para a tela de controle de cotas, mandando o registro do agrupador em questão como contexto.
  • Botões de ação
    • Visualizar controles: Quando clicado, deve encaminhar o usuário para a tela de controle de cotas.
    • "Voltar": retorna à página anterior

03.03.03 Tela de controle de cotas

Contexto / Gatilho:

  • No ambiente Web,

Lógica:

  • O sistema deve encaminhar o usuário para a tela de controles de cota, que deve conter elementos visuais referenciando-se com o protótipo a seguir:

  • A tela deve conter os seguintes elementos visuais:
  • `Controles de cota - ${cota.descricao} (cota.datainiciovigencia - cota.datafimvigencia)`
  • Conteúdo da página
    • Cabeçalho de pesquisa: 
      • "Pesquisa rápida": Campo de entrada textual
        • Quando pesquisado, a informação do campo é utilizada para comparar com:
          • produto.descricao referente aos produtos do campo controlecota.idproduto
          • usuario.nome referente aos usuarios do campo controlecota.idproduto
          • local.descricao referente às filiais do campo controlecota.idlocalfilial
      • "Pesquisa avançada": Texto clicável, para exibir/ocultar os seguintes campos:
        • "Unidade": Campo de pesquisa, múltipla seleção, consultando as filiais pertencentes àquela cota
          • Quando preenchido, é utilizado para comparar com o campo controlecota.idlocalfilial
        • "Profissional": Campo de pesquisa, múltipla seleção, consultando os usuários pertencentes àquela cota
          •  Quando preenchido, é utilizado para comparar com o campo controlecota.idusuario
        • "Produto":  Campo de pesquisa, múltipla seleção, consultando os produtos pertencentes àquela cota
          •  Quando preenchido, é utilizado para comparar com o campo controlecota.idproduto
        • "Situação": campos check-box com opções:
          • "Ativo": Marcado por padrão. Quando marcado, filtra registros de credencial onde o campo credencial.idnativo = 1
          • "Inativo": Desmarcado por padrão. Quando marcado, filtra registros de credencial onde o campo credencial.idnativo = 0
      • Botões de ação:
        • Pesquisar: Quando clicado, dispara a requisição de pesquisa de registros da entidade de controles de cota, utilizando as comparações descritas acima
          • A busca padrão de registros deve considerar os seguintes filtros:

            select * from controlecota where idnativo = 1 and idcota = (?)
          • Caso a tela tenha sido aberta a partir do botão de editar controles do agrupador de cota, o sistema deve popular os filtros dos modelos vinculados com o agrupador em questão, respeitando o filtro CONSULTA_CONTROLECOTA_VINCULADO_AGRUPADOR

            Por exemplo, se clicado no botão editar sobre um agrupamento de supervisor
            
            O sistema deverá abrir a tela de controle filtrando o campo "Profissional" com os valores selecionados dos usuários vinculados com aquele supervisor.
        • Limpar: Limpa os valores dos campos de pesquisa
    • Grid de informações de controle de cota, contendo as seguintes colunas:
      • "Profissional": Campo textual, somente leitura, exibindo o conteúdo do campo controlecota.idusuario → usuario.nome
        • Coluna somente deve ser exibida caso a entidade usuario estiver selecionada nos modelos da cota

          /* (select valor from cotaconfiguracao where idcota = ? and sglconfiguracao = 'modelo') */ = 'usuario'
      • "Produto": Campo textual, somente leitura, exibindo o conteúdo do campo controlecota.isproduto → produto.descricao
        • Coluna somente deve ser exibida caso a entidade produto estiver selecionada nos modelos da cota

          /* (select valor from cotaconfiguracao where idcota = ? and sglconfiguracao = 'modelo') */ = 'produto'	
      • "Filial": Campo textual, somente leitura, exibindo o conteúdo do campo controlecota.idlocalfilial → local.descricao
        • Coluna somente deve ser exibida caso a entidade filial estiver selecionada nos modelos da cota

          /* select valor from cotaconfiguracao where idcota = ? and sglconfiguracao = 'modelo' */
      • "Saldo inicial": Campo numérico, somente leitura, exibindo o conteúdo do campo controlecota.saldoinicio
      • "Saldo disponível": Campo numérico, somente leitura, exibindo o conteúdo do campo controlecota.saldodisponivel
      • "Saldo processado": Campo numérico, somente leitura, exibindo o somatório de todas as movimentações ativas e processadas com relação aos controles de cota que possuem vínculo com o agrupador, sendo:

        /*
        	select sum(valor) from controlecotamovimento ccm where ccm.idcontrolecota = (?) and ccm.idnativo = 1 and ccm.idnprocessado = 1 
        /*
      • "Saldo a processar": Campo numérico, somente leitura, exibindo o somatório de todas as movimentações ativas e não-processadas com relação aos controles de cota que possuem vínculo com o agrupador, sendo:

        /*
        	select sum(valor) from controlecotamovimento ccm where ccm.idcontrolecota = (?) and ccm.idnativo = 1 and ccm.idnprocessado = 0
        /*
      • "Situação": Texto, editável exibindo Ativo/Inativo quando o campo controlecota.idnativo estiver com respectivos valores 1/0. Ao editar o campo, o tipo do campo vira check-box marcada/desmarcada quando o campo controlecota.idnativo estiver com respectivos valores 1/0
      •  "Transferir saldo": Ícone clicável que, quando clicado, executa a lógica referente à função de transferência de saldo, passando como contexto o identificador do registro de controle de cota em questão
      •    "Visualizar movimentos": Quando clicado, deve encaminhar o usuário para a tela de movimentos de controles de cota, passando como contexto o identificador do registro de controle de cota em questão
  • Botões de ação

03.03.04 Tela de movimentos de controles de cota

Contexto / Gatilho:

  • No ambiente Web, na tela de controles de cotas,
      • Ao clicar sobre o botão "Editar" (Gatilho 1) , passando como contexto o identificador do controle de cota em questão
    • OU

      • Ao clicar sobre o botão "Visualizar movimentos"

Lógica:

  • O sistema deve encaminhar o usuário para a tela de movimentos de controles de cota, que deve exibir elementos referenciando-se com o protótipo a seguir:

  • A tela deve possuir os seguintes elementos visuais:
  • `Movimentos - ${cota.descricao} (cota.datainiciovigencia - cota.datafimvigencia)`
  • Conteúdo da página
    • Cabeçalho de pesquisa: 
      • "Pesquisa rápida": Campo de entrada textual
        • Quando pesquisado, a informação do campo é utilizada para comparar com:
          • produto.descricao referente aos produtos do campo controlecota.idproduto
          • usuario.nome referente aos usuarios do campo controlecota.idproduto
          • local.descricao referente às filiais do campo controlecota.idlocalfilial
      • "Pesquisa avançada": Texto clicável, para exibir/ocultar os seguintes campos:
        • "Unidade": Campo de pesquisa, múltipla seleção, consultando as filiais pertencentes àquela cota
          • Quando preenchido, é utilizado para comparar com o campo controlecota.idlocalfilial
        • "Profissional": Campo de pesquisa, múltipla seleção, consultando os usuários pertencentes àquela cota
          • Quando preenchido, é utilizado para comparar com o campo controlecota.idusuario
        • "Produto":  Campo de pesquisa, múltipla seleção, consultando os produtos pertencentes àquela cota
          • Quando preenchido, é utilizado para comparar com o campo controlecota.idproduto
        • "Situação": campos check-box com opções:
          • "Ativo": Marcado por padrão. Quando marcado, filtra registros de credencial onde o campo credencial.idnativo = 1
          • "Inativo": Desmarcado por padrão. Quando marcado, filtra registros de credencial onde o campo credencial.idnativo = 0
      • Botões de ação:
        • Pesquisar: Quando clicado, dispara a requisição de pesquisa de registros da entidade de controles de cota, utilizando as comparações descritas acima
          • A busca padrão de registros deve considerar os seguintes filtros:

            select * from controlecotamovimento where idcota = (?)
          • Caso a tela tenha sido aberta a partir do botão de visualizar movimentos de controle de cota, o sistema deve popular os filtros dos modelos vinculados com o agrupador em questão, respeitando os seguintes filtros

            /* 
            	select * from controlecotamovimento 
            	where idproduto = (? -> controlecota.idproduto) -- caso valor não nulo
            	and idusuario = (? -> controlecota.idusuario) -- caso valor não nulo
             	and idlocalfilial = (? -> controlecota.idlocalfilial) -- caso valor não nulo
            */
        • Limpar: Limpa os valores dos campos de pesquisa
  • Grid de informações de controle de cota, contendo
    • Botões de ação
      • Adicionar: Botão que, quando clicado,
        • Adiciona nova linha na grid de movimentos, tornando editáveis os campos:
          • Profissional: campo pesquisa, buscando registros de profissionais ativos da cota
          • Produto: campo pesquisa, buscando registros de produtos ativos da cota
          • Filial: campo pesquisa, buscando registros de locais do tipo filial ativos da cota
          • Quantidade: input textual
            • O input deve aceitar valores negativos
          • Observação: input text area
        • Quando gravado, o registro deverá

          • Ser persistido na tabela controlecotamovimento, sendo que:

            {
            	idprofissional: identificador da entidade do campo "Profissional"
            	idproduto: identificador da entidade do campo "Produto"
            	idlocalfilial: identificador da entidade do campo "Filial"
            	quantidade: campo "Quantidade"
            	observação: campo "Observação" concatenado a mensagem "\n\nMovimento criado e processado manualmente pela aplicação",
            	sglorigem: 'WEB'
            	idnativo: 1
            	idnprocessado: 1
            	data: current_date
            	datamovimento:current_date
            }
          • Ser somado ao saldo do controle de cota do contexto da tela, sendo: 

            update controlecota set saldodisponivel = saldodisponivel + ${controlecotamovimento.quantidade}
      • Cancelar alteração: cancela alterações da grid ainda não commitadas em banco
      • Gravar: commita as alterações da grid, mais especificamente para registros adicionados, visto que nenhum campo é editável após o registro ter sido gravado.
    • As seguintes colunas:
      • "Profissional": Campo textual, somente leitura, exibindo o conteúdo do campo controlecota.idusuario → usuario.nome
        • Coluna somente deve ser exibida caso a entidade usuario estiver selecionada nos modelos da cota

          /* (select valor from cotaconfiguracao where idcota = ? and sglconfiguracao = 'modelo') */ = 'usuario'
      • "Produto": Campo textual, somente leitura, exibindo o conteúdo do campo controlecota.isproduto → produto.descricao
        • Coluna somente deve ser exibida caso a entidade produto estiver selecionada nos modelos da cota

          /* (select valor from cotaconfiguracao where idcota = ? and sglconfiguracao = 'modelo') */ = 'produto'	
      • "Filial": Campo textual, somente leitura, exibindo o conteúdo do campo controlecota.idlocalfilial → local.descricao
        • Coluna somente deve ser exibida caso a entidade filial estiver selecionada nos modelos da cota

          /* select valor from cotaconfiguracao where idcota = ? and sglconfiguracao = 'modelo' */
      • "Origem": campo textual, somente leitura, exibindo a descrição dos enums cadastrados para o campo controlecotamovimento.sglorigem
      • "Situação": Texto, editável exibindo Ativo/Inativo quando o campo contolecotamovimento.idnativo estiver com respectivos valores 1/0. Ao editar o campo, o tipo do campo vira check-box marcada/desmarcada quando o campo contolecotamovimento.idnativo estiver com respectivos valores 1/0
      • "Processado": Texto, editável exibindo Ativo/Inativo quando o campo contolecotamovimento.idnprocessado estiver com respectivos valores 1/0. Ao editar o campo, o tipo do campo vira check-box marcada/desmarcada quando o campo contolecotamovimento.idnprocessado estiver com respectivos valores 1/0
      • "Data": Campo de data, somente leitura, exibindo o conteúdo do campo controlecotamovimento.datamovimento || controlecotamovimento.data
      • "Quantidade": Campo numérico, somente leitura, exibindo o conteúdo do campo controlecotamovimento.quantidade
      • "Observação": Campo textual, somente leitura, exibindo o conteúdo do campo controlecotamovimento.observacao

03.04 Função de alterar saldo

Contexto / Gatilho:

  • No ambiente Web,
    • (Gatilho 1) Na tela de controles de cota, ao clicar sobre o botão "Alterar saldos", passando como contexto os modelos filtrados pela pesquisa.
    • (Gatilho 2) Na tela de agrupamentos de cota, ao clicar sobre o botão "Alterar saldos", passando como contexto o registro da entidade agrupadora

Lógica:

  • O sistema deve abrir modal referenciando-se com o protótipo a seguir:

  • A modal deve conter os seguintes elementos visuais:
  • "Alteração de saldo de cota": título da modal
  • Campo radio button, com duas opções:
      • "Adicionar saldo"
      • "Deduzir saldo"
    • Ao lado das opções, deve ser exibido campo input numérico, editável
  • Separador horizontal
  • "Distribuição de saldo": título de grupo de elementos
    • "Modelo de distribuição": Campo de opções selecionáveis (combo-box), mostrando as opções:
        • "Distribuir igualmente"
        • "Dividir proporcionalmente ao valor de pedidos anteriores"
      • "Dias de histórico: input numérico, aceitando valores inteiros positivos, editável
        • O campo somente deve ser exibido, caso o campo "Modelo de distribuição" estiver marcado com a opção "Dividir proporcionalmente ao valor de pedidos anteriores"
        • O valor preenchido no campo deve ser persistido na sessão, de forma que ao abrir a modal novamente, o campo venha previamente preenchido.
      • "Saldo mínimo": input numérico editável
        • O campo somente deve ser exibido, caso o campo "Modelo de distribuição" estiver marcado com a opção "Dividir proporcionalmente ao valor de pedidos anteriores"
        • O valor preenchido no campo deve ser persistido na sessão, de forma que ao abrir a modal novamente, o campo venha previamente preenchido.
  • "Filtro de controles de cota de destino": título de grupo de elementos
    • "Profissional": Botão que, quando clicado, abre modal de seleção múltipla para a entidade selecionada em questão (usuario)
      • Somente devem ser exibidos usuários que pertencem à cota do contexto e estejam com o controle ativo

        select idusuario from controlecota where idcota = ? and idnativo = 1
      • O botão somente deve ser visível quando a entidade estiver selecionada no campo Modelo de cota
      • Quando confirmadas as seleções da modal, o sistema deverá exibir texto `${contagem de registros selecionados} registros selecionados` ao lado do botão "Selecionar"
        • Caso nenhum registro estiver selecionado, exibir "Nenhum registro selecionado. Aplicável a todos"
    • "Produto": Botão que, quando clicado, abre modal de seleção múltipla para a entidade selecionada em questão (produto)
      • Somente devem ser exibidos produtos que pertencem à cota do contexto e estejam com o controle ativo

        select idproduto from controlecota where idcota = ? and idnativo = 1
      • O botão somente deve ser visível quando a entidade estiver selecionada no campo Modelo de cota
      • Quando confirmadas as seleções da modal, o sistema deverá exibir texto `${contagem de registros selecionados} registros selecionados` ao lado do botão "Selecionar"
        • Caso nenhum registro estiver selecionado, exibir "Nenhum registro selecionado. Aplicável a todos"
    • "Filial": Botão que, quando clicado, abre modal de seleção múltipla para a entidade selecionada em questão (local, do tipo filial)
      • Somente devem ser exibidas filiais que pertencem à cota do contexto e estejam com o controle ativo

        select idlocalfilial from controlecota where idcota = ? and idnativo = 1
      • O botão somente deve ser visível quando a entidade estiver selecionada no campo Modelo de cota
      • Quando confirmadas as seleções da modal, o sistema deverá exibir texto `${contagem de registros selecionados} registros selecionados` ao lado do botão "Selecionar"
        • Caso nenhum registro estiver selecionado, exibir "Nenhum registro selecionado. Aplicável a todos"
  • Botões de ação
    • "Cancelar": Fecha a modal
    • "Confirmar e Sair": Executa toda a lógica do botão "Confirmar" e fecha a modal
    • "Confirmar": Quando clicado, o sistema deve:
      • Verificar se o campo de input referente ao campo "Adicionar saldo" / "Deduzir saldo" selecionado está preenchido.
        • Caso não estiver, rollback + mensagem: Preencha o campo ${"Adicionar saldo" ou "Deduzir saldo" dependendo do que  estiver selecionado}
      • Verificar se os campos "Dias de histórico" e "Saldo mínimo" estiverem visíveis e não preenchidos
        • Caso verdadeiro, rollback + mensagem: Preencha o campo ${campo não preenchido em questão}
      • Validar se todos os controles de cotas ativas filtradas pelos filtros de controles de cota de destino receberão o montante definido no campo "Saldo mínimo"

        ${Saldo a ser distribuido igualmente}
        /* select ${Valor do saldo adicionado} / count(*) from controlecota 
        where (idusuario in (:filtro_usuario) or (:filtro_usuario) is null) 
        and  (idproduto in (:filtro_produto) or (:filtro_produto) is null)  
        and  (idlocalfilial in (:filtro_filial) or (:filtro_filial) is null) */
        
        Verificar se ${Saldo a ser distribuido, se igualmente} > ${Valor do saldo mínimo}
        • Se falso, rollback + mensagem: "O saldo adicionado não é suficiente para respeitar o saldo mínimo definido"
      • Se "Modelo de distribuição" = "Distribuir igualmente"
        • Se o campo radio button estiver marcado como "Adicionar saldo"
          • O sistema deverá adicionar um movimento de cota igual positivo na controlecotamovimento para todos os controles de cota filtrados pelos filtros de controles de cota de destino e somá-lo ao saldo do controle de cota, da seguinte forma:

            Por exemplo, se filtrados usuários e produtos na modal
            
            SET1: set de controlecotas a serem atualizadas
            	/* select idcontrolecota from controlecota where idproduto in (?) and idusuario in (?) and idnativo = 1
            
            Para cada registro:
            /* insert into controlecotamovimento ... values
            {
            	idprofissional: identificador da entidade do campo "Profissional"
            	idproduto: identificador da entidade do campo "Produto"
            	quantidade: ${Saldo a ser distribuido igualmente}
            	observação: "Movimento criado e processado manualmente pela aplicação",
            	sglorigem: 'WEB'
            	idnativo: 1
            	idnprocessado: 1
            	data: current_date
            	datamovimento:current_date
            }
            */
            
            /*
            update controlecota set saldodisponivel = saldodisponivel + ${controlecotamovimento.quantidade}
            */


            • O sistema deverá retornar feedback visual toast (Success): "Operação realizada com sucesso"
        • Se o campo radio button estiver marcado como "Deduzir saldo"
          • O sistema deverá adicionar um movimento de cota igual negativo na controlecotamovimento para todos os controles de cota filtrados pelos filtros de controles de cota de destino e somá-lo ao saldo do controle de cota
            • Caso o saldo disponível pelo controle de cota não for suficiente para ser deduzido integralmente, o sistema deve retornar o valor que não pôde ser deduzido, com a mensagem pop up:
              • "Dedução de ${${Valor do campo deduzir saldo } - ${Valor que não pôde ser deduzido}} foi realizada com sucesso. Não foi possível deduzir  ${Valor que não pôde ser deduzido} do saldo de cota, devido à saldos disponíveis insuficientes" Opções "OK" e  "Deduzir restante"
              • Ao clicar em ok, fechar a modal
              • Ao clicar em "Deduzir restante", aplicar  ${Valor que não pôde ser deduzido} no campo "Deduzir saldo"
          • Por exemplo, se filtrados usuários e produtos na modal
            
            SET1: set de controlecotas a serem deduzidas 
            	/* select idcontrolecota from controlecota where idproduto in (?) and idusuario in (?) and idnativo = 1 and saldodisponivel > 0
            
            Para cada registro:
            ${Saldo a ser deduzido} = controlecota.saldodisponivel >= ${Saldo a ser distribuido igualmente} ? ${Saldo a ser distribuido igualmente} : controlecota.saldodisponivel
            -- Se controlecota.saldodisponivel < ${Saldo a ser distribuido igualmente}, somar os valores que não puderam ser deduzidos
            ${Valor que não pôde ser deduzido} = ${Saldo a ser distribuido igualmente} - controlecota.saldodisponivel
            
            /* insert into controlecotamovimento ... values
            {
            	idprofissional: identificador da entidade do campo "Profissional"
            	idproduto: identificador da entidade do campo "Produto"
            	quantidade: -${Saldo a ser deduzido}
            	observação: "Movimento criado e processado manualmente pela aplicação",
            	sglorigem: 'WEB'
            	idnativo: 1
            	idnprocessado: 1
            	data: current_date
            	datamovimento:current_date
            }
            */
            
            /*
            update controlecota set saldodisponivel = saldodisponivel + ${controlecotamovimento.quantidade}
            */ -- Caso o saldo disponível não seja suficiente para ser deduzido, o campo saldodisponivel deve obrigatoriamente resultar em 0


            • Caso o saldo todo pôde ser deduzido, o sistema deverá retornar feedback visual toast (Success): "Operação realizada com sucesso"
      • Se "Modelo de distribuição" = "Dividir proporcionalmente ao valor de pedidos anteriores"
        •  Se o campo radio button estiver marcado como "Adicionar saldo"
          • A lógica de distribuição será realizada desta forma:

            Por exemplo, se filtrados usuários e produtos na modal
            
            SET1: set de controlecotas a serem deduzidas 
            	/* select idcontrolecota from controlecota where idproduto in (?) and idusuario in (?) and idnativo = 1
            
            /* select sum(pp.quantidadefaturada * pp.precofaturado) as valor from pedidoproduto pp
            inner join pedido p on pp.idpedido = p.idpedido
            inner join tiposituacaopedido tsp on tsp.idtiposituacaopedido = p.idtiposituacaopedido
            where p.idusuario in (:filtro_usuario)
            and pp.idproduto in (:filtro_produto) 
            and tsp.sgltiposituacaopedido in (:parametro_sim3g.cota.distribuicao.historico.sgltiposituacaopedido /* Deve ser criado pelo tools, opção 18 */
            group by pp.idproduto, p.idusuario
            */ CONSULTA_A
            
            /* select sum(valor) as valor_total from CONSULTA_A */
            
            O sistema deverá atribuir peso de 0 a 1 para todos os registros filtrados, com base na relação entre o valor e o valor total
            /* select idproduto,idusuario,valor/${valor_total} as peso */ CONSULTA_PESOS
            
            Com os pesos em mãos, o sistema deverá em primeiro momento contabilizar o excedente entre o saldo a adicionar e o saldo mínimo a adicionar
            ${Valor total distribuido igualmente} = SET1.size() * ${Valor do saldo mínimo}
            ${Valor restante} = ${Valor a ser adicionado} - ${Valor total distribuido igualmente} 
            
            Para cada registro:
            /* insert into controlecotamovimento ... values
            {
            	idprofissional: identificador da entidade do campo "Profissional"
            	idproduto: identificador da entidade do campo "Produto"
            	quantidade: ${Saldo a ser distribuido igualmente} + ${${Valor restante} * CONSULTA_PESOS.peso}
            	observação: "Movimento criado e processado manualmente pela aplicação",
            	sglorigem: 'WEB'
            	idnativo: 1
            	idnprocessado: 1
            	data: current_date
            	datamovimento:current_date
            }
            */
            
            /*
            update controlecota set saldodisponivel = saldodisponivel + ${controlecotamovimento.quantidade}
            */
        • Se o campo radio button estiver marcado como "Deduzir saldo"
            • O sistema deverá adicionar um movimento de cota igual negativo na controlecotamovimento para todos os controles de cota filtrados pelos filtros de controles de cota de destino e somá-lo ao saldo do controle de cota
              • Caso o saldo disponível pelo controle de cota não for suficiente para ser deduzido integralmente, o sistema deve retornar o valor que não pôde ser deduzido, com a mensagem pop up:
                • "Dedução de ${${Valor do campo deduzir saldo } - ${Valor que não pôde ser deduzido}} foi realizada com sucesso. Não foi possível deduzir  ${Valor que não pôde ser deduzido} do saldo de cota, devido à saldos disponíveis insuficientes" Opções "OK" e  "Deduzir restante"
                • Ao clicar em ok, fechar a modal
                • Ao clicar em "Deduzir restante", aplicar  ${Valor que não pôde ser deduzido} no campo "Deduzir saldo"


                  Por exemplo, se filtrados usuários e produtos na modal
                  
                  SET1: set de controlecotas a serem deduzidas 
                  	/* select idcontrolecota from controlecota where idproduto in (?) and idusuario in (?) and idnativo = 1 and saldodisponivel > 0
                  
                  Mesma lógica para encontrar CONSULTA_PESOS da lógica de adição acima
                  
                  Para cada registro:
                  ${Saldo a ser deduzido proporcionalmente ao histórico} = ${Saldo a ser distribuido igualmente} + ${${Valor restante} * CONSULTA_PESOS.peso}
                  ${Saldo a ser deduzido} = controlecota.saldodisponivel >= ${Saldo a ser deduzido proporcionalmente ao histórico} ? ${Saldo a ser deduzido proporcionalmente ao histórico} : controlecota.saldodisponivel
                  -- Se controlecota.saldodisponivel < ${Saldo a ser deduzido proporcionalmente ao histórico}, somar os valores que não puderam ser deduzidos
                  ${Valor que não pôde ser deduzido} = ${Saldo a ser deduzido proporcionalmente ao histórico} - controlecota.saldodisponivel
                  
                  /* insert into controlecotamovimento ... values
                  {
                  	idprofissional: identificador da entidade do campo "Profissional"
                  	idproduto: identificador da entidade do campo "Produto"
                  	quantidade: -${Saldo a ser deduzido proporcionalmente ao histórico}
                  	observação: "Movimento criado e processado manualmente pela aplicação",
                  	sglorigem: 'WEB'
                  	idnativo: 1
                  	idnprocessado: 1
                  	data: current_date
                  	datamovimento:current_date
                  }
                  */
                  
                  /*
                  update controlecota set saldodisponivel = saldodisponivel + ${controlecotamovimento.quantidade}
                  */ -- Caso o saldo disponível não seja suficiente para ser deduzido, o campo saldodisponivel deve obrigatoriamente resultar em 0
                  • Visto que o processo pode levar um tempo considerável, é importante existir um feedback visual, como barra de progresso, ou no mínino um GIF de carregando com a mensagem: "Por favor, aguarde. Esse processo pode levar alguns minutos"

03.05 Função de alterar controles

Contexto / Gatilho:

Lógica:

  • O sistema deve abrir modal referenciando-se com o protótipo a seguir:

  • A modal deve conter os seguintes elementos visuais:
  • "Alteração de controles de cota": título da modal
  • Campo radio button, com duas opções:
      • "Adicionar controles"
      • "Inativar controles"
    • Ao trocar a opção, a seleção do campo de Modelos de controle deverá ser limpa.
  • Separador horizontal
  • "Selectione os registros de controles que deseja ${"Adicionar / Inativar" dependendo da opção do radio button selecionada}": Texto fixo
  • Modelos de controle: Combobox com os modelos podendo ser consultados através da consulta a seguir

    select valor from cotaconfiguracao where sglconfiguracao = "modelo"


      • Se o resultado for 'usuario', exibir opção "Profissional"
      • Se o resultado for 'produto', exibir opção "Produto"
      • Se o resultado for 'filial', exibir opção "Filial"
    • Ao lado do campo combobox, deve haver botão "Selecione" que, quando clicado, abre modal de seleção múltipla para a entidade selecionada em questão
      • Caso o campo de modelo seja selecionado como "Filial"
        • Caso o campo radio button selecionado for "Adicionar controles", devem ser somente filiais ativas que não pertencem à cota de contexto.

          select idlocal from local where idnativo = 1 and idlocal not in (select idlocalfilial from controlecota where idcota = ?) 
        • Caso o campo radio button selecionado for "Inativar controles", devem ser listados somente filiais ativas que pertencem à cota de contexto

          select idlocalfilial from controlecota where idcota = ?
      • Caso o campo de modelo seja selecionado como "Profissional"
        • Caso o campo radio button selecionado for "Adicionar controles", devem ser somente profissionais ativos que não pertencem à cota de contexto.

          select idusuario from usuario where idnativo = 1 and idusuario not in (select idusuario from controlecota where idcota = ?) 
        • Caso o campo radio button selecionado for "Inativar controles", devem ser listados somente profissionais ativos que pertencem à cota de contexto

          select idusuario from controlecota where idcota = ?
      • Caso o campo de modelo seja selecionado como "Filial"
        • Caso o campo radio button selecionado for "Adicionar controles", devem ser somente produtos ativos que não pertencem à cota de contexto.

          select idproduto from produto where idnativo = 1 and idproduto not in (select idproduto from controlecota where idcota = ?) 
        • Caso o campo radio button selecionado for "Inativar controles", devem ser listados somente produtos ativos que pertencem à cota de contexto

          select idproduto from controlecota where idcota = ?
      • Quando confirmadas as seleções da modal, o sistema deverá exibir texto `${contagem de registros selecionados} registros selecionados` ao lado do botão "Selecionar"
        • Caso nenhum registro estiver selecionado, exibir "Nenhum registro selecionado"
  • Botões de ação
    • "Cancelar": Fecha a modal, quando clicado
    • "Confirmar": Quando clicado, 
      • Caso o campo radio button selecionado for "Adicionar controles"
        • O sistema deverá realizar a persistência dos controles de cota selecionados, da seguinte forma:

          • Realizar cruzamento entre os registros do modelo a ser adicionado, com os registros de outros modelos ativos presentes na cota

          • Adicionar novas linhas de controle para os novos registros selecionados.
            /*
            Exemplo de adição de controles de cota, selecionando 5 novos usuários
            O sistema deverá adicionar registro de todos os produtos para estes 5 novos profissionais
            
            CONSULTA_A
            select idusuario,idproduto, NULL AS IDLOCALFILIAL from ${lista_usuarios_selecionados}
            cross join produto p
            where p.idproduto in (select idproduto from controlecota where idcota = ? and idnativo = 1)
            
            insert into controlecota (idnativo,saldodisponivel,saldoinicio,idcota,idusuario,idproduto,idlocalfilial)
            values (
            	select 1,0,0,:identificador_cota_contexto, CONSULTA_A.idusuario, CONSULTA_A.idproduto, CONSULTA_A.idlocalfilial from CONSULTA_A
            )
            
            */
      • Caso o campo radio button selecionado for "Inativar controles"
        • O sistema deverá realizar a atualização dos controles de cota selecionados, da seguinte forma:

          • Realizar cruzamento entre os registros do modelo a ser adicionado, com os registros de outros modelos ativos presentes na cota

          • Atualizar para inativo as linhas de controle para os registros de modelo selecionado.

            /*
            Exemplo de inativação de controles de cota, selecionando 5 produtos
            O sistema deverá atualizar todos os registros para estes 5 produtos
            
            update controlecota set idnativo = 0 where idproduto in (:lista_produtos_selecionados)
            
            */
      • Visto que o processo pode levar um tempo considerável, é importante existir um feedback visual, como barra de progresso, ou no mínino um GIF de carregando com a mensagem: "Por favor, aguarde. Esse processo pode levar alguns minutos"

03.05 Função de transferência de saldo de cota

Contexto / Gatilho:

  • No ambiente Web, na tela de controles de cota, ao clicar sobre o botão "Transferir saldo"

Lógica:

  • O sistema deve abrir modal referenciando-se com o protótipo a seguir:

  • A modal deve conter os seguintes elementos visuais:
  • "Transferência de saldo de cota": título da modal
  • "${Modelo 1} - ${Modelo 2} - ${Modelo 3}": Descrição dos modelos da cota original, concatenados.
  • "Saldo disponível para transferência: ${controlecota.saldodisponivel}": Texto fixo, buscando campo de saldo disponível relacionado à cota original
  • "Saldo a transferir": campo de input numérico editável
  • Linha horizontal
  • "Distribuição de saldo": Campos iguais ao agrupamento Distribuição de saldo
  • "Filtro de controles de cota de destino": Campos iguais ao agrupamento Filtro de controles de cota de destino
  • Botões de ação: Elementos iguais à seção de Botões de ação da função de alterar saldo
    • Para a lógica do botão Confirmar, o sistema deve executar a seguinte ação:
      • Verificar se o valor do campo Saldo a transferir não supera o valor disponível a ser transferido. Caso superar, o sistema deverá realizar rollback + mensagem: "Não há saldo disponível de ${Saldo a transferir} na conta de origem. O saldo disponível é ${controlecota.saldodisponivel}" 
      • Criar um débito de saldo na conta de origem, aproveitando a lógica de débito descrita na função de alterar saldo, cujo valor debitado é ${saldo a transferir}
      • Criar uma adição de saldo de cota nas contas filtradas de destino, aproveitando a lógica de adição descrita na função de alterar saldo, respeitando o modelo de distribuição selecionado, cujo valor é ${saldo a transferir}
  • Sem rótulos