diff --git a/README.md b/README.md index c1d63ae..8311559 100644 --- a/README.md +++ b/README.md @@ -83,7 +83,7 @@ As entidades atualmente permitidas para interação são: - [x] Notificações (`.notificacoes`) - [x] Pedidos - Compras (`.pedidosCompras`) - [x] Pedidos - Vendas (`.pedidosVendas`) -- [ ] Produtos (`.produtos`) +- [x] Produtos (`.produtos`) - [x] Produtos - Estruturas (`.produtosEstruturas`) - [x] Produtos - Fornecedores (`.produtosFornecedores`) - [x] Produtos - Lojas (`.produtosLojas`) @@ -94,8 +94,6 @@ As entidades atualmente permitidas para interação são: - [x] Usuários (`.usuarios`) - [x] Vendedores (`.vendedores`) -Adicionaremos as restantes de acordo com as _releases_. - ## Exemplo de uso Para listar seus produtos, basta executar: diff --git a/src/bling.spec.ts b/src/bling.spec.ts index 6fa7611..856e380 100644 --- a/src/bling.spec.ts +++ b/src/bling.spec.ts @@ -29,6 +29,7 @@ import { Nfses } from './entities/nfses' import { Notificacoes } from './entities/notificacoes' import { PedidosCompras } from './entities/pedidosCompras' import { PedidosVendas } from './entities/pedidosVendas' +import { Produtos } from './entities/produtos' import { ProdutosEstruturas } from './entities/produtosEstruturas' import { ProdutosFornecedores } from './entities/produtosFornecedores' import { ProdutosLojas } from './entities/produtosLojas' @@ -186,6 +187,10 @@ describe('Bling main module', () => { ) }) + it('should retrieve produtos entity', () => { + expect(createBling(chance.word()).produtos).toBeInstanceOf(Produtos) + }) + it('should retrieve produtos - estruturas entity', () => { expect(createBling(chance.word()).produtosEstruturas).toBeInstanceOf( ProdutosEstruturas diff --git a/src/bling.ts b/src/bling.ts index c928374..6d85184 100644 --- a/src/bling.ts +++ b/src/bling.ts @@ -28,6 +28,7 @@ import { Nfses } from './entities/nfses' import { Notificacoes } from './entities/notificacoes' import { PedidosCompras } from './entities/pedidosCompras' import { PedidosVendas } from './entities/pedidosVendas' +import { Produtos } from './entities/produtos' import { ProdutosEstruturas } from './entities/produtosEstruturas' import { ProdutosFornecedores } from './entities/produtosFornecedores' import { ProdutosLojas } from './entities/produtosLojas' @@ -322,6 +323,15 @@ export default class Bling { return this.getModule(PedidosVendas) } + /** + * Obtém a instância de interação com produtos. + * + * @return {Produtos} + */ + public get produtos(): Produtos { + return this.getModule(Produtos) + } + /** * Obtém a instância de interação com produtos - estruturas. * diff --git a/src/entities/produtos/__tests__/change-situation-many-response.ts b/src/entities/produtos/__tests__/change-situation-many-response.ts new file mode 100644 index 0000000..4cab987 --- /dev/null +++ b/src/entities/produtos/__tests__/change-situation-many-response.ts @@ -0,0 +1,37 @@ +export default { + data: { + alertas: [ + { + id: 12345678, + error: { + type: 'VALIDATION_ERROR', + message: 'Não foi possível salvar a venda', + description: + 'A venda não pode ser salva, pois ocorreram problemas em sua validação.', + fields: [ + { + code: 49, + msg: 'Uma ou mais parcelas da venda possuem erros de validação', + element: 'parcelas', + namespace: 'VENDAS', + collection: [ + { + index: 1, + code: 12, + msg: 'Id da forma de pagamento inválido.', + element: 'formaPagamento', + namespace: 'VENDAS' + } + ] + } + ] + } + } + ] + } +} + +export const changeSituationManyRequest = { + idsProdutos: [12345678], + situacao: 'A' as const +} diff --git a/src/entities/produtos/__tests__/change-situation-response.ts b/src/entities/produtos/__tests__/change-situation-response.ts new file mode 100644 index 0000000..ff212c0 --- /dev/null +++ b/src/entities/produtos/__tests__/change-situation-response.ts @@ -0,0 +1,5 @@ +export default null + +export const changeSituationRequest = { + situacao: 'A' as const +} diff --git a/src/entities/produtos/__tests__/create-response.ts b/src/entities/produtos/__tests__/create-response.ts new file mode 100644 index 0000000..940b913 --- /dev/null +++ b/src/entities/produtos/__tests__/create-response.ts @@ -0,0 +1,253 @@ +export default { + data: { + id: 6423817751, + variations: { + deleted: [ + { + id: 6423817579, + variations: {}, + warnings: ['Mensagem de aviso.'] + } + ], + updated: [ + { + id: 6423817579, + variations: {}, + warnings: ['Mensagem de aviso.'] + } + ], + saved: [ + { + id: 6423817579, + variations: {}, + warnings: ['Mensagem de aviso.'] + } + ] + }, + warnings: ['Mensagem de aviso.'] + } +} + +export const createRequestBody = { + id: 123456789, + nome: 'Produto 1', + codigo: 'CODE_123', + preco: 1, + tipo: 'P' as const, + situacao: 'A' as const, + formato: 'S' as const, + descricaoCurta: 'Descrição curta', + dataValidade: '2020-01-01', + unidade: 'UN', + pesoLiquido: 1, + pesoBruto: 1, + volumes: 1, + itensPorCaixa: 1, + gtin: '1234567890123', + gtinEmbalagem: '1234567890123', + tipoProducao: 'P' as const, + condicao: 0 as const, + freteGratis: false, + marca: 'Marca', + descricaoComplementar: 'Descrição complementar', + linkExterno: 'https://www.google.com', + observacoes: 'Observações', + categoria: { + id: 123456789 + }, + estoque: { + minimo: 1, + maximo: 100, + crossdocking: 1, + localizacao: '14A' + }, + actionEstoque: 'Z' as const, + dimensoes: { + largura: 1, + altura: 1, + profundidade: 1, + unidadeMedida: 1 + }, + tributacao: { + origem: 0, + nFCI: '', + ncm: '', + cest: '', + codigoListaServicos: '', + spedTipoItem: '', + codigoItem: '', + percentualTributos: 0, + valorBaseStRetencao: 0, + valorStRetencao: 0, + valorICMSSubstituto: 0, + codigoExcecaoTipi: '', + classeEnquadramentoIpi: '', + valorIpiFixo: 0, + codigoSeloIpi: '', + valorPisFixo: 0, + valorCofinsFixo: 0, + codigoANP: '', + descricaoANP: '', + percentualGLP: 0, + percentualGasNacional: 0, + percentualGasImportado: 0, + valorPartida: 0, + tipoArmamento: 0 as const, + descricaoCompletaArmamento: '', + dadosAdicionais: '', + grupoProduto: { + id: 123456789 + } + }, + midia: { + video: { + url: 'https://www.youtube.com/watch?v=1' + }, + imagens: { + externas: [ + { + link: 'https://shutterstock.com/lalala123' + } + ] + } + }, + linhaProduto: { + id: 1 + }, + estrutura: { + tipoEstoque: 'F' as const, + lancamentoEstoque: 'A' as const, + componentes: [ + { + produto: { + id: 1 + }, + quantidade: 2.1 + } + ] + }, + camposCustomizados: [ + { + idCampoCustomizado: 123456789, + idVinculo: 123456789, + valor: '256GB', + item: 'Opção A' + } + ], + variacoes: [ + { + id: 123456789, + nome: 'Produto 1', + codigo: 'CODE_123', + preco: 1, + tipo: 'P' as const, + situacao: 'A' as const, + formato: 'S' as const, + descricaoCurta: 'Descrição curta', + dataValidade: '2020-01-01', + unidade: 'UN', + pesoLiquido: 1, + pesoBruto: 1, + volumes: 1, + itensPorCaixa: 1, + gtin: '1234567890123', + gtinEmbalagem: '1234567890123', + tipoProducao: 'P' as const, + condicao: 0 as const, + freteGratis: false, + marca: 'Marca', + descricaoComplementar: 'Descrição complementar', + linkExterno: 'https://www.google.com', + observacoes: 'Observações', + categoria: { + id: 123456789 + }, + estoque: { + minimo: 1, + maximo: 100, + crossdocking: 1, + localizacao: '14A' + }, + actionEstoque: 'Z' as const, + dimensoes: { + largura: 1, + altura: 1, + profundidade: 1, + unidadeMedida: 1 + }, + tributacao: { + origem: 0, + nFCI: '', + ncm: '', + cest: '', + codigoListaServicos: '', + spedTipoItem: '', + codigoItem: '', + percentualTributos: 0, + valorBaseStRetencao: 0, + valorStRetencao: 0, + valorICMSSubstituto: 0, + codigoExcecaoTipi: '', + classeEnquadramentoIpi: '', + valorIpiFixo: 0, + codigoSeloIpi: '', + valorPisFixo: 0, + valorCofinsFixo: 0, + codigoANP: '', + descricaoANP: '', + percentualGLP: 0, + percentualGasNacional: 0, + percentualGasImportado: 0, + valorPartida: 0, + tipoArmamento: 0 as const, + descricaoCompletaArmamento: '', + dadosAdicionais: '', + grupoProduto: { + id: 123456789 + } + }, + midia: { + video: { + url: 'https://www.youtube.com/watch?v=1' + }, + imagens: { + externas: [ + { + link: 'https://shutterstock.com/lalala123' + } + ] + } + }, + linhaProduto: { + id: 1 + }, + estrutura: { + tipoEstoque: 'F' as const, + lancamentoEstoque: 'A' as const, + componentes: [ + { + produto: { + id: 1 + }, + quantidade: 2.1 + } + ] + }, + camposCustomizados: [ + { + idCampoCustomizado: 123456789, + idVinculo: 123456789, + valor: '256GB', + item: 'Opção A' + } + ], + variacao: { + nome: 'Tamanho:G;Cor:Verde', + ordem: 1, + produtoPai: { + cloneInfo: true + } + } + } + ] +} diff --git a/src/entities/produtos/__tests__/delete-many-response.ts b/src/entities/produtos/__tests__/delete-many-response.ts new file mode 100644 index 0000000..10c276c --- /dev/null +++ b/src/entities/produtos/__tests__/delete-many-response.ts @@ -0,0 +1,32 @@ +export default { + data: { + alertas: [ + { + id: 12345678, + error: { + type: 'VALIDATION_ERROR', + message: 'Não foi possível salvar a venda', + description: + 'A venda não pode ser salva, pois ocorreram problemas em sua validação.', + fields: [ + { + code: 49, + msg: 'Uma ou mais parcelas da venda possuem erros de validação', + element: 'parcelas', + namespace: 'VENDAS', + collection: [ + { + index: 1, + code: 12, + msg: 'Id da forma de pagamento inválido.', + element: 'formaPagamento', + namespace: 'VENDAS' + } + ] + } + ] + } + } + ] + } +} diff --git a/src/entities/produtos/__tests__/delete-response.ts b/src/entities/produtos/__tests__/delete-response.ts new file mode 100644 index 0000000..7b85954 --- /dev/null +++ b/src/entities/produtos/__tests__/delete-response.ts @@ -0,0 +1 @@ +export default null diff --git a/src/entities/produtos/__tests__/find-response.ts b/src/entities/produtos/__tests__/find-response.ts new file mode 100644 index 0000000..36344bc --- /dev/null +++ b/src/entities/produtos/__tests__/find-response.ts @@ -0,0 +1,225 @@ +export default { + data: { + id: 123456789, + nome: 'Produto 1', + codigo: 'CODE_123', + preco: 1, + tipo: 'P' as const, + situacao: 'A' as const, + formato: 'S' as const, + descricaoCurta: 'Descrição curta', + dataValidade: '2020-01-01', + unidade: 'UN', + pesoLiquido: 1, + pesoBruto: 1, + volumes: 1, + itensPorCaixa: 1, + gtin: '1234567890123', + gtinEmbalagem: '1234567890123', + tipoProducao: 'P' as const, + condicao: 0 as const, + freteGratis: false, + marca: 'Marca', + descricaoComplementar: 'Descrição complementar', + linkExterno: 'https://www.google.com', + observacoes: 'Observações', + categoria: { + id: 123456789 + }, + estoque: { + minimo: 1, + maximo: 100, + crossdocking: 1, + localizacao: '14A' + }, + actionEstoque: 'Z' as const, + dimensoes: { + largura: 1, + altura: 1, + profundidade: 1, + unidadeMedida: 1 + }, + tributacao: { + origem: 0, + nFCI: '', + ncm: '', + cest: '', + codigoListaServicos: '', + spedTipoItem: '', + codigoItem: '', + percentualTributos: 0, + valorBaseStRetencao: 0, + valorStRetencao: 0, + valorICMSSubstituto: 0, + codigoExcecaoTipi: '', + classeEnquadramentoIpi: '', + valorIpiFixo: 0, + codigoSeloIpi: '', + valorPisFixo: 0, + valorCofinsFixo: 0, + codigoANP: '', + descricaoANP: '', + percentualGLP: 0, + percentualGasNacional: 0, + percentualGasImportado: 0, + valorPartida: 0, + tipoArmamento: 0 as const, + descricaoCompletaArmamento: '', + dadosAdicionais: '', + grupoProduto: { + id: 123456789 + } + }, + midia: { + video: { + url: 'https://www.youtube.com/watch?v=1' + }, + imagens: { + externas: [ + { + link: 'https://shutterstock.com/lalala123' + } + ] + } + }, + linhaProduto: { + id: 1 + }, + estrutura: { + tipoEstoque: 'F' as const, + lancamentoEstoque: 'A' as const, + componentes: [ + { + produto: { + id: 1 + }, + quantidade: 2.1 + } + ] + }, + camposCustomizados: [ + { + idCampoCustomizado: 123456789, + idVinculo: 123456789, + valor: '256GB', + item: 'Opção A' + } + ], + variacoes: [ + { + id: 123456789, + nome: 'Produto 1', + codigo: 'CODE_123', + preco: 1, + tipo: 'P' as const, + situacao: 'A' as const, + formato: 'S' as const, + descricaoCurta: 'Descrição curta', + dataValidade: '2020-01-01', + unidade: 'UN', + pesoLiquido: 1, + pesoBruto: 1, + volumes: 1, + itensPorCaixa: 1, + gtin: '1234567890123', + gtinEmbalagem: '1234567890123', + tipoProducao: 'P' as const, + condicao: 0 as const, + freteGratis: false, + marca: 'Marca', + descricaoComplementar: 'Descrição complementar', + linkExterno: 'https://www.google.com', + observacoes: 'Observações', + categoria: { + id: 123456789 + }, + estoque: { + minimo: 1, + maximo: 100, + crossdocking: 1, + localizacao: '14A' + }, + actionEstoque: 'Z' as const, + dimensoes: { + largura: 1, + altura: 1, + profundidade: 1, + unidadeMedida: 1 + }, + tributacao: { + origem: 0, + nFCI: '', + ncm: '', + cest: '', + codigoListaServicos: '', + spedTipoItem: '', + codigoItem: '', + percentualTributos: 0, + valorBaseStRetencao: 0, + valorStRetencao: 0, + valorICMSSubstituto: 0, + codigoExcecaoTipi: '', + classeEnquadramentoIpi: '', + valorIpiFixo: 0, + codigoSeloIpi: '', + valorPisFixo: 0, + valorCofinsFixo: 0, + codigoANP: '', + descricaoANP: '', + percentualGLP: 0, + percentualGasNacional: 0, + percentualGasImportado: 0, + valorPartida: 0, + tipoArmamento: 0 as const, + descricaoCompletaArmamento: '', + dadosAdicionais: '', + grupoProduto: { + id: 123456789 + } + }, + midia: { + video: { + url: 'https://www.youtube.com/watch?v=1' + }, + imagens: { + externas: [ + { + link: 'https://shutterstock.com/lalala123' + } + ] + } + }, + linhaProduto: { + id: 1 + }, + estrutura: { + tipoEstoque: 'F' as const, + lancamentoEstoque: 'A' as const, + componentes: [ + { + produto: { + id: 1 + }, + quantidade: 2.1 + } + ] + }, + camposCustomizados: [ + { + idCampoCustomizado: 123456789, + idVinculo: 123456789, + valor: '256GB', + item: 'Opção A' + } + ], + variacao: { + nome: 'Tamanho:G;Cor:Verde', + ordem: 1, + produtoPai: { + cloneInfo: true + } + } + } + ] + } +} diff --git a/src/entities/produtos/__tests__/get-response.ts b/src/entities/produtos/__tests__/get-response.ts new file mode 100644 index 0000000..ee8bccb --- /dev/null +++ b/src/entities/produtos/__tests__/get-response.ts @@ -0,0 +1,14 @@ +export default { + data: [ + { + id: 123456789, + nome: 'Produto 1', + codigo: 'CODE_123', + preco: 1, + tipo: 'P' as const, + situacao: 'A' as const, + formato: 'S' as const, + descricaoCurta: 'Descrição curta' + } + ] +} diff --git a/src/entities/produtos/__tests__/index.spec.ts b/src/entities/produtos/__tests__/index.spec.ts new file mode 100644 index 0000000..1a767e9 --- /dev/null +++ b/src/entities/produtos/__tests__/index.spec.ts @@ -0,0 +1,200 @@ +import { Chance } from 'chance' +import { Produtos } from '..' +import { InMemoryBlingRepository } from '../../../repositories/bling-in-memory.repository' +import { IChangeSituationManyResponse } from '../interfaces/change-situation-many.interface' +import { ICreateResponse } from '../interfaces/create.interface' +import { IDeleteManyResponse } from '../interfaces/delete-many.interface' +import { IFindResponse } from '../interfaces/find.interface' +import { IGetResponse } from '../interfaces/get.interface' +import { IUpdateResponse } from '../interfaces/update.interface' +import changeSituationManyResponse, { + changeSituationManyRequest +} from './change-situation-many-response' +import changeSituationResponse, { + changeSituationRequest +} from './change-situation-response' +import createResponse, { createRequestBody } from './create-response' +import deleteManyResponse from './delete-many-response' +import deleteResponse from './delete-response' +import findResponse from './find-response' +import getResponse from './get-response' +import updateResponse, { updateRequestBody } from './update-response' + +const chance = Chance() + +describe('Produtos entity', () => { + let repository: InMemoryBlingRepository + let entity: Produtos + + beforeEach(() => { + repository = new InMemoryBlingRepository() + entity = new Produtos(repository) + }) + + afterEach(() => { + jest.restoreAllMocks() + }) + + it('should delete many successfully', async () => { + const idsProdutos: number[] = [] + for (let i = 0; i < chance.natural({ min: 1, max: 5 }); i++) { + idsProdutos.push(chance.natural()) + } + const spy = jest.spyOn(repository, 'destroy') + repository.setResponse(deleteManyResponse) + + const response = await entity.deleteMany({ idsProdutos }) + + expect(spy).toHaveBeenCalledWith({ + endpoint: 'produtos', + id: '', + params: { idsProdutos } + }) + expect(response).toBe(deleteManyResponse) + + const typingResponseTest: IDeleteManyResponse = deleteManyResponse + expect(typingResponseTest).toBe(deleteManyResponse) + }) + + it('should delete successfully', async () => { + const idProduto = chance.natural() + const spy = jest.spyOn(repository, 'destroy') + repository.setResponse(deleteResponse) + + const response = await entity.delete({ idProduto }) + + expect(spy).toHaveBeenCalledWith({ + endpoint: 'produtos', + id: String(idProduto) + }) + expect(response).toBe(deleteResponse) + + const typingResponseTest: null = deleteResponse + expect(typingResponseTest).toBe(deleteResponse) + }) + + it('should get successfully', async () => { + const spy = jest.spyOn(repository, 'index') + repository.setResponse(getResponse) + + const response = await entity.get() + + expect(spy).toHaveBeenCalledWith({ + endpoint: 'produtos', + params: { + limite: undefined, + pagina: undefined, + criterio: undefined, + tipo: undefined, + idComponente: undefined, + dataInclusaoInicial: undefined, + dataInclusaoFinal: undefined, + dataAlteracaoInicial: undefined, + dataAlteracaoFinal: undefined, + idCategoria: undefined, + idLoja: undefined, + codigo: undefined, + nome: undefined, + idsProdutos: undefined + } + }) + expect(response).toBe(getResponse) + + const typingResponseTest: IGetResponse = getResponse + expect(typingResponseTest).toBe(getResponse) + }) + + it('should find successfully', async () => { + const spy = jest.spyOn(repository, 'show') + const idProduto = chance.natural() + repository.setResponse(findResponse) + + const response = await entity.find({ idProduto }) + + expect(spy).toHaveBeenCalledWith({ + endpoint: 'produtos', + id: String(idProduto) + }) + expect(response).toBe(findResponse) + + const typingResponseTest: IFindResponse = findResponse + expect(typingResponseTest).toBe(findResponse) + }) + + it('should change situation successfully', async () => { + const spy = jest.spyOn(repository, 'update') + const idProduto = chance.natural() + repository.setResponse(changeSituationResponse) + + const response = await entity.changeSituation({ + idProduto, + ...changeSituationRequest + }) + + expect(spy).toHaveBeenCalledWith({ + endpoint: 'produtos', + id: `${idProduto}/situacoes`, + body: changeSituationRequest + }) + expect(response).toBe(changeSituationResponse) + + const typingResponseTest: null = changeSituationResponse + expect(typingResponseTest).toBe(changeSituationResponse) + }) + + it('should create successfully', async () => { + const spy = jest.spyOn(repository, 'store') + repository.setResponse(createResponse) + + const response = await entity.create(createRequestBody) + + expect(spy).toHaveBeenCalledWith({ + endpoint: 'produtos', + body: createRequestBody + }) + expect(response).toBe(createResponse) + + const typingResponseTest: ICreateResponse = createResponse + expect(typingResponseTest).toBe(createResponse) + }) + + it('should change situation many successfully', async () => { + const spy = jest.spyOn(repository, 'store') + repository.setResponse(changeSituationManyResponse) + + const response = await entity.changeSituationMany( + changeSituationManyRequest + ) + + expect(spy).toHaveBeenCalledWith({ + endpoint: 'produtos/situacoes', + body: changeSituationManyRequest + }) + expect(response).toBe(changeSituationManyResponse) + + const typingResponseTest: IChangeSituationManyResponse = + changeSituationManyResponse + expect(typingResponseTest).toBe(changeSituationManyResponse) + }) + + it('should update successfully', async () => { + const spy = jest.spyOn(repository, 'replace') + const idProduto = chance.natural() + repository.setResponse(updateResponse) + + const response = await entity.update({ + idProduto, + ...updateRequestBody + }) + + expect(spy).toHaveBeenCalledWith({ + endpoint: 'produtos', + id: String(idProduto), + body: updateRequestBody + }) + expect(response).toBe(updateResponse) + + const typingResponseTest: IUpdateResponse = updateResponse + expect(typingResponseTest).toBe(updateResponse) + }) +}) diff --git a/src/entities/produtos/__tests__/update-response.ts b/src/entities/produtos/__tests__/update-response.ts new file mode 100644 index 0000000..afc3e28 --- /dev/null +++ b/src/entities/produtos/__tests__/update-response.ts @@ -0,0 +1,253 @@ +export default { + data: { + id: 6423817751, + variations: { + deleted: [ + { + id: 6423817579, + variations: {}, + warnings: ['Mensagem de aviso.'] + } + ], + updated: [ + { + id: 6423817579, + variations: {}, + warnings: ['Mensagem de aviso.'] + } + ], + saved: [ + { + id: 6423817579, + variations: {}, + warnings: ['Mensagem de aviso.'] + } + ] + }, + warnings: ['Mensagem de aviso.'] + } +} + +export const updateRequestBody = { + id: 123456789, + nome: 'Produto 1', + codigo: 'CODE_123', + preco: 1, + tipo: 'P' as const, + situacao: 'A' as const, + formato: 'S' as const, + descricaoCurta: 'Descrição curta', + dataValidade: '2020-01-01', + unidade: 'UN', + pesoLiquido: 1, + pesoBruto: 1, + volumes: 1, + itensPorCaixa: 1, + gtin: '1234567890123', + gtinEmbalagem: '1234567890123', + tipoProducao: 'P' as const, + condicao: 0 as const, + freteGratis: false, + marca: 'Marca', + descricaoComplementar: 'Descrição complementar', + linkExterno: 'https://www.google.com', + observacoes: 'Observações', + categoria: { + id: 123456789 + }, + estoque: { + minimo: 1, + maximo: 100, + crossdocking: 1, + localizacao: '14A' + }, + actionEstoque: 'Z' as const, + dimensoes: { + largura: 1, + altura: 1, + profundidade: 1, + unidadeMedida: 1 + }, + tributacao: { + origem: 0, + nFCI: '', + ncm: '', + cest: '', + codigoListaServicos: '', + spedTipoItem: '', + codigoItem: '', + percentualTributos: 0, + valorBaseStRetencao: 0, + valorStRetencao: 0, + valorICMSSubstituto: 0, + codigoExcecaoTipi: '', + classeEnquadramentoIpi: '', + valorIpiFixo: 0, + codigoSeloIpi: '', + valorPisFixo: 0, + valorCofinsFixo: 0, + codigoANP: '', + descricaoANP: '', + percentualGLP: 0, + percentualGasNacional: 0, + percentualGasImportado: 0, + valorPartida: 0, + tipoArmamento: 0 as const, + descricaoCompletaArmamento: '', + dadosAdicionais: '', + grupoProduto: { + id: 123456789 + } + }, + midia: { + video: { + url: 'https://www.youtube.com/watch?v=1' + }, + imagens: { + externas: [ + { + link: 'https://shutterstock.com/lalala123' + } + ] + } + }, + linhaProduto: { + id: 1 + }, + estrutura: { + tipoEstoque: 'F' as const, + lancamentoEstoque: 'A' as const, + componentes: [ + { + produto: { + id: 1 + }, + quantidade: 2.1 + } + ] + }, + camposCustomizados: [ + { + idCampoCustomizado: 123456789, + idVinculo: 123456789, + valor: '256GB', + item: 'Opção A' + } + ], + variacoes: [ + { + id: 123456789, + nome: 'Produto 1', + codigo: 'CODE_123', + preco: 1, + tipo: 'P' as const, + situacao: 'A' as const, + formato: 'S' as const, + descricaoCurta: 'Descrição curta', + dataValidade: '2020-01-01', + unidade: 'UN', + pesoLiquido: 1, + pesoBruto: 1, + volumes: 1, + itensPorCaixa: 1, + gtin: '1234567890123', + gtinEmbalagem: '1234567890123', + tipoProducao: 'P' as const, + condicao: 0 as const, + freteGratis: false, + marca: 'Marca', + descricaoComplementar: 'Descrição complementar', + linkExterno: 'https://www.google.com', + observacoes: 'Observações', + categoria: { + id: 123456789 + }, + estoque: { + minimo: 1, + maximo: 100, + crossdocking: 1, + localizacao: '14A' + }, + actionEstoque: 'Z' as const, + dimensoes: { + largura: 1, + altura: 1, + profundidade: 1, + unidadeMedida: 1 + }, + tributacao: { + origem: 0, + nFCI: '', + ncm: '', + cest: '', + codigoListaServicos: '', + spedTipoItem: '', + codigoItem: '', + percentualTributos: 0, + valorBaseStRetencao: 0, + valorStRetencao: 0, + valorICMSSubstituto: 0, + codigoExcecaoTipi: '', + classeEnquadramentoIpi: '', + valorIpiFixo: 0, + codigoSeloIpi: '', + valorPisFixo: 0, + valorCofinsFixo: 0, + codigoANP: '', + descricaoANP: '', + percentualGLP: 0, + percentualGasNacional: 0, + percentualGasImportado: 0, + valorPartida: 0, + tipoArmamento: 0 as const, + descricaoCompletaArmamento: '', + dadosAdicionais: '', + grupoProduto: { + id: 123456789 + } + }, + midia: { + video: { + url: 'https://www.youtube.com/watch?v=1' + }, + imagens: { + externas: [ + { + link: 'https://shutterstock.com/lalala123' + } + ] + } + }, + linhaProduto: { + id: 1 + }, + estrutura: { + tipoEstoque: 'F' as const, + lancamentoEstoque: 'A' as const, + componentes: [ + { + produto: { + id: 1 + }, + quantidade: 2.1 + } + ] + }, + camposCustomizados: [ + { + idCampoCustomizado: 123456789, + idVinculo: 123456789, + valor: '256GB', + item: 'Opção A' + } + ], + variacao: { + nome: 'Tamanho:G;Cor:Verde', + ordem: 1, + produtoPai: { + cloneInfo: true + } + } + } + ] +} diff --git a/src/entities/produtos/index.ts b/src/entities/produtos/index.ts new file mode 100644 index 0000000..b73b9a3 --- /dev/null +++ b/src/entities/produtos/index.ts @@ -0,0 +1,202 @@ +import { Entity } from '../@shared/entity' +import { + IChangeSituationManyBody, + IChangeSituationManyResponse +} from './interfaces/change-situation-many.interface' +import { + IChangeSituationBody, + IChangeSituationParams +} from './interfaces/change-situation.interface' +import { ICreateBody, ICreateResponse } from './interfaces/create.interface' +import { + IDeleteManyParams, + IDeleteManyResponse +} from './interfaces/delete-many.interface' +import { IDeleteParams } from './interfaces/delete.interface' +import { IFindParams, IFindResponse } from './interfaces/find.interface' +import { IGetParams, IGetResponse } from './interfaces/get.interface' +import { + IUpdateBody, + IUpdateParams, + IUpdateResponse +} from './interfaces/update.interface' + +/** + * Entidade para interação com Produtos. + * + * @see https://developer.bling.com.br/referencia#/Produtos + */ +export class Produtos extends Entity { + /** + * Remove múltiplos produtos. + * + * @param {IDeleteManyParams} params Parâmetros da remoção. + * + * @returns {Promise<IDeleteManyResponse>} Não há retorno. + * @throws {BlingApiException|BlingInternalException} + * + * @see https://developer.bling.com.br/referencia#/Produtos/delete_produtos + */ + public async deleteMany( + params: IDeleteManyParams + ): Promise<IDeleteManyResponse> { + return await this.repository.destroy({ + endpoint: 'produtos', + id: '', + params: { idsProdutos: params.idsProdutos } + }) + } + + /** + * Remove um produto. + * + * @param {IDeleteParams} params Parâmetros da remoção. + * + * @returns {Promise<null>} Não há retorno. + * @throws {BlingApiException|BlingInternalException} + * + * @see https://developer.bling.com.br/referencia#/Produtos/delete_produtos__idProduto_ + */ + public async delete(params: IDeleteParams): Promise<null> { + return await this.repository.destroy({ + endpoint: 'produtos', + id: String(params.idProduto) + }) + } + + /** + * Obtém produtos. + * + * @param {IGetParams} params Parâmetros da busca. + * + * @returns {Promise<IGetResponse>} + * @throws {BlingApiException|BlingInternalException} + * + * @see https://developer.bling.com.br/referencia#/Produtos/get_produtos + */ + public async get(params?: IGetParams): Promise<IGetResponse> { + return await this.repository.index({ + endpoint: 'produtos', + params: { + pagina: params?.pagina, + limite: params?.limite, + criterio: params?.criterio, + tipo: params?.tipo, + idComponente: params?.idComponente, + dataInclusaoInicial: this.prepareStringOrDateParam( + params?.dataInclusaoInicial + ), + dataInclusaoFinal: this.prepareStringOrDateParam( + params?.dataInclusaoFinal + ), + dataAlteracaoInicial: this.prepareStringOrDateParam( + params?.dataAlteracaoInicial + ), + dataAlteracaoFinal: this.prepareStringOrDateParam( + params?.dataAlteracaoFinal + ), + idCategoria: params?.idCategoria, + idLoja: params?.idLoja, + codigo: params?.codigo, + nome: params?.nome, + idsProdutos: params?.idsProdutos + } + }) + } + + /** + * Obtém um produto. + * + * @param {IFindParams} params Parâmetros da busca. + * + * @returns {Promise<IFindResponse>} + * @throws {BlingApiException|BlingInternalException} + * + * @see https://developer.bling.com.br/referencia#/Produtos/get_produtos__idProduto_ + */ + public async find(params: IFindParams): Promise<IFindResponse> { + return await this.repository.show({ + endpoint: 'produtos', + id: String(params.idProduto) + }) + } + + /** + * Altera a situação de um produto. + * + * @param {IChangeSituationParams & IChangeSituationBody} params Parâmetros da alteração. + * + * @returns {Promise<null>} + * @throws {BlingApiException|BlingInternalException} + * + * @see https://developer.bling.com.br/referencia#/Produtos/patch_produtos__idProduto__situacoes + */ + public async changeSituation( + params: IChangeSituationParams & IChangeSituationBody + ): Promise<null> { + const { idProduto, ...body } = params + return await this.repository.update({ + endpoint: 'produtos', + id: `${idProduto}/situacoes`, + body + }) + } + + /** + * Cria um produto. + * + * @param {ICreateBody} body O conteúdo para a criação. + * + * @returns {Promise<ICreateResponse>} + * @throws {BlingApiException|BlingInternalException} + * + * @see https://developer.bling.com.br/referencia#/Produtos/post_produtos + */ + public async create(body: ICreateBody): Promise<ICreateResponse> { + return await this.repository.store({ + endpoint: 'produtos', + body + }) + } + + /** + * Altera a situação de múltiplos produtos. + * + * @param {IChangeSituationManyBody} body O conteúdo para a criação. + * + * @returns {Promise<IChangeSituationManyResponse | null>} + * @throws {BlingApiException|BlingInternalException} + * + * @see https://developer.bling.com.br/referencia#/Produtos/post_produtos_situacoes + */ + public async changeSituationMany( + body: IChangeSituationManyBody + ): Promise<IChangeSituationManyResponse | null> { + return await this.repository.store({ + endpoint: 'produtos/situacoes', + body + }) + } + + /** + * Altera um produto. + * + * @param {IUpdateParams & IUpdateBody} params Os parâmetros da atualização. + * + * @return {Promise<IUpdateResponse>} + * @throws {BlingApiException|BlingInternalException} + * + * @see https://developer.bling.com.br/referencia#/Produtos/put_produtos__idProduto_ + */ + public async update( + params: IUpdateParams & IUpdateBody + ): Promise<IUpdateResponse> { + const { idProduto, ...body } = params + + return await this.repository.replace({ + endpoint: 'produtos', + id: String(idProduto), + body + }) + } +} diff --git a/src/entities/produtos/interfaces/change-situation-many.interface.ts b/src/entities/produtos/interfaces/change-situation-many.interface.ts new file mode 100644 index 0000000..1622959 --- /dev/null +++ b/src/entities/produtos/interfaces/change-situation-many.interface.ts @@ -0,0 +1,13 @@ +import { IDefaultErrorResponse } from 'src/entities/@shared/interfaces/error.interface' +import { ISituacao } from '../types/situacao.type' + +export interface IChangeSituationManyBody { + idsProdutos?: number[] + situacao?: ISituacao | 'E' +} + +export interface IChangeSituationManyResponse { + data: { + alertas?: ({ id: number } & IDefaultErrorResponse)[] + } +} diff --git a/src/entities/produtos/interfaces/change-situation.interface.ts b/src/entities/produtos/interfaces/change-situation.interface.ts new file mode 100644 index 0000000..0a1bdc2 --- /dev/null +++ b/src/entities/produtos/interfaces/change-situation.interface.ts @@ -0,0 +1,12 @@ +import { ISituacao } from '../types/situacao.type' + +export interface IChangeSituationParams { + /** + * ID do produto + */ + idProduto: number +} + +export interface IChangeSituationBody { + situacao: ISituacao +} diff --git a/src/entities/produtos/interfaces/create.interface.ts b/src/entities/produtos/interfaces/create.interface.ts new file mode 100644 index 0000000..0fa2296 --- /dev/null +++ b/src/entities/produtos/interfaces/create.interface.ts @@ -0,0 +1,207 @@ +import { IActionEstoque } from '../types/action-estoque.type' +import { ICondicao } from '../types/condicao.type' +import { IEstruturaLancamentoEstoque } from '../types/estrutura-lancamento-estoque.type' +import { IEstruturaTipoEstoque } from '../types/estrutura-tipo-estoque.type' +import { IFormato } from '../types/formato.type' +import { ISituacao } from '../types/situacao.type' +import { ITipoArmamento } from '../types/tipo-armamento.type' +import { ITipoProducao } from '../types/tipo-producao.type' +import { ITipo } from '../types/tipo.type' + +export interface ICreateBody { + id?: number + nome: string + codigo?: string + preco?: number + tipo: ITipo + situacao: ISituacao + formato: IFormato + descricaoCurta?: string + dataValidade?: string + unidade?: string + pesoLiquido?: number + pesoBruto?: number + volumes?: number + itensPorCaixa?: number + gtin?: string + gtinEmbalagem?: string + tipoProducao?: ITipoProducao + condicao?: ICondicao + freteGratis?: boolean + marca?: string + descricaoComplementar?: string + linkExterno?: string + observacoes?: string + categoria?: { id: number } + estoque?: { + minimo?: number + maximo?: number + crossdocking?: number + localizacao?: string + } + actionEstoque?: IActionEstoque + dimensoes?: { + largura?: number + altura?: number + profundidade?: number + unidadeMedida?: number + } + tributacao?: { + origem?: number + nFCI?: string + ncm?: string + cest?: string + codigoListaServicos?: string + spedTipoItem?: string + codigoItem?: string + percentualTributos?: number + valorBaseStRetencao?: number + valorStRetencao?: number + valorICMSSubstituto?: number + codigoExcecaoTipi?: string + classeEnquadramentoIpi?: string + valorIpiFixo?: number + codigoSeloIpi?: string + valorPisFixo?: number + valorCofinsFixo?: number + codigoANP?: string + descricaoANP?: string + percentualGLP?: number + percentualGasNacional?: number + percentualGasImportado?: number + valorPartida?: number + tipoArmamento?: ITipoArmamento + descricaoCompletaArmamento?: string + dadosAdicionais?: string + grupoProduto?: { id: number } + } + midia?: { + video: { url: string } + imagens: { externas: { link: string }[] } + } + linhaProduto?: { id: number } + estrutura?: { + tipoEstoque: IEstruturaTipoEstoque + lancamentoEstoque: IEstruturaLancamentoEstoque + componentes: { + produto: { id: number } + quantidade: number + }[] + } + camposCustomizados?: { + idCampoCustomizado: number + idVinculo?: number + valor?: string + item?: string + }[] + variacoes: { + id?: number + nome: string + codigo?: string + preco?: number + tipo: ITipo + situacao: ISituacao + formato: IFormato + descricaoCurta?: string + dataValidade?: string + unidade?: string + pesoLiquido?: number + pesoBruto?: number + volumes?: number + itensPorCaixa?: number + gtin?: string + gtinEmbalagem?: string + tipoProducao?: ITipoProducao + condicao?: ICondicao + freteGratis?: boolean + marca?: string + descricaoComplementar?: string + linkExterno?: string + observacoes?: string + categoria?: { id: number } + estoque?: { + minimo?: number + maximo?: number + crossdocking?: number + localizacao?: string + } + actionEstoque?: IActionEstoque + dimensoes?: { + largura?: number + altura?: number + profundidade?: number + unidadeMedida?: number + } + tributacao?: { + origem?: number + nFCI?: string + ncm?: string + cest?: string + codigoListaServicos?: string + spedTipoItem?: string + codigoItem?: string + percentualTributos?: number + valorBaseStRetencao?: number + valorStRetencao?: number + valorICMSSubstituto?: number + codigoExcecaoTipi?: string + classeEnquadramentoIpi?: string + valorIpiFixo?: number + codigoSeloIpi?: string + valorPisFixo?: number + valorCofinsFixo?: number + codigoANP?: string + descricaoANP?: string + percentualGLP?: number + percentualGasNacional?: number + percentualGasImportado?: number + valorPartida?: number + tipoArmamento?: ITipoArmamento + descricaoCompletaArmamento?: string + dadosAdicionais?: string + grupoProduto?: { id: number } + } + midia?: { + video: { url: string } + imagens: { externas: { link: string }[] } + } + linhaProduto?: { id: number } + estrutura?: { + tipoEstoque: IEstruturaTipoEstoque + lancamentoEstoque: IEstruturaLancamentoEstoque + componentes: { + produto: { id: number } + quantidade: number + }[] + } + camposCustomizados?: { + idCampoCustomizado: number + idVinculo?: number + valor?: string + item?: string + }[] + variacao: { + nome: string + ordem: number + produtoPai: { cloneInfo: boolean } + } + }[] +} + +interface ICreateResponseActionItem { + id?: number + variations?: any + warnings?: string[] +} + +export interface ICreateResponse { + data: { + id?: number + variations?: { + deleted?: ICreateResponseActionItem[] + updated?: ICreateResponseActionItem[] + saved?: ICreateResponseActionItem[] + } + warnings?: string[] + } +} diff --git a/src/entities/produtos/interfaces/delete-many.interface.ts b/src/entities/produtos/interfaces/delete-many.interface.ts new file mode 100644 index 0000000..7e3af37 --- /dev/null +++ b/src/entities/produtos/interfaces/delete-many.interface.ts @@ -0,0 +1,14 @@ +import { IDefaultErrorResponse } from 'src/entities/@shared/interfaces/error.interface' + +export interface IDeleteManyParams { + /** + * IDs dos produtos + */ + idsProdutos: number[] +} + +export interface IDeleteManyResponse { + data: { + alertas?: ({ id: number } & IDefaultErrorResponse)[] + } +} diff --git a/src/entities/produtos/interfaces/delete.interface.ts b/src/entities/produtos/interfaces/delete.interface.ts new file mode 100644 index 0000000..2e42f46 --- /dev/null +++ b/src/entities/produtos/interfaces/delete.interface.ts @@ -0,0 +1,6 @@ +export interface IDeleteParams { + /** + * ID do produto + */ + idProduto: number +} diff --git a/src/entities/produtos/interfaces/find.interface.ts b/src/entities/produtos/interfaces/find.interface.ts new file mode 100644 index 0000000..13b52b0 --- /dev/null +++ b/src/entities/produtos/interfaces/find.interface.ts @@ -0,0 +1,198 @@ +import { IActionEstoque } from '../types/action-estoque.type' +import { ICondicao } from '../types/condicao.type' +import { IEstruturaLancamentoEstoque } from '../types/estrutura-lancamento-estoque.type' +import { IEstruturaTipoEstoque } from '../types/estrutura-tipo-estoque.type' +import { IFormato } from '../types/formato.type' +import { ISituacao } from '../types/situacao.type' +import { ITipoArmamento } from '../types/tipo-armamento.type' +import { ITipoProducao } from '../types/tipo-producao.type' +import { ITipo } from '../types/tipo.type' + +export interface IFindParams { + /** + * ID do produto + */ + idProduto: number +} + +export interface IFindResponse { + data: { + id?: number + nome: string + codigo?: string + preco?: number + tipo: ITipo + situacao: ISituacao + formato: IFormato + descricaoCurta?: string + dataValidade?: string + unidade?: string + pesoLiquido?: number + pesoBruto?: number + volumes?: number + itensPorCaixa?: number + gtin?: string + gtinEmbalagem?: string + tipoProducao?: ITipoProducao + condicao?: ICondicao + freteGratis?: boolean + marca?: string + descricaoComplementar?: string + linkExterno?: string + observacoes?: string + categoria?: { id: number } + estoque?: { + minimo?: number + maximo?: number + crossdocking?: number + localizacao?: string + } + actionEstoque?: IActionEstoque + dimensoes?: { + largura?: number + altura?: number + profundidade?: number + unidadeMedida?: number + } + tributacao?: { + origem?: number + nFCI?: string + ncm?: string + cest?: string + codigoListaServicos?: string + spedTipoItem?: string + codigoItem?: string + percentualTributos?: number + valorBaseStRetencao?: number + valorStRetencao?: number + valorICMSSubstituto?: number + codigoExcecaoTipi?: string + classeEnquadramentoIpi?: string + valorIpiFixo?: number + codigoSeloIpi?: string + valorPisFixo?: number + valorCofinsFixo?: number + codigoANP?: string + descricaoANP?: string + percentualGLP?: number + percentualGasNacional?: number + percentualGasImportado?: number + valorPartida?: number + tipoArmamento?: ITipoArmamento + descricaoCompletaArmamento?: string + dadosAdicionais?: string + grupoProduto?: { id: number } + } + midia?: { + video: { url: string } + imagens: { externas: { link: string }[] } + } + linhaProduto?: { id: number } + estrutura?: { + tipoEstoque: IEstruturaTipoEstoque + lancamentoEstoque: IEstruturaLancamentoEstoque + componentes: { + produto: { id: number } + quantidade: number + }[] + } + camposCustomizados?: { + idCampoCustomizado: number + idVinculo?: number + valor?: string + item?: string + }[] + variacoes: { + id?: number + nome: string + codigo?: string + preco?: number + tipo: ITipo + situacao: ISituacao + formato: IFormato + descricaoCurta?: string + dataValidade?: string + unidade?: string + pesoLiquido?: number + pesoBruto?: number + volumes?: number + itensPorCaixa?: number + gtin?: string + gtinEmbalagem?: string + tipoProducao?: ITipoProducao + condicao?: ICondicao + freteGratis?: boolean + marca?: string + descricaoComplementar?: string + linkExterno?: string + observacoes?: string + categoria?: { id: number } + estoque?: { + minimo?: number + maximo?: number + crossdocking?: number + localizacao?: string + } + actionEstoque?: IActionEstoque + dimensoes?: { + largura?: number + altura?: number + profundidade?: number + unidadeMedida?: number + } + tributacao?: { + origem?: number + nFCI?: string + ncm?: string + cest?: string + codigoListaServicos?: string + spedTipoItem?: string + codigoItem?: string + percentualTributos?: number + valorBaseStRetencao?: number + valorStRetencao?: number + valorICMSSubstituto?: number + codigoExcecaoTipi?: string + classeEnquadramentoIpi?: string + valorIpiFixo?: number + codigoSeloIpi?: string + valorPisFixo?: number + valorCofinsFixo?: number + codigoANP?: string + descricaoANP?: string + percentualGLP?: number + percentualGasNacional?: number + percentualGasImportado?: number + valorPartida?: number + tipoArmamento?: ITipoArmamento + descricaoCompletaArmamento?: string + dadosAdicionais?: string + grupoProduto?: { id: number } + } + midia?: { + video: { url: string } + imagens: { externas: { link: string }[] } + } + linhaProduto?: { id: number } + estrutura?: { + tipoEstoque: IEstruturaTipoEstoque + lancamentoEstoque: IEstruturaLancamentoEstoque + componentes: { + produto: { id: number } + quantidade: number + }[] + } + camposCustomizados?: { + idCampoCustomizado: number + idVinculo?: number + valor?: string + item?: string + }[] + variacao: { + nome: string + ordem: number + produtoPai: { cloneInfo: boolean } + } + }[] + } +} diff --git a/src/entities/produtos/interfaces/get.interface.ts b/src/entities/produtos/interfaces/get.interface.ts new file mode 100644 index 0000000..f105f33 --- /dev/null +++ b/src/entities/produtos/interfaces/get.interface.ts @@ -0,0 +1,77 @@ +import { ICriterio } from '../types/criterio.type' +import { IFormato } from '../types/formato.type' +import { ISituacao } from '../types/situacao.type' +import { ITipoFiltro } from '../types/tipo-filtro.type' +import { ITipo } from '../types/tipo.type' + +export interface IGetParams { + /** + * N° da página da listagem + */ + pagina?: number + /** + * Quantidade de registros que devem ser exibidos por página + */ + limite?: number + /** + * Critério de listagem + */ + criterio?: ICriterio + /** + * + */ + tipo?: ITipoFiltro + /** + * ID do componente. Utilizado quando o filtro tipo for `E`. + */ + idComponente?: number + /** + * Data de inclusão inicial + */ + dataInclusaoInicial?: Date | string + /** + * Data de inclusão final + */ + dataInclusaoFinal?: Date | string + /** + * Data de alteração inicial + */ + dataAlteracaoInicial?: Date | string + /** + * Data de alteração final + */ + dataAlteracaoFinal?: Date | string + /** + * ID da categoria do produto + */ + idCategoria?: number + /** + * ID da loja + */ + idLoja?: number + /** + * Código do produto + */ + codigo?: string + /** + * Nome do produto + */ + nome?: string + /** + * IDs dos produtos + */ + idsProdutos?: number[] +} + +export interface IGetResponse { + data: { + id?: number + nome: string + codigo?: string + preco?: number + tipo: ITipo + situacao: ISituacao + formato: IFormato + descricaoCurta?: string + }[] +} diff --git a/src/entities/produtos/interfaces/update.interface.ts b/src/entities/produtos/interfaces/update.interface.ts new file mode 100644 index 0000000..7d469b9 --- /dev/null +++ b/src/entities/produtos/interfaces/update.interface.ts @@ -0,0 +1,214 @@ +import { IActionEstoque } from '../types/action-estoque.type' +import { ICondicao } from '../types/condicao.type' +import { IEstruturaLancamentoEstoque } from '../types/estrutura-lancamento-estoque.type' +import { IEstruturaTipoEstoque } from '../types/estrutura-tipo-estoque.type' +import { IFormato } from '../types/formato.type' +import { ISituacao } from '../types/situacao.type' +import { ITipoArmamento } from '../types/tipo-armamento.type' +import { ITipoProducao } from '../types/tipo-producao.type' +import { ITipo } from '../types/tipo.type' + +export interface IUpdateParams { + /** + * ID do produto + */ + idProduto: number +} + +export interface IUpdateBody { + id?: number + nome: string + codigo?: string + preco?: number + tipo: ITipo + situacao: ISituacao + formato: IFormato + descricaoCurta?: string + dataValidade?: string + unidade?: string + pesoLiquido?: number + pesoBruto?: number + volumes?: number + itensPorCaixa?: number + gtin?: string + gtinEmbalagem?: string + tipoProducao?: ITipoProducao + condicao?: ICondicao + freteGratis?: boolean + marca?: string + descricaoComplementar?: string + linkExterno?: string + observacoes?: string + categoria?: { id: number } + estoque?: { + minimo?: number + maximo?: number + crossdocking?: number + localizacao?: string + } + actionEstoque?: IActionEstoque + dimensoes?: { + largura?: number + altura?: number + profundidade?: number + unidadeMedida?: number + } + tributacao?: { + origem?: number + nFCI?: string + ncm?: string + cest?: string + codigoListaServicos?: string + spedTipoItem?: string + codigoItem?: string + percentualTributos?: number + valorBaseStRetencao?: number + valorStRetencao?: number + valorICMSSubstituto?: number + codigoExcecaoTipi?: string + classeEnquadramentoIpi?: string + valorIpiFixo?: number + codigoSeloIpi?: string + valorPisFixo?: number + valorCofinsFixo?: number + codigoANP?: string + descricaoANP?: string + percentualGLP?: number + percentualGasNacional?: number + percentualGasImportado?: number + valorPartida?: number + tipoArmamento?: ITipoArmamento + descricaoCompletaArmamento?: string + dadosAdicionais?: string + grupoProduto?: { id: number } + } + midia?: { + video: { url: string } + imagens: { externas: { link: string }[] } + } + linhaProduto?: { id: number } + estrutura?: { + tipoEstoque: IEstruturaTipoEstoque + lancamentoEstoque: IEstruturaLancamentoEstoque + componentes: { + produto: { id: number } + quantidade: number + }[] + } + camposCustomizados?: { + idCampoCustomizado: number + idVinculo?: number + valor?: string + item?: string + }[] + variacoes: { + id?: number + nome: string + codigo?: string + preco?: number + tipo: ITipo + situacao: ISituacao + formato: IFormato + descricaoCurta?: string + dataValidade?: string + unidade?: string + pesoLiquido?: number + pesoBruto?: number + volumes?: number + itensPorCaixa?: number + gtin?: string + gtinEmbalagem?: string + tipoProducao?: ITipoProducao + condicao?: ICondicao + freteGratis?: boolean + marca?: string + descricaoComplementar?: string + linkExterno?: string + observacoes?: string + categoria?: { id: number } + estoque?: { + minimo?: number + maximo?: number + crossdocking?: number + localizacao?: string + } + actionEstoque?: IActionEstoque + dimensoes?: { + largura?: number + altura?: number + profundidade?: number + unidadeMedida?: number + } + tributacao?: { + origem?: number + nFCI?: string + ncm?: string + cest?: string + codigoListaServicos?: string + spedTipoItem?: string + codigoItem?: string + percentualTributos?: number + valorBaseStRetencao?: number + valorStRetencao?: number + valorICMSSubstituto?: number + codigoExcecaoTipi?: string + classeEnquadramentoIpi?: string + valorIpiFixo?: number + codigoSeloIpi?: string + valorPisFixo?: number + valorCofinsFixo?: number + codigoANP?: string + descricaoANP?: string + percentualGLP?: number + percentualGasNacional?: number + percentualGasImportado?: number + valorPartida?: number + tipoArmamento?: ITipoArmamento + descricaoCompletaArmamento?: string + dadosAdicionais?: string + grupoProduto?: { id: number } + } + midia?: { + video: { url: string } + imagens: { externas: { link: string }[] } + } + linhaProduto?: { id: number } + estrutura?: { + tipoEstoque: IEstruturaTipoEstoque + lancamentoEstoque: IEstruturaLancamentoEstoque + componentes: { + produto: { id: number } + quantidade: number + }[] + } + camposCustomizados?: { + idCampoCustomizado: number + idVinculo?: number + valor?: string + item?: string + }[] + variacao: { + nome: string + ordem: number + produtoPai: { cloneInfo: boolean } + } + }[] +} + +interface ICreateResponseActionItem { + id?: number + variations?: any + warnings?: string[] +} + +export interface IUpdateResponse { + data: { + id?: number + variations?: { + deleted?: ICreateResponseActionItem[] + updated?: ICreateResponseActionItem[] + saved?: ICreateResponseActionItem[] + } + warnings?: string[] + } +} diff --git a/src/entities/produtos/types/action-estoque.type.ts b/src/entities/produtos/types/action-estoque.type.ts new file mode 100644 index 0000000..012232f --- /dev/null +++ b/src/entities/produtos/types/action-estoque.type.ts @@ -0,0 +1,8 @@ +/** + * Tipagem referente à ação de estoque ao transformar um produto simples em + * variação. + * + * - `Z`: Irá zerar os saldos de estoque + * - `T`: Transfere o estoque do produto pai para a primeira variação informada + */ +export type IActionEstoque = 'Z' | 'T' diff --git a/src/entities/produtos/types/condicao.type.ts b/src/entities/produtos/types/condicao.type.ts new file mode 100644 index 0000000..53ed33c --- /dev/null +++ b/src/entities/produtos/types/condicao.type.ts @@ -0,0 +1,8 @@ +/** + * Tipagem referente à condição do produto. + * + * - `0`: Não especificado + * - `1`: Novo + * - `2`: Usado + */ +export type ICondicao = 0 | 1 | 2 diff --git a/src/entities/produtos/types/criterio.type.ts b/src/entities/produtos/types/criterio.type.ts new file mode 100644 index 0000000..814d124 --- /dev/null +++ b/src/entities/produtos/types/criterio.type.ts @@ -0,0 +1,10 @@ +/** + * Tipagem referente ao critério de listagem de produtos. + * + * - `1`: Últimos incluídos + * - `2`: Ativos + * - `3`: Inativos + * - `4`: Excluídos + * - `5`: Todos + */ +export type ICriterio = 1 | 2 | 3 | 4 | 5 diff --git a/src/entities/produtos/types/estrutura-lancamento-estoque.type.ts b/src/entities/produtos/types/estrutura-lancamento-estoque.type.ts new file mode 100644 index 0000000..4823a94 --- /dev/null +++ b/src/entities/produtos/types/estrutura-lancamento-estoque.type.ts @@ -0,0 +1,8 @@ +/** + * Tipagem referente ao lançamento de estoque para a estrutura. + * + * - `A`: Produto e Componente + * - `M`: Componente + * - `P`: Produto + */ +export type IEstruturaLancamentoEstoque = 'A' | 'M' | 'P' diff --git a/src/entities/produtos/types/estrutura-tipo-estoque.type.ts b/src/entities/produtos/types/estrutura-tipo-estoque.type.ts new file mode 100644 index 0000000..a835dd1 --- /dev/null +++ b/src/entities/produtos/types/estrutura-tipo-estoque.type.ts @@ -0,0 +1,7 @@ +/** + * Tipagem referente ao tipo do estoque para a estrutura. + * + * - `F`: Físico + * - `V`: Virtual + */ +export type IEstruturaTipoEstoque = 'F' | 'V' diff --git a/src/entities/produtos/types/formato.type.ts b/src/entities/produtos/types/formato.type.ts new file mode 100644 index 0000000..79c6437 --- /dev/null +++ b/src/entities/produtos/types/formato.type.ts @@ -0,0 +1,8 @@ +/** + * Tipagem referente ao formato do produto. + * + * - `S`: Simples + * - `V`: Com variações + * - `E`: Com composição + */ +export type IFormato = 'S' | 'V' | 'E' diff --git a/src/entities/produtos/types/situacao.type.ts b/src/entities/produtos/types/situacao.type.ts new file mode 100644 index 0000000..bffb723 --- /dev/null +++ b/src/entities/produtos/types/situacao.type.ts @@ -0,0 +1,7 @@ +/** + * Tipagem referente à situação de um produto. + * + * - `A`: Ativo + * - `I`: Inativo + */ +export type ISituacao = 'A' | 'I' diff --git a/src/entities/produtos/types/tipo-armamento.type.ts b/src/entities/produtos/types/tipo-armamento.type.ts new file mode 100644 index 0000000..277ff6d --- /dev/null +++ b/src/entities/produtos/types/tipo-armamento.type.ts @@ -0,0 +1,7 @@ +/** + * Tipagem referente ao tipo do armamento (quando o produto se referir a um). + * + * - `0`: Uso permitido + * - `1`: Uso restrito + */ +export type ITipoArmamento = 0 | 1 diff --git a/src/entities/produtos/types/tipo-filtro.type.ts b/src/entities/produtos/types/tipo-filtro.type.ts new file mode 100644 index 0000000..3ab1a30 --- /dev/null +++ b/src/entities/produtos/types/tipo-filtro.type.ts @@ -0,0 +1,12 @@ +/** + * Tipagem referente ao filtro do tipo do produto. + * + * - `T`: Todos + * - `P`: Produtos + * - `S`: Serviços + * - `E`: Composições + * - `PS`: Produtos simples + * - `C`: Com variações + * - `V`: Variações + */ +export type ITipoFiltro = 'T' | 'P' | 'S' | 'E' | 'PS' | 'C' | 'V' diff --git a/src/entities/produtos/types/tipo-producao.type.ts b/src/entities/produtos/types/tipo-producao.type.ts new file mode 100644 index 0000000..023e52e --- /dev/null +++ b/src/entities/produtos/types/tipo-producao.type.ts @@ -0,0 +1,7 @@ +/** + * Tipagem referente ao tipo da produção do produto. + * + * - `P`: Própria + * - `T`: Terceiros + */ +export type ITipoProducao = 'P' | 'T' diff --git a/src/entities/produtos/types/tipo.type.ts b/src/entities/produtos/types/tipo.type.ts new file mode 100644 index 0000000..73e99f9 --- /dev/null +++ b/src/entities/produtos/types/tipo.type.ts @@ -0,0 +1,8 @@ +/** + * Tipagem referente ao tipo de um produto. + * + * - `S`: Serviço + * - `P`: Produto + * - `N`: Serviço 06 21 22 + */ +export type ITipo = 'S' | 'P' | 'N'