A proposta desse estudo é visualizar uma maneira em que a retaguarda envie arquivos de dados ao Sync Server, que serão processados pelo Sync Client no PDV. Isso não substitui a API, mas complementa o fluxo para situações em que seja mais eficiente carregar os dados dessa maneira.

Desafios gerados para esse estudo foram:

SOLUÇÃO PROPOSTA - SUBIDA DE ARQUIVO JSON CRIPTOGRAFADO BI FORMATO AES-256 CONTENDO TODOS OS DADOS PARA BAIXA

Na solução proposta foi desenhado o seguinte escopo:

Para esse fluxo, foi considerado o envio do arquivo pelo Bucked Cloud. No teste realizado, foi utilizado o bucket do GCP (biblioteca Google.Cloud.Storage).

Para o uso do bucket de arquivos do GCP, deve ser considerado as seguintes observações:

PRINCIPAIS RECURSOS:

✅Armazenamento escalável para grandes volumes de dados
Alto desempenho para leitura e escrita de arquivos
Suporte a múltiplos tipos de armazenamento (Standard, Nearline, Coldline e Archive)
Integração com serviços Google (BigQuery, AI, Kubernetes, etc.)
Segurança com criptografia automática e permissões IAM
Versionamento e backup de arquivos

TIPOS DE STORAGE E CASOS DE USO:

Tipo de ArmazenamentoCusto ($/GB/mês)RecuperaçãoUso Ideal
Standard$$$ (Alto)RápidoDados acessados frequentemente
Nearline$$ (Médio)Leve atrasoBackups, arquivamento de médio prazo
Coldline$ (Baixo)DemoradoDados raramente acessados (1x por ano)
Archive$ (Muito Baixo)Muito lentoArquivamento de longo prazo

 Exemplo de Preços (EUA, Março/2024):

Para o nosso caso, o tipo de armazenamento standard é o mais recomendado, visto que precisamos de um processo que a subida de arquivo seja feita de forma rápida e que o mesmo seja acessado frequentemente (subindo o arquivo uma vez e baixando o arquivo apenas uma vez na máquina local para o recebimento dos dados via arquivo).

Vantagens do Google Cloud Storage

Escalabilidade → Suporta petabytes de dados sem limitação de tamanho.
Segurança Avançada → Dados criptografados e integração com IAM.
Baixa Latência → Alta performance para leitura e escrita de arquivos.
Multi-Regional → Armazene dados em várias regiões para redundância.
Integração com BigQuery, AI e Kubernetes.

Desvantagens do Google Cloud Storage

Custo pode ser alto para grandes volumes de dados em classes Standard.
Cobrança por requisições e downloads → Cada leitura/escrita pode gerar custos extras.
Necessidade de autenticação → Exige configuração de chaves e permissões via IAM.
Recuperação lenta em Coldline/Archive → Pode levar horas para acessar arquivos arquivados.

POC - Testando a subida e download de um arquivo

No teste foi criado duas APIs simulando a subida e download de um arquivo via bucket cloud do GCP. 

No GCP foi criado um bucket onde fosse possível armazenar os arquivos subidos através da API.



Para a criação do bucket foi necessário colocar permissão de envio/baixa de arquivo para o usuário utilizado no micro serviço de Controle que faz o acesso ao diretório através da aplicação.

Após a criação do bucket, foi criado as APIs POST para envio do arquivo e a API GET para a baixa do arquivo.

API POST - Carga Loja - Envio:


API GET - Baixa do Arquivo:


MÉTODO PARA ENVIO DE ARQUIVOS CRIPTOGRAFADOS USANDO O MODELO AES-256

Para a solução proposta, é necessário que o arquivo enviado esteja criptografado. Para isso, iremos utilizar o modelo AES, já utilizado dentro do PDV SYNC, na criptografia de senhas do banco de dados dos serviços do client. 

Para isso, podemos utilizar o modelo abaixo para criptografia do arquivo, uma vez que o arquivo enviado já tem que estar devidamente criptografado.

using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;

class AESFileEncryption
{
    static void Main()
    {
        string filePath = "C:\\Temp\\arquivo.txt"; // Arquivo original
        string encryptedFilePath = "C:\\Temp\\arquivo_encrypted.aes"; // Arquivo criptografado
        string decryptedFilePath = "C:\\Temp\\arquivo_decrypted.txt"; // Arquivo descriptografado

        // Gerar chave e IV AES-256
        byte[] key = GenerateRandomKey(32); // 256 bits
        byte[] iv = GenerateRandomKey(16);  // 128 bits

        Console.WriteLine($"🔑 Chave AES-256: {Convert.ToBase64String(key)}");
        Console.WriteLine($"🌀 IV: {Convert.ToBase64String(iv)}");

        // Criptografar arquivo
        EncryptFile(filePath, encryptedFilePath, key, iv);
        Console.WriteLine("✅ Arquivo criptografado com sucesso!");

        // Descriptografar arquivo
        DecryptFile(encryptedFilePath, decryptedFilePath, key, iv);
        Console.WriteLine("✅ Arquivo descriptografado com sucesso!");
    }

    // Método para gerar chave e IV aleatórios
    static byte[] GenerateRandomKey(int size)
    {
        using (var rng = new RNGCryptoServiceProvider())
        {
            byte[] key = new byte[size];
            rng.GetBytes(key);
            return key;
        }
    }

    // Método para descriptografar um arquivo
    public static void DecryptFile(string inputFile, string outputFile, byte[] key, byte[] iv)
    {
        using (Aes aes = Aes.Create())
        {
            aes.Key = key;
            aes.IV = iv;
            aes.Mode = CipherMode.CBC;
            aes.Padding = PaddingMode.PKCS7;

            using (FileStream fsInput = new FileStream(inputFile, FileMode.Open))
            using (CryptoStream cryptoStream = new CryptoStream(fsInput, aes.CreateDecryptor(), CryptoStreamMode.Read))
            using (FileStream fsOutput = new FileStream(outputFile, FileMode.Create))
            {
                cryptoStream.CopyTo(fsOutput);
            }
        }
    }
}

BAIXA DE ARQUIVOS NO CLIENT

Para a baixa de arquivo de carga, o modelo ideal para a proposta seria a seguinte:

CONSIDERAÇÕES FINAIS + SEPARAÇÃO DE ISSUES PARA CADA TAREFA

O solução proposta unindo todos esses pontos é eficiente, rápido e eficaz, uma vez que o processo de leitura/gravação de dados por arquivo já está implementado no client, com a baixa de dados via Function, e com o modelo de dados proposto para o envio do arquivo para o server, vai gerar mais fluidez para o processo de carga inicial de uma loja. Dito isso, as issues de história que devemos considerar para que esse modelo acima seja seguido são:

  1. Criação da API POST para envio do Arquivo, inclusão da validação do arquivo criptografado + criação da tabela no Controle para a manutenção do envio desses arquivos, incluído campos para status de processamento e logs de mensagens
  2. Processamento de Arquivo no PDV SYNC SERVER Controle
  3. Criação da API GET para a baixa do arquivo no Client
  4. Criação da API PUT para a confirmação da baixa do arquivo e envio de logs referentes ao seu processamento 
  5. Alteração do serviço client Down para a baixa do arquivo enviado no server, leitura do arquivo criptografado, separação dos registros por tipo de dados e acionamento da baixa de dados via function


EXEMPLO DO ARQUIVO COM CONTEÚDO DOS DADOS

[	
	{
		"CodigoTipo": "12",
		"TipoDado": "AssociacaoProdutoClassificacao",
		"Dados": [
			{
				"ProdutoIdRetaguarda": "PRD1000010",
				"ClassificacaoProdutoIdRetaguarda": "APCP1000010",
				"Ordem": 1,
				"Situacao": 1,
				"IdRetaguarda": "APC1000010",
				"Id": 0,
				"DataCadastro": "0001-01-01T00:00:00",
				"DataAtualizacao": "0001-01-01T00:00:00"
			}
		]
	},
	{
		"CodigoTipo": "11",
		"TipoDado": "ClassificacaoProduto",
		"Dados": [
			{
				"Descricao": "MALHAS",
				"Nome": "MALHAS E TECIDOS",
				"Sigla": "MT",
				"ClassificacaoProdutoPaiIdRetaguarda": "",
				"Situacao": 1,
				"IdRetaguarda": "CP01",
				"Id": 0,
				"DataCadastro": "2025-04-01T20:41:40.2134Z",
				"DataAtualizacao": "2025-04-01T20:41:40.213426Z"
			}
		]
	},
	{
		"CodigoTipo": "0",
		"TipoDado": "Cliente",
		"Dados": [
			{
				"Nome": "Carolina Dias Herrera",
				"Endereco": "",
				"Numero": "",
				"Complemento": "",
				"Bairro": "IPANEMA",
				"Cidade": "Rio de Janeiro",
				"Estado": "",
				"Cep": "1350065005",
				"Telefone": "",
				"Celular": "21955058770",
				"Email": "[email protected]",
				"DataNascimento": "1987-01-15T16:58:17.727-02:00",
				"PessoaFisica": 0,
				"CpfCnpj": "22665113007",
				"RgInscricao": "418509307",
				"Sexo": 0,
				"EstadoCivil": 0,
				"AvatarUrl": "",
				"Enviarpnet": 0,
				"Atividade": "",
				"Cracha": "",
				"IdRetaguardaProfissional": null,
				"IdRetaguardaRamoAtividade": null,
				"IdRetaguardaRedeCliente": null,
				"IdRetaguardaClientePrincipal": null,
				"IdRetaguardaPraca": null,
				"IdRetaguardaRegiao": null,
				"UtilizaPrecoAtacado": false,
				"Situacao": 1,
				"IdRetaguarda": "CLI101003",
				"Id": 0,
				"DataCadastro": "2025-04-01T20:33:26.808123Z",
				"DataAtualizacao": "2025-04-01T20:33:26.808154Z"
			}
		]
	},
	{
		"CodigoTipo": "56",
		"TipoDado": "ClienteEndereco",
		"Dados": [
			{
				"Bairro": "PARAISO",
				"Cep": "16500251",
				"Cidade": "ARAÇATUBA",
				"ClienteIdRetaguarda": "CLI101001",
				"Complemento": "",
				"Endereco": "AVENIDA MARCÍLIO DIAS",
				"Estado": "SP",
				"IdCliente": 6082,
				"Numero": "3270",
				"DescricaoTipo": "RESIDENCIAL",
				"EnviarPnet": 0,
				"Situacao": 1,
				"IdRetaguarda": "CLIEND1001002",
				"Id": 0,
				"DataCadastro": "2025-04-01T21:07:45.77272Z",
				"DataAtualizacao": "2025-04-01T21:07:45.77272Z"
			}
		]
	},
	{
		"CodigoTipo": "12",
		"TipoDado": "CodigoProduto",
		"Dados": [
			{
				"ProdutoIdRetagurada": "PRD1000010",
				"Codigo": "10011004",
				"CodigoExterno": null,
				"Descricao": "PRODUTO TESTE - AUTENTICADOR",
				"Situacao": 0,
				"IdRetaguarda": "CPPRD1000010",
				"Id": 0,
				"DataCadastro": "2024-03-28T13:13:11.127Z",
				"DataAtualizacao": "2024-03-28T13:13:11.127Z"
			}
		]
	},
	{
		"CodigoTipo": "16",
		"TipoDado": "DadoComplementarPagto",
		"Dados": [
			{
				"Descricao": "TESTE",
				"Tipo": 0,
				"Obrigatorio": 10,
				"Tamanho": 10,
				"TipoCampoTef": null,
				"Situacao": 1,
				"IdRetaguarda": "DCP00001",
				"Id": 0,
				"DataCadastro": "2025-04-01T20:52:48.188076Z",
				"DataAtualizacao": "2025-04-01T20:52:48.188077Z"
			}
		]
	},
	{
		"CodigoTipo": "14",
		"TipoDado" : "Estoque",
		"Dados": [
			{
				"Saldo": 50.0,
				"Sincronizado": 1,
				"ProdutoIdRetaguarda": "7891132001453-55",
				"ProdutoLote": null,
				"Situacao": 1,
				"IdRetaguarda": "EST00026",
				"Id": 0,
				"DataCadastro": "2025-04-01T20:43:54.873766Z",
				"DataAtualizacao": "2025-04-01T20:43:54.873766Z"
			}
		]
	},
	{
		"CodigoTipo": "18",
		"TipoDado": "FormaPagto",
		"Dados": [
			{
				"Descricao": "CREDITO",
				"DescricaoFiscal": "CREDITO",
				"CodigoImpressora": null,
				"PagamentoValorTotal": null,
				"PermiteTroco": 1,
				"FormaPagamentoTrocoIdRetaguarda": "",
				"ValorMinimoAceito": "5",
				"CodigoSistemaExterno": "10",
				"CodigoModalidadePagamento": 0,
				"Tipo": 1,
				"IdPagamentoFormaMestre": null,
				"TipoCliente": 1,
				"ClienteConsumidor": null,
				"UtilizaLimiteCredito": false,
				"Situacao": 1,
				"IdRetaguarda": "FP0010",
				"Id": 0,
				"DataCadastro": "2025-04-01T20:48:32.417083Z",
				"DataAtualizacao": "2025-04-01T20:48:32.417084Z"
			}
		]
	},
	{
		"CodigoTipo": "21",
		"TipoDado": "Grupo",
		"Dados": [
			{
				"IdRetaguardaLoja": "9999",
				"IdRetaguardaCliente": "3168",
				"IdRetaguardaGrupo": "GP0004",
				"Situacao": 1,
				"IdRetaguarda": "GP0004",
				"Id": 0,
				"DataCadastro": "0001-01-01T00:00:00",
				"DataAtualizacao": "0001-01-01T00:00:00"
			}
		]
	},
	{
		"CodigoTipo": "7",
		"TipoDado": "Imposto",
		"Dados": [
			{
				"AliquotaTributo": "5",
				"Tipo": "1",
				"Modalidade": "Teste",
				"IndiceTributoImpressora": null,
				"ReducaoBaseCalculo": "0",
				"Simbolo": "TESTE",
				"Cfop": "10",
				"CstCsosn": "10",
				"Situacao": 0,
				"IdRetaguarda": "IMP00011",
				"Id": 0,
				"DataCadastro": "2025-04-01T20:35:15.025273Z",
				"DataAtualizacao": "2025-04-01T20:35:15.025313Z"
			}
		]
	},
	{
		"CodigoTipo": "2",
		"TipoDado": "Motivo",
		"Dados": [
			{
				"Descricao": "Motivo Teste 3",
				"Tipo": 1,
				"IdPromocaoMotorPromocaoTerceiro": null,
				"TipoMecanica": null,
				"Situacao": 1,
				"IdRetaguarda": "10",
				"Id": 0,
				"DataCadastro": "2025-04-01T20:34:12.844775Z",
				"DataAtualizacao": "2025-04-01T20:34:12.844803Z"
			}
		]
	},
	{
		"CodigoTipo": "8",
		"TipoDado": "Ncm",
		"Dados": [
			{
				"CodigoNcm": "12345678",
				"CodigoExcecao": "20",
				"AliquotaNacional": "3.0",
				"AliquotaImportada": "2.0",
				"AliquotaEstadual": "1.0",
				"AliquotaMunicipal": "1.0",
				"Chave": "TESTE",
				"Fonte": "ARIAL 12",
				"CodigoCest": "1234567",
				"Situacao": 1,
				"IdRetaguarda": "NCM00002",
				"Id": 0,
				"DataCadastro": "2025-04-01T20:35:35.746964Z",
				"DataAtualizacao": "2025-04-01T20:35:35.746964Z"
			}
		]
	},
	{
		"CodigoTipo": "15",
		"TipoDado": "Operadora",
		"Dados": [
			{
				"Descricao": "ELO",
				"CodigoTef": "10",
				"Administradora": "ELO",
				"TipoTransacao": 1,
				"Situacao": 1,
				"IdRetaguarda": "OP100010",
				"Id": 0,
				"DataCadastro": "2025-04-01T20:47:46.432391Z",
				"DataAtualizacao": "2025-04-01T20:47:46.432418Z"
			}
		]
	},
	{
		"CodigoTipo": "3",
		"TipoDado": "Perfil",
		"Dados": [
			{
				"Nome": "Supervisor Geral",
				"TipoPerfil": 1,
				"DescontoMaximoItem": 100.0,
				"DescontoMaximoTotal": 100.0,
				"Situacao": 1,
				"IdRetaguarda": "18",
				"Id": 0,
				"DataCadastro": "2025-04-01T20:34:29.842174Z",
				"DataAtualizacao": "2025-04-01T20:34:29.842175Z"
			}
		]
	},
	{
		"CodigoTipo": "9",
		"TipoDado": "PisCofins",
		"Dados": [
			{
				"CstPis": "1",
				"AliquotaPis": "8.0",
				"CstCofins": "1",
				"AliquotaCofins": "5.0",
				"Situacao": 1,
				"IdRetaguarda": "PC00010",
				"Id": 0,
				"DataCadastro": "2025-04-01T20:41:02.264344Z",
				"DataAtualizacao": "2025-04-01T20:41:02.264345Z"
			}
		]
	},
	{
		"CodigoTipo": "13",
		"TipoDado": "Preco",
		"Dados": [
			{
				"ProdutoIdRetaguarda": "PRD00003",
				"ProdutoEmbalagemIdRetaguarda": "PRDEMB0001",
				"DataVigenciaInicial": "2024-10-28T16:26:14.977-03:00",
				"DataVigenciaFinal": "2025-03-28T16:26:14.977-03:00",
				"Valor": "20.0",
				"SincronizadoEtiquetaEletronica": 0,
				"PrecoPromocional": "5.0",
				"Custo": 1.0,
				"RegiaoIdRetaguarda": "",
				"Margem": 0.0,
				"PrecoOrigem": "",
				"PrecoPrincipal": true,
				"ValorAtacado": 17.0,
				"IndicePreco": "",
				"Situacao": 1,
				"IdRetaguarda": "PRE00001010",
				"Id": 0,
				"DataCadastro": "2025-04-01T20:43:03.804015Z",
				"DataAtualizacao": "2025-04-01T20:43:03.80404Z"
			}
		]
	},
	{
		"CodigoTipo": "12",
		"TipoDado": "Produto",
		"Dados": [
			{
				"Descricao": "PRODUTO TESTE - AUTENTICADOR",
				"ImpostoIdRetaguarda": null,
				"Imposto": null,
				"NcmIdRetaguarda": null,
				"UnidadeMedida": "UN",
				"DescontoMaximo": "3",
				"TipoArredondaTrunca": "0",
				"CodigoProduto": "10011004",
				"CodigoAlternativo": "1001100405958579",
				"OrigemProduto": "0",
				"PisCofinsIdRetaguarda": null,
				"Imagem": "",
				"TipoProduto": 0,
				"Fracionado": true,
				"CnpjFornecedor": "05054526000178",
				"EscalaRelevante": true,
				"ValorBaseFcp": "0",
				"CodigoBeneficioFiscal": "",
				"PercentualFcp": "0",
				"CstIcms": null,
				"PercentualReducaoIcms": "1",
				"AliquotaIcms": "1",
				"VlIcmsRet": "0",
				"MotivoDesoneracaoIcms": 0,
				"DescontaDesoneracaoNf": false,
				"Cest": "10",
				"ValorPautaIcms": null,
				"Encomenda": false,
				"PesoBruto": 315.0,
				"PesoLiquido": 300.0,
				"QuantidadeMovimentacao": 100.0,
				"IdRetaguardaProdutoPrincipal": null,
				"QuantidadeValorAtacado": 10.0,
				"IdRetaguardaCategoria": null,
				"IdRetaguardaDepartamento": null,
				"IdRetaguardaFornecedor": null,
				"IdRetaguardaMarca": null,
				"IdRetaguardaSecao": null,
				"IdRetaguardaSubCategoria": null,
				"ControlaLote": false,
				"Situacao": 1,
				"IdRetaguarda": "PRD1000010",
				"Id": 0,
				"DataCadastro": "2025-04-01T20:42:05.523853Z",
				"DataAtualizacao": "2025-04-01T20:42:05.523853Z"
			}
		]
	},
	{
		"CodigoTipo": "12",
		"TipoDado": "ProdutoEmbalagem",
		"Dados": [
			{
				"CodigoBarras": "8314961742676478",
				"Descricao": "PRODUTO TESTE - AUTENTICADOR",
				"PesoBruto": 1.0,
				"PesoLiquido": 1.0,
				"Quantidade": 1.0,
				"UnidadeMedida": "UN",
				"QuantidadeValorAtacado": 0.0,
				"Situacao": 1,
				"IdRetaguarda": "PE010101010",
				"Id": 0,
				"DataCadastro": "2025-04-01T20:42:05.523853Z",
				"DataAtualizacao": "2025-04-01T20:42:05.523853Z"
			}
		]
	},
	{
		"CodigoTipo": "58",
		"TipoDado": "RamoAtividade",
		"Dados": [
				{
					"Descricao": "SERVICOS EM MANUTENCAO DE EQUIPAMENTOS",
					"IdRetaguardaAtividadePrincipal": null,
					"PercentualTaxa": 8.5,
					"Situacao": 1,
					"IdRetaguarda": "RA00001",
					"Id": 0,
					"DataCadastro": "2025-04-01T21:08:15.71412Z",
					"DataAtualizacao": "2025-04-01T21:08:15.714148Z"
				}
			]
	},
	{
		"CodigoTipo": "4",
		"TipoDado": "Usuario",
		"Dados": [
			{
				"PerfilIdRetaguarda": "12",
				"Nome": "Marilsa Cardoso Damato",
				"Cpf": "86683259062",
				"Login": "marilsa.damato",
				"Senha": "WXYZ",
				"SenhaCriptografada": "",
				"Administrador": 0,
				"Matricula": "150006",
				"Situacao": 1,
				"IdRetaguarda": "102",
				"Id": 0,
				"DataCadastro": "2025-04-01T20:34:42.938532Z",
				"DataAtualizacao": "2025-04-01T20:34:42.938532Z"
			}
		]
	}
]