import { v } from 'convex/values'; import { mutation, query, internalQuery } from './_generated/server'; import { encryptSMTPPassword } from './auth/utils'; import { registrarAtividade } from './logsAtividades'; /** * Obter configuração de busca de código de barras ativa (credenciais mascaradas) */ export const obterConfigBuscaCodigoBarras = query({ args: {}, handler: async (ctx) => { const config = await ctx.db .query('configuracaoBuscaCodigoBarras') .withIndex('by_ativo', (q) => q.eq('ativo', true)) .first(); if (!config) { return null; } // Retornar config com credenciais mascaradas return { _id: config._id, // GS1 Brasil gs1BrasilClientId: config.gs1BrasilClientId || '', gs1BrasilClientSecret: '********', // Mascarar gs1BrasilTokenUrl: config.gs1BrasilTokenUrl || '', gs1BrasilApiUrl: config.gs1BrasilApiUrl || '', gs1BrasilAtivo: config.gs1BrasilAtivo, // Bluesoft Cosmo bluesoftApiKey: '********', // Mascarar bluesoftApiUrl: config.bluesoftApiUrl || '', bluesoftAtivo: config.bluesoftAtivo, // Product-Search.net productSearchApiKey: '********', // Mascarar productSearchApiUrl: config.productSearchApiUrl || '', productSearchAtivo: config.productSearchAtivo, ativo: config.ativo, atualizadoEm: config.atualizadoEm }; } }); /** * Salvar configuração de busca de código de barras */ export const salvarConfigBuscaCodigoBarras = mutation({ args: { // GS1 Brasil gs1BrasilClientId: v.optional(v.string()), gs1BrasilClientSecret: v.optional(v.string()), gs1BrasilTokenUrl: v.optional(v.string()), gs1BrasilApiUrl: v.optional(v.string()), gs1BrasilAtivo: v.boolean(), // Bluesoft Cosmo bluesoftApiKey: v.optional(v.string()), bluesoftApiUrl: v.optional(v.string()), bluesoftAtivo: v.boolean(), // Product-Search.net productSearchApiKey: v.optional(v.string()), productSearchApiUrl: v.optional(v.string()), productSearchAtivo: v.boolean(), configuradoPorId: v.id('usuarios') }, returns: v.union( v.object({ sucesso: v.literal(true), configId: v.id('configuracaoBuscaCodigoBarras') }), v.object({ sucesso: v.literal(false), erro: v.string() }) ), handler: async (ctx, args) => { // Buscar config ativa anterior para manter credenciais se não fornecidas const configAtiva = await ctx.db .query('configuracaoBuscaCodigoBarras') .withIndex('by_ativo', (q) => q.eq('ativo', true)) .first(); // Determinar credenciais: usar novas se fornecidas, senão manter as atuais let gs1BrasilClientSecret: string | undefined; if (args.gs1BrasilClientSecret && args.gs1BrasilClientSecret.trim().length > 0) { // Nova credencial fornecida, criptografar gs1BrasilClientSecret = await encryptSMTPPassword(args.gs1BrasilClientSecret); } else if (configAtiva?.gs1BrasilClientSecret) { // Credencial não fornecida, manter a atual gs1BrasilClientSecret = configAtiva.gs1BrasilClientSecret; } let bluesoftApiKey: string | undefined; if (args.bluesoftApiKey && args.bluesoftApiKey.trim().length > 0) { bluesoftApiKey = await encryptSMTPPassword(args.bluesoftApiKey); } else if (configAtiva?.bluesoftApiKey) { bluesoftApiKey = configAtiva.bluesoftApiKey; } let productSearchApiKey: string | undefined; if (args.productSearchApiKey && args.productSearchApiKey.trim().length > 0) { productSearchApiKey = await encryptSMTPPassword(args.productSearchApiKey); } else if (configAtiva?.productSearchApiKey) { productSearchApiKey = configAtiva.productSearchApiKey; } // Desativar config anterior const configsAntigas = await ctx.db .query('configuracaoBuscaCodigoBarras') .withIndex('by_ativo', (q) => q.eq('ativo', true)) .collect(); for (const config of configsAntigas) { await ctx.db.patch(config._id, { ativo: false }); } // Criar nova config const configId = await ctx.db.insert('configuracaoBuscaCodigoBarras', { gs1BrasilClientId: args.gs1BrasilClientId || undefined, gs1BrasilClientSecret, gs1BrasilTokenUrl: args.gs1BrasilTokenUrl || undefined, gs1BrasilApiUrl: args.gs1BrasilApiUrl || undefined, gs1BrasilAtivo: args.gs1BrasilAtivo, bluesoftApiKey, bluesoftApiUrl: args.bluesoftApiUrl || undefined, bluesoftAtivo: args.bluesoftAtivo, productSearchApiKey, productSearchApiUrl: args.productSearchApiUrl || undefined, productSearchAtivo: args.productSearchAtivo, ativo: true, configuradoPor: args.configuradoPorId, atualizadoEm: Date.now() }); // Log de atividade await registrarAtividade( ctx, args.configuradoPorId, 'configurar', 'buscaCodigoBarras', JSON.stringify({ gs1BrasilAtivo: args.gs1BrasilAtivo, bluesoftAtivo: args.bluesoftAtivo, productSearchAtivo: args.productSearchAtivo }), configId ); return { sucesso: true as const, configId }; } }); /** * Obter configuração de busca de código de barras (internal query) * Usado pela action de busca para obter credenciais descriptografadas */ export const obterConfigBuscaCodigoBarrasInternal = internalQuery({ args: {}, handler: async (ctx) => { const config = await ctx.db .query('configuracaoBuscaCodigoBarras') .withIndex('by_ativo', (q) => q.eq('ativo', true)) .first(); if (!config) { return null; } // Retornar config completa (para uso interno) return config; } });