Ir para o conteúdo
KAMOUniverse

Changelog

O que há de novo.

Cada melhoria para a plataforma, como ele envia.

  1. · kamo-internal

    Adicionar a página Políticas e parar de oferecer chats que a infra- estrutura recusa

    Quatro pontos de vista sobre um projecto de regulamento, porque existem quatro questões diferentes e nenhum layout responde a todos. Regras é o que cada regra faz, Matrix é como a organização se parece, Simulator é o que acontece com dois nomeados pessoas, Atividade é o que a política está fazendo para todos os outros. Uma regra é uma sentença, não um formulário. Um administrador a reunir o significado de seis dropdowns rotulados irão interpretar mal a sua própria política; uma leitura "Vendas podem não conversar com todos em um departamento diferente" não vai. Cada editável frase é um chip, e as funções frase ao vivo em app/lib para que possam ser unit-tested -- o vocabulário cruza esse limite como dados em vez de como um Tradutor, já que o vitest os executa no ambiente de nó. As duas extremidades de uma regra de sentido único são ditas separadamente de propósito. "Vendas podem começar bate-papo com a Engenharia, que só pode responder enquanto essa janela permanece aberta" descreve o que o motor faz; qualquer frase simétrica simples descreveria uma regra que não existe. Ordenar é o que custa o primeiro jogo, então o conselho paga-lo: o impacto do rascunho é verificado continuamente contra o que é realmente vivo, sombreado e regras duplicadas são nomeadas sob a regra que afetam, e publicando mostras Quantos pares bloqueia antes do botão. Novas regras e cada modelo chegam em modo de auditoria, onde gravam o que teriam bloqueado e bloqueado Nada. A lista é anotada, não filtrada. Um membro bloqueado mantém seu nome, foto e presença, e seu botão de bate-papo se explica em vez de desaparecer. Também cria /api/members/directório, que o seletor de membros adicionais do ChatBox tem foi buscar desde que foi escrito -- a rota nunca existiu, então o pedido O 404'd e o diálogo renderizaram uma lista vazia com nada relatando um problema.

  2. · InitializerService

    Criar o esquema da política de chat

    Seis quadros: o conjunto de regras versionadas, as suas regras e as suas cláusulas, a resposta subsídios por trás de "resposta somente enquanto sua janela está aberta", e o rastro do que A política recusou-se. Cada declaração é escrita para ser completa e idempotente, porque este corredor é aplicado à mão tantas vezes quanto é executado. Empurrar este acordo não dá em nada... não há nenhum CI e nenhuma carga de trabalho -- enquanto MediaService e SecurityService ambos execute ddl-auto:none, então nada cria essas tabelas em sua inicialização também. Se a DDL não desembarcou primeiro, esses serviços implantar de forma limpa e depois jogar sobre todas as regras lidas. A DDL para esta mudança foi aplicada a Yugabyte antes de ambos os serviços empurra, e verificado rodando as próprias duas consultas de instantâneo do motor contra ele em vez do que verificando o catálogo. O teste que o acompanha compara as entidades com essas afirmações por reflexão. Dentro do inicializador Hibernate cria as tabelas das entidades antes qualquer corredor executa, então uma coluna faltando aqui é invisível deste lado e fatal no outro.

  3. · SecurityService

    Anotar a lista de membros com o seu veredicto de política de chat

    SecurityService serve o roster o chat UI é construído de, por isso tem que resposta com os mesmos vereditos MediaService obriga com -- um compartilhado avaliador, ou o produto oferece conversas o backend então se recusa e lê como um bate-papo quebrado em vez de como uma política. A lista é anotada, nunca filtrada. Um membro que os blocos de políticas mantêm nome, foto e presença e perde apenas o preço do chat, que então carrega A própria explicação da organização. Escondê-los teria sido menos trabalho e Teria feito a lista mentir sobre quem trabalha aqui. Vereditos para toda a lista resolvem em um passe um instantâneo em cache. Perguntar por membro teria colocado uma avaliação -- e em um cache frio, uma consulta -- dentro de um laço que já funciona uma vez por colega. Uma política lida que falha deixa cada linha sem anotação em vez de falhar na lista: o caminho de envio é ainda a autoridade, de modo que o custo é um affordance confuso, não um política.

  4. · MediaService

    Forçar a política de chat org, e fechar dois buracos em que se sentou

    Aplica a política nos três locais onde uma conversação pode começar ou continuar: criação de sessão, adição de membro e o caminho de envio. Um quarto não é um par de polícias. par -- o portão de convite é o portão de mensagem direta, então você pode trazer alguém em uma sala exatamente quando você poderia tê-los enviado mensagem, e um quarto que encolhe de volta para dois membros bloqueados é re-ler como uma mensagem direta. Dois buracos pré-existentes estavam diretamente sob este trabalho e são fixados com ele. O endpoint de envio nunca verificou se o remetente pertencia à sessão, por isso qualquer membro autenticado poderia postar em qualquer guid de sessão que pudesse adivinhar -- a O portão da política teria sido decorativo sem ele. E os indicadores de digitação foram publicado para um /topic/chat/tipagem que cada cliente conectado no organização subscrito; scoping-los por sessão pára o vazamento e pára um par separado de sinalização um para o outro. Responder concede resposta "responda somente enquanto sua janela estiver aberta": o navegador reporta o que ele pode ver e o servidor decide, com uma graça que sobrevive a uma falta bater e não um laptop fechado. Sua transmissão é por membro e vigiado, desde Uma subvenção forjada abriria a um compositor a política bloqueada. O administrador write é seu próprio feijão e sua própria transação. No YugabyteDB uma leitura Depois de uma gravação numa transacção, aumenta 4001 e aborta tudo ao seu redor, e um @Transactional auto-invocado não é um limite -- então o save reads antes, escreve, e lê novamente apenas uma vez que tenha cometido.

  5. · kamo-shared-library

    Adicionar o motor de política de chat org

    Decide se um membro pode abrir uma conversa com outro, e se Eles podem enviar para um que existe. Regras são uma lista ordenada sobre encomendas Os pares e a primeira partida decidem, por isso todos os nomes do veredicto são exactamente uma regra. que é o que permite que as configurações UI se expliquem em vez de perguntar administrador para confiar nele. A regra de orientação é a parte de carga. Uma regra escrita SUJEITO -> TARGET é avaliado de ambos os lados: para frente o ator é o lado a partir do qual é escrito, Inverta o lado sobre o qual está escrito. Sem isso, "Vendas podem mensagem Engenharia unidirecional" combinaria quando um vendedor atua e cair para o que quer que se sente abaixo quando um engenheiro faz -- não fazendo nada no único direcção que existe para restringir. Ausência nunca é um acordo. Uma cláusula de departamento, título ou gestor não pode corresponder um simples Membro, e curtos-circuitos de inaplicabilidade antes da negação, por isso "não em Vendas" não varre cada assinante que não tem nenhum departamento. O avaliador não detém nenhum repositório e não abre nenhuma sessão: duas consultas por-org instantâneo, e cada veredito depois disso é definido aritmética. Resolver uma cadeia de gerente através do JPA teria sido uma consulta por link por membro em profundidade ilimitada, em um caminho que corre sempre que um cache fica frio.

  6. · kamo-internal

    Reordenar as abas e pintar Binders e Uploads

    A tira lê Originais □ Modificado □ Common □ Binders as três visões dos documentos em conjunto e os dois destinos após eles. Ligantes e Envios agora carregam essa leitura visualmente: marrom e azul fundos com rótulos e ícones brancos. O `&&&' em Tab pintado é suporte de carga. O pai Tabs estilos seus filhos através de `& .MuiTab-root`, um seletor descendente que supera uma simples per-tab sx, então um único `&` perde a cascata e o rótulo permanece cinza no novo Antecedentes.

  7. · kamo-internal

    Dizer quando não foi possível adicionar um documento seleccionado

    O ficheiro Docs seleccionado ignora um documento que não pode manter legalmente em vez de falhando em toda a sincronização, o que é certo — mas ele fez isso silenciosamente, então um fichário tendo menos documentos do que o membro verificado lido como sendo o recurso quebrado, e o único lugar que a razão existiu foi o registro DocsService.

  8. · kamo-internal

    Dobre a aba Modificar em Binders

    A tira é agora Originals . Ligadores . Modificado . Common . Modificar é ido: tudo o que ele fez — organizar os documentos verificados, visualizá-los, mesclar eles em um PDF ou um ZIP — o organizador já fez melhor, e ele fez isso para uma lista que possas manter. O que os conecta é uma entrada de "Docs selecionados" no topo da pasta lista. Ele detém o que é verificado na grade e é reescrito em cada mudança de seleção, assim que um membro verifica documentos em Originals, abre Binders, e encontra-os em ordem. Não pode ser renomeado, excluído ou compartilhado; o botão que o salva, "Salvar como Binder", é o mesmo duplicado do editor já tinha, re-labelled — em qualquer outro aglutinante ele lê "Duplicate This Binder", e ambos fazem um novo fichário do próprio membro segurando tudo o Abra uma porta. Baixando agora oferece ZIP ao lado do PDF fundido, que é a última coisa que a aba Modify poderia fazer que um fichário não poderia. Gotas Modificadas PublishedWithChanges for Difference, dois documentos side by lado, e a barra de ferramentas está morta "Preparar e Baixar" botão agora abre o fichário o seu rótulo estava sempre a descrever.

  9. · DocsService

    Sirva e sincronize o arquivo Docs Selected

    POST /api/docs/binders/scratch obtém o arquivo Docs Selecionado do chamador para uma coleção, criando-o no primeiro uso, e substitui seus documentos por seleção da grade na mesma viagem de ida e volta — o organizador chama isso em cada mudança de seleção, e duas chamadas por caixa de seleção é a diferença entre Atalho que se mantém com a grade e um que visivelmente defasa. A sincronização mantém cada documento ainda selecionado na posição do membro e anexa os novos; separadores e páginas geradas são nunca tocou, porque eles são adições do próprio membro em vez de um reflexo da rede. Um documento que não pode aderir legalmente ao ficheiro é pulou em vez de falhar toda a sincronização — uma seleção de grade não é curado, Assim, uma má fileira não deve impedir os outros vinte de chegar. A ordenação regras são uma função pura para que possam ser testadas sem um banco de dados. Renomear, excluir, compartilhar e promover modelo são recusados para ele, e as regras para o que pode tornar-se um item DOC agora viver em um ajudante assim adicionando à mão e A sincronização não pode separar-se daquilo que aceitam.

  10. · InitializerService

    Adicionar aglutinantes.is scratch

    Quatro declarações em vez de um ALTER: os fichários são povoados, e Yugabyte rejeita toda a declaração ADD COLUNN ... NÃO NULL em vez da cláusula, por isso a coluna chega nula, é recheada, ganha seu DEFAULT, e só então está apertado. @Order(0) pela convenção coluna-add — a entidade de compartilhamento-lib agora maps is scratch, assim qualquer corredor que carrega um Binder antes deste morrer uma coluna que ainda não existe.

  11. · kamo-shared-library

    Marque o gerenciador de Docs Selecionados automaticamente do membro

    binders.is scratch sinaliza o único binder por (proprietário, coleção) cujo documentos são a seleção de grade DocManager em vez de uma lista com curadoria. Está. um aglutinante ordinário em todos os outros aspectos, então a consulta de lista tem que excluí-lo à mão: o organizador pins-lo acima da lista, e deixá-lo em iria colocá-lo ali duas vezes e — pior — oferecem-no em cada "adicionar ao fichário". A pesquisa devolve uma lista em vez de uma Opcional porque duas páginas abrem o organizador em conjunto pode perder e ambos inserir; o chamador leva o mais antigo.

  12. · kamo-internal

    Reúna o disco principal em vez de segurá-lo atrás de um girador

    O estado de carga da aba Detalhes era uma carta de quatorze linhas de pulso MUI cinzentas — uma forma que o painel nunca assume, num relógio por elemento, substituído por uma layout que não se parece nada. E esperou em 'loading.insights': um registro que já tinha chegado sentado atrás de placeholders até uma comunicação não relacionada A contagem voltou. O painel agora mostra seu próprio layout enquanto espera — quatro peças de estatísticas, o callbacks strip, duas linhas de três cartas, na largura real — sob uma faixa de luz de marca cruzando a página em uma diagonal, e as cartas reais mão fora de seus fantasmas na mesma ordem, assim que o registro resolve ao longo do caminho o A luz viajou. Somente os portões de registro o painel; as contagens e a lista de tarefas resolver dentro de seus próprios azulejos, e os painéis do mercado estender a entrada ordem quando a sua configuração aterrar. O masthead junta- se à mesma sequência: um fantasma em forma de nome em vez da palavra "Carregamento", e um trilho de três segmentos na sua borda inferior — registo, actividade, configuração — onde um segmento preenche branco no momento em que o seu buscar terras. Real Chegadas, não um cronómetro. Está absolutamente posicionada para que a aba sublinhada permaneça flush com o conteúdo que rotula. Um esqueleto que nunca resolve é o pior estado final que um projeto de carregamento tem, então um registro falhou agora dá lugar ao que aconteceu e uma repetição que executa o abrindo buscas, nas abas Detalhes e Hipoteca ambos. A coreografia 'kmail-*' em globals.css torna-se a família 'kload-*' da casa — as mesmas regras, o mesmo contrato de movimento reduzido, mais `kload-settle' para a transferência e os segmentos do carril. /mensagens, /notas e /rede mover-se sobre inalterado. Sem novas chaves I18n.

  13. · SecurityService

    Pergunte ao EmailService para preencher o e-mail passado de um lead

    Implementa o LeadEmailBackfillTrigger da biblioteca compartilhada, então marcando "Associar E-mails passados w/ Lead" em um lead save atinge o único serviço que pode ler caixas de correio. Dois perigos tratados aqui em vez de em LeadService. Espera pelo compromisso: o back-fill corresponde ao ponto de contacto que o salvamento ainda está a escrever, e disparado em linha que seria executado contra uma linha nenhuma outra conexão pode ver ainda, encontrar nada, e relatar o sucesso. E nunca faz o membro esperar: mesmo aceitando o trabalho é um salto para outro serviço que pode estar para baixo, por isso sai em um thread de fundo com curtos intervalos de tempo. O pior resultado disponível para o member é um lead que foi salvo normalmente.

  14. · EmailService

    Analise as caixas de correio da org por e-mail passado de uma pista a pedido

    Serve a caixa de seleção "Associar e-mails passados w/ Lead". Dada uma pista e o endereço apenas gravado nele, ler INBOX e enviado de cada caixa de correio em que A organização do lead volta um ano e anexa qualquer coisa que carregue o endereço. Cada guarda o caminho automático ainda se aplica, porque ambos os caminhos agora compartilhar uma classificação (): uma org cujos endereços não podem ser classificados é recusado, um thread puramente interno é recusado, e um endereço da empresa nunca é compatível candidato — assinale assim a caixa numa linha cujo e-mail é noreply@<org-domínio> ainda não associa nada em vez de entregar que levar todo o correio da empresa Fluxo. Além disso, o endereço do próprio líder tem de estar no Mensagem. Executa o tópico de requisição e mono-threaded: toda uma organização caixas de correio levam muito mais tempo para ler do que um lead save pode bloquear, eo correio servidor permite apenas um punhado de conexões por usuário para o pod inteiro, então A concorrência aqui passaria fome na varredura ao vivo em vez de ir mais rápido. A endpoint responde 202 "queued", nunca "encontrar algo" — o membro observa o A aba de e-mails preenche. Selecção de pastas move- se para o MailboxFolderScope para que a varredura e o preenchimento posterior não pode derivar sobre onde o e- mail vive; uma linha do tempo cujo conteúdo dependia da qual caminho encontrado uma mensagem primeiro seria pior do que qualquer um deles.

  15. · kamo-shared-library

    Deixe um e-mail de reivindicação de lead que antecede seu endereço de e-mail

    Correspondência é ponto-em-tempo por projeto — um ponto de contato apenas reivindica tráfego dentro de sua janela, para editar um lead não pode retroativamente reescrever o histórico. A o custo é que um lead inserido após o início da conversa nunca pode mostrar que conversa, e o membro não tem como dizer "este endereço já era deles". A história é assim. Alarga exactamente uma coisa, a janela, e nada. outro: o endereço ainda deve ser um ponto de contato desse lead exato, Exatamente org, em alguma janela. Não pode inventar um fósforo, cruzar um inquilino, ou alcançar um chumbo que nunca segurou o endereço — os testes fixar cada um desses, porque todos três falham silenciosamente, como o correio ligado ao chumbo errado lê como um chumbo que realmente escreveu-nos. LeadService ganha a costura que carrega a intenção do membro (um opcional LeadEmailBackfillTrigger, ausente em serviços sem acesso ao correio) e ambos pedir DTOs ganhar a bandeira. A bandeira não é deliberadamente persistida: descreve uma poupança, e cada pessoa que liga — importações, parâmetros de consumo, MeridianLink patches, o salvamento automático do varredor de bloqueio — não envia nada e assim não adquire nenhum exame de caixa de correio que nunca pediu.

  16. · kamo-internal

    Ofereça associar e-mail passado quando o endereço de um lead for definido

    O correio corresponde a uma ligação estritamente pontual: um endereço só reivindica tráfego a partir do momento em que é gravado, para que a edição de um lead hoje não pode Reescrever o correio da semana passada. Isso é certo para o caminho automático e errado para o caso um membro realmente bate — entrando em uma pista que eles já têm foi e- mailing, em seguida, encontrar a aba E- mails vazio e o tópico aparentemente Perdido. Assim ambos os lugares o próprio endereço de um lead pode ser definido — o painel de contato em /leades/view/{id} e o formulário de nova liderança — agora mostram um "Associate Past" desmarcado E-Mails w/ Lead" caixa ao lado dele. Assinalar pede ao servidor para ir à procura; deixar isso em paz não muda nada. A caixa só aparece uma vez que um endereço tenha sido digitado, e nunca se lembra de ser marcado: descreve um salvo, não o chumbo, por isso não é persistido e o construtor lista branca omite-lo inteiramente quando falso em vez de enviar um falso o auto-salvar do varredor de bloqueio iria repetir como um Escolha.

  17. · kamo-internal

    Um escolhidor de agentes para atribuição, reservas e o filtro

    O controle do Agente Atribuído no painel de atribuição de uma pista era um componente local em LeadViewClient. Dois outros lugares queriam exatamente isso, então ele se move para * * **********************e faz o diálogo de escolha com ele. O painel de atribuição é inalterado em aparência e comportamento — simplesmente não possui mais O código. Oportunidade de reserva — um membro que detém EDIT OPPORTUNIDADES, o direito de porta gestão de oportunidades em /leades/oportunidades/reservado, agora recebe um agente de vendas campo que nomeia para quem é a reserva. Abre-se em si mesmos, por isso, arquivar o seu o próprio pedido não custa nada extra. Ao contrário do agente designado pelo líder, não pode ser esvaziado: uma reserva é uma reivindicação de alguém, e um de propriedade não é um estado o O recorde aguenta. Esse é o conjunto de `clearable={false}` — nenhum botão claro em o campo, e não remover no coletor. O filtro /leades Agent foi um Select alimentado por uma busca de toda a equipe diretório, que é de onde suas opções vieram e por que ele só poderia oferecer uma página de uma org que pode correr para cinco figuras de pessoas. Ele se move para o mesmo escolhedor, que pesquisa uma página de cada vez, para que o filtro possa agora chegar a cada nome — e a busca por todo o diretório, seu cache de módulo e seu filtro ativo se foram com ele, a mesma limpeza que o painel de tarefas já fez. As respostas úteis do filtro incluem três que não são pessoas, então MemberPickerDialog cresce `quickOptions`: linhas fixadas acima dos resultados, aqui Primeiro eu mesmo, depois o All Leads, depois o Undesigned Leads para um membro que pode ver. Aqueles. Eu mesmo conduz porque é a resposta desejada mais frequentemente e o um pesquisa de diretórios torna mais difícil de alcançar — caso contrário, você digita seu próprio nome e Escolhe o teu nome. O *************Sentinels mover-se para chumboGridQuery ao lado o mapeamento que os lê. Eram literais de cordas em ambos os lugares, e um drift entre os dois não deixaria de compilar: a consulta trataria não reconhecido sentinela como um membro id, filtro em um membro ninguém é, e mostrar um grade vazia - que lê como "você não tem leads" em vez de como um bug. A sessão carrega um ID de membro e um e- mail, mas nenhum nome de exibição, de modo a semear o forma de reserva com "você" resolve uma vez através da pesquisa de diretório. A correspondência está no ID do membro, nunca no email que produziu a página: uma caixa de correio partilhada retorna várias pessoas, e tomar o primeiro iria arquivar uma oportunidade para Um colega que nunca o pediu. Também deixa getAgentFilterMemberId, que não tinha ID do membro de 19 dígitos.

  18. · SecurityService

    Aceitar uma reserva levantada para outro agente

    Agora, honras em "BehalfOfMemberId", o direito que impõe a gestão das oportunidades no lista reservada, e já o direito necessário para mover uma oportunidade entre agentes depois do facto. CREATE OPPORTUNIDADES sozinho ainda apenas arquivos seus próprios. Um ouvinte sem ele que nomeia um agente é REFUSADO em vez de ter o campo Largado. Gravar silenciosamente a reserva com o seu próprio nome atribuiria uma reivindicação para alguém que nunca fez isso, e mostraria ao gerente um pedido que Acho que pediram outra pessoa. O agente nomeado é validado contra a comissãoElegibleMemberIds — o mesmo VIEW LEADS pool applyPrimaryAgent usa e o mesmo pool que o catador oferece. Estacionar uma reserva em alguém que não pode abrir o chumbo que reserva é Impraticáveis para eles. O ator do corredor da história permanece a pessoa que agiu; o bilhete diz para quem era. E porque PEDIDO SUBMITED vai para aprovadores, o agente que foi arquivado é Acrescentado explicitamente — não são aprovadores, caso contrário, o primeiro ouvir uma reivindicação em seu nome é a sua aprovação ou negação. Requer a migração do KamoInitializerService adicionando CREATED BY MEMBER ID para ter correr primeiro, ou a primeira leitura de qualquer lançamento reserva.

  19. · InitializerService

    - Não

    Registos que fizeram uma reserva quando não é esse o nome do agente. gestão de oportunidades pode levantar um em nome de um agente de vendas sem o registro ter que alegar que o agente o fez. Nulable with no backfill, for the reason PRIMARY AGENT MEMBER ID não levou nenhum: null significa "o solicitante arquivou ele mesmo", cada linha anterior a esta coluna genuinamente foi auto-filed, e copiar o solicitante em iria inventar um fato e colocar uma linha "Arquivado por" na história que ninguém fez. Nenhum índice — nada filtra ou classifica nele, de modo que se custaria cada escrita e compra Não há leitura. Isto deve ser implementado e executado ANTES da alteração do SecurityService que mapeia o coluna: serviços executam ddl-auto:none, e Hibernate nomes cada coluna mapeada em seu SELECT, para que o serviço começasse saudável e depois jogar na primeira leitura de qualquer reserva.

  20. · kamo-shared-library

    Deixe um gerente levantar uma reserva para um agente

    Alguém que gere oportunidades pode agora apresentar um pedido de reserva sobre uma venda Em nome do agente. CreateReservationRequest continuaBehalfOfMemberId para ele. O agente nomeado torna-se PEDIDO BY MEMBER ID, não a pessoa que o arquivou. Todas as regras a jusante são chaves dessa coluna — quem pode pedir uma extensão, quem a comissão segue, o que o filtro Agent da lista reservada corresponde - assim o A alegação tem que se sentar onde essas regras olham, e é verdadeiramente a reivindicação do agente. Quem sentou no teclado vai em um novo CREATED BY MEMBER ID em vez de ser dobrado na mesma coluna, então nenhum fato tem que ser inferido da outra. Nulable, e null mantém seu próprio significado: o solicitante arquivou-o eles mesmos. PRIMARY AGENT MEMBER ID é deliberadamente deixado nulo neste caminho. Significa "um Aprovador retirou isso do agente que pediu", e a lista reservada renderiza um âmbar "Reatribuído de" linha para ele — mas um pedido apresentado para um agente nunca foi se afastou de qualquer um, então `reatribuído' permanece falso e `onBelfof' diz o verdadeiro coisa em vez disso.

  21. · kamo-internal

    Ocultar os controles de equilíbrio que free- for-all não pode usar

    O saldo de crédito, a colocação diária e o saldo máximo actuam num saldo concedido, e um produto FFA não tem nenhum — a aceitação ali menta e gasta seu próprio crédito. Deixando-os editáveis convidou um gerente para definir números que nunca poderiam vincular. Eles agora renderizam como um chip mudo com uma dica dizendo isso. Passivo máximo diário editável e é a verdadeira alavanca sobre um produto FFA: a infra-estrutura agora conta um Aceitação de FFA como um gasto, então a tampa também se aplica lá.

  22. · kamo-shared-library

    Fazer livre-para-toda aceitação gastável, para que possa ser tampado

    A FFA ignorou o sistema de crédito totalmente, o que deixou um gerente sem alavanca sobre Ele: Max Daily Spend sentou-se atrás se (!ffa) e não poderia tampar um produto FFA, e "aceitado hoje" não tinha filas para contar, porque nada foi gasto. Uma aceitação FFA agora menta um crédito e gasta-o na liderança no mesmo bloco como a reivindicação, assim o registro de gastos sempre existe e nunca pode derivar do atribuição. Max Daily Spend sai da filial somente de crédito e se aplica ambas as vias — significa que não foi concedido ao membro um saldo a pagar de, não que um gerente não pode amarrar quantos eles tomam em um dia. Deliberadamente ainda somente crédito: o interruptor de crédito org-wide e a verificação de saldo. A FFA não tem equilíbrio a menos. A tampa é verificada após esses, então um crédito membro que está quebrado e capped continua relatando INSUFICIENT CREDITS. Nota AceitarResult.creditSpent é agora verdadeiro no caminho FFA (foi documentado como Sempre falso). É exato — um crédito realmente é consumido — e atinge o Aceitar resposta e publicar Carga útil NATS atribuída. Atribuição de Chumbo Tipo ainda registra AUTO ASSIGN para FFA, então a história mantém os dois separados.

  23. · kamo-internal

    Nomeie o solicitante, mova a linha org, encurtar o botão Abrir org

    Três ajustes nas superfícies de suporte. "Open org as System User" é agora "Open Org", sentado imediatamente após a atribuição/reatribuição em vez de no final da linha — pertence à mesma pergunta que as respostas: é a outra coisa que você faz quando um bilhete cai em sua mesa e a resposta está dentro do inquilino do cliente. A dica ainda indica que a aba abre como Usuário do Sistema, que o rótulo curto deixa cair. Mantém o seu peso; é uma porta para dentro de outra pessoa negócio e não deve ler como um irmão do dropdown prioridade. A organização sai do cabeçalho do ticket e para a esquerda do "+ Novo ticket" linha, que deixa o cabeçalho para o próprio ticket. Com várias abas abrindo a barra de abas carrega o controle do novo bilhete em vez disso, de modo que a linha renderiza para a organização sozinho — cada aba pode ser um cliente diferente, e é exatamente quando vale a pena dizer. A o próprio título da janela agora lê "{person} - {org}", construído em um lugar porque o visitante- renomear caminho empurra um título também e uma segunda expressão é como o org silenciosamente cai no momento em que um visitante anônimo dá o seu nome. Chats → As linhas de suporte são intituladas após a pessoa que pediu, sempre. Abrir um ticket junta-se ao seu bate-papo, de modo que um ocupado acumula agentes, e titling do outro participantes renomearam a linha cada vez que um colega olhou para ele — o mesmo A conversa aparece como uma pessoa diferente. O nome do solicitante agora concorda com O rosto já está na fila.

  24. · kamo-internal

    Diga em qual relógio a janela do evento está ligada e mostre a hora inicial

    Quatro coisas que o compositor errou, no calendário e na página principal. A zona era do navegador. Isso é um fato sobre o laptop, não sobre o membro: alguém cujo perfil diz Eastern e que está trabalhando de Denver ainda livrou seu dia no Oriente, e o diálogo semeou "3pm Mountain" com Nada no ecrã para o revelar. Novos eventos agora compõem no próprio membro zona de perfil, resolvida através do fuso horário/eficaz do SecurityService — que Existe desde agosto e não tem nenhum próximo caminho na frente dele, então cada chamada O 404 entrou na Next e voltou para a UTC. A zona é nomeada no valor, sob o seletor, e ao lado da data no cabeçalho, no deslocamento realmente em vigor na data do evento em vez da de hoje. Os campos de início e fim sentaram-se lado a lado com uma seta entre eles e não etiquetas, duas caixas sem aviso prévio que partilham a largura do cartão — nessa largura uma entrada local-datetime tem menos espaço do que o seu próprio conteúdo precisa, por isso a leitura Foi cortado. Com o cartão "Iniciar tempo" e as únicas palavras visíveis sendo o Hoje / Amanhã / Todos os botões ao lado dele, nada na tela disse um início O tempo estava lá para ser ajustado. Eles são empilhados largura completa agora, cada um nomeado, e o cartão é dirigido "Quando". Um novo evento começou no topo da hora atual, que está no passado para cinquenta e nove minutos de cada sessenta; o retorno da página principal acrescentou uma hora e manteve os minutos ímpares, oferecendo 4:37 pm. Ambos agora usam o padrãoEventStart — Uma hora fora, arredondada para o quarto de hora. O calendário padrão era qualquer que fosse o serviço listado primeiro, e o serviço lista primeiro o calendário partilhado da organização de propósito, porque ordem de leitura direita na barra lateral onde é um filtro. Aqui o primeiro item é também o padrão, então um novo evento foi publicado org-wide a menos que o membro notaram e optaram por uma decisão que nunca tomaram. Primária do próprio membro O calendário leva agora, e o compartilhado carrega um crachá "org-wide". O compositor principal de callback já não semeia a zona do líder silenciosamente; oferece como um interruptor de uma tap ao lado do próprio membro. Seu contexto de compositor é memorizado, que é suporte de carga em vez de arrumado — construído em linha era um novo objeto cada renderização, assim calendários que chegam da rede mid-tipping redefinir o diálogo e descartado o que o membro havia inserido.

  25. · SecurityService

    Publicar a declaração Hibernate conta para Prometeu

    /actuator/prometheus já transportado jdbc * e hikaricp * mas sem hibernate *, porque Spring Boot 3 só auto-configura essas métricas quando Está na pista de aula. Adicionado, mais hibernate.generate statistics. A razão é concreta. A auditoria deste serviço para consultas N+1 teve que ser feita por grapping para navegação de associação, e esse método está errado em ambos directions: over-counts, porque um nome de associação como 'vendor' ou 'usuário' é preguiçoso em algumas entidades e ansioso por outras (9 de 67 sites relatados para ser ansioso e não precisava de nada), e ele sub-conta mal, porque vê .getX().getY() mas não iteração sobre uma coleção preguiçosa — que é a maioria Superfície real. hibernate statements total responde à mesma pergunta por medida. Um ponto final a emissão de 200 declarações por chamada é visível, independentemente da forma que o código assuma, e Estar em visão aberta significa que cada uma dessas cargas preguiçosas é silenciosa. Custa alguns por cento. Vale a pena num serviço onde a última auditoria encontrou quatro Endpoints O( linhas) separados.

  26. · kamo-internal

    Mostrar a foto do solicitante em cada linha de chat de suporte

    Cada linha em Chats → Suporte usava o mesmo glifo de suporte azul, que não ajuda em tudo quando a lista é o que você verifica para decidir o que pegar. O rosto agora é o pessoa que perguntou. O glifo sobrevive para exatamente um caso, e é um fato do servidor em vez do que um palpite: um visitante web-chat anônimo não tem registro de membro, então o ticket Nomeia o membro do sistema de org — o proprietário — como seu requerente. Mostrando essa foto colocaria a pessoa errada na conversa, e no marketing da própria plataforma widget seria o rosto de quem está lendo a lista. O diretório org do visualizador ainda é consultado primeiro, porque é a cópia ao vivo — um membro que mudou sua foto um momento atrás já está lá — e o URL do servidor é o backback que cobre solicitantes em outras organizações, que Esse diretório nunca ouviu falar. As iniciais deliberadamente NÃO caem para trás para o título da linha: em uma linha de suporte o título é a contrapartida, então um requestor o servidor não poderia nome seria dado as iniciais do agente de apoio, no avatar que existe para dizer quem está perguntando. Com nem um nome nem uma foto não há pessoa para desenhar, e o glifo é honesto.

  27. · MediaService

    Coloque o rosto e o nome do solicitante em cada linha de chat de suporte

    Uma linha de Chats → Suporte mostrou o mesmo glifo de suporte em cada linha, então uma fila de Eram uma parede de círculos azuis idênticos. O rosto que as pessoas realmente procuram é Quem quer que tenha pedido, então a linha agora carrega o id do solicitante, o nome da exibição e a foto. A foto é resolvida aqui em vez de deixada para o cliente, que é o todo dificuldade: todos os outros avatar neste feed são recheados do próprio visualizador diretório de organização, e um solicitante de suporte é — na mesa da plataforma — sempre membro de outra pessoa, de modo que o diretório retorna nada para exatamente as linhas é para. Duas leituras em lote cobrem uma página, no mesmo espírito que o visitante pré-fetch Ao lado deles. A linha avatar é re-ler por id em vez de ser retirada member.getAvatar(): Avatar é uma hierarquia unida e a associação é preguiçosa, por isso o que retorna é uma proxy do tipo BASE. instânciade AvatarFoto é falso através dele mesmo depois inicialização, e cada foto carregada seria procurada no vetor do Criador Avatar caminho. Carregar por id dá a subclasse de concreto e sua extensão de arquivo. requestorIsAmbiguous é o caso pelo qual o glifo sobrevive, e é um caso específico em vez de uma hedge: um visitante anônimo de web-chat não tem registro de membro, então o O nome do membro do SISTEMA da org — o proprietário — como seu solicitante. Sua foto colocaria a pessoa errada na conversa, e no marketing da própria plataforma widget seria o rosto de quem está lendo a lista.

  28. · kamo-internal

    Contagem de grupo no cabeçalho do produto, aceito hoje por membro

    Leads Disponível foi renderizado em cada linha de membros de um grupo de produtos, mas é um propriedade do agrupamento (produto, mercado) — o mesmo número repetido no coluna para tantos membros como manter regras. Ele se move para o cabeçalho do grupo, uma vez, Onde pertence. A coluna liberada agora mostra o que estava faltando: quantos leads cada membro aceitou até hoje, renderizado como "3 / 10" contra o seu Max A sala de cabeceira restante é legível de relance. A contagem vem de /management, que resolve "hoje" da mesma forma que o cap faz — o próprio fuso horário do membro.

  29. · kamo-shared-library

    Resolver o URL de foto de um membro da biblioteca partilhada

    A lista de Chats → Suporte está prestes a mostrar o rosto do solicitante, e um suporte solicitante é — na própria mesa da plataforma — sempre membro de outra pessoa. Cada outro avatar nesse feed é recheado sobre o cliente a partir da org do VEÍCULO diretório, que nunca ouviu falar deles, então este tem que ser resolvido do lado do servidor por MediaService. Isso significa que um segundo serviço nomeando um objeto avatar, e o caminho do objeto é exatamente a coisa que não deve existir duas vezes: costumava ser prefixada com qualquer máquina pedido chegou em, então uma foto carregado no domínio de uma org 404'd quando lido de outro, degradante para iniciais e parecendo "sem foto" em vez de como um bug. Então o AvatarObjectPaths move-se para aqui e a cópia do SecurityService torna-se uma delegação Alias, não detém nenhum fio próprio. O MemberAvatarUrls adiciona o resto da resolução: membro-superar antes do usuário padrão, foto vs Avatar Criador decidido pelo DISCRIMINADOR antes de instância — um preguiçoso o avatar carregado é um proxy do tipo base, então o instanceof enviaria todos os enviados foto para o caminho do vetor — e domínio do tema host →. Uma máquina que não é um domínio não produz nenhum URL em vez de um palpite: nenhuma imagem se degrada para iniciais, uma imagem quebrada não. Também adiciona PEQUESTOR ID às duas projeções de chat-feed de suporte.

  30. · SecurityService

    Devolver a contagem de cada membro aceite por produto

    Gerenciar-Credits mostra Max Daily Spend mas nada sobre o quanto dele é usado, para que um gerente não pudesse dizer se um membro era um lead de seu cap ou tinha não começou. /manage now retorna aceitaToday keyed memberId::vendorProductId. "Hoje" is resolvido exatamente como CreditLeadAssignmentService resolve-lo ao executar o limite máximo — fuso horário do próprio MEMBRO, início do dia até agora, contando o mesmo LeadCredit.dateLinhas passadas — então a figura é literalmente o número do cap Testei contra uma segunda opinião sobre o que é um dia. Uma consulta agrupada por membro, não uma por membro x produto. Nota Produtos FFA relatório 0: aceitação não gasta nenhum crédito, e o limite faz não se aplica a eles também (todo o bloco de crédito está atrás se (!ffa)), por isso o duas colunas permanecem consistentes.

Seu universo está esperando.

Comece gratuitamente em minutos.Adicione produtos sempre que estiver pronto — sem migração, sem novos logins.

Gratuito para sempre — não é necessário cartão de crédito