From 9fbd40b3adcf761208ad3824b9e21a9c4bff3c5c Mon Sep 17 00:00:00 2001 From: Pedro Fonseca Date: Wed, 19 Apr 2023 22:02:41 -0300 Subject: [PATCH 001/139] criar transferencia pix --- bb_wrapper/wrapper/pagamento_lote.py | 120 ++++++++++++++++++++++++++- 1 file changed, 118 insertions(+), 2 deletions(-) diff --git a/bb_wrapper/wrapper/pagamento_lote.py b/bb_wrapper/wrapper/pagamento_lote.py index 845585f7..ba6800d2 100644 --- a/bb_wrapper/wrapper/pagamento_lote.py +++ b/bb_wrapper/wrapper/pagamento_lote.py @@ -15,8 +15,7 @@ class PagamentoLoteBBWrapper(BaseBBWrapper): """ Wrapper da API Pagamentos em Lote """ - - SCOPE = "pagamentos-lote.lotes-requisicao pagamentos-lote.transferencias-info pagamentos-lote.transferencias-requisicao pagamentos-lote.cancelar-requisicao pagamentos-lote.devolvidos-info pagamentos-lote.lotes-info pagamentos-lote.pagamentos-guias-sem-codigo-barras-info pagamentos-lote.pagamentos-info pagamentos-lote.pagamentos-guias-sem-codigo-barras-requisicao pagamentos-lote.pagamentos-codigo-barras-info pagamentos-lote.boletos-requisicao pagamentos-lote.guias-codigo-barras-info pagamentos-lote.guias-codigo-barras-requisicao pagamentos-lote.transferencias-pix-info pagamentos-lote.transferencias-pix-requisicao pagamentos-lote.pix-info pagamentos-lote.boletos-info" # noqa + SCOPE = "pagamentos-lote.lotes-requisicao pagamentos-lote.transferencias-info pagamentos-lote.transferencias-requisicao pagamentos-lote.cancelar-requisicao pagamentos-lote.devolvidos-info pagamentos-lote.lotes-info pagamentos-lote.pagamentos-guias-sem-codigo-barras-info pagamentos-lote.pagamentos-info pagamentos-lote.pagamentos-guias-sem-codigo-barras-requisicao pagamentos-lote.pagamentos-codigo-barras-info pagamentos-lote.boletos-requisicao pagamentos-lote.guias-codigo-barras-info pagamentos-lote.guias-codigo-barras-requisicao pagamentos-lote.transferencias-pix-requisicao" # noqa BASE_PROD_ADDITION = "-ip" BASE_DOMAIN = ".bb.com.br/pagamentos-lote/v1" @@ -481,3 +480,120 @@ def consultar_pagamento_tributo(self, _id): response = self._get(url) return response + + ################ + # PIX # + ################ + + def _criar_dados_transferencia_pix( + self, + n_requisicao, + agencia, + conta, + dv_conta, + data_transferencia, + valor_transferencia, + forma_id, + ddd, + telefone, + email, + cpf, + cnpj, + chave_aleatoria, + descricao, + tipo_pagamento, + ): + lote_data = { + "numeroRequisicao": n_requisicao, + "agenciaDebito": agencia, + "contaCorrenteDebito": conta, + "digitoVerificadorContaCorrente": dv_conta, + "tipoPagamento": tipo_pagamento, + } + + transferencia_data = { + "data": data_transferencia, + "valor": valor_transferencia, + "formaIdentificacao": forma_id, + "descricaoPagamento": descricao, + } + + if forma_id == 1: + transferencia_data["dddTelefone"] = ddd + transferencia_data["telefone"] = telefone + elif forma_id == 2: + transferencia_data["email"] = email + elif forma_id == 3: + transferencia_data["cpf"] = cpf + transferencia_data["cnpj"] = cnpj + elif forma_id == 4: + transferencia_data["identificacaoAleatoria"] = chave_aleatoria + + return {**lote_data, "listaTransferencias": [{**transferencia_data}]} + + def criar_transferencia_pix( + self, + n_requisicao, + agencia, + conta, + dv_conta, + data_transferencia, + valor_transferencia, + forma_id, + ddd=None, + telefone=None, + email=None, + cpf=None, + cnpj=None, + chave_aleatoria=None, + descricao="", + tipo_pagamento=128, + ): + """ + Efetua pagamentos em lote via tranferência PIX + + Args: + n_requisicao: Nº da requisição a ser utilizado. Deve ser único + agencia: Agência da conta de origem do pagamento + conta: Nº da conta de origem do pagamento + dv_conta: DV da conta de origem do pagamento + tipo_pagamento: Tipo de pagamento a ser feito (126, 127 ou 128) + data_transferencia: Data do pagamento. No formato "ddmmyyyy" + valor_transferencia: Valor do pagamento + forma_id: Tipo de chave utilizada + 1. Telefone + 2. E-mail + 3. CPF/CNPJ + 4. Chave Aleatória + ddd: DDD com dígitos. Obrigatório caso forma_id seja igual 1 + telefone: Telefone do recebedor. Obrigatório caso forma_id seja igual 1 + email: Email do recebedor. Obrigatório caso forma_id seja igual 2 + cpf: CPF do recebedor. + Opcional caso forma_id seja igual a 1 ou 2 e caso o campo cnpj não seja informado + Obrigatório caso forma_id seja igual a 3 ou 5 e caso o campo cnpj não seja informado + cnpj: CNPJ do recebedor: Tem os mesmos casos de Obrigatório e opcional do cpf + chave_aleatoria: Chave aleatória gerada pelo recebedor. Obrigatório caso forma_id seja igual 4 + descricao: Campo de uso livre pelo cliente + """ + data = self._criar_dados_transferencia_pix( + n_requisicao, + agencia, + conta, + dv_conta, + data_transferencia, + valor_transferencia, + forma_id, + ddd, + telefone, + email, + cpf, + cnpj, + chave_aleatoria, + descricao, + tipo_pagamento, + ) + import pdb; pdb.set_trace() + url = self._construct_url("lotes-transferencias-pix") + response = self._post(url, data) + + return response From 230699716c5cfb0b61fa9abe7ce068b9f9e99cf7 Mon Sep 17 00:00:00 2001 From: Pedro Fonseca Date: Wed, 19 Apr 2023 22:03:04 -0300 Subject: [PATCH 002/139] testes de transferencias pix --- tests/wrapper/test_pagamentos.py | 116 +++++++++++++++++++++++++++++++ 1 file changed, 116 insertions(+) diff --git a/tests/wrapper/test_pagamentos.py b/tests/wrapper/test_pagamentos.py index 0c4b5c35..75ed47a9 100644 --- a/tests/wrapper/test_pagamentos.py +++ b/tests/wrapper/test_pagamentos.py @@ -446,3 +446,119 @@ def test_consultar_pagamento_tributo_1(self): self.assertEqual(2, self.total_requests()) self.mock_responses.assert_call_count(request_url, 1) + + def test_criar_transferencia_pix_chave_aleatoria(self): + """ + Teste para verificar a URL da requisição e dados + """ + + request_url = PagamentoLoteBBWrapper()._construct_url("lotes-transferencias-pix") + expected_json = { + "numeroRequisicao": "123", + "agenciaDebito": "345", + "contaCorrenteDebito": "678", + "digitoVerificadorContaCorrente": "X", + "tipoPagamento": 128, + "listaTransferencias": [ + { + "data": "19042023", + "valor": "11", + "descricaoPagamento": "Pagamento", + "formaIdentificacao": 4, + "identificacaoAleatoria": "d14d32de-b3b9-4c31-9f89-8df2cec92c50", + } + ], + } + self.mock_responses.add( + responses.POST, + request_url, + headers=self._build_authorization_header(1), + json=expected_json, + ) + + response = PagamentoLoteBBWrapper().criar_transferencia_pix( + "123", "345", "678", "X", "19042023", "11", 4, None, None, None, None, None, "d14d32de-b3b9-4c31-9f89-8df2cec92c50", "Pagamento" + ) + + self.assertEqual(request_url, response.url) + self.assertEqual(self._get_headers(), response.headers) + self.assertEqual(expected_json, response.json()) + self.assertEqual(2, self.total_requests()) + self.mock_responses.assert_call_count(request_url, 1) + + def test_criar_transferencia_pix_email(self): + """ + Teste para verificar a URL da requisição e dados + """ + + request_url = PagamentoLoteBBWrapper()._construct_url("lotes-transferencias-pix") + expected_json = { + "numeroRequisicao": "123", + "agenciaDebito": "345", + "contaCorrenteDebito": "678", + "digitoVerificadorContaCorrente": "X", + "tipoPagamento": 128, + "listaTransferencias": [ + { + "data": "19042023", + "valor": "12", + "descricaoPagamento": "Teste transfer", + "formaIdentificacao": 2, + "email": "testqrcode01@bb.com.br", + } + ], + } + self.mock_responses.add( + responses.POST, + request_url, + headers=self._build_authorization_header(1), + json=expected_json, + ) + + response = PagamentoLoteBBWrapper().criar_transferencia_pix( + "123", "345", "678", "X", "19042023", "11", 2, None, None, "testqrcode01@bb.com.br", None, None, None, "Teste transfer") + + self.assertEqual(request_url, response.url) + self.assertEqual(self._get_headers(), response.headers) + self.assertEqual(expected_json, response.json()) + self.assertEqual(2, self.total_requests()) + self.mock_responses.assert_call_count(request_url, 1) + + def test_criar_transferencia_pix_telefone(self): + """ + Teste para verificar a URL da requisição e dados + """ + + request_url = PagamentoLoteBBWrapper()._construct_url("lotes-transferencias-pix") + expected_json = { + "numeroRequisicao": "123", + "agenciaDebito": "345", + "contaCorrenteDebito": "678", + "digitoVerificadorContaCorrente": "X", + "tipoPagamento": 128, + "listaTransferencias": [ + { + "data": "19042023", + "ddd": "11", + "telefone": "985732102", + "valor": "12", + "descricaoPagamento": "Teste telefone", + "formaIdentificacao": 1, + } + ], + } + self.mock_responses.add( + responses.POST, + request_url, + headers=self._build_authorization_header(1), + json=expected_json, + ) + + response = PagamentoLoteBBWrapper().criar_transferencia_pix( + "123", "345", "678", "X", "19042023", "11", 1, "11", "985732102", None, None, None, None, "Teste telefone") + + self.assertEqual(request_url, response.url) + self.assertEqual(self._get_headers(), response.headers) + self.assertEqual(expected_json, response.json()) + self.assertEqual(2, self.total_requests()) + self.mock_responses.assert_call_count(request_url, 1) From e1c6b249559fe781e78b623f7a19520e86bc8df7 Mon Sep 17 00:00:00 2001 From: Pedro Fonseca Date: Wed, 19 Apr 2023 22:04:17 -0300 Subject: [PATCH 003/139] exemplo de transferencia pix --- .../transferencia_pix_chave_aleatoria.json | 35 +++++++++++++++++++ .../transferencia_pix_chave_aleatoria.py | 31 ++++++++++++++++ 2 files changed, 66 insertions(+) create mode 100644 examples/lotes_pagamento/data/transferencia_pix_chave_aleatoria.json create mode 100644 examples/lotes_pagamento/transferencia_pix_chave_aleatoria.py diff --git a/examples/lotes_pagamento/data/transferencia_pix_chave_aleatoria.json b/examples/lotes_pagamento/data/transferencia_pix_chave_aleatoria.json new file mode 100644 index 00000000..6d20de6a --- /dev/null +++ b/examples/lotes_pagamento/data/transferencia_pix_chave_aleatoria.json @@ -0,0 +1,35 @@ +{ + "numeroRequisicao": 921347, + "estadoRequisicao": 1, + "quantidadeTransferencias": 1, + "valorTransferencias": 15.5, + "quantidadeTransferenciasValidas": 1, + "valorTransferenciasValidas": 15.5, + "listaTransferencias": [ + { + "identificadorPagamento": 90921347731030000, + "data": 19042023, + "valor": 15.5, + "documentoDebito": 0, + "documentoCredito": 0, + "descricaoPagamento": "nova transferencia", + "descricaoPagamentoInstantaneo": "", + "formaIdentificacao": 4, + "dddTelefone": 0, + "telefone": 0, + "email": "", + "cpf": 0, + "cnpj": 0, + "identificacaoAleatoria": "d14d32de-b3b9-4c31-9f89-8df2cec92c50", + "numeroCOMPE": 0, + "numeroISPB": 0, + "tipoConta": 0, + "agencia": 0, + "conta": 0, + "digitoVerificadorConta": "", + "contaPagamento": "", + "indicadorMovimentoAceito": "S", + "erros": [] + } + ] +} \ No newline at end of file diff --git a/examples/lotes_pagamento/transferencia_pix_chave_aleatoria.py b/examples/lotes_pagamento/transferencia_pix_chave_aleatoria.py new file mode 100644 index 00000000..e93330c2 --- /dev/null +++ b/examples/lotes_pagamento/transferencia_pix_chave_aleatoria.py @@ -0,0 +1,31 @@ +import os +from datetime import date + +from examples.utils import dump_response + +from bb_wrapper.wrapper import PagamentoLoteBBWrapper + +c = PagamentoLoteBBWrapper(cert=("./certs/cert.pem", "./certs/key.pem")) + + +today = date.today() +bb_fmt = "%d%m%Y" + + +lote_data = { + "n_requisicao": 921347, + "agencia": 1607, + "conta": 99738672, + "dv_conta": "X", +} + +transferencia_data = { + "descricao": "nova transferencia", + "data_transferencia": today.strftime(bb_fmt), + "valor_transferencia": 15.50, + "forma_id": 4, + "chave_aleatoria": "d14d32de-b3b9-4c31-9f89-8df2cec92c50", +} + +response = c.criar_transferencia_pix(**lote_data, **transferencia_data) +dump_response(response, os.path.realpath(__file__)) From 5121f2dbfdd90f066ada83c3ad50439c74ce7511 Mon Sep 17 00:00:00 2001 From: Pedro Fonseca Date: Wed, 19 Apr 2023 22:49:35 -0300 Subject: [PATCH 004/139] formatacao e remocao de pdb --- bb_wrapper/wrapper/pagamento_lote.py | 6 +-- tests/wrapper/test_pagamentos.py | 71 +++++++++++++++++++++++----- 2 files changed, 62 insertions(+), 15 deletions(-) diff --git a/bb_wrapper/wrapper/pagamento_lote.py b/bb_wrapper/wrapper/pagamento_lote.py index ba6800d2..f8395192 100644 --- a/bb_wrapper/wrapper/pagamento_lote.py +++ b/bb_wrapper/wrapper/pagamento_lote.py @@ -15,7 +15,8 @@ class PagamentoLoteBBWrapper(BaseBBWrapper): """ Wrapper da API Pagamentos em Lote """ - SCOPE = "pagamentos-lote.lotes-requisicao pagamentos-lote.transferencias-info pagamentos-lote.transferencias-requisicao pagamentos-lote.cancelar-requisicao pagamentos-lote.devolvidos-info pagamentos-lote.lotes-info pagamentos-lote.pagamentos-guias-sem-codigo-barras-info pagamentos-lote.pagamentos-info pagamentos-lote.pagamentos-guias-sem-codigo-barras-requisicao pagamentos-lote.pagamentos-codigo-barras-info pagamentos-lote.boletos-requisicao pagamentos-lote.guias-codigo-barras-info pagamentos-lote.guias-codigo-barras-requisicao pagamentos-lote.transferencias-pix-requisicao" # noqa + + SCOPE = "pagamentos-lote.lotes-requisicao pagamentos-lote.transferencias-info pagamentos-lote.transferencias-requisicao pagamentos-lote.cancelar-requisicao pagamentos-lote.devolvidos-info pagamentos-lote.lotes-info pagamentos-lote.pagamentos-guias-sem-codigo-barras-info pagamentos-lote.pagamentos-info pagamentos-lote.pagamentos-guias-sem-codigo-barras-requisicao pagamentos-lote.pagamentos-codigo-barras-info pagamentos-lote.boletos-requisicao pagamentos-lote.guias-codigo-barras-info pagamentos-lote.guias-codigo-barras-requisicao pagamentos-lote.transferencias-pix-requisicao" # noqa BASE_PROD_ADDITION = "-ip" BASE_DOMAIN = ".bb.com.br/pagamentos-lote/v1" @@ -530,7 +531,7 @@ def _criar_dados_transferencia_pix( transferencia_data["identificacaoAleatoria"] = chave_aleatoria return {**lote_data, "listaTransferencias": [{**transferencia_data}]} - + def criar_transferencia_pix( self, n_requisicao, @@ -592,7 +593,6 @@ def criar_transferencia_pix( descricao, tipo_pagamento, ) - import pdb; pdb.set_trace() url = self._construct_url("lotes-transferencias-pix") response = self._post(url, data) diff --git a/tests/wrapper/test_pagamentos.py b/tests/wrapper/test_pagamentos.py index 75ed47a9..8965509f 100644 --- a/tests/wrapper/test_pagamentos.py +++ b/tests/wrapper/test_pagamentos.py @@ -451,8 +451,10 @@ def test_criar_transferencia_pix_chave_aleatoria(self): """ Teste para verificar a URL da requisição e dados """ - - request_url = PagamentoLoteBBWrapper()._construct_url("lotes-transferencias-pix") + + request_url = PagamentoLoteBBWrapper()._construct_url( + "lotes-transferencias-pix" + ) expected_json = { "numeroRequisicao": "123", "agenciaDebito": "345", @@ -475,9 +477,22 @@ def test_criar_transferencia_pix_chave_aleatoria(self): headers=self._build_authorization_header(1), json=expected_json, ) - + response = PagamentoLoteBBWrapper().criar_transferencia_pix( - "123", "345", "678", "X", "19042023", "11", 4, None, None, None, None, None, "d14d32de-b3b9-4c31-9f89-8df2cec92c50", "Pagamento" + "123", + "345", + "678", + "X", + "19042023", + "11", + 4, + None, + None, + None, + None, + None, + "d14d32de-b3b9-4c31-9f89-8df2cec92c50", + "Pagamento", ) self.assertEqual(request_url, response.url) @@ -490,8 +505,10 @@ def test_criar_transferencia_pix_email(self): """ Teste para verificar a URL da requisição e dados """ - - request_url = PagamentoLoteBBWrapper()._construct_url("lotes-transferencias-pix") + + request_url = PagamentoLoteBBWrapper()._construct_url( + "lotes-transferencias-pix" + ) expected_json = { "numeroRequisicao": "123", "agenciaDebito": "345", @@ -514,9 +531,23 @@ def test_criar_transferencia_pix_email(self): headers=self._build_authorization_header(1), json=expected_json, ) - + response = PagamentoLoteBBWrapper().criar_transferencia_pix( - "123", "345", "678", "X", "19042023", "11", 2, None, None, "testqrcode01@bb.com.br", None, None, None, "Teste transfer") + "123", + "345", + "678", + "X", + "19042023", + "11", + 2, + None, + None, + "testqrcode01@bb.com.br", + None, + None, + None, + "Teste transfer", + ) self.assertEqual(request_url, response.url) self.assertEqual(self._get_headers(), response.headers) @@ -528,8 +559,10 @@ def test_criar_transferencia_pix_telefone(self): """ Teste para verificar a URL da requisição e dados """ - - request_url = PagamentoLoteBBWrapper()._construct_url("lotes-transferencias-pix") + + request_url = PagamentoLoteBBWrapper()._construct_url( + "lotes-transferencias-pix" + ) expected_json = { "numeroRequisicao": "123", "agenciaDebito": "345", @@ -553,9 +586,23 @@ def test_criar_transferencia_pix_telefone(self): headers=self._build_authorization_header(1), json=expected_json, ) - + response = PagamentoLoteBBWrapper().criar_transferencia_pix( - "123", "345", "678", "X", "19042023", "11", 1, "11", "985732102", None, None, None, None, "Teste telefone") + "123", + "345", + "678", + "X", + "19042023", + "11", + 1, + "11", + "985732102", + None, + None, + None, + None, + "Teste telefone", + ) self.assertEqual(request_url, response.url) self.assertEqual(self._get_headers(), response.headers) From cbcc864cd1e7fa9810bf8c41b47683e5486af004 Mon Sep 17 00:00:00 2001 From: Pedro Fonseca <32584628+peidrao@users.noreply.github.com> Date: Thu, 20 Apr 2023 12:14:37 -0300 Subject: [PATCH 005/139] Update tests/wrapper/test_pagamentos.py Co-authored-by: Breno Viana --- tests/wrapper/test_pagamentos.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/wrapper/test_pagamentos.py b/tests/wrapper/test_pagamentos.py index 8965509f..c1126507 100644 --- a/tests/wrapper/test_pagamentos.py +++ b/tests/wrapper/test_pagamentos.py @@ -503,7 +503,7 @@ def test_criar_transferencia_pix_chave_aleatoria(self): def test_criar_transferencia_pix_email(self): """ - Teste para verificar a URL da requisição e dados + Teste para verificar a URL da requisição e dados de transferência PIX email """ request_url = PagamentoLoteBBWrapper()._construct_url( From dca8256b1f8a4eb3ae6e81b14ccc86b70f63d918 Mon Sep 17 00:00:00 2001 From: Pedro Fonseca <32584628+peidrao@users.noreply.github.com> Date: Thu, 20 Apr 2023 12:17:30 -0300 Subject: [PATCH 006/139] Update tests/wrapper/test_pagamentos.py Co-authored-by: Breno Viana --- tests/wrapper/test_pagamentos.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/wrapper/test_pagamentos.py b/tests/wrapper/test_pagamentos.py index c1126507..74e905a1 100644 --- a/tests/wrapper/test_pagamentos.py +++ b/tests/wrapper/test_pagamentos.py @@ -557,7 +557,7 @@ def test_criar_transferencia_pix_email(self): def test_criar_transferencia_pix_telefone(self): """ - Teste para verificar a URL da requisição e dados + Teste para verificar a URL da requisição e dados de transferência PIX telefone """ request_url = PagamentoLoteBBWrapper()._construct_url( From 33b6c340553c4a0b614ba77d2c0dd8db7a592356 Mon Sep 17 00:00:00 2001 From: Pedro Fonseca <32584628+peidrao@users.noreply.github.com> Date: Thu, 20 Apr 2023 12:19:39 -0300 Subject: [PATCH 007/139] Update tests/wrapper/test_pagamentos.py Co-authored-by: Breno Viana --- tests/wrapper/test_pagamentos.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/wrapper/test_pagamentos.py b/tests/wrapper/test_pagamentos.py index 74e905a1..58390233 100644 --- a/tests/wrapper/test_pagamentos.py +++ b/tests/wrapper/test_pagamentos.py @@ -449,7 +449,7 @@ def test_consultar_pagamento_tributo_1(self): def test_criar_transferencia_pix_chave_aleatoria(self): """ - Teste para verificar a URL da requisição e dados + Teste para verificar a URL da requisição e dados de transferência PIX chave aleatória """ request_url = PagamentoLoteBBWrapper()._construct_url( From 216dd29fabdb5970df255ad880d759b9abad4710 Mon Sep 17 00:00:00 2001 From: Pedro Fonseca Date: Thu, 20 Apr 2023 12:22:07 -0300 Subject: [PATCH 008/139] fmt --- bb_wrapper/wrapper/pagamento_lote.py | 8 +-- .../transferencia_pix_chave_aleatoria.json | 68 +++++++++---------- 2 files changed, 38 insertions(+), 38 deletions(-) diff --git a/bb_wrapper/wrapper/pagamento_lote.py b/bb_wrapper/wrapper/pagamento_lote.py index f8395192..a9ad63d4 100644 --- a/bb_wrapper/wrapper/pagamento_lote.py +++ b/bb_wrapper/wrapper/pagamento_lote.py @@ -570,10 +570,10 @@ def criar_transferencia_pix( telefone: Telefone do recebedor. Obrigatório caso forma_id seja igual 1 email: Email do recebedor. Obrigatório caso forma_id seja igual 2 cpf: CPF do recebedor. - Opcional caso forma_id seja igual a 1 ou 2 e caso o campo cnpj não seja informado - Obrigatório caso forma_id seja igual a 3 ou 5 e caso o campo cnpj não seja informado - cnpj: CNPJ do recebedor: Tem os mesmos casos de Obrigatório e opcional do cpf - chave_aleatoria: Chave aleatória gerada pelo recebedor. Obrigatório caso forma_id seja igual 4 + Opcional caso forma_id seja igual a 1 ou 2 e caso o campo cnpj não seja informado # noqa: E501 + Obrigatório caso forma_id seja igual a 3 ou 5 e caso o campo cnpj não seja informado # noqa: E501 + cnpj: CNPJ do recebedor: Tem os mesmos casos de Obrigatório e opcional do cpf # noqa: E501 + chave_aleatoria: Chave aleatória gerada pelo recebedor. Obrigatório caso forma_id seja igual 4 # noqa: E501 descricao: Campo de uso livre pelo cliente """ data = self._criar_dados_transferencia_pix( diff --git a/examples/lotes_pagamento/data/transferencia_pix_chave_aleatoria.json b/examples/lotes_pagamento/data/transferencia_pix_chave_aleatoria.json index 6d20de6a..204ab004 100644 --- a/examples/lotes_pagamento/data/transferencia_pix_chave_aleatoria.json +++ b/examples/lotes_pagamento/data/transferencia_pix_chave_aleatoria.json @@ -1,35 +1,35 @@ { - "numeroRequisicao": 921347, - "estadoRequisicao": 1, - "quantidadeTransferencias": 1, - "valorTransferencias": 15.5, - "quantidadeTransferenciasValidas": 1, - "valorTransferenciasValidas": 15.5, - "listaTransferencias": [ - { - "identificadorPagamento": 90921347731030000, - "data": 19042023, - "valor": 15.5, - "documentoDebito": 0, - "documentoCredito": 0, - "descricaoPagamento": "nova transferencia", - "descricaoPagamentoInstantaneo": "", - "formaIdentificacao": 4, - "dddTelefone": 0, - "telefone": 0, - "email": "", - "cpf": 0, - "cnpj": 0, - "identificacaoAleatoria": "d14d32de-b3b9-4c31-9f89-8df2cec92c50", - "numeroCOMPE": 0, - "numeroISPB": 0, - "tipoConta": 0, - "agencia": 0, - "conta": 0, - "digitoVerificadorConta": "", - "contaPagamento": "", - "indicadorMovimentoAceito": "S", - "erros": [] - } - ] -} \ No newline at end of file + "numeroRequisicao": 921347, + "estadoRequisicao": 1, + "quantidadeTransferencias": 1, + "valorTransferencias": 15.5, + "quantidadeTransferenciasValidas": 1, + "valorTransferenciasValidas": 15.5, + "listaTransferencias": [ + { + "identificadorPagamento": 90921347731030000, + "data": 19042023, + "valor": 15.5, + "documentoDebito": 0, + "documentoCredito": 0, + "descricaoPagamento": "nova transferencia", + "descricaoPagamentoInstantaneo": "", + "formaIdentificacao": 4, + "dddTelefone": 0, + "telefone": 0, + "email": "", + "cpf": 0, + "cnpj": 0, + "identificacaoAleatoria": "d14d32de-b3b9-4c31-9f89-8df2cec92c50", + "numeroCOMPE": 0, + "numeroISPB": 0, + "tipoConta": 0, + "agencia": 0, + "conta": 0, + "digitoVerificadorConta": "", + "contaPagamento": "", + "indicadorMovimentoAceito": "S", + "erros": [] + } + ] +} From cec80e5ff1c17c8f1f1a51a689ff367ff373d922 Mon Sep 17 00:00:00 2001 From: Pedro Fonseca Date: Thu, 20 Apr 2023 12:26:22 -0300 Subject: [PATCH 009/139] adicao de novos escopo de autorizacao do pix --- bb_wrapper/wrapper/pagamento_lote.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bb_wrapper/wrapper/pagamento_lote.py b/bb_wrapper/wrapper/pagamento_lote.py index a9ad63d4..023e8ddd 100644 --- a/bb_wrapper/wrapper/pagamento_lote.py +++ b/bb_wrapper/wrapper/pagamento_lote.py @@ -16,7 +16,7 @@ class PagamentoLoteBBWrapper(BaseBBWrapper): Wrapper da API Pagamentos em Lote """ - SCOPE = "pagamentos-lote.lotes-requisicao pagamentos-lote.transferencias-info pagamentos-lote.transferencias-requisicao pagamentos-lote.cancelar-requisicao pagamentos-lote.devolvidos-info pagamentos-lote.lotes-info pagamentos-lote.pagamentos-guias-sem-codigo-barras-info pagamentos-lote.pagamentos-info pagamentos-lote.pagamentos-guias-sem-codigo-barras-requisicao pagamentos-lote.pagamentos-codigo-barras-info pagamentos-lote.boletos-requisicao pagamentos-lote.guias-codigo-barras-info pagamentos-lote.guias-codigo-barras-requisicao pagamentos-lote.transferencias-pix-requisicao" # noqa + SCOPE = "pagamentos-lote.lotes-requisicao pagamentos-lote.transferencias-info pagamentos-lote.transferencias-requisicao pagamentos-lote.cancelar-requisicao pagamentos-lote.devolvidos-info pagamentos-lote.lotes-info pagamentos-lote.pagamentos-guias-sem-codigo-barras-info pagamentos-lote.pagamentos-info pagamentos-lote.pagamentos-guias-sem-codigo-barras-requisicao pagamentos-lote.pagamentos-codigo-barras-info pagamentos-lote.boletos-requisicao pagamentos-lote.guias-codigo-barras-info pagamentos-lote.guias-codigo-barras-requisicao pagamentos-lote.transferencias-pix-requisicao pagamentos-lote.transferencias-pix-info pagamentos-lote.pix-info" # noqa BASE_PROD_ADDITION = "-ip" BASE_DOMAIN = ".bb.com.br/pagamentos-lote/v1" From dbf4d761f584a0fb0a08958708c4cf3da1d61e3f Mon Sep 17 00:00:00 2001 From: Pedro Fonseca Date: Thu, 20 Apr 2023 13:54:08 -0300 Subject: [PATCH 010/139] fix testes --- bb_wrapper/wrapper/pagamento_lote.py | 3 ++- tests/wrapper/test_pagamentos.py | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/bb_wrapper/wrapper/pagamento_lote.py b/bb_wrapper/wrapper/pagamento_lote.py index 023e8ddd..73604622 100644 --- a/bb_wrapper/wrapper/pagamento_lote.py +++ b/bb_wrapper/wrapper/pagamento_lote.py @@ -16,7 +16,8 @@ class PagamentoLoteBBWrapper(BaseBBWrapper): Wrapper da API Pagamentos em Lote """ - SCOPE = "pagamentos-lote.lotes-requisicao pagamentos-lote.transferencias-info pagamentos-lote.transferencias-requisicao pagamentos-lote.cancelar-requisicao pagamentos-lote.devolvidos-info pagamentos-lote.lotes-info pagamentos-lote.pagamentos-guias-sem-codigo-barras-info pagamentos-lote.pagamentos-info pagamentos-lote.pagamentos-guias-sem-codigo-barras-requisicao pagamentos-lote.pagamentos-codigo-barras-info pagamentos-lote.boletos-requisicao pagamentos-lote.guias-codigo-barras-info pagamentos-lote.guias-codigo-barras-requisicao pagamentos-lote.transferencias-pix-requisicao pagamentos-lote.transferencias-pix-info pagamentos-lote.pix-info" # noqa + SCOPE = "pagamentos-lote.lotes-requisicao pagamentos-lote.transferencias-info pagamentos-lote.transferencias-requisicao pagamentos-lote.cancelar-requisicao pagamentos-lote.devolvidos-info pagamentos-lote.lotes-info pagamentos-lote.pagamentos-guias-sem-codigo-barras-info pagamentos-lote.pagamentos-info pagamentos-lote.pagamentos-guias-sem-codigo-barras-requisicao pagamentos-lote.pagamentos-codigo-barras-info pagamentos-lote.boletos-requisicao pagamentos-lote.guias-codigo-barras-info pagamentos-lote.guias-codigo-barras-requisicao pagamentos-lote.boletos-info pagamentos-lote.transferencias-pix-requisicao pagamentos-lote.transferencias-pix-info pagamentos-lote.pix-info" # noqa + BASE_PROD_ADDITION = "-ip" BASE_DOMAIN = ".bb.com.br/pagamentos-lote/v1" diff --git a/tests/wrapper/test_pagamentos.py b/tests/wrapper/test_pagamentos.py index 58390233..37e07bea 100644 --- a/tests/wrapper/test_pagamentos.py +++ b/tests/wrapper/test_pagamentos.py @@ -449,7 +449,7 @@ def test_consultar_pagamento_tributo_1(self): def test_criar_transferencia_pix_chave_aleatoria(self): """ - Teste para verificar a URL da requisição e dados de transferência PIX chave aleatória + Teste para verificar a URL da requisição 43e dados de transferência PIX chave aleatória # noqa """ request_url = PagamentoLoteBBWrapper()._construct_url( From 558871da8ed416f5d53997486083af5b93e25137 Mon Sep 17 00:00:00 2001 From: Pedro Fonseca Date: Thu, 20 Apr 2023 13:57:10 -0300 Subject: [PATCH 011/139] fmt --- bb_wrapper/wrapper/pagamento_lote.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bb_wrapper/wrapper/pagamento_lote.py b/bb_wrapper/wrapper/pagamento_lote.py index 73604622..a7fae68a 100644 --- a/bb_wrapper/wrapper/pagamento_lote.py +++ b/bb_wrapper/wrapper/pagamento_lote.py @@ -17,7 +17,7 @@ class PagamentoLoteBBWrapper(BaseBBWrapper): """ SCOPE = "pagamentos-lote.lotes-requisicao pagamentos-lote.transferencias-info pagamentos-lote.transferencias-requisicao pagamentos-lote.cancelar-requisicao pagamentos-lote.devolvidos-info pagamentos-lote.lotes-info pagamentos-lote.pagamentos-guias-sem-codigo-barras-info pagamentos-lote.pagamentos-info pagamentos-lote.pagamentos-guias-sem-codigo-barras-requisicao pagamentos-lote.pagamentos-codigo-barras-info pagamentos-lote.boletos-requisicao pagamentos-lote.guias-codigo-barras-info pagamentos-lote.guias-codigo-barras-requisicao pagamentos-lote.boletos-info pagamentos-lote.transferencias-pix-requisicao pagamentos-lote.transferencias-pix-info pagamentos-lote.pix-info" # noqa - + BASE_PROD_ADDITION = "-ip" BASE_DOMAIN = ".bb.com.br/pagamentos-lote/v1" From e9d83cc3adc488d60e4c88103be0f34efd4eb61a Mon Sep 17 00:00:00 2001 From: Pedro Fonseca <32584628+peidrao@users.noreply.github.com> Date: Thu, 20 Apr 2023 14:05:03 -0300 Subject: [PATCH 012/139] Update tests/wrapper/test_pagamentos.py Co-authored-by: Breno Viana --- tests/wrapper/test_pagamentos.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/wrapper/test_pagamentos.py b/tests/wrapper/test_pagamentos.py index 37e07bea..c57734f0 100644 --- a/tests/wrapper/test_pagamentos.py +++ b/tests/wrapper/test_pagamentos.py @@ -449,7 +449,7 @@ def test_consultar_pagamento_tributo_1(self): def test_criar_transferencia_pix_chave_aleatoria(self): """ - Teste para verificar a URL da requisição 43e dados de transferência PIX chave aleatória # noqa + Teste para verificar a URL da requisição e dados de transferência PIX chave aleatória # noqa """ request_url = PagamentoLoteBBWrapper()._construct_url( From f088f9e908fc5dfbd7dafa9877277afb9309ac9a Mon Sep 17 00:00:00 2001 From: Pedro Fonseca Date: Thu, 20 Apr 2023 14:49:44 -0300 Subject: [PATCH 013/139] adicao de exemplo de trasnferencia usando cpf --- .../data/transferencia_pix_cpf.json | 35 +++++++++++++++++++ .../lotes_pagamento/transferencia_pix_cpf.py | 31 ++++++++++++++++ 2 files changed, 66 insertions(+) create mode 100644 examples/lotes_pagamento/data/transferencia_pix_cpf.json create mode 100644 examples/lotes_pagamento/transferencia_pix_cpf.py diff --git a/examples/lotes_pagamento/data/transferencia_pix_cpf.json b/examples/lotes_pagamento/data/transferencia_pix_cpf.json new file mode 100644 index 00000000..b88f6f7b --- /dev/null +++ b/examples/lotes_pagamento/data/transferencia_pix_cpf.json @@ -0,0 +1,35 @@ +{ + "numeroRequisicao": 9221347, + "estadoRequisicao": 1, + "quantidadeTransferencias": 1, + "valorTransferencias": 7999.99, + "quantidadeTransferenciasValidas": 1, + "valorTransferenciasValidas": 7999.99, + "listaTransferencias": [ + { + "identificadorPagamento": 99221347731030000, + "data": 20042023, + "valor": 7999.99, + "documentoDebito": 0, + "documentoCredito": 0, + "descricaoPagamento": "transferencia CPF", + "descricaoPagamentoInstantaneo": "", + "formaIdentificacao": 3, + "dddTelefone": 0, + "telefone": 0, + "email": "", + "cpf": 28779295827, + "cnpj": 0, + "identificacaoAleatoria": "", + "numeroCOMPE": 0, + "numeroISPB": 0, + "tipoConta": 0, + "agencia": 0, + "conta": 0, + "digitoVerificadorConta": "", + "contaPagamento": "", + "indicadorMovimentoAceito": "S", + "erros": [] + } + ] +} \ No newline at end of file diff --git a/examples/lotes_pagamento/transferencia_pix_cpf.py b/examples/lotes_pagamento/transferencia_pix_cpf.py new file mode 100644 index 00000000..4b01212b --- /dev/null +++ b/examples/lotes_pagamento/transferencia_pix_cpf.py @@ -0,0 +1,31 @@ +import os +from datetime import date + +from examples.utils import dump_response + +from bb_wrapper.wrapper import PagamentoLoteBBWrapper + +c = PagamentoLoteBBWrapper(cert=("./certs/cert.pem", "./certs/key.pem")) + + +today = date.today() +bb_fmt = "%d%m%Y" + + +lote_data = { + "n_requisicao": 9221347, + "agencia": 1607, + "conta": 99738672, + "dv_conta": "X", +} + +transferencia_data = { + "descricao": "transferencia CPF", + "data_transferencia": today.strftime(bb_fmt), + "valor_transferencia":7999.99, + "forma_id": 3, + "cpf": "28779295827", +} + +response = c.criar_transferencia_pix(**lote_data, **transferencia_data) +dump_response(response, os.path.realpath(__file__)) From 7168239801656d64b2897387ba7c0f49feec3a71 Mon Sep 17 00:00:00 2001 From: Pedro Fonseca Date: Thu, 20 Apr 2023 17:16:21 -0300 Subject: [PATCH 014/139] adicao de wrapper para consulta de pix --- bb_wrapper/wrapper/pagamento_lote.py | 7 ++++ .../consultar_transferencia_pix.py | 16 +++++++++ .../data/consultar_transferencia_pix.json | 35 +++++++++++++++++++ 3 files changed, 58 insertions(+) create mode 100644 examples/lotes_pagamento/consultar_transferencia_pix.py create mode 100644 examples/lotes_pagamento/data/consultar_transferencia_pix.json diff --git a/bb_wrapper/wrapper/pagamento_lote.py b/bb_wrapper/wrapper/pagamento_lote.py index a7fae68a..b2c77681 100644 --- a/bb_wrapper/wrapper/pagamento_lote.py +++ b/bb_wrapper/wrapper/pagamento_lote.py @@ -598,3 +598,10 @@ def criar_transferencia_pix( response = self._post(url, data) return response + + def consultar_transferencia_pix(self, _id): + url = self._construct_url("lotes-transferencias-pix", _id, "solicitacao") + + response = self._get(url) + + return response diff --git a/examples/lotes_pagamento/consultar_transferencia_pix.py b/examples/lotes_pagamento/consultar_transferencia_pix.py new file mode 100644 index 00000000..e4d6418b --- /dev/null +++ b/examples/lotes_pagamento/consultar_transferencia_pix.py @@ -0,0 +1,16 @@ +import os + +from examples.utils import dump_response + +from bb_wrapper.wrapper import PagamentoLoteBBWrapper + +c = PagamentoLoteBBWrapper(cert=("./certs/cert.pem", "./certs/key.pem")) + +_id = "9221347" + + +response = c.consultar_transferencia_pix( + _id, +) + +dump_response(response, os.path.realpath(__file__)) diff --git a/examples/lotes_pagamento/data/consultar_transferencia_pix.json b/examples/lotes_pagamento/data/consultar_transferencia_pix.json new file mode 100644 index 00000000..603a354a --- /dev/null +++ b/examples/lotes_pagamento/data/consultar_transferencia_pix.json @@ -0,0 +1,35 @@ +{ + "numeroRequisicao": 9221347, + "estadoRequisicao": 4, + "quantidadeTransferencias": 1, + "valorTransferencias": 7999.99, + "quantidadeTransferenciasValidas": 1, + "valorTransferenciasValidas": 7999.99, + "listaTransferencias": [ + { + "identificadorPagamento": 99221347731030000, + "data": 20042023, + "valor": 7999.99, + "documentoDebito": 0, + "documentoCredito": 0, + "descricaoPagamento": "transferencia CPF", + "descricaoPagamentoInstantaneo": "", + "formaIdentificacao": 3, + "dddTelefone": 0, + "telefone": 0, + "email": "", + "cpf": 28779295827, + "cnpj": 0, + "identificacaoAleatoria": "", + "numeroCOMPE": 0, + "numeroISPB": 0, + "tipoConta": 0, + "agencia": 0, + "conta": 0, + "digitoVerificadorConta": "", + "contaPagamento": "", + "indicadorMovimentoAceito": "S", + "erros": [] + } + ] +} From 08b50a6fabc72d760f36437c0b9fd85b55c09c07 Mon Sep 17 00:00:00 2001 From: Pedro Fonseca Date: Thu, 20 Apr 2023 18:03:56 -0300 Subject: [PATCH 015/139] testes no service de pix --- bb_wrapper/services/__init__.py | 1 + bb_wrapper/services/pix.py | 3 +- .../data/transferencia_pix_cpf.json | 66 ++++----- tests/services/test_identify_key_type.py | 128 +++++++++++++++++ tests/wrapper/test_pagamentos.py | 130 ++++++++++++++++++ 5 files changed, 294 insertions(+), 34 deletions(-) create mode 100644 tests/services/test_identify_key_type.py diff --git a/bb_wrapper/services/__init__.py b/bb_wrapper/services/__init__.py index e70b3cc5..643fa06c 100644 --- a/bb_wrapper/services/__init__.py +++ b/bb_wrapper/services/__init__.py @@ -4,6 +4,7 @@ from .barcode import BarcodeService from .mod import ModService # noqa: F401 from .pixcode import PixCodeService # noqa: F401 +from .pix import PixService # noqa: F401 parse_unicode_to_alphanumeric = UnicodeService().parse_unicode_to_alphanumeric diff --git a/bb_wrapper/services/pix.py b/bb_wrapper/services/pix.py index fb12571f..a1ea1ccd 100644 --- a/bb_wrapper/services/pix.py +++ b/bb_wrapper/services/pix.py @@ -32,11 +32,12 @@ def identify_key_type(self, key: str): is_document = cpfcnpj.validate(key) # 3 - is_phone = key_len == 11 and key[2] == "9" + is_phone = key_len == 9 and key[0] == "9" # 4 try: is_uuid = uuid.UUID(key) + is_uuid = True except ValueError: is_uuid = False diff --git a/examples/lotes_pagamento/data/transferencia_pix_cpf.json b/examples/lotes_pagamento/data/transferencia_pix_cpf.json index b88f6f7b..6f64c6b8 100644 --- a/examples/lotes_pagamento/data/transferencia_pix_cpf.json +++ b/examples/lotes_pagamento/data/transferencia_pix_cpf.json @@ -1,35 +1,35 @@ { - "numeroRequisicao": 9221347, - "estadoRequisicao": 1, - "quantidadeTransferencias": 1, - "valorTransferencias": 7999.99, - "quantidadeTransferenciasValidas": 1, - "valorTransferenciasValidas": 7999.99, - "listaTransferencias": [ - { - "identificadorPagamento": 99221347731030000, - "data": 20042023, - "valor": 7999.99, - "documentoDebito": 0, - "documentoCredito": 0, - "descricaoPagamento": "transferencia CPF", - "descricaoPagamentoInstantaneo": "", - "formaIdentificacao": 3, - "dddTelefone": 0, - "telefone": 0, - "email": "", - "cpf": 28779295827, - "cnpj": 0, - "identificacaoAleatoria": "", - "numeroCOMPE": 0, - "numeroISPB": 0, - "tipoConta": 0, - "agencia": 0, - "conta": 0, - "digitoVerificadorConta": "", - "contaPagamento": "", - "indicadorMovimentoAceito": "S", - "erros": [] - } - ] + "numeroRequisicao": 9221347, + "estadoRequisicao": 1, + "quantidadeTransferencias": 1, + "valorTransferencias": 7999.99, + "quantidadeTransferenciasValidas": 1, + "valorTransferenciasValidas": 7999.99, + "listaTransferencias": [ + { + "identificadorPagamento": 99221347731030000, + "data": 20042023, + "valor": 7999.99, + "documentoDebito": 0, + "documentoCredito": 0, + "descricaoPagamento": "transferencia CPF", + "descricaoPagamentoInstantaneo": "", + "formaIdentificacao": 3, + "dddTelefone": 0, + "telefone": 0, + "email": "", + "cpf": 28779295827, + "cnpj": 0, + "identificacaoAleatoria": "", + "numeroCOMPE": 0, + "numeroISPB": 0, + "tipoConta": 0, + "agencia": 0, + "conta": 0, + "digitoVerificadorConta": "", + "contaPagamento": "", + "indicadorMovimentoAceito": "S", + "erros": [] + } + ] } \ No newline at end of file diff --git a/tests/services/test_identify_key_type.py b/tests/services/test_identify_key_type.py new file mode 100644 index 00000000..205e2bb2 --- /dev/null +++ b/tests/services/test_identify_key_type.py @@ -0,0 +1,128 @@ +from unittest import TestCase + +from bb_wrapper.services.pix import PixService + + +class PixServiceTestCase(TestCase): + + def test_is_email(self): + """ + Dado: + - Dado uma string 'test@test.com' + Quando: + - for chamado PixService().identify_key_type('test@test.com') + Então: + - o resultado deve ser 2 + """ + email = "test@test.com" + + result = PixService().identify_key_type(email) + + expected = 2 + + self.assertEqual(result, expected) + + def test_is_phone(self): + """ + Dado: + - Dado uma string 'phone' + Quando: + - for chamado PixService().identify_key_type(phone) + Então: + - o resultado deve ser 1 + """ + phone = "999887766" + + result = PixService().identify_key_type(phone) + + expected = 1 + + self.assertEqual(result, expected) + + def test_is_uuid(self): + """ + Dado: + - Dado uma string 'uuid' + Quando: + - for chamado PixService().identify_key_type(uuid) + Então: + - o resultado deve ser 4 + """ + uuid = "45abb60a-6253-4f22-802b-0d84045ea76a" + + result = PixService().identify_key_type(uuid) + + expected = 4 + + self.assertEqual(result, expected) + + def test_is_cnpj(self): + """ + Dado: + - Dado uma string 'cnpj' + Quando: + - for chamado PixService().identify_key_type(cnpj) + Então: + - o resultado deve ser 4 + """ + cnpj = "03794722000153" + + result = PixService().identify_key_type(cnpj) + + expected = 3 + + self.assertEqual(result, expected) + + def test_is_cpf(self): + """ + Dado: + - Dado uma string 'cpf' + Quando: + - for chamado PixService().identify_key_type(cpf) + Então: + - o resultado deve ser 4 + """ + cpf = "43166663045" + + result = PixService().identify_key_type(cpf) + + expected = 3 + + self.assertEqual(result, expected) + + def test_is_not_key(self): + """ + Dado: + - Dado uma string 'key_invalid' + Quando: + - for chamado PixService().identify_key_type(key_invalid) + Então: + - deve ser lançado um ValueError com + "Tipo de chave não identificado" + """ + key_invalid = "1" + + with self.assertRaises(ValueError) as ctx: + PixService().identify_key_type(key_invalid) + + self.assertEqual(ctx.exception.args[0], "Tipo de chave não identificado") + + def test_key_invalid(self): + """ + Dado: + - Dado uma string + - que tenha um '@' + - comece com '9' + - tenha 9 digitos + Quando: + - for chamado PixService().identify_key_type(key_invalid) + Então: + - deve ser lançado um ValueError com + "Tipo de chave não identificado" + """ + key_invalid = "999@@7766" + + with self.assertRaises(ValueError) as ctx: + PixService().identify_key_type(key_invalid) + + self.assertEqual(ctx.exception.args[0], "A chave utilizada pode ser mais de um tipo!") \ No newline at end of file diff --git a/tests/wrapper/test_pagamentos.py b/tests/wrapper/test_pagamentos.py index c57734f0..4e1fdc83 100644 --- a/tests/wrapper/test_pagamentos.py +++ b/tests/wrapper/test_pagamentos.py @@ -609,3 +609,133 @@ def test_criar_transferencia_pix_telefone(self): self.assertEqual(expected_json, response.json()) self.assertEqual(2, self.total_requests()) self.mock_responses.assert_call_count(request_url, 1) + + def test_criar_transferencia_pix_cpf(self): + """ + Teste para verificar a URL da requisição e dados de transferência PIX via cpf + """ + + request_url = PagamentoLoteBBWrapper()._construct_url( + "lotes-transferencias-pix" + ) + expected_json = { + "numeroRequisicao": "123", + "agenciaDebito": "345", + "contaCorrenteDebito": "678", + "digitoVerificadorContaCorrente": "X", + "tipoPagamento": 128, + "listaTransferencias": [ + { + "data": "19042023", + "cpf": "28779295827", + "valor": "12", + "descricaoPagamento": "Teste CPF", + "formaIdentificacao": 3, + } + ], + } + self.mock_responses.add( + responses.POST, + request_url, + headers=self._build_authorization_header(1), + json=expected_json, + ) + + response = PagamentoLoteBBWrapper().criar_transferencia_pix( + "123", + "345", + "678", + "X", + "19042023", + "11", + 3, + None, + None, + None, + "28779295827", + None, + None, + "Teste CPF", + ) + + self.assertEqual(request_url, response.url) + self.assertEqual(self._get_headers(), response.headers) + self.assertEqual(expected_json, response.json()) + self.assertEqual(2, self.total_requests()) + self.mock_responses.assert_call_count(request_url, 1) + + def test_criar_transferencia_pix_cnpj(self): + """ + Teste para verificar a URL da requisição e dados de transferência PIX via CNPJ + """ + + request_url = PagamentoLoteBBWrapper()._construct_url( + "lotes-transferencias-pix" + ) + expected_json = { + "numeroRequisicao": "123", + "agenciaDebito": "345", + "contaCorrenteDebito": "678", + "digitoVerificadorContaCorrente": "X", + "tipoPagamento": 128, + "listaTransferencias": [ + { + "data": "19042023", + "cnpj": "95127446000198", + "valor": "12", + "descricaoPagamento": "Teste CNPJ", + "formaIdentificacao": 3, + } + ], + } + self.mock_responses.add( + responses.POST, + request_url, + headers=self._build_authorization_header(1), + json=expected_json, + ) + + response = PagamentoLoteBBWrapper().criar_transferencia_pix( + "123", + "345", + "678", + "X", + "19042023", + "11", + 3, + None, + None, + None, + None, + "95127446000198", + None, + "Teste CPF", + ) + + self.assertEqual(request_url, response.url) + self.assertEqual(self._get_headers(), response.headers) + self.assertEqual(expected_json, response.json()) + self.assertEqual(2, self.total_requests()) + self.mock_responses.assert_call_count(request_url, 1) + + def test_consultar_transferencia_pix(self): + """ + Teste para verificar a URL da requisição e dados da transferência pix + """ + request_url = PagamentoLoteBBWrapper()._construct_url("boletos", "1") + expected_json = {} + self.mock_responses.add( + responses.GET, + request_url, + headers=self._build_authorization_header(1), + json=expected_json, + ) + + response = PagamentoLoteBBWrapper().consultar_pagamento_boleto("1") + + self.assertEqual(request_url, response.url) + self.assertEqual(self._get_headers(), response.headers) + self.assertEqual(expected_json, response.json()) + + self.assertEqual(2, self.total_requests()) + self.mock_responses.assert_call_count(request_url, 1) From 18a7e8bbf05c4b96d24be136363d48beeb1077a2 Mon Sep 17 00:00:00 2001 From: Pedro Fonseca Date: Sat, 22 Apr 2023 13:03:52 -0300 Subject: [PATCH 016/139] testes na funcao para criar body da transferencia pix --- tests/services/test_identify_key_type.py | 23 +- tests/wrapper/test_pagamentos.py | 262 ++++++++++++++++++----- 2 files changed, 215 insertions(+), 70 deletions(-) diff --git a/tests/services/test_identify_key_type.py b/tests/services/test_identify_key_type.py index 205e2bb2..458d3e82 100644 --- a/tests/services/test_identify_key_type.py +++ b/tests/services/test_identify_key_type.py @@ -4,7 +4,6 @@ class PixServiceTestCase(TestCase): - def test_is_email(self): """ Dado: @@ -31,7 +30,7 @@ def test_is_phone(self): Então: - o resultado deve ser 1 """ - phone = "999887766" + phone = "11999887766" result = PixService().identify_key_type(phone) @@ -106,23 +105,3 @@ def test_is_not_key(self): PixService().identify_key_type(key_invalid) self.assertEqual(ctx.exception.args[0], "Tipo de chave não identificado") - - def test_key_invalid(self): - """ - Dado: - - Dado uma string - - que tenha um '@' - - comece com '9' - - tenha 9 digitos - Quando: - - for chamado PixService().identify_key_type(key_invalid) - Então: - - deve ser lançado um ValueError com - "Tipo de chave não identificado" - """ - key_invalid = "999@@7766" - - with self.assertRaises(ValueError) as ctx: - PixService().identify_key_type(key_invalid) - - self.assertEqual(ctx.exception.args[0], "A chave utilizada pode ser mais de um tipo!") \ No newline at end of file diff --git a/tests/wrapper/test_pagamentos.py b/tests/wrapper/test_pagamentos.py index 4e1fdc83..1f1e7624 100644 --- a/tests/wrapper/test_pagamentos.py +++ b/tests/wrapper/test_pagamentos.py @@ -96,6 +96,216 @@ def test_valida_lote_2_remocao_convenio(self): mocked_model.assert_called_with(**expected_kwargs_call) + @MockedRequestsTestCase.no_auth + def test_criar_dados_chave_aleatoria_transferencia_pix(self): + """ + Teste para verificar e montar os dados da transferência pix usando chave aleatoria # noqa + """ + + expected_json = { + "numeroRequisicao": "123", + "agenciaDebito": "345", + "contaCorrenteDebito": "678", + "digitoVerificadorContaCorrente": "X", + "tipoPagamento": 128, + "listaTransferencias": [ + { + "email": None, + "cnpj": None, + "cpf": None, + "dddTelefone": None, + "telefone": None, + "data": "19042023", + "valor": 11.0, + "descricaoPagamento": "Pagamento", + "formaIdentificacao": 4, + "identificacaoAleatoria": "d14d32de-b3b9-4c31-9f89-8df2cec92c50", + } + ], + } + + response = PagamentoLoteBBWrapper()._criar_dados_transferencia_pix( + "123", + "345", + "678", + "X", + "19042023", + "11", + "d14d32de-b3b9-4c31-9f89-8df2cec92c50", + "Pagamento", + 128, + ) + + self.assertEqual(expected_json, response) + + @MockedRequestsTestCase.no_auth + def test_criar_dados_telefone_transferencia_pix(self): + """ + Teste para verificar e montar os dados da transferência pix usando telefone como chave # noqa + """ + + expected_json = { + "numeroRequisicao": "123", + "agenciaDebito": "345", + "contaCorrenteDebito": "678", + "digitoVerificadorContaCorrente": "X", + "tipoPagamento": 128, + "listaTransferencias": [ + { + "email": None, + "cnpj": None, + "cpf": None, + "dddTelefone": "11", + "telefone": "985732102", + "data": "19042023", + "valor": 11.0, + "descricaoPagamento": "Pagamento", + "formaIdentificacao": 1, + "identificacaoAleatoria": None, + } + ], + } + + response = PagamentoLoteBBWrapper()._criar_dados_transferencia_pix( + "123", + "345", + "678", + "X", + "19042023", + "11", + "11985732102", + "Pagamento", + 128, + ) + + self.assertEqual(expected_json, response) + + @MockedRequestsTestCase.no_auth + def test_criar_dados_email_transferencia_pix(self): + """ + Teste para verificar e montar os dados da transferência pix usando email como chave # noqa + """ + + expected_json = { + "numeroRequisicao": "123", + "agenciaDebito": "345", + "contaCorrenteDebito": "678", + "digitoVerificadorContaCorrente": "X", + "tipoPagamento": 128, + "listaTransferencias": [ + { + "email": "teste@imo.com", + "cnpj": None, + "cpf": None, + "dddTelefone": None, + "telefone": None, + "data": "19042023", + "valor": 11.0, + "descricaoPagamento": "Pagamento", + "formaIdentificacao": 2, + "identificacaoAleatoria": None, + } + ], + } + + response = PagamentoLoteBBWrapper()._criar_dados_transferencia_pix( + "123", + "345", + "678", + "X", + "19042023", + 11, + "teste@imo.com", + "Pagamento", + 128, + ) + + self.assertEqual(expected_json, response) + + @MockedRequestsTestCase.no_auth + def test_criar_dados_cpf_transferencia_pix(self): + """ + Teste para verificar e montar os dados da transferência pix usando cpf como chave # noqa + """ + + expected_json = { + "numeroRequisicao": "123", + "agenciaDebito": "345", + "contaCorrenteDebito": "678", + "digitoVerificadorContaCorrente": "X", + "tipoPagamento": 128, + "listaTransferencias": [ + { + "email": None, + "cnpj": None, + "cpf": "28779295827", + "dddTelefone": None, + "telefone": None, + "data": "19042023", + "valor": 11.0, + "descricaoPagamento": "Pagamento", + "formaIdentificacao": 3, + "identificacaoAleatoria": None, + } + ], + } + + response = PagamentoLoteBBWrapper()._criar_dados_transferencia_pix( + "123", + "345", + "678", + "X", + "19042023", + 11, + "28779295827", + "Pagamento", + 128, + ) + + self.assertEqual(expected_json, response) + + @MockedRequestsTestCase.no_auth + def test_criar_dados_cnpj_transferencia_pix(self): + """ + Teste para verificar e montar os dados da transferência pix usando cnpj como chave # noqa + """ + + expected_json = { + "numeroRequisicao": "123", + "agenciaDebito": "345", + "contaCorrenteDebito": "678", + "digitoVerificadorContaCorrente": "X", + "tipoPagamento": 128, + "listaTransferencias": [ + { + "email": None, + "cnpj": "95127446000198", + "cpf": None, + "dddTelefone": None, + "telefone": None, + "data": "19042023", + "valor": 11.0, + "descricaoPagamento": "Pagamento", + "formaIdentificacao": 3, + "identificacaoAleatoria": None, + } + ], + } + + response = PagamentoLoteBBWrapper()._criar_dados_transferencia_pix( + "123", + "345", + "678", + "X", + "19042023", + 11, + "95127446000198", + "Pagamento", + 128, + ) + + self.assertEqual(expected_json, response) + def test_cancelar_pagamento_1(self): """ Teste para verificar a URL da requisição e dados @@ -485,12 +695,6 @@ def test_criar_transferencia_pix_chave_aleatoria(self): "X", "19042023", "11", - 4, - None, - None, - None, - None, - None, "d14d32de-b3b9-4c31-9f89-8df2cec92c50", "Pagamento", ) @@ -538,14 +742,8 @@ def test_criar_transferencia_pix_email(self): "678", "X", "19042023", - "11", - 2, - None, - None, + 12, "testqrcode01@bb.com.br", - None, - None, - None, "Teste transfer", ) @@ -594,13 +792,7 @@ def test_criar_transferencia_pix_telefone(self): "X", "19042023", "11", - 1, - "11", - "985732102", - None, - None, - None, - None, + "11985732102", "Teste telefone", ) @@ -642,20 +834,7 @@ def test_criar_transferencia_pix_cpf(self): ) response = PagamentoLoteBBWrapper().criar_transferencia_pix( - "123", - "345", - "678", - "X", - "19042023", - "11", - 3, - None, - None, - None, - "28779295827", - None, - None, - "Teste CPF", + "123", "345", "678", "X", "19042023", 12, "28779295827", "Teste CPF" ) self.assertEqual(request_url, response.url) @@ -696,20 +875,7 @@ def test_criar_transferencia_pix_cnpj(self): ) response = PagamentoLoteBBWrapper().criar_transferencia_pix( - "123", - "345", - "678", - "X", - "19042023", - "11", - 3, - None, - None, - None, - None, - "95127446000198", - None, - "Teste CPF", + "123", "345", "678", "X", "19042023", "11", "95127446000198", "Teste CNPJ" ) self.assertEqual(request_url, response.url) From 8ab341db52b90c9847cfde012d26a3ac9e005cad Mon Sep 17 00:00:00 2001 From: Pedro Fonseca Date: Sat, 22 Apr 2023 13:04:49 -0300 Subject: [PATCH 017/139] atualizacao de modelo e service transferencia pix --- bb_wrapper/models/pagamentos.py | 25 ++++++++++++++----------- bb_wrapper/services/__init__.py | 2 +- bb_wrapper/services/pix.py | 2 +- 3 files changed, 16 insertions(+), 13 deletions(-) diff --git a/bb_wrapper/models/pagamentos.py b/bb_wrapper/models/pagamentos.py index cf2437be..105e9f8c 100644 --- a/bb_wrapper/models/pagamentos.py +++ b/bb_wrapper/models/pagamentos.py @@ -56,11 +56,12 @@ class TransferenciaPIX(BaseModel): valor: float chave: str formaIdentificacao: Optional[TipoChavePIX] - dddTelefone: Optional[int] - telefone: Optional[int] + descricaoPagamento: Optional[str] + dddTelefone: Optional[str] + telefone: Optional[str] email: Optional[str] - cpf: Optional[int] - cnpj: Optional[int] + cpf: Optional[str] + cnpj: Optional[str] identificacaoAleatoria: Optional[str] # noinspection PyMethodParameters @@ -74,23 +75,25 @@ def _set_data(cls, values): from ..services.pix import PixService key = values.get("chave") - key_type = PixService().identify_key_type(key) - values["formaIdentificacao"] = key_type + values["formaIdentificacao"] = key_type.value if key_type == TipoChavePIX.telefone: - values["dddTelefone"] = int(key[:2]) - values["telefone"] = int(key[2:]) + values["dddTelefone"] = key[:2] + values["telefone"] = key[2:] elif key_type == TipoChavePIX.email: values["email"] = key elif key_type == TipoChavePIX.uuid: values["identificacaoAleatoria"] = key elif key_type == TipoChavePIX.documento: key_value = cpfcnpj.clear_punctuation(key) - if len(key_value) == 1: - values["cpf"] = int(key_value) + + if len(key_value) == 11: + values["cpf"] = key_value else: - values["cnpj"] = int(key_value) + values["cnpj"] = key_value + + values.pop("chave") return values diff --git a/bb_wrapper/services/__init__.py b/bb_wrapper/services/__init__.py index 643fa06c..a668856e 100644 --- a/bb_wrapper/services/__init__.py +++ b/bb_wrapper/services/__init__.py @@ -4,7 +4,7 @@ from .barcode import BarcodeService from .mod import ModService # noqa: F401 from .pixcode import PixCodeService # noqa: F401 -from .pix import PixService # noqa: F401 +from .pix import PixService # noqa: F401 parse_unicode_to_alphanumeric = UnicodeService().parse_unicode_to_alphanumeric diff --git a/bb_wrapper/services/pix.py b/bb_wrapper/services/pix.py index a1ea1ccd..3b8174f5 100644 --- a/bb_wrapper/services/pix.py +++ b/bb_wrapper/services/pix.py @@ -32,7 +32,7 @@ def identify_key_type(self, key: str): is_document = cpfcnpj.validate(key) # 3 - is_phone = key_len == 9 and key[0] == "9" + is_phone = key_len == 11 and key[2] == "9" # 4 try: From 3a7e9de48451a276bdd38a051beb9d6f31b122d9 Mon Sep 17 00:00:00 2001 From: Pedro Fonseca Date: Sat, 22 Apr 2023 13:06:48 -0300 Subject: [PATCH 018/139] refatorando servico de transferencia pix em lote --- bb_wrapper/wrapper/pagamento_lote.py | 56 ++++------------------------ 1 file changed, 8 insertions(+), 48 deletions(-) diff --git a/bb_wrapper/wrapper/pagamento_lote.py b/bb_wrapper/wrapper/pagamento_lote.py index b2c77681..f401d4a7 100644 --- a/bb_wrapper/wrapper/pagamento_lote.py +++ b/bb_wrapper/wrapper/pagamento_lote.py @@ -6,6 +6,7 @@ LoteData, LoteTransferenciaData, LiberarPagamentos, + TransferenciaPIX, ) from ..services.document import DocumentoService from ..services.barcode import BarcodeService @@ -495,13 +496,7 @@ def _criar_dados_transferencia_pix( dv_conta, data_transferencia, valor_transferencia, - forma_id, - ddd, - telefone, - email, - cpf, - cnpj, - chave_aleatoria, + chave, descricao, tipo_pagamento, ): @@ -516,22 +511,11 @@ def _criar_dados_transferencia_pix( transferencia_data = { "data": data_transferencia, "valor": valor_transferencia, - "formaIdentificacao": forma_id, "descricaoPagamento": descricao, + "chave": chave, } - - if forma_id == 1: - transferencia_data["dddTelefone"] = ddd - transferencia_data["telefone"] = telefone - elif forma_id == 2: - transferencia_data["email"] = email - elif forma_id == 3: - transferencia_data["cpf"] = cpf - transferencia_data["cnpj"] = cnpj - elif forma_id == 4: - transferencia_data["identificacaoAleatoria"] = chave_aleatoria - - return {**lote_data, "listaTransferencias": [{**transferencia_data}]} + transferencia_data = TransferenciaPIX(**transferencia_data).dict() + return {**lote_data, "listaTransferencias": [transferencia_data]} def criar_transferencia_pix( self, @@ -541,13 +525,7 @@ def criar_transferencia_pix( dv_conta, data_transferencia, valor_transferencia, - forma_id, - ddd=None, - telefone=None, - email=None, - cpf=None, - cnpj=None, - chave_aleatoria=None, + chave, descricao="", tipo_pagamento=128, ): @@ -562,19 +540,7 @@ def criar_transferencia_pix( tipo_pagamento: Tipo de pagamento a ser feito (126, 127 ou 128) data_transferencia: Data do pagamento. No formato "ddmmyyyy" valor_transferencia: Valor do pagamento - forma_id: Tipo de chave utilizada - 1. Telefone - 2. E-mail - 3. CPF/CNPJ - 4. Chave Aleatória - ddd: DDD com dígitos. Obrigatório caso forma_id seja igual 1 - telefone: Telefone do recebedor. Obrigatório caso forma_id seja igual 1 - email: Email do recebedor. Obrigatório caso forma_id seja igual 2 - cpf: CPF do recebedor. - Opcional caso forma_id seja igual a 1 ou 2 e caso o campo cnpj não seja informado # noqa: E501 - Obrigatório caso forma_id seja igual a 3 ou 5 e caso o campo cnpj não seja informado # noqa: E501 - cnpj: CNPJ do recebedor: Tem os mesmos casos de Obrigatório e opcional do cpf # noqa: E501 - chave_aleatoria: Chave aleatória gerada pelo recebedor. Obrigatório caso forma_id seja igual 4 # noqa: E501 + chave: Valor corresponde a chave que sera usada para tranferência # noqa: E501 descricao: Campo de uso livre pelo cliente """ data = self._criar_dados_transferencia_pix( @@ -584,13 +550,7 @@ def criar_transferencia_pix( dv_conta, data_transferencia, valor_transferencia, - forma_id, - ddd, - telefone, - email, - cpf, - cnpj, - chave_aleatoria, + chave, descricao, tipo_pagamento, ) From 191b492fde82987004128fff7ef0e7a59d5a157e Mon Sep 17 00:00:00 2001 From: Pedro Fonseca Date: Sat, 22 Apr 2023 13:08:17 -0300 Subject: [PATCH 019/139] refatorando examplo de transferencia pix usando cpf --- examples/lotes_pagamento/transferencia_pix_cpf.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/examples/lotes_pagamento/transferencia_pix_cpf.py b/examples/lotes_pagamento/transferencia_pix_cpf.py index 4b01212b..9ed3bb64 100644 --- a/examples/lotes_pagamento/transferencia_pix_cpf.py +++ b/examples/lotes_pagamento/transferencia_pix_cpf.py @@ -13,7 +13,7 @@ lote_data = { - "n_requisicao": 9221347, + "n_requisicao": 9222347, "agencia": 1607, "conta": 99738672, "dv_conta": "X", @@ -22,9 +22,8 @@ transferencia_data = { "descricao": "transferencia CPF", "data_transferencia": today.strftime(bb_fmt), - "valor_transferencia":7999.99, - "forma_id": 3, - "cpf": "28779295827", + "valor_transferencia": 7999.99, + "chave": "28779295827", } response = c.criar_transferencia_pix(**lote_data, **transferencia_data) From 7d8f3d7943c3f49adb5babe792f3a27689801b14 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=F0=9F=90=98=20Pedro=20Fonseca?= Date: Sat, 22 Apr 2023 20:43:43 -0400 Subject: [PATCH 020/139] servico para verificar se email eh valido --- bb_wrapper/models/pagamentos.py | 5 ++- bb_wrapper/services/pix.py | 11 +++++++ tests/services/test_identify_key_type.py | 30 +++++++++++++++++ tests/wrapper/test_pagamentos.py | 42 ++++++++++++++++++++++++ 4 files changed, 87 insertions(+), 1 deletion(-) diff --git a/bb_wrapper/models/pagamentos.py b/bb_wrapper/models/pagamentos.py index 105e9f8c..58ed5f22 100644 --- a/bb_wrapper/models/pagamentos.py +++ b/bb_wrapper/models/pagamentos.py @@ -82,7 +82,10 @@ def _set_data(cls, values): values["dddTelefone"] = key[:2] values["telefone"] = key[2:] elif key_type == TipoChavePIX.email: - values["email"] = key + if PixService().verify_email(key): + values["email"] = key + else: + values["email"] = "" elif key_type == TipoChavePIX.uuid: values["identificacaoAleatoria"] = key elif key_type == TipoChavePIX.documento: diff --git a/bb_wrapper/services/pix.py b/bb_wrapper/services/pix.py index 3b8174f5..ef440971 100644 --- a/bb_wrapper/services/pix.py +++ b/bb_wrapper/services/pix.py @@ -1,4 +1,5 @@ import uuid +import re from pycpfcnpj import cpfcnpj @@ -53,3 +54,13 @@ def identify_key_type(self, key: str): return TipoChavePIX.uuid else: raise ValueError("Tipo de chave não identificado") + + def verify_email(self, email: str): + regex = re.compile( + r"([A-Za-z0-9]+[.-_])*[A-Za-z0-9]+@[A-Za-z0-9-]+(\.[A-Z|a-z]{2,})+" + ) + + if re.fullmatch(regex, email): + return True + else: + return False diff --git a/tests/services/test_identify_key_type.py b/tests/services/test_identify_key_type.py index 458d3e82..91de8ad1 100644 --- a/tests/services/test_identify_key_type.py +++ b/tests/services/test_identify_key_type.py @@ -105,3 +105,33 @@ def test_is_not_key(self): PixService().identify_key_type(key_invalid) self.assertEqual(ctx.exception.args[0], "Tipo de chave não identificado") + + def test_email_valid(self): + """ + Dado: + - Dado um um 'test@test.com' + Quando: + - for chamado PixService().verify_email('test@test.com') + Então: + - o resultado deve ser False + """ + email = "test@test.com" + + result = PixService().verify_email(email) + + self.assertTrue(result) + + def test_email_invalid(self): + """ + Dado: + - Dado um um 'teste@...br' + Quando: + - for chamado PixService().verify_email('teste@...br') + Então: + - o resultado deve ser True + """ + email = "teste@...br" + + result = PixService().verify_email(email) + + self.assertFalse(result) diff --git a/tests/wrapper/test_pagamentos.py b/tests/wrapper/test_pagamentos.py index 1f1e7624..8d5f327e 100644 --- a/tests/wrapper/test_pagamentos.py +++ b/tests/wrapper/test_pagamentos.py @@ -222,6 +222,48 @@ def test_criar_dados_email_transferencia_pix(self): self.assertEqual(expected_json, response) + @MockedRequestsTestCase.no_auth + def test_criar_dados_com_email_invalido(self): + """ + Teste para verificar e montar os dados da transferência pix usando email como chave # noqa + """ + + expected_json = { + "numeroRequisicao": "123", + "agenciaDebito": "345", + "contaCorrenteDebito": "678", + "digitoVerificadorContaCorrente": "X", + "tipoPagamento": 128, + "listaTransferencias": [ + { + "email": "", + "cnpj": None, + "cpf": None, + "dddTelefone": None, + "telefone": None, + "data": "19042023", + "valor": 11.0, + "descricaoPagamento": "Pagamento", + "formaIdentificacao": 2, + "identificacaoAleatoria": None, + } + ], + } + + response = PagamentoLoteBBWrapper()._criar_dados_transferencia_pix( + "123", + "345", + "678", + "X", + "19042023", + 11, + "teste@...", + "Pagamento", + 128, + ) + + self.assertEqual(expected_json, response) + @MockedRequestsTestCase.no_auth def test_criar_dados_cpf_transferencia_pix(self): """ From 5b97b4645651ab9774c1070acfa3a7cbb9a6ba9a Mon Sep 17 00:00:00 2001 From: Pedro Fonseca Date: Mon, 24 Apr 2023 15:54:05 -0300 Subject: [PATCH 021/139] testes em DocumentService --- tests/services/test_documento.py | 91 ++++++++++++++++++++++++++++++++ 1 file changed, 91 insertions(+) create mode 100644 tests/services/test_documento.py diff --git a/tests/services/test_documento.py b/tests/services/test_documento.py new file mode 100644 index 00000000..5fcd8f4d --- /dev/null +++ b/tests/services/test_documento.py @@ -0,0 +1,91 @@ +from unittest import TestCase + +from bb_wrapper.services.document import DocumentoService + + +class DocumentServiceTestCase(TestCase): + maxDiff = None + + def test_identifica_tipo_pessoa_fisica(self): + """ + Dado: + - Dado uma string '77855240098' + Quando: + - for chamado DocumentoService().identifica_tipo('77855240098') + Então: + - o resultado deve ser 1 + """ + cpf = "77855240098" + + result = DocumentoService().identifica_tipo(cpf) + + expected = 1 + + self.assertEqual(result, expected) + + def test_identifica_tipo_pessoa_fisica_com_pontuacao(self): + """ + Dado: + - Dado uma string '778.552.400-98' + Quando: + - for chamado DocumentoService().identifica_tipo('778.552.400-98') + Então: + - o resultado deve ser 1 + """ + cpf = "778.552.400-98" + + result = DocumentoService().identifica_tipo(cpf) + + expected = 1 + + self.assertEqual(result, expected) + + def test_identifica_tipo_pessoa_juridica(self): + """ + Dado: + - Dado uma string '55468100000139' + Quando: + - for chamado DocumentoService().identifica_tipo('55468100000139') + Então: + - o resultado deve ser 1 + """ + cnpj = "55468100000139" + + result = DocumentoService().identifica_tipo(cnpj) + + expected = 2 + + self.assertEqual(result, expected) + + def test_identifica_tipo_pessoa_juridica_com_pontuacao(self): + """ + Dado: + - Dado uma string '18.853.097/0001-40' + Quando: + - for chamado DocumentoService().identifica_tipo('18.853.097/0001-40') + Então: + - o resultado deve ser 1 + """ + cnpj = "18.853.097/0001-40" + + result = DocumentoService().identifica_tipo(cnpj) + + expected = 2 + + self.assertEqual(result, expected) + + def test_identifica_tipo_pessoa_document_invalid(self): + """ + Dado: + - Dado uma string '554681000001' + Quando: + - for chamado DocumentoService().identifica_tipo('554681000001') + Então: + - o resultado deve ser 1 + """ + invalid_document = "554681000001" + + with self.assertRaises(ValueError) as ctx: + DocumentoService().identifica_tipo(invalid_document) + + self.assertEqual(ctx.exception.args[0], f"CPF/CNPJ '{invalid_document}' é inválido!") # noqa From dede79a6f31d7aa6e3d76a6dd73a3ddf5847ffbe Mon Sep 17 00:00:00 2001 From: Pedro Fonseca Date: Mon, 24 Apr 2023 15:54:57 -0300 Subject: [PATCH 022/139] fmt em DocumentService --- tests/services/test_documento.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/services/test_documento.py b/tests/services/test_documento.py index 5fcd8f4d..c99595c1 100644 --- a/tests/services/test_documento.py +++ b/tests/services/test_documento.py @@ -88,4 +88,6 @@ def test_identifica_tipo_pessoa_document_invalid(self): with self.assertRaises(ValueError) as ctx: DocumentoService().identifica_tipo(invalid_document) - self.assertEqual(ctx.exception.args[0], f"CPF/CNPJ '{invalid_document}' é inválido!") # noqa + self.assertEqual( + ctx.exception.args[0], f"CPF/CNPJ '{invalid_document}' é inválido!" + ) # noqa From 01a6dabe077d08844e646f8887a8c1f224980490 Mon Sep 17 00:00:00 2001 From: Pedro Fonseca <32584628+peidrao@users.noreply.github.com> Date: Mon, 24 Apr 2023 17:20:33 -0300 Subject: [PATCH 023/139] Update bb_wrapper/services/pix.py Co-authored-by: Rodrigo Castro --- bb_wrapper/services/pix.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/bb_wrapper/services/pix.py b/bb_wrapper/services/pix.py index ef440971..36d0076f 100644 --- a/bb_wrapper/services/pix.py +++ b/bb_wrapper/services/pix.py @@ -37,8 +37,7 @@ def identify_key_type(self, key: str): # 4 try: - is_uuid = uuid.UUID(key) - is_uuid = True + is_uuid = bool(uuid.UUID(key)) except ValueError: is_uuid = False From 4f0166cbf11eb17c12eba85e7a458b5db26109a2 Mon Sep 17 00:00:00 2001 From: Pedro Fonseca <32584628+peidrao@users.noreply.github.com> Date: Mon, 24 Apr 2023 17:21:28 -0300 Subject: [PATCH 024/139] Update bb_wrapper/services/pix.py Co-authored-by: Rodrigo Castro --- bb_wrapper/services/pix.py | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/bb_wrapper/services/pix.py b/bb_wrapper/services/pix.py index 36d0076f..458dec0d 100644 --- a/bb_wrapper/services/pix.py +++ b/bb_wrapper/services/pix.py @@ -54,12 +54,13 @@ def identify_key_type(self, key: str): else: raise ValueError("Tipo de chave não identificado") - def verify_email(self, email: str): + def verify_email(self, email: str, raise_exception=True): regex = re.compile( r"([A-Za-z0-9]+[.-_])*[A-Za-z0-9]+@[A-Za-z0-9-]+(\.[A-Z|a-z]{2,})+" ) - - if re.fullmatch(regex, email): - return True - else: - return False + + is_email_valid = re.fullmatch(regex, email) + + if raise_exception and not is_email_valid: + raise ValueError("Email inválido!") + return is_email_valid From e14abe7c9756b7099e9e4e9a73564a0ed35dcfd9 Mon Sep 17 00:00:00 2001 From: Pedro Fonseca Date: Mon, 24 Apr 2023 17:44:14 -0300 Subject: [PATCH 025/139] ajustes em testes --- bb_wrapper/services/pix.py | 4 +- tests/services/test_identify_key_type.py | 5 ++- tests/wrapper/test_pagamentos.py | 51 ++++++++---------------- 3 files changed, 21 insertions(+), 39 deletions(-) diff --git a/bb_wrapper/services/pix.py b/bb_wrapper/services/pix.py index 458dec0d..2881271b 100644 --- a/bb_wrapper/services/pix.py +++ b/bb_wrapper/services/pix.py @@ -58,9 +58,9 @@ def verify_email(self, email: str, raise_exception=True): regex = re.compile( r"([A-Za-z0-9]+[.-_])*[A-Za-z0-9]+@[A-Za-z0-9-]+(\.[A-Z|a-z]{2,})+" ) - + is_email_valid = re.fullmatch(regex, email) - + if raise_exception and not is_email_valid: raise ValueError("Email inválido!") return is_email_valid diff --git a/tests/services/test_identify_key_type.py b/tests/services/test_identify_key_type.py index 91de8ad1..1271fb63 100644 --- a/tests/services/test_identify_key_type.py +++ b/tests/services/test_identify_key_type.py @@ -132,6 +132,7 @@ def test_email_invalid(self): """ email = "teste@...br" - result = PixService().verify_email(email) + with self.assertRaises(ValueError) as ctx: + PixService().verify_email(email) - self.assertFalse(result) + self.assertEqual(ctx.exception.args[0], "Email inválido!") diff --git a/tests/wrapper/test_pagamentos.py b/tests/wrapper/test_pagamentos.py index 8d5f327e..7f5216d5 100644 --- a/tests/wrapper/test_pagamentos.py +++ b/tests/wrapper/test_pagamentos.py @@ -228,41 +228,22 @@ def test_criar_dados_com_email_invalido(self): Teste para verificar e montar os dados da transferência pix usando email como chave # noqa """ - expected_json = { - "numeroRequisicao": "123", - "agenciaDebito": "345", - "contaCorrenteDebito": "678", - "digitoVerificadorContaCorrente": "X", - "tipoPagamento": 128, - "listaTransferencias": [ - { - "email": "", - "cnpj": None, - "cpf": None, - "dddTelefone": None, - "telefone": None, - "data": "19042023", - "valor": 11.0, - "descricaoPagamento": "Pagamento", - "formaIdentificacao": 2, - "identificacaoAleatoria": None, - } - ], - } - - response = PagamentoLoteBBWrapper()._criar_dados_transferencia_pix( - "123", - "345", - "678", - "X", - "19042023", - 11, - "teste@...", - "Pagamento", - 128, - ) - - self.assertEqual(expected_json, response) + with self.assertRaises(ValueError) as ctx: + PagamentoLoteBBWrapper()._criar_dados_transferencia_pix( + "123", + "345", + "678", + "X", + "19042023", + 11, + "teste@...", + "Pagamento", + 128, + ) + + self.assertEqual( + ctx.exception.args[0][0].exc.args[0], "Email inválido!" + ) # noqa @MockedRequestsTestCase.no_auth def test_criar_dados_cpf_transferencia_pix(self): From 4c435606696f7572e7fa6da7327143c390828ae8 Mon Sep 17 00:00:00 2001 From: Pedro Fonseca Date: Tue, 25 Apr 2023 12:04:08 -0300 Subject: [PATCH 026/139] correcoes em teste --- bb_wrapper/models/pagamentos.py | 2 -- tests/wrapper/test_pagamentos.py | 20 +++++++++++--------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/bb_wrapper/models/pagamentos.py b/bb_wrapper/models/pagamentos.py index 58ed5f22..a719660c 100644 --- a/bb_wrapper/models/pagamentos.py +++ b/bb_wrapper/models/pagamentos.py @@ -84,8 +84,6 @@ def _set_data(cls, values): elif key_type == TipoChavePIX.email: if PixService().verify_email(key): values["email"] = key - else: - values["email"] = "" elif key_type == TipoChavePIX.uuid: values["identificacaoAleatoria"] = key elif key_type == TipoChavePIX.documento: diff --git a/tests/wrapper/test_pagamentos.py b/tests/wrapper/test_pagamentos.py index 7f5216d5..345fa791 100644 --- a/tests/wrapper/test_pagamentos.py +++ b/tests/wrapper/test_pagamentos.py @@ -125,15 +125,17 @@ def test_criar_dados_chave_aleatoria_transferencia_pix(self): } response = PagamentoLoteBBWrapper()._criar_dados_transferencia_pix( - "123", - "345", - "678", - "X", - "19042023", - "11", - "d14d32de-b3b9-4c31-9f89-8df2cec92c50", - "Pagamento", - 128, + **{ + "n_requisicao": "123", + "agencia": "345", + "conta": "678", + "dv_conta": "X", + "data_transferencia": "19042023", + "valor_transferencia": "11", + "chave": "d14d32de-b3b9-4c31-9f89-8df2cec92c50", + "descricao": "Pagamento", + "tipo_pagamento": 128, + } ) self.assertEqual(expected_json, response) From a6e746bfe881ec0f9445cabb9a4a94c2e2777c28 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=F0=9F=90=98=20Pedro=20Fonseca?= Date: Wed, 26 Apr 2023 09:24:53 -0400 Subject: [PATCH 027/139] mock em test_retry_request --- tests/wrapper/test_request.py | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/tests/wrapper/test_request.py b/tests/wrapper/test_request.py index b0c4670a..4934a050 100644 --- a/tests/wrapper/test_request.py +++ b/tests/wrapper/test_request.py @@ -1,10 +1,9 @@ -from unittest.mock import patch +from unittest.mock import patch, MagicMock from requests import Timeout from py_bdd_context import BDDContextTestCase from bb_wrapper.wrapper.request import RequestsWrapper - class RequestsWrapperTestCase(BDDContextTestCase): maxDiff = None @@ -120,7 +119,8 @@ def test_request_timeout(self): ): self.headers_patcher.stop() - def test_retry_request(self): + @patch('bb_wrapper.wrapper.request.requests') + def test_retry_request(self, mock_requests): with self.given( """ - uma requisição qualquer @@ -130,7 +130,10 @@ def test_retry_request(self): "bb_wrapper.wrapper.request.RequestsWrapper._get_request_info" ) self.mocked_headers = self.headers_patcher.start() - + mock_response = MagicMock() + mock_response.status_code = 200 + mock_response.content.return_value = 'Ok' + mock_requests.get.return_value = mock_response max_retries = 3 def raise_connection_reset_error(headers=None): @@ -143,7 +146,7 @@ def raise_connection_reset_error(headers=None): self.mocked_headers.side_effect = raise_connection_reset_error wrapper = RequestsWrapper(base_url="") - url = "https://httpstat.us/200?sleep=1" + url = "foo" with self.when( """ From 2846d7b2c6f2915bbfbd49cc6e81cacc322410a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=F0=9F=90=98=20Pedro=20Fonseca?= Date: Wed, 26 Apr 2023 09:28:34 -0400 Subject: [PATCH 028/139] fmt --- tests/wrapper/test_request.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/wrapper/test_request.py b/tests/wrapper/test_request.py index 4934a050..8532e507 100644 --- a/tests/wrapper/test_request.py +++ b/tests/wrapper/test_request.py @@ -4,6 +4,7 @@ from bb_wrapper.wrapper.request import RequestsWrapper + class RequestsWrapperTestCase(BDDContextTestCase): maxDiff = None @@ -119,7 +120,7 @@ def test_request_timeout(self): ): self.headers_patcher.stop() - @patch('bb_wrapper.wrapper.request.requests') + @patch("bb_wrapper.wrapper.request.requests") def test_retry_request(self, mock_requests): with self.given( """ @@ -132,7 +133,7 @@ def test_retry_request(self, mock_requests): self.mocked_headers = self.headers_patcher.start() mock_response = MagicMock() mock_response.status_code = 200 - mock_response.content.return_value = 'Ok' + mock_response.content.return_value = "Ok" mock_requests.get.return_value = mock_response max_retries = 3 From f9cff492454f681af09e2e0f907333d565047efc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=F0=9F=90=98=20Pedro=20Fonseca?= Date: Wed, 26 Apr 2023 15:12:55 -0400 Subject: [PATCH 029/139] atualizacao da versao do py-bdd-context --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 83463ffb..d781985e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -84,7 +84,7 @@ coverage = {extras = ["toml"], version = "^5.5"} isort = "^5.9.2" freezegun = "1.1.0" responses = "^0.21.0" -py-bdd-context = "^0.0.2" +py-bdd-context = "^0.0.4" [tool.poetry.scripts] From 298faf05ddeb63fd3566ab91f2229a6ef7ae36a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=F0=9F=90=98=20Pedro=20Fonseca?= Date: Wed, 26 Apr 2023 16:51:45 -0400 Subject: [PATCH 030/139] adicao de novos testes --- tests/services/test_qrcode.py | 3 +- tests/utils.py | 6 +++ tests/wrapper/test_request.py | 77 ++++++++++++++++++++++++++++++----- 3 files changed, 73 insertions(+), 13 deletions(-) diff --git a/tests/services/test_qrcode.py b/tests/services/test_qrcode.py index 811bfceb..c34352f8 100644 --- a/tests/services/test_qrcode.py +++ b/tests/services/test_qrcode.py @@ -1,5 +1,4 @@ from unittest import TestCase - from bb_wrapper.services import QRCodeService @@ -19,6 +18,6 @@ def test_generate_qrcode_b64image_1(self): result = QRCodeService().generate_qrcode_b64image(qrcode_data) - expected = "data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0nMS4wJyBlbmNvZGluZz0nVVRGLTgnPz4KPHN2ZyB3aWR0aD0iNTdtbSIgaGVpZ2h0PSI1N21tIiB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHJlY3QgeD0iNG1tIiB5PSI0bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjVtbSIgeT0iNG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI2bW0iIHk9IjRtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iN21tIiB5PSI0bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjhtbSIgeT0iNG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI5bW0iIHk9IjRtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMTBtbSIgeT0iNG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIxNW1tIiB5PSI0bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjE2bW0iIHk9IjRtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMTdtbSIgeT0iNG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIxOG1tIiB5PSI0bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjE5bW0iIHk9IjRtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMjBtbSIgeT0iNG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIyNW1tIiB5PSI0bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjI2bW0iIHk9IjRtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMjdtbSIgeT0iNG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIzMG1tIiB5PSI0bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjMybW0iIHk9IjRtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMzRtbSIgeT0iNG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIzNW1tIiB5PSI0bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjM2bW0iIHk9IjRtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iNDBtbSIgeT0iNG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI0NG1tIiB5PSI0bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjQ2bW0iIHk9IjRtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iNDdtbSIgeT0iNG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI0OG1tIiB5PSI0bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjQ5bW0iIHk9IjRtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iNTBtbSIgeT0iNG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI1MW1tIiB5PSI0bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjUybW0iIHk9IjRtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iNG1tIiB5PSI1bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjEwbW0iIHk9IjVtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMTVtbSIgeT0iNW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIxNm1tIiB5PSI1bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjIwbW0iIHk9IjVtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMjFtbSIgeT0iNW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIyMm1tIiB5PSI1bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjI2bW0iIHk9IjVtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMjdtbSIgeT0iNW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIyOG1tIiB5PSI1bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjI5bW0iIHk9IjVtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMzBtbSIgeT0iNW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIzMW1tIiB5PSI1bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjMybW0iIHk9IjVtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMzVtbSIgeT0iNW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI0MG1tIiB5PSI1bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjQxbW0iIHk9IjVtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iNDJtbSIgeT0iNW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI0M21tIiB5PSI1bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjQ0bW0iIHk9IjVtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iNDZtbSIgeT0iNW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI1Mm1tIiB5PSI1bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjRtbSIgeT0iNm1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI2bW0iIHk9IjZtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iN21tIiB5PSI2bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjhtbSIgeT0iNm1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIxMG1tIiB5PSI2bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjEybW0iIHk9IjZtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMTNtbSIgeT0iNm1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIxOG1tIiB5PSI2bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjE5bW0iIHk9IjZtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMjBtbSIgeT0iNm1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIyMW1tIiB5PSI2bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjI1bW0iIHk9IjZtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMjZtbSIgeT0iNm1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIyOG1tIiB5PSI2bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjMwbW0iIHk9IjZtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMzJtbSIgeT0iNm1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIzN21tIiB5PSI2bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjM4bW0iIHk9IjZtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMzltbSIgeT0iNm1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI0MW1tIiB5PSI2bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjQzbW0iIHk9IjZtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iNDRtbSIgeT0iNm1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI0Nm1tIiB5PSI2bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjQ4bW0iIHk9IjZtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iNDltbSIgeT0iNm1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI1MG1tIiB5PSI2bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjUybW0iIHk9IjZtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iNG1tIiB5PSI3bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjZtbSIgeT0iN21tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI3bW0iIHk9IjdtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iOG1tIiB5PSI3bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjEwbW0iIHk9IjdtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMTJtbSIgeT0iN21tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIxN21tIiB5PSI3bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjIwbW0iIHk9IjdtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMjFtbSIgeT0iN21tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIyMm1tIiB5PSI3bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjIzbW0iIHk9IjdtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMjZtbSIgeT0iN21tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIzMG1tIiB5PSI3bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjMxbW0iIHk9IjdtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMzRtbSIgeT0iN21tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIzOG1tIiB5PSI3bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjQzbW0iIHk9IjdtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iNDZtbSIgeT0iN21tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI0OG1tIiB5PSI3bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjQ5bW0iIHk9IjdtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iNTBtbSIgeT0iN21tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI1Mm1tIiB5PSI3bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjRtbSIgeT0iOG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI2bW0iIHk9IjhtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iN21tIiB5PSI4bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjhtbSIgeT0iOG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIxMG1tIiB5PSI4bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjEybW0iIHk9IjhtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMTRtbSIgeT0iOG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIxNW1tIiB5PSI4bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjE2bW0iIHk9IjhtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMThtbSIgeT0iOG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIyMW1tIiB5PSI4bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjI1bW0iIHk9IjhtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMjZtbSIgeT0iOG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIyN21tIiB5PSI4bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjI4bW0iIHk9IjhtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMjltbSIgeT0iOG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIzMG1tIiB5PSI4bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjMxbW0iIHk9IjhtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMzRtbSIgeT0iOG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIzNm1tIiB5PSI4bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjM3bW0iIHk9IjhtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iNDFtbSIgeT0iOG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI0Nm1tIiB5PSI4bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjQ4bW0iIHk9IjhtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iNDltbSIgeT0iOG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI1MG1tIiB5PSI4bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjUybW0iIHk9IjhtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iNG1tIiB5PSI5bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjEwbW0iIHk9IjltbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMTJtbSIgeT0iOW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIxNG1tIiB5PSI5bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjE4bW0iIHk9IjltbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMTltbSIgeT0iOW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIyMW1tIiB5PSI5bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjIybW0iIHk9IjltbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMjNtbSIgeT0iOW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIyNW1tIiB5PSI5bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjI2bW0iIHk9IjltbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMzBtbSIgeT0iOW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIzM21tIiB5PSI5bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjQxbW0iIHk9IjltbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iNDJtbSIgeT0iOW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI0Nm1tIiB5PSI5bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjUybW0iIHk9IjltbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iNG1tIiB5PSIxMG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI1bW0iIHk9IjEwbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjZtbSIgeT0iMTBtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iN21tIiB5PSIxMG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI4bW0iIHk9IjEwbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjltbSIgeT0iMTBtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMTBtbSIgeT0iMTBtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMTJtbSIgeT0iMTBtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMTRtbSIgeT0iMTBtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMTZtbSIgeT0iMTBtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMThtbSIgeT0iMTBtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMjBtbSIgeT0iMTBtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMjJtbSIgeT0iMTBtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMjRtbSIgeT0iMTBtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMjZtbSIgeT0iMTBtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMjhtbSIgeT0iMTBtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMzBtbSIgeT0iMTBtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMzJtbSIgeT0iMTBtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMzRtbSIgeT0iMTBtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMzZtbSIgeT0iMTBtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMzhtbSIgeT0iMTBtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iNDBtbSIgeT0iMTBtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iNDJtbSIgeT0iMTBtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iNDRtbSIgeT0iMTBtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iNDZtbSIgeT0iMTBtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iNDdtbSIgeT0iMTBtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iNDhtbSIgeT0iMTBtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iNDltbSIgeT0iMTBtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iNTBtbSIgeT0iMTBtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iNTFtbSIgeT0iMTBtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iNTJtbSIgeT0iMTBtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMTJtbSIgeT0iMTFtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMTNtbSIgeT0iMTFtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMTRtbSIgeT0iMTFtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMTdtbSIgeT0iMTFtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMjBtbSIgeT0iMTFtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMjJtbSIgeT0iMTFtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMjVtbSIgeT0iMTFtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMjZtbSIgeT0iMTFtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMzBtbSIgeT0iMTFtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMzRtbSIgeT0iMTFtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMzVtbSIgeT0iMTFtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMzZtbSIgeT0iMTFtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMzltbSIgeT0iMTFtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iNDBtbSIgeT0iMTFtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iNDNtbSIgeT0iMTFtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iNDRtbSIgeT0iMTFtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iNG1tIiB5PSIxMm1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI2bW0iIHk9IjEybW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjdtbSIgeT0iMTJtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iOG1tIiB5PSIxMm1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI5bW0iIHk9IjEybW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjEwbW0iIHk9IjEybW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjEzbW0iIHk9IjEybW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjE2bW0iIHk9IjEybW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjIwbW0iIHk9IjEybW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjIxbW0iIHk9IjEybW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjIzbW0iIHk9IjEybW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjI2bW0iIHk9IjEybW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjI3bW0iIHk9IjEybW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjI4bW0iIHk9IjEybW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjI5bW0iIHk9IjEybW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjMwbW0iIHk9IjEybW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjMxbW0iIHk9IjEybW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjM4bW0iIHk9IjEybW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjQwbW0iIHk9IjEybW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjQxbW0iIHk9IjEybW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjQ2bW0iIHk9IjEybW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjQ3bW0iIHk9IjEybW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjQ4bW0iIHk9IjEybW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjQ5bW0iIHk9IjEybW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjUwbW0iIHk9IjEybW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjRtbSIgeT0iMTNtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iNW1tIiB5PSIxM21tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI2bW0iIHk9IjEzbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjExbW0iIHk9IjEzbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjEybW0iIHk9IjEzbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjE0bW0iIHk9IjEzbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjE4bW0iIHk9IjEzbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjIwbW0iIHk9IjEzbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjIxbW0iIHk9IjEzbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjIybW0iIHk9IjEzbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjI4bW0iIHk9IjEzbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjMwbW0iIHk9IjEzbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjMxbW0iIHk9IjEzbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjM3bW0iIHk9IjEzbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjM4bW0iIHk9IjEzbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjQwbW0iIHk9IjEzbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjQzbW0iIHk9IjEzbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjQ1bW0iIHk9IjEzbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjQ2bW0iIHk9IjEzbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjQ3bW0iIHk9IjEzbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjQ4bW0iIHk9IjEzbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjQ5bW0iIHk9IjEzbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjUxbW0iIHk9IjEzbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjUybW0iIHk9IjEzbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjRtbSIgeT0iMTRtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iNW1tIiB5PSIxNG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI2bW0iIHk9IjE0bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjdtbSIgeT0iMTRtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iOW1tIiB5PSIxNG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIxMG1tIiB5PSIxNG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIxMm1tIiB5PSIxNG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIxNG1tIiB5PSIxNG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIxNW1tIiB5PSIxNG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIxN21tIiB5PSIxNG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIxOW1tIiB5PSIxNG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIyMG1tIiB5PSIxNG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIyMm1tIiB5PSIxNG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIyNW1tIiB5PSIxNG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIyOG1tIiB5PSIxNG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIyOW1tIiB5PSIxNG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIzMG1tIiB5PSIxNG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIzMW1tIiB5PSIxNG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIzMm1tIiB5PSIxNG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIzM21tIiB5PSIxNG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIzNG1tIiB5PSIxNG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIzNm1tIiB5PSIxNG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIzOG1tIiB5PSIxNG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIzOW1tIiB5PSIxNG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI0MW1tIiB5PSIxNG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI0Mm1tIiB5PSIxNG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI0NG1tIiB5PSIxNG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI1Mm1tIiB5PSIxNG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI0bW0iIHk9IjE1bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjdtbSIgeT0iMTVtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iOG1tIiB5PSIxNW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI5bW0iIHk9IjE1bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjExbW0iIHk9IjE1bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjEzbW0iIHk9IjE1bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjE0bW0iIHk9IjE1bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjE1bW0iIHk9IjE1bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjE2bW0iIHk9IjE1bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjE3bW0iIHk9IjE1bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjIwbW0iIHk9IjE1bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjI1bW0iIHk9IjE1bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjI3bW0iIHk9IjE1bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjI4bW0iIHk9IjE1bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjI5bW0iIHk9IjE1bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjM0bW0iIHk9IjE1bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjM1bW0iIHk9IjE1bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjM2bW0iIHk9IjE1bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjM3bW0iIHk9IjE1bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjM5bW0iIHk9IjE1bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjQybW0iIHk9IjE1bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjQ0bW0iIHk9IjE1bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjQ2bW0iIHk9IjE1bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjQ3bW0iIHk9IjE1bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjQ5bW0iIHk9IjE1bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjUybW0iIHk9IjE1bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjRtbSIgeT0iMTZtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iNm1tIiB5PSIxNm1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI3bW0iIHk9IjE2bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjhtbSIgeT0iMTZtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iOW1tIiB5PSIxNm1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIxMG1tIiB5PSIxNm1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIxNG1tIiB5PSIxNm1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIxNW1tIiB5PSIxNm1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIxOG1tIiB5PSIxNm1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIyMm1tIiB5PSIxNm1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIyNm1tIiB5PSIxNm1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIyOG1tIiB5PSIxNm1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIzMG1tIiB5PSIxNm1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIzMW1tIiB5PSIxNm1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIzNG1tIiB5PSIxNm1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIzN21tIiB5PSIxNm1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI0MW1tIiB5PSIxNm1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI0Mm1tIiB5PSIxNm1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI0Nm1tIiB5PSIxNm1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI0OG1tIiB5PSIxNm1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI1MG1tIiB5PSIxNm1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI1MW1tIiB5PSIxNm1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI1Mm1tIiB5PSIxNm1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI2bW0iIHk9IjE3bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjEzbW0iIHk9IjE3bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjE0bW0iIHk9IjE3bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjE1bW0iIHk9IjE3bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjE2bW0iIHk9IjE3bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjE3bW0iIHk9IjE3bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjE4bW0iIHk9IjE3bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjE5bW0iIHk9IjE3bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjIxbW0iIHk9IjE3bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjIybW0iIHk9IjE3bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjIzbW0iIHk9IjE3bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjI0bW0iIHk9IjE3bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjI4bW0iIHk9IjE3bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjMwbW0iIHk9IjE3bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjMybW0iIHk9IjE3bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjM0bW0iIHk9IjE3bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjM1bW0iIHk9IjE3bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjM2bW0iIHk9IjE3bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjM3bW0iIHk9IjE3bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjM4bW0iIHk9IjE3bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjM5bW0iIHk9IjE3bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjQybW0iIHk9IjE3bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjQzbW0iIHk9IjE3bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjQ1bW0iIHk9IjE3bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjQ4bW0iIHk9IjE3bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjUwbW0iIHk9IjE3bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjUybW0iIHk9IjE3bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjVtbSIgeT0iMThtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iNm1tIiB5PSIxOG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI3bW0iIHk9IjE4bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjhtbSIgeT0iMThtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iOW1tIiB5PSIxOG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIxMG1tIiB5PSIxOG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIxMW1tIiB5PSIxOG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIxNG1tIiB5PSIxOG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIxNW1tIiB5PSIxOG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIxN21tIiB5PSIxOG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIxOG1tIiB5PSIxOG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIxOW1tIiB5PSIxOG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIyMm1tIiB5PSIxOG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIyNG1tIiB5PSIxOG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIyN21tIiB5PSIxOG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIyOG1tIiB5PSIxOG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIyOW1tIiB5PSIxOG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIzMW1tIiB5PSIxOG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIzMm1tIiB5PSIxOG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIzNW1tIiB5PSIxOG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIzOG1tIiB5PSIxOG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIzOW1tIiB5PSIxOG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI0MG1tIiB5PSIxOG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI0MW1tIiB5PSIxOG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI0M21tIiB5PSIxOG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI0Nm1tIiB5PSIxOG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI0N21tIiB5PSIxOG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI0OW1tIiB5PSIxOG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI1MG1tIiB5PSIxOG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI1Mm1tIiB5PSIxOG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI0bW0iIHk9IjE5bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjZtbSIgeT0iMTltbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iN21tIiB5PSIxOW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIxMW1tIiB5PSIxOW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIxM21tIiB5PSIxOW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIxNW1tIiB5PSIxOW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIxNm1tIiB5PSIxOW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIxN21tIiB5PSIxOW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIxOG1tIiB5PSIxOW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIxOW1tIiB5PSIxOW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIyMW1tIiB5PSIxOW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIyMm1tIiB5PSIxOW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIyM21tIiB5PSIxOW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIyNG1tIiB5PSIxOW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIyNm1tIiB5PSIxOW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIyN21tIiB5PSIxOW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIyOG1tIiB5PSIxOW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIyOW1tIiB5PSIxOW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIzMG1tIiB5PSIxOW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIzMW1tIiB5PSIxOW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIzMm1tIiB5PSIxOW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIzNG1tIiB5PSIxOW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIzNm1tIiB5PSIxOW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIzOG1tIiB5PSIxOW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI0MG1tIiB5PSIxOW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI0Mm1tIiB5PSIxOW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI0M21tIiB5PSIxOW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI0NG1tIiB5PSIxOW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI0Nm1tIiB5PSIxOW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI0N21tIiB5PSIxOW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI0OG1tIiB5PSIxOW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI0OW1tIiB5PSIxOW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI1MG1tIiB5PSIxOW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI1Mm1tIiB5PSIxOW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI0bW0iIHk9IjIwbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjhtbSIgeT0iMjBtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMTBtbSIgeT0iMjBtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMTNtbSIgeT0iMjBtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMTltbSIgeT0iMjBtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMjNtbSIgeT0iMjBtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMjhtbSIgeT0iMjBtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMzBtbSIgeT0iMjBtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMzFtbSIgeT0iMjBtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMzRtbSIgeT0iMjBtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMzVtbSIgeT0iMjBtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMzdtbSIgeT0iMjBtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iNDBtbSIgeT0iMjBtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iNDFtbSIgeT0iMjBtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iNDRtbSIgeT0iMjBtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iNDVtbSIgeT0iMjBtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iNDZtbSIgeT0iMjBtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iNTJtbSIgeT0iMjBtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iNG1tIiB5PSIyMW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI1bW0iIHk9IjIxbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjhtbSIgeT0iMjFtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iOW1tIiB5PSIyMW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIxMW1tIiB5PSIyMW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIxMm1tIiB5PSIyMW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIxNG1tIiB5PSIyMW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIxOG1tIiB5PSIyMW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIyMG1tIiB5PSIyMW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIyMW1tIiB5PSIyMW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIyMm1tIiB5PSIyMW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIyNG1tIiB5PSIyMW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIyNW1tIiB5PSIyMW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIyN21tIiB5PSIyMW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIyOG1tIiB5PSIyMW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIyOW1tIiB5PSIyMW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIzMW1tIiB5PSIyMW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIzMm1tIiB5PSIyMW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIzNG1tIiB5PSIyMW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIzOG1tIiB5PSIyMW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI0MG1tIiB5PSIyMW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI0MW1tIiB5PSIyMW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI0Mm1tIiB5PSIyMW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI0M21tIiB5PSIyMW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI0N21tIiB5PSIyMW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI0OG1tIiB5PSIyMW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI0OW1tIiB5PSIyMW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI1MW1tIiB5PSIyMW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI1Mm1tIiB5PSIyMW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI1bW0iIHk9IjIybW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjEwbW0iIHk9IjIybW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjExbW0iIHk9IjIybW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjE0bW0iIHk9IjIybW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjE2bW0iIHk9IjIybW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjE3bW0iIHk9IjIybW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjE5bW0iIHk9IjIybW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjIwbW0iIHk9IjIybW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjI1bW0iIHk9IjIybW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjI2bW0iIHk9IjIybW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjI4bW0iIHk9IjIybW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjMxbW0iIHk9IjIybW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjM2bW0iIHk9IjIybW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjM3bW0iIHk9IjIybW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjM4bW0iIHk9IjIybW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjQwbW0iIHk9IjIybW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjQybW0iIHk9IjIybW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjQ0bW0iIHk9IjIybW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjQ1bW0iIHk9IjIybW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjQ3bW0iIHk9IjIybW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjUwbW0iIHk9IjIybW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjltbSIgeT0iMjNtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMTNtbSIgeT0iMjNtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMTRtbSIgeT0iMjNtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMTVtbSIgeT0iMjNtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMTZtbSIgeT0iMjNtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMThtbSIgeT0iMjNtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMTltbSIgeT0iMjNtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMjFtbSIgeT0iMjNtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMjNtbSIgeT0iMjNtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMjRtbSIgeT0iMjNtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMjVtbSIgeT0iMjNtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMjdtbSIgeT0iMjNtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMzBtbSIgeT0iMjNtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMzFtbSIgeT0iMjNtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMzNtbSIgeT0iMjNtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMzRtbSIgeT0iMjNtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMzVtbSIgeT0iMjNtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMzZtbSIgeT0iMjNtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMzltbSIgeT0iMjNtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iNDBtbSIgeT0iMjNtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iNDdtbSIgeT0iMjNtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iNDltbSIgeT0iMjNtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iNG1tIiB5PSIyNG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIxMG1tIiB5PSIyNG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIxMW1tIiB5PSIyNG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIxMm1tIiB5PSIyNG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIxM21tIiB5PSIyNG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIxN21tIiB5PSIyNG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIxOG1tIiB5PSIyNG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIyMG1tIiB5PSIyNG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIyM21tIiB5PSIyNG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIyNG1tIiB5PSIyNG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIyNm1tIiB5PSIyNG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIzMW1tIiB5PSIyNG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIzMm1tIiB5PSIyNG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIzNG1tIiB5PSIyNG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIzOG1tIiB5PSIyNG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI0MW1tIiB5PSIyNG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI0M21tIiB5PSIyNG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI0NG1tIiB5PSIyNG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI0OW1tIiB5PSIyNG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI1MG1tIiB5PSIyNG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI1MW1tIiB5PSIyNG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI1bW0iIHk9IjI1bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjhtbSIgeT0iMjVtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iOW1tIiB5PSIyNW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIxMW1tIiB5PSIyNW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIxNG1tIiB5PSIyNW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIxNW1tIiB5PSIyNW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIxOG1tIiB5PSIyNW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIxOW1tIiB5PSIyNW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIyNG1tIiB5PSIyNW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIyN21tIiB5PSIyNW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIyOG1tIiB5PSIyNW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIzMm1tIiB5PSIyNW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIzN21tIiB5PSIyNW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIzOW1tIiB5PSIyNW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI0M21tIiB5PSIyNW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI0Nm1tIiB5PSIyNW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI0N21tIiB5PSIyNW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI1MW1tIiB5PSIyNW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI1bW0iIHk9IjI2bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjdtbSIgeT0iMjZtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iOG1tIiB5PSIyNm1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI5bW0iIHk9IjI2bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjEwbW0iIHk9IjI2bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjExbW0iIHk9IjI2bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjEybW0iIHk9IjI2bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjE0bW0iIHk9IjI2bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjE1bW0iIHk9IjI2bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjE4bW0iIHk9IjI2bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjE5bW0iIHk9IjI2bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjIxbW0iIHk9IjI2bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjIybW0iIHk9IjI2bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjIzbW0iIHk9IjI2bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjI2bW0iIHk9IjI2bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjI3bW0iIHk9IjI2bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjI4bW0iIHk9IjI2bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjI5bW0iIHk9IjI2bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjMwbW0iIHk9IjI2bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjMxbW0iIHk9IjI2bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjMzbW0iIHk9IjI2bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjM1bW0iIHk9IjI2bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjM4bW0iIHk9IjI2bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjQxbW0iIHk9IjI2bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjQybW0iIHk9IjI2bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjQzbW0iIHk9IjI2bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjQ0bW0iIHk9IjI2bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjQ1bW0iIHk9IjI2bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjQ2bW0iIHk9IjI2bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjQ3bW0iIHk9IjI2bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjQ4bW0iIHk9IjI2bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjUwbW0iIHk9IjI2bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjhtbSIgeT0iMjdtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMTJtbSIgeT0iMjdtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMTVtbSIgeT0iMjdtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMThtbSIgeT0iMjdtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMjRtbSIgeT0iMjdtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMjVtbSIgeT0iMjdtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMjZtbSIgeT0iMjdtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMzBtbSIgeT0iMjdtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMzNtbSIgeT0iMjdtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMzVtbSIgeT0iMjdtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMzdtbSIgeT0iMjdtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMzhtbSIgeT0iMjdtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMzltbSIgeT0iMjdtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iNDJtbSIgeT0iMjdtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iNDRtbSIgeT0iMjdtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iNDhtbSIgeT0iMjdtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iNDltbSIgeT0iMjdtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iNG1tIiB5PSIyOG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI1bW0iIHk9IjI4bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjZtbSIgeT0iMjhtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iOG1tIiB5PSIyOG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIxMG1tIiB5PSIyOG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIxMm1tIiB5PSIyOG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIxM21tIiB5PSIyOG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIxNG1tIiB5PSIyOG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIxNm1tIiB5PSIyOG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIxOG1tIiB5PSIyOG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIyMG1tIiB5PSIyOG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIyM21tIiB5PSIyOG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIyNG1tIiB5PSIyOG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIyNm1tIiB5PSIyOG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIyOG1tIiB5PSIyOG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIzMG1tIiB5PSIyOG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIzMW1tIiB5PSIyOG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIzNG1tIiB5PSIyOG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIzOG1tIiB5PSIyOG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI0MW1tIiB5PSIyOG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI0M21tIiB5PSIyOG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI0NG1tIiB5PSIyOG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI0Nm1tIiB5PSIyOG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI0OG1tIiB5PSIyOG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI1MG1tIiB5PSIyOG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI1MW1tIiB5PSIyOG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI1Mm1tIiB5PSIyOG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI0bW0iIHk9IjI5bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjVtbSIgeT0iMjltbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iOG1tIiB5PSIyOW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIxMm1tIiB5PSIyOW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIxM21tIiB5PSIyOW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIxNG1tIiB5PSIyOW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIxN21tIiB5PSIyOW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIxOG1tIiB5PSIyOW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIxOW1tIiB5PSIyOW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIyMW1tIiB5PSIyOW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIyMm1tIiB5PSIyOW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIyNG1tIiB5PSIyOW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIyNW1tIiB5PSIyOW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIyNm1tIiB5PSIyOW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIzMG1tIiB5PSIyOW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIzMW1tIiB5PSIyOW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIzMm1tIiB5PSIyOW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIzNG1tIiB5PSIyOW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIzN21tIiB5PSIyOW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI0MG1tIiB5PSIyOW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI0M21tIiB5PSIyOW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI0NG1tIiB5PSIyOW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI0OG1tIiB5PSIyOW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI0OW1tIiB5PSIyOW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI1MW1tIiB5PSIyOW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI0bW0iIHk9IjMwbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjZtbSIgeT0iMzBtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iN21tIiB5PSIzMG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI4bW0iIHk9IjMwbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjltbSIgeT0iMzBtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMTBtbSIgeT0iMzBtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMTFtbSIgeT0iMzBtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMTJtbSIgeT0iMzBtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMTNtbSIgeT0iMzBtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMTRtbSIgeT0iMzBtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMTZtbSIgeT0iMzBtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMTdtbSIgeT0iMzBtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMTltbSIgeT0iMzBtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMjFtbSIgeT0iMzBtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMjJtbSIgeT0iMzBtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMjVtbSIgeT0iMzBtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMjZtbSIgeT0iMzBtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMjdtbSIgeT0iMzBtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMjhtbSIgeT0iMzBtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMjltbSIgeT0iMzBtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMzBtbSIgeT0iMzBtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMzFtbSIgeT0iMzBtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMzNtbSIgeT0iMzBtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMzRtbSIgeT0iMzBtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMzVtbSIgeT0iMzBtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMzZtbSIgeT0iMzBtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMzltbSIgeT0iMzBtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iNDBtbSIgeT0iMzBtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iNDFtbSIgeT0iMzBtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iNDNtbSIgeT0iMzBtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iNDRtbSIgeT0iMzBtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iNDVtbSIgeT0iMzBtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iNDZtbSIgeT0iMzBtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iNDdtbSIgeT0iMzBtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iNDhtbSIgeT0iMzBtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iNW1tIiB5PSIzMW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI3bW0iIHk9IjMxbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjhtbSIgeT0iMzFtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iOW1tIiB5PSIzMW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIxMW1tIiB5PSIzMW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIxM21tIiB5PSIzMW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIxNG1tIiB5PSIzMW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIxNW1tIiB5PSIzMW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIxOW1tIiB5PSIzMW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIyMW1tIiB5PSIzMW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIyM21tIiB5PSIzMW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIyNm1tIiB5PSIzMW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIyOG1tIiB5PSIzMW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIyOW1tIiB5PSIzMW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIzNW1tIiB5PSIzMW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIzN21tIiB5PSIzMW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIzOW1tIiB5PSIzMW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI0Mm1tIiB5PSIzMW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI0M21tIiB5PSIzMW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI0NG1tIiB5PSIzMW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI0NW1tIiB5PSIzMW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI0Nm1tIiB5PSIzMW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI0N21tIiB5PSIzMW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI0OW1tIiB5PSIzMW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI1MG1tIiB5PSIzMW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI3bW0iIHk9IjMybW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjEwbW0iIHk9IjMybW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjE3bW0iIHk9IjMybW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjE4bW0iIHk9IjMybW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjIwbW0iIHk9IjMybW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjIxbW0iIHk9IjMybW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjIybW0iIHk9IjMybW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjI4bW0iIHk9IjMybW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjMwbW0iIHk9IjMybW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjMxbW0iIHk9IjMybW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjMybW0iIHk9IjMybW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjQxbW0iIHk9IjMybW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjQ0bW0iIHk9IjMybW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjQ4bW0iIHk9IjMybW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjUxbW0iIHk9IjMybW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjUybW0iIHk9IjMybW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjVtbSIgeT0iMzNtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iN21tIiB5PSIzM21tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI4bW0iIHk9IjMzbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjltbSIgeT0iMzNtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMTFtbSIgeT0iMzNtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMTNtbSIgeT0iMzNtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMTRtbSIgeT0iMzNtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMTVtbSIgeT0iMzNtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMThtbSIgeT0iMzNtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMjhtbSIgeT0iMzNtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMzFtbSIgeT0iMzNtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMzJtbSIgeT0iMzNtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMzNtbSIgeT0iMzNtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMzRtbSIgeT0iMzNtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMzVtbSIgeT0iMzNtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMzdtbSIgeT0iMzNtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMzhtbSIgeT0iMzNtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMzltbSIgeT0iMzNtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iNDNtbSIgeT0iMzNtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iNDRtbSIgeT0iMzNtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iNDVtbSIgeT0iMzNtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iNDZtbSIgeT0iMzNtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iNDhtbSIgeT0iMzNtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iNTBtbSIgeT0iMzNtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iNTJtbSIgeT0iMzNtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iNW1tIiB5PSIzNG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI3bW0iIHk9IjM0bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjltbSIgeT0iMzRtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMTBtbSIgeT0iMzRtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMTNtbSIgeT0iMzRtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMTZtbSIgeT0iMzRtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMjFtbSIgeT0iMzRtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMjVtbSIgeT0iMzRtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMjdtbSIgeT0iMzRtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMjhtbSIgeT0iMzRtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMzBtbSIgeT0iMzRtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMzFtbSIgeT0iMzRtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMzJtbSIgeT0iMzRtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMzNtbSIgeT0iMzRtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMzRtbSIgeT0iMzRtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMzdtbSIgeT0iMzRtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iNDBtbSIgeT0iMzRtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iNDFtbSIgeT0iMzRtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iNDJtbSIgeT0iMzRtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iNDNtbSIgeT0iMzRtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iNDRtbSIgeT0iMzRtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iNDZtbSIgeT0iMzRtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iNDhtbSIgeT0iMzRtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iNTJtbSIgeT0iMzRtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iNG1tIiB5PSIzNW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI2bW0iIHk9IjM1bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjhtbSIgeT0iMzVtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iOW1tIiB5PSIzNW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIxMW1tIiB5PSIzNW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIyMm1tIiB5PSIzNW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIyNW1tIiB5PSIzNW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIyOG1tIiB5PSIzNW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIyOW1tIiB5PSIzNW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIzMG1tIiB5PSIzNW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIzMW1tIiB5PSIzNW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIzM21tIiB5PSIzNW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIzNW1tIiB5PSIzNW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIzNm1tIiB5PSIzNW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI0M21tIiB5PSIzNW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI0NW1tIiB5PSIzNW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI0Nm1tIiB5PSIzNW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI0OW1tIiB5PSIzNW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI1MG1tIiB5PSIzNW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI1MW1tIiB5PSIzNW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI1Mm1tIiB5PSIzNW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI0bW0iIHk9IjM2bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjZtbSIgeT0iMzZtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iOW1tIiB5PSIzNm1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIxMG1tIiB5PSIzNm1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIxM21tIiB5PSIzNm1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIxNm1tIiB5PSIzNm1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIyMm1tIiB5PSIzNm1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIyNW1tIiB5PSIzNm1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIyNm1tIiB5PSIzNm1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIzMG1tIiB5PSIzNm1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIzMm1tIiB5PSIzNm1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIzM21tIiB5PSIzNm1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIzNG1tIiB5PSIzNm1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIzNW1tIiB5PSIzNm1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIzN21tIiB5PSIzNm1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIzOG1tIiB5PSIzNm1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI0MW1tIiB5PSIzNm1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI0Mm1tIiB5PSIzNm1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI0M21tIiB5PSIzNm1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI0NG1tIiB5PSIzNm1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI0N21tIiB5PSIzNm1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI0OW1tIiB5PSIzNm1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI1MW1tIiB5PSIzNm1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI1Mm1tIiB5PSIzNm1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI0bW0iIHk9IjM3bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjVtbSIgeT0iMzdtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iN21tIiB5PSIzN21tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI4bW0iIHk9IjM3bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjExbW0iIHk9IjM3bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjEybW0iIHk9IjM3bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjE0bW0iIHk9IjM3bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjE1bW0iIHk9IjM3bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjE4bW0iIHk9IjM3bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjIxbW0iIHk9IjM3bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjIybW0iIHk9IjM3bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjI0bW0iIHk9IjM3bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjI1bW0iIHk9IjM3bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjI2bW0iIHk9IjM3bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjI3bW0iIHk9IjM3bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjMwbW0iIHk9IjM3bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjM0bW0iIHk9IjM3bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjM2bW0iIHk9IjM3bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjM5bW0iIHk9IjM3bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjQwbW0iIHk9IjM3bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjQ4bW0iIHk9IjM3bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjUybW0iIHk9IjM3bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjRtbSIgeT0iMzhtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iNW1tIiB5PSIzOG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI2bW0iIHk9IjM4bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjhtbSIgeT0iMzhtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iOW1tIiB5PSIzOG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIxMG1tIiB5PSIzOG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIxNG1tIiB5PSIzOG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIxNW1tIiB5PSIzOG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIxNm1tIiB5PSIzOG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIxOG1tIiB5PSIzOG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIyMG1tIiB5PSIzOG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIyNG1tIiB5PSIzOG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIyN21tIiB5PSIzOG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIzMW1tIiB5PSIzOG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIzM21tIiB5PSIzOG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIzNG1tIiB5PSIzOG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIzNW1tIiB5PSIzOG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIzNm1tIiB5PSIzOG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIzN21tIiB5PSIzOG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIzOW1tIiB5PSIzOG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI0MG1tIiB5PSIzOG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI0MW1tIiB5PSIzOG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI0Mm1tIiB5PSIzOG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI0M21tIiB5PSIzOG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI0NG1tIiB5PSIzOG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI0NW1tIiB5PSIzOG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI0OW1tIiB5PSIzOG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI1MW1tIiB5PSIzOG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI1Mm1tIiB5PSIzOG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI2bW0iIHk9IjM5bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjdtbSIgeT0iMzltbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMTFtbSIgeT0iMzltbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMTJtbSIgeT0iMzltbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMTNtbSIgeT0iMzltbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMTRtbSIgeT0iMzltbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMTVtbSIgeT0iMzltbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMThtbSIgeT0iMzltbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMjBtbSIgeT0iMzltbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMjFtbSIgeT0iMzltbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMjRtbSIgeT0iMzltbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMjVtbSIgeT0iMzltbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMjhtbSIgeT0iMzltbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMjltbSIgeT0iMzltbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMzBtbSIgeT0iMzltbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMzFtbSIgeT0iMzltbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMzNtbSIgeT0iMzltbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMzdtbSIgeT0iMzltbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMzltbSIgeT0iMzltbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iNDBtbSIgeT0iMzltbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iNDJtbSIgeT0iMzltbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iNDNtbSIgeT0iMzltbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iNDVtbSIgeT0iMzltbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iNDdtbSIgeT0iMzltbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iNDhtbSIgeT0iMzltbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iNDltbSIgeT0iMzltbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iNTFtbSIgeT0iMzltbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iNTJtbSIgeT0iMzltbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iNW1tIiB5PSI0MG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI3bW0iIHk9IjQwbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjltbSIgeT0iNDBtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMTBtbSIgeT0iNDBtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMTFtbSIgeT0iNDBtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMTRtbSIgeT0iNDBtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMTVtbSIgeT0iNDBtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMTdtbSIgeT0iNDBtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMTltbSIgeT0iNDBtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMjJtbSIgeT0iNDBtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMjNtbSIgeT0iNDBtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMjdtbSIgeT0iNDBtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMjltbSIgeT0iNDBtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMzRtbSIgeT0iNDBtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iNDBtbSIgeT0iNDBtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iNDFtbSIgeT0iNDBtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iNDVtbSIgeT0iNDBtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iNDZtbSIgeT0iNDBtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iNDdtbSIgeT0iNDBtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iNDltbSIgeT0iNDBtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iNTJtbSIgeT0iNDBtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iOW1tIiB5PSI0MW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIxM21tIiB5PSI0MW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIxNW1tIiB5PSI0MW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIxNm1tIiB5PSI0MW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIxN21tIiB5PSI0MW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIyMG1tIiB5PSI0MW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIyMW1tIiB5PSI0MW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIyOG1tIiB5PSI0MW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIzNG1tIiB5PSI0MW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIzNW1tIiB5PSI0MW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIzN21tIiB5PSI0MW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIzOW1tIiB5PSI0MW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI0NG1tIiB5PSI0MW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI0NW1tIiB5PSI0MW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI0OW1tIiB5PSI0MW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI1MW1tIiB5PSI0MW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI1Mm1tIiB5PSI0MW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI1bW0iIHk9IjQybW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjltbSIgeT0iNDJtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMTBtbSIgeT0iNDJtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMTJtbSIgeT0iNDJtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMTRtbSIgeT0iNDJtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMThtbSIgeT0iNDJtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMTltbSIgeT0iNDJtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMjBtbSIgeT0iNDJtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMjRtbSIgeT0iNDJtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMjdtbSIgeT0iNDJtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMjltbSIgeT0iNDJtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMzJtbSIgeT0iNDJtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMzNtbSIgeT0iNDJtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMzRtbSIgeT0iNDJtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMzhtbSIgeT0iNDJtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iNDBtbSIgeT0iNDJtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iNDFtbSIgeT0iNDJtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iNDNtbSIgeT0iNDJtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iNDRtbSIgeT0iNDJtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iNDdtbSIgeT0iNDJtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iNTJtbSIgeT0iNDJtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iNW1tIiB5PSI0M21tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI2bW0iIHk9IjQzbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjdtbSIgeT0iNDNtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMTFtbSIgeT0iNDNtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMTJtbSIgeT0iNDNtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMTZtbSIgeT0iNDNtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMTdtbSIgeT0iNDNtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMTltbSIgeT0iNDNtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMjZtbSIgeT0iNDNtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMjhtbSIgeT0iNDNtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMzJtbSIgeT0iNDNtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMzVtbSIgeT0iNDNtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMzdtbSIgeT0iNDNtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMzhtbSIgeT0iNDNtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMzltbSIgeT0iNDNtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iNDFtbSIgeT0iNDNtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iNDRtbSIgeT0iNDNtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iNDVtbSIgeT0iNDNtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iNDltbSIgeT0iNDNtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iNTFtbSIgeT0iNDNtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iNG1tIiB5PSI0NG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI1bW0iIHk9IjQ0bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjZtbSIgeT0iNDRtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMTBtbSIgeT0iNDRtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMTFtbSIgeT0iNDRtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMTNtbSIgeT0iNDRtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMTRtbSIgeT0iNDRtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMTZtbSIgeT0iNDRtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMTdtbSIgeT0iNDRtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMThtbSIgeT0iNDRtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMjBtbSIgeT0iNDRtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMjNtbSIgeT0iNDRtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMjRtbSIgeT0iNDRtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMjVtbSIgeT0iNDRtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMjZtbSIgeT0iNDRtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMjdtbSIgeT0iNDRtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMjhtbSIgeT0iNDRtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMjltbSIgeT0iNDRtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMzBtbSIgeT0iNDRtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMzFtbSIgeT0iNDRtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMzJtbSIgeT0iNDRtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMzZtbSIgeT0iNDRtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iNDBtbSIgeT0iNDRtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iNDFtbSIgeT0iNDRtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iNDJtbSIgeT0iNDRtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iNDNtbSIgeT0iNDRtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iNDRtbSIgeT0iNDRtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iNDVtbSIgeT0iNDRtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iNDZtbSIgeT0iNDRtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iNDdtbSIgeT0iNDRtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iNDhtbSIgeT0iNDRtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iNTBtbSIgeT0iNDRtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iNTJtbSIgeT0iNDRtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMTJtbSIgeT0iNDVtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMTRtbSIgeT0iNDVtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMTVtbSIgeT0iNDVtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMThtbSIgeT0iNDVtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMjBtbSIgeT0iNDVtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMjZtbSIgeT0iNDVtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMzBtbSIgeT0iNDVtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMzFtbSIgeT0iNDVtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMzJtbSIgeT0iNDVtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMzVtbSIgeT0iNDVtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMzZtbSIgeT0iNDVtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMzdtbSIgeT0iNDVtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iNDBtbSIgeT0iNDVtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iNDJtbSIgeT0iNDVtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iNDNtbSIgeT0iNDVtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iNDRtbSIgeT0iNDVtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iNDhtbSIgeT0iNDVtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iNDltbSIgeT0iNDVtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iNTBtbSIgeT0iNDVtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iNTFtbSIgeT0iNDVtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iNTJtbSIgeT0iNDVtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iNG1tIiB5PSI0Nm1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI1bW0iIHk9IjQ2bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjZtbSIgeT0iNDZtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iN21tIiB5PSI0Nm1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI4bW0iIHk9IjQ2bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjltbSIgeT0iNDZtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMTBtbSIgeT0iNDZtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMTRtbSIgeT0iNDZtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMTZtbSIgeT0iNDZtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMTdtbSIgeT0iNDZtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMjBtbSIgeT0iNDZtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMjFtbSIgeT0iNDZtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMjVtbSIgeT0iNDZtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMjZtbSIgeT0iNDZtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMjhtbSIgeT0iNDZtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMzBtbSIgeT0iNDZtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMzFtbSIgeT0iNDZtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMzNtbSIgeT0iNDZtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMzVtbSIgeT0iNDZtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iNDFtbSIgeT0iNDZtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iNDJtbSIgeT0iNDZtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iNDNtbSIgeT0iNDZtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iNDRtbSIgeT0iNDZtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iNDZtbSIgeT0iNDZtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iNDhtbSIgeT0iNDZtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iNTJtbSIgeT0iNDZtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iNG1tIiB5PSI0N21tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIxMG1tIiB5PSI0N21tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIxMm1tIiB5PSI0N21tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIxM21tIiB5PSI0N21tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIxNG1tIiB5PSI0N21tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIxNW1tIiB5PSI0N21tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIxNm1tIiB5PSI0N21tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIxOW1tIiB5PSI0N21tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIyMG1tIiB5PSI0N21tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIyNG1tIiB5PSI0N21tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIyNW1tIiB5PSI0N21tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIyNm1tIiB5PSI0N21tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIzMG1tIiB5PSI0N21tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIzM21tIiB5PSI0N21tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIzNW1tIiB5PSI0N21tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIzNm1tIiB5PSI0N21tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIzN21tIiB5PSI0N21tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIzOG1tIiB5PSI0N21tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIzOW1tIiB5PSI0N21tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI0M21tIiB5PSI0N21tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI0NG1tIiB5PSI0N21tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI0OG1tIiB5PSI0N21tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI0OW1tIiB5PSI0N21tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI1Mm1tIiB5PSI0N21tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI0bW0iIHk9IjQ4bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjZtbSIgeT0iNDhtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iN21tIiB5PSI0OG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI4bW0iIHk9IjQ4bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjEwbW0iIHk9IjQ4bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjEybW0iIHk9IjQ4bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjEzbW0iIHk9IjQ4bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjE2bW0iIHk9IjQ4bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjE4bW0iIHk9IjQ4bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjE5bW0iIHk9IjQ4bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjIwbW0iIHk9IjQ4bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjIxbW0iIHk9IjQ4bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjI1bW0iIHk9IjQ4bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjI2bW0iIHk9IjQ4bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjI3bW0iIHk9IjQ4bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjI4bW0iIHk9IjQ4bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjI5bW0iIHk9IjQ4bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjMwbW0iIHk9IjQ4bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjMxbW0iIHk9IjQ4bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjMzbW0iIHk9IjQ4bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjM2bW0iIHk9IjQ4bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjM3bW0iIHk9IjQ4bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjQwbW0iIHk9IjQ4bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjQybW0iIHk9IjQ4bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjQzbW0iIHk9IjQ4bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjQ0bW0iIHk9IjQ4bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjQ1bW0iIHk9IjQ4bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjQ2bW0iIHk9IjQ4bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjQ3bW0iIHk9IjQ4bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjQ4bW0iIHk9IjQ4bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjUxbW0iIHk9IjQ4bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjRtbSIgeT0iNDltbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iNm1tIiB5PSI0OW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI3bW0iIHk9IjQ5bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjhtbSIgeT0iNDltbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMTBtbSIgeT0iNDltbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMTJtbSIgeT0iNDltbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMTNtbSIgeT0iNDltbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMTRtbSIgeT0iNDltbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMTVtbSIgeT0iNDltbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMTZtbSIgeT0iNDltbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMTltbSIgeT0iNDltbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMjBtbSIgeT0iNDltbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMjFtbSIgeT0iNDltbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMjJtbSIgeT0iNDltbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMjZtbSIgeT0iNDltbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMjdtbSIgeT0iNDltbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMzNtbSIgeT0iNDltbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMzVtbSIgeT0iNDltbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMzdtbSIgeT0iNDltbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iMzltbSIgeT0iNDltbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iNDdtbSIgeT0iNDltbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iNDhtbSIgeT0iNDltbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iNTJtbSIgeT0iNDltbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iNG1tIiB5PSI1MG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI2bW0iIHk9IjUwbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjdtbSIgeT0iNTBtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iOG1tIiB5PSI1MG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIxMG1tIiB5PSI1MG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIxMm1tIiB5PSI1MG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIxNm1tIiB5PSI1MG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIxOG1tIiB5PSI1MG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIxOW1tIiB5PSI1MG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIyMW1tIiB5PSI1MG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIyNW1tIiB5PSI1MG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIyOG1tIiB5PSI1MG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIyOW1tIiB5PSI1MG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIzMW1tIiB5PSI1MG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIzMm1tIiB5PSI1MG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIzOG1tIiB5PSI1MG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSIzOW1tIiB5PSI1MG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI0MG1tIiB5PSI1MG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI0MW1tIiB5PSI1MG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI0Mm1tIiB5PSI1MG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI0NG1tIiB5PSI1MG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI0Nm1tIiB5PSI1MG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI0OW1tIiB5PSI1MG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI1Mm1tIiB5PSI1MG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI0bW0iIHk9IjUxbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjEwbW0iIHk9IjUxbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjE0bW0iIHk9IjUxbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjE4bW0iIHk9IjUxbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjE5bW0iIHk9IjUxbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjIxbW0iIHk9IjUxbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjIzbW0iIHk9IjUxbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjI0bW0iIHk9IjUxbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjI1bW0iIHk9IjUxbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjI2bW0iIHk9IjUxbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjI3bW0iIHk9IjUxbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjI4bW0iIHk9IjUxbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjMybW0iIHk9IjUxbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjM0bW0iIHk9IjUxbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjM1bW0iIHk9IjUxbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjM2bW0iIHk9IjUxbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjM4bW0iIHk9IjUxbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjQxbW0iIHk9IjUxbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjQybW0iIHk9IjUxbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjQ0bW0iIHk9IjUxbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjQ4bW0iIHk9IjUxbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjQ5bW0iIHk9IjUxbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjUxbW0iIHk9IjUxbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjUybW0iIHk9IjUxbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjRtbSIgeT0iNTJtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iNW1tIiB5PSI1Mm1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI2bW0iIHk9IjUybW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjdtbSIgeT0iNTJtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHJlY3QgeD0iOG1tIiB5PSI1Mm1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48cmVjdCB4PSI5bW0iIHk9IjUybW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjEwbW0iIHk9IjUybW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjEybW0iIHk9IjUybW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjEzbW0iIHk9IjUybW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjE2bW0iIHk9IjUybW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjIybW0iIHk9IjUybW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjIzbW0iIHk9IjUybW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjI0bW0iIHk9IjUybW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjI2bW0iIHk9IjUybW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjI5bW0iIHk9IjUybW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjMxbW0iIHk9IjUybW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjMybW0iIHk9IjUybW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjMzbW0iIHk9IjUybW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjM1bW0iIHk9IjUybW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjM2bW0iIHk9IjUybW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjM3bW0iIHk9IjUybW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjM5bW0iIHk9IjUybW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjQwbW0iIHk9IjUybW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjQzbW0iIHk9IjUybW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjQ0bW0iIHk9IjUybW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjQ1bW0iIHk9IjUybW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjQ4bW0iIHk9IjUybW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjQ5bW0iIHk9IjUybW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxyZWN0IHg9IjUybW0iIHk9IjUybW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjwvc3ZnPg==" # noqa + expected = "data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0nMS4wJyBlbmNvZGluZz0nVVRGLTgnPz4KPHN2ZyB4bWxuczpzdmc9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB3aWR0aD0iNTdtbSIgaGVpZ2h0PSI1N21tIiB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHN2ZzpyZWN0IHg9IjRtbSIgeT0iNG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iNW1tIiB5PSI0bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI2bW0iIHk9IjRtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjdtbSIgeT0iNG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iOG1tIiB5PSI0bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI5bW0iIHk9IjRtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjEwbW0iIHk9IjRtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjE1bW0iIHk9IjRtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjE2bW0iIHk9IjRtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjE3bW0iIHk9IjRtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjE4bW0iIHk9IjRtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjE5bW0iIHk9IjRtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjIwbW0iIHk9IjRtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjI1bW0iIHk9IjRtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjI2bW0iIHk9IjRtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjI3bW0iIHk9IjRtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjMwbW0iIHk9IjRtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjMybW0iIHk9IjRtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjM0bW0iIHk9IjRtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjM1bW0iIHk9IjRtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjM2bW0iIHk9IjRtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjQwbW0iIHk9IjRtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjQ0bW0iIHk9IjRtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjQ2bW0iIHk9IjRtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjQ3bW0iIHk9IjRtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjQ4bW0iIHk9IjRtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjQ5bW0iIHk9IjRtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjUwbW0iIHk9IjRtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjUxbW0iIHk9IjRtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjUybW0iIHk9IjRtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjRtbSIgeT0iNW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMTBtbSIgeT0iNW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMTVtbSIgeT0iNW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMTZtbSIgeT0iNW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMjBtbSIgeT0iNW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMjFtbSIgeT0iNW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMjJtbSIgeT0iNW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMjZtbSIgeT0iNW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMjdtbSIgeT0iNW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMjhtbSIgeT0iNW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMjltbSIgeT0iNW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMzBtbSIgeT0iNW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMzFtbSIgeT0iNW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMzJtbSIgeT0iNW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMzVtbSIgeT0iNW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iNDBtbSIgeT0iNW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iNDFtbSIgeT0iNW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iNDJtbSIgeT0iNW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iNDNtbSIgeT0iNW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iNDRtbSIgeT0iNW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iNDZtbSIgeT0iNW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iNTJtbSIgeT0iNW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iNG1tIiB5PSI2bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI2bW0iIHk9IjZtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjdtbSIgeT0iNm1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iOG1tIiB5PSI2bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIxMG1tIiB5PSI2bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIxMm1tIiB5PSI2bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIxM21tIiB5PSI2bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIxOG1tIiB5PSI2bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIxOW1tIiB5PSI2bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIyMG1tIiB5PSI2bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIyMW1tIiB5PSI2bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIyNW1tIiB5PSI2bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIyNm1tIiB5PSI2bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIyOG1tIiB5PSI2bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIzMG1tIiB5PSI2bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIzMm1tIiB5PSI2bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIzN21tIiB5PSI2bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIzOG1tIiB5PSI2bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIzOW1tIiB5PSI2bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI0MW1tIiB5PSI2bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI0M21tIiB5PSI2bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI0NG1tIiB5PSI2bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI0Nm1tIiB5PSI2bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI0OG1tIiB5PSI2bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI0OW1tIiB5PSI2bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI1MG1tIiB5PSI2bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI1Mm1tIiB5PSI2bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI0bW0iIHk9IjdtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjZtbSIgeT0iN21tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iN21tIiB5PSI3bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI4bW0iIHk9IjdtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjEwbW0iIHk9IjdtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjEybW0iIHk9IjdtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjE3bW0iIHk9IjdtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjIwbW0iIHk9IjdtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjIxbW0iIHk9IjdtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjIybW0iIHk9IjdtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjIzbW0iIHk9IjdtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjI2bW0iIHk9IjdtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjMwbW0iIHk9IjdtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjMxbW0iIHk9IjdtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjM0bW0iIHk9IjdtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjM4bW0iIHk9IjdtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjQzbW0iIHk9IjdtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjQ2bW0iIHk9IjdtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjQ4bW0iIHk9IjdtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjQ5bW0iIHk9IjdtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjUwbW0iIHk9IjdtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjUybW0iIHk9IjdtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjRtbSIgeT0iOG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iNm1tIiB5PSI4bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI3bW0iIHk9IjhtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjhtbSIgeT0iOG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMTBtbSIgeT0iOG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMTJtbSIgeT0iOG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMTRtbSIgeT0iOG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMTVtbSIgeT0iOG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMTZtbSIgeT0iOG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMThtbSIgeT0iOG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMjFtbSIgeT0iOG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMjVtbSIgeT0iOG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMjZtbSIgeT0iOG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMjdtbSIgeT0iOG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMjhtbSIgeT0iOG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMjltbSIgeT0iOG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMzBtbSIgeT0iOG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMzFtbSIgeT0iOG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMzRtbSIgeT0iOG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMzZtbSIgeT0iOG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMzdtbSIgeT0iOG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iNDFtbSIgeT0iOG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iNDZtbSIgeT0iOG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iNDhtbSIgeT0iOG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iNDltbSIgeT0iOG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iNTBtbSIgeT0iOG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iNTJtbSIgeT0iOG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iNG1tIiB5PSI5bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIxMG1tIiB5PSI5bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIxMm1tIiB5PSI5bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIxNG1tIiB5PSI5bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIxOG1tIiB5PSI5bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIxOW1tIiB5PSI5bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIyMW1tIiB5PSI5bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIyMm1tIiB5PSI5bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIyM21tIiB5PSI5bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIyNW1tIiB5PSI5bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIyNm1tIiB5PSI5bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIzMG1tIiB5PSI5bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIzM21tIiB5PSI5bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI0MW1tIiB5PSI5bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI0Mm1tIiB5PSI5bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI0Nm1tIiB5PSI5bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI1Mm1tIiB5PSI5bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI0bW0iIHk9IjEwbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI1bW0iIHk9IjEwbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI2bW0iIHk9IjEwbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI3bW0iIHk9IjEwbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI4bW0iIHk9IjEwbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI5bW0iIHk9IjEwbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIxMG1tIiB5PSIxMG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMTJtbSIgeT0iMTBtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjE0bW0iIHk9IjEwbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIxNm1tIiB5PSIxMG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMThtbSIgeT0iMTBtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjIwbW0iIHk9IjEwbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIyMm1tIiB5PSIxMG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMjRtbSIgeT0iMTBtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjI2bW0iIHk9IjEwbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIyOG1tIiB5PSIxMG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMzBtbSIgeT0iMTBtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjMybW0iIHk9IjEwbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIzNG1tIiB5PSIxMG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMzZtbSIgeT0iMTBtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjM4bW0iIHk9IjEwbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI0MG1tIiB5PSIxMG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iNDJtbSIgeT0iMTBtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjQ0bW0iIHk9IjEwbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI0Nm1tIiB5PSIxMG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iNDdtbSIgeT0iMTBtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjQ4bW0iIHk9IjEwbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI0OW1tIiB5PSIxMG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iNTBtbSIgeT0iMTBtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjUxbW0iIHk9IjEwbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI1Mm1tIiB5PSIxMG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMTJtbSIgeT0iMTFtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjEzbW0iIHk9IjExbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIxNG1tIiB5PSIxMW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMTdtbSIgeT0iMTFtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjIwbW0iIHk9IjExbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIyMm1tIiB5PSIxMW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMjVtbSIgeT0iMTFtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjI2bW0iIHk9IjExbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIzMG1tIiB5PSIxMW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMzRtbSIgeT0iMTFtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjM1bW0iIHk9IjExbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIzNm1tIiB5PSIxMW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMzltbSIgeT0iMTFtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjQwbW0iIHk9IjExbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI0M21tIiB5PSIxMW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iNDRtbSIgeT0iMTFtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjRtbSIgeT0iMTJtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjZtbSIgeT0iMTJtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjdtbSIgeT0iMTJtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjhtbSIgeT0iMTJtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjltbSIgeT0iMTJtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjEwbW0iIHk9IjEybW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIxM21tIiB5PSIxMm1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMTZtbSIgeT0iMTJtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjIwbW0iIHk9IjEybW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIyMW1tIiB5PSIxMm1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMjNtbSIgeT0iMTJtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjI2bW0iIHk9IjEybW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIyN21tIiB5PSIxMm1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMjhtbSIgeT0iMTJtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjI5bW0iIHk9IjEybW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIzMG1tIiB5PSIxMm1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMzFtbSIgeT0iMTJtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjM4bW0iIHk9IjEybW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI0MG1tIiB5PSIxMm1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iNDFtbSIgeT0iMTJtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjQ2bW0iIHk9IjEybW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI0N21tIiB5PSIxMm1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iNDhtbSIgeT0iMTJtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjQ5bW0iIHk9IjEybW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI1MG1tIiB5PSIxMm1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iNG1tIiB5PSIxM21tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iNW1tIiB5PSIxM21tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iNm1tIiB5PSIxM21tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMTFtbSIgeT0iMTNtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjEybW0iIHk9IjEzbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIxNG1tIiB5PSIxM21tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMThtbSIgeT0iMTNtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjIwbW0iIHk9IjEzbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIyMW1tIiB5PSIxM21tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMjJtbSIgeT0iMTNtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjI4bW0iIHk9IjEzbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIzMG1tIiB5PSIxM21tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMzFtbSIgeT0iMTNtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjM3bW0iIHk9IjEzbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIzOG1tIiB5PSIxM21tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iNDBtbSIgeT0iMTNtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjQzbW0iIHk9IjEzbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI0NW1tIiB5PSIxM21tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iNDZtbSIgeT0iMTNtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjQ3bW0iIHk9IjEzbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI0OG1tIiB5PSIxM21tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iNDltbSIgeT0iMTNtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjUxbW0iIHk9IjEzbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI1Mm1tIiB5PSIxM21tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iNG1tIiB5PSIxNG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iNW1tIiB5PSIxNG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iNm1tIiB5PSIxNG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iN21tIiB5PSIxNG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iOW1tIiB5PSIxNG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMTBtbSIgeT0iMTRtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjEybW0iIHk9IjE0bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIxNG1tIiB5PSIxNG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMTVtbSIgeT0iMTRtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjE3bW0iIHk9IjE0bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIxOW1tIiB5PSIxNG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMjBtbSIgeT0iMTRtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjIybW0iIHk9IjE0bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIyNW1tIiB5PSIxNG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMjhtbSIgeT0iMTRtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjI5bW0iIHk9IjE0bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIzMG1tIiB5PSIxNG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMzFtbSIgeT0iMTRtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjMybW0iIHk9IjE0bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIzM21tIiB5PSIxNG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMzRtbSIgeT0iMTRtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjM2bW0iIHk9IjE0bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIzOG1tIiB5PSIxNG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMzltbSIgeT0iMTRtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjQxbW0iIHk9IjE0bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI0Mm1tIiB5PSIxNG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iNDRtbSIgeT0iMTRtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjUybW0iIHk9IjE0bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI0bW0iIHk9IjE1bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI3bW0iIHk9IjE1bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI4bW0iIHk9IjE1bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI5bW0iIHk9IjE1bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIxMW1tIiB5PSIxNW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMTNtbSIgeT0iMTVtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjE0bW0iIHk9IjE1bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIxNW1tIiB5PSIxNW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMTZtbSIgeT0iMTVtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjE3bW0iIHk9IjE1bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIyMG1tIiB5PSIxNW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMjVtbSIgeT0iMTVtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjI3bW0iIHk9IjE1bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIyOG1tIiB5PSIxNW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMjltbSIgeT0iMTVtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjM0bW0iIHk9IjE1bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIzNW1tIiB5PSIxNW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMzZtbSIgeT0iMTVtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjM3bW0iIHk9IjE1bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIzOW1tIiB5PSIxNW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iNDJtbSIgeT0iMTVtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjQ0bW0iIHk9IjE1bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI0Nm1tIiB5PSIxNW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iNDdtbSIgeT0iMTVtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjQ5bW0iIHk9IjE1bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI1Mm1tIiB5PSIxNW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iNG1tIiB5PSIxNm1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iNm1tIiB5PSIxNm1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iN21tIiB5PSIxNm1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iOG1tIiB5PSIxNm1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iOW1tIiB5PSIxNm1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMTBtbSIgeT0iMTZtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjE0bW0iIHk9IjE2bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIxNW1tIiB5PSIxNm1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMThtbSIgeT0iMTZtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjIybW0iIHk9IjE2bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIyNm1tIiB5PSIxNm1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMjhtbSIgeT0iMTZtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjMwbW0iIHk9IjE2bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIzMW1tIiB5PSIxNm1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMzRtbSIgeT0iMTZtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjM3bW0iIHk9IjE2bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI0MW1tIiB5PSIxNm1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iNDJtbSIgeT0iMTZtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjQ2bW0iIHk9IjE2bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI0OG1tIiB5PSIxNm1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iNTBtbSIgeT0iMTZtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjUxbW0iIHk9IjE2bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI1Mm1tIiB5PSIxNm1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iNm1tIiB5PSIxN21tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMTNtbSIgeT0iMTdtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjE0bW0iIHk9IjE3bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIxNW1tIiB5PSIxN21tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMTZtbSIgeT0iMTdtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjE3bW0iIHk9IjE3bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIxOG1tIiB5PSIxN21tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMTltbSIgeT0iMTdtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjIxbW0iIHk9IjE3bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIyMm1tIiB5PSIxN21tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMjNtbSIgeT0iMTdtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjI0bW0iIHk9IjE3bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIyOG1tIiB5PSIxN21tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMzBtbSIgeT0iMTdtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjMybW0iIHk9IjE3bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIzNG1tIiB5PSIxN21tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMzVtbSIgeT0iMTdtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjM2bW0iIHk9IjE3bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIzN21tIiB5PSIxN21tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMzhtbSIgeT0iMTdtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjM5bW0iIHk9IjE3bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI0Mm1tIiB5PSIxN21tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iNDNtbSIgeT0iMTdtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjQ1bW0iIHk9IjE3bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI0OG1tIiB5PSIxN21tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iNTBtbSIgeT0iMTdtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjUybW0iIHk9IjE3bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI1bW0iIHk9IjE4bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI2bW0iIHk9IjE4bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI3bW0iIHk9IjE4bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI4bW0iIHk9IjE4bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI5bW0iIHk9IjE4bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIxMG1tIiB5PSIxOG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMTFtbSIgeT0iMThtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjE0bW0iIHk9IjE4bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIxNW1tIiB5PSIxOG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMTdtbSIgeT0iMThtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjE4bW0iIHk9IjE4bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIxOW1tIiB5PSIxOG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMjJtbSIgeT0iMThtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjI0bW0iIHk9IjE4bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIyN21tIiB5PSIxOG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMjhtbSIgeT0iMThtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjI5bW0iIHk9IjE4bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIzMW1tIiB5PSIxOG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMzJtbSIgeT0iMThtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjM1bW0iIHk9IjE4bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIzOG1tIiB5PSIxOG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMzltbSIgeT0iMThtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjQwbW0iIHk9IjE4bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI0MW1tIiB5PSIxOG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iNDNtbSIgeT0iMThtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjQ2bW0iIHk9IjE4bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI0N21tIiB5PSIxOG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iNDltbSIgeT0iMThtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjUwbW0iIHk9IjE4bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI1Mm1tIiB5PSIxOG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iNG1tIiB5PSIxOW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iNm1tIiB5PSIxOW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iN21tIiB5PSIxOW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMTFtbSIgeT0iMTltbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjEzbW0iIHk9IjE5bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIxNW1tIiB5PSIxOW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMTZtbSIgeT0iMTltbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjE3bW0iIHk9IjE5bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIxOG1tIiB5PSIxOW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMTltbSIgeT0iMTltbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjIxbW0iIHk9IjE5bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIyMm1tIiB5PSIxOW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMjNtbSIgeT0iMTltbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjI0bW0iIHk9IjE5bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIyNm1tIiB5PSIxOW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMjdtbSIgeT0iMTltbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjI4bW0iIHk9IjE5bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIyOW1tIiB5PSIxOW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMzBtbSIgeT0iMTltbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjMxbW0iIHk9IjE5bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIzMm1tIiB5PSIxOW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMzRtbSIgeT0iMTltbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjM2bW0iIHk9IjE5bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIzOG1tIiB5PSIxOW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iNDBtbSIgeT0iMTltbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjQybW0iIHk9IjE5bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI0M21tIiB5PSIxOW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iNDRtbSIgeT0iMTltbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjQ2bW0iIHk9IjE5bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI0N21tIiB5PSIxOW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iNDhtbSIgeT0iMTltbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjQ5bW0iIHk9IjE5bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI1MG1tIiB5PSIxOW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iNTJtbSIgeT0iMTltbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjRtbSIgeT0iMjBtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjhtbSIgeT0iMjBtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjEwbW0iIHk9IjIwbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIxM21tIiB5PSIyMG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMTltbSIgeT0iMjBtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjIzbW0iIHk9IjIwbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIyOG1tIiB5PSIyMG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMzBtbSIgeT0iMjBtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjMxbW0iIHk9IjIwbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIzNG1tIiB5PSIyMG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMzVtbSIgeT0iMjBtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjM3bW0iIHk9IjIwbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI0MG1tIiB5PSIyMG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iNDFtbSIgeT0iMjBtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjQ0bW0iIHk9IjIwbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI0NW1tIiB5PSIyMG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iNDZtbSIgeT0iMjBtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjUybW0iIHk9IjIwbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI0bW0iIHk9IjIxbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI1bW0iIHk9IjIxbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI4bW0iIHk9IjIxbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI5bW0iIHk9IjIxbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIxMW1tIiB5PSIyMW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMTJtbSIgeT0iMjFtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjE0bW0iIHk9IjIxbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIxOG1tIiB5PSIyMW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMjBtbSIgeT0iMjFtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjIxbW0iIHk9IjIxbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIyMm1tIiB5PSIyMW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMjRtbSIgeT0iMjFtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjI1bW0iIHk9IjIxbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIyN21tIiB5PSIyMW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMjhtbSIgeT0iMjFtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjI5bW0iIHk9IjIxbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIzMW1tIiB5PSIyMW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMzJtbSIgeT0iMjFtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjM0bW0iIHk9IjIxbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIzOG1tIiB5PSIyMW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iNDBtbSIgeT0iMjFtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjQxbW0iIHk9IjIxbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI0Mm1tIiB5PSIyMW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iNDNtbSIgeT0iMjFtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjQ3bW0iIHk9IjIxbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI0OG1tIiB5PSIyMW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iNDltbSIgeT0iMjFtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjUxbW0iIHk9IjIxbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI1Mm1tIiB5PSIyMW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iNW1tIiB5PSIyMm1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMTBtbSIgeT0iMjJtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjExbW0iIHk9IjIybW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIxNG1tIiB5PSIyMm1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMTZtbSIgeT0iMjJtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjE3bW0iIHk9IjIybW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIxOW1tIiB5PSIyMm1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMjBtbSIgeT0iMjJtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjI1bW0iIHk9IjIybW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIyNm1tIiB5PSIyMm1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMjhtbSIgeT0iMjJtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjMxbW0iIHk9IjIybW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIzNm1tIiB5PSIyMm1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMzdtbSIgeT0iMjJtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjM4bW0iIHk9IjIybW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI0MG1tIiB5PSIyMm1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iNDJtbSIgeT0iMjJtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjQ0bW0iIHk9IjIybW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI0NW1tIiB5PSIyMm1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iNDdtbSIgeT0iMjJtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjUwbW0iIHk9IjIybW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI5bW0iIHk9IjIzbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIxM21tIiB5PSIyM21tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMTRtbSIgeT0iMjNtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjE1bW0iIHk9IjIzbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIxNm1tIiB5PSIyM21tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMThtbSIgeT0iMjNtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjE5bW0iIHk9IjIzbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIyMW1tIiB5PSIyM21tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMjNtbSIgeT0iMjNtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjI0bW0iIHk9IjIzbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIyNW1tIiB5PSIyM21tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMjdtbSIgeT0iMjNtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjMwbW0iIHk9IjIzbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIzMW1tIiB5PSIyM21tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMzNtbSIgeT0iMjNtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjM0bW0iIHk9IjIzbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIzNW1tIiB5PSIyM21tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMzZtbSIgeT0iMjNtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjM5bW0iIHk9IjIzbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI0MG1tIiB5PSIyM21tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iNDdtbSIgeT0iMjNtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjQ5bW0iIHk9IjIzbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI0bW0iIHk9IjI0bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIxMG1tIiB5PSIyNG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMTFtbSIgeT0iMjRtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjEybW0iIHk9IjI0bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIxM21tIiB5PSIyNG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMTdtbSIgeT0iMjRtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjE4bW0iIHk9IjI0bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIyMG1tIiB5PSIyNG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMjNtbSIgeT0iMjRtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjI0bW0iIHk9IjI0bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIyNm1tIiB5PSIyNG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMzFtbSIgeT0iMjRtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjMybW0iIHk9IjI0bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIzNG1tIiB5PSIyNG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMzhtbSIgeT0iMjRtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjQxbW0iIHk9IjI0bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI0M21tIiB5PSIyNG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iNDRtbSIgeT0iMjRtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjQ5bW0iIHk9IjI0bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI1MG1tIiB5PSIyNG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iNTFtbSIgeT0iMjRtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjVtbSIgeT0iMjVtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjhtbSIgeT0iMjVtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjltbSIgeT0iMjVtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjExbW0iIHk9IjI1bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIxNG1tIiB5PSIyNW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMTVtbSIgeT0iMjVtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjE4bW0iIHk9IjI1bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIxOW1tIiB5PSIyNW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMjRtbSIgeT0iMjVtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjI3bW0iIHk9IjI1bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIyOG1tIiB5PSIyNW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMzJtbSIgeT0iMjVtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjM3bW0iIHk9IjI1bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIzOW1tIiB5PSIyNW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iNDNtbSIgeT0iMjVtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjQ2bW0iIHk9IjI1bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI0N21tIiB5PSIyNW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iNTFtbSIgeT0iMjVtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjVtbSIgeT0iMjZtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjdtbSIgeT0iMjZtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjhtbSIgeT0iMjZtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjltbSIgeT0iMjZtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjEwbW0iIHk9IjI2bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIxMW1tIiB5PSIyNm1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMTJtbSIgeT0iMjZtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjE0bW0iIHk9IjI2bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIxNW1tIiB5PSIyNm1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMThtbSIgeT0iMjZtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjE5bW0iIHk9IjI2bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIyMW1tIiB5PSIyNm1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMjJtbSIgeT0iMjZtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjIzbW0iIHk9IjI2bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIyNm1tIiB5PSIyNm1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMjdtbSIgeT0iMjZtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjI4bW0iIHk9IjI2bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIyOW1tIiB5PSIyNm1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMzBtbSIgeT0iMjZtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjMxbW0iIHk9IjI2bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIzM21tIiB5PSIyNm1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMzVtbSIgeT0iMjZtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjM4bW0iIHk9IjI2bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI0MW1tIiB5PSIyNm1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iNDJtbSIgeT0iMjZtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjQzbW0iIHk9IjI2bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI0NG1tIiB5PSIyNm1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iNDVtbSIgeT0iMjZtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjQ2bW0iIHk9IjI2bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI0N21tIiB5PSIyNm1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iNDhtbSIgeT0iMjZtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjUwbW0iIHk9IjI2bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI4bW0iIHk9IjI3bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIxMm1tIiB5PSIyN21tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMTVtbSIgeT0iMjdtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjE4bW0iIHk9IjI3bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIyNG1tIiB5PSIyN21tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMjVtbSIgeT0iMjdtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjI2bW0iIHk9IjI3bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIzMG1tIiB5PSIyN21tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMzNtbSIgeT0iMjdtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjM1bW0iIHk9IjI3bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIzN21tIiB5PSIyN21tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMzhtbSIgeT0iMjdtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjM5bW0iIHk9IjI3bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI0Mm1tIiB5PSIyN21tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iNDRtbSIgeT0iMjdtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjQ4bW0iIHk9IjI3bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI0OW1tIiB5PSIyN21tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iNG1tIiB5PSIyOG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iNW1tIiB5PSIyOG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iNm1tIiB5PSIyOG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iOG1tIiB5PSIyOG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMTBtbSIgeT0iMjhtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjEybW0iIHk9IjI4bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIxM21tIiB5PSIyOG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMTRtbSIgeT0iMjhtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjE2bW0iIHk9IjI4bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIxOG1tIiB5PSIyOG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMjBtbSIgeT0iMjhtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjIzbW0iIHk9IjI4bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIyNG1tIiB5PSIyOG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMjZtbSIgeT0iMjhtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjI4bW0iIHk9IjI4bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIzMG1tIiB5PSIyOG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMzFtbSIgeT0iMjhtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjM0bW0iIHk9IjI4bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIzOG1tIiB5PSIyOG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iNDFtbSIgeT0iMjhtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjQzbW0iIHk9IjI4bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI0NG1tIiB5PSIyOG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iNDZtbSIgeT0iMjhtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjQ4bW0iIHk9IjI4bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI1MG1tIiB5PSIyOG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iNTFtbSIgeT0iMjhtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjUybW0iIHk9IjI4bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI0bW0iIHk9IjI5bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI1bW0iIHk9IjI5bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI4bW0iIHk9IjI5bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIxMm1tIiB5PSIyOW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMTNtbSIgeT0iMjltbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjE0bW0iIHk9IjI5bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIxN21tIiB5PSIyOW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMThtbSIgeT0iMjltbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjE5bW0iIHk9IjI5bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIyMW1tIiB5PSIyOW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMjJtbSIgeT0iMjltbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjI0bW0iIHk9IjI5bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIyNW1tIiB5PSIyOW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMjZtbSIgeT0iMjltbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjMwbW0iIHk9IjI5bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIzMW1tIiB5PSIyOW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMzJtbSIgeT0iMjltbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjM0bW0iIHk9IjI5bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIzN21tIiB5PSIyOW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iNDBtbSIgeT0iMjltbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjQzbW0iIHk9IjI5bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI0NG1tIiB5PSIyOW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iNDhtbSIgeT0iMjltbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjQ5bW0iIHk9IjI5bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI1MW1tIiB5PSIyOW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iNG1tIiB5PSIzMG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iNm1tIiB5PSIzMG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iN21tIiB5PSIzMG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iOG1tIiB5PSIzMG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iOW1tIiB5PSIzMG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMTBtbSIgeT0iMzBtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjExbW0iIHk9IjMwbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIxMm1tIiB5PSIzMG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMTNtbSIgeT0iMzBtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjE0bW0iIHk9IjMwbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIxNm1tIiB5PSIzMG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMTdtbSIgeT0iMzBtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjE5bW0iIHk9IjMwbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIyMW1tIiB5PSIzMG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMjJtbSIgeT0iMzBtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjI1bW0iIHk9IjMwbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIyNm1tIiB5PSIzMG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMjdtbSIgeT0iMzBtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjI4bW0iIHk9IjMwbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIyOW1tIiB5PSIzMG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMzBtbSIgeT0iMzBtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjMxbW0iIHk9IjMwbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIzM21tIiB5PSIzMG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMzRtbSIgeT0iMzBtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjM1bW0iIHk9IjMwbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIzNm1tIiB5PSIzMG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMzltbSIgeT0iMzBtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjQwbW0iIHk9IjMwbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI0MW1tIiB5PSIzMG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iNDNtbSIgeT0iMzBtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjQ0bW0iIHk9IjMwbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI0NW1tIiB5PSIzMG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iNDZtbSIgeT0iMzBtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjQ3bW0iIHk9IjMwbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI0OG1tIiB5PSIzMG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iNW1tIiB5PSIzMW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iN21tIiB5PSIzMW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iOG1tIiB5PSIzMW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iOW1tIiB5PSIzMW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMTFtbSIgeT0iMzFtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjEzbW0iIHk9IjMxbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIxNG1tIiB5PSIzMW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMTVtbSIgeT0iMzFtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjE5bW0iIHk9IjMxbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIyMW1tIiB5PSIzMW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMjNtbSIgeT0iMzFtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjI2bW0iIHk9IjMxbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIyOG1tIiB5PSIzMW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMjltbSIgeT0iMzFtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjM1bW0iIHk9IjMxbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIzN21tIiB5PSIzMW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMzltbSIgeT0iMzFtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjQybW0iIHk9IjMxbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI0M21tIiB5PSIzMW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iNDRtbSIgeT0iMzFtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjQ1bW0iIHk9IjMxbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI0Nm1tIiB5PSIzMW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iNDdtbSIgeT0iMzFtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjQ5bW0iIHk9IjMxbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI1MG1tIiB5PSIzMW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iN21tIiB5PSIzMm1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMTBtbSIgeT0iMzJtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjE3bW0iIHk9IjMybW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIxOG1tIiB5PSIzMm1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMjBtbSIgeT0iMzJtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjIxbW0iIHk9IjMybW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIyMm1tIiB5PSIzMm1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMjhtbSIgeT0iMzJtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjMwbW0iIHk9IjMybW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIzMW1tIiB5PSIzMm1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMzJtbSIgeT0iMzJtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjQxbW0iIHk9IjMybW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI0NG1tIiB5PSIzMm1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iNDhtbSIgeT0iMzJtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjUxbW0iIHk9IjMybW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI1Mm1tIiB5PSIzMm1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iNW1tIiB5PSIzM21tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iN21tIiB5PSIzM21tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iOG1tIiB5PSIzM21tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iOW1tIiB5PSIzM21tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMTFtbSIgeT0iMzNtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjEzbW0iIHk9IjMzbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIxNG1tIiB5PSIzM21tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMTVtbSIgeT0iMzNtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjE4bW0iIHk9IjMzbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIyOG1tIiB5PSIzM21tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMzFtbSIgeT0iMzNtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjMybW0iIHk9IjMzbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIzM21tIiB5PSIzM21tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMzRtbSIgeT0iMzNtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjM1bW0iIHk9IjMzbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIzN21tIiB5PSIzM21tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMzhtbSIgeT0iMzNtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjM5bW0iIHk9IjMzbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI0M21tIiB5PSIzM21tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iNDRtbSIgeT0iMzNtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjQ1bW0iIHk9IjMzbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI0Nm1tIiB5PSIzM21tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iNDhtbSIgeT0iMzNtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjUwbW0iIHk9IjMzbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI1Mm1tIiB5PSIzM21tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iNW1tIiB5PSIzNG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iN21tIiB5PSIzNG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iOW1tIiB5PSIzNG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMTBtbSIgeT0iMzRtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjEzbW0iIHk9IjM0bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIxNm1tIiB5PSIzNG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMjFtbSIgeT0iMzRtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjI1bW0iIHk9IjM0bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIyN21tIiB5PSIzNG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMjhtbSIgeT0iMzRtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjMwbW0iIHk9IjM0bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIzMW1tIiB5PSIzNG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMzJtbSIgeT0iMzRtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjMzbW0iIHk9IjM0bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIzNG1tIiB5PSIzNG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMzdtbSIgeT0iMzRtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjQwbW0iIHk9IjM0bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI0MW1tIiB5PSIzNG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iNDJtbSIgeT0iMzRtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjQzbW0iIHk9IjM0bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI0NG1tIiB5PSIzNG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iNDZtbSIgeT0iMzRtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjQ4bW0iIHk9IjM0bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI1Mm1tIiB5PSIzNG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iNG1tIiB5PSIzNW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iNm1tIiB5PSIzNW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iOG1tIiB5PSIzNW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iOW1tIiB5PSIzNW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMTFtbSIgeT0iMzVtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjIybW0iIHk9IjM1bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIyNW1tIiB5PSIzNW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMjhtbSIgeT0iMzVtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjI5bW0iIHk9IjM1bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIzMG1tIiB5PSIzNW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMzFtbSIgeT0iMzVtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjMzbW0iIHk9IjM1bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIzNW1tIiB5PSIzNW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMzZtbSIgeT0iMzVtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjQzbW0iIHk9IjM1bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI0NW1tIiB5PSIzNW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iNDZtbSIgeT0iMzVtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjQ5bW0iIHk9IjM1bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI1MG1tIiB5PSIzNW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iNTFtbSIgeT0iMzVtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjUybW0iIHk9IjM1bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI0bW0iIHk9IjM2bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI2bW0iIHk9IjM2bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI5bW0iIHk9IjM2bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIxMG1tIiB5PSIzNm1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMTNtbSIgeT0iMzZtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjE2bW0iIHk9IjM2bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIyMm1tIiB5PSIzNm1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMjVtbSIgeT0iMzZtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjI2bW0iIHk9IjM2bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIzMG1tIiB5PSIzNm1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMzJtbSIgeT0iMzZtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjMzbW0iIHk9IjM2bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIzNG1tIiB5PSIzNm1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMzVtbSIgeT0iMzZtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjM3bW0iIHk9IjM2bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIzOG1tIiB5PSIzNm1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iNDFtbSIgeT0iMzZtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjQybW0iIHk9IjM2bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI0M21tIiB5PSIzNm1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iNDRtbSIgeT0iMzZtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjQ3bW0iIHk9IjM2bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI0OW1tIiB5PSIzNm1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iNTFtbSIgeT0iMzZtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjUybW0iIHk9IjM2bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI0bW0iIHk9IjM3bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI1bW0iIHk9IjM3bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI3bW0iIHk9IjM3bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI4bW0iIHk9IjM3bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIxMW1tIiB5PSIzN21tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMTJtbSIgeT0iMzdtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjE0bW0iIHk9IjM3bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIxNW1tIiB5PSIzN21tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMThtbSIgeT0iMzdtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjIxbW0iIHk9IjM3bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIyMm1tIiB5PSIzN21tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMjRtbSIgeT0iMzdtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjI1bW0iIHk9IjM3bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIyNm1tIiB5PSIzN21tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMjdtbSIgeT0iMzdtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjMwbW0iIHk9IjM3bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIzNG1tIiB5PSIzN21tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMzZtbSIgeT0iMzdtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjM5bW0iIHk9IjM3bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI0MG1tIiB5PSIzN21tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iNDhtbSIgeT0iMzdtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjUybW0iIHk9IjM3bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI0bW0iIHk9IjM4bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI1bW0iIHk9IjM4bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI2bW0iIHk9IjM4bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI4bW0iIHk9IjM4bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI5bW0iIHk9IjM4bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIxMG1tIiB5PSIzOG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMTRtbSIgeT0iMzhtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjE1bW0iIHk9IjM4bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIxNm1tIiB5PSIzOG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMThtbSIgeT0iMzhtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjIwbW0iIHk9IjM4bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIyNG1tIiB5PSIzOG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMjdtbSIgeT0iMzhtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjMxbW0iIHk9IjM4bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIzM21tIiB5PSIzOG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMzRtbSIgeT0iMzhtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjM1bW0iIHk9IjM4bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIzNm1tIiB5PSIzOG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMzdtbSIgeT0iMzhtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjM5bW0iIHk9IjM4bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI0MG1tIiB5PSIzOG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iNDFtbSIgeT0iMzhtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjQybW0iIHk9IjM4bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI0M21tIiB5PSIzOG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iNDRtbSIgeT0iMzhtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjQ1bW0iIHk9IjM4bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI0OW1tIiB5PSIzOG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iNTFtbSIgeT0iMzhtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjUybW0iIHk9IjM4bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI2bW0iIHk9IjM5bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI3bW0iIHk9IjM5bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIxMW1tIiB5PSIzOW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMTJtbSIgeT0iMzltbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjEzbW0iIHk9IjM5bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIxNG1tIiB5PSIzOW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMTVtbSIgeT0iMzltbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjE4bW0iIHk9IjM5bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIyMG1tIiB5PSIzOW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMjFtbSIgeT0iMzltbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjI0bW0iIHk9IjM5bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIyNW1tIiB5PSIzOW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMjhtbSIgeT0iMzltbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjI5bW0iIHk9IjM5bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIzMG1tIiB5PSIzOW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMzFtbSIgeT0iMzltbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjMzbW0iIHk9IjM5bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIzN21tIiB5PSIzOW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMzltbSIgeT0iMzltbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjQwbW0iIHk9IjM5bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI0Mm1tIiB5PSIzOW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iNDNtbSIgeT0iMzltbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjQ1bW0iIHk9IjM5bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI0N21tIiB5PSIzOW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iNDhtbSIgeT0iMzltbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjQ5bW0iIHk9IjM5bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI1MW1tIiB5PSIzOW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iNTJtbSIgeT0iMzltbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjVtbSIgeT0iNDBtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjdtbSIgeT0iNDBtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjltbSIgeT0iNDBtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjEwbW0iIHk9IjQwbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIxMW1tIiB5PSI0MG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMTRtbSIgeT0iNDBtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjE1bW0iIHk9IjQwbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIxN21tIiB5PSI0MG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMTltbSIgeT0iNDBtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjIybW0iIHk9IjQwbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIyM21tIiB5PSI0MG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMjdtbSIgeT0iNDBtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjI5bW0iIHk9IjQwbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIzNG1tIiB5PSI0MG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iNDBtbSIgeT0iNDBtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjQxbW0iIHk9IjQwbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI0NW1tIiB5PSI0MG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iNDZtbSIgeT0iNDBtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjQ3bW0iIHk9IjQwbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI0OW1tIiB5PSI0MG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iNTJtbSIgeT0iNDBtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjltbSIgeT0iNDFtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjEzbW0iIHk9IjQxbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIxNW1tIiB5PSI0MW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMTZtbSIgeT0iNDFtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjE3bW0iIHk9IjQxbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIyMG1tIiB5PSI0MW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMjFtbSIgeT0iNDFtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjI4bW0iIHk9IjQxbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIzNG1tIiB5PSI0MW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMzVtbSIgeT0iNDFtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjM3bW0iIHk9IjQxbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIzOW1tIiB5PSI0MW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iNDRtbSIgeT0iNDFtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjQ1bW0iIHk9IjQxbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI0OW1tIiB5PSI0MW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iNTFtbSIgeT0iNDFtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjUybW0iIHk9IjQxbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI1bW0iIHk9IjQybW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI5bW0iIHk9IjQybW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIxMG1tIiB5PSI0Mm1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMTJtbSIgeT0iNDJtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjE0bW0iIHk9IjQybW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIxOG1tIiB5PSI0Mm1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMTltbSIgeT0iNDJtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjIwbW0iIHk9IjQybW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIyNG1tIiB5PSI0Mm1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMjdtbSIgeT0iNDJtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjI5bW0iIHk9IjQybW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIzMm1tIiB5PSI0Mm1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMzNtbSIgeT0iNDJtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjM0bW0iIHk9IjQybW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIzOG1tIiB5PSI0Mm1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iNDBtbSIgeT0iNDJtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjQxbW0iIHk9IjQybW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI0M21tIiB5PSI0Mm1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iNDRtbSIgeT0iNDJtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjQ3bW0iIHk9IjQybW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI1Mm1tIiB5PSI0Mm1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iNW1tIiB5PSI0M21tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iNm1tIiB5PSI0M21tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iN21tIiB5PSI0M21tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMTFtbSIgeT0iNDNtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjEybW0iIHk9IjQzbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIxNm1tIiB5PSI0M21tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMTdtbSIgeT0iNDNtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjE5bW0iIHk9IjQzbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIyNm1tIiB5PSI0M21tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMjhtbSIgeT0iNDNtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjMybW0iIHk9IjQzbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIzNW1tIiB5PSI0M21tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMzdtbSIgeT0iNDNtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjM4bW0iIHk9IjQzbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIzOW1tIiB5PSI0M21tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iNDFtbSIgeT0iNDNtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjQ0bW0iIHk9IjQzbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI0NW1tIiB5PSI0M21tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iNDltbSIgeT0iNDNtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjUxbW0iIHk9IjQzbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI0bW0iIHk9IjQ0bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI1bW0iIHk9IjQ0bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI2bW0iIHk9IjQ0bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIxMG1tIiB5PSI0NG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMTFtbSIgeT0iNDRtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjEzbW0iIHk9IjQ0bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIxNG1tIiB5PSI0NG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMTZtbSIgeT0iNDRtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjE3bW0iIHk9IjQ0bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIxOG1tIiB5PSI0NG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMjBtbSIgeT0iNDRtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjIzbW0iIHk9IjQ0bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIyNG1tIiB5PSI0NG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMjVtbSIgeT0iNDRtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjI2bW0iIHk9IjQ0bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIyN21tIiB5PSI0NG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMjhtbSIgeT0iNDRtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjI5bW0iIHk9IjQ0bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIzMG1tIiB5PSI0NG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMzFtbSIgeT0iNDRtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjMybW0iIHk9IjQ0bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIzNm1tIiB5PSI0NG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iNDBtbSIgeT0iNDRtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjQxbW0iIHk9IjQ0bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI0Mm1tIiB5PSI0NG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iNDNtbSIgeT0iNDRtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjQ0bW0iIHk9IjQ0bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI0NW1tIiB5PSI0NG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iNDZtbSIgeT0iNDRtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjQ3bW0iIHk9IjQ0bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI0OG1tIiB5PSI0NG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iNTBtbSIgeT0iNDRtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjUybW0iIHk9IjQ0bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIxMm1tIiB5PSI0NW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMTRtbSIgeT0iNDVtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjE1bW0iIHk9IjQ1bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIxOG1tIiB5PSI0NW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMjBtbSIgeT0iNDVtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjI2bW0iIHk9IjQ1bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIzMG1tIiB5PSI0NW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMzFtbSIgeT0iNDVtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjMybW0iIHk9IjQ1bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIzNW1tIiB5PSI0NW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMzZtbSIgeT0iNDVtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjM3bW0iIHk9IjQ1bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI0MG1tIiB5PSI0NW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iNDJtbSIgeT0iNDVtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjQzbW0iIHk9IjQ1bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI0NG1tIiB5PSI0NW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iNDhtbSIgeT0iNDVtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjQ5bW0iIHk9IjQ1bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI1MG1tIiB5PSI0NW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iNTFtbSIgeT0iNDVtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjUybW0iIHk9IjQ1bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI0bW0iIHk9IjQ2bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI1bW0iIHk9IjQ2bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI2bW0iIHk9IjQ2bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI3bW0iIHk9IjQ2bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI4bW0iIHk9IjQ2bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI5bW0iIHk9IjQ2bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIxMG1tIiB5PSI0Nm1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMTRtbSIgeT0iNDZtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjE2bW0iIHk9IjQ2bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIxN21tIiB5PSI0Nm1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMjBtbSIgeT0iNDZtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjIxbW0iIHk9IjQ2bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIyNW1tIiB5PSI0Nm1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMjZtbSIgeT0iNDZtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjI4bW0iIHk9IjQ2bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIzMG1tIiB5PSI0Nm1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMzFtbSIgeT0iNDZtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjMzbW0iIHk9IjQ2bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIzNW1tIiB5PSI0Nm1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iNDFtbSIgeT0iNDZtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjQybW0iIHk9IjQ2bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI0M21tIiB5PSI0Nm1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iNDRtbSIgeT0iNDZtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjQ2bW0iIHk9IjQ2bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI0OG1tIiB5PSI0Nm1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iNTJtbSIgeT0iNDZtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjRtbSIgeT0iNDdtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjEwbW0iIHk9IjQ3bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIxMm1tIiB5PSI0N21tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMTNtbSIgeT0iNDdtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjE0bW0iIHk9IjQ3bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIxNW1tIiB5PSI0N21tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMTZtbSIgeT0iNDdtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjE5bW0iIHk9IjQ3bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIyMG1tIiB5PSI0N21tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMjRtbSIgeT0iNDdtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjI1bW0iIHk9IjQ3bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIyNm1tIiB5PSI0N21tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMzBtbSIgeT0iNDdtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjMzbW0iIHk9IjQ3bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIzNW1tIiB5PSI0N21tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMzZtbSIgeT0iNDdtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjM3bW0iIHk9IjQ3bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIzOG1tIiB5PSI0N21tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMzltbSIgeT0iNDdtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjQzbW0iIHk9IjQ3bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI0NG1tIiB5PSI0N21tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iNDhtbSIgeT0iNDdtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjQ5bW0iIHk9IjQ3bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI1Mm1tIiB5PSI0N21tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iNG1tIiB5PSI0OG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iNm1tIiB5PSI0OG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iN21tIiB5PSI0OG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iOG1tIiB5PSI0OG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMTBtbSIgeT0iNDhtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjEybW0iIHk9IjQ4bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIxM21tIiB5PSI0OG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMTZtbSIgeT0iNDhtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjE4bW0iIHk9IjQ4bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIxOW1tIiB5PSI0OG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMjBtbSIgeT0iNDhtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjIxbW0iIHk9IjQ4bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIyNW1tIiB5PSI0OG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMjZtbSIgeT0iNDhtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjI3bW0iIHk9IjQ4bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIyOG1tIiB5PSI0OG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMjltbSIgeT0iNDhtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjMwbW0iIHk9IjQ4bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIzMW1tIiB5PSI0OG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMzNtbSIgeT0iNDhtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjM2bW0iIHk9IjQ4bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIzN21tIiB5PSI0OG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iNDBtbSIgeT0iNDhtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjQybW0iIHk9IjQ4bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI0M21tIiB5PSI0OG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iNDRtbSIgeT0iNDhtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjQ1bW0iIHk9IjQ4bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI0Nm1tIiB5PSI0OG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iNDdtbSIgeT0iNDhtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjQ4bW0iIHk9IjQ4bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI1MW1tIiB5PSI0OG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iNG1tIiB5PSI0OW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iNm1tIiB5PSI0OW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iN21tIiB5PSI0OW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iOG1tIiB5PSI0OW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMTBtbSIgeT0iNDltbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjEybW0iIHk9IjQ5bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIxM21tIiB5PSI0OW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMTRtbSIgeT0iNDltbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjE1bW0iIHk9IjQ5bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIxNm1tIiB5PSI0OW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMTltbSIgeT0iNDltbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjIwbW0iIHk9IjQ5bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIyMW1tIiB5PSI0OW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMjJtbSIgeT0iNDltbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjI2bW0iIHk9IjQ5bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIyN21tIiB5PSI0OW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMzNtbSIgeT0iNDltbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjM1bW0iIHk9IjQ5bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIzN21tIiB5PSI0OW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMzltbSIgeT0iNDltbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjQ3bW0iIHk9IjQ5bW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI0OG1tIiB5PSI0OW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iNTJtbSIgeT0iNDltbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjRtbSIgeT0iNTBtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjZtbSIgeT0iNTBtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjdtbSIgeT0iNTBtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjhtbSIgeT0iNTBtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjEwbW0iIHk9IjUwbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIxMm1tIiB5PSI1MG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMTZtbSIgeT0iNTBtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjE4bW0iIHk9IjUwbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIxOW1tIiB5PSI1MG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMjFtbSIgeT0iNTBtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjI1bW0iIHk9IjUwbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIyOG1tIiB5PSI1MG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMjltbSIgeT0iNTBtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjMxbW0iIHk9IjUwbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIzMm1tIiB5PSI1MG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMzhtbSIgeT0iNTBtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjM5bW0iIHk9IjUwbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI0MG1tIiB5PSI1MG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iNDFtbSIgeT0iNTBtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjQybW0iIHk9IjUwbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI0NG1tIiB5PSI1MG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iNDZtbSIgeT0iNTBtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjQ5bW0iIHk9IjUwbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI1Mm1tIiB5PSI1MG1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iNG1tIiB5PSI1MW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMTBtbSIgeT0iNTFtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjE0bW0iIHk9IjUxbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIxOG1tIiB5PSI1MW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMTltbSIgeT0iNTFtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjIxbW0iIHk9IjUxbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIyM21tIiB5PSI1MW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMjRtbSIgeT0iNTFtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjI1bW0iIHk9IjUxbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIyNm1tIiB5PSI1MW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMjdtbSIgeT0iNTFtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjI4bW0iIHk9IjUxbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIzMm1tIiB5PSI1MW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMzRtbSIgeT0iNTFtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjM1bW0iIHk9IjUxbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIzNm1tIiB5PSI1MW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMzhtbSIgeT0iNTFtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjQxbW0iIHk9IjUxbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI0Mm1tIiB5PSI1MW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iNDRtbSIgeT0iNTFtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjQ4bW0iIHk9IjUxbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI0OW1tIiB5PSI1MW1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iNTFtbSIgeT0iNTFtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjUybW0iIHk9IjUxbW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI0bW0iIHk9IjUybW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI1bW0iIHk9IjUybW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI2bW0iIHk9IjUybW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI3bW0iIHk9IjUybW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI4bW0iIHk9IjUybW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI5bW0iIHk9IjUybW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIxMG1tIiB5PSI1Mm1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMTJtbSIgeT0iNTJtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjEzbW0iIHk9IjUybW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIxNm1tIiB5PSI1Mm1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMjJtbSIgeT0iNTJtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjIzbW0iIHk9IjUybW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIyNG1tIiB5PSI1Mm1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMjZtbSIgeT0iNTJtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjI5bW0iIHk9IjUybW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIzMW1tIiB5PSI1Mm1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMzJtbSIgeT0iNTJtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjMzbW0iIHk9IjUybW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIzNW1tIiB5PSI1Mm1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iMzZtbSIgeT0iNTJtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjM3bW0iIHk9IjUybW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSIzOW1tIiB5PSI1Mm1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iNDBtbSIgeT0iNTJtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjQzbW0iIHk9IjUybW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI0NG1tIiB5PSI1Mm1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iNDVtbSIgeT0iNTJtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PHN2ZzpyZWN0IHg9IjQ4bW0iIHk9IjUybW0iIHdpZHRoPSIxbW0iIGhlaWdodD0iMW1tIiAvPjxzdmc6cmVjdCB4PSI0OW1tIiB5PSI1Mm1tIiB3aWR0aD0iMW1tIiBoZWlnaHQ9IjFtbSIgLz48c3ZnOnJlY3QgeD0iNTJtbSIgeT0iNTJtbSIgd2lkdGg9IjFtbSIgaGVpZ2h0PSIxbW0iIC8+PC9zdmc+" # noqa self.assertEqual(result, expected) diff --git a/tests/utils.py b/tests/utils.py index dab4863e..ef036253 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -1,6 +1,8 @@ from unittest import TestCase from unittest.mock import patch import json +from requests import Timeout + import responses from responses import registries @@ -82,6 +84,9 @@ def build_auth_success_response(self, call_count): data = json.dumps(self.__auth_success_201_data(call_count)) return status, headers, data + def raise_timeout(self): + raise Timeout() + @staticmethod def __auth_fail_401_data(call_count): return { @@ -115,6 +120,7 @@ def set_auth(self, number_of_retries_to_success: int = 0): self.mock_responses.reset() def auth_request(request): + call_count = self.__get_auth_request().call_count + 1 never_fail = number_of_retries_to_success == 0 diff --git a/tests/wrapper/test_request.py b/tests/wrapper/test_request.py index 8532e507..eaa46506 100644 --- a/tests/wrapper/test_request.py +++ b/tests/wrapper/test_request.py @@ -1,13 +1,19 @@ -from unittest.mock import patch, MagicMock +from unittest.mock import patch +import responses from requests import Timeout from py_bdd_context import BDDContextTestCase from bb_wrapper.wrapper.request import RequestsWrapper +from tests.utils import MockedRequestsTestCase, IsolatedEnvTestCase -class RequestsWrapperTestCase(BDDContextTestCase): + +class RequestsWrapperTestCase( + BDDContextTestCase, MockedRequestsTestCase, IsolatedEnvTestCase +): maxDiff = None + @MockedRequestsTestCase.no_auth def test_contruct_url_1(self): with self.given( """ @@ -34,6 +40,7 @@ def test_contruct_url_1(self): self.assertEqual(result, expected) + @MockedRequestsTestCase.no_auth def test_contruct_url_2(self): with self.given( """ @@ -61,6 +68,7 @@ def test_contruct_url_2(self): self.assertEqual(result, expected) + @MockedRequestsTestCase.no_auth def test_contruct_url_3(self): with self.given( """ @@ -89,19 +97,21 @@ def test_contruct_url_3(self): self.assertEqual(result, expected) - def test_request_timeout(self): + @MockedRequestsTestCase.no_auth + def test_request_timeout_1(self): + with self.given( """ - uma requisição qualquer """ ): + self.mock_responses.stop() self.headers_patcher = patch( "bb_wrapper.wrapper.request.RequestsWrapper._get_request_info" ) self.mocked_headers = self.headers_patcher.start() self.mocked_headers.return_value = {} - wrapper = RequestsWrapper(base_url="", timeout=2) with self.when( @@ -120,21 +130,66 @@ def test_request_timeout(self): ): self.headers_patcher.stop() - @patch("bb_wrapper.wrapper.request.requests") - def test_retry_request(self, mock_requests): + @MockedRequestsTestCase.no_auth + def test_request_timeout_2(self): with self.given( """ - uma requisição qualquer """ ): + url = "http://foo.com" + self.headers_patcher = patch( "bb_wrapper.wrapper.request.RequestsWrapper._get_request_info" ) self.mocked_headers = self.headers_patcher.start() - mock_response = MagicMock() - mock_response.status_code = 200 - mock_response.content.return_value = "Ok" - mock_requests.get.return_value = mock_response + + def raise_timeout(request): + return self.raise_timeout() + + self.mocked_headers.return_value = {} + self.mock_responses.add_callback( + responses.GET, + url, + callback=raise_timeout, + ) + wrapper = RequestsWrapper(base_url="", timeout=2) + + with self.when( + """ + - o servidor demorar X segundos para responder + """ + ): + with self.assertRaises(Timeout): + wrapper._get(url) + + with self.then( + """ + - um erro de timeout deve ser lançado + """ + ): + self.headers_patcher.stop() + + @MockedRequestsTestCase.no_auth + def test_retry_request(self): + with self.given( + """ + - uma requisição qualquer + """ + ): + self.headers_patcher = patch( + "bb_wrapper.wrapper.request.RequestsWrapper._get_request_info" + ) + url = "http://foo" + + self.mocked_headers = self.headers_patcher.start() + self.mock_responses.add( + responses.GET, + url, + "OK", + headers=self._build_authorization_header(1), + status=200, + ) max_retries = 3 def raise_connection_reset_error(headers=None): @@ -147,7 +202,6 @@ def raise_connection_reset_error(headers=None): self.mocked_headers.side_effect = raise_connection_reset_error wrapper = RequestsWrapper(base_url="") - url = "foo" with self.when( """ @@ -168,6 +222,7 @@ def raise_connection_reset_error(headers=None): self.headers_patcher.stop() + @MockedRequestsTestCase.no_auth def test_fail_retry_request(self): with self.given( """ From 4f773400d5855f16be7979d0efb6ab8e7276d33a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=F0=9F=90=98=20Pedro=20Fonseca?= Date: Wed, 26 Apr 2023 16:59:33 -0400 Subject: [PATCH 031/139] update lock file --- poetry.lock | 100 ++++++++++++++++++++++++++++------------------------ 1 file changed, 54 insertions(+), 46 deletions(-) diff --git a/poetry.lock b/poetry.lock index 17ced8d2..f84c01cb 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,10 +1,10 @@ [[package]] name = "black" -version = "22.6.0" +version = "22.12.0" description = "The uncompromising code formatter." category = "dev" optional = false -python-versions = ">=3.6.2" +python-versions = ">=3.7" [package.dependencies] click = ">=8.0.0" @@ -22,7 +22,7 @@ uvloop = ["uvloop (>=0.15.2)"] [[package]] name = "certifi" -version = "2022.6.15" +version = "2022.12.7" description = "Python package for providing Mozilla's CA Bundle." category = "main" optional = false @@ -30,14 +30,11 @@ python-versions = ">=3.6" [[package]] name = "charset-normalizer" -version = "2.1.0" +version = "3.1.0" description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." category = "main" optional = false -python-versions = ">=3.6.0" - -[package.extras] -unicode_backport = ["unicodedata2"] +python-versions = ">=3.7.0" [[package]] name = "click" @@ -52,11 +49,11 @@ colorama = {version = "*", markers = "platform_system == \"Windows\""} [[package]] name = "colorama" -version = "0.4.5" +version = "0.4.6" description = "Cross-platform colored terminal text." category = "main" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" [[package]] name = "coverage" @@ -74,7 +71,7 @@ toml = ["toml"] [[package]] name = "crc" -version = "1.2.0" +version = "1.3.0" description = "Library and CLI to calculate and verify all kinds of CRC checksums" category = "main" optional = false @@ -106,7 +103,7 @@ python-dateutil = ">=2.7" [[package]] name = "idna" -version = "3.3" +version = "3.4" description = "Internationalized Domain Names in Applications (IDNA)" category = "main" optional = false @@ -114,16 +111,16 @@ python-versions = ">=3.5" [[package]] name = "isort" -version = "5.10.1" +version = "5.12.0" description = "A Python utility / library to sort Python imports." category = "dev" optional = false -python-versions = ">=3.6.1,<4.0" +python-versions = ">=3.8.0" [package.extras] -pipfile_deprecated_finder = ["pipreqs", "requirementslib"] -requirements_deprecated_finder = ["pipreqs", "pip-api"] -colors = ["colorama (>=0.4.3,<0.5.0)"] +colors = ["colorama (>=0.4.3)"] +requirements-deprecated-finder = ["pip-api", "pipreqs"] +pipfile-deprecated-finder = ["pip-shims (>=0.5.2)", "pipreqs", "requirementslib"] plugins = ["setuptools"] [[package]] @@ -136,35 +133,35 @@ python-versions = "*" [[package]] name = "mypy-extensions" -version = "0.4.3" -description = "Experimental type system extensions for programs checked with the mypy typechecker." +version = "1.0.0" +description = "Type system extensions for programs checked with the mypy type checker." category = "dev" optional = false -python-versions = "*" +python-versions = ">=3.5" [[package]] name = "pathspec" -version = "0.9.0" +version = "0.11.1" description = "Utility library for gitignore style pattern matching of file paths." category = "dev" optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" +python-versions = ">=3.7" [[package]] name = "platformdirs" -version = "2.5.2" -description = "A small Python module for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." +version = "3.4.0" +description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." category = "dev" optional = false python-versions = ">=3.7" [package.extras] -docs = ["furo (>=2021.7.5b38)", "proselint (>=0.10.2)", "sphinx-autodoc-typehints (>=1.12)", "sphinx (>=4)"] -test = ["appdirs (==1.4.4)", "pytest-cov (>=2.7)", "pytest-mock (>=3.6)", "pytest (>=6)"] +docs = ["furo (>=2023.3.27)", "proselint (>=0.13)", "sphinx-autodoc-typehints (>=1.23,!=1.23.4)", "sphinx (>=6.1.3)"] +test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest-cov (>=4)", "pytest-mock (>=3.10)", "pytest (>=7.3.1)"] [[package]] name = "py-bdd-context" -version = "0.0.2" +version = "0.0.4" description = "Biblioteca com Context Manager para facilitar os testes de Behavior Driven Development (BDD)" category = "dev" optional = false @@ -188,14 +185,14 @@ python-versions = "*" [[package]] name = "pydantic" -version = "1.9.1" +version = "1.10.7" description = "Data validation and settings management using python type hints" category = "main" optional = false -python-versions = ">=3.6.1" +python-versions = ">=3.7" [package.dependencies] -typing-extensions = ">=3.7.4.3" +typing-extensions = ">=4.2.0" [package.extras] dotenv = ["python-dotenv (>=0.10.4)"] @@ -209,6 +206,14 @@ category = "dev" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +[[package]] +name = "pypng" +version = "0.20220715.0" +description = "Pure Python library for saving and loading PNG images" +category = "main" +optional = false +python-versions = "*" + [[package]] name = "python-barcode" version = "0.13.1" @@ -233,7 +238,7 @@ six = ">=1.5" [[package]] name = "python-decouple" -version = "3.6" +version = "3.8" description = "Strict separation of settings from code." category = "main" optional = false @@ -241,33 +246,35 @@ python-versions = "*" [[package]] name = "qrcode" -version = "7.3.1" +version = "7.4.2" description = "QR Code image generator" category = "main" optional = false -python-versions = ">=3.6" +python-versions = ">=3.7" [package.dependencies] colorama = {version = "*", markers = "platform_system == \"Windows\""} +pypng = "*" +typing-extensions = "*" [package.extras] -all = ["zest.releaser", "tox", "pytest", "pytest", "pytest-cov", "pillow"] -dev = ["tox", "pytest"] +all = ["zest.releaser", "tox", "pytest", "pytest-cov", "pillow (>=9.1.0)"] +dev = ["tox", "pytest", "pytest-cov"] maintainer = ["zest.releaser"] -pil = ["pillow"] -test = ["pytest", "pytest-cov"] +pil = ["pillow (>=9.1.0)"] +test = ["coverage", "pytest"] [[package]] name = "requests" -version = "2.28.1" +version = "2.29.0" description = "Python HTTP for Humans." category = "main" optional = false -python-versions = ">=3.7, <4" +python-versions = ">=3.7" [package.dependencies] certifi = ">=2017.4.17" -charset-normalizer = ">=2,<3" +charset-normalizer = ">=2,<4" idna = ">=2.5,<4" urllib3 = ">=1.21.1,<1.27" @@ -316,7 +323,7 @@ python-versions = ">=3.7" [[package]] name = "typing-extensions" -version = "4.3.0" +version = "4.5.0" description = "Backported and Experimental Type Hints for Python 3.7+" category = "main" optional = false @@ -324,7 +331,7 @@ python-versions = ">=3.7" [[package]] name = "unidecode" -version = "1.3.4" +version = "1.3.6" description = "ASCII transliterations of Unicode text" category = "main" optional = false @@ -332,21 +339,21 @@ python-versions = ">=3.5" [[package]] name = "urllib3" -version = "1.26.11" +version = "1.26.15" description = "HTTP library with thread-safe connection pooling, file post, and more." category = "main" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*, <4" +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*" [package.extras] brotli = ["brotlicffi (>=0.8.0)", "brotli (>=1.0.9)", "brotlipy (>=0.6.0)"] -secure = ["pyOpenSSL (>=0.14)", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "certifi", "ipaddress"] +secure = ["pyOpenSSL (>=0.14)", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "certifi", "urllib3-secure-extra", "ipaddress"] socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"] [metadata] lock-version = "1.1" python-versions = "^3.8" -content-hash = "407db878c845999151040627c86ff1a8d1c6fdbe5bc24c42138d6b3257dc3346" +content-hash = "0a56fecadb5e45261565c68937881ba7507093bb087230d32c43f7aa5d7ebe95" [metadata.files] black = [] @@ -369,6 +376,7 @@ pycodestyle = [] pycpfcnpj = [] pydantic = [] pyflakes = [] +pypng = [] python-barcode = [] python-dateutil = [] python-decouple = [] From 14e2564d972072d0c02f306948ac7a15f1924440 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=F0=9F=90=98=20Pedro=20Fonseca?= Date: Wed, 26 Apr 2023 17:01:03 -0400 Subject: [PATCH 032/139] fmt --- tests/wrapper/test_request.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/wrapper/test_request.py b/tests/wrapper/test_request.py index eaa46506..539f8028 100644 --- a/tests/wrapper/test_request.py +++ b/tests/wrapper/test_request.py @@ -154,7 +154,7 @@ def raise_timeout(request): callback=raise_timeout, ) wrapper = RequestsWrapper(base_url="", timeout=2) - + with self.when( """ - o servidor demorar X segundos para responder From e54c317eb70347b820ed2c7c576586a9541db703 Mon Sep 17 00:00:00 2001 From: Pedro Fonseca <32584628+peidrao@users.noreply.github.com> Date: Thu, 27 Apr 2023 09:56:03 -0300 Subject: [PATCH 033/139] Update tests/wrapper/test_pagamentos.py Co-authored-by: Rodrigo Castro --- tests/wrapper/test_pagamentos.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/tests/wrapper/test_pagamentos.py b/tests/wrapper/test_pagamentos.py index 345fa791..1db61ad3 100644 --- a/tests/wrapper/test_pagamentos.py +++ b/tests/wrapper/test_pagamentos.py @@ -232,15 +232,15 @@ def test_criar_dados_com_email_invalido(self): with self.assertRaises(ValueError) as ctx: PagamentoLoteBBWrapper()._criar_dados_transferencia_pix( - "123", - "345", - "678", - "X", - "19042023", - 11, - "teste@...", - "Pagamento", - 128, + n_requisicao="123", + agencia="345", + conta="678", + dv_conta="X", + data_transferencia="19042023", + valor_transferencia=11, + chave="teste@...", + descricao="Pagamento", + tipo_pagamento=128, ) self.assertEqual( From 857f9a37e644496a83b1920bc72e0625a9510799 Mon Sep 17 00:00:00 2001 From: Pedro Fonseca Date: Thu, 27 Apr 2023 10:19:48 -0300 Subject: [PATCH 034/139] refatoracao de testes --- tests/wrapper/test_pagamentos.py | 92 ++++++++++++++++---------------- 1 file changed, 45 insertions(+), 47 deletions(-) diff --git a/tests/wrapper/test_pagamentos.py b/tests/wrapper/test_pagamentos.py index 1db61ad3..2dbbfc32 100644 --- a/tests/wrapper/test_pagamentos.py +++ b/tests/wrapper/test_pagamentos.py @@ -125,17 +125,15 @@ def test_criar_dados_chave_aleatoria_transferencia_pix(self): } response = PagamentoLoteBBWrapper()._criar_dados_transferencia_pix( - **{ - "n_requisicao": "123", - "agencia": "345", - "conta": "678", - "dv_conta": "X", - "data_transferencia": "19042023", - "valor_transferencia": "11", - "chave": "d14d32de-b3b9-4c31-9f89-8df2cec92c50", - "descricao": "Pagamento", - "tipo_pagamento": 128, - } + n_requisicao="123", + agencia="345", + conta="678", + dv_conta="X", + data_transferencia="19042023", + valor_transferencia=11, + chave="d14d32de-b3b9-4c31-9f89-8df2cec92c50", + descricao="Pagamento", + tipo_pagamento=128 ) self.assertEqual(expected_json, response) @@ -169,15 +167,15 @@ def test_criar_dados_telefone_transferencia_pix(self): } response = PagamentoLoteBBWrapper()._criar_dados_transferencia_pix( - "123", - "345", - "678", - "X", - "19042023", - "11", - "11985732102", - "Pagamento", - 128, + n_requisicao="123", + agencia="345", + conta="678", + dv_conta="X", + data_transferencia="19042023", + valor_transferencia=11, + chave="11985732102", + descricao="Pagamento", + tipo_pagamento=128 ) self.assertEqual(expected_json, response) @@ -211,15 +209,15 @@ def test_criar_dados_email_transferencia_pix(self): } response = PagamentoLoteBBWrapper()._criar_dados_transferencia_pix( - "123", - "345", - "678", - "X", - "19042023", - 11, - "teste@imo.com", - "Pagamento", - 128, + n_requisicao="123", + agencia="345", + conta="678", + dv_conta="X", + data_transferencia="19042023", + valor_transferencia=11, + chave="teste@imo.com", + descricao="Pagamento", + tipo_pagamento=128 ) self.assertEqual(expected_json, response) @@ -276,15 +274,15 @@ def test_criar_dados_cpf_transferencia_pix(self): } response = PagamentoLoteBBWrapper()._criar_dados_transferencia_pix( - "123", - "345", - "678", - "X", - "19042023", - 11, - "28779295827", - "Pagamento", - 128, + n_requisicao="123", + agencia="345", + conta="678", + dv_conta="X", + data_transferencia="19042023", + valor_transferencia=11, + chave="28779295827", + descricao="Pagamento", + tipo_pagamento=128 ) self.assertEqual(expected_json, response) @@ -318,15 +316,15 @@ def test_criar_dados_cnpj_transferencia_pix(self): } response = PagamentoLoteBBWrapper()._criar_dados_transferencia_pix( - "123", - "345", - "678", - "X", - "19042023", - 11, - "95127446000198", - "Pagamento", - 128, + n_requisicao="123", + agencia="345", + conta="678", + dv_conta="X", + data_transferencia="19042023", + valor_transferencia=11, + chave="95127446000198", + descricao="Pagamento", + tipo_pagamento=128 ) self.assertEqual(expected_json, response) From 89478736df6047b0220ac2e60c14de2a2eb2cbd0 Mon Sep 17 00:00:00 2001 From: Pedro Fonseca Date: Thu, 27 Apr 2023 10:20:37 -0300 Subject: [PATCH 035/139] fmt --- tests/wrapper/test_pagamentos.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/wrapper/test_pagamentos.py b/tests/wrapper/test_pagamentos.py index 2dbbfc32..4c44700f 100644 --- a/tests/wrapper/test_pagamentos.py +++ b/tests/wrapper/test_pagamentos.py @@ -133,7 +133,7 @@ def test_criar_dados_chave_aleatoria_transferencia_pix(self): valor_transferencia=11, chave="d14d32de-b3b9-4c31-9f89-8df2cec92c50", descricao="Pagamento", - tipo_pagamento=128 + tipo_pagamento=128, ) self.assertEqual(expected_json, response) @@ -175,7 +175,7 @@ def test_criar_dados_telefone_transferencia_pix(self): valor_transferencia=11, chave="11985732102", descricao="Pagamento", - tipo_pagamento=128 + tipo_pagamento=128, ) self.assertEqual(expected_json, response) @@ -217,7 +217,7 @@ def test_criar_dados_email_transferencia_pix(self): valor_transferencia=11, chave="teste@imo.com", descricao="Pagamento", - tipo_pagamento=128 + tipo_pagamento=128, ) self.assertEqual(expected_json, response) @@ -282,7 +282,7 @@ def test_criar_dados_cpf_transferencia_pix(self): valor_transferencia=11, chave="28779295827", descricao="Pagamento", - tipo_pagamento=128 + tipo_pagamento=128, ) self.assertEqual(expected_json, response) @@ -324,7 +324,7 @@ def test_criar_dados_cnpj_transferencia_pix(self): valor_transferencia=11, chave="95127446000198", descricao="Pagamento", - tipo_pagamento=128 + tipo_pagamento=128, ) self.assertEqual(expected_json, response) From 19c63e0574aecb351da2b9f58bbca0685ec38ece Mon Sep 17 00:00:00 2001 From: Pedro Fonseca <32584628+peidrao@users.noreply.github.com> Date: Fri, 28 Apr 2023 09:55:06 -0300 Subject: [PATCH 036/139] Update tests/utils.py Co-authored-by: Breno Viana --- tests/utils.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/utils.py b/tests/utils.py index ef036253..cdcdf76b 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -120,7 +120,6 @@ def set_auth(self, number_of_retries_to_success: int = 0): self.mock_responses.reset() def auth_request(request): - call_count = self.__get_auth_request().call_count + 1 never_fail = number_of_retries_to_success == 0 From 585508b92b744a972af5aed202423613446440ec Mon Sep 17 00:00:00 2001 From: Pedro Fonseca <32584628+peidrao@users.noreply.github.com> Date: Fri, 28 Apr 2023 09:56:01 -0300 Subject: [PATCH 037/139] Update examples/lotes_pagamento/consultar_transferencia_pix.py Co-authored-by: Breno Viana --- examples/lotes_pagamento/consultar_transferencia_pix.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/examples/lotes_pagamento/consultar_transferencia_pix.py b/examples/lotes_pagamento/consultar_transferencia_pix.py index e4d6418b..728d1974 100644 --- a/examples/lotes_pagamento/consultar_transferencia_pix.py +++ b/examples/lotes_pagamento/consultar_transferencia_pix.py @@ -8,9 +8,6 @@ _id = "9221347" - -response = c.consultar_transferencia_pix( - _id, -) +response = c.consultar_transferencia_pix(_id) dump_response(response, os.path.realpath(__file__)) From b3aa3631fab8c606db59998c44d82c93662b5b97 Mon Sep 17 00:00:00 2001 From: Pedro Fonseca <32584628+peidrao@users.noreply.github.com> Date: Fri, 28 Apr 2023 09:56:22 -0300 Subject: [PATCH 038/139] Update tests/wrapper/test_request.py Co-authored-by: Breno Viana --- tests/wrapper/test_request.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/wrapper/test_request.py b/tests/wrapper/test_request.py index 539f8028..b2d04991 100644 --- a/tests/wrapper/test_request.py +++ b/tests/wrapper/test_request.py @@ -99,7 +99,6 @@ def test_contruct_url_3(self): @MockedRequestsTestCase.no_auth def test_request_timeout_1(self): - with self.given( """ - uma requisição qualquer From fdc0250b0d0c7772759172c3f1fadf163c6acc29 Mon Sep 17 00:00:00 2001 From: Pedro Fonseca Date: Fri, 28 Apr 2023 11:25:56 -0300 Subject: [PATCH 039/139] BDD em PixServiceTesteCase --- tests/services/test_identify_key_type.py | 273 +++++++++++++---------- tests/wrapper/test_request.py | 4 +- 2 files changed, 156 insertions(+), 121 deletions(-) diff --git a/tests/services/test_identify_key_type.py b/tests/services/test_identify_key_type.py index 1271fb63..8e9b81cf 100644 --- a/tests/services/test_identify_key_type.py +++ b/tests/services/test_identify_key_type.py @@ -1,138 +1,171 @@ -from unittest import TestCase - +from py_bdd_context import BDDContextTestCase from bb_wrapper.services.pix import PixService -class PixServiceTestCase(TestCase): +class PixServiceTestCase(BDDContextTestCase): def test_is_email(self): - """ - Dado: - - Dado uma string 'test@test.com' - Quando: - - for chamado PixService().identify_key_type('test@test.com') - Então: - - o resultado deve ser 2 - """ - email = "test@test.com" - - result = PixService().identify_key_type(email) - - expected = 2 - - self.assertEqual(result, expected) + with self.given( + """ + - Uma string 'test@test.com' + """ + ): + email = "test@test.com" + with self.when( + """ + - PixService().identify_key_type('test@test.com') + """ + ): + result = PixService().identify_key_type(email) + with self.then( + """ + - O resultado deve ser 2 + """ + ): + expected = 2 + self.assertEqual(result, expected) def test_is_phone(self): - """ - Dado: - - Dado uma string 'phone' - Quando: - - for chamado PixService().identify_key_type(phone) - Então: - - o resultado deve ser 1 - """ - phone = "11999887766" - - result = PixService().identify_key_type(phone) - - expected = 1 - - self.assertEqual(result, expected) + with self.given( + """ + - Uma string 'phone' + """ + ): + phone = "11999887766" + with self.when( + """ + - PixService().identify_key_type(phone) + """ + ): + result = PixService().identify_key_type(phone) + with self.then( + """ + - O resultado deve ser 1 + """ + ): + expected = 1 + self.assertEqual(result, expected) def test_is_uuid(self): - """ - Dado: - - Dado uma string 'uuid' - Quando: - - for chamado PixService().identify_key_type(uuid) - Então: - - o resultado deve ser 4 - """ - uuid = "45abb60a-6253-4f22-802b-0d84045ea76a" - - result = PixService().identify_key_type(uuid) - - expected = 4 - - self.assertEqual(result, expected) + with self.given( + """ + - Uma string 'uuid' + """ + ): + uuid = "45abb60a-6253-4f22-802b-0d84045ea76a" + with self.when( + """ + - PixService().identify_key_type(uuid) + """ + ): + result = PixService().identify_key_type(uuid) + with self.then( + """ + - O resultado deve ser 4 + """ + ): + expected = 4 + self.assertEqual(result, expected) def test_is_cnpj(self): - """ - Dado: - - Dado uma string 'cnpj' - Quando: - - for chamado PixService().identify_key_type(cnpj) - Então: - - o resultado deve ser 4 - """ - cnpj = "03794722000153" - - result = PixService().identify_key_type(cnpj) - - expected = 3 - - self.assertEqual(result, expected) + with self.given( + """ + - Uma string '03794722000153' + """ + ): + cnpj = "03794722000153" + with self.when( + """ + - PixService().identify_key_type("03794722000153") + """ + ): + result = PixService().identify_key_type(cnpj) + with self.then( + """ + - O resultado deve ser 4 + """ + ): + expected = 3 + self.assertEqual(result, expected) def test_is_cpf(self): - """ - Dado: - - Dado uma string 'cpf' - Quando: - - for chamado PixService().identify_key_type(cpf) - Então: - - o resultado deve ser 4 - """ - cpf = "43166663045" - - result = PixService().identify_key_type(cpf) - - expected = 3 - - self.assertEqual(result, expected) + with self.given( + """ + - Uma string '43166663045' + """ + ): + cpf = "43166663045" + with self.when( + """ + - PixService().identify_key_type("43166663045") + """ + ): + result = PixService().identify_key_type(cpf) + with self.then( + """ + - O resultado deve ser 4 + """ + ): + expected = 3 + self.assertEqual(result, expected) def test_is_not_key(self): - """ - Dado: - - Dado uma string 'key_invalid' - Quando: - - for chamado PixService().identify_key_type(key_invalid) - Então: - - deve ser lançado um ValueError com - "Tipo de chave não identificado" - """ - key_invalid = "1" - - with self.assertRaises(ValueError) as ctx: - PixService().identify_key_type(key_invalid) - - self.assertEqual(ctx.exception.args[0], "Tipo de chave não identificado") + with self.given( + """ + - Dado uma string '1' + """ + ): + key_invalid = "1" + with self.when( + """ + - PixService().identify_key_type("1") + """ + ): + with self.assertRaises(ValueError) as ctx: + PixService().identify_key_type(key_invalid) + with self.then( + """ + - Deve ser lançado um ValueError com "Tipo de chave não identificado" + """ + ): + self.assertEqual(ctx.exception.args[0], "Tipo de chave não identificado") def test_email_valid(self): - """ - Dado: - - Dado um um 'test@test.com' - Quando: - - for chamado PixService().verify_email('test@test.com') - Então: - - o resultado deve ser False - """ - email = "test@test.com" - - result = PixService().verify_email(email) - - self.assertTrue(result) + with self.given( + """ + - Uma string 'test@test.com' + """ + ): + email = "test@test.com" + with self.when( + """ + - PixService().verify_email('test@test.com') + """ + ): + result = PixService().verify_email(email) + with self.then( + """ + - O resultado deve ser True + """ + ): + self.assertTrue(result) def test_email_invalid(self): - """ - Dado: - - Dado um um 'teste@...br' - Quando: - - for chamado PixService().verify_email('teste@...br') - Então: - - o resultado deve ser True - """ - email = "teste@...br" - - with self.assertRaises(ValueError) as ctx: - PixService().verify_email(email) - - self.assertEqual(ctx.exception.args[0], "Email inválido!") + with self.given( + """ + - Uma string 'teste@...br' + """ + ): + email = "teste@...br" + with self.when( + """ + - PixService().verify_email('teste@...br') + """ + ): + with self.assertRaises(ValueError) as ctx: + PixService().verify_email(email) + with self.then( + """ + - O resultado deve ser True + """ + ): + self.assertEqual(ctx.exception.args[0], "Email inválido!") diff --git a/tests/wrapper/test_request.py b/tests/wrapper/test_request.py index b2d04991..e2f2166e 100644 --- a/tests/wrapper/test_request.py +++ b/tests/wrapper/test_request.py @@ -1,5 +1,6 @@ from unittest.mock import patch import responses +from time import sleep from requests import Timeout from py_bdd_context import BDDContextTestCase @@ -144,6 +145,7 @@ def test_request_timeout_2(self): self.mocked_headers = self.headers_patcher.start() def raise_timeout(request): + sleep(3) return self.raise_timeout() self.mocked_headers.return_value = {} @@ -152,7 +154,7 @@ def raise_timeout(request): url, callback=raise_timeout, ) - wrapper = RequestsWrapper(base_url="", timeout=2) + wrapper = RequestsWrapper(base_url="", timeout=1) with self.when( """ From 8408423420e10351277c58eab6e5743d1bd66384 Mon Sep 17 00:00:00 2001 From: Pedro Fonseca Date: Fri, 28 Apr 2023 11:35:05 -0300 Subject: [PATCH 040/139] fmt --- tests/services/test_identify_key_type.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/services/test_identify_key_type.py b/tests/services/test_identify_key_type.py index 8e9b81cf..c0732fcc 100644 --- a/tests/services/test_identify_key_type.py +++ b/tests/services/test_identify_key_type.py @@ -27,7 +27,7 @@ def test_is_email(self): def test_is_phone(self): with self.given( """ - - Uma string 'phone' + - Uma string 'phone' """ ): phone = "11999887766" From 993dda42bf29cba379487004f6a49b72c300c436 Mon Sep 17 00:00:00 2001 From: Pedro Fonseca Date: Fri, 28 Apr 2023 11:40:00 -0300 Subject: [PATCH 041/139] espaco branco no final do arquivo json --- examples/lotes_pagamento/data/transferencia_pix_cpf.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/lotes_pagamento/data/transferencia_pix_cpf.json b/examples/lotes_pagamento/data/transferencia_pix_cpf.json index 6f64c6b8..de26db60 100644 --- a/examples/lotes_pagamento/data/transferencia_pix_cpf.json +++ b/examples/lotes_pagamento/data/transferencia_pix_cpf.json @@ -32,4 +32,4 @@ "erros": [] } ] -} \ No newline at end of file +} From b130142c12d1af600fb6fe88855fae12731b4da7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=F0=9F=90=98=20Pedro=20Fonseca?= Date: Tue, 2 May 2023 14:39:46 -0400 Subject: [PATCH 042/139] adicionando bdd em testes --- tests/services/test_documento.py | 179 +++++++++++++++++-------------- tests/wrapper/test_request.py | 5 +- 2 files changed, 103 insertions(+), 81 deletions(-) diff --git a/tests/services/test_documento.py b/tests/services/test_documento.py index c99595c1..da7c4baf 100644 --- a/tests/services/test_documento.py +++ b/tests/services/test_documento.py @@ -1,93 +1,116 @@ -from unittest import TestCase +from py_bdd_context import BDDContextTestCase from bb_wrapper.services.document import DocumentoService -class DocumentServiceTestCase(TestCase): +class DocumentServiceTestCase(BDDContextTestCase): maxDiff = None def test_identifica_tipo_pessoa_fisica(self): - """ - Dado: - - Dado uma string '77855240098' - Quando: - - for chamado DocumentoService().identifica_tipo('77855240098') - Então: - - o resultado deve ser 1 - """ - cpf = "77855240098" - - result = DocumentoService().identifica_tipo(cpf) - - expected = 1 - - self.assertEqual(result, expected) + with self.given( + """ + - Uma string '77855240098' + """ + ): + cpf = "77855240098" + with self.when( + """ + - DocumentoService().identifica_tipo('77855240098') + """ + ): + result = DocumentoService().identifica_tipo(cpf) + with self.then( + """ + - O resultado deve ser 1 + """ + ): + expected = 1 + self.assertEqual(result, expected) def test_identifica_tipo_pessoa_fisica_com_pontuacao(self): - """ - Dado: - - Dado uma string '778.552.400-98' - Quando: - - for chamado DocumentoService().identifica_tipo('778.552.400-98') - Então: - - o resultado deve ser 1 - """ - cpf = "778.552.400-98" - - result = DocumentoService().identifica_tipo(cpf) - - expected = 1 - - self.assertEqual(result, expected) + with self.given( + """ + - Uma string '778.552.400-98' + """ + ): + cpf = "778.552.400-98" + with self.when( + """ + - DocumentoService().identifica_tipo('778.552.400-98') + """ + ): + result = DocumentoService().identifica_tipo(cpf) + with self.then( + """ + - O resultado deve ser 1 + """ + ): + expected = 1 + + self.assertEqual(result, expected) def test_identifica_tipo_pessoa_juridica(self): - """ - Dado: - - Dado uma string '55468100000139' - Quando: - - for chamado DocumentoService().identifica_tipo('55468100000139') - Então: - - o resultado deve ser 1 - """ - cnpj = "55468100000139" - - result = DocumentoService().identifica_tipo(cnpj) - - expected = 2 - - self.assertEqual(result, expected) + with self.given( + """ + - Uma string '55468100000139' + """ + ): + cnpj = "55468100000139" + with self.when( + """ + - DocumentoService().identifica_tipo('55468100000139') + """ + ): + result = DocumentoService().identifica_tipo(cnpj) + with self.then( + """ + - O resultado deve ser 1 + """ + ): + expected = 2 + self.assertEqual(result, expected) def test_identifica_tipo_pessoa_juridica_com_pontuacao(self): - """ - Dado: - - Dado uma string '18.853.097/0001-40' - Quando: - - for chamado DocumentoService().identifica_tipo('18.853.097/0001-40') - Então: - - o resultado deve ser 1 - """ - cnpj = "18.853.097/0001-40" - - result = DocumentoService().identifica_tipo(cnpj) - - expected = 2 - - self.assertEqual(result, expected) + with self.given( + """ + - Uma string '18.853.097/0001-40' + """ + ): + cnpj = "18.853.097/0001-40" + + with self.when( + """ + - DocumentoService().identifica_tipo('18.853.097/0001-40') + """ + ): + result = DocumentoService().identifica_tipo(cnpj) + with self.then( + """ + - O resultado deve ser 1 + """ + ): + expected = 2 + self.assertEqual(result, expected) def test_identifica_tipo_pessoa_document_invalid(self): - """ - Dado: - - Dado uma string '554681000001' - Quando: - - for chamado DocumentoService().identifica_tipo('554681000001') - Então: - - o resultado deve ser 1 - """ - invalid_document = "554681000001" - - with self.assertRaises(ValueError) as ctx: - DocumentoService().identifica_tipo(invalid_document) - - self.assertEqual( - ctx.exception.args[0], f"CPF/CNPJ '{invalid_document}' é inválido!" - ) # noqa + with self.given( + """ + - Uma string '554681000001' + """ + ): + invalid_document = "554681000001" + with self.when( + """ + - DocumentoService().identifica_tipo('554681000001') + """ + ): + with self.assertRaises(ValueError) as ctx: + DocumentoService().identifica_tipo(invalid_document) + with self.then( + """ + - CPF/CNPJ '554681000001' é inválido! + """ + ): + self.assertEqual( + ctx.exception.args[0], f"CPF/CNPJ '{invalid_document}' é inválido!" + ) # noqa diff --git a/tests/wrapper/test_request.py b/tests/wrapper/test_request.py index e2f2166e..539f8028 100644 --- a/tests/wrapper/test_request.py +++ b/tests/wrapper/test_request.py @@ -1,6 +1,5 @@ from unittest.mock import patch import responses -from time import sleep from requests import Timeout from py_bdd_context import BDDContextTestCase @@ -100,6 +99,7 @@ def test_contruct_url_3(self): @MockedRequestsTestCase.no_auth def test_request_timeout_1(self): + with self.given( """ - uma requisição qualquer @@ -145,7 +145,6 @@ def test_request_timeout_2(self): self.mocked_headers = self.headers_patcher.start() def raise_timeout(request): - sleep(3) return self.raise_timeout() self.mocked_headers.return_value = {} @@ -154,7 +153,7 @@ def raise_timeout(request): url, callback=raise_timeout, ) - wrapper = RequestsWrapper(base_url="", timeout=1) + wrapper = RequestsWrapper(base_url="", timeout=2) with self.when( """ From 6a86e7c7dfc73dfe26e33ac59065322ca9b4434b Mon Sep 17 00:00:00 2001 From: Pedro Fonseca <32584628+peidrao@users.noreply.github.com> Date: Tue, 2 May 2023 16:23:18 -0400 Subject: [PATCH 043/139] Update tests/services/test_documento.py Co-authored-by: PedroRegisPOAR --- tests/services/test_documento.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/services/test_documento.py b/tests/services/test_documento.py index da7c4baf..a900146e 100644 --- a/tests/services/test_documento.py +++ b/tests/services/test_documento.py @@ -64,7 +64,7 @@ def test_identifica_tipo_pessoa_juridica(self): result = DocumentoService().identifica_tipo(cnpj) with self.then( """ - - O resultado deve ser 1 + - O resultado deve ser 2 """ ): expected = 2 From 1afda49d9d70b45cba65e5558558bad285485f0e Mon Sep 17 00:00:00 2001 From: Pedro Fonseca <32584628+peidrao@users.noreply.github.com> Date: Tue, 2 May 2023 16:23:43 -0400 Subject: [PATCH 044/139] Update tests/services/test_documento.py Co-authored-by: PedroRegisPOAR --- tests/services/test_documento.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/services/test_documento.py b/tests/services/test_documento.py index a900146e..793ef040 100644 --- a/tests/services/test_documento.py +++ b/tests/services/test_documento.py @@ -86,7 +86,7 @@ def test_identifica_tipo_pessoa_juridica_com_pontuacao(self): result = DocumentoService().identifica_tipo(cnpj) with self.then( """ - - O resultado deve ser 1 + - O resultado deve ser 2 """ ): expected = 2 From 4b02e216055116b1b62b09d581e42f5aa648c13b Mon Sep 17 00:00:00 2001 From: Pedro Fonseca <32584628+peidrao@users.noreply.github.com> Date: Tue, 2 May 2023 16:24:10 -0400 Subject: [PATCH 045/139] Update tests/services/test_identify_key_type.py Co-authored-by: PedroRegisPOAR --- tests/services/test_identify_key_type.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/services/test_identify_key_type.py b/tests/services/test_identify_key_type.py index c0732fcc..299de960 100644 --- a/tests/services/test_identify_key_type.py +++ b/tests/services/test_identify_key_type.py @@ -81,7 +81,7 @@ def test_is_cnpj(self): result = PixService().identify_key_type(cnpj) with self.then( """ - - O resultado deve ser 4 + - O resultado deve ser 3 """ ): expected = 3 From 4355f036a4efbb61f72d8cc919fd6d8f8fb01bda Mon Sep 17 00:00:00 2001 From: Pedro Fonseca <32584628+peidrao@users.noreply.github.com> Date: Tue, 2 May 2023 16:24:20 -0400 Subject: [PATCH 046/139] Update tests/services/test_identify_key_type.py Co-authored-by: PedroRegisPOAR --- tests/services/test_identify_key_type.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/services/test_identify_key_type.py b/tests/services/test_identify_key_type.py index 299de960..6e7ab2ec 100644 --- a/tests/services/test_identify_key_type.py +++ b/tests/services/test_identify_key_type.py @@ -102,7 +102,7 @@ def test_is_cpf(self): result = PixService().identify_key_type(cpf) with self.then( """ - - O resultado deve ser 4 + - O resultado deve ser 3 """ ): expected = 3 From 7b5a90550d0b7a4c0788733e176a75e2c3efaf3c Mon Sep 17 00:00:00 2001 From: Pedro Fonseca <32584628+peidrao@users.noreply.github.com> Date: Tue, 2 May 2023 16:25:24 -0400 Subject: [PATCH 047/139] Update tests/wrapper/test_request.py Co-authored-by: PedroRegisPOAR --- tests/wrapper/test_request.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/wrapper/test_request.py b/tests/wrapper/test_request.py index 539f8028..94ba0612 100644 --- a/tests/wrapper/test_request.py +++ b/tests/wrapper/test_request.py @@ -157,7 +157,7 @@ def raise_timeout(request): with self.when( """ - - o servidor demorar X segundos para responder + - o servidor demorar tempo o suficiente para ocorrer timeout """ ): with self.assertRaises(Timeout): From b0575e634f6cf27df9804da9bdf5da29d719ba6e Mon Sep 17 00:00:00 2001 From: Pedro Fonseca <32584628+peidrao@users.noreply.github.com> Date: Tue, 2 May 2023 16:36:32 -0400 Subject: [PATCH 048/139] Update tests/services/test_identify_key_type.py Co-authored-by: Rodrigo Castro --- tests/services/test_identify_key_type.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/tests/services/test_identify_key_type.py b/tests/services/test_identify_key_type.py index 6e7ab2ec..22775529 100644 --- a/tests/services/test_identify_key_type.py +++ b/tests/services/test_identify_key_type.py @@ -6,22 +6,24 @@ class PixServiceTestCase(BDDContextTestCase): def test_is_email(self): with self.given( """ - - Uma string 'test@test.com' + - uma chave 'test@test.com' """ ): email = "test@test.com" + with self.when( """ - - PixService().identify_key_type('test@test.com') + - for utilizado o service de PIX para identificação do tipo da chave """ ): result = PixService().identify_key_type(email) + with self.then( """ - - O resultado deve ser 2 + - o tipo da chave identificado deve ser EMAIL """ ): - expected = 2 + expected = PixKeyTypeEnum.EMAIL self.assertEqual(result, expected) def test_is_phone(self): From 100bb9e68886c43caa16e6432203cd5138624039 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=F0=9F=90=98=20Pedro=20Fonseca?= Date: Tue, 2 May 2023 17:00:30 -0400 Subject: [PATCH 049/139] ajustes na descricao dos testes --- tests/services/test_identify_key_type.py | 57 ++++++++++++------------ 1 file changed, 29 insertions(+), 28 deletions(-) diff --git a/tests/services/test_identify_key_type.py b/tests/services/test_identify_key_type.py index 22775529..783c848c 100644 --- a/tests/services/test_identify_key_type.py +++ b/tests/services/test_identify_key_type.py @@ -1,5 +1,6 @@ from py_bdd_context import BDDContextTestCase from bb_wrapper.services.pix import PixService +from bb_wrapper.models.pagamentos import TipoChavePIX class PixServiceTestCase(BDDContextTestCase): @@ -10,7 +11,7 @@ def test_is_email(self): """ ): email = "test@test.com" - + with self.when( """ - for utilizado o service de PIX para identificação do tipo da chave @@ -20,113 +21,113 @@ def test_is_email(self): with self.then( """ - - o tipo da chave identificado deve ser EMAIL + - o tipo da chave identificado deve ser email """ ): - expected = PixKeyTypeEnum.EMAIL + expected = TipoChavePIX.email self.assertEqual(result, expected) def test_is_phone(self): with self.given( """ - - Uma string 'phone' + - uma chave '11999887766' """ ): phone = "11999887766" with self.when( """ - - PixService().identify_key_type(phone) + - for utilizado o service de PIX para identificação do tipo da chave """ ): result = PixService().identify_key_type(phone) with self.then( """ - - O resultado deve ser 1 + - o tipo da chave identificado deve ser telefone """ ): - expected = 1 + expected = TipoChavePIX.telefone self.assertEqual(result, expected) def test_is_uuid(self): with self.given( """ - - Uma string 'uuid' + - uma chave '45abb60a-6253-4f22-802b-0d84045ea76a' """ ): uuid = "45abb60a-6253-4f22-802b-0d84045ea76a" with self.when( """ - - PixService().identify_key_type(uuid) + - for utilizado o service de PIX para identificação do tipo da chave """ ): result = PixService().identify_key_type(uuid) with self.then( """ - - O resultado deve ser 4 + - o tipo da chave identificado deve ser uuid """ ): - expected = 4 + expected = TipoChavePIX.uuid self.assertEqual(result, expected) def test_is_cnpj(self): with self.given( """ - - Uma string '03794722000153' + - uma chave '03794722000153' """ ): cnpj = "03794722000153" with self.when( """ - - PixService().identify_key_type("03794722000153") + - for utilizado o service de PIX para identificação do tipo da chave """ ): result = PixService().identify_key_type(cnpj) with self.then( """ - - O resultado deve ser 3 + - o tipo da chave identificado deve ser documento """ ): - expected = 3 + expected = TipoChavePIX.documento self.assertEqual(result, expected) def test_is_cpf(self): with self.given( """ - - Uma string '43166663045' + - uma chave '43166663045' """ ): cpf = "43166663045" with self.when( """ - - PixService().identify_key_type("43166663045") + - for utilizado o service de PIX para identificação do tipo da chave """ ): result = PixService().identify_key_type(cpf) with self.then( """ - - O resultado deve ser 3 + - o tipo da chave identificado deve ser documento """ ): - expected = 3 + expected = TipoChavePIX.documento self.assertEqual(result, expected) def test_is_not_key(self): with self.given( """ - - Dado uma string '1' + - uma chave '1' """ ): key_invalid = "1" with self.when( """ - - PixService().identify_key_type("1") + - for utilizado o service de PIX para identificação do tipo da chave """ ): with self.assertRaises(ValueError) as ctx: PixService().identify_key_type(key_invalid) with self.then( """ - - Deve ser lançado um ValueError com "Tipo de chave não identificado" + - deve ser levantada uma exceção informando que a chave informada é inválida # noqa """ ): self.assertEqual(ctx.exception.args[0], "Tipo de chave não identificado") @@ -134,19 +135,19 @@ def test_is_not_key(self): def test_email_valid(self): with self.given( """ - - Uma string 'test@test.com' + - um email 'test@test.com' """ ): email = "test@test.com" with self.when( """ - - PixService().verify_email('test@test.com') + - o service de PIX para verificar email for chamado """ ): result = PixService().verify_email(email) with self.then( """ - - O resultado deve ser True + - o service deve retornar que o email informado é válido """ ): self.assertTrue(result) @@ -154,20 +155,20 @@ def test_email_valid(self): def test_email_invalid(self): with self.given( """ - - Uma string 'teste@...br' + - um email 'teste@...br' """ ): email = "teste@...br" with self.when( """ - - PixService().verify_email('teste@...br') + - o service de PIX para verificar email for chamado """ ): with self.assertRaises(ValueError) as ctx: PixService().verify_email(email) with self.then( """ - - O resultado deve ser True + - deve ser levantada uma exceção informando que o email é inválido """ ): self.assertEqual(ctx.exception.args[0], "Email inválido!") From dbc034ff6986ef00bc7a53bd92aaf8b7c949cfc7 Mon Sep 17 00:00:00 2001 From: Pedro Fonseca <32584628+peidrao@users.noreply.github.com> Date: Wed, 3 May 2023 16:15:33 -0300 Subject: [PATCH 050/139] Update tests/services/test_identify_key_type.py Co-authored-by: Breno Viana --- tests/services/test_identify_key_type.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/services/test_identify_key_type.py b/tests/services/test_identify_key_type.py index 783c848c..71a33e13 100644 --- a/tests/services/test_identify_key_type.py +++ b/tests/services/test_identify_key_type.py @@ -166,6 +166,7 @@ def test_email_invalid(self): ): with self.assertRaises(ValueError) as ctx: PixService().verify_email(email) + with self.then( """ - deve ser levantada uma exceção informando que o email é inválido From 7a13a2562db804f69ca5c64ec904e3c3a8719d43 Mon Sep 17 00:00:00 2001 From: Pedro Fonseca <32584628+peidrao@users.noreply.github.com> Date: Wed, 3 May 2023 16:12:39 -0400 Subject: [PATCH 051/139] Update tests/wrapper/test_request.py Co-authored-by: Breno Viana --- tests/wrapper/test_request.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/tests/wrapper/test_request.py b/tests/wrapper/test_request.py index 94ba0612..421d3fd8 100644 --- a/tests/wrapper/test_request.py +++ b/tests/wrapper/test_request.py @@ -144,9 +144,6 @@ def test_request_timeout_2(self): ) self.mocked_headers = self.headers_patcher.start() - def raise_timeout(request): - return self.raise_timeout() - self.mocked_headers.return_value = {} self.mock_responses.add_callback( responses.GET, From 12f174b33cf2cb230b850a534c55713cf81eefca Mon Sep 17 00:00:00 2001 From: Pedro Fonseca <32584628+peidrao@users.noreply.github.com> Date: Wed, 3 May 2023 16:12:52 -0400 Subject: [PATCH 052/139] Update tests/utils.py Co-authored-by: Breno Viana --- tests/utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/utils.py b/tests/utils.py index cdcdf76b..1637d0c7 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -84,7 +84,7 @@ def build_auth_success_response(self, call_count): data = json.dumps(self.__auth_success_201_data(call_count)) return status, headers, data - def raise_timeout(self): + def raise_timeout(self, request): raise Timeout() @staticmethod From 0d40ce791dacfefe901274f3a85613ac7fecfd12 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=F0=9F=90=98=20Pedro=20Fonseca?= Date: Wed, 3 May 2023 16:17:03 -0400 Subject: [PATCH 053/139] ajustes em test --- tests/wrapper/test_request.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/wrapper/test_request.py b/tests/wrapper/test_request.py index 421d3fd8..29a94e4b 100644 --- a/tests/wrapper/test_request.py +++ b/tests/wrapper/test_request.py @@ -148,7 +148,7 @@ def test_request_timeout_2(self): self.mock_responses.add_callback( responses.GET, url, - callback=raise_timeout, + callback=self.raise_timeout, ) wrapper = RequestsWrapper(base_url="", timeout=2) From f16bd69db1c9dd6df1a574e99a62b02a5d8c3e22 Mon Sep 17 00:00:00 2001 From: Pedro Fonseca <32584628+peidrao@users.noreply.github.com> Date: Thu, 4 May 2023 10:22:56 -0300 Subject: [PATCH 054/139] Update tests/services/test_identify_key_type.py Co-authored-by: Breno Viana --- tests/services/test_identify_key_type.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/services/test_identify_key_type.py b/tests/services/test_identify_key_type.py index 71a33e13..52768e55 100644 --- a/tests/services/test_identify_key_type.py +++ b/tests/services/test_identify_key_type.py @@ -159,6 +159,7 @@ def test_email_invalid(self): """ ): email = "teste@...br" + with self.when( """ - o service de PIX para verificar email for chamado From 471d83dc89f2582ea306998f26d9432488f21e06 Mon Sep 17 00:00:00 2001 From: Pedro Fonseca <32584628+peidrao@users.noreply.github.com> Date: Thu, 4 May 2023 10:23:13 -0300 Subject: [PATCH 055/139] Update tests/services/test_identify_key_type.py Co-authored-by: Breno Viana --- tests/services/test_identify_key_type.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/services/test_identify_key_type.py b/tests/services/test_identify_key_type.py index 52768e55..596de6b9 100644 --- a/tests/services/test_identify_key_type.py +++ b/tests/services/test_identify_key_type.py @@ -145,6 +145,7 @@ def test_email_valid(self): """ ): result = PixService().verify_email(email) + with self.then( """ - o service deve retornar que o email informado é válido From 5ebe8ce551dfed004c2366829ae278583162a3ea Mon Sep 17 00:00:00 2001 From: Pedro Fonseca <32584628+peidrao@users.noreply.github.com> Date: Thu, 4 May 2023 10:23:28 -0300 Subject: [PATCH 056/139] Update tests/services/test_identify_key_type.py Co-authored-by: Breno Viana --- tests/services/test_identify_key_type.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/services/test_identify_key_type.py b/tests/services/test_identify_key_type.py index 596de6b9..b059d358 100644 --- a/tests/services/test_identify_key_type.py +++ b/tests/services/test_identify_key_type.py @@ -139,6 +139,7 @@ def test_email_valid(self): """ ): email = "test@test.com" + with self.when( """ - o service de PIX para verificar email for chamado From f18f7daf87785d380733f0f7015d2ba4ff6cb5e6 Mon Sep 17 00:00:00 2001 From: Pedro Fonseca <32584628+peidrao@users.noreply.github.com> Date: Thu, 4 May 2023 10:23:39 -0300 Subject: [PATCH 057/139] Update tests/services/test_identify_key_type.py Co-authored-by: Breno Viana --- tests/services/test_identify_key_type.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/services/test_identify_key_type.py b/tests/services/test_identify_key_type.py index b059d358..7a6ccef4 100644 --- a/tests/services/test_identify_key_type.py +++ b/tests/services/test_identify_key_type.py @@ -118,6 +118,7 @@ def test_is_not_key(self): """ ): key_invalid = "1" + with self.when( """ - for utilizado o service de PIX para identificação do tipo da chave From 146b1eca914741cd0ae856224ec15828d23343af Mon Sep 17 00:00:00 2001 From: Pedro Fonseca <32584628+peidrao@users.noreply.github.com> Date: Thu, 4 May 2023 10:24:24 -0300 Subject: [PATCH 058/139] Update tests/services/test_identify_key_type.py Co-authored-by: Breno Viana --- tests/services/test_identify_key_type.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/services/test_identify_key_type.py b/tests/services/test_identify_key_type.py index 7a6ccef4..4704272a 100644 --- a/tests/services/test_identify_key_type.py +++ b/tests/services/test_identify_key_type.py @@ -126,6 +126,7 @@ def test_is_not_key(self): ): with self.assertRaises(ValueError) as ctx: PixService().identify_key_type(key_invalid) + with self.then( """ - deve ser levantada uma exceção informando que a chave informada é inválida # noqa From 83c5f1ef25b4a8ff73f9f55109cbd5dfc1bcb32d Mon Sep 17 00:00:00 2001 From: Pedro Fonseca <32584628+peidrao@users.noreply.github.com> Date: Thu, 4 May 2023 10:25:01 -0300 Subject: [PATCH 059/139] Update tests/services/test_documento.py Co-authored-by: Breno Viana --- tests/services/test_documento.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/services/test_documento.py b/tests/services/test_documento.py index 793ef040..15c6a986 100644 --- a/tests/services/test_documento.py +++ b/tests/services/test_documento.py @@ -34,6 +34,7 @@ def test_identifica_tipo_pessoa_fisica_com_pontuacao(self): """ ): cpf = "778.552.400-98" + with self.when( """ - DocumentoService().identifica_tipo('778.552.400-98') From d50dfa3f1db871f2ed95aa5e215eee40f1be6cc4 Mon Sep 17 00:00:00 2001 From: Pedro Fonseca <32584628+peidrao@users.noreply.github.com> Date: Thu, 4 May 2023 10:25:22 -0300 Subject: [PATCH 060/139] Update tests/services/test_documento.py Co-authored-by: Breno Viana --- tests/services/test_documento.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/services/test_documento.py b/tests/services/test_documento.py index 15c6a986..0e91a58c 100644 --- a/tests/services/test_documento.py +++ b/tests/services/test_documento.py @@ -19,6 +19,7 @@ def test_identifica_tipo_pessoa_fisica(self): """ ): result = DocumentoService().identifica_tipo(cpf) + with self.then( """ - O resultado deve ser 1 From 014bff8f88422921f5423817fc7a34089e61d2ff Mon Sep 17 00:00:00 2001 From: Pedro Fonseca <32584628+peidrao@users.noreply.github.com> Date: Thu, 4 May 2023 10:25:49 -0300 Subject: [PATCH 061/139] Update tests/services/test_documento.py Co-authored-by: Breno Viana --- tests/services/test_documento.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/services/test_documento.py b/tests/services/test_documento.py index 0e91a58c..0e7daa5d 100644 --- a/tests/services/test_documento.py +++ b/tests/services/test_documento.py @@ -13,6 +13,7 @@ def test_identifica_tipo_pessoa_fisica(self): """ ): cpf = "77855240098" + with self.when( """ - DocumentoService().identifica_tipo('77855240098') From 32a309d7015946ed983f1f3a7753f9bc4bce41db Mon Sep 17 00:00:00 2001 From: Pedro Fonseca <32584628+peidrao@users.noreply.github.com> Date: Thu, 4 May 2023 10:26:03 -0300 Subject: [PATCH 062/139] Update bb_wrapper/models/pagamentos.py Co-authored-by: Breno Viana --- bb_wrapper/models/pagamentos.py | 1 - 1 file changed, 1 deletion(-) diff --git a/bb_wrapper/models/pagamentos.py b/bb_wrapper/models/pagamentos.py index a719660c..bf6c3d69 100644 --- a/bb_wrapper/models/pagamentos.py +++ b/bb_wrapper/models/pagamentos.py @@ -88,7 +88,6 @@ def _set_data(cls, values): values["identificacaoAleatoria"] = key elif key_type == TipoChavePIX.documento: key_value = cpfcnpj.clear_punctuation(key) - if len(key_value) == 11: values["cpf"] = key_value else: From e331ce318691bd06bdc649cd55f39cbb1626b5af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=F0=9F=87=BB=F0=9F=87=A6=20=20Pedro=20Fonseca?= Date: Thu, 4 May 2023 10:32:12 -0300 Subject: [PATCH 063/139] ajuste em espaco de teste --- tests/wrapper/test_request.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/wrapper/test_request.py b/tests/wrapper/test_request.py index 29a94e4b..d3f8abb3 100644 --- a/tests/wrapper/test_request.py +++ b/tests/wrapper/test_request.py @@ -99,7 +99,6 @@ def test_contruct_url_3(self): @MockedRequestsTestCase.no_auth def test_request_timeout_1(self): - with self.given( """ - uma requisição qualquer From ae5e6d9ad59298413a2b70306e1c50a0d65edd55 Mon Sep 17 00:00:00 2001 From: Pedro Fonseca <32584628+peidrao@users.noreply.github.com> Date: Thu, 4 May 2023 10:40:26 -0300 Subject: [PATCH 064/139] Update tests/services/test_identify_key_type.py Co-authored-by: Breno Viana --- tests/services/test_identify_key_type.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/services/test_identify_key_type.py b/tests/services/test_identify_key_type.py index 4704272a..1dd9c047 100644 --- a/tests/services/test_identify_key_type.py +++ b/tests/services/test_identify_key_type.py @@ -103,6 +103,7 @@ def test_is_cpf(self): """ ): result = PixService().identify_key_type(cpf) + with self.then( """ - o tipo da chave identificado deve ser documento From 17faf03cefba4ecefb41d75f5e1386767911b615 Mon Sep 17 00:00:00 2001 From: Pedro Fonseca <32584628+peidrao@users.noreply.github.com> Date: Thu, 4 May 2023 10:40:53 -0300 Subject: [PATCH 065/139] Update tests/services/test_documento.py Co-authored-by: Breno Viana --- tests/services/test_documento.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/services/test_documento.py b/tests/services/test_documento.py index 0e7daa5d..ba836bff 100644 --- a/tests/services/test_documento.py +++ b/tests/services/test_documento.py @@ -59,6 +59,7 @@ def test_identifica_tipo_pessoa_juridica(self): """ ): cnpj = "55468100000139" + with self.when( """ - DocumentoService().identifica_tipo('55468100000139') From 55103b0e2c871d069affb657246892c56ee3e154 Mon Sep 17 00:00:00 2001 From: Pedro Fonseca <32584628+peidrao@users.noreply.github.com> Date: Thu, 4 May 2023 10:41:07 -0300 Subject: [PATCH 066/139] Update tests/services/test_documento.py Co-authored-by: Breno Viana --- tests/services/test_documento.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/services/test_documento.py b/tests/services/test_documento.py index ba836bff..eda45edc 100644 --- a/tests/services/test_documento.py +++ b/tests/services/test_documento.py @@ -66,6 +66,7 @@ def test_identifica_tipo_pessoa_juridica(self): """ ): result = DocumentoService().identifica_tipo(cnpj) + with self.then( """ - O resultado deve ser 2 From 18f6ad6e37fc32e36f419277bffaa848469ec925 Mon Sep 17 00:00:00 2001 From: Pedro Fonseca <32584628+peidrao@users.noreply.github.com> Date: Thu, 4 May 2023 10:41:22 -0300 Subject: [PATCH 067/139] Update tests/services/test_documento.py Co-authored-by: Breno Viana --- tests/services/test_documento.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/services/test_documento.py b/tests/services/test_documento.py index eda45edc..f6e9ca7e 100644 --- a/tests/services/test_documento.py +++ b/tests/services/test_documento.py @@ -111,6 +111,7 @@ def test_identifica_tipo_pessoa_document_invalid(self): ): with self.assertRaises(ValueError) as ctx: DocumentoService().identifica_tipo(invalid_document) + with self.then( """ - CPF/CNPJ '554681000001' é inválido! From 5964dd397ae724d3055f12aceeda319923d58ba4 Mon Sep 17 00:00:00 2001 From: Pedro Fonseca <32584628+peidrao@users.noreply.github.com> Date: Thu, 4 May 2023 10:41:45 -0300 Subject: [PATCH 068/139] Update tests/services/test_identify_key_type.py Co-authored-by: Breno Viana --- tests/services/test_identify_key_type.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/services/test_identify_key_type.py b/tests/services/test_identify_key_type.py index 1dd9c047..9e6936b8 100644 --- a/tests/services/test_identify_key_type.py +++ b/tests/services/test_identify_key_type.py @@ -61,6 +61,7 @@ def test_is_uuid(self): """ ): result = PixService().identify_key_type(uuid) + with self.then( """ - o tipo da chave identificado deve ser uuid From 59228f81f7eea89428e7eaed003584f53f370c6a Mon Sep 17 00:00:00 2001 From: Pedro Fonseca <32584628+peidrao@users.noreply.github.com> Date: Thu, 4 May 2023 10:42:10 -0300 Subject: [PATCH 069/139] Update tests/services/test_documento.py Co-authored-by: Breno Viana --- tests/services/test_documento.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/services/test_documento.py b/tests/services/test_documento.py index f6e9ca7e..2e81a4b0 100644 --- a/tests/services/test_documento.py +++ b/tests/services/test_documento.py @@ -43,6 +43,7 @@ def test_identifica_tipo_pessoa_fisica_com_pontuacao(self): """ ): result = DocumentoService().identifica_tipo(cpf) + with self.then( """ - O resultado deve ser 1 From 545d9a4d11f1001bb5d7a916fe5a3c93e6827f65 Mon Sep 17 00:00:00 2001 From: Pedro Fonseca <32584628+peidrao@users.noreply.github.com> Date: Thu, 4 May 2023 10:42:24 -0300 Subject: [PATCH 070/139] Update tests/services/test_documento.py Co-authored-by: Breno Viana --- tests/services/test_documento.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/services/test_documento.py b/tests/services/test_documento.py index 2e81a4b0..9a593906 100644 --- a/tests/services/test_documento.py +++ b/tests/services/test_documento.py @@ -105,6 +105,7 @@ def test_identifica_tipo_pessoa_document_invalid(self): """ ): invalid_document = "554681000001" + with self.when( """ - DocumentoService().identifica_tipo('554681000001') From 33f4c669ca8468b4066a7b7a22b139895bf39bc5 Mon Sep 17 00:00:00 2001 From: Pedro Fonseca <32584628+peidrao@users.noreply.github.com> Date: Thu, 4 May 2023 10:42:44 -0300 Subject: [PATCH 071/139] Update tests/services/test_identify_key_type.py Co-authored-by: Breno Viana --- tests/services/test_identify_key_type.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/services/test_identify_key_type.py b/tests/services/test_identify_key_type.py index 9e6936b8..9ede6f40 100644 --- a/tests/services/test_identify_key_type.py +++ b/tests/services/test_identify_key_type.py @@ -40,6 +40,7 @@ def test_is_phone(self): """ ): result = PixService().identify_key_type(phone) + with self.then( """ - o tipo da chave identificado deve ser telefone From 3b1c7614bf3bab855d3429b126655c97f077272a Mon Sep 17 00:00:00 2001 From: Pedro Fonseca <32584628+peidrao@users.noreply.github.com> Date: Thu, 4 May 2023 10:43:18 -0300 Subject: [PATCH 072/139] Update tests/services/test_identify_key_type.py Co-authored-by: Breno Viana --- tests/services/test_identify_key_type.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/services/test_identify_key_type.py b/tests/services/test_identify_key_type.py index 9ede6f40..46ff67fc 100644 --- a/tests/services/test_identify_key_type.py +++ b/tests/services/test_identify_key_type.py @@ -56,6 +56,7 @@ def test_is_uuid(self): """ ): uuid = "45abb60a-6253-4f22-802b-0d84045ea76a" + with self.when( """ - for utilizado o service de PIX para identificação do tipo da chave From 398adc9a302a696017bd4ea28b8997d322df6a90 Mon Sep 17 00:00:00 2001 From: Pedro Fonseca <32584628+peidrao@users.noreply.github.com> Date: Thu, 4 May 2023 10:43:36 -0300 Subject: [PATCH 073/139] Update tests/services/test_identify_key_type.py Co-authored-by: Breno Viana --- tests/services/test_identify_key_type.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/services/test_identify_key_type.py b/tests/services/test_identify_key_type.py index 46ff67fc..540aeefd 100644 --- a/tests/services/test_identify_key_type.py +++ b/tests/services/test_identify_key_type.py @@ -100,6 +100,7 @@ def test_is_cpf(self): """ ): cpf = "43166663045" + with self.when( """ - for utilizado o service de PIX para identificação do tipo da chave From a7f99e6caa9d5f270052b7c8356f7a0791f6291c Mon Sep 17 00:00:00 2001 From: Pedro Fonseca <32584628+peidrao@users.noreply.github.com> Date: Thu, 4 May 2023 10:47:57 -0300 Subject: [PATCH 074/139] Update tests/services/test_identify_key_type.py Co-authored-by: Breno Viana --- tests/services/test_identify_key_type.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/services/test_identify_key_type.py b/tests/services/test_identify_key_type.py index 540aeefd..86737749 100644 --- a/tests/services/test_identify_key_type.py +++ b/tests/services/test_identify_key_type.py @@ -34,6 +34,7 @@ def test_is_phone(self): """ ): phone = "11999887766" + with self.when( """ - for utilizado o service de PIX para identificação do tipo da chave From f7a03da3177ec544212c0282dacfbf83119b0239 Mon Sep 17 00:00:00 2001 From: Pedro Fonseca <32584628+peidrao@users.noreply.github.com> Date: Thu, 4 May 2023 10:48:12 -0300 Subject: [PATCH 075/139] Update tests/services/test_documento.py Co-authored-by: Breno Viana --- tests/services/test_documento.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/services/test_documento.py b/tests/services/test_documento.py index 9a593906..315d35ff 100644 --- a/tests/services/test_documento.py +++ b/tests/services/test_documento.py @@ -90,6 +90,7 @@ def test_identifica_tipo_pessoa_juridica_com_pontuacao(self): """ ): result = DocumentoService().identifica_tipo(cnpj) + with self.then( """ - O resultado deve ser 2 From 14bdb297e4eedcbdf172db332f48bedc5762fdeb Mon Sep 17 00:00:00 2001 From: Pedro Fonseca <32584628+peidrao@users.noreply.github.com> Date: Thu, 4 May 2023 10:49:19 -0300 Subject: [PATCH 076/139] Update tests/services/test_identify_key_type.py Co-authored-by: Breno Viana --- tests/services/test_identify_key_type.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/services/test_identify_key_type.py b/tests/services/test_identify_key_type.py index 86737749..6a609790 100644 --- a/tests/services/test_identify_key_type.py +++ b/tests/services/test_identify_key_type.py @@ -86,6 +86,7 @@ def test_is_cnpj(self): """ ): result = PixService().identify_key_type(cnpj) + with self.then( """ - o tipo da chave identificado deve ser documento From 3e2fc284b2586fe4c14298a04bf54b0950c593f2 Mon Sep 17 00:00:00 2001 From: Pedro Fonseca <32584628+peidrao@users.noreply.github.com> Date: Thu, 4 May 2023 10:49:52 -0300 Subject: [PATCH 077/139] Update tests/services/test_identify_key_type.py Co-authored-by: Breno Viana --- tests/services/test_identify_key_type.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/services/test_identify_key_type.py b/tests/services/test_identify_key_type.py index 6a609790..c6a901ee 100644 --- a/tests/services/test_identify_key_type.py +++ b/tests/services/test_identify_key_type.py @@ -80,6 +80,7 @@ def test_is_cnpj(self): """ ): cnpj = "03794722000153" + with self.when( """ - for utilizado o service de PIX para identificação do tipo da chave From 5f13d75e134ab9fa7f14ae3286c099b7f17b38cf Mon Sep 17 00:00:00 2001 From: Pedro Fonseca <32584628+peidrao@users.noreply.github.com> Date: Thu, 4 May 2023 16:08:50 -0300 Subject: [PATCH 078/139] Update bb_wrapper/models/pagamentos.py Co-authored-by: Rodrigo Castro --- bb_wrapper/models/pagamentos.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bb_wrapper/models/pagamentos.py b/bb_wrapper/models/pagamentos.py index bf6c3d69..c1bbcbb7 100644 --- a/bb_wrapper/models/pagamentos.py +++ b/bb_wrapper/models/pagamentos.py @@ -82,8 +82,8 @@ def _set_data(cls, values): values["dddTelefone"] = key[:2] values["telefone"] = key[2:] elif key_type == TipoChavePIX.email: - if PixService().verify_email(key): - values["email"] = key + PixService().verify_email(key) + values["email"] = key elif key_type == TipoChavePIX.uuid: values["identificacaoAleatoria"] = key elif key_type == TipoChavePIX.documento: From f7c8c76676377660d38ab15c8570204a6cd080a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=F0=9F=87=BB=F0=9F=87=A6=20=20Pedro=20Fonseca?= Date: Fri, 5 May 2023 10:26:51 -0300 Subject: [PATCH 079/139] =?UTF-8?q?Melhorar=20coment=C3=A1rios=20em=20test?= =?UTF-8?q?es=20e=20remo=C3=A7=C3=A3o=20de=20m=C3=A9todo=20para=20buscar?= =?UTF-8?q?=20transfer=C3=AAncia=20em=20lotes.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bb_wrapper/services/document.py | 5 ++- bb_wrapper/wrapper/pagamento_lote.py | 7 ---- .../consultar_transferencia_pix.py | 13 ------ .../data/consultar_transferencia_pix.json | 35 ---------------- tests/services/test_documento.py | 40 +++++++++---------- tests/wrapper/test_pagamentos.py | 22 ---------- 6 files changed, 23 insertions(+), 99 deletions(-) delete mode 100644 examples/lotes_pagamento/consultar_transferencia_pix.py delete mode 100644 examples/lotes_pagamento/data/consultar_transferencia_pix.json diff --git a/bb_wrapper/services/document.py b/bb_wrapper/services/document.py index f464319c..c3461b9c 100644 --- a/bb_wrapper/services/document.py +++ b/bb_wrapper/services/document.py @@ -1,4 +1,5 @@ from pycpfcnpj import cpfcnpj +from bb_wrapper.models.perfis import TipoInscricaoEnum class DocumentoService: @@ -12,9 +13,9 @@ def identifica_tipo(self, documento): """ documento = self.valida(documento) if len(documento) == 11: - return 1 + return TipoInscricaoEnum.cpf else: - return 2 + return TipoInscricaoEnum.cnpj def valida(self, documento): """ diff --git a/bb_wrapper/wrapper/pagamento_lote.py b/bb_wrapper/wrapper/pagamento_lote.py index f401d4a7..d43ca4f7 100644 --- a/bb_wrapper/wrapper/pagamento_lote.py +++ b/bb_wrapper/wrapper/pagamento_lote.py @@ -558,10 +558,3 @@ def criar_transferencia_pix( response = self._post(url, data) return response - - def consultar_transferencia_pix(self, _id): - url = self._construct_url("lotes-transferencias-pix", _id, "solicitacao") - - response = self._get(url) - - return response diff --git a/examples/lotes_pagamento/consultar_transferencia_pix.py b/examples/lotes_pagamento/consultar_transferencia_pix.py deleted file mode 100644 index 728d1974..00000000 --- a/examples/lotes_pagamento/consultar_transferencia_pix.py +++ /dev/null @@ -1,13 +0,0 @@ -import os - -from examples.utils import dump_response - -from bb_wrapper.wrapper import PagamentoLoteBBWrapper - -c = PagamentoLoteBBWrapper(cert=("./certs/cert.pem", "./certs/key.pem")) - -_id = "9221347" - -response = c.consultar_transferencia_pix(_id) - -dump_response(response, os.path.realpath(__file__)) diff --git a/examples/lotes_pagamento/data/consultar_transferencia_pix.json b/examples/lotes_pagamento/data/consultar_transferencia_pix.json deleted file mode 100644 index 603a354a..00000000 --- a/examples/lotes_pagamento/data/consultar_transferencia_pix.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "numeroRequisicao": 9221347, - "estadoRequisicao": 4, - "quantidadeTransferencias": 1, - "valorTransferencias": 7999.99, - "quantidadeTransferenciasValidas": 1, - "valorTransferenciasValidas": 7999.99, - "listaTransferencias": [ - { - "identificadorPagamento": 99221347731030000, - "data": 20042023, - "valor": 7999.99, - "documentoDebito": 0, - "documentoCredito": 0, - "descricaoPagamento": "transferencia CPF", - "descricaoPagamentoInstantaneo": "", - "formaIdentificacao": 3, - "dddTelefone": 0, - "telefone": 0, - "email": "", - "cpf": 28779295827, - "cnpj": 0, - "identificacaoAleatoria": "", - "numeroCOMPE": 0, - "numeroISPB": 0, - "tipoConta": 0, - "agencia": 0, - "conta": 0, - "digitoVerificadorConta": "", - "contaPagamento": "", - "indicadorMovimentoAceito": "S", - "erros": [] - } - ] -} diff --git a/tests/services/test_documento.py b/tests/services/test_documento.py index 315d35ff..0e43465e 100644 --- a/tests/services/test_documento.py +++ b/tests/services/test_documento.py @@ -1,4 +1,5 @@ from py_bdd_context import BDDContextTestCase +from bb_wrapper.models.perfis import TipoInscricaoEnum from bb_wrapper.services.document import DocumentoService @@ -9,107 +10,106 @@ class DocumentServiceTestCase(BDDContextTestCase): def test_identifica_tipo_pessoa_fisica(self): with self.given( """ - - Uma string '77855240098' + - um CPF '77855240098' """ ): cpf = "77855240098" with self.when( """ - - DocumentoService().identifica_tipo('77855240098') + - utilizar o service de Documento para identificar o tipo de pessoa """ ): result = DocumentoService().identifica_tipo(cpf) with self.then( """ - - O resultado deve ser 1 + - o tipo de pessoa deve ser física """ ): - expected = 1 + expected = TipoInscricaoEnum.cpf self.assertEqual(result, expected) def test_identifica_tipo_pessoa_fisica_com_pontuacao(self): with self.given( """ - - Uma string '778.552.400-98' + - um CPF com pontuação '778.552.400-98' """ ): cpf = "778.552.400-98" with self.when( """ - - DocumentoService().identifica_tipo('778.552.400-98') + - utilizar o service de Documento para identificar o tipo de pessoa """ ): result = DocumentoService().identifica_tipo(cpf) with self.then( """ - - O resultado deve ser 1 + - o tipo de pessoa deve ser física """ ): - expected = 1 - + expected = TipoInscricaoEnum.cpf self.assertEqual(result, expected) def test_identifica_tipo_pessoa_juridica(self): with self.given( """ - - Uma string '55468100000139' + - um CNPJ sem pontuação '55468100000139' """ ): cnpj = "55468100000139" with self.when( """ - - DocumentoService().identifica_tipo('55468100000139') + - utilizar o service de Documento para identificar o tipo de pessoa """ ): result = DocumentoService().identifica_tipo(cnpj) with self.then( """ - - O resultado deve ser 2 + - o tipo de pessoa deve ser jurídica """ ): - expected = 2 + expected = TipoInscricaoEnum.cnpj self.assertEqual(result, expected) def test_identifica_tipo_pessoa_juridica_com_pontuacao(self): with self.given( """ - - Uma string '18.853.097/0001-40' + - um CNPJ sem pontuação '18.853.097/0001-40' """ ): cnpj = "18.853.097/0001-40" with self.when( """ - - DocumentoService().identifica_tipo('18.853.097/0001-40') + - utilizar o service de Documento para identificar o tipo de pessoa """ ): result = DocumentoService().identifica_tipo(cnpj) with self.then( """ - - O resultado deve ser 2 + - o tipo de pessoa deve ser jurídica """ ): - expected = 2 + expected = TipoInscricaoEnum.cnpj self.assertEqual(result, expected) def test_identifica_tipo_pessoa_document_invalid(self): with self.given( """ - - Uma string '554681000001' + - um valor que não corresponde a um CPF e nem CPNJ sem pontuação: '554681000001' """ ): invalid_document = "554681000001" with self.when( """ - - DocumentoService().identifica_tipo('554681000001') + - utilizar o service de Documento para identificar o tipo de pessoa """ ): with self.assertRaises(ValueError) as ctx: @@ -117,7 +117,7 @@ def test_identifica_tipo_pessoa_document_invalid(self): with self.then( """ - - CPF/CNPJ '554681000001' é inválido! + - deverá ser levantada uma exceção informando que o CPF/CNPJ é inválido! """ ): self.assertEqual( diff --git a/tests/wrapper/test_pagamentos.py b/tests/wrapper/test_pagamentos.py index 4c44700f..4869e68e 100644 --- a/tests/wrapper/test_pagamentos.py +++ b/tests/wrapper/test_pagamentos.py @@ -906,25 +906,3 @@ def test_criar_transferencia_pix_cnpj(self): self.assertEqual(expected_json, response.json()) self.assertEqual(2, self.total_requests()) self.mock_responses.assert_call_count(request_url, 1) - - def test_consultar_transferencia_pix(self): - """ - Teste para verificar a URL da requisição e dados da transferência pix - """ - request_url = PagamentoLoteBBWrapper()._construct_url("boletos", "1") - expected_json = {} - self.mock_responses.add( - responses.GET, - request_url, - headers=self._build_authorization_header(1), - json=expected_json, - ) - - response = PagamentoLoteBBWrapper().consultar_pagamento_boleto("1") - - self.assertEqual(request_url, response.url) - self.assertEqual(self._get_headers(), response.headers) - self.assertEqual(expected_json, response.json()) - - self.assertEqual(2, self.total_requests()) - self.mock_responses.assert_call_count(request_url, 1) From 002c06580cb50a0707e43b2a301e017cc566821d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=F0=9F=87=BB=F0=9F=87=A6=20=20Pedro=20Fonseca?= Date: Fri, 5 May 2023 10:35:42 -0300 Subject: [PATCH 080/139] Atualizacao de requests --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index d781985e..ffb994fe 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -68,7 +68,7 @@ include = [] [tool.poetry.dependencies] python = "^3.8" -requests = "^2.26.0" +requests = "^2.30.0" python-decouple = "^3.4" pydantic = "^1.8.2" python-barcode = "^0.13.1" From 605729eb146e70842a9681ba74144d0a20708c05 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=F0=9F=87=BB=F0=9F=87=A6=20=20Pedro=20Fonseca?= Date: Fri, 5 May 2023 10:37:00 -0300 Subject: [PATCH 081/139] Atualizacao de poetry.lock --- poetry.lock | 373 ++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 320 insertions(+), 53 deletions(-) diff --git a/poetry.lock b/poetry.lock index f84c01cb..030ead4e 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,3 +1,5 @@ +# This file is automatically @generated by Poetry 1.4.2 and should not be changed by hand. + [[package]] name = "black" version = "22.12.0" @@ -5,6 +7,20 @@ description = "The uncompromising code formatter." category = "dev" optional = false python-versions = ">=3.7" +files = [ + {file = "black-22.12.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9eedd20838bd5d75b80c9f5487dbcb06836a43833a37846cf1d8c1cc01cef59d"}, + {file = "black-22.12.0-cp310-cp310-win_amd64.whl", hash = "sha256:159a46a4947f73387b4d83e87ea006dbb2337eab6c879620a3ba52699b1f4351"}, + {file = "black-22.12.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d30b212bffeb1e252b31dd269dfae69dd17e06d92b87ad26e23890f3efea366f"}, + {file = "black-22.12.0-cp311-cp311-win_amd64.whl", hash = "sha256:7412e75863aa5c5411886804678b7d083c7c28421210180d67dfd8cf1221e1f4"}, + {file = "black-22.12.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c116eed0efb9ff870ded8b62fe9f28dd61ef6e9ddd28d83d7d264a38417dcee2"}, + {file = "black-22.12.0-cp37-cp37m-win_amd64.whl", hash = "sha256:1f58cbe16dfe8c12b7434e50ff889fa479072096d79f0a7f25e4ab8e94cd8350"}, + {file = "black-22.12.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:77d86c9f3db9b1bf6761244bc0b3572a546f5fe37917a044e02f3166d5aafa7d"}, + {file = "black-22.12.0-cp38-cp38-win_amd64.whl", hash = "sha256:82d9fe8fee3401e02e79767016b4907820a7dc28d70d137eb397b92ef3cc5bfc"}, + {file = "black-22.12.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:101c69b23df9b44247bd88e1d7e90154336ac4992502d4197bdac35dd7ee3320"}, + {file = "black-22.12.0-cp39-cp39-win_amd64.whl", hash = "sha256:559c7a1ba9a006226f09e4916060982fd27334ae1998e7a38b3f33a37f7a2148"}, + {file = "black-22.12.0-py3-none-any.whl", hash = "sha256:436cc9167dd28040ad90d3b404aec22cedf24a6e4d7de221bec2730ec0c97bcf"}, + {file = "black-22.12.0.tar.gz", hash = "sha256:229351e5a18ca30f447bf724d007f890f97e13af070bb6ad4c0a441cd7596a2f"}, +] [package.dependencies] click = ">=8.0.0" @@ -27,6 +43,10 @@ description = "Python package for providing Mozilla's CA Bundle." category = "main" optional = false python-versions = ">=3.6" +files = [ + {file = "certifi-2022.12.7-py3-none-any.whl", hash = "sha256:4ad3232f5e926d6718ec31cfc1fcadfde020920e278684144551c91769c7bc18"}, + {file = "certifi-2022.12.7.tar.gz", hash = "sha256:35824b4c3a97115964b408844d64aa14db1cc518f6562e8d7261699d1350a9e3"}, +] [[package]] name = "charset-normalizer" @@ -35,6 +55,83 @@ description = "The Real First Universal Charset Detector. Open, modern and activ category = "main" optional = false python-versions = ">=3.7.0" +files = [ + {file = "charset-normalizer-3.1.0.tar.gz", hash = "sha256:34e0a2f9c370eb95597aae63bf85eb5e96826d81e3dcf88b8886012906f509b5"}, + {file = "charset_normalizer-3.1.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:e0ac8959c929593fee38da1c2b64ee9778733cdf03c482c9ff1d508b6b593b2b"}, + {file = "charset_normalizer-3.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d7fc3fca01da18fbabe4625d64bb612b533533ed10045a2ac3dd194bfa656b60"}, + {file = "charset_normalizer-3.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:04eefcee095f58eaabe6dc3cc2262f3bcd776d2c67005880894f447b3f2cb9c1"}, + {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:20064ead0717cf9a73a6d1e779b23d149b53daf971169289ed2ed43a71e8d3b0"}, + {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1435ae15108b1cb6fffbcea2af3d468683b7afed0169ad718451f8db5d1aff6f"}, + {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c84132a54c750fda57729d1e2599bb598f5fa0344085dbde5003ba429a4798c0"}, + {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:75f2568b4189dda1c567339b48cba4ac7384accb9c2a7ed655cd86b04055c795"}, + {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:11d3bcb7be35e7b1bba2c23beedac81ee893ac9871d0ba79effc7fc01167db6c"}, + {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:891cf9b48776b5c61c700b55a598621fdb7b1e301a550365571e9624f270c203"}, + {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:5f008525e02908b20e04707a4f704cd286d94718f48bb33edddc7d7b584dddc1"}, + {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:b06f0d3bf045158d2fb8837c5785fe9ff9b8c93358be64461a1089f5da983137"}, + {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:49919f8400b5e49e961f320c735388ee686a62327e773fa5b3ce6721f7e785ce"}, + {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:22908891a380d50738e1f978667536f6c6b526a2064156203d418f4856d6e86a"}, + {file = "charset_normalizer-3.1.0-cp310-cp310-win32.whl", hash = "sha256:12d1a39aa6b8c6f6248bb54550efcc1c38ce0d8096a146638fd4738e42284448"}, + {file = "charset_normalizer-3.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:65ed923f84a6844de5fd29726b888e58c62820e0769b76565480e1fdc3d062f8"}, + {file = "charset_normalizer-3.1.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:9a3267620866c9d17b959a84dd0bd2d45719b817245e49371ead79ed4f710d19"}, + {file = "charset_normalizer-3.1.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6734e606355834f13445b6adc38b53c0fd45f1a56a9ba06c2058f86893ae8017"}, + {file = "charset_normalizer-3.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f8303414c7b03f794347ad062c0516cee0e15f7a612abd0ce1e25caf6ceb47df"}, + {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aaf53a6cebad0eae578f062c7d462155eada9c172bd8c4d250b8c1d8eb7f916a"}, + {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3dc5b6a8ecfdc5748a7e429782598e4f17ef378e3e272eeb1340ea57c9109f41"}, + {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e1b25e3ad6c909f398df8921780d6a3d120d8c09466720226fc621605b6f92b1"}, + {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0ca564606d2caafb0abe6d1b5311c2649e8071eb241b2d64e75a0d0065107e62"}, + {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b82fab78e0b1329e183a65260581de4375f619167478dddab510c6c6fb04d9b6"}, + {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:bd7163182133c0c7701b25e604cf1611c0d87712e56e88e7ee5d72deab3e76b5"}, + {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:11d117e6c63e8f495412d37e7dc2e2fff09c34b2d09dbe2bee3c6229577818be"}, + {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:cf6511efa4801b9b38dc5546d7547d5b5c6ef4b081c60b23e4d941d0eba9cbeb"}, + {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:abc1185d79f47c0a7aaf7e2412a0eb2c03b724581139193d2d82b3ad8cbb00ac"}, + {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:cb7b2ab0188829593b9de646545175547a70d9a6e2b63bf2cd87a0a391599324"}, + {file = "charset_normalizer-3.1.0-cp311-cp311-win32.whl", hash = "sha256:c36bcbc0d5174a80d6cccf43a0ecaca44e81d25be4b7f90f0ed7bcfbb5a00909"}, + {file = "charset_normalizer-3.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:cca4def576f47a09a943666b8f829606bcb17e2bc2d5911a46c8f8da45f56755"}, + {file = "charset_normalizer-3.1.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:0c95f12b74681e9ae127728f7e5409cbbef9cd914d5896ef238cc779b8152373"}, + {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fca62a8301b605b954ad2e9c3666f9d97f63872aa4efcae5492baca2056b74ab"}, + {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ac0aa6cd53ab9a31d397f8303f92c42f534693528fafbdb997c82bae6e477ad9"}, + {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c3af8e0f07399d3176b179f2e2634c3ce9c1301379a6b8c9c9aeecd481da494f"}, + {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3a5fc78f9e3f501a1614a98f7c54d3969f3ad9bba8ba3d9b438c3bc5d047dd28"}, + {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:628c985afb2c7d27a4800bfb609e03985aaecb42f955049957814e0491d4006d"}, + {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:74db0052d985cf37fa111828d0dd230776ac99c740e1a758ad99094be4f1803d"}, + {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:1e8fcdd8f672a1c4fc8d0bd3a2b576b152d2a349782d1eb0f6b8e52e9954731d"}, + {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:04afa6387e2b282cf78ff3dbce20f0cc071c12dc8f685bd40960cc68644cfea6"}, + {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:dd5653e67b149503c68c4018bf07e42eeed6b4e956b24c00ccdf93ac79cdff84"}, + {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:d2686f91611f9e17f4548dbf050e75b079bbc2a82be565832bc8ea9047b61c8c"}, + {file = "charset_normalizer-3.1.0-cp37-cp37m-win32.whl", hash = "sha256:4155b51ae05ed47199dc5b2a4e62abccb274cee6b01da5b895099b61b1982974"}, + {file = "charset_normalizer-3.1.0-cp37-cp37m-win_amd64.whl", hash = "sha256:322102cdf1ab682ecc7d9b1c5eed4ec59657a65e1c146a0da342b78f4112db23"}, + {file = "charset_normalizer-3.1.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:e633940f28c1e913615fd624fcdd72fdba807bf53ea6925d6a588e84e1151531"}, + {file = "charset_normalizer-3.1.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:3a06f32c9634a8705f4ca9946d667609f52cf130d5548881401f1eb2c39b1e2c"}, + {file = "charset_normalizer-3.1.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:7381c66e0561c5757ffe616af869b916c8b4e42b367ab29fedc98481d1e74e14"}, + {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3573d376454d956553c356df45bb824262c397c6e26ce43e8203c4c540ee0acb"}, + {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e89df2958e5159b811af9ff0f92614dabf4ff617c03a4c1c6ff53bf1c399e0e1"}, + {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:78cacd03e79d009d95635e7d6ff12c21eb89b894c354bd2b2ed0b4763373693b"}, + {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:de5695a6f1d8340b12a5d6d4484290ee74d61e467c39ff03b39e30df62cf83a0"}, + {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1c60b9c202d00052183c9be85e5eaf18a4ada0a47d188a83c8f5c5b23252f649"}, + {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:f645caaf0008bacf349875a974220f1f1da349c5dbe7c4ec93048cdc785a3326"}, + {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:ea9f9c6034ea2d93d9147818f17c2a0860d41b71c38b9ce4d55f21b6f9165a11"}, + {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:80d1543d58bd3d6c271b66abf454d437a438dff01c3e62fdbcd68f2a11310d4b"}, + {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:73dc03a6a7e30b7edc5b01b601e53e7fc924b04e1835e8e407c12c037e81adbd"}, + {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:6f5c2e7bc8a4bf7c426599765b1bd33217ec84023033672c1e9a8b35eaeaaaf8"}, + {file = "charset_normalizer-3.1.0-cp38-cp38-win32.whl", hash = "sha256:12a2b561af122e3d94cdb97fe6fb2bb2b82cef0cdca131646fdb940a1eda04f0"}, + {file = "charset_normalizer-3.1.0-cp38-cp38-win_amd64.whl", hash = "sha256:3160a0fd9754aab7d47f95a6b63ab355388d890163eb03b2d2b87ab0a30cfa59"}, + {file = "charset_normalizer-3.1.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:38e812a197bf8e71a59fe55b757a84c1f946d0ac114acafaafaf21667a7e169e"}, + {file = "charset_normalizer-3.1.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6baf0baf0d5d265fa7944feb9f7451cc316bfe30e8df1a61b1bb08577c554f31"}, + {file = "charset_normalizer-3.1.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:8f25e17ab3039b05f762b0a55ae0b3632b2e073d9c8fc88e89aca31a6198e88f"}, + {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3747443b6a904001473370d7810aa19c3a180ccd52a7157aacc264a5ac79265e"}, + {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b116502087ce8a6b7a5f1814568ccbd0e9f6cfd99948aa59b0e241dc57cf739f"}, + {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d16fd5252f883eb074ca55cb622bc0bee49b979ae4e8639fff6ca3ff44f9f854"}, + {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:21fa558996782fc226b529fdd2ed7866c2c6ec91cee82735c98a197fae39f706"}, + {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6f6c7a8a57e9405cad7485f4c9d3172ae486cfef1344b5ddd8e5239582d7355e"}, + {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:ac3775e3311661d4adace3697a52ac0bab17edd166087d493b52d4f4f553f9f0"}, + {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:10c93628d7497c81686e8e5e557aafa78f230cd9e77dd0c40032ef90c18f2230"}, + {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:6f4f4668e1831850ebcc2fd0b1cd11721947b6dc7c00bf1c6bd3c929ae14f2c7"}, + {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:0be65ccf618c1e7ac9b849c315cc2e8a8751d9cfdaa43027d4f6624bd587ab7e"}, + {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:53d0a3fa5f8af98a1e261de6a3943ca631c526635eb5817a87a59d9a57ebf48f"}, + {file = "charset_normalizer-3.1.0-cp39-cp39-win32.whl", hash = "sha256:a04f86f41a8916fe45ac5024ec477f41f886b3c435da2d4e3d2709b22ab02af1"}, + {file = "charset_normalizer-3.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:830d2948a5ec37c386d3170c483063798d7879037492540f10a475e3fd6f244b"}, + {file = "charset_normalizer-3.1.0-py3-none-any.whl", hash = "sha256:3d9098b479e78c85080c98e1e35ff40b4a31d8953102bb0fd7d1b6f8a2111a3d"}, +] [[package]] name = "click" @@ -43,6 +140,10 @@ description = "Composable command line interface toolkit" category = "dev" optional = false python-versions = ">=3.7" +files = [ + {file = "click-8.1.3-py3-none-any.whl", hash = "sha256:bb4d8133cb15a609f44e8213d9b391b0809795062913b383c62be0ee95b1db48"}, + {file = "click-8.1.3.tar.gz", hash = "sha256:7682dc8afb30297001674575ea00d1814d808d6a36af415a82bd481d37ba7b8e"}, +] [package.dependencies] colorama = {version = "*", markers = "platform_system == \"Windows\""} @@ -54,6 +155,10 @@ description = "Cross-platform colored terminal text." category = "main" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" +files = [ + {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, + {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, +] [[package]] name = "coverage" @@ -62,6 +167,60 @@ description = "Code coverage measurement for Python" category = "dev" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <4" +files = [ + {file = "coverage-5.5-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:b6d534e4b2ab35c9f93f46229363e17f63c53ad01330df9f2d6bd1187e5eaacf"}, + {file = "coverage-5.5-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:b7895207b4c843c76a25ab8c1e866261bcfe27bfaa20c192de5190121770672b"}, + {file = "coverage-5.5-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:c2723d347ab06e7ddad1a58b2a821218239249a9e4365eaff6649d31180c1669"}, + {file = "coverage-5.5-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:900fbf7759501bc7807fd6638c947d7a831fc9fdf742dc10f02956ff7220fa90"}, + {file = "coverage-5.5-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:004d1880bed2d97151facef49f08e255a20ceb6f9432df75f4eef018fdd5a78c"}, + {file = "coverage-5.5-cp27-cp27m-win32.whl", hash = "sha256:06191eb60f8d8a5bc046f3799f8a07a2d7aefb9504b0209aff0b47298333302a"}, + {file = "coverage-5.5-cp27-cp27m-win_amd64.whl", hash = "sha256:7501140f755b725495941b43347ba8a2777407fc7f250d4f5a7d2a1050ba8e82"}, + {file = "coverage-5.5-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:372da284cfd642d8e08ef606917846fa2ee350f64994bebfbd3afb0040436905"}, + {file = "coverage-5.5-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:8963a499849a1fc54b35b1c9f162f4108017b2e6db2c46c1bed93a72262ed083"}, + {file = "coverage-5.5-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:869a64f53488f40fa5b5b9dcb9e9b2962a66a87dab37790f3fcfb5144b996ef5"}, + {file = "coverage-5.5-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:4a7697d8cb0f27399b0e393c0b90f0f1e40c82023ea4d45d22bce7032a5d7b81"}, + {file = "coverage-5.5-cp310-cp310-macosx_10_14_x86_64.whl", hash = "sha256:8d0a0725ad7c1a0bcd8d1b437e191107d457e2ec1084b9f190630a4fb1af78e6"}, + {file = "coverage-5.5-cp310-cp310-manylinux1_x86_64.whl", hash = "sha256:51cb9476a3987c8967ebab3f0fe144819781fca264f57f89760037a2ea191cb0"}, + {file = "coverage-5.5-cp310-cp310-win_amd64.whl", hash = "sha256:c0891a6a97b09c1f3e073a890514d5012eb256845c451bd48f7968ef939bf4ae"}, + {file = "coverage-5.5-cp35-cp35m-macosx_10_9_x86_64.whl", hash = "sha256:3487286bc29a5aa4b93a072e9592f22254291ce96a9fbc5251f566b6b7343cdb"}, + {file = "coverage-5.5-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:deee1077aae10d8fa88cb02c845cfba9b62c55e1183f52f6ae6a2df6a2187160"}, + {file = "coverage-5.5-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:f11642dddbb0253cc8853254301b51390ba0081750a8ac03f20ea8103f0c56b6"}, + {file = "coverage-5.5-cp35-cp35m-manylinux2010_i686.whl", hash = "sha256:6c90e11318f0d3c436a42409f2749ee1a115cd8b067d7f14c148f1ce5574d701"}, + {file = "coverage-5.5-cp35-cp35m-manylinux2010_x86_64.whl", hash = "sha256:30c77c1dc9f253283e34c27935fded5015f7d1abe83bc7821680ac444eaf7793"}, + {file = "coverage-5.5-cp35-cp35m-win32.whl", hash = "sha256:9a1ef3b66e38ef8618ce5fdc7bea3d9f45f3624e2a66295eea5e57966c85909e"}, + {file = "coverage-5.5-cp35-cp35m-win_amd64.whl", hash = "sha256:972c85d205b51e30e59525694670de6a8a89691186012535f9d7dbaa230e42c3"}, + {file = "coverage-5.5-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:af0e781009aaf59e25c5a678122391cb0f345ac0ec272c7961dc5455e1c40066"}, + {file = "coverage-5.5-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:74d881fc777ebb11c63736622b60cb9e4aee5cace591ce274fb69e582a12a61a"}, + {file = "coverage-5.5-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:92b017ce34b68a7d67bd6d117e6d443a9bf63a2ecf8567bb3d8c6c7bc5014465"}, + {file = "coverage-5.5-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:d636598c8305e1f90b439dbf4f66437de4a5e3c31fdf47ad29542478c8508bbb"}, + {file = "coverage-5.5-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:41179b8a845742d1eb60449bdb2992196e211341818565abded11cfa90efb821"}, + {file = "coverage-5.5-cp36-cp36m-win32.whl", hash = "sha256:040af6c32813fa3eae5305d53f18875bedd079960822ef8ec067a66dd8afcd45"}, + {file = "coverage-5.5-cp36-cp36m-win_amd64.whl", hash = "sha256:5fec2d43a2cc6965edc0bb9e83e1e4b557f76f843a77a2496cbe719583ce8184"}, + {file = "coverage-5.5-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:18ba8bbede96a2c3dde7b868de9dcbd55670690af0988713f0603f037848418a"}, + {file = "coverage-5.5-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:2910f4d36a6a9b4214bb7038d537f015346f413a975d57ca6b43bf23d6563b53"}, + {file = "coverage-5.5-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:f0b278ce10936db1a37e6954e15a3730bea96a0997c26d7fee88e6c396c2086d"}, + {file = "coverage-5.5-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:796c9c3c79747146ebd278dbe1e5c5c05dd6b10cc3bcb8389dfdf844f3ead638"}, + {file = "coverage-5.5-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:53194af30d5bad77fcba80e23a1441c71abfb3e01192034f8246e0d8f99528f3"}, + {file = "coverage-5.5-cp37-cp37m-win32.whl", hash = "sha256:184a47bbe0aa6400ed2d41d8e9ed868b8205046518c52464fde713ea06e3a74a"}, + {file = "coverage-5.5-cp37-cp37m-win_amd64.whl", hash = "sha256:2949cad1c5208b8298d5686d5a85b66aae46d73eec2c3e08c817dd3513e5848a"}, + {file = "coverage-5.5-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:217658ec7187497e3f3ebd901afdca1af062b42cfe3e0dafea4cced3983739f6"}, + {file = "coverage-5.5-cp38-cp38-manylinux1_i686.whl", hash = "sha256:1aa846f56c3d49205c952d8318e76ccc2ae23303351d9270ab220004c580cfe2"}, + {file = "coverage-5.5-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:24d4a7de75446be83244eabbff746d66b9240ae020ced65d060815fac3423759"}, + {file = "coverage-5.5-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:d1f8bf7b90ba55699b3a5e44930e93ff0189aa27186e96071fac7dd0d06a1873"}, + {file = "coverage-5.5-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:970284a88b99673ccb2e4e334cfb38a10aab7cd44f7457564d11898a74b62d0a"}, + {file = "coverage-5.5-cp38-cp38-win32.whl", hash = "sha256:01d84219b5cdbfc8122223b39a954820929497a1cb1422824bb86b07b74594b6"}, + {file = "coverage-5.5-cp38-cp38-win_amd64.whl", hash = "sha256:2e0d881ad471768bf6e6c2bf905d183543f10098e3b3640fc029509530091502"}, + {file = "coverage-5.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:d1f9ce122f83b2305592c11d64f181b87153fc2c2bbd3bb4a3dde8303cfb1a6b"}, + {file = "coverage-5.5-cp39-cp39-manylinux1_i686.whl", hash = "sha256:13c4ee887eca0f4c5a247b75398d4114c37882658300e153113dafb1d76de529"}, + {file = "coverage-5.5-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:52596d3d0e8bdf3af43db3e9ba8dcdaac724ba7b5ca3f6358529d56f7a166f8b"}, + {file = "coverage-5.5-cp39-cp39-manylinux2010_i686.whl", hash = "sha256:2cafbbb3af0733db200c9b5f798d18953b1a304d3f86a938367de1567f4b5bff"}, + {file = "coverage-5.5-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:44d654437b8ddd9eee7d1eaee28b7219bec228520ff809af170488fd2fed3e2b"}, + {file = "coverage-5.5-cp39-cp39-win32.whl", hash = "sha256:d314ed732c25d29775e84a960c3c60808b682c08d86602ec2c3008e1202e3bb6"}, + {file = "coverage-5.5-cp39-cp39-win_amd64.whl", hash = "sha256:13034c4409db851670bc9acd836243aeee299949bd5673e11844befcb0149f03"}, + {file = "coverage-5.5-pp36-none-any.whl", hash = "sha256:f030f8873312a16414c0d8e1a1ddff2d3235655a2174e3648b4fa66b3f2f1079"}, + {file = "coverage-5.5-pp37-none-any.whl", hash = "sha256:2a3859cb82dcbda1cfd3e6f71c27081d18aa251d20a17d87d26d4cd216fb0af4"}, + {file = "coverage-5.5.tar.gz", hash = "sha256:ebe78fe9a0e874362175b02371bdfbee64d8edc42a044253ddf4ee7d3c15212c"}, +] [package.dependencies] toml = {version = "*", optional = true, markers = "extra == \"toml\""} @@ -76,6 +235,10 @@ description = "Library and CLI to calculate and verify all kinds of CRC checksum category = "main" optional = false python-versions = ">=3.7,<4.0" +files = [ + {file = "crc-1.3.0-py3-none-any.whl", hash = "sha256:963bbb9b0aabb511654551fe5d24402294096a731776ca79910a2363318f41cd"}, + {file = "crc-1.3.0.tar.gz", hash = "sha256:0f4b7c2fbf259c5712adbe3e8cf072609cec5ae5ea6de77cc052de9078fce1ea"}, +] [[package]] name = "flake8" @@ -84,6 +247,10 @@ description = "the modular source code checker: pep8 pyflakes and co" category = "dev" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" +files = [ + {file = "flake8-3.9.2-py2.py3-none-any.whl", hash = "sha256:bf8fd333346d844f616e8d47905ef3a3384edae6b4e9beb0c5101e25e3110907"}, + {file = "flake8-3.9.2.tar.gz", hash = "sha256:07528381786f2a6237b061f6e96610a4167b226cb926e2aa2b6b1d78057c576b"}, +] [package.dependencies] mccabe = ">=0.6.0,<0.7.0" @@ -97,6 +264,10 @@ description = "Let your Python tests travel through time" category = "dev" optional = false python-versions = ">=3.5" +files = [ + {file = "freezegun-1.1.0-py2.py3-none-any.whl", hash = "sha256:2ae695f7eb96c62529f03a038461afe3c692db3465e215355e1bb4b0ab408712"}, + {file = "freezegun-1.1.0.tar.gz", hash = "sha256:177f9dd59861d871e27a484c3332f35a6e3f5d14626f2bf91be37891f18927f3"}, +] [package.dependencies] python-dateutil = ">=2.7" @@ -108,6 +279,10 @@ description = "Internationalized Domain Names in Applications (IDNA)" category = "main" optional = false python-versions = ">=3.5" +files = [ + {file = "idna-3.4-py3-none-any.whl", hash = "sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2"}, + {file = "idna-3.4.tar.gz", hash = "sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4"}, +] [[package]] name = "isort" @@ -116,12 +291,16 @@ description = "A Python utility / library to sort Python imports." category = "dev" optional = false python-versions = ">=3.8.0" +files = [ + {file = "isort-5.12.0-py3-none-any.whl", hash = "sha256:f84c2818376e66cf843d497486ea8fed8700b340f308f076c6fb1229dff318b6"}, + {file = "isort-5.12.0.tar.gz", hash = "sha256:8bef7dde241278824a6d83f44a544709b065191b95b6e50894bdc722fcba0504"}, +] [package.extras] colors = ["colorama (>=0.4.3)"] -requirements-deprecated-finder = ["pip-api", "pipreqs"] pipfile-deprecated-finder = ["pip-shims (>=0.5.2)", "pipreqs", "requirementslib"] plugins = ["setuptools"] +requirements-deprecated-finder = ["pip-api", "pipreqs"] [[package]] name = "mccabe" @@ -130,6 +309,10 @@ description = "McCabe checker, plugin for flake8" category = "dev" optional = false python-versions = "*" +files = [ + {file = "mccabe-0.6.1-py2.py3-none-any.whl", hash = "sha256:ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42"}, + {file = "mccabe-0.6.1.tar.gz", hash = "sha256:dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f"}, +] [[package]] name = "mypy-extensions" @@ -138,6 +321,10 @@ description = "Type system extensions for programs checked with the mypy type ch category = "dev" optional = false python-versions = ">=3.5" +files = [ + {file = "mypy_extensions-1.0.0-py3-none-any.whl", hash = "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d"}, + {file = "mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"}, +] [[package]] name = "pathspec" @@ -146,18 +333,26 @@ description = "Utility library for gitignore style pattern matching of file path category = "dev" optional = false python-versions = ">=3.7" +files = [ + {file = "pathspec-0.11.1-py3-none-any.whl", hash = "sha256:d8af70af76652554bd134c22b3e8a1cc46ed7d91edcdd721ef1a0c51a84a5293"}, + {file = "pathspec-0.11.1.tar.gz", hash = "sha256:2798de800fa92780e33acca925945e9a19a133b715067cf165b8866c15a31687"}, +] [[package]] name = "platformdirs" -version = "3.4.0" +version = "3.5.0" description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." category = "dev" optional = false python-versions = ">=3.7" +files = [ + {file = "platformdirs-3.5.0-py3-none-any.whl", hash = "sha256:47692bc24c1958e8b0f13dd727307cff1db103fca36399f457da8e05f222fdc4"}, + {file = "platformdirs-3.5.0.tar.gz", hash = "sha256:7954a68d0ba23558d753f73437c55f89027cf8f5108c19844d4b82e5af396335"}, +] [package.extras] -docs = ["furo (>=2023.3.27)", "proselint (>=0.13)", "sphinx-autodoc-typehints (>=1.23,!=1.23.4)", "sphinx (>=6.1.3)"] -test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest-cov (>=4)", "pytest-mock (>=3.10)", "pytest (>=7.3.1)"] +docs = ["furo (>=2023.3.27)", "proselint (>=0.13)", "sphinx (>=6.1.3)", "sphinx-autodoc-typehints (>=1.23,!=1.23.4)"] +test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.3.1)", "pytest-cov (>=4)", "pytest-mock (>=3.10)"] [[package]] name = "py-bdd-context" @@ -166,6 +361,10 @@ description = "Biblioteca com Context Manager para facilitar os testes de Behavi category = "dev" optional = false python-versions = ">=3.8,<4.0" +files = [ + {file = "py-bdd-context-0.0.4.tar.gz", hash = "sha256:cd14204bfb3a98fe64386757b7c6f8a5be8b510e4404b61bfcbc6a8cb9fe5f9e"}, + {file = "py_bdd_context-0.0.4-py3-none-any.whl", hash = "sha256:e7a77b1edf60e40e4f1d6f10f6ea82ae082f989ee60bf05f4bf4bf3520c033e7"}, +] [[package]] name = "pycodestyle" @@ -174,6 +373,10 @@ description = "Python style guide checker" category = "dev" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +files = [ + {file = "pycodestyle-2.7.0-py2.py3-none-any.whl", hash = "sha256:514f76d918fcc0b55c6680472f0a37970994e07bbb80725808c17089be302068"}, + {file = "pycodestyle-2.7.0.tar.gz", hash = "sha256:c389c1d06bf7904078ca03399a4816f974a1d590090fecea0c63ec26ebaf1cef"}, +] [[package]] name = "pycpfcnpj" @@ -182,6 +385,10 @@ description = "Python module for brazilian register numbers for persons (CPF) an category = "main" optional = false python-versions = "*" +files = [ + {file = "pycpfcnpj-1.7.0-py3-none-any.whl", hash = "sha256:28cff52153956062cb931747e56cdf2881fa86635bad64383a398da6836d4719"}, + {file = "pycpfcnpj-1.7.0.tar.gz", hash = "sha256:00ffceb1ed57234b4bcc081523140f604cd7929256d43913dbb413c263bee558"}, +] [[package]] name = "pydantic" @@ -190,6 +397,44 @@ description = "Data validation and settings management using python type hints" category = "main" optional = false python-versions = ">=3.7" +files = [ + {file = "pydantic-1.10.7-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e79e999e539872e903767c417c897e729e015872040e56b96e67968c3b918b2d"}, + {file = "pydantic-1.10.7-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:01aea3a42c13f2602b7ecbbea484a98169fb568ebd9e247593ea05f01b884b2e"}, + {file = "pydantic-1.10.7-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:516f1ed9bc2406a0467dd777afc636c7091d71f214d5e413d64fef45174cfc7a"}, + {file = "pydantic-1.10.7-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ae150a63564929c675d7f2303008d88426a0add46efd76c3fc797cd71cb1b46f"}, + {file = "pydantic-1.10.7-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:ecbbc51391248116c0a055899e6c3e7ffbb11fb5e2a4cd6f2d0b93272118a209"}, + {file = "pydantic-1.10.7-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:f4a2b50e2b03d5776e7f21af73e2070e1b5c0d0df255a827e7c632962f8315af"}, + {file = "pydantic-1.10.7-cp310-cp310-win_amd64.whl", hash = "sha256:a7cd2251439988b413cb0a985c4ed82b6c6aac382dbaff53ae03c4b23a70e80a"}, + {file = "pydantic-1.10.7-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:68792151e174a4aa9e9fc1b4e653e65a354a2fa0fed169f7b3d09902ad2cb6f1"}, + {file = "pydantic-1.10.7-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:dfe2507b8ef209da71b6fb5f4e597b50c5a34b78d7e857c4f8f3115effaef5fe"}, + {file = "pydantic-1.10.7-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:10a86d8c8db68086f1e30a530f7d5f83eb0685e632e411dbbcf2d5c0150e8dcd"}, + {file = "pydantic-1.10.7-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d75ae19d2a3dbb146b6f324031c24f8a3f52ff5d6a9f22f0683694b3afcb16fb"}, + {file = "pydantic-1.10.7-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:464855a7ff7f2cc2cf537ecc421291b9132aa9c79aef44e917ad711b4a93163b"}, + {file = "pydantic-1.10.7-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:193924c563fae6ddcb71d3f06fa153866423ac1b793a47936656e806b64e24ca"}, + {file = "pydantic-1.10.7-cp311-cp311-win_amd64.whl", hash = "sha256:b4a849d10f211389502059c33332e91327bc154acc1845f375a99eca3afa802d"}, + {file = "pydantic-1.10.7-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:cc1dde4e50a5fc1336ee0581c1612215bc64ed6d28d2c7c6f25d2fe3e7c3e918"}, + {file = "pydantic-1.10.7-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e0cfe895a504c060e5d36b287ee696e2fdad02d89e0d895f83037245218a87fe"}, + {file = "pydantic-1.10.7-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:670bb4683ad1e48b0ecb06f0cfe2178dcf74ff27921cdf1606e527d2617a81ee"}, + {file = "pydantic-1.10.7-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:950ce33857841f9a337ce07ddf46bc84e1c4946d2a3bba18f8280297157a3fd1"}, + {file = "pydantic-1.10.7-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:c15582f9055fbc1bfe50266a19771bbbef33dd28c45e78afbe1996fd70966c2a"}, + {file = "pydantic-1.10.7-cp37-cp37m-win_amd64.whl", hash = "sha256:82dffb306dd20bd5268fd6379bc4bfe75242a9c2b79fec58e1041fbbdb1f7914"}, + {file = "pydantic-1.10.7-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:8c7f51861d73e8b9ddcb9916ae7ac39fb52761d9ea0df41128e81e2ba42886cd"}, + {file = "pydantic-1.10.7-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:6434b49c0b03a51021ade5c4daa7d70c98f7a79e95b551201fff682fc1661245"}, + {file = "pydantic-1.10.7-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:64d34ab766fa056df49013bb6e79921a0265204c071984e75a09cbceacbbdd5d"}, + {file = "pydantic-1.10.7-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:701daea9ffe9d26f97b52f1d157e0d4121644f0fcf80b443248434958fd03dc3"}, + {file = "pydantic-1.10.7-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:cf135c46099ff3f919d2150a948ce94b9ce545598ef2c6c7bf55dca98a304b52"}, + {file = "pydantic-1.10.7-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:b0f85904f73161817b80781cc150f8b906d521fa11e3cdabae19a581c3606209"}, + {file = "pydantic-1.10.7-cp38-cp38-win_amd64.whl", hash = "sha256:9f6f0fd68d73257ad6685419478c5aece46432f4bdd8d32c7345f1986496171e"}, + {file = "pydantic-1.10.7-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:c230c0d8a322276d6e7b88c3f7ce885f9ed16e0910354510e0bae84d54991143"}, + {file = "pydantic-1.10.7-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:976cae77ba6a49d80f461fd8bba183ff7ba79f44aa5cfa82f1346b5626542f8e"}, + {file = "pydantic-1.10.7-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7d45fc99d64af9aaf7e308054a0067fdcd87ffe974f2442312372dfa66e1001d"}, + {file = "pydantic-1.10.7-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d2a5ebb48958754d386195fe9e9c5106f11275867051bf017a8059410e9abf1f"}, + {file = "pydantic-1.10.7-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:abfb7d4a7cd5cc4e1d1887c43503a7c5dd608eadf8bc615413fc498d3e4645cd"}, + {file = "pydantic-1.10.7-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:80b1fab4deb08a8292d15e43a6edccdffa5377a36a4597bb545b93e79c5ff0a5"}, + {file = "pydantic-1.10.7-cp39-cp39-win_amd64.whl", hash = "sha256:d71e69699498b020ea198468e2480a2f1e7433e32a3a99760058c6520e2bea7e"}, + {file = "pydantic-1.10.7-py3-none-any.whl", hash = "sha256:0cd181f1d0b1d00e2b705f1bf1ac7799a2d938cce3376b8007df62b29be3c2c6"}, + {file = "pydantic-1.10.7.tar.gz", hash = "sha256:cfc83c0678b6ba51b0532bea66860617c4cd4251ecf76e9846fa5a9f3454e97e"}, +] [package.dependencies] typing-extensions = ">=4.2.0" @@ -205,6 +450,10 @@ description = "passive checker of Python programs" category = "dev" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +files = [ + {file = "pyflakes-2.3.1-py2.py3-none-any.whl", hash = "sha256:7893783d01b8a89811dd72d7dfd4d84ff098e5eed95cfa8905b22bbffe52efc3"}, + {file = "pyflakes-2.3.1.tar.gz", hash = "sha256:f5bc8ecabc05bb9d291eb5203d6810b49040f6ff446a756326104746cc00c1db"}, +] [[package]] name = "pypng" @@ -213,6 +462,10 @@ description = "Pure Python library for saving and loading PNG images" category = "main" optional = false python-versions = "*" +files = [ + {file = "pypng-0.20220715.0-py3-none-any.whl", hash = "sha256:4a43e969b8f5aaafb2a415536c1a8ec7e341cd6a3f957fd5b5f32a4cfeed902c"}, + {file = "pypng-0.20220715.0.tar.gz", hash = "sha256:739c433ba96f078315de54c0db975aee537cbc3e1d0ae4ed9aab0ca1e427e2c1"}, +] [[package]] name = "python-barcode" @@ -221,6 +474,10 @@ description = "Create standard barcodes with Python. No external modules needed. category = "main" optional = false python-versions = "*" +files = [ + {file = "python-barcode-0.13.1.tar.gz", hash = "sha256:fafba4aa24e9d969777be521c294ff18f6c2b36ad63b5fc2f2108d972e23b252"}, + {file = "python_barcode-0.13.1-py3-none-any.whl", hash = "sha256:daa32fb999a843812fbb1c75ff909638811af7c465f0a991e9e41d26d2a44a24"}, +] [package.extras] images = ["pillow"] @@ -232,6 +489,10 @@ description = "Extensions to the standard Python datetime module" category = "dev" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" +files = [ + {file = "python-dateutil-2.8.2.tar.gz", hash = "sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86"}, + {file = "python_dateutil-2.8.2-py2.py3-none-any.whl", hash = "sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9"}, +] [package.dependencies] six = ">=1.5" @@ -243,6 +504,10 @@ description = "Strict separation of settings from code." category = "main" optional = false python-versions = "*" +files = [ + {file = "python-decouple-3.8.tar.gz", hash = "sha256:ba6e2657d4f376ecc46f77a3a615e058d93ba5e465c01bbe57289bfb7cce680f"}, + {file = "python_decouple-3.8-py3-none-any.whl", hash = "sha256:d0d45340815b25f4de59c974b855bb38d03151d81b037d9e3f463b0c9f8cbd66"}, +] [[package]] name = "qrcode" @@ -251,6 +516,10 @@ description = "QR Code image generator" category = "main" optional = false python-versions = ">=3.7" +files = [ + {file = "qrcode-7.4.2-py3-none-any.whl", hash = "sha256:581dca7a029bcb2deef5d01068e39093e80ef00b4a61098a2182eac59d01643a"}, + {file = "qrcode-7.4.2.tar.gz", hash = "sha256:9dd969454827e127dbd93696b20747239e6d540e082937c90f14ac95b30f5845"}, +] [package.dependencies] colorama = {version = "*", markers = "platform_system == \"Windows\""} @@ -258,29 +527,33 @@ pypng = "*" typing-extensions = "*" [package.extras] -all = ["zest.releaser", "tox", "pytest", "pytest-cov", "pillow (>=9.1.0)"] -dev = ["tox", "pytest", "pytest-cov"] -maintainer = ["zest.releaser"] +all = ["pillow (>=9.1.0)", "pytest", "pytest-cov", "tox", "zest.releaser[recommended]"] +dev = ["pytest", "pytest-cov", "tox"] +maintainer = ["zest.releaser[recommended]"] pil = ["pillow (>=9.1.0)"] test = ["coverage", "pytest"] [[package]] name = "requests" -version = "2.29.0" +version = "2.30.0" description = "Python HTTP for Humans." category = "main" optional = false python-versions = ">=3.7" +files = [ + {file = "requests-2.30.0-py3-none-any.whl", hash = "sha256:10e94cc4f3121ee6da529d358cdaeaff2f1c409cd377dbc72b825852f2f7e294"}, + {file = "requests-2.30.0.tar.gz", hash = "sha256:239d7d4458afcb28a692cdd298d87542235f4ca8d36d03a15bfc128a6559a2f4"}, +] [package.dependencies] certifi = ">=2017.4.17" charset-normalizer = ">=2,<4" idna = ">=2.5,<4" -urllib3 = ">=1.21.1,<1.27" +urllib3 = ">=1.21.1,<3" [package.extras] socks = ["PySocks (>=1.5.6,!=1.5.7)"] -use_chardet_on_py3 = ["chardet (>=3.0.2,<6)"] +use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] [[package]] name = "responses" @@ -289,13 +562,17 @@ description = "A utility library for mocking out the `requests` Python library." category = "dev" optional = false python-versions = ">=3.7" +files = [ + {file = "responses-0.21.0-py3-none-any.whl", hash = "sha256:2dcc863ba63963c0c3d9ee3fa9507cbe36b7d7b0fccb4f0bdfd9e96c539b1487"}, + {file = "responses-0.21.0.tar.gz", hash = "sha256:b82502eb5f09a0289d8e209e7bad71ef3978334f56d09b444253d5ad67bf5253"}, +] [package.dependencies] requests = ">=2.0,<3.0" urllib3 = ">=1.25.10" [package.extras] -tests = ["pytest (>=7.0.0)", "coverage (>=6.0.0)", "pytest-cov", "pytest-asyncio", "pytest-localserver", "flake8", "types-mock", "types-requests", "mypy"] +tests = ["coverage (>=6.0.0)", "flake8", "mypy", "pytest (>=7.0.0)", "pytest-asyncio", "pytest-cov", "pytest-localserver", "types-mock", "types-requests"] [[package]] name = "six" @@ -304,6 +581,10 @@ description = "Python 2 and 3 compatibility utilities" category = "dev" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" +files = [ + {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, + {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, +] [[package]] name = "toml" @@ -312,6 +593,10 @@ description = "Python Library for Tom's Obvious, Minimal Language" category = "dev" optional = false python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" +files = [ + {file = "toml-0.10.2-py2.py3-none-any.whl", hash = "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b"}, + {file = "toml-0.10.2.tar.gz", hash = "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"}, +] [[package]] name = "tomli" @@ -320,6 +605,10 @@ description = "A lil' TOML parser" category = "dev" optional = false python-versions = ">=3.7" +files = [ + {file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"}, + {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"}, +] [[package]] name = "typing-extensions" @@ -328,6 +617,10 @@ description = "Backported and Experimental Type Hints for Python 3.7+" category = "main" optional = false python-versions = ">=3.7" +files = [ + {file = "typing_extensions-4.5.0-py3-none-any.whl", hash = "sha256:fb33085c39dd998ac16d1431ebc293a8b3eedd00fd4a32de0ff79002c19511b4"}, + {file = "typing_extensions-4.5.0.tar.gz", hash = "sha256:5cb5f4a79139d699607b3ef622a1dedafa84e115ab0024e0d9c044a9479ca7cb"}, +] [[package]] name = "unidecode" @@ -336,56 +629,30 @@ description = "ASCII transliterations of Unicode text" category = "main" optional = false python-versions = ">=3.5" +files = [ + {file = "Unidecode-1.3.6-py3-none-any.whl", hash = "sha256:547d7c479e4f377b430dd91ac1275d593308dce0fc464fb2ab7d41f82ec653be"}, + {file = "Unidecode-1.3.6.tar.gz", hash = "sha256:fed09cf0be8cf415b391642c2a5addfc72194407caee4f98719e40ec2a72b830"}, +] [[package]] name = "urllib3" -version = "1.26.15" +version = "2.0.2" description = "HTTP library with thread-safe connection pooling, file post, and more." category = "main" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*" +python-versions = ">=3.7" +files = [ + {file = "urllib3-2.0.2-py3-none-any.whl", hash = "sha256:d055c2f9d38dc53c808f6fdc8eab7360b6fdbbde02340ed25cfbcd817c62469e"}, + {file = "urllib3-2.0.2.tar.gz", hash = "sha256:61717a1095d7e155cdb737ac7bb2f4324a858a1e2e6466f6d03ff630ca68d3cc"}, +] [package.extras] -brotli = ["brotlicffi (>=0.8.0)", "brotli (>=1.0.9)", "brotlipy (>=0.6.0)"] -secure = ["pyOpenSSL (>=0.14)", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "certifi", "urllib3-secure-extra", "ipaddress"] -socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"] +brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)"] +secure = ["certifi", "cryptography (>=1.9)", "idna (>=2.0.0)", "pyopenssl (>=17.1.0)", "urllib3-secure-extra"] +socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"] +zstd = ["zstandard (>=0.18.0)"] [metadata] -lock-version = "1.1" +lock-version = "2.0" python-versions = "^3.8" -content-hash = "0a56fecadb5e45261565c68937881ba7507093bb087230d32c43f7aa5d7ebe95" - -[metadata.files] -black = [] -certifi = [] -charset-normalizer = [] -click = [] -colorama = [] -coverage = [] -crc = [] -flake8 = [] -freezegun = [] -idna = [] -isort = [] -mccabe = [] -mypy-extensions = [] -pathspec = [] -platformdirs = [] -py-bdd-context = [] -pycodestyle = [] -pycpfcnpj = [] -pydantic = [] -pyflakes = [] -pypng = [] -python-barcode = [] -python-dateutil = [] -python-decouple = [] -qrcode = [] -requests = [] -responses = [] -six = [] -toml = [] -tomli = [] -typing-extensions = [] -unidecode = [] -urllib3 = [] +content-hash = "c0e54c3f36677d20a6110944652d56705eddb3f83e8b1e92f29ea89be889151f" From 30bb5899e16d84164a170c09c5f0e2011c9fc56b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=F0=9F=87=BB=F0=9F=87=A6=20=20Pedro=20Fonseca?= Date: Fri, 5 May 2023 11:33:34 -0300 Subject: [PATCH 082/139] update requests --- poetry.lock | 2 +- pyproject.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/poetry.lock b/poetry.lock index 030ead4e..f5faa7be 100644 --- a/poetry.lock +++ b/poetry.lock @@ -655,4 +655,4 @@ zstd = ["zstandard (>=0.18.0)"] [metadata] lock-version = "2.0" python-versions = "^3.8" -content-hash = "c0e54c3f36677d20a6110944652d56705eddb3f83e8b1e92f29ea89be889151f" +content-hash = "b52ba035f8d331911de8c63b5a2f04c9e1bdb9ee662bd8dab3847cc5a801ec3c" diff --git a/pyproject.toml b/pyproject.toml index ffb994fe..557c7bfc 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -68,7 +68,7 @@ include = [] [tool.poetry.dependencies] python = "^3.8" -requests = "^2.30.0" +requests = "2.30.0" python-decouple = "^3.4" pydantic = "^1.8.2" python-barcode = "^0.13.1" From 07ee192874408003804456754d1f64e39b9a8471 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=F0=9F=87=BB=F0=9F=87=A6=20=20Pedro=20Fonseca?= Date: Fri, 5 May 2023 14:04:05 -0300 Subject: [PATCH 083/139] atualizacao do poetry.lock --- poetry.lock | 354 +++++++--------------------------------------------- 1 file changed, 44 insertions(+), 310 deletions(-) diff --git a/poetry.lock b/poetry.lock index f5faa7be..84cc6ef8 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,5 +1,3 @@ -# This file is automatically @generated by Poetry 1.4.2 and should not be changed by hand. - [[package]] name = "black" version = "22.12.0" @@ -7,20 +5,6 @@ description = "The uncompromising code formatter." category = "dev" optional = false python-versions = ">=3.7" -files = [ - {file = "black-22.12.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9eedd20838bd5d75b80c9f5487dbcb06836a43833a37846cf1d8c1cc01cef59d"}, - {file = "black-22.12.0-cp310-cp310-win_amd64.whl", hash = "sha256:159a46a4947f73387b4d83e87ea006dbb2337eab6c879620a3ba52699b1f4351"}, - {file = "black-22.12.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d30b212bffeb1e252b31dd269dfae69dd17e06d92b87ad26e23890f3efea366f"}, - {file = "black-22.12.0-cp311-cp311-win_amd64.whl", hash = "sha256:7412e75863aa5c5411886804678b7d083c7c28421210180d67dfd8cf1221e1f4"}, - {file = "black-22.12.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c116eed0efb9ff870ded8b62fe9f28dd61ef6e9ddd28d83d7d264a38417dcee2"}, - {file = "black-22.12.0-cp37-cp37m-win_amd64.whl", hash = "sha256:1f58cbe16dfe8c12b7434e50ff889fa479072096d79f0a7f25e4ab8e94cd8350"}, - {file = "black-22.12.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:77d86c9f3db9b1bf6761244bc0b3572a546f5fe37917a044e02f3166d5aafa7d"}, - {file = "black-22.12.0-cp38-cp38-win_amd64.whl", hash = "sha256:82d9fe8fee3401e02e79767016b4907820a7dc28d70d137eb397b92ef3cc5bfc"}, - {file = "black-22.12.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:101c69b23df9b44247bd88e1d7e90154336ac4992502d4197bdac35dd7ee3320"}, - {file = "black-22.12.0-cp39-cp39-win_amd64.whl", hash = "sha256:559c7a1ba9a006226f09e4916060982fd27334ae1998e7a38b3f33a37f7a2148"}, - {file = "black-22.12.0-py3-none-any.whl", hash = "sha256:436cc9167dd28040ad90d3b404aec22cedf24a6e4d7de221bec2730ec0c97bcf"}, - {file = "black-22.12.0.tar.gz", hash = "sha256:229351e5a18ca30f447bf724d007f890f97e13af070bb6ad4c0a441cd7596a2f"}, -] [package.dependencies] click = ">=8.0.0" @@ -43,10 +27,6 @@ description = "Python package for providing Mozilla's CA Bundle." category = "main" optional = false python-versions = ">=3.6" -files = [ - {file = "certifi-2022.12.7-py3-none-any.whl", hash = "sha256:4ad3232f5e926d6718ec31cfc1fcadfde020920e278684144551c91769c7bc18"}, - {file = "certifi-2022.12.7.tar.gz", hash = "sha256:35824b4c3a97115964b408844d64aa14db1cc518f6562e8d7261699d1350a9e3"}, -] [[package]] name = "charset-normalizer" @@ -55,83 +35,6 @@ description = "The Real First Universal Charset Detector. Open, modern and activ category = "main" optional = false python-versions = ">=3.7.0" -files = [ - {file = "charset-normalizer-3.1.0.tar.gz", hash = "sha256:34e0a2f9c370eb95597aae63bf85eb5e96826d81e3dcf88b8886012906f509b5"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:e0ac8959c929593fee38da1c2b64ee9778733cdf03c482c9ff1d508b6b593b2b"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d7fc3fca01da18fbabe4625d64bb612b533533ed10045a2ac3dd194bfa656b60"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:04eefcee095f58eaabe6dc3cc2262f3bcd776d2c67005880894f447b3f2cb9c1"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:20064ead0717cf9a73a6d1e779b23d149b53daf971169289ed2ed43a71e8d3b0"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1435ae15108b1cb6fffbcea2af3d468683b7afed0169ad718451f8db5d1aff6f"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c84132a54c750fda57729d1e2599bb598f5fa0344085dbde5003ba429a4798c0"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:75f2568b4189dda1c567339b48cba4ac7384accb9c2a7ed655cd86b04055c795"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:11d3bcb7be35e7b1bba2c23beedac81ee893ac9871d0ba79effc7fc01167db6c"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:891cf9b48776b5c61c700b55a598621fdb7b1e301a550365571e9624f270c203"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:5f008525e02908b20e04707a4f704cd286d94718f48bb33edddc7d7b584dddc1"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:b06f0d3bf045158d2fb8837c5785fe9ff9b8c93358be64461a1089f5da983137"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:49919f8400b5e49e961f320c735388ee686a62327e773fa5b3ce6721f7e785ce"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:22908891a380d50738e1f978667536f6c6b526a2064156203d418f4856d6e86a"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-win32.whl", hash = "sha256:12d1a39aa6b8c6f6248bb54550efcc1c38ce0d8096a146638fd4738e42284448"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:65ed923f84a6844de5fd29726b888e58c62820e0769b76565480e1fdc3d062f8"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:9a3267620866c9d17b959a84dd0bd2d45719b817245e49371ead79ed4f710d19"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6734e606355834f13445b6adc38b53c0fd45f1a56a9ba06c2058f86893ae8017"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f8303414c7b03f794347ad062c0516cee0e15f7a612abd0ce1e25caf6ceb47df"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aaf53a6cebad0eae578f062c7d462155eada9c172bd8c4d250b8c1d8eb7f916a"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3dc5b6a8ecfdc5748a7e429782598e4f17ef378e3e272eeb1340ea57c9109f41"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e1b25e3ad6c909f398df8921780d6a3d120d8c09466720226fc621605b6f92b1"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0ca564606d2caafb0abe6d1b5311c2649e8071eb241b2d64e75a0d0065107e62"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b82fab78e0b1329e183a65260581de4375f619167478dddab510c6c6fb04d9b6"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:bd7163182133c0c7701b25e604cf1611c0d87712e56e88e7ee5d72deab3e76b5"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:11d117e6c63e8f495412d37e7dc2e2fff09c34b2d09dbe2bee3c6229577818be"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:cf6511efa4801b9b38dc5546d7547d5b5c6ef4b081c60b23e4d941d0eba9cbeb"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:abc1185d79f47c0a7aaf7e2412a0eb2c03b724581139193d2d82b3ad8cbb00ac"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:cb7b2ab0188829593b9de646545175547a70d9a6e2b63bf2cd87a0a391599324"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-win32.whl", hash = "sha256:c36bcbc0d5174a80d6cccf43a0ecaca44e81d25be4b7f90f0ed7bcfbb5a00909"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:cca4def576f47a09a943666b8f829606bcb17e2bc2d5911a46c8f8da45f56755"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:0c95f12b74681e9ae127728f7e5409cbbef9cd914d5896ef238cc779b8152373"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fca62a8301b605b954ad2e9c3666f9d97f63872aa4efcae5492baca2056b74ab"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ac0aa6cd53ab9a31d397f8303f92c42f534693528fafbdb997c82bae6e477ad9"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c3af8e0f07399d3176b179f2e2634c3ce9c1301379a6b8c9c9aeecd481da494f"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3a5fc78f9e3f501a1614a98f7c54d3969f3ad9bba8ba3d9b438c3bc5d047dd28"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:628c985afb2c7d27a4800bfb609e03985aaecb42f955049957814e0491d4006d"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:74db0052d985cf37fa111828d0dd230776ac99c740e1a758ad99094be4f1803d"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:1e8fcdd8f672a1c4fc8d0bd3a2b576b152d2a349782d1eb0f6b8e52e9954731d"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:04afa6387e2b282cf78ff3dbce20f0cc071c12dc8f685bd40960cc68644cfea6"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:dd5653e67b149503c68c4018bf07e42eeed6b4e956b24c00ccdf93ac79cdff84"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:d2686f91611f9e17f4548dbf050e75b079bbc2a82be565832bc8ea9047b61c8c"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-win32.whl", hash = "sha256:4155b51ae05ed47199dc5b2a4e62abccb274cee6b01da5b895099b61b1982974"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-win_amd64.whl", hash = "sha256:322102cdf1ab682ecc7d9b1c5eed4ec59657a65e1c146a0da342b78f4112db23"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:e633940f28c1e913615fd624fcdd72fdba807bf53ea6925d6a588e84e1151531"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:3a06f32c9634a8705f4ca9946d667609f52cf130d5548881401f1eb2c39b1e2c"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:7381c66e0561c5757ffe616af869b916c8b4e42b367ab29fedc98481d1e74e14"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3573d376454d956553c356df45bb824262c397c6e26ce43e8203c4c540ee0acb"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e89df2958e5159b811af9ff0f92614dabf4ff617c03a4c1c6ff53bf1c399e0e1"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:78cacd03e79d009d95635e7d6ff12c21eb89b894c354bd2b2ed0b4763373693b"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:de5695a6f1d8340b12a5d6d4484290ee74d61e467c39ff03b39e30df62cf83a0"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1c60b9c202d00052183c9be85e5eaf18a4ada0a47d188a83c8f5c5b23252f649"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:f645caaf0008bacf349875a974220f1f1da349c5dbe7c4ec93048cdc785a3326"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:ea9f9c6034ea2d93d9147818f17c2a0860d41b71c38b9ce4d55f21b6f9165a11"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:80d1543d58bd3d6c271b66abf454d437a438dff01c3e62fdbcd68f2a11310d4b"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:73dc03a6a7e30b7edc5b01b601e53e7fc924b04e1835e8e407c12c037e81adbd"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:6f5c2e7bc8a4bf7c426599765b1bd33217ec84023033672c1e9a8b35eaeaaaf8"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-win32.whl", hash = "sha256:12a2b561af122e3d94cdb97fe6fb2bb2b82cef0cdca131646fdb940a1eda04f0"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-win_amd64.whl", hash = "sha256:3160a0fd9754aab7d47f95a6b63ab355388d890163eb03b2d2b87ab0a30cfa59"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:38e812a197bf8e71a59fe55b757a84c1f946d0ac114acafaafaf21667a7e169e"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6baf0baf0d5d265fa7944feb9f7451cc316bfe30e8df1a61b1bb08577c554f31"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:8f25e17ab3039b05f762b0a55ae0b3632b2e073d9c8fc88e89aca31a6198e88f"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3747443b6a904001473370d7810aa19c3a180ccd52a7157aacc264a5ac79265e"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b116502087ce8a6b7a5f1814568ccbd0e9f6cfd99948aa59b0e241dc57cf739f"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d16fd5252f883eb074ca55cb622bc0bee49b979ae4e8639fff6ca3ff44f9f854"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:21fa558996782fc226b529fdd2ed7866c2c6ec91cee82735c98a197fae39f706"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6f6c7a8a57e9405cad7485f4c9d3172ae486cfef1344b5ddd8e5239582d7355e"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:ac3775e3311661d4adace3697a52ac0bab17edd166087d493b52d4f4f553f9f0"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:10c93628d7497c81686e8e5e557aafa78f230cd9e77dd0c40032ef90c18f2230"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:6f4f4668e1831850ebcc2fd0b1cd11721947b6dc7c00bf1c6bd3c929ae14f2c7"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:0be65ccf618c1e7ac9b849c315cc2e8a8751d9cfdaa43027d4f6624bd587ab7e"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:53d0a3fa5f8af98a1e261de6a3943ca631c526635eb5817a87a59d9a57ebf48f"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-win32.whl", hash = "sha256:a04f86f41a8916fe45ac5024ec477f41f886b3c435da2d4e3d2709b22ab02af1"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:830d2948a5ec37c386d3170c483063798d7879037492540f10a475e3fd6f244b"}, - {file = "charset_normalizer-3.1.0-py3-none-any.whl", hash = "sha256:3d9098b479e78c85080c98e1e35ff40b4a31d8953102bb0fd7d1b6f8a2111a3d"}, -] [[package]] name = "click" @@ -140,10 +43,6 @@ description = "Composable command line interface toolkit" category = "dev" optional = false python-versions = ">=3.7" -files = [ - {file = "click-8.1.3-py3-none-any.whl", hash = "sha256:bb4d8133cb15a609f44e8213d9b391b0809795062913b383c62be0ee95b1db48"}, - {file = "click-8.1.3.tar.gz", hash = "sha256:7682dc8afb30297001674575ea00d1814d808d6a36af415a82bd481d37ba7b8e"}, -] [package.dependencies] colorama = {version = "*", markers = "platform_system == \"Windows\""} @@ -155,10 +54,6 @@ description = "Cross-platform colored terminal text." category = "main" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" -files = [ - {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, - {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, -] [[package]] name = "coverage" @@ -167,60 +62,6 @@ description = "Code coverage measurement for Python" category = "dev" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <4" -files = [ - {file = "coverage-5.5-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:b6d534e4b2ab35c9f93f46229363e17f63c53ad01330df9f2d6bd1187e5eaacf"}, - {file = "coverage-5.5-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:b7895207b4c843c76a25ab8c1e866261bcfe27bfaa20c192de5190121770672b"}, - {file = "coverage-5.5-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:c2723d347ab06e7ddad1a58b2a821218239249a9e4365eaff6649d31180c1669"}, - {file = "coverage-5.5-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:900fbf7759501bc7807fd6638c947d7a831fc9fdf742dc10f02956ff7220fa90"}, - {file = "coverage-5.5-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:004d1880bed2d97151facef49f08e255a20ceb6f9432df75f4eef018fdd5a78c"}, - {file = "coverage-5.5-cp27-cp27m-win32.whl", hash = "sha256:06191eb60f8d8a5bc046f3799f8a07a2d7aefb9504b0209aff0b47298333302a"}, - {file = "coverage-5.5-cp27-cp27m-win_amd64.whl", hash = "sha256:7501140f755b725495941b43347ba8a2777407fc7f250d4f5a7d2a1050ba8e82"}, - {file = "coverage-5.5-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:372da284cfd642d8e08ef606917846fa2ee350f64994bebfbd3afb0040436905"}, - {file = "coverage-5.5-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:8963a499849a1fc54b35b1c9f162f4108017b2e6db2c46c1bed93a72262ed083"}, - {file = "coverage-5.5-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:869a64f53488f40fa5b5b9dcb9e9b2962a66a87dab37790f3fcfb5144b996ef5"}, - {file = "coverage-5.5-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:4a7697d8cb0f27399b0e393c0b90f0f1e40c82023ea4d45d22bce7032a5d7b81"}, - {file = "coverage-5.5-cp310-cp310-macosx_10_14_x86_64.whl", hash = "sha256:8d0a0725ad7c1a0bcd8d1b437e191107d457e2ec1084b9f190630a4fb1af78e6"}, - {file = "coverage-5.5-cp310-cp310-manylinux1_x86_64.whl", hash = "sha256:51cb9476a3987c8967ebab3f0fe144819781fca264f57f89760037a2ea191cb0"}, - {file = "coverage-5.5-cp310-cp310-win_amd64.whl", hash = "sha256:c0891a6a97b09c1f3e073a890514d5012eb256845c451bd48f7968ef939bf4ae"}, - {file = "coverage-5.5-cp35-cp35m-macosx_10_9_x86_64.whl", hash = "sha256:3487286bc29a5aa4b93a072e9592f22254291ce96a9fbc5251f566b6b7343cdb"}, - {file = "coverage-5.5-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:deee1077aae10d8fa88cb02c845cfba9b62c55e1183f52f6ae6a2df6a2187160"}, - {file = "coverage-5.5-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:f11642dddbb0253cc8853254301b51390ba0081750a8ac03f20ea8103f0c56b6"}, - {file = "coverage-5.5-cp35-cp35m-manylinux2010_i686.whl", hash = "sha256:6c90e11318f0d3c436a42409f2749ee1a115cd8b067d7f14c148f1ce5574d701"}, - {file = "coverage-5.5-cp35-cp35m-manylinux2010_x86_64.whl", hash = "sha256:30c77c1dc9f253283e34c27935fded5015f7d1abe83bc7821680ac444eaf7793"}, - {file = "coverage-5.5-cp35-cp35m-win32.whl", hash = "sha256:9a1ef3b66e38ef8618ce5fdc7bea3d9f45f3624e2a66295eea5e57966c85909e"}, - {file = "coverage-5.5-cp35-cp35m-win_amd64.whl", hash = "sha256:972c85d205b51e30e59525694670de6a8a89691186012535f9d7dbaa230e42c3"}, - {file = "coverage-5.5-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:af0e781009aaf59e25c5a678122391cb0f345ac0ec272c7961dc5455e1c40066"}, - {file = "coverage-5.5-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:74d881fc777ebb11c63736622b60cb9e4aee5cace591ce274fb69e582a12a61a"}, - {file = "coverage-5.5-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:92b017ce34b68a7d67bd6d117e6d443a9bf63a2ecf8567bb3d8c6c7bc5014465"}, - {file = "coverage-5.5-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:d636598c8305e1f90b439dbf4f66437de4a5e3c31fdf47ad29542478c8508bbb"}, - {file = "coverage-5.5-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:41179b8a845742d1eb60449bdb2992196e211341818565abded11cfa90efb821"}, - {file = "coverage-5.5-cp36-cp36m-win32.whl", hash = "sha256:040af6c32813fa3eae5305d53f18875bedd079960822ef8ec067a66dd8afcd45"}, - {file = "coverage-5.5-cp36-cp36m-win_amd64.whl", hash = "sha256:5fec2d43a2cc6965edc0bb9e83e1e4b557f76f843a77a2496cbe719583ce8184"}, - {file = "coverage-5.5-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:18ba8bbede96a2c3dde7b868de9dcbd55670690af0988713f0603f037848418a"}, - {file = "coverage-5.5-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:2910f4d36a6a9b4214bb7038d537f015346f413a975d57ca6b43bf23d6563b53"}, - {file = "coverage-5.5-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:f0b278ce10936db1a37e6954e15a3730bea96a0997c26d7fee88e6c396c2086d"}, - {file = "coverage-5.5-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:796c9c3c79747146ebd278dbe1e5c5c05dd6b10cc3bcb8389dfdf844f3ead638"}, - {file = "coverage-5.5-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:53194af30d5bad77fcba80e23a1441c71abfb3e01192034f8246e0d8f99528f3"}, - {file = "coverage-5.5-cp37-cp37m-win32.whl", hash = "sha256:184a47bbe0aa6400ed2d41d8e9ed868b8205046518c52464fde713ea06e3a74a"}, - {file = "coverage-5.5-cp37-cp37m-win_amd64.whl", hash = "sha256:2949cad1c5208b8298d5686d5a85b66aae46d73eec2c3e08c817dd3513e5848a"}, - {file = "coverage-5.5-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:217658ec7187497e3f3ebd901afdca1af062b42cfe3e0dafea4cced3983739f6"}, - {file = "coverage-5.5-cp38-cp38-manylinux1_i686.whl", hash = "sha256:1aa846f56c3d49205c952d8318e76ccc2ae23303351d9270ab220004c580cfe2"}, - {file = "coverage-5.5-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:24d4a7de75446be83244eabbff746d66b9240ae020ced65d060815fac3423759"}, - {file = "coverage-5.5-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:d1f8bf7b90ba55699b3a5e44930e93ff0189aa27186e96071fac7dd0d06a1873"}, - {file = "coverage-5.5-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:970284a88b99673ccb2e4e334cfb38a10aab7cd44f7457564d11898a74b62d0a"}, - {file = "coverage-5.5-cp38-cp38-win32.whl", hash = "sha256:01d84219b5cdbfc8122223b39a954820929497a1cb1422824bb86b07b74594b6"}, - {file = "coverage-5.5-cp38-cp38-win_amd64.whl", hash = "sha256:2e0d881ad471768bf6e6c2bf905d183543f10098e3b3640fc029509530091502"}, - {file = "coverage-5.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:d1f9ce122f83b2305592c11d64f181b87153fc2c2bbd3bb4a3dde8303cfb1a6b"}, - {file = "coverage-5.5-cp39-cp39-manylinux1_i686.whl", hash = "sha256:13c4ee887eca0f4c5a247b75398d4114c37882658300e153113dafb1d76de529"}, - {file = "coverage-5.5-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:52596d3d0e8bdf3af43db3e9ba8dcdaac724ba7b5ca3f6358529d56f7a166f8b"}, - {file = "coverage-5.5-cp39-cp39-manylinux2010_i686.whl", hash = "sha256:2cafbbb3af0733db200c9b5f798d18953b1a304d3f86a938367de1567f4b5bff"}, - {file = "coverage-5.5-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:44d654437b8ddd9eee7d1eaee28b7219bec228520ff809af170488fd2fed3e2b"}, - {file = "coverage-5.5-cp39-cp39-win32.whl", hash = "sha256:d314ed732c25d29775e84a960c3c60808b682c08d86602ec2c3008e1202e3bb6"}, - {file = "coverage-5.5-cp39-cp39-win_amd64.whl", hash = "sha256:13034c4409db851670bc9acd836243aeee299949bd5673e11844befcb0149f03"}, - {file = "coverage-5.5-pp36-none-any.whl", hash = "sha256:f030f8873312a16414c0d8e1a1ddff2d3235655a2174e3648b4fa66b3f2f1079"}, - {file = "coverage-5.5-pp37-none-any.whl", hash = "sha256:2a3859cb82dcbda1cfd3e6f71c27081d18aa251d20a17d87d26d4cd216fb0af4"}, - {file = "coverage-5.5.tar.gz", hash = "sha256:ebe78fe9a0e874362175b02371bdfbee64d8edc42a044253ddf4ee7d3c15212c"}, -] [package.dependencies] toml = {version = "*", optional = true, markers = "extra == \"toml\""} @@ -235,10 +76,6 @@ description = "Library and CLI to calculate and verify all kinds of CRC checksum category = "main" optional = false python-versions = ">=3.7,<4.0" -files = [ - {file = "crc-1.3.0-py3-none-any.whl", hash = "sha256:963bbb9b0aabb511654551fe5d24402294096a731776ca79910a2363318f41cd"}, - {file = "crc-1.3.0.tar.gz", hash = "sha256:0f4b7c2fbf259c5712adbe3e8cf072609cec5ae5ea6de77cc052de9078fce1ea"}, -] [[package]] name = "flake8" @@ -247,10 +84,6 @@ description = "the modular source code checker: pep8 pyflakes and co" category = "dev" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" -files = [ - {file = "flake8-3.9.2-py2.py3-none-any.whl", hash = "sha256:bf8fd333346d844f616e8d47905ef3a3384edae6b4e9beb0c5101e25e3110907"}, - {file = "flake8-3.9.2.tar.gz", hash = "sha256:07528381786f2a6237b061f6e96610a4167b226cb926e2aa2b6b1d78057c576b"}, -] [package.dependencies] mccabe = ">=0.6.0,<0.7.0" @@ -264,10 +97,6 @@ description = "Let your Python tests travel through time" category = "dev" optional = false python-versions = ">=3.5" -files = [ - {file = "freezegun-1.1.0-py2.py3-none-any.whl", hash = "sha256:2ae695f7eb96c62529f03a038461afe3c692db3465e215355e1bb4b0ab408712"}, - {file = "freezegun-1.1.0.tar.gz", hash = "sha256:177f9dd59861d871e27a484c3332f35a6e3f5d14626f2bf91be37891f18927f3"}, -] [package.dependencies] python-dateutil = ">=2.7" @@ -279,10 +108,6 @@ description = "Internationalized Domain Names in Applications (IDNA)" category = "main" optional = false python-versions = ">=3.5" -files = [ - {file = "idna-3.4-py3-none-any.whl", hash = "sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2"}, - {file = "idna-3.4.tar.gz", hash = "sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4"}, -] [[package]] name = "isort" @@ -291,16 +116,12 @@ description = "A Python utility / library to sort Python imports." category = "dev" optional = false python-versions = ">=3.8.0" -files = [ - {file = "isort-5.12.0-py3-none-any.whl", hash = "sha256:f84c2818376e66cf843d497486ea8fed8700b340f308f076c6fb1229dff318b6"}, - {file = "isort-5.12.0.tar.gz", hash = "sha256:8bef7dde241278824a6d83f44a544709b065191b95b6e50894bdc722fcba0504"}, -] [package.extras] colors = ["colorama (>=0.4.3)"] +requirements-deprecated-finder = ["pip-api", "pipreqs"] pipfile-deprecated-finder = ["pip-shims (>=0.5.2)", "pipreqs", "requirementslib"] plugins = ["setuptools"] -requirements-deprecated-finder = ["pip-api", "pipreqs"] [[package]] name = "mccabe" @@ -309,10 +130,6 @@ description = "McCabe checker, plugin for flake8" category = "dev" optional = false python-versions = "*" -files = [ - {file = "mccabe-0.6.1-py2.py3-none-any.whl", hash = "sha256:ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42"}, - {file = "mccabe-0.6.1.tar.gz", hash = "sha256:dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f"}, -] [[package]] name = "mypy-extensions" @@ -321,10 +138,6 @@ description = "Type system extensions for programs checked with the mypy type ch category = "dev" optional = false python-versions = ">=3.5" -files = [ - {file = "mypy_extensions-1.0.0-py3-none-any.whl", hash = "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d"}, - {file = "mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"}, -] [[package]] name = "pathspec" @@ -333,10 +146,6 @@ description = "Utility library for gitignore style pattern matching of file path category = "dev" optional = false python-versions = ">=3.7" -files = [ - {file = "pathspec-0.11.1-py3-none-any.whl", hash = "sha256:d8af70af76652554bd134c22b3e8a1cc46ed7d91edcdd721ef1a0c51a84a5293"}, - {file = "pathspec-0.11.1.tar.gz", hash = "sha256:2798de800fa92780e33acca925945e9a19a133b715067cf165b8866c15a31687"}, -] [[package]] name = "platformdirs" @@ -345,14 +154,10 @@ description = "A small Python package for determining appropriate platform-speci category = "dev" optional = false python-versions = ">=3.7" -files = [ - {file = "platformdirs-3.5.0-py3-none-any.whl", hash = "sha256:47692bc24c1958e8b0f13dd727307cff1db103fca36399f457da8e05f222fdc4"}, - {file = "platformdirs-3.5.0.tar.gz", hash = "sha256:7954a68d0ba23558d753f73437c55f89027cf8f5108c19844d4b82e5af396335"}, -] [package.extras] -docs = ["furo (>=2023.3.27)", "proselint (>=0.13)", "sphinx (>=6.1.3)", "sphinx-autodoc-typehints (>=1.23,!=1.23.4)"] -test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.3.1)", "pytest-cov (>=4)", "pytest-mock (>=3.10)"] +docs = ["furo (>=2023.3.27)", "proselint (>=0.13)", "sphinx-autodoc-typehints (>=1.23,!=1.23.4)", "sphinx (>=6.1.3)"] +test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest-cov (>=4)", "pytest-mock (>=3.10)", "pytest (>=7.3.1)"] [[package]] name = "py-bdd-context" @@ -361,10 +166,6 @@ description = "Biblioteca com Context Manager para facilitar os testes de Behavi category = "dev" optional = false python-versions = ">=3.8,<4.0" -files = [ - {file = "py-bdd-context-0.0.4.tar.gz", hash = "sha256:cd14204bfb3a98fe64386757b7c6f8a5be8b510e4404b61bfcbc6a8cb9fe5f9e"}, - {file = "py_bdd_context-0.0.4-py3-none-any.whl", hash = "sha256:e7a77b1edf60e40e4f1d6f10f6ea82ae082f989ee60bf05f4bf4bf3520c033e7"}, -] [[package]] name = "pycodestyle" @@ -373,10 +174,6 @@ description = "Python style guide checker" category = "dev" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -files = [ - {file = "pycodestyle-2.7.0-py2.py3-none-any.whl", hash = "sha256:514f76d918fcc0b55c6680472f0a37970994e07bbb80725808c17089be302068"}, - {file = "pycodestyle-2.7.0.tar.gz", hash = "sha256:c389c1d06bf7904078ca03399a4816f974a1d590090fecea0c63ec26ebaf1cef"}, -] [[package]] name = "pycpfcnpj" @@ -385,10 +182,6 @@ description = "Python module for brazilian register numbers for persons (CPF) an category = "main" optional = false python-versions = "*" -files = [ - {file = "pycpfcnpj-1.7.0-py3-none-any.whl", hash = "sha256:28cff52153956062cb931747e56cdf2881fa86635bad64383a398da6836d4719"}, - {file = "pycpfcnpj-1.7.0.tar.gz", hash = "sha256:00ffceb1ed57234b4bcc081523140f604cd7929256d43913dbb413c263bee558"}, -] [[package]] name = "pydantic" @@ -397,44 +190,6 @@ description = "Data validation and settings management using python type hints" category = "main" optional = false python-versions = ">=3.7" -files = [ - {file = "pydantic-1.10.7-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e79e999e539872e903767c417c897e729e015872040e56b96e67968c3b918b2d"}, - {file = "pydantic-1.10.7-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:01aea3a42c13f2602b7ecbbea484a98169fb568ebd9e247593ea05f01b884b2e"}, - {file = "pydantic-1.10.7-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:516f1ed9bc2406a0467dd777afc636c7091d71f214d5e413d64fef45174cfc7a"}, - {file = "pydantic-1.10.7-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ae150a63564929c675d7f2303008d88426a0add46efd76c3fc797cd71cb1b46f"}, - {file = "pydantic-1.10.7-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:ecbbc51391248116c0a055899e6c3e7ffbb11fb5e2a4cd6f2d0b93272118a209"}, - {file = "pydantic-1.10.7-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:f4a2b50e2b03d5776e7f21af73e2070e1b5c0d0df255a827e7c632962f8315af"}, - {file = "pydantic-1.10.7-cp310-cp310-win_amd64.whl", hash = "sha256:a7cd2251439988b413cb0a985c4ed82b6c6aac382dbaff53ae03c4b23a70e80a"}, - {file = "pydantic-1.10.7-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:68792151e174a4aa9e9fc1b4e653e65a354a2fa0fed169f7b3d09902ad2cb6f1"}, - {file = "pydantic-1.10.7-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:dfe2507b8ef209da71b6fb5f4e597b50c5a34b78d7e857c4f8f3115effaef5fe"}, - {file = "pydantic-1.10.7-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:10a86d8c8db68086f1e30a530f7d5f83eb0685e632e411dbbcf2d5c0150e8dcd"}, - {file = "pydantic-1.10.7-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d75ae19d2a3dbb146b6f324031c24f8a3f52ff5d6a9f22f0683694b3afcb16fb"}, - {file = "pydantic-1.10.7-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:464855a7ff7f2cc2cf537ecc421291b9132aa9c79aef44e917ad711b4a93163b"}, - {file = "pydantic-1.10.7-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:193924c563fae6ddcb71d3f06fa153866423ac1b793a47936656e806b64e24ca"}, - {file = "pydantic-1.10.7-cp311-cp311-win_amd64.whl", hash = "sha256:b4a849d10f211389502059c33332e91327bc154acc1845f375a99eca3afa802d"}, - {file = "pydantic-1.10.7-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:cc1dde4e50a5fc1336ee0581c1612215bc64ed6d28d2c7c6f25d2fe3e7c3e918"}, - {file = "pydantic-1.10.7-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e0cfe895a504c060e5d36b287ee696e2fdad02d89e0d895f83037245218a87fe"}, - {file = "pydantic-1.10.7-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:670bb4683ad1e48b0ecb06f0cfe2178dcf74ff27921cdf1606e527d2617a81ee"}, - {file = "pydantic-1.10.7-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:950ce33857841f9a337ce07ddf46bc84e1c4946d2a3bba18f8280297157a3fd1"}, - {file = "pydantic-1.10.7-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:c15582f9055fbc1bfe50266a19771bbbef33dd28c45e78afbe1996fd70966c2a"}, - {file = "pydantic-1.10.7-cp37-cp37m-win_amd64.whl", hash = "sha256:82dffb306dd20bd5268fd6379bc4bfe75242a9c2b79fec58e1041fbbdb1f7914"}, - {file = "pydantic-1.10.7-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:8c7f51861d73e8b9ddcb9916ae7ac39fb52761d9ea0df41128e81e2ba42886cd"}, - {file = "pydantic-1.10.7-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:6434b49c0b03a51021ade5c4daa7d70c98f7a79e95b551201fff682fc1661245"}, - {file = "pydantic-1.10.7-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:64d34ab766fa056df49013bb6e79921a0265204c071984e75a09cbceacbbdd5d"}, - {file = "pydantic-1.10.7-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:701daea9ffe9d26f97b52f1d157e0d4121644f0fcf80b443248434958fd03dc3"}, - {file = "pydantic-1.10.7-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:cf135c46099ff3f919d2150a948ce94b9ce545598ef2c6c7bf55dca98a304b52"}, - {file = "pydantic-1.10.7-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:b0f85904f73161817b80781cc150f8b906d521fa11e3cdabae19a581c3606209"}, - {file = "pydantic-1.10.7-cp38-cp38-win_amd64.whl", hash = "sha256:9f6f0fd68d73257ad6685419478c5aece46432f4bdd8d32c7345f1986496171e"}, - {file = "pydantic-1.10.7-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:c230c0d8a322276d6e7b88c3f7ce885f9ed16e0910354510e0bae84d54991143"}, - {file = "pydantic-1.10.7-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:976cae77ba6a49d80f461fd8bba183ff7ba79f44aa5cfa82f1346b5626542f8e"}, - {file = "pydantic-1.10.7-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7d45fc99d64af9aaf7e308054a0067fdcd87ffe974f2442312372dfa66e1001d"}, - {file = "pydantic-1.10.7-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d2a5ebb48958754d386195fe9e9c5106f11275867051bf017a8059410e9abf1f"}, - {file = "pydantic-1.10.7-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:abfb7d4a7cd5cc4e1d1887c43503a7c5dd608eadf8bc615413fc498d3e4645cd"}, - {file = "pydantic-1.10.7-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:80b1fab4deb08a8292d15e43a6edccdffa5377a36a4597bb545b93e79c5ff0a5"}, - {file = "pydantic-1.10.7-cp39-cp39-win_amd64.whl", hash = "sha256:d71e69699498b020ea198468e2480a2f1e7433e32a3a99760058c6520e2bea7e"}, - {file = "pydantic-1.10.7-py3-none-any.whl", hash = "sha256:0cd181f1d0b1d00e2b705f1bf1ac7799a2d938cce3376b8007df62b29be3c2c6"}, - {file = "pydantic-1.10.7.tar.gz", hash = "sha256:cfc83c0678b6ba51b0532bea66860617c4cd4251ecf76e9846fa5a9f3454e97e"}, -] [package.dependencies] typing-extensions = ">=4.2.0" @@ -450,10 +205,6 @@ description = "passive checker of Python programs" category = "dev" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -files = [ - {file = "pyflakes-2.3.1-py2.py3-none-any.whl", hash = "sha256:7893783d01b8a89811dd72d7dfd4d84ff098e5eed95cfa8905b22bbffe52efc3"}, - {file = "pyflakes-2.3.1.tar.gz", hash = "sha256:f5bc8ecabc05bb9d291eb5203d6810b49040f6ff446a756326104746cc00c1db"}, -] [[package]] name = "pypng" @@ -462,10 +213,6 @@ description = "Pure Python library for saving and loading PNG images" category = "main" optional = false python-versions = "*" -files = [ - {file = "pypng-0.20220715.0-py3-none-any.whl", hash = "sha256:4a43e969b8f5aaafb2a415536c1a8ec7e341cd6a3f957fd5b5f32a4cfeed902c"}, - {file = "pypng-0.20220715.0.tar.gz", hash = "sha256:739c433ba96f078315de54c0db975aee537cbc3e1d0ae4ed9aab0ca1e427e2c1"}, -] [[package]] name = "python-barcode" @@ -474,10 +221,6 @@ description = "Create standard barcodes with Python. No external modules needed. category = "main" optional = false python-versions = "*" -files = [ - {file = "python-barcode-0.13.1.tar.gz", hash = "sha256:fafba4aa24e9d969777be521c294ff18f6c2b36ad63b5fc2f2108d972e23b252"}, - {file = "python_barcode-0.13.1-py3-none-any.whl", hash = "sha256:daa32fb999a843812fbb1c75ff909638811af7c465f0a991e9e41d26d2a44a24"}, -] [package.extras] images = ["pillow"] @@ -489,10 +232,6 @@ description = "Extensions to the standard Python datetime module" category = "dev" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" -files = [ - {file = "python-dateutil-2.8.2.tar.gz", hash = "sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86"}, - {file = "python_dateutil-2.8.2-py2.py3-none-any.whl", hash = "sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9"}, -] [package.dependencies] six = ">=1.5" @@ -504,10 +243,6 @@ description = "Strict separation of settings from code." category = "main" optional = false python-versions = "*" -files = [ - {file = "python-decouple-3.8.tar.gz", hash = "sha256:ba6e2657d4f376ecc46f77a3a615e058d93ba5e465c01bbe57289bfb7cce680f"}, - {file = "python_decouple-3.8-py3-none-any.whl", hash = "sha256:d0d45340815b25f4de59c974b855bb38d03151d81b037d9e3f463b0c9f8cbd66"}, -] [[package]] name = "qrcode" @@ -516,10 +251,6 @@ description = "QR Code image generator" category = "main" optional = false python-versions = ">=3.7" -files = [ - {file = "qrcode-7.4.2-py3-none-any.whl", hash = "sha256:581dca7a029bcb2deef5d01068e39093e80ef00b4a61098a2182eac59d01643a"}, - {file = "qrcode-7.4.2.tar.gz", hash = "sha256:9dd969454827e127dbd93696b20747239e6d540e082937c90f14ac95b30f5845"}, -] [package.dependencies] colorama = {version = "*", markers = "platform_system == \"Windows\""} @@ -527,9 +258,9 @@ pypng = "*" typing-extensions = "*" [package.extras] -all = ["pillow (>=9.1.0)", "pytest", "pytest-cov", "tox", "zest.releaser[recommended]"] -dev = ["pytest", "pytest-cov", "tox"] -maintainer = ["zest.releaser[recommended]"] +all = ["zest.releaser", "tox", "pytest", "pytest-cov", "pillow (>=9.1.0)"] +dev = ["tox", "pytest", "pytest-cov"] +maintainer = ["zest.releaser"] pil = ["pillow (>=9.1.0)"] test = ["coverage", "pytest"] @@ -540,10 +271,6 @@ description = "Python HTTP for Humans." category = "main" optional = false python-versions = ">=3.7" -files = [ - {file = "requests-2.30.0-py3-none-any.whl", hash = "sha256:10e94cc4f3121ee6da529d358cdaeaff2f1c409cd377dbc72b825852f2f7e294"}, - {file = "requests-2.30.0.tar.gz", hash = "sha256:239d7d4458afcb28a692cdd298d87542235f4ca8d36d03a15bfc128a6559a2f4"}, -] [package.dependencies] certifi = ">=2017.4.17" @@ -553,7 +280,7 @@ urllib3 = ">=1.21.1,<3" [package.extras] socks = ["PySocks (>=1.5.6,!=1.5.7)"] -use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] +use_chardet_on_py3 = ["chardet (>=3.0.2,<6)"] [[package]] name = "responses" @@ -562,17 +289,13 @@ description = "A utility library for mocking out the `requests` Python library." category = "dev" optional = false python-versions = ">=3.7" -files = [ - {file = "responses-0.21.0-py3-none-any.whl", hash = "sha256:2dcc863ba63963c0c3d9ee3fa9507cbe36b7d7b0fccb4f0bdfd9e96c539b1487"}, - {file = "responses-0.21.0.tar.gz", hash = "sha256:b82502eb5f09a0289d8e209e7bad71ef3978334f56d09b444253d5ad67bf5253"}, -] [package.dependencies] requests = ">=2.0,<3.0" urllib3 = ">=1.25.10" [package.extras] -tests = ["coverage (>=6.0.0)", "flake8", "mypy", "pytest (>=7.0.0)", "pytest-asyncio", "pytest-cov", "pytest-localserver", "types-mock", "types-requests"] +tests = ["pytest (>=7.0.0)", "coverage (>=6.0.0)", "pytest-cov", "pytest-asyncio", "pytest-localserver", "flake8", "types-mock", "types-requests", "mypy"] [[package]] name = "six" @@ -581,10 +304,6 @@ description = "Python 2 and 3 compatibility utilities" category = "dev" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" -files = [ - {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, - {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, -] [[package]] name = "toml" @@ -593,10 +312,6 @@ description = "Python Library for Tom's Obvious, Minimal Language" category = "dev" optional = false python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" -files = [ - {file = "toml-0.10.2-py2.py3-none-any.whl", hash = "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b"}, - {file = "toml-0.10.2.tar.gz", hash = "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"}, -] [[package]] name = "tomli" @@ -605,10 +320,6 @@ description = "A lil' TOML parser" category = "dev" optional = false python-versions = ">=3.7" -files = [ - {file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"}, - {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"}, -] [[package]] name = "typing-extensions" @@ -617,10 +328,6 @@ description = "Backported and Experimental Type Hints for Python 3.7+" category = "main" optional = false python-versions = ">=3.7" -files = [ - {file = "typing_extensions-4.5.0-py3-none-any.whl", hash = "sha256:fb33085c39dd998ac16d1431ebc293a8b3eedd00fd4a32de0ff79002c19511b4"}, - {file = "typing_extensions-4.5.0.tar.gz", hash = "sha256:5cb5f4a79139d699607b3ef622a1dedafa84e115ab0024e0d9c044a9479ca7cb"}, -] [[package]] name = "unidecode" @@ -629,10 +336,6 @@ description = "ASCII transliterations of Unicode text" category = "main" optional = false python-versions = ">=3.5" -files = [ - {file = "Unidecode-1.3.6-py3-none-any.whl", hash = "sha256:547d7c479e4f377b430dd91ac1275d593308dce0fc464fb2ab7d41f82ec653be"}, - {file = "Unidecode-1.3.6.tar.gz", hash = "sha256:fed09cf0be8cf415b391642c2a5addfc72194407caee4f98719e40ec2a72b830"}, -] [[package]] name = "urllib3" @@ -641,10 +344,6 @@ description = "HTTP library with thread-safe connection pooling, file post, and category = "main" optional = false python-versions = ">=3.7" -files = [ - {file = "urllib3-2.0.2-py3-none-any.whl", hash = "sha256:d055c2f9d38dc53c808f6fdc8eab7360b6fdbbde02340ed25cfbcd817c62469e"}, - {file = "urllib3-2.0.2.tar.gz", hash = "sha256:61717a1095d7e155cdb737ac7bb2f4324a858a1e2e6466f6d03ff630ca68d3cc"}, -] [package.extras] brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)"] @@ -653,6 +352,41 @@ socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"] zstd = ["zstandard (>=0.18.0)"] [metadata] -lock-version = "2.0" +lock-version = "1.1" python-versions = "^3.8" content-hash = "b52ba035f8d331911de8c63b5a2f04c9e1bdb9ee662bd8dab3847cc5a801ec3c" + +[metadata.files] +black = [] +certifi = [] +charset-normalizer = [] +click = [] +colorama = [] +coverage = [] +crc = [] +flake8 = [] +freezegun = [] +idna = [] +isort = [] +mccabe = [] +mypy-extensions = [] +pathspec = [] +platformdirs = [] +py-bdd-context = [] +pycodestyle = [] +pycpfcnpj = [] +pydantic = [] +pyflakes = [] +pypng = [] +python-barcode = [] +python-dateutil = [] +python-decouple = [] +qrcode = [] +requests = [] +responses = [] +six = [] +toml = [] +tomli = [] +typing-extensions = [] +unidecode = [] +urllib3 = [] From 03aac77fc9e10e620b9a9b13074cd4c751737119 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=F0=9F=87=BB=F0=9F=87=A6=20=20Pedro=20Fonseca?= Date: Fri, 5 May 2023 14:12:37 -0300 Subject: [PATCH 084/139] utilizando requests 2.29.0 --- poetry.lock | 17 ++++++++--------- pyproject.toml | 2 +- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/poetry.lock b/poetry.lock index 84cc6ef8..99402aa9 100644 --- a/poetry.lock +++ b/poetry.lock @@ -266,7 +266,7 @@ test = ["coverage", "pytest"] [[package]] name = "requests" -version = "2.30.0" +version = "2.29.0" description = "Python HTTP for Humans." category = "main" optional = false @@ -276,7 +276,7 @@ python-versions = ">=3.7" certifi = ">=2017.4.17" charset-normalizer = ">=2,<4" idna = ">=2.5,<4" -urllib3 = ">=1.21.1,<3" +urllib3 = ">=1.21.1,<1.27" [package.extras] socks = ["PySocks (>=1.5.6,!=1.5.7)"] @@ -339,22 +339,21 @@ python-versions = ">=3.5" [[package]] name = "urllib3" -version = "2.0.2" +version = "1.26.15" description = "HTTP library with thread-safe connection pooling, file post, and more." category = "main" optional = false -python-versions = ">=3.7" +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*" [package.extras] -brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)"] -secure = ["certifi", "cryptography (>=1.9)", "idna (>=2.0.0)", "pyopenssl (>=17.1.0)", "urllib3-secure-extra"] -socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"] -zstd = ["zstandard (>=0.18.0)"] +brotli = ["brotlicffi (>=0.8.0)", "brotli (>=1.0.9)", "brotlipy (>=0.6.0)"] +secure = ["pyOpenSSL (>=0.14)", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "certifi", "urllib3-secure-extra", "ipaddress"] +socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"] [metadata] lock-version = "1.1" python-versions = "^3.8" -content-hash = "b52ba035f8d331911de8c63b5a2f04c9e1bdb9ee662bd8dab3847cc5a801ec3c" +content-hash = "f6c122761af6fa10a1aa373422c7cf0ee870faaafdbb204764ce358d0005d73b" [metadata.files] black = [] diff --git a/pyproject.toml b/pyproject.toml index 557c7bfc..e07792d1 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -68,7 +68,7 @@ include = [] [tool.poetry.dependencies] python = "^3.8" -requests = "2.30.0" +requests = "2.29.0" python-decouple = "^3.4" pydantic = "^1.8.2" python-barcode = "^0.13.1" From 9f15f13031ef2a545679a06e1ecfcd3f88b9a6e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=F0=9F=87=BB=F0=9F=87=A6=20=20Pedro=20Fonseca?= Date: Fri, 5 May 2023 15:21:30 -0300 Subject: [PATCH 085/139] ajuste no actions --- .github/workflows/tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 8f02f062..45eff2b3 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -28,7 +28,7 @@ jobs: - name: Install dependencies run: | - make poetry.config.native + make poetry.config.venv make poetry.install - name: Lint code with black From c1b147218eb4e5d92d43eb6f36315f884fe1f71c Mon Sep 17 00:00:00 2001 From: Pedro Date: Fri, 5 May 2023 16:11:33 -0300 Subject: [PATCH 086/139] Debugando CI, ls -al --- .github/workflows/tests.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 45eff2b3..2fb75a2a 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -28,6 +28,8 @@ jobs: - name: Install dependencies run: | + ls -al ~/.cache/pypoetry + ls -al make poetry.config.venv make poetry.install From 24d71283a96095743f23ffb15c4f921c3fa2077e Mon Sep 17 00:00:00 2001 From: Pedro Date: Fri, 5 May 2023 16:31:56 -0300 Subject: [PATCH 087/139] Debugando CI, ls -al --- .github/workflows/tests.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 2fb75a2a..feee88e3 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -28,10 +28,11 @@ jobs: - name: Install dependencies run: | - ls -al ~/.cache/pypoetry ls -al make poetry.config.venv make poetry.install + ls -al + ls -al ~/.cache/pypoetry - name: Lint code with black run: make fmt.check From d5316a61aaa29f8539437c221392ebaaaf7f2ada Mon Sep 17 00:00:00 2001 From: Pedro Date: Fri, 5 May 2023 16:35:19 -0300 Subject: [PATCH 088/139] Debugando CI, remove .native -> .venv --- .github/workflows/pypi.yml | 2 +- .github/workflows/tests.yml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/pypi.yml b/.github/workflows/pypi.yml index a52b0f9c..3331ded3 100644 --- a/.github/workflows/pypi.yml +++ b/.github/workflows/pypi.yml @@ -23,7 +23,7 @@ jobs: - name: Install dependencies run: | - make poetry.config.native + make poetry.config.venv make poetry.install - name: build package diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index feee88e3..3dd14eed 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -59,7 +59,7 @@ jobs: - name: Install dependencies run: | - make poetry.config.native + make poetry.config.venv make poetry.install - name: Config env @@ -86,7 +86,7 @@ jobs: - name: Install dependencies run: | - make poetry.config.native + make poetry.config.venv make poetry.install - name: Config env From f0f7e3a13525977dec9961dcabe1508bdcbb481c Mon Sep 17 00:00:00 2001 From: Pedro Date: Fri, 5 May 2023 16:39:45 -0300 Subject: [PATCH 089/139] Debugando CI, poetry show --tree --- .github/workflows/pypi.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/pypi.yml b/.github/workflows/pypi.yml index 3331ded3..46fe0bd0 100644 --- a/.github/workflows/pypi.yml +++ b/.github/workflows/pypi.yml @@ -23,8 +23,7 @@ jobs: - name: Install dependencies run: | - make poetry.config.venv - make poetry.install + poetry show --tree - name: build package run: make package.build From 1d2f8f9cf9f3820168fc52ed93bbbd3d9eb8dfe3 Mon Sep 17 00:00:00 2001 From: Pedro Date: Fri, 5 May 2023 16:42:12 -0300 Subject: [PATCH 090/139] Debugando CI, poetry show --tree --- .github/workflows/pypi.yml | 3 ++- .github/workflows/tests.yml | 6 +----- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/.github/workflows/pypi.yml b/.github/workflows/pypi.yml index 46fe0bd0..3331ded3 100644 --- a/.github/workflows/pypi.yml +++ b/.github/workflows/pypi.yml @@ -23,7 +23,8 @@ jobs: - name: Install dependencies run: | - poetry show --tree + make poetry.config.venv + make poetry.install - name: build package run: make package.build diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 3dd14eed..c44427ba 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -28,11 +28,7 @@ jobs: - name: Install dependencies run: | - ls -al - make poetry.config.venv - make poetry.install - ls -al - ls -al ~/.cache/pypoetry + poetry show --tree - name: Lint code with black run: make fmt.check From f9f5beddc36741f270fbd685c8b5ca8addca5e85 Mon Sep 17 00:00:00 2001 From: PedroRegisPOAR Date: Sun, 7 May 2023 14:39:30 -0300 Subject: [PATCH 091/139] Update .github/workflows/pypi.yml Co-authored-by: Rodrigo Castro --- .github/workflows/pypi.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pypi.yml b/.github/workflows/pypi.yml index 3331ded3..a52b0f9c 100644 --- a/.github/workflows/pypi.yml +++ b/.github/workflows/pypi.yml @@ -23,7 +23,7 @@ jobs: - name: Install dependencies run: | - make poetry.config.venv + make poetry.config.native make poetry.install - name: build package From 86da7f550f300000b6bef8d3450b2ebb6d4ea997 Mon Sep 17 00:00:00 2001 From: PedroRegisPOAR Date: Sun, 7 May 2023 14:39:45 -0300 Subject: [PATCH 092/139] Update .github/workflows/tests.yml Co-authored-by: Rodrigo Castro --- .github/workflows/tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index c44427ba..7856c0db 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -55,7 +55,7 @@ jobs: - name: Install dependencies run: | - make poetry.config.venv + make poetry.config.native make poetry.install - name: Config env From 88d6b8e4007086b8c6db8b015ad02d33cfdcd009 Mon Sep 17 00:00:00 2001 From: PedroRegisPOAR Date: Sun, 7 May 2023 14:39:56 -0300 Subject: [PATCH 093/139] Update .github/workflows/tests.yml Co-authored-by: Rodrigo Castro --- .github/workflows/tests.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 7856c0db..0de9c771 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -28,7 +28,8 @@ jobs: - name: Install dependencies run: | - poetry show --tree + make poetry.config.native + make poetry.install - name: Lint code with black run: make fmt.check From a05ddceed96061a7ff23d0e9a22c36230908794c Mon Sep 17 00:00:00 2001 From: PedroRegisPOAR Date: Sun, 7 May 2023 14:40:08 -0300 Subject: [PATCH 094/139] Update .github/workflows/tests.yml Co-authored-by: Rodrigo Castro --- .github/workflows/tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 0de9c771..8f02f062 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -83,7 +83,7 @@ jobs: - name: Install dependencies run: | - make poetry.config.venv + make poetry.config.native make poetry.install - name: Config env From c9295fbf3647472e3e289ddeb9d74833e9c5d77b Mon Sep 17 00:00:00 2001 From: Pedro Date: Sun, 7 May 2023 14:58:47 -0300 Subject: [PATCH 095/139] Fixa requests = "2.30.0" --- poetry.lock | 19 ++++++++++--------- pyproject.toml | 2 +- result-bin | 1 + 3 files changed, 12 insertions(+), 10 deletions(-) create mode 120000 result-bin diff --git a/poetry.lock b/poetry.lock index 99402aa9..25c55395 100644 --- a/poetry.lock +++ b/poetry.lock @@ -22,7 +22,7 @@ uvloop = ["uvloop (>=0.15.2)"] [[package]] name = "certifi" -version = "2022.12.7" +version = "2023.5.7" description = "Python package for providing Mozilla's CA Bundle." category = "main" optional = false @@ -266,7 +266,7 @@ test = ["coverage", "pytest"] [[package]] name = "requests" -version = "2.29.0" +version = "2.30.0" description = "Python HTTP for Humans." category = "main" optional = false @@ -276,7 +276,7 @@ python-versions = ">=3.7" certifi = ">=2017.4.17" charset-normalizer = ">=2,<4" idna = ">=2.5,<4" -urllib3 = ">=1.21.1,<1.27" +urllib3 = ">=1.21.1,<3" [package.extras] socks = ["PySocks (>=1.5.6,!=1.5.7)"] @@ -339,21 +339,22 @@ python-versions = ">=3.5" [[package]] name = "urllib3" -version = "1.26.15" +version = "2.0.2" description = "HTTP library with thread-safe connection pooling, file post, and more." category = "main" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*" +python-versions = ">=3.7" [package.extras] -brotli = ["brotlicffi (>=0.8.0)", "brotli (>=1.0.9)", "brotlipy (>=0.6.0)"] -secure = ["pyOpenSSL (>=0.14)", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "certifi", "urllib3-secure-extra", "ipaddress"] -socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"] +brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)"] +secure = ["certifi", "cryptography (>=1.9)", "idna (>=2.0.0)", "pyopenssl (>=17.1.0)", "urllib3-secure-extra"] +socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"] +zstd = ["zstandard (>=0.18.0)"] [metadata] lock-version = "1.1" python-versions = "^3.8" -content-hash = "f6c122761af6fa10a1aa373422c7cf0ee870faaafdbb204764ce358d0005d73b" +content-hash = "b52ba035f8d331911de8c63b5a2f04c9e1bdb9ee662bd8dab3847cc5a801ec3c" [metadata.files] black = [] diff --git a/pyproject.toml b/pyproject.toml index e07792d1..557c7bfc 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -68,7 +68,7 @@ include = [] [tool.poetry.dependencies] python = "^3.8" -requests = "2.29.0" +requests = "2.30.0" python-decouple = "^3.4" pydantic = "^1.8.2" python-barcode = "^0.13.1" diff --git a/result-bin b/result-bin new file mode 120000 index 00000000..0bc5ba14 --- /dev/null +++ b/result-bin @@ -0,0 +1 @@ +/nix/store/yvis74nnab0s8pcbyyb0k6glbbjm7viz-glibc-2.37-8-bin \ No newline at end of file From a2f84be867b4d1147454e1f68bbb38824e8535cd Mon Sep 17 00:00:00 2001 From: Pedro Date: Sun, 7 May 2023 15:01:27 -0300 Subject: [PATCH 096/139] Fixa urllib3 = "1.26.15" --- poetry.lock | 13 ++++++------- pyproject.toml | 1 + 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/poetry.lock b/poetry.lock index 25c55395..d63d5515 100644 --- a/poetry.lock +++ b/poetry.lock @@ -339,22 +339,21 @@ python-versions = ">=3.5" [[package]] name = "urllib3" -version = "2.0.2" +version = "1.26.15" description = "HTTP library with thread-safe connection pooling, file post, and more." category = "main" optional = false -python-versions = ">=3.7" +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*" [package.extras] -brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)"] -secure = ["certifi", "cryptography (>=1.9)", "idna (>=2.0.0)", "pyopenssl (>=17.1.0)", "urllib3-secure-extra"] -socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"] -zstd = ["zstandard (>=0.18.0)"] +brotli = ["brotlicffi (>=0.8.0)", "brotli (>=1.0.9)", "brotlipy (>=0.6.0)"] +secure = ["pyOpenSSL (>=0.14)", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "certifi", "urllib3-secure-extra", "ipaddress"] +socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"] [metadata] lock-version = "1.1" python-versions = "^3.8" -content-hash = "b52ba035f8d331911de8c63b5a2f04c9e1bdb9ee662bd8dab3847cc5a801ec3c" +content-hash = "6e73be2a5927ab14270805e3aaefa01f9a020abd33e812d2ad116ee26d49f08f" [metadata.files] black = [] diff --git a/pyproject.toml b/pyproject.toml index 557c7bfc..98806312 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -76,6 +76,7 @@ Unidecode = "^1.2.0" qrcode = "^7.3" crc = "^1.0.1" pycpfcnpj = "^1.5.1" +urllib3 = "1.26.15" [tool.poetry.dev-dependencies] flake8 = "^3.9.2" From d6243ca3b810d41271afc341cc5e97112aa9e6c2 Mon Sep 17 00:00:00 2001 From: Pedro Date: Sun, 7 May 2023 15:04:15 -0300 Subject: [PATCH 097/139] Atualiza poetry da Action --- .github/workflows/pypi.yml | 2 +- .github/workflows/tests.yml | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/pypi.yml b/.github/workflows/pypi.yml index a52b0f9c..34944e8d 100644 --- a/.github/workflows/pypi.yml +++ b/.github/workflows/pypi.yml @@ -19,7 +19,7 @@ jobs: - name: Set up Poetry uses: Gr1N/setup-poetry@v7 with: - poetry-version: 1.1.8 + poetry-version: 1.4.2 - name: Install dependencies run: | diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 8f02f062..53d7c032 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -24,7 +24,7 @@ jobs: - name: Set up Poetry uses: Gr1N/setup-poetry@v7 with: - poetry-version: 1.1.8 + poetry-version: 1.4.2 - name: Install dependencies run: | @@ -52,7 +52,7 @@ jobs: - name: Set up Poetry uses: Gr1N/setup-poetry@v7 with: - poetry-version: 1.1.8 + poetry-version: 1.4.2 - name: Install dependencies run: | @@ -79,7 +79,7 @@ jobs: - name: Set up Poetry uses: Gr1N/setup-poetry@v7 with: - poetry-version: 1.1.8 + poetry-version: 1.4.2 - name: Install dependencies run: | From c5f9ed97c8b2402447a65b80394285135d4995b6 Mon Sep 17 00:00:00 2001 From: Pedro Date: Sun, 7 May 2023 15:11:34 -0300 Subject: [PATCH 098/139] fmt --- tests/services/test_documento.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/tests/services/test_documento.py b/tests/services/test_documento.py index 0e43465e..310d4849 100644 --- a/tests/services/test_documento.py +++ b/tests/services/test_documento.py @@ -17,7 +17,7 @@ def test_identifica_tipo_pessoa_fisica(self): with self.when( """ - - utilizar o service de Documento para identificar o tipo de pessoa + - utilizar o service de Documento para identificar o tipo de pessoa """ ): result = DocumentoService().identifica_tipo(cpf) @@ -40,7 +40,7 @@ def test_identifica_tipo_pessoa_fisica_com_pontuacao(self): with self.when( """ - - utilizar o service de Documento para identificar o tipo de pessoa + - utilizar o service de Documento para identificar o tipo de pessoa """ ): result = DocumentoService().identifica_tipo(cpf) @@ -63,14 +63,14 @@ def test_identifica_tipo_pessoa_juridica(self): with self.when( """ - - utilizar o service de Documento para identificar o tipo de pessoa + - utilizar o service de Documento para identificar o tipo de pessoa """ ): result = DocumentoService().identifica_tipo(cnpj) with self.then( """ - - o tipo de pessoa deve ser jurídica + - o tipo de pessoa deve ser jurídica """ ): expected = TipoInscricaoEnum.cnpj @@ -86,14 +86,14 @@ def test_identifica_tipo_pessoa_juridica_com_pontuacao(self): with self.when( """ - - utilizar o service de Documento para identificar o tipo de pessoa + - utilizar o service de Documento para identificar o tipo de pessoa """ ): result = DocumentoService().identifica_tipo(cnpj) with self.then( """ - - o tipo de pessoa deve ser jurídica + - o tipo de pessoa deve ser jurídica """ ): expected = TipoInscricaoEnum.cnpj @@ -102,14 +102,14 @@ def test_identifica_tipo_pessoa_juridica_com_pontuacao(self): def test_identifica_tipo_pessoa_document_invalid(self): with self.given( """ - - um valor que não corresponde a um CPF e nem CPNJ sem pontuação: '554681000001' + - um valor que não corresponde a um CPF e nem CPNJ sem pontuação: '554681000001' # noqa E501 """ ): invalid_document = "554681000001" with self.when( """ - - utilizar o service de Documento para identificar o tipo de pessoa + - utilizar o service de Documento para identificar o tipo de pessoa """ ): with self.assertRaises(ValueError) as ctx: From 304d4abc4ec95d3738f6a5ed4666293082a1ab84 Mon Sep 17 00:00:00 2001 From: Pedro Date: Sun, 7 May 2023 15:20:04 -0300 Subject: [PATCH 099/139] Atualiza poetry usado localmente para 1.4.2 --- flake.lock | 30 ++++++++++++++++++++++++------ 1 file changed, 24 insertions(+), 6 deletions(-) diff --git a/flake.lock b/flake.lock index 447838fc..604dd6de 100644 --- a/flake.lock +++ b/flake.lock @@ -1,12 +1,15 @@ { "nodes": { "flake-utils": { + "inputs": { + "systems": "systems" + }, "locked": { - "lastModified": 1629481132, - "narHash": "sha256-JHgasjPR0/J1J3DRm4KxM4zTyAj4IOJY8vIl75v/kPI=", + "lastModified": 1681202837, + "narHash": "sha256-H+Rh19JDwRtpVPAWp64F+rlEtxUWBAQW28eAi3SRSzg=", "owner": "numtide", "repo": "flake-utils", - "rev": "997f7efcb746a9c140ce1f13c72263189225f482", + "rev": "cfacdce06f30d2b68473a46042957675eebb3401", "type": "github" }, "original": { @@ -17,11 +20,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1629485646, - "narHash": "sha256-m/BhLkERvJv1LWEZAHISSzRPgyikQ0X6XjVRh2sFv10=", + "lastModified": 1683408522, + "narHash": "sha256-9kcPh6Uxo17a3kK3XCHhcWiV1Yu1kYj22RHiymUhMkU=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "8391951d5d1286a97f63c166bfd9312ae5627ef5", + "rev": "897876e4c484f1e8f92009fd11b7d988a121a4e7", "type": "github" }, "original": { @@ -34,6 +37,21 @@ "flake-utils": "flake-utils", "nixpkgs": "nixpkgs" } + }, + "systems": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } } }, "root": "root", From d5c37ce6fd9253a2eec778dda2c89ad307da0fa8 Mon Sep 17 00:00:00 2001 From: Pedro Fonseca <32584628+peidrao@users.noreply.github.com> Date: Mon, 8 May 2023 11:27:43 -0300 Subject: [PATCH 100/139] Update tests/wrapper/test_pagamentos.py Co-authored-by: Breno Viana --- tests/wrapper/test_pagamentos.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/wrapper/test_pagamentos.py b/tests/wrapper/test_pagamentos.py index 4869e68e..696f90b2 100644 --- a/tests/wrapper/test_pagamentos.py +++ b/tests/wrapper/test_pagamentos.py @@ -99,7 +99,7 @@ def test_valida_lote_2_remocao_convenio(self): @MockedRequestsTestCase.no_auth def test_criar_dados_chave_aleatoria_transferencia_pix(self): """ - Teste para verificar e montar os dados da transferência pix usando chave aleatoria # noqa + Teste para verificar e montar os dados da transferência pix usando chave aleatória # noqa """ expected_json = { From b3fd154fb94068b2bf0899c83d7b9c01f48f5dde Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=F0=9F=87=BB=F0=9F=87=A6=20=20Pedro=20Fonseca?= Date: Mon, 8 May 2023 11:55:49 -0300 Subject: [PATCH 101/139] atualizacao de nomes cpf e cnpj --- tests/wrapper/test_pagamentos.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/wrapper/test_pagamentos.py b/tests/wrapper/test_pagamentos.py index 696f90b2..db1844ad 100644 --- a/tests/wrapper/test_pagamentos.py +++ b/tests/wrapper/test_pagamentos.py @@ -248,7 +248,7 @@ def test_criar_dados_com_email_invalido(self): @MockedRequestsTestCase.no_auth def test_criar_dados_cpf_transferencia_pix(self): """ - Teste para verificar e montar os dados da transferência pix usando cpf como chave # noqa + Teste para verificar e montar os dados da transferência pix usando CPF como chave # noqa """ expected_json = { @@ -290,7 +290,7 @@ def test_criar_dados_cpf_transferencia_pix(self): @MockedRequestsTestCase.no_auth def test_criar_dados_cnpj_transferencia_pix(self): """ - Teste para verificar e montar os dados da transferência pix usando cnpj como chave # noqa + Teste para verificar e montar os dados da transferência pix usando CNPJ como chave # noqa """ expected_json = { @@ -827,7 +827,7 @@ def test_criar_transferencia_pix_telefone(self): def test_criar_transferencia_pix_cpf(self): """ - Teste para verificar a URL da requisição e dados de transferência PIX via cpf + Teste para verificar a URL da requisição e dados de transferência PIX via CPF """ request_url = PagamentoLoteBBWrapper()._construct_url( From 5174020799109f5ba3d5d8f0f4bbb0bdb155ee3b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=F0=9F=87=BB=F0=9F=87=A6=20=20Pedro=20Fonseca?= Date: Mon, 8 May 2023 13:31:53 -0300 Subject: [PATCH 102/139] alterando nomeacao de pix para PIX em comentarios --- bb_wrapper/wrapper/pix_cob.py | 12 ++++++------ tests/wrapper/test_pagamentos.py | 12 ++++++------ 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/bb_wrapper/wrapper/pix_cob.py b/bb_wrapper/wrapper/pix_cob.py index f16b7d98..fbea142e 100644 --- a/bb_wrapper/wrapper/pix_cob.py +++ b/bb_wrapper/wrapper/pix_cob.py @@ -15,7 +15,7 @@ class PIXCobBBWrapper(BaseBBWrapper): def listar_pix(self, inicio=None, fim=None, page=0): """ - Método para consultar todos os pix recebidos. + Método para consultar todos os PIX recebidos. Args: inicio: filtro de data inicio. Respeita o formato definido na RFC 3339 @@ -38,10 +38,10 @@ def listar_pix(self, inicio=None, fim=None, page=0): def consultar_pix(self, end_to_end_id): """ - Método para consultar um pix recebido. + Método para consultar um PIX recebido. Args: - end_to_end_id: identificador end_to_end do pix + end_to_end_id: identificador end_to_end do PIX """ url = self._construct_url("pix", end_to_end_id) @@ -51,10 +51,10 @@ def consultar_pix(self, end_to_end_id): def devolver_pix(self, end_to_end_id, valor, txid): """ - Método para devolver uma quantia de um pix recebido. + Método para devolver uma quantia de um PIX recebido. Args: - end_to_end_id: identificador end_to_end do pix + end_to_end_id: identificador end_to_end do PIX valor: valor a ser devolvido (formato float vulgo 10.00 para R$ 10,00) txid: identificador único da devolução """ @@ -69,7 +69,7 @@ def consultar_devolucao_pix(self, end_to_end_id, txid): Método para consultar uma devolução feita. Args: - end_to_end_id: identificador end_to_end do pix + end_to_end_id: identificador end_to_end do PIX txid: identificador único da devolução """ url = self._construct_url("pix", end_to_end_id, "devolucao", txid) diff --git a/tests/wrapper/test_pagamentos.py b/tests/wrapper/test_pagamentos.py index db1844ad..c016c59f 100644 --- a/tests/wrapper/test_pagamentos.py +++ b/tests/wrapper/test_pagamentos.py @@ -99,7 +99,7 @@ def test_valida_lote_2_remocao_convenio(self): @MockedRequestsTestCase.no_auth def test_criar_dados_chave_aleatoria_transferencia_pix(self): """ - Teste para verificar e montar os dados da transferência pix usando chave aleatória # noqa + Teste para verificar e montar os dados da transferência PIX usando chave aleatória # noqa """ expected_json = { @@ -141,7 +141,7 @@ def test_criar_dados_chave_aleatoria_transferencia_pix(self): @MockedRequestsTestCase.no_auth def test_criar_dados_telefone_transferencia_pix(self): """ - Teste para verificar e montar os dados da transferência pix usando telefone como chave # noqa + Teste para verificar e montar os dados da transferência PIX usando telefone como chave # noqa """ expected_json = { @@ -183,7 +183,7 @@ def test_criar_dados_telefone_transferencia_pix(self): @MockedRequestsTestCase.no_auth def test_criar_dados_email_transferencia_pix(self): """ - Teste para verificar e montar os dados da transferência pix usando email como chave # noqa + Teste para verificar e montar os dados da transferência PIX usando email como chave # noqa """ expected_json = { @@ -225,7 +225,7 @@ def test_criar_dados_email_transferencia_pix(self): @MockedRequestsTestCase.no_auth def test_criar_dados_com_email_invalido(self): """ - Teste para verificar e montar os dados da transferência pix usando email como chave # noqa + Teste para verificar e montar os dados da transferência PIX usando email como chave # noqa """ with self.assertRaises(ValueError) as ctx: @@ -248,7 +248,7 @@ def test_criar_dados_com_email_invalido(self): @MockedRequestsTestCase.no_auth def test_criar_dados_cpf_transferencia_pix(self): """ - Teste para verificar e montar os dados da transferência pix usando CPF como chave # noqa + Teste para verificar e montar os dados da transferência PIX usando CPF como chave # noqa """ expected_json = { @@ -290,7 +290,7 @@ def test_criar_dados_cpf_transferencia_pix(self): @MockedRequestsTestCase.no_auth def test_criar_dados_cnpj_transferencia_pix(self): """ - Teste para verificar e montar os dados da transferência pix usando CNPJ como chave # noqa + Teste para verificar e montar os dados da transferência PIX usando CNPJ como chave # noqa """ expected_json = { From 756df5f84cbf57000f89ddc6a6afb260de017c53 Mon Sep 17 00:00:00 2001 From: "Pedro O. A. Regis" Date: Mon, 8 May 2023 14:04:29 -0300 Subject: [PATCH 103/139] Remove result-bin --- result-bin | 1 - 1 file changed, 1 deletion(-) delete mode 120000 result-bin diff --git a/result-bin b/result-bin deleted file mode 120000 index 0bc5ba14..00000000 --- a/result-bin +++ /dev/null @@ -1 +0,0 @@ -/nix/store/yvis74nnab0s8pcbyyb0k6glbbjm7viz-glibc-2.37-8-bin \ No newline at end of file From e1836047087136b32f316a09a2c0b206c52b22e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=F0=9F=87=BB=F0=9F=87=A6=20=20Pedro=20Fonseca?= Date: Mon, 8 May 2023 16:30:56 -0300 Subject: [PATCH 104/139] consultar pix --- bb_wrapper/wrapper/pagamento_lote.py | 9 +++ examples/lotes_pagamento/consultar_pix.py | 15 +++++ .../transferencia_pix_chave_aleatoria.json | 66 +++++++++---------- .../transferencia_pix_chave_aleatoria.py | 5 +- 4 files changed, 59 insertions(+), 36 deletions(-) create mode 100644 examples/lotes_pagamento/consultar_pix.py diff --git a/bb_wrapper/wrapper/pagamento_lote.py b/bb_wrapper/wrapper/pagamento_lote.py index d43ca4f7..1b6b0ff6 100644 --- a/bb_wrapper/wrapper/pagamento_lote.py +++ b/bb_wrapper/wrapper/pagamento_lote.py @@ -558,3 +558,12 @@ def criar_transferencia_pix( response = self._post(url, data) return response + + def consultar_pix(self, _id): + """ + Consulta os dados de um pagamento efetuado na modalidade PIX. + """ + + url = self._construct_url("pix", _id) + response = self._get(url) + return response diff --git a/examples/lotes_pagamento/consultar_pix.py b/examples/lotes_pagamento/consultar_pix.py new file mode 100644 index 00000000..c2b89ed7 --- /dev/null +++ b/examples/lotes_pagamento/consultar_pix.py @@ -0,0 +1,15 @@ +import os + +from examples.utils import dump_response + +from bb_wrapper.wrapper import PagamentoLoteBBWrapper + +c = PagamentoLoteBBWrapper(cert=("./certs/cert.pem", "./certs/key.pem")) + + +_id = "99221347731030000" + + +response = c.consultar_pix(_id) + +dump_response(response, os.path.realpath(__file__)) diff --git a/examples/lotes_pagamento/data/transferencia_pix_chave_aleatoria.json b/examples/lotes_pagamento/data/transferencia_pix_chave_aleatoria.json index 204ab004..31df0dd3 100644 --- a/examples/lotes_pagamento/data/transferencia_pix_chave_aleatoria.json +++ b/examples/lotes_pagamento/data/transferencia_pix_chave_aleatoria.json @@ -1,35 +1,35 @@ { - "numeroRequisicao": 921347, - "estadoRequisicao": 1, - "quantidadeTransferencias": 1, - "valorTransferencias": 15.5, - "quantidadeTransferenciasValidas": 1, - "valorTransferenciasValidas": 15.5, - "listaTransferencias": [ - { - "identificadorPagamento": 90921347731030000, - "data": 19042023, - "valor": 15.5, - "documentoDebito": 0, - "documentoCredito": 0, - "descricaoPagamento": "nova transferencia", - "descricaoPagamentoInstantaneo": "", - "formaIdentificacao": 4, - "dddTelefone": 0, - "telefone": 0, - "email": "", - "cpf": 0, - "cnpj": 0, - "identificacaoAleatoria": "d14d32de-b3b9-4c31-9f89-8df2cec92c50", - "numeroCOMPE": 0, - "numeroISPB": 0, - "tipoConta": 0, - "agencia": 0, - "conta": 0, - "digitoVerificadorConta": "", - "contaPagamento": "", - "indicadorMovimentoAceito": "S", - "erros": [] - } - ] + "numeroRequisicao": 13987, + "estadoRequisicao": 1, + "quantidadeTransferencias": 1, + "valorTransferencias": 15.5, + "quantidadeTransferenciasValidas": 1, + "valorTransferenciasValidas": 15.5, + "listaTransferencias": [ + { + "identificadorPagamento": 90013987731030000, + "data": 8052023, + "valor": 15.5, + "documentoDebito": 0, + "documentoCredito": 0, + "descricaoPagamento": "nova transferencia", + "descricaoPagamentoInstantaneo": "", + "formaIdentificacao": 4, + "dddTelefone": 0, + "telefone": 0, + "email": "", + "cpf": 0, + "cnpj": 0, + "identificacaoAleatoria": "d14d32de-b3b9-4c31-9f89-8df2cec92c50", + "numeroCOMPE": 0, + "numeroISPB": 0, + "tipoConta": 0, + "agencia": 0, + "conta": 0, + "digitoVerificadorConta": "", + "contaPagamento": "", + "indicadorMovimentoAceito": "S", + "erros": [] + } + ] } diff --git a/examples/lotes_pagamento/transferencia_pix_chave_aleatoria.py b/examples/lotes_pagamento/transferencia_pix_chave_aleatoria.py index e93330c2..79559af9 100644 --- a/examples/lotes_pagamento/transferencia_pix_chave_aleatoria.py +++ b/examples/lotes_pagamento/transferencia_pix_chave_aleatoria.py @@ -13,7 +13,7 @@ lote_data = { - "n_requisicao": 921347, + "n_requisicao": 13987, "agencia": 1607, "conta": 99738672, "dv_conta": "X", @@ -23,8 +23,7 @@ "descricao": "nova transferencia", "data_transferencia": today.strftime(bb_fmt), "valor_transferencia": 15.50, - "forma_id": 4, - "chave_aleatoria": "d14d32de-b3b9-4c31-9f89-8df2cec92c50", + "chave": "d14d32de-b3b9-4c31-9f89-8df2cec92c50", } response = c.criar_transferencia_pix(**lote_data, **transferencia_data) From 07b044e4ae78dd095cf39aa5b62f3d7c54cd335f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=F0=9F=87=BB=F0=9F=87=A6=20=20Pedro=20Fonseca?= Date: Mon, 8 May 2023 17:52:25 -0300 Subject: [PATCH 105/139] teste de consulta de pix --- tests/wrapper/test_pagamentos.py | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/tests/wrapper/test_pagamentos.py b/tests/wrapper/test_pagamentos.py index c016c59f..c2913e26 100644 --- a/tests/wrapper/test_pagamentos.py +++ b/tests/wrapper/test_pagamentos.py @@ -906,3 +906,25 @@ def test_criar_transferencia_pix_cnpj(self): self.assertEqual(expected_json, response.json()) self.assertEqual(2, self.total_requests()) self.mock_responses.assert_call_count(request_url, 1) + + def test_consultar_pix(self): + """ + - Teste para consultar um pix de um determinado lote + """ + request_url = PagamentoLoteBBWrapper()._construct_url("pix", "1") + expected_json = {} + self.mock_responses.add( + responses.GET, + request_url, + headers=self._build_authorization_header(1), + json=expected_json, + ) + + response = PagamentoLoteBBWrapper().consultar_pix("1") + + self.assertEqual(request_url, response.url) + self.assertEqual(self._get_headers(), response.headers) + self.assertEqual(expected_json, response.json()) + + self.assertEqual(2, self.total_requests()) + self.mock_responses.assert_call_count(request_url, 1) From a158a0138397db3d59cae3ea5bfad6df957eb5ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=F0=9F=87=BB=F0=9F=87=A6=20=20Pedro=20Fonseca?= Date: Mon, 8 May 2023 18:04:03 -0300 Subject: [PATCH 106/139] fmt --- bb_wrapper/wrapper/pagamento_lote.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bb_wrapper/wrapper/pagamento_lote.py b/bb_wrapper/wrapper/pagamento_lote.py index 1b6b0ff6..64a953b1 100644 --- a/bb_wrapper/wrapper/pagamento_lote.py +++ b/bb_wrapper/wrapper/pagamento_lote.py @@ -561,7 +561,7 @@ def criar_transferencia_pix( def consultar_pix(self, _id): """ - Consulta os dados de um pagamento efetuado na modalidade PIX. + - Consulta os dados de um pagamento efetuado na modalidade PIX. """ url = self._construct_url("pix", _id) From 3c23d45f14c3a2820e7bb6f4902130a73fb1aa99 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=F0=9F=87=BB=F0=9F=87=A6=20=20Pedro=20Fonseca?= Date: Mon, 8 May 2023 18:05:32 -0300 Subject: [PATCH 107/139] fmt --- tests/wrapper/test_pagamentos.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/wrapper/test_pagamentos.py b/tests/wrapper/test_pagamentos.py index c2913e26..12a2603e 100644 --- a/tests/wrapper/test_pagamentos.py +++ b/tests/wrapper/test_pagamentos.py @@ -909,7 +909,7 @@ def test_criar_transferencia_pix_cnpj(self): def test_consultar_pix(self): """ - - Teste para consultar um pix de um determinado lote + - Teste para consultar um pix de um determinado lote """ request_url = PagamentoLoteBBWrapper()._construct_url("pix", "1") expected_json = {} From 0df0a6f76f1f5b671e545329ffe8c533f28a113a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=F0=9F=87=BB=F0=9F=87=A6=20=20Pedro=20Fonseca?= Date: Mon, 8 May 2023 18:41:12 -0300 Subject: [PATCH 108/139] consultar pix exemplo --- examples/lotes_pagamento/consultar_pix.py | 2 +- .../lotes_pagamento/data/consultar_pix.json | 39 +++++++++++ .../data/transferencia_pix_cpf.json | 66 +++++++++---------- .../lotes_pagamento/transferencia_pix_cpf.py | 2 +- 4 files changed, 74 insertions(+), 35 deletions(-) create mode 100644 examples/lotes_pagamento/data/consultar_pix.json diff --git a/examples/lotes_pagamento/consultar_pix.py b/examples/lotes_pagamento/consultar_pix.py index c2b89ed7..841d73e2 100644 --- a/examples/lotes_pagamento/consultar_pix.py +++ b/examples/lotes_pagamento/consultar_pix.py @@ -7,7 +7,7 @@ c = PagamentoLoteBBWrapper(cert=("./certs/cert.pem", "./certs/key.pem")) -_id = "99221347731030000" +_id = "99931219731030001" response = c.consultar_pix(_id) diff --git a/examples/lotes_pagamento/data/consultar_pix.json b/examples/lotes_pagamento/data/consultar_pix.json new file mode 100644 index 00000000..ff36e97d --- /dev/null +++ b/examples/lotes_pagamento/data/consultar_pix.json @@ -0,0 +1,39 @@ +{ + "id": "99931219731030001", + "estadoPagamento": "CONSISTENTE", + "agenciaDebito": 1607, + "contaDebito": 99738672, + "digitoContaDebito": "X", + "numeroCartaoInicio": 0, + "numeroCartaoFim": 0, + "requisicaoPagamento": 9931219, + "arquivoPagamento": "", + "dataPagamento": 8052023, + "valorPagamento": 7999.99, + "numeroDocumentoDebito": 0, + "descricaoPagamento": "transferencia CPF", + "autenticacaoPagamento": "", + "quantidadeOcorrenciaPix": 1, + "listaPix": [ + { + "numeroCOMPE": 0, + "numeroISPB": 0, + "agenciaCredito": 0, + "contaCorrenteCredito": 0, + "digitoVerificadorContaCorrente": "", + "numeroContaPagamentoCredito": "", + "tipoBeneficiario": 1, + "cpfCnpjBeneficiario": 28779295827, + "nomeBeneficiario": "ALAN GUIACHERO BUENO", + "documentoCredito": 0, + "descricaoPagamentoInstantaneo": "0000", + "tipoConta": 0, + "formaIdentificacao": 3, + "dddTelefone": 0, + "telefone": 0, + "email": "", + "identificacaoAleatoria": "", + "textoPix": "" + } + ] +} \ No newline at end of file diff --git a/examples/lotes_pagamento/data/transferencia_pix_cpf.json b/examples/lotes_pagamento/data/transferencia_pix_cpf.json index de26db60..6e6f0b30 100644 --- a/examples/lotes_pagamento/data/transferencia_pix_cpf.json +++ b/examples/lotes_pagamento/data/transferencia_pix_cpf.json @@ -1,35 +1,35 @@ { - "numeroRequisicao": 9221347, - "estadoRequisicao": 1, - "quantidadeTransferencias": 1, - "valorTransferencias": 7999.99, - "quantidadeTransferenciasValidas": 1, - "valorTransferenciasValidas": 7999.99, - "listaTransferencias": [ - { - "identificadorPagamento": 99221347731030000, - "data": 20042023, - "valor": 7999.99, - "documentoDebito": 0, - "documentoCredito": 0, - "descricaoPagamento": "transferencia CPF", - "descricaoPagamentoInstantaneo": "", - "formaIdentificacao": 3, - "dddTelefone": 0, - "telefone": 0, - "email": "", - "cpf": 28779295827, - "cnpj": 0, - "identificacaoAleatoria": "", - "numeroCOMPE": 0, - "numeroISPB": 0, - "tipoConta": 0, - "agencia": 0, - "conta": 0, - "digitoVerificadorConta": "", - "contaPagamento": "", - "indicadorMovimentoAceito": "S", - "erros": [] - } - ] + "numeroRequisicao": 9931219, + "estadoRequisicao": 1, + "quantidadeTransferencias": 1, + "valorTransferencias": 7999.99, + "quantidadeTransferenciasValidas": 1, + "valorTransferenciasValidas": 7999.99, + "listaTransferencias": [ + { + "identificadorPagamento": 99931219731030000, + "data": 8052023, + "valor": 7999.99, + "documentoDebito": 0, + "documentoCredito": 0, + "descricaoPagamento": "transferencia CPF", + "descricaoPagamentoInstantaneo": "", + "formaIdentificacao": 3, + "dddTelefone": 0, + "telefone": 0, + "email": "", + "cpf": 28779295827, + "cnpj": 0, + "identificacaoAleatoria": "", + "numeroCOMPE": 0, + "numeroISPB": 0, + "tipoConta": 0, + "agencia": 0, + "conta": 0, + "digitoVerificadorConta": "", + "contaPagamento": "", + "indicadorMovimentoAceito": "S", + "erros": [] + } + ] } diff --git a/examples/lotes_pagamento/transferencia_pix_cpf.py b/examples/lotes_pagamento/transferencia_pix_cpf.py index 9ed3bb64..4915de71 100644 --- a/examples/lotes_pagamento/transferencia_pix_cpf.py +++ b/examples/lotes_pagamento/transferencia_pix_cpf.py @@ -13,7 +13,7 @@ lote_data = { - "n_requisicao": 9222347, + "n_requisicao": 9931219, "agencia": 1607, "conta": 99738672, "dv_conta": "X", From 28796a491353c190e0d386cbc2c8879c6f61d1f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=F0=9F=90=98=20Pedro=20Fonseca?= Date: Tue, 9 May 2023 11:15:29 -0400 Subject: [PATCH 109/139] refatoracao de testes usando o bdd --- tests/wrapper/test_bb_base.py | 289 ++++++++++++++++++++-------------- 1 file changed, 170 insertions(+), 119 deletions(-) diff --git a/tests/wrapper/test_bb_base.py b/tests/wrapper/test_bb_base.py index 594172c1..c80d87dc 100644 --- a/tests/wrapper/test_bb_base.py +++ b/tests/wrapper/test_bb_base.py @@ -1,5 +1,7 @@ from freezegun import freeze_time from datetime import timedelta +from py_bdd_context import BDDContextTestCase + from tests.utils import IsolatedEnvTestCase, MockedRequestsTestCase from bb_wrapper.wrapper.bb import BaseBBWrapper @@ -8,157 +10,206 @@ from requests import HTTPError -class BaseBBWrapperTestCase(IsolatedEnvTestCase, MockedRequestsTestCase): +class BaseBBWrapperTestCase( + BDDContextTestCase, IsolatedEnvTestCase, MockedRequestsTestCase +): def test_authentication(self): """ - Teste para verificar a validação da autenticação. - - Dado: - - - Quando: - - for chamado BaseBBWrapper()._BaseBBWrapper__authenticate() - Então: - - o resultado de uma autenticação bem sucedida deve ser True - - apenas uma requisição deve ser realizada + - Teste para verificar a validação da autenticação. """ - result = BaseBBWrapper()._BaseBBWrapper__authenticate() + with self.given( + """ + - + """ + ): + pass + + with self.when( + """ + - o service de autenticação do BaseBBWrapper for chamado + """ + ): + result = BaseBBWrapper()._BaseBBWrapper__authenticate() + + with self.then( + """ + - o resultado da autenticação deve ser bem sucedida + - apenas uma requisição deve ser realizada + """ + ): - self.assertTrue(result) - self.assertEqual(1, self.total_requests()) + self.assertTrue(result) + self.assertEqual(1, self.total_requests()) def test_reauthentication(self): """ - Teste para verificar a validação da reautenticação. - - Dado: - - - Quando: - - o token de autenticação expirar - Então: - - uma nova autenticação deve ser realizada - - o wrapper deve ter um novo token de autenticação + - Teste para verificar a validação da reautenticação. """ - bb_wrapper = BaseBBWrapper() - - result = bb_wrapper._BaseBBWrapper__authenticate() - - self.assertTrue(result) - self.assertEqual("token_1", bb_wrapper._access_token) - expire_time = timedelta(seconds=bb_wrapper.TOKEN_EXPIRE_TIME) - time_travel = bb_wrapper._token_time + expire_time - - with freeze_time(time_travel): + with self.given( + """ + - uma autenticação já realizada peloBase BBWrapper + """ + ): + bb_wrapper = BaseBBWrapper() result = bb_wrapper._BaseBBWrapper__authenticate() self.assertTrue(result) - self.assertEqual("token_2", bb_wrapper._access_token) - - self.assertEqual(2, self.total_requests()) + self.assertEqual("token_1", bb_wrapper._access_token) + + with self.when( + """ + - o token de autenticação expirar + """ + ): + expire_time = timedelta(seconds=bb_wrapper.TOKEN_EXPIRE_TIME) + time_travel = bb_wrapper._token_time + expire_time + + with self.then( + """ + - uma nova autenticação deve ser realizada + - o wrapper deve ter um novo token de autenticação + """ + ): + with freeze_time(time_travel): + result = bb_wrapper._BaseBBWrapper__authenticate() + + self.assertTrue(result) + self.assertEqual("token_2", bb_wrapper._access_token) + + self.assertEqual(2, self.total_requests()) def test_authentication_for_multiple_instances(self): """ Teste para verificar se o token de autenticação é utilizado por instâncias diferentes. - - Dado: - - - Quando: - - 2 instâncias BaseBBWrapper realizarem requisições - Então: - - o dado de autenticação deve ser compartilhado - - o tempo de expiração deve ser igual """ - bb_wrapper1 = BaseBBWrapper() - result1 = bb_wrapper1._BaseBBWrapper__authenticate() - self.assertTrue(result1) - self.assertEqual("token_1", bb_wrapper1._access_token) - - bb_wrapper2 = BaseBBWrapper() - result2 = bb_wrapper2._BaseBBWrapper__authenticate() - - self.assertFalse(result2) - self.assertEqual("token_1", bb_wrapper2._access_token) - - self.assertEqual(bb_wrapper1._token_time, bb_wrapper2._token_time) - - self.assertEqual(1, self.total_requests()) + with self.given( + """ + - duas instâncias BaseBBWrapper + """ + ): + bb_wrapper1 = BaseBBWrapper() + bb_wrapper2 = BaseBBWrapper() + + with self.when( + """ + - duas instâncias BaseBBWrapper realizarem requisições + """ + ): + result1 = bb_wrapper1._BaseBBWrapper__authenticate() + + self.assertTrue(result1) + self.assertEqual("token_1", bb_wrapper1._access_token) + + result2 = bb_wrapper2._BaseBBWrapper__authenticate() + + self.assertFalse(result2) + self.assertEqual("token_1", bb_wrapper2._access_token) + + with self.then( + """ + - o dado de autenticação deve ser compartilhado + - o tempo de expiração deve ser igual + """ + ): + self.assertEqual(bb_wrapper1._token_time, bb_wrapper2._token_time) + self.assertEqual(1, self.total_requests()) def test_authentication_multiple_wrappers(self): - """ - Dado: - - um wrapper BaseBBWrapper - - outro wrapper PIXCobBBWrapper - Quando: - - BaseBBWrapper se autenticar - - PIXCobBBWrapper se autenticar - Então: - - cada wrapper deve ter um token diferente - """ - wrapper1 = BaseBBWrapper() - wrapper2 = PIXCobBBWrapper() - - self.assertNotEqual(wrapper1._data, wrapper2._data) - - wrapper1._BaseBBWrapper__authenticate() - wrapper2._BaseBBWrapper__authenticate() - - self.assertNotEqual(wrapper1._access_token, wrapper2._access_token) - - self.assertEqual("token_1", wrapper1._access_token) - self.assertEqual("token_2", wrapper2._access_token) - - self.assertEqual(2, self.total_requests()) + with self.given( + """ + - dois wrapper BaseBBWrapper e PIXCobBBWrapper + """ + ): + wrapper1 = BaseBBWrapper() + wrapper2 = PIXCobBBWrapper() + self.assertNotEqual(wrapper1._data, wrapper2._data) + + with self.when( + """ + - BaseBBWrapper e PIXCobBBWrapper fizem autenticação + """ + ): + wrapper1._BaseBBWrapper__authenticate() + wrapper2._BaseBBWrapper__authenticate() + + with self.then( + """ + - cada wrapper deve ter um token diferente + """ + ): + self.assertNotEqual(wrapper1._access_token, wrapper2._access_token) + + self.assertEqual("token_1", wrapper1._access_token) + self.assertEqual("token_2", wrapper2._access_token) + + self.assertEqual(2, self.total_requests()) def test_authentication_fail_and_reauthentication(self): """ Teste para verificar uma nova tentativa de autenticação após uma falha na autenticação. - - Dado: - - - Quando: - - for chamado BaseBBWrapper()._BaseBBWrapper__authenticate() - Então: - - 2 tentativas de autenticação devem ser realizadas, - uma falha e uma bem sucedida - - o resultado da autenticação deve ser True """ - fail_attempts = 1 - total_requests = fail_attempts + 1 - - self.set_auth(fail_attempts) - - bb_wrapper = BaseBBWrapper() - result = bb_wrapper._BaseBBWrapper__authenticate() - self.assertTrue(result) - self.assertEqual("token_2", bb_wrapper._access_token) + with self.given( + """ + - + """ + ): + fail_attempts = 1 + total_requests = fail_attempts + 1 + + self.set_auth(fail_attempts) + + with self.when( + """ + - o service de autenticação do BaseBBWrapper for chamado + """ + ): + bb_wrapper = BaseBBWrapper() + result = bb_wrapper._BaseBBWrapper__authenticate() - self.assertEqual(total_requests, self.total_requests()) + with self.then( + """ + - 2 tentativas de autenticação devem ser realizadas, uma falha e uma bem sucedida # noqa: E501 + - o resultado da autenticação deve ser True + """ + ): + self.assertTrue(result) + self.assertEqual("token_2", bb_wrapper._access_token) + self.assertEqual(total_requests, self.total_requests()) def test_authentication_fail_and_reauthentication_fail_after_5_attempts(self): """ Teste para verificar falhas em todas as tentativas de autenticação. - - Dado: - - - Quando: - - for chamado BaseBBWrapper()._BaseBBWrapper__authenticate() - Então: - - o máximo de tentativas de autenticação devem ser realizadas - - a autenticação deve terminar em um lançamento de exceção HTTPError """ - self.set_auth(-1) - - bb_wrapper = BaseBBWrapper() - - with self.assertRaises(HTTPError) as ctx: - bb_wrapper._BaseBBWrapper__authenticate() - response = ctx.exception.response - - self.assertEqual(401, response.status_code, msg=response.data) - total_requests = bb_wrapper.AUTH_MAX_RETRY_ATTEMPTS + 1 - self.assertEqual(total_requests, self.total_requests()) + with self.given( + """ + - + """ + ): + self.set_auth(-1) + bb_wrapper = BaseBBWrapper() + + with self.when( + """ + - o service de autenticação do BaseBBWrapper for chamado + """ + ): + with self.assertRaises(HTTPError) as ctx: + bb_wrapper._BaseBBWrapper__authenticate() + response = ctx.exception.response + + with self.then( + """ + - o máximo de tentativas de autenticação devem ser realizadas + - a autenticação deve terminar em um lançamento de exceção HTTPError + """ + ): + self.assertEqual(401, response.status_code, msg=response.data) + + total_requests = bb_wrapper.AUTH_MAX_RETRY_ATTEMPTS + 1 + self.assertEqual(total_requests, self.total_requests()) From bc13ca33aec1611dd39bf0c4906d0c92529a9e59 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=F0=9F=87=BB=F0=9F=87=A6=20=20Pedro=20Fonseca?= Date: Wed, 10 May 2023 10:35:57 -0300 Subject: [PATCH 110/139] alteracao do readme, com novos recursos --- README.rst | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/README.rst b/README.rst index 1d78e9ad..b1d24ad2 100644 --- a/README.rst +++ b/README.rst @@ -50,11 +50,11 @@ API's --------------------- - ☑ API de Cobrança (geração de boletos) -- ☑ API PIX (recebimento PIX) {essa API ainda está instável e incompleta no BB} +- ☑ API PIX (recebimento PIX) - ☐ API Arrecadação PIX {sem previsão de implementação} -- ☑ API Lotes de Pagamentos {essa API ainda está instável e incompleta no BB} +- ☑ API Lotes de Pagamentos - - ☐ Transferência PIX + - ☑ Transferência PIX - ☑ Transferência Bancária - ☐ Pagamento GPS - ☐ Pagamento GRU @@ -70,6 +70,7 @@ Recursos auxiliares - ☑ Geração, validação e conversão de código de barras de tributos - ☑ Geração de QR Code PIX - ☑ Validação e limpeza de CPF/CNPJ +- ☑ Validação do tipo de chave PIX Exemplos disponíveis ===================== From 9a30c81918884b4b6747b19ffd941c30528b0536 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=F0=9F=90=98=20Pedro=20Fonseca?= Date: Wed, 10 May 2023 12:51:01 -0400 Subject: [PATCH 111/139] ajustando comentarios nos testes do BaseBBWrapper --- tests/wrapper/test_bb_base.py | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/tests/wrapper/test_bb_base.py b/tests/wrapper/test_bb_base.py index c80d87dc..3006d663 100644 --- a/tests/wrapper/test_bb_base.py +++ b/tests/wrapper/test_bb_base.py @@ -19,17 +19,17 @@ def test_authentication(self): """ with self.given( """ - - + - uma instância do BaseBBWrapper """ ): - pass + bb_wrapper = BaseBBWrapper() with self.when( """ - o service de autenticação do BaseBBWrapper for chamado """ ): - result = BaseBBWrapper()._BaseBBWrapper__authenticate() + result = bb_wrapper._BaseBBWrapper__authenticate() with self.then( """ @@ -81,8 +81,7 @@ def test_reauthentication(self): def test_authentication_for_multiple_instances(self): """ - Teste para verificar se o token de autenticação é utilizado - por instâncias diferentes. + - Teste para verificar se o token de autenticação é utilizado por instâncias diferentes. # noqa: E501 """ with self.given( @@ -149,15 +148,15 @@ def test_authentication_multiple_wrappers(self): def test_authentication_fail_and_reauthentication(self): """ - Teste para verificar uma nova tentativa de autenticação - após uma falha na autenticação. + - Teste para verificar uma nova tentativa de autenticação após uma falha na autenticação. # noqa: E501 """ with self.given( """ - - + - uma instância do BaseBBWrapper """ ): + bb_wrapper = BaseBBWrapper() fail_attempts = 1 total_requests = fail_attempts + 1 @@ -168,7 +167,6 @@ def test_authentication_fail_and_reauthentication(self): - o service de autenticação do BaseBBWrapper for chamado """ ): - bb_wrapper = BaseBBWrapper() result = bb_wrapper._BaseBBWrapper__authenticate() with self.then( @@ -183,12 +181,12 @@ def test_authentication_fail_and_reauthentication(self): def test_authentication_fail_and_reauthentication_fail_after_5_attempts(self): """ - Teste para verificar falhas em todas as tentativas de autenticação. + - Teste para verificar falhas em todas as tentativas de autenticação. """ with self.given( """ - - + - uma instância do BaseBBWrapper """ ): self.set_auth(-1) From e3c5b70ec56203d91b4b755180d3724c4540296b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=F0=9F=90=98=20Pedro=20Fonseca?= Date: Wed, 10 May 2023 15:40:33 -0400 Subject: [PATCH 112/139] adicionando campo de documento para enviar cpf/cnpj --- bb_wrapper/models/pagamentos.py | 20 ++++++++++++++------ bb_wrapper/wrapper/pagamento_lote.py | 7 ++++++- tests/wrapper/test_pagamentos.py | 12 +++++++++--- 3 files changed, 29 insertions(+), 10 deletions(-) diff --git a/bb_wrapper/models/pagamentos.py b/bb_wrapper/models/pagamentos.py index c1bbcbb7..95c7c016 100644 --- a/bb_wrapper/models/pagamentos.py +++ b/bb_wrapper/models/pagamentos.py @@ -63,6 +63,7 @@ class TransferenciaPIX(BaseModel): cpf: Optional[str] cnpj: Optional[str] identificacaoAleatoria: Optional[str] + documento: Optional[str] # noinspection PyMethodParameters @root_validator @@ -86,16 +87,23 @@ def _set_data(cls, values): values["email"] = key elif key_type == TipoChavePIX.uuid: values["identificacaoAleatoria"] = key - elif key_type == TipoChavePIX.documento: - key_value = cpfcnpj.clear_punctuation(key) - if len(key_value) == 11: - values["cpf"] = key_value - else: - values["cnpj"] = key_value + + documento = values.pop("documento") + if key_type == TipoChavePIX.documento: + cls.verifica_documento(key, values) + else: + cls.verifica_documento(key=documento, values=values) values.pop("chave") return values + def verifica_documento(key, values): + key_value = cpfcnpj.clear_punctuation(key) + if len(key_value) == 11: + values["cpf"] = key_value + else: + values["cnpj"] = key_value + class TransferenciaTED(BaseModel): numeroCOMPE: int diff --git a/bb_wrapper/wrapper/pagamento_lote.py b/bb_wrapper/wrapper/pagamento_lote.py index 64a953b1..691dd7de 100644 --- a/bb_wrapper/wrapper/pagamento_lote.py +++ b/bb_wrapper/wrapper/pagamento_lote.py @@ -499,6 +499,7 @@ def _criar_dados_transferencia_pix( chave, descricao, tipo_pagamento, + documento, ): lote_data = { "numeroRequisicao": n_requisicao, @@ -507,13 +508,14 @@ def _criar_dados_transferencia_pix( "digitoVerificadorContaCorrente": dv_conta, "tipoPagamento": tipo_pagamento, } - transferencia_data = { + "documento": documento, "data": data_transferencia, "valor": valor_transferencia, "descricaoPagamento": descricao, "chave": chave, } + transferencia_data = TransferenciaPIX(**transferencia_data).dict() return {**lote_data, "listaTransferencias": [transferencia_data]} @@ -528,6 +530,7 @@ def criar_transferencia_pix( chave, descricao="", tipo_pagamento=128, + documento="", ): """ Efetua pagamentos em lote via tranferência PIX @@ -541,6 +544,7 @@ def criar_transferencia_pix( data_transferencia: Data do pagamento. No formato "ddmmyyyy" valor_transferencia: Valor do pagamento chave: Valor corresponde a chave que sera usada para tranferência # noqa: E501 + documento: Valor que corresponde a o CPF/CNPJ descricao: Campo de uso livre pelo cliente """ data = self._criar_dados_transferencia_pix( @@ -553,6 +557,7 @@ def criar_transferencia_pix( chave, descricao, tipo_pagamento, + documento, ) url = self._construct_url("lotes-transferencias-pix") response = self._post(url, data) diff --git a/tests/wrapper/test_pagamentos.py b/tests/wrapper/test_pagamentos.py index 12a2603e..2ae60388 100644 --- a/tests/wrapper/test_pagamentos.py +++ b/tests/wrapper/test_pagamentos.py @@ -112,7 +112,7 @@ def test_criar_dados_chave_aleatoria_transferencia_pix(self): { "email": None, "cnpj": None, - "cpf": None, + "cpf": "11122233300", "dddTelefone": None, "telefone": None, "data": "19042023", @@ -134,6 +134,7 @@ def test_criar_dados_chave_aleatoria_transferencia_pix(self): chave="d14d32de-b3b9-4c31-9f89-8df2cec92c50", descricao="Pagamento", tipo_pagamento=128, + documento="11122233300", ) self.assertEqual(expected_json, response) @@ -154,7 +155,7 @@ def test_criar_dados_telefone_transferencia_pix(self): { "email": None, "cnpj": None, - "cpf": None, + "cpf": "11122233300", "dddTelefone": "11", "telefone": "985732102", "data": "19042023", @@ -176,6 +177,7 @@ def test_criar_dados_telefone_transferencia_pix(self): chave="11985732102", descricao="Pagamento", tipo_pagamento=128, + documento="11122233300", ) self.assertEqual(expected_json, response) @@ -196,7 +198,7 @@ def test_criar_dados_email_transferencia_pix(self): { "email": "teste@imo.com", "cnpj": None, - "cpf": None, + "cpf": "11122233300", "dddTelefone": None, "telefone": None, "data": "19042023", @@ -218,6 +220,7 @@ def test_criar_dados_email_transferencia_pix(self): chave="teste@imo.com", descricao="Pagamento", tipo_pagamento=128, + documento=11122233300, ) self.assertEqual(expected_json, response) @@ -239,6 +242,7 @@ def test_criar_dados_com_email_invalido(self): chave="teste@...", descricao="Pagamento", tipo_pagamento=128, + documento=11122233300, ) self.assertEqual( @@ -283,6 +287,7 @@ def test_criar_dados_cpf_transferencia_pix(self): chave="28779295827", descricao="Pagamento", tipo_pagamento=128, + documento="", ) self.assertEqual(expected_json, response) @@ -325,6 +330,7 @@ def test_criar_dados_cnpj_transferencia_pix(self): chave="95127446000198", descricao="Pagamento", tipo_pagamento=128, + documento="", ) self.assertEqual(expected_json, response) From b2a6a2d8a616c4bdb1937d65ac25b056550a4105 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=F0=9F=90=98=20Pedro=20Fonseca?= Date: Wed, 10 May 2023 16:29:34 -0400 Subject: [PATCH 113/139] adicionando classmethod em verifica_documento --- bb_wrapper/models/pagamentos.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/bb_wrapper/models/pagamentos.py b/bb_wrapper/models/pagamentos.py index 95c7c016..ef2a3b25 100644 --- a/bb_wrapper/models/pagamentos.py +++ b/bb_wrapper/models/pagamentos.py @@ -97,7 +97,8 @@ def _set_data(cls, values): values.pop("chave") return values - def verifica_documento(key, values): + @classmethod + def verifica_documento(cls, key, values): key_value = cpfcnpj.clear_punctuation(key) if len(key_value) == 11: values["cpf"] = key_value From 720d3e6eeec2b4597f0501f1261fd2e40dd98bce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=F0=9F=90=98=20Pedro=20Fonseca?= Date: Thu, 11 May 2023 16:52:57 -0400 Subject: [PATCH 114/139] criacao de pasta certs com nix --- flake.nix | 3 +++ 1 file changed, 3 insertions(+) diff --git a/flake.nix b/flake.nix index d6185802..1599dc05 100644 --- a/flake.nix +++ b/flake.nix @@ -40,6 +40,9 @@ # um .venv desatualizado. test -f .venv/bin/activate || make poetry.install source .venv/bin/activate + + test d certs || mkdir -v certs + # Se não existir cria o .env com valores padrão if ! test -f .env; then make config.env From c38445bee8bde3e2bd4dbe124c8cc4fbe778e898 Mon Sep 17 00:00:00 2001 From: Pedro Fonseca <32584628+peidrao@users.noreply.github.com> Date: Fri, 12 May 2023 09:55:06 -0400 Subject: [PATCH 115/139] Update bb_wrapper/wrapper/pagamento_lote.py Co-authored-by: Rodrigo Castro --- bb_wrapper/wrapper/pagamento_lote.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bb_wrapper/wrapper/pagamento_lote.py b/bb_wrapper/wrapper/pagamento_lote.py index 691dd7de..75e72bf3 100644 --- a/bb_wrapper/wrapper/pagamento_lote.py +++ b/bb_wrapper/wrapper/pagamento_lote.py @@ -530,7 +530,7 @@ def criar_transferencia_pix( chave, descricao="", tipo_pagamento=128, - documento="", + documento=None, ): """ Efetua pagamentos em lote via tranferência PIX From 6691f0c2e80c426b4bb0624c8c59530c80455064 Mon Sep 17 00:00:00 2001 From: Pedro Fonseca <32584628+peidrao@users.noreply.github.com> Date: Fri, 12 May 2023 09:56:05 -0400 Subject: [PATCH 116/139] Update bb_wrapper/models/pagamentos.py Co-authored-by: Rodrigo Castro --- bb_wrapper/models/pagamentos.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/bb_wrapper/models/pagamentos.py b/bb_wrapper/models/pagamentos.py index ef2a3b25..e39abe4c 100644 --- a/bb_wrapper/models/pagamentos.py +++ b/bb_wrapper/models/pagamentos.py @@ -89,10 +89,11 @@ def _set_data(cls, values): values["identificacaoAleatoria"] = key documento = values.pop("documento") - if key_type == TipoChavePIX.documento: - cls.verifica_documento(key, values) - else: - cls.verifica_documento(key=documento, values=values) + if document is not None: + if key_type == TipoChavePIX.documento: + cls.verifica_documento(key, values) + else: + cls.verifica_documento(key=documento, values=values) values.pop("chave") return values From 7af9f636bff87eb3c7d8c9c9b9b567e6bfb57220 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=F0=9F=90=98=20Pedro=20Fonseca?= Date: Fri, 12 May 2023 10:38:50 -0400 Subject: [PATCH 117/139] ajustes na interface do transferencia pix --- bb_wrapper/models/pagamentos.py | 9 ++++----- tests/wrapper/test_pagamentos.py | 4 ++-- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/bb_wrapper/models/pagamentos.py b/bb_wrapper/models/pagamentos.py index e39abe4c..94438cb7 100644 --- a/bb_wrapper/models/pagamentos.py +++ b/bb_wrapper/models/pagamentos.py @@ -87,13 +87,12 @@ def _set_data(cls, values): values["email"] = key elif key_type == TipoChavePIX.uuid: values["identificacaoAleatoria"] = key + elif key_type == TipoChavePIX.documento: + cls.verifica_documento(key, values) documento = values.pop("documento") - if document is not None: - if key_type == TipoChavePIX.documento: - cls.verifica_documento(key, values) - else: - cls.verifica_documento(key=documento, values=values) + if documento is not None: + cls.verifica_documento(documento, values) values.pop("chave") return values diff --git a/tests/wrapper/test_pagamentos.py b/tests/wrapper/test_pagamentos.py index 2ae60388..7d33a2aa 100644 --- a/tests/wrapper/test_pagamentos.py +++ b/tests/wrapper/test_pagamentos.py @@ -287,7 +287,7 @@ def test_criar_dados_cpf_transferencia_pix(self): chave="28779295827", descricao="Pagamento", tipo_pagamento=128, - documento="", + documento=None, ) self.assertEqual(expected_json, response) @@ -330,7 +330,7 @@ def test_criar_dados_cnpj_transferencia_pix(self): chave="95127446000198", descricao="Pagamento", tipo_pagamento=128, - documento="", + documento=None, ) self.assertEqual(expected_json, response) From f48d900c3878787734f975a05bf00779490f801f Mon Sep 17 00:00:00 2001 From: Pedro Fonseca <32584628+peidrao@users.noreply.github.com> Date: Mon, 15 May 2023 07:48:12 -0400 Subject: [PATCH 118/139] Update bb_wrapper/models/pagamentos.py Co-authored-by: Rodrigo Castro --- bb_wrapper/models/pagamentos.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bb_wrapper/models/pagamentos.py b/bb_wrapper/models/pagamentos.py index 94438cb7..7bb13af3 100644 --- a/bb_wrapper/models/pagamentos.py +++ b/bb_wrapper/models/pagamentos.py @@ -90,7 +90,7 @@ def _set_data(cls, values): elif key_type == TipoChavePIX.documento: cls.verifica_documento(key, values) - documento = values.pop("documento") + documento = values.pop("documento", None) if documento is not None: cls.verifica_documento(documento, values) From eedcbe51d1e1beccee89421750d57efa8127b26b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=F0=9F=90=98=20Pedro=20Fonseca?= Date: Mon, 15 May 2023 08:22:47 -0400 Subject: [PATCH 119/139] ajustes em testes e ajustes na documentacao --- bb_wrapper/wrapper/pagamento_lote.py | 4 ++- tests/wrapper/test_pagamentos.py | 43 ++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+), 1 deletion(-) diff --git a/bb_wrapper/wrapper/pagamento_lote.py b/bb_wrapper/wrapper/pagamento_lote.py index 75e72bf3..faec8708 100644 --- a/bb_wrapper/wrapper/pagamento_lote.py +++ b/bb_wrapper/wrapper/pagamento_lote.py @@ -544,7 +544,9 @@ def criar_transferencia_pix( data_transferencia: Data do pagamento. No formato "ddmmyyyy" valor_transferencia: Valor do pagamento chave: Valor corresponde a chave que sera usada para tranferência # noqa: E501 - documento: Valor que corresponde a o CPF/CNPJ + documento: Valor que corresponde ao CPF/CNPJ + - Opcional e serve para validar que a chave aleatória/email/telefone pertencem ao cpf/cnpj # noqa: E501 + - Deve ser validado e contratado com o gerente BB/suporte da API descricao: Campo de uso livre pelo cliente """ data = self._criar_dados_transferencia_pix( diff --git a/tests/wrapper/test_pagamentos.py b/tests/wrapper/test_pagamentos.py index 7d33a2aa..e2a199c1 100644 --- a/tests/wrapper/test_pagamentos.py +++ b/tests/wrapper/test_pagamentos.py @@ -139,6 +139,49 @@ def test_criar_dados_chave_aleatoria_transferencia_pix(self): self.assertEqual(expected_json, response) + @MockedRequestsTestCase.no_auth + def test_criar_dados_chave_aleatoria_transferencia_pix_sem_documento(self): + """ + Teste para verificar e montar os dados da transferência PIX usando chave aleatória sem a chave de documento # noqa + """ + + expected_json = { + "numeroRequisicao": "123", + "agenciaDebito": "345", + "contaCorrenteDebito": "678", + "digitoVerificadorContaCorrente": "X", + "tipoPagamento": 128, + "listaTransferencias": [ + { + "email": None, + "cnpj": None, + "cpf": None, + "dddTelefone": None, + "telefone": None, + "data": "19042023", + "valor": 11.0, + "descricaoPagamento": "Pagamento", + "formaIdentificacao": 4, + "identificacaoAleatoria": "d14d32de-b3b9-4c31-9f89-8df2cec92c50", + } + ], + } + + response = PagamentoLoteBBWrapper()._criar_dados_transferencia_pix( + n_requisicao="123", + agencia="345", + conta="678", + dv_conta="X", + data_transferencia="19042023", + valor_transferencia=11, + chave="d14d32de-b3b9-4c31-9f89-8df2cec92c50", + descricao="Pagamento", + tipo_pagamento=128, + documento=None, + ) + + self.assertEqual(expected_json, response) + @MockedRequestsTestCase.no_auth def test_criar_dados_telefone_transferencia_pix(self): """ From 9925265b1196d77c1e346439cdbe9bb57d7fef0f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=F0=9F=A5=B6=20Pedro=20Fonseca?= Date: Mon, 29 Jan 2024 18:50:46 -0300 Subject: [PATCH 120/139] =?UTF-8?q?adiciona=20pequenas=20mudan=C3=A7as=20e?= =?UTF-8?q?m=20nomes=20de=20m=C3=A9todos=20e=20classes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bb_wrapper/models/pagamentos.py | 2 +- bb_wrapper/wrapper/pagamento_lote.py | 10 ++++---- .../transferencia_pix_chave_aleatoria.py | 2 +- .../lotes_pagamento/transferencia_pix_cpf.py | 2 +- tests/wrapper/test_pagamentos.py | 24 +++++++++---------- 5 files changed, 20 insertions(+), 20 deletions(-) diff --git a/bb_wrapper/models/pagamentos.py b/bb_wrapper/models/pagamentos.py index 29159d23..c9095116 100644 --- a/bb_wrapper/models/pagamentos.py +++ b/bb_wrapper/models/pagamentos.py @@ -51,7 +51,7 @@ class FinalidadeTED(IntEnum): poupanca = 11 -class TransferenciaPIX(BaseModel): +class TransferenciaChavePIX(BaseModel): data: str valor: float chave: str diff --git a/bb_wrapper/wrapper/pagamento_lote.py b/bb_wrapper/wrapper/pagamento_lote.py index faec8708..813fb969 100644 --- a/bb_wrapper/wrapper/pagamento_lote.py +++ b/bb_wrapper/wrapper/pagamento_lote.py @@ -6,7 +6,7 @@ LoteData, LoteTransferenciaData, LiberarPagamentos, - TransferenciaPIX, + TransferenciaChavePIX, ) from ..services.document import DocumentoService from ..services.barcode import BarcodeService @@ -488,7 +488,7 @@ def consultar_pagamento_tributo(self, _id): # PIX # ################ - def _criar_dados_transferencia_pix( + def _criar_dados_transferencia_chave_pix( self, n_requisicao, agencia, @@ -516,10 +516,10 @@ def _criar_dados_transferencia_pix( "chave": chave, } - transferencia_data = TransferenciaPIX(**transferencia_data).dict() + transferencia_data = TransferenciaChavePIX(**transferencia_data).dict() return {**lote_data, "listaTransferencias": [transferencia_data]} - def criar_transferencia_pix( + def criar_transferencia_por_chave_pix( self, n_requisicao, agencia, @@ -549,7 +549,7 @@ def criar_transferencia_pix( - Deve ser validado e contratado com o gerente BB/suporte da API descricao: Campo de uso livre pelo cliente """ - data = self._criar_dados_transferencia_pix( + data = self._criar_dados_transferencia_chave_pix( n_requisicao, agencia, conta, diff --git a/examples/lotes_pagamento/transferencia_pix_chave_aleatoria.py b/examples/lotes_pagamento/transferencia_pix_chave_aleatoria.py index 79559af9..9411ec84 100644 --- a/examples/lotes_pagamento/transferencia_pix_chave_aleatoria.py +++ b/examples/lotes_pagamento/transferencia_pix_chave_aleatoria.py @@ -26,5 +26,5 @@ "chave": "d14d32de-b3b9-4c31-9f89-8df2cec92c50", } -response = c.criar_transferencia_pix(**lote_data, **transferencia_data) +response = c.criar_transferencia_por_chave_pix(**lote_data, **transferencia_data) dump_response(response, os.path.realpath(__file__)) diff --git a/examples/lotes_pagamento/transferencia_pix_cpf.py b/examples/lotes_pagamento/transferencia_pix_cpf.py index 4915de71..f21311ab 100644 --- a/examples/lotes_pagamento/transferencia_pix_cpf.py +++ b/examples/lotes_pagamento/transferencia_pix_cpf.py @@ -26,5 +26,5 @@ "chave": "28779295827", } -response = c.criar_transferencia_pix(**lote_data, **transferencia_data) +response = c.criar_transferencia_por_chave_pix(**lote_data, **transferencia_data) dump_response(response, os.path.realpath(__file__)) diff --git a/tests/wrapper/test_pagamentos.py b/tests/wrapper/test_pagamentos.py index e2a199c1..6a892514 100644 --- a/tests/wrapper/test_pagamentos.py +++ b/tests/wrapper/test_pagamentos.py @@ -124,7 +124,7 @@ def test_criar_dados_chave_aleatoria_transferencia_pix(self): ], } - response = PagamentoLoteBBWrapper()._criar_dados_transferencia_pix( + response = PagamentoLoteBBWrapper()._criar_dados_transferencia_chave_pix( n_requisicao="123", agencia="345", conta="678", @@ -167,7 +167,7 @@ def test_criar_dados_chave_aleatoria_transferencia_pix_sem_documento(self): ], } - response = PagamentoLoteBBWrapper()._criar_dados_transferencia_pix( + response = PagamentoLoteBBWrapper()._criar_dados_transferencia_chave_pix( n_requisicao="123", agencia="345", conta="678", @@ -210,7 +210,7 @@ def test_criar_dados_telefone_transferencia_pix(self): ], } - response = PagamentoLoteBBWrapper()._criar_dados_transferencia_pix( + response = PagamentoLoteBBWrapper()._criar_dados_transferencia_chave_pix( n_requisicao="123", agencia="345", conta="678", @@ -253,7 +253,7 @@ def test_criar_dados_email_transferencia_pix(self): ], } - response = PagamentoLoteBBWrapper()._criar_dados_transferencia_pix( + response = PagamentoLoteBBWrapper()._criar_dados_transferencia_chave_pix( n_requisicao="123", agencia="345", conta="678", @@ -275,7 +275,7 @@ def test_criar_dados_com_email_invalido(self): """ with self.assertRaises(ValueError) as ctx: - PagamentoLoteBBWrapper()._criar_dados_transferencia_pix( + PagamentoLoteBBWrapper()._criar_dados_transferencia_chave_pix( n_requisicao="123", agencia="345", conta="678", @@ -320,7 +320,7 @@ def test_criar_dados_cpf_transferencia_pix(self): ], } - response = PagamentoLoteBBWrapper()._criar_dados_transferencia_pix( + response = PagamentoLoteBBWrapper()._criar_dados_transferencia_chave_pix( n_requisicao="123", agencia="345", conta="678", @@ -363,7 +363,7 @@ def test_criar_dados_cnpj_transferencia_pix(self): ], } - response = PagamentoLoteBBWrapper()._criar_dados_transferencia_pix( + response = PagamentoLoteBBWrapper()._criar_dados_transferencia_chave_pix( n_requisicao="123", agencia="345", conta="678", @@ -760,7 +760,7 @@ def test_criar_transferencia_pix_chave_aleatoria(self): json=expected_json, ) - response = PagamentoLoteBBWrapper().criar_transferencia_pix( + response = PagamentoLoteBBWrapper().criar_transferencia_por_chave_pix( "123", "345", "678", @@ -808,7 +808,7 @@ def test_criar_transferencia_pix_email(self): json=expected_json, ) - response = PagamentoLoteBBWrapper().criar_transferencia_pix( + response = PagamentoLoteBBWrapper().criar_transferencia_por_chave_pix( "123", "345", "678", @@ -857,7 +857,7 @@ def test_criar_transferencia_pix_telefone(self): json=expected_json, ) - response = PagamentoLoteBBWrapper().criar_transferencia_pix( + response = PagamentoLoteBBWrapper().criar_transferencia_por_chave_pix( "123", "345", "678", @@ -905,7 +905,7 @@ def test_criar_transferencia_pix_cpf(self): json=expected_json, ) - response = PagamentoLoteBBWrapper().criar_transferencia_pix( + response = PagamentoLoteBBWrapper().criar_transferencia_por_chave_pix( "123", "345", "678", "X", "19042023", 12, "28779295827", "Teste CPF" ) @@ -946,7 +946,7 @@ def test_criar_transferencia_pix_cnpj(self): json=expected_json, ) - response = PagamentoLoteBBWrapper().criar_transferencia_pix( + response = PagamentoLoteBBWrapper().criar_transferencia_por_chave_pix( "123", "345", "678", "X", "19042023", "11", "95127446000198", "Teste CNPJ" ) From 6e4c515867d483fcbc9b38b6f37adcb3025018bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=F0=9F=A5=B6=20Pedro=20Fonseca?= Date: Mon, 29 Jan 2024 18:54:48 -0300 Subject: [PATCH 121/139] remover tipo de chave pix da docsstring TipoChavePIX --- bb_wrapper/models/pagamentos.py | 1 - 1 file changed, 1 deletion(-) diff --git a/bb_wrapper/models/pagamentos.py b/bb_wrapper/models/pagamentos.py index c9095116..53bc22bb 100644 --- a/bb_wrapper/models/pagamentos.py +++ b/bb_wrapper/models/pagamentos.py @@ -30,7 +30,6 @@ class TipoChavePIX(IntEnum): 2: Chave Pix tipo Email 3: Chave Pix tipo CPF/CNPJ 4: Chave Aleatória - 5: Dados Bancários """ telefone = 1 From 9db10798eb0725acf88b2daed6603062b9864270 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=F0=9F=A5=B6=20Pedro=20Fonseca?= Date: Tue, 30 Jan 2024 15:07:13 -0300 Subject: [PATCH 122/139] =?UTF-8?q?adiciona=20verificador=20de=20documento?= =?UTF-8?q?=20no=20servi=C3=A7o=20destinado=20ao=20pix?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bb_wrapper/services/pix.py | 7 +++ ...{test_identify_key_type.py => test_pix.py} | 52 +++++++++++++++++++ 2 files changed, 59 insertions(+) rename tests/services/{test_identify_key_type.py => test_pix.py} (79%) diff --git a/bb_wrapper/services/pix.py b/bb_wrapper/services/pix.py index 2881271b..f0f5bff7 100644 --- a/bb_wrapper/services/pix.py +++ b/bb_wrapper/services/pix.py @@ -64,3 +64,10 @@ def verify_email(self, email: str, raise_exception=True): if raise_exception and not is_email_valid: raise ValueError("Email inválido!") return is_email_valid + + def verify_document(self, key, values): + key_value = cpfcnpj.clear_punctuation(key) + if len(key_value) == 11: + values["cpf"] = key_value + else: + values["cnpj"] = key_value diff --git a/tests/services/test_identify_key_type.py b/tests/services/test_pix.py similarity index 79% rename from tests/services/test_identify_key_type.py rename to tests/services/test_pix.py index c6a901ee..cad00c6a 100644 --- a/tests/services/test_identify_key_type.py +++ b/tests/services/test_pix.py @@ -186,3 +186,55 @@ def test_email_invalid(self): """ ): self.assertEqual(ctx.exception.args[0], "Email inválido!") + + def test_verify_document_cpf(self): + with self.given( + """ + - uma chave '43166663045' + """ + ): + cpf = "43166663045" + + with self.when( + """ + - for utilizado o service de PIX para verificar + qual documento está sendo utilizado + """ + ): + data = {} + PixService().verify_document(cpf, data) + + with self.then( + """ + - o valor esperado deve ser igual ao data + """ + ): + + expected = {"cpf": cpf} + self.assertEqual(data, expected) + + def test_verify_document_cnpj(self): + with self.given( + """ + - uma chave '03794722000153' + """ + ): + cnpj = "03794722000153" + + with self.when( + """ + - for utilizado o service de PIX para verificar + qual documento está sendo utilizado + """ + ): + data = {} + PixService().verify_document(cnpj, data) + + with self.then( + """ + - o valor esperado deve ser igual ao data + """ + ): + + expected = {"cnpj": cnpj} + self.assertEqual(data, expected) From 219ae200466969e03e19d9b28292598cf00451db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=F0=9F=A5=B6=20Pedro=20Fonseca?= Date: Tue, 30 Jan 2024 15:07:37 -0300 Subject: [PATCH 123/139] =?UTF-8?q?adiciona=20modelo=20para=20transferenci?= =?UTF-8?q?a=20pix=20via=20dados=20banc=C3=A1rios?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bb_wrapper/models/pagamentos.py | 44 +++++++++++++++++++++++++-------- 1 file changed, 34 insertions(+), 10 deletions(-) diff --git a/bb_wrapper/models/pagamentos.py b/bb_wrapper/models/pagamentos.py index 53bc22bb..8652dad9 100644 --- a/bb_wrapper/models/pagamentos.py +++ b/bb_wrapper/models/pagamentos.py @@ -2,7 +2,6 @@ from enum import IntEnum, Enum from pydantic import BaseModel, root_validator -from pycpfcnpj import cpfcnpj from .perfis import TipoInscricaoEnum @@ -87,22 +86,47 @@ def _set_data(cls, values): elif key_type == TipoChavePIX.uuid: values["identificacaoAleatoria"] = key elif key_type == TipoChavePIX.documento: - cls.verifica_documento(key, values) + PixService().verify_document(key, values) documento = values.pop("documento", None) if documento is not None: - cls.verifica_documento(documento, values) + PixService().verify_document(documento, values) values.pop("chave") return values - @classmethod - def verifica_documento(cls, key, values): - key_value = cpfcnpj.clear_punctuation(key) - if len(key_value) == 11: - values["cpf"] = key_value - else: - values["cnpj"] = key_value + +class TransferenciaDadosBancariosPIX(BaseModel): + data: str + valor: float + documento: str + tipoConta: str + agencia: str + conta: str + digitoVerificadorConta: str + formaIdentificacao: Optional[str] + descricaoPagamento: Optional[str] + cpf: Optional[str] + cnpj: Optional[str] + contaPagamento: Optional[str] + + # noinspection PyMethodParameters + @root_validator + def _set_data(cls, values): + """ + Esse método realiza o processamento em cima do valor 'chave' + identificando que tipo de chave é e configurando-a corretamente + no objeto. + """ + from ..services.pix import PixService + + values["formaIdentificacao"] = "5" + + documento = values.pop("documento", None) + if documento is not None: + PixService().verify_document(documento, values) + + return values class TransferenciaTED(BaseModel): From e58dd3284ef5fef6441a85d9eb30017caf82109b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=F0=9F=A5=B6=20Pedro=20Fonseca?= Date: Tue, 30 Jan 2024 15:08:20 -0300 Subject: [PATCH 124/139] =?UTF-8?q?adiciona=20servi=C3=A7o=20de=20transfer?= =?UTF-8?q?encia=20pix=20via=20dados=20banc=C3=A1rios=20no=20bb-wrapper?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bb_wrapper/wrapper/pagamento_lote.py | 101 +++++++++++++++++++++++++++ 1 file changed, 101 insertions(+) diff --git a/bb_wrapper/wrapper/pagamento_lote.py b/bb_wrapper/wrapper/pagamento_lote.py index 813fb969..e94d173b 100644 --- a/bb_wrapper/wrapper/pagamento_lote.py +++ b/bb_wrapper/wrapper/pagamento_lote.py @@ -7,6 +7,7 @@ LoteTransferenciaData, LiberarPagamentos, TransferenciaChavePIX, + TransferenciaDadosBancariosPIX, ) from ..services.document import DocumentoService from ..services.barcode import BarcodeService @@ -566,6 +567,106 @@ def criar_transferencia_por_chave_pix( return response + def _criar_dados_transferencia_dados_bancarios_pix( + self, + n_requisicao, + agencia, + conta, + dv_conta, + data_transferencia, + valor_transferencia, + tipo_conta_favorecido, + agencia_favorecido, + conta_favorecido, + digito_verificador_conta, + conta_pagamento, + descricao, + tipo_pagamento, + documento, + ): + lote_data = { + "numeroRequisicao": n_requisicao, + "agenciaDebito": agencia, + "contaCorrenteDebito": conta, + "digitoVerificadorContaCorrente": dv_conta, + "tipoPagamento": tipo_pagamento, + } + transferencia_data = { + "documento": documento, + "data": data_transferencia, + "valor": valor_transferencia, + "descricaoPagamento": descricao, + "tipoConta": tipo_conta_favorecido, + "agencia": agencia_favorecido, + "conta": conta_favorecido, + "digitoVerificadorConta": digito_verificador_conta, + "contaPagamento": conta_pagamento, + } + + transferencia_data = TransferenciaDadosBancariosPIX(**transferencia_data).dict() + return {**lote_data, "listaTransferencias": [transferencia_data]} + + def criar_transferencia_por_dados_bancarios_pix( + self, + n_requisicao, + agencia, + conta, + dv_conta, + data_transferencia, + valor_transferencia, + tipo_conta_favorecido, + agencia_favorecido, + conta_favorecido, + digito_verificador_conta, + conta_pagamento=None, + descricao="", + tipo_pagamento=128, + documento=None, + ): + """ + Efetua pagamentos em lote via tranferência PIX + + Args: + n_requisicao: Nº da requisição a ser utilizado. Deve ser único + agencia: Agência da conta de origem do pagamento + conta: Nº da conta de origem do pagamento + dv_conta: DV da conta de origem do pagamento + tipo_pagamento: Tipo de pagamento a ser feito (126, 127 ou 128) + data_transferencia: Data do pagamento. No formato "ddmmyyyy" + valor_transferencia: Valor do pagamento + tipo_conta_favorecido: Tipo de conta de crédito do favorecido + - 1 Conta Corrente + - 2 Conta Pagamento + - 3 Conta Poupança + agencia_favorecido: Número da agência da conta de crédito do favorecido. + conta_favorecido: Número da conta de crédito do favorecido + digito_verificador_conta: Dígito verificador da agência da conta de crédito do favorecido # noqa: E501 + conta_pagamento: Número da conta pagamento do favorecido + descricao: Campo de uso livre pelo cliente + documento: Valor que corresponde ao CPF/CNPJ + - Obrigatório e serve para validar que os dados bancários pertencem ao cpf/cnpj # noqa: E501 + """ + data = self._criar_dados_transferencia_dados_bancarios_pix( + n_requisicao, + agencia, + conta, + dv_conta, + data_transferencia, + valor_transferencia, + tipo_conta_favorecido, + agencia_favorecido, + conta_favorecido, + digito_verificador_conta, + conta_pagamento, + descricao, + tipo_pagamento, + documento, + ) + url = self._construct_url("lotes-transferencias-pix") + response = self._post(url, data) + + return response + def consultar_pix(self, _id): """ - Consulta os dados de um pagamento efetuado na modalidade PIX. From 012dccc049b9e243a538c2e8ec70f41062645df5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=F0=9F=A5=B6=20Pedro=20Fonseca?= Date: Tue, 30 Jan 2024 15:08:28 -0300 Subject: [PATCH 125/139] =?UTF-8?q?adiciona=20testes=20unit=C3=A1rios?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tests/wrapper/test_pagamentos.py | 60 ++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/tests/wrapper/test_pagamentos.py b/tests/wrapper/test_pagamentos.py index 6a892514..b6888d01 100644 --- a/tests/wrapper/test_pagamentos.py +++ b/tests/wrapper/test_pagamentos.py @@ -956,6 +956,66 @@ def test_criar_transferencia_pix_cnpj(self): self.assertEqual(2, self.total_requests()) self.mock_responses.assert_call_count(request_url, 1) + def test_criar_transferencia_pix_dados_bancarios(self): + """ + Teste para verificar a URL da requisição e + dados de transferência PIX por dados bancarios + """ + + request_url = PagamentoLoteBBWrapper()._construct_url( + "lotes-transferencias-pix" + ) + + expected_json = { + "numeroRequisicao": "123", + "agenciaDebito": "345", + "contaCorrenteDebito": "678", + "digitoVerificadorContaCorrente": "X", + "tipoPagamento": 128, + "listaTransferencias": [ + { + "data": "19042023", + "valor": "50", + "descricaoPagamento": "Uma transferência via dados bancários", + "formaIdentificacao": 5, + "tipoConta": 1, + "agencia": 1234, + "conta": 12345, + "digitoVerificadorConta": "X", + "cpf": "28779295827", + } + ], + } + + self.mock_responses.add( + responses.POST, + request_url, + headers=self._build_authorization_header(1), + json=expected_json, + ) + + response = PagamentoLoteBBWrapper().criar_transferencia_por_dados_bancarios_pix( + n_requisicao="123", + agencia="345", + conta="678", + dv_conta="X", + data_transferencia="19042023", + valor_transferencia=12, + tipo_conta_favorecido=1, + agencia_favorecido=1234, + conta_favorecido=12345, + digito_verificador_conta="X", + conta_pagamento=None, + descricao="Uma transferência via dados bancários", + documento="28779295827", + ) + + self.assertEqual(request_url, response.url) + self.assertEqual(self._get_headers(), response.headers) + self.assertEqual(expected_json, response.json()) + self.assertEqual(2, self.total_requests()) + self.mock_responses.assert_call_count(request_url, 1) + def test_consultar_pix(self): """ - Teste para consultar um pix de um determinado lote From 31cc8ae315373baf9148ec987f000da3488817b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=F0=9F=A5=B6=20Pedro=20Fonseca?= Date: Tue, 30 Jan 2024 15:08:49 -0300 Subject: [PATCH 126/139] =?UTF-8?q?adiciona=20example=20de=20chamada=20de?= =?UTF-8?q?=20requisi=C3=A7=C3=A3o?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../transferencia_pix_dados_bancarios.json | 37 +++++++++++++++++++ .../transferencia_pix_dados_bancarios.py | 36 ++++++++++++++++++ 2 files changed, 73 insertions(+) create mode 100644 examples/lotes_pagamento/data/transferencia_pix_dados_bancarios.json create mode 100644 examples/lotes_pagamento/transferencia_pix_dados_bancarios.py diff --git a/examples/lotes_pagamento/data/transferencia_pix_dados_bancarios.json b/examples/lotes_pagamento/data/transferencia_pix_dados_bancarios.json new file mode 100644 index 00000000..69f7a344 --- /dev/null +++ b/examples/lotes_pagamento/data/transferencia_pix_dados_bancarios.json @@ -0,0 +1,37 @@ +{ + "numeroRequisicao": 11489, + "estadoRequisicao": 3, + "quantidadeTransferencias": 1, + "valorTransferencias": 15.5, + "quantidadeTransferenciasValidas": 0, + "valorTransferenciasValidas": 0, + "listaTransferencias": [ + { + "identificadorPagamento": 90011489731030000, + "data": 30012024, + "valor": 15.5, + "documentoDebito": 0, + "documentoCredito": 0, + "descricaoPagamento": "Uma transfer\u00fdncia via dados banc\u00fdrios", + "descricaoPagamentoInstantaneo": "", + "formaIdentificacao": 5, + "dddTelefone": 0, + "telefone": 0, + "email": "", + "cpf": 28779295827, + "cnpj": 0, + "identificacaoAleatoria": "", + "numeroCOMPE": 0, + "numeroISPB": 0, + "tipoConta": 1, + "agencia": 1234, + "conta": 12345, + "digitoVerificadorConta": "X", + "contaPagamento": "", + "indicadorMovimentoAceito": "N", + "erros": [ + 10 + ] + } + ] +} \ No newline at end of file diff --git a/examples/lotes_pagamento/transferencia_pix_dados_bancarios.py b/examples/lotes_pagamento/transferencia_pix_dados_bancarios.py new file mode 100644 index 00000000..ed901f0e --- /dev/null +++ b/examples/lotes_pagamento/transferencia_pix_dados_bancarios.py @@ -0,0 +1,36 @@ +import os +from datetime import date + +from examples.utils import dump_response + +from bb_wrapper.wrapper import PagamentoLoteBBWrapper + +c = PagamentoLoteBBWrapper(cert=("./certs/cert.pem", "./certs/key.pem")) + + +today = date.today() +bb_fmt = "%d%m%Y" + + +lote_data = { + "n_requisicao": 11489, + "agencia": 1607, + "conta": 99738672, + "dv_conta": "X", +} + +transferencia_data = { + "data_transferencia": today.strftime(bb_fmt), + "valor_transferencia": 15.50, + "descricao": "Uma transferência via dados bancários", + "tipo_conta_favorecido": 1, + "agencia_favorecido": 1234, + "conta_favorecido": 12345, + "digito_verificador_conta": "X", + "documento": "28779295827", +} + +response = c.criar_transferencia_por_dados_bancarios_pix( + **lote_data, **transferencia_data +) +dump_response(response, os.path.realpath(__file__)) From c2ff8f4c4af8cb4c09c6390c07f83a53bd32956e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=F0=9F=A5=B6=20Pedro=20Fonseca?= Date: Tue, 30 Jan 2024 17:09:11 -0300 Subject: [PATCH 127/139] adiciona numero ISPB --- bb_wrapper/models/pagamentos.py | 1 + bb_wrapper/wrapper/pagamento_lote.py | 5 +++++ .../lotes_pagamento/transferencia_pix_dados_bancarios.py | 1 + tests/wrapper/test_pagamentos.py | 2 ++ 4 files changed, 9 insertions(+) diff --git a/bb_wrapper/models/pagamentos.py b/bb_wrapper/models/pagamentos.py index 8652dad9..0f63df3c 100644 --- a/bb_wrapper/models/pagamentos.py +++ b/bb_wrapper/models/pagamentos.py @@ -109,6 +109,7 @@ class TransferenciaDadosBancariosPIX(BaseModel): cpf: Optional[str] cnpj: Optional[str] contaPagamento: Optional[str] + numeroISPB: Optional[str] # noinspection PyMethodParameters @root_validator diff --git a/bb_wrapper/wrapper/pagamento_lote.py b/bb_wrapper/wrapper/pagamento_lote.py index e94d173b..f66d0005 100644 --- a/bb_wrapper/wrapper/pagamento_lote.py +++ b/bb_wrapper/wrapper/pagamento_lote.py @@ -583,6 +583,7 @@ def _criar_dados_transferencia_dados_bancarios_pix( descricao, tipo_pagamento, documento, + numero_ispb, ): lote_data = { "numeroRequisicao": n_requisicao, @@ -601,6 +602,7 @@ def _criar_dados_transferencia_dados_bancarios_pix( "conta": conta_favorecido, "digitoVerificadorConta": digito_verificador_conta, "contaPagamento": conta_pagamento, + "numeroISPB": numero_ispb, } transferencia_data = TransferenciaDadosBancariosPIX(**transferencia_data).dict() @@ -618,6 +620,7 @@ def criar_transferencia_por_dados_bancarios_pix( agencia_favorecido, conta_favorecido, digito_verificador_conta, + numero_ispb, conta_pagamento=None, descricao="", tipo_pagamento=128, @@ -641,6 +644,7 @@ def criar_transferencia_por_dados_bancarios_pix( agencia_favorecido: Número da agência da conta de crédito do favorecido. conta_favorecido: Número da conta de crédito do favorecido digito_verificador_conta: Dígito verificador da agência da conta de crédito do favorecido # noqa: E501 + numero_ispb: Identificador de Sistema de Pagamento Brasileiro conta_pagamento: Número da conta pagamento do favorecido descricao: Campo de uso livre pelo cliente documento: Valor que corresponde ao CPF/CNPJ @@ -661,6 +665,7 @@ def criar_transferencia_por_dados_bancarios_pix( descricao, tipo_pagamento, documento, + numero_ispb, ) url = self._construct_url("lotes-transferencias-pix") response = self._post(url, data) diff --git a/examples/lotes_pagamento/transferencia_pix_dados_bancarios.py b/examples/lotes_pagamento/transferencia_pix_dados_bancarios.py index ed901f0e..a9cfb66f 100644 --- a/examples/lotes_pagamento/transferencia_pix_dados_bancarios.py +++ b/examples/lotes_pagamento/transferencia_pix_dados_bancarios.py @@ -27,6 +27,7 @@ "agencia_favorecido": 1234, "conta_favorecido": 12345, "digito_verificador_conta": "X", + "numeroISPB": "360305", "documento": "28779295827", } diff --git a/tests/wrapper/test_pagamentos.py b/tests/wrapper/test_pagamentos.py index b6888d01..c74c8a3f 100644 --- a/tests/wrapper/test_pagamentos.py +++ b/tests/wrapper/test_pagamentos.py @@ -982,6 +982,7 @@ def test_criar_transferencia_pix_dados_bancarios(self): "agencia": 1234, "conta": 12345, "digitoVerificadorConta": "X", + "numeroISPB": "360305", "cpf": "28779295827", } ], @@ -1006,6 +1007,7 @@ def test_criar_transferencia_pix_dados_bancarios(self): conta_favorecido=12345, digito_verificador_conta="X", conta_pagamento=None, + numero_ispb="360305", descricao="Uma transferência via dados bancários", documento="28779295827", ) From f59ddc551fc7988375f655b2e04997f57fdfd12d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=F0=9F=A5=B6=20Pedro=20Fonseca?= Date: Tue, 30 Jan 2024 17:28:54 -0300 Subject: [PATCH 128/139] =?UTF-8?q?adiciona=20valores=20banc=C3=A1rios=20c?= =?UTF-8?q?omo=20opcionais?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bb_wrapper/models/pagamentos.py | 20 ++++++++-- bb_wrapper/wrapper/pagamento_lote.py | 6 +-- tests/wrapper/test_pagamentos.py | 57 ++++++++++++++++++++++++++++ 3 files changed, 76 insertions(+), 7 deletions(-) diff --git a/bb_wrapper/models/pagamentos.py b/bb_wrapper/models/pagamentos.py index 0f63df3c..a9562372 100644 --- a/bb_wrapper/models/pagamentos.py +++ b/bb_wrapper/models/pagamentos.py @@ -37,6 +37,18 @@ class TipoChavePIX(IntEnum): uuid = 4 +class TipoContaPIX(IntEnum): + """ + 1: Conta do tipo corrente + 2: Conta do tipo pagamento + 3: Conta do tipo poupança + """ + + conta_corrente = 1 + conta_pagamento = 3 + conta_poupanca = 3 + + class FinalidadeTED(IntEnum): """ 1: Conta corrente outros bancos @@ -100,10 +112,10 @@ class TransferenciaDadosBancariosPIX(BaseModel): data: str valor: float documento: str - tipoConta: str - agencia: str - conta: str - digitoVerificadorConta: str + tipoConta: TipoContaPIX + agencia: Optional[str] + conta: Optional[str] + digitoVerificadorConta: Optional[str] formaIdentificacao: Optional[str] descricaoPagamento: Optional[str] cpf: Optional[str] diff --git a/bb_wrapper/wrapper/pagamento_lote.py b/bb_wrapper/wrapper/pagamento_lote.py index f66d0005..3c1b6396 100644 --- a/bb_wrapper/wrapper/pagamento_lote.py +++ b/bb_wrapper/wrapper/pagamento_lote.py @@ -617,10 +617,10 @@ def criar_transferencia_por_dados_bancarios_pix( data_transferencia, valor_transferencia, tipo_conta_favorecido, - agencia_favorecido, - conta_favorecido, - digito_verificador_conta, numero_ispb, + agencia_favorecido=None, + conta_favorecido=None, + digito_verificador_conta=None, conta_pagamento=None, descricao="", tipo_pagamento=128, diff --git a/tests/wrapper/test_pagamentos.py b/tests/wrapper/test_pagamentos.py index c74c8a3f..3d9508aa 100644 --- a/tests/wrapper/test_pagamentos.py +++ b/tests/wrapper/test_pagamentos.py @@ -1018,6 +1018,63 @@ def test_criar_transferencia_pix_dados_bancarios(self): self.assertEqual(2, self.total_requests()) self.mock_responses.assert_call_count(request_url, 1) + def test_criar_transferencia_pix_dados_bancarios2(self): + """ + Teste para verificar a URL da requisição e + dados de transferência PIX por dados bancarios + """ + + request_url = PagamentoLoteBBWrapper()._construct_url( + "lotes-transferencias-pix" + ) + + expected_json = { + "numeroRequisicao": "123", + "agenciaDebito": "345", + "contaCorrenteDebito": "678", + "digitoVerificadorContaCorrente": "X", + "tipoPagamento": 128, + "listaTransferencias": [ + { + "data": "19042023", + "valor": "50", + "descricaoPagamento": "Uma transferência via dados bancários", + "formaIdentificacao": 5, + "tipoConta": 1, + "contaPagamento": 12345678, + "numeroISPB": "360305", + "cpf": "28779295827", + } + ], + } + + self.mock_responses.add( + responses.POST, + request_url, + headers=self._build_authorization_header(1), + json=expected_json, + ) + + response = PagamentoLoteBBWrapper().criar_transferencia_por_dados_bancarios_pix( + n_requisicao="123", + agencia="345", + conta="678", + dv_conta="X", + data_transferencia="19042023", + valor_transferencia=12, + tipo_conta_favorecido=1, + conta_pagamento=12345678, + numero_ispb="360305", + descricao="Uma transferência via dados bancários", + documento="28779295827", + ) + + self.assertEqual(request_url, response.url) + self.assertEqual(self._get_headers(), response.headers) + self.assertEqual(expected_json, response.json()) + self.assertEqual(2, self.total_requests()) + self.mock_responses.assert_call_count(request_url, 1) + def test_consultar_pix(self): """ - Teste para consultar um pix de um determinado lote From 8934d56d0955a5d580da6834c787db3444cee59c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=F0=9F=A5=B6=20Pedro=20Fonseca?= Date: Tue, 30 Jan 2024 17:29:35 -0300 Subject: [PATCH 129/139] =?UTF-8?q?cria=20exemplo=20de=20transferencia=20p?= =?UTF-8?q?ix=20via=20dados=20banc=C3=A1rios=20apenas=20pela=20conta=5Fpag?= =?UTF-8?q?amento?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...ia_pix_dados_bancario_conta_pagamento.json | 37 +++++++++++++++++++ ...ncia_pix_dados_bancario_conta_pagamento.py | 35 ++++++++++++++++++ .../transferencia_pix_dados_bancarios.py | 2 +- 3 files changed, 73 insertions(+), 1 deletion(-) create mode 100644 examples/lotes_pagamento/data/transferencia_pix_dados_bancario_conta_pagamento.json create mode 100644 examples/lotes_pagamento/transferencia_pix_dados_bancario_conta_pagamento.py diff --git a/examples/lotes_pagamento/data/transferencia_pix_dados_bancario_conta_pagamento.json b/examples/lotes_pagamento/data/transferencia_pix_dados_bancario_conta_pagamento.json new file mode 100644 index 00000000..0b20eb8f --- /dev/null +++ b/examples/lotes_pagamento/data/transferencia_pix_dados_bancario_conta_pagamento.json @@ -0,0 +1,37 @@ +{ + "numeroRequisicao": 11488, + "estadoRequisicao": 3, + "quantidadeTransferencias": 1, + "valorTransferencias": 15.5, + "quantidadeTransferenciasValidas": 0, + "valorTransferenciasValidas": 0, + "listaTransferencias": [ + { + "identificadorPagamento": 90011488731030000, + "data": 30012024, + "valor": 15.5, + "documentoDebito": 0, + "documentoCredito": 0, + "descricaoPagamento": "Uma transfer\u00fdncia via dados banc\u00fdrios", + "descricaoPagamentoInstantaneo": "", + "formaIdentificacao": 5, + "dddTelefone": 0, + "telefone": 0, + "email": "", + "cpf": 28779295827, + "cnpj": 0, + "identificacaoAleatoria": "", + "numeroCOMPE": 0, + "numeroISPB": 360305, + "tipoConta": 1, + "agencia": 0, + "conta": 0, + "digitoVerificadorConta": "", + "contaPagamento": "12345678", + "indicadorMovimentoAceito": "N", + "erros": [ + 1 + ] + } + ] +} \ No newline at end of file diff --git a/examples/lotes_pagamento/transferencia_pix_dados_bancario_conta_pagamento.py b/examples/lotes_pagamento/transferencia_pix_dados_bancario_conta_pagamento.py new file mode 100644 index 00000000..cb9c9e0f --- /dev/null +++ b/examples/lotes_pagamento/transferencia_pix_dados_bancario_conta_pagamento.py @@ -0,0 +1,35 @@ +import os +from datetime import date + +from examples.utils import dump_response + +from bb_wrapper.wrapper import PagamentoLoteBBWrapper + +c = PagamentoLoteBBWrapper(cert=("./certs/cert.pem", "./certs/key.pem")) + + +today = date.today() +bb_fmt = "%d%m%Y" + + +lote_data = { + "n_requisicao": 11488, + "agencia": 1607, + "conta": 99738672, + "dv_conta": "X", +} + +transferencia_data = { + "data_transferencia": today.strftime(bb_fmt), + "valor_transferencia": 15.50, + "descricao": "Uma transferência via dados bancários", + "tipo_conta_favorecido": 1, + "numero_ispb": "360305", + "conta_pagamento": 12345678, + "documento": "28779295827", +} + +response = c.criar_transferencia_por_dados_bancarios_pix( + **lote_data, **transferencia_data +) +dump_response(response, os.path.realpath(__file__)) diff --git a/examples/lotes_pagamento/transferencia_pix_dados_bancarios.py b/examples/lotes_pagamento/transferencia_pix_dados_bancarios.py index a9cfb66f..602f2579 100644 --- a/examples/lotes_pagamento/transferencia_pix_dados_bancarios.py +++ b/examples/lotes_pagamento/transferencia_pix_dados_bancarios.py @@ -27,7 +27,7 @@ "agencia_favorecido": 1234, "conta_favorecido": 12345, "digito_verificador_conta": "X", - "numeroISPB": "360305", + "numero_ispb": "360305", "documento": "28779295827", } From 310a6e829db2cfd77341e63b6b3d38f297453cb8 Mon Sep 17 00:00:00 2001 From: Pedro Fonseca <32584628+peidrao@users.noreply.github.com> Date: Tue, 30 Jan 2024 18:22:03 -0300 Subject: [PATCH 130/139] Apply suggestions from code review MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Sugestões feitas por rodrigo Co-authored-by: Rodrigo Castro --- bb_wrapper/models/pagamentos.py | 14 +++++++------- bb_wrapper/wrapper/pagamento_lote.py | 8 ++++---- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/bb_wrapper/models/pagamentos.py b/bb_wrapper/models/pagamentos.py index a9562372..a22cc4a2 100644 --- a/bb_wrapper/models/pagamentos.py +++ b/bb_wrapper/models/pagamentos.py @@ -113,15 +113,15 @@ class TransferenciaDadosBancariosPIX(BaseModel): valor: float documento: str tipoConta: TipoContaPIX - agencia: Optional[str] - conta: Optional[str] + agencia: Optional[int] + conta: Optional[int] digitoVerificadorConta: Optional[str] - formaIdentificacao: Optional[str] + formaIdentificacao: TipoFormaIdentificacao[int] descricaoPagamento: Optional[str] - cpf: Optional[str] - cnpj: Optional[str] + cpf: Optional[int] + cnpj: Optional[int] contaPagamento: Optional[str] - numeroISPB: Optional[str] + numeroISPB: int # noinspection PyMethodParameters @root_validator @@ -133,7 +133,7 @@ def _set_data(cls, values): """ from ..services.pix import PixService - values["formaIdentificacao"] = "5" + values["formaIdentificacao"] = 5 documento = values.pop("documento", None) if documento is not None: diff --git a/bb_wrapper/wrapper/pagamento_lote.py b/bb_wrapper/wrapper/pagamento_lote.py index 3c1b6396..3187438b 100644 --- a/bb_wrapper/wrapper/pagamento_lote.py +++ b/bb_wrapper/wrapper/pagamento_lote.py @@ -578,12 +578,12 @@ def _criar_dados_transferencia_dados_bancarios_pix( tipo_conta_favorecido, agencia_favorecido, conta_favorecido, - digito_verificador_conta, - conta_pagamento, + digito_verificador_conta_favorecido, + conta_pagamento_favorecido, descricao, tipo_pagamento, - documento, - numero_ispb, + documento_favorecido, + numero_ispb_favorecido, ): lote_data = { "numeroRequisicao": n_requisicao, From a81a5b358e3ab1a9d65f999343cef1250b843cc6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=F0=9F=A5=B6=20Pedro=20Fonseca?= Date: Tue, 30 Jan 2024 18:37:03 -0300 Subject: [PATCH 131/139] ajustes --- bb_wrapper/models/pagamentos.py | 12 ++++++++++-- bb_wrapper/wrapper/pagamento_lote.py | 8 ++++---- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/bb_wrapper/models/pagamentos.py b/bb_wrapper/models/pagamentos.py index a22cc4a2..bfafa128 100644 --- a/bb_wrapper/models/pagamentos.py +++ b/bb_wrapper/models/pagamentos.py @@ -45,7 +45,7 @@ class TipoContaPIX(IntEnum): """ conta_corrente = 1 - conta_pagamento = 3 + conta_pagamento = 2 conta_poupanca = 3 @@ -116,7 +116,7 @@ class TransferenciaDadosBancariosPIX(BaseModel): agencia: Optional[int] conta: Optional[int] digitoVerificadorConta: Optional[str] - formaIdentificacao: TipoFormaIdentificacao[int] + formaIdentificacao: Optional[int] descricaoPagamento: Optional[str] cpf: Optional[int] cnpj: Optional[int] @@ -135,6 +135,14 @@ def _set_data(cls, values): values["formaIdentificacao"] = 5 + tipo_conta = values.get("tipo_conta_favorecido") + if TipoContaPIX.conta_pagamento == tipo_conta: + values.pop("agencia") + values.pop("conta") + values.pop("digitoVerificadorConta") + else: + values.pop("contaPagamento") + documento = values.pop("documento", None) if documento is not None: PixService().verify_document(documento, values) diff --git a/bb_wrapper/wrapper/pagamento_lote.py b/bb_wrapper/wrapper/pagamento_lote.py index 3187438b..3f0f192d 100644 --- a/bb_wrapper/wrapper/pagamento_lote.py +++ b/bb_wrapper/wrapper/pagamento_lote.py @@ -593,16 +593,16 @@ def _criar_dados_transferencia_dados_bancarios_pix( "tipoPagamento": tipo_pagamento, } transferencia_data = { - "documento": documento, + "documento": documento_favorecido, "data": data_transferencia, "valor": valor_transferencia, "descricaoPagamento": descricao, "tipoConta": tipo_conta_favorecido, "agencia": agencia_favorecido, "conta": conta_favorecido, - "digitoVerificadorConta": digito_verificador_conta, - "contaPagamento": conta_pagamento, - "numeroISPB": numero_ispb, + "digitoVerificadorConta": digito_verificador_conta_favorecido, + "contaPagamento": conta_pagamento_favorecido, + "numeroISPB": numero_ispb_favorecido, } transferencia_data = TransferenciaDadosBancariosPIX(**transferencia_data).dict() From 446e6df1c8f58bbc03abe85080243a137c815899 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=F0=9F=A5=B6=20Pedro=20Fonseca?= Date: Wed, 31 Jan 2024 17:43:53 -0300 Subject: [PATCH 132/139] ajustar modelos --- bb_wrapper/models/pagamentos.py | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/bb_wrapper/models/pagamentos.py b/bb_wrapper/models/pagamentos.py index bfafa128..c664a6f5 100644 --- a/bb_wrapper/models/pagamentos.py +++ b/bb_wrapper/models/pagamentos.py @@ -62,18 +62,18 @@ class FinalidadeTED(IntEnum): class TransferenciaChavePIX(BaseModel): - data: str + data: int valor: float chave: str formaIdentificacao: Optional[TipoChavePIX] descricaoPagamento: Optional[str] - dddTelefone: Optional[str] - telefone: Optional[str] + dddTelefone: Optional[int] + telefone: Optional[int] email: Optional[str] - cpf: Optional[str] - cnpj: Optional[str] + cpf: Optional[int] + cnpj: Optional[int] identificacaoAleatoria: Optional[str] - documento: Optional[str] + documento: Optional[int] # noinspection PyMethodParameters @root_validator @@ -90,8 +90,8 @@ def _set_data(cls, values): values["formaIdentificacao"] = key_type.value if key_type == TipoChavePIX.telefone: - values["dddTelefone"] = key[:2] - values["telefone"] = key[2:] + values["dddTelefone"] = int(key[:2]) + values["telefone"] = int(key[2:]) elif key_type == TipoChavePIX.email: PixService().verify_email(key) values["email"] = key @@ -109,9 +109,9 @@ def _set_data(cls, values): class TransferenciaDadosBancariosPIX(BaseModel): - data: str + data: int valor: float - documento: str + documento: int tipoConta: TipoContaPIX agencia: Optional[int] conta: Optional[int] From e462efa14bf7b0ef3460baac56ba8f551a47fc53 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=F0=9F=A5=B6=20Pedro=20Fonseca?= Date: Wed, 31 Jan 2024 17:44:10 -0300 Subject: [PATCH 133/139] ajustar testes em wrapper --- tests/wrapper/test_pagamentos.py | 268 +++++++++++++++---------------- 1 file changed, 134 insertions(+), 134 deletions(-) diff --git a/tests/wrapper/test_pagamentos.py b/tests/wrapper/test_pagamentos.py index 3d9508aa..af12a436 100644 --- a/tests/wrapper/test_pagamentos.py +++ b/tests/wrapper/test_pagamentos.py @@ -103,19 +103,19 @@ def test_criar_dados_chave_aleatoria_transferencia_pix(self): """ expected_json = { - "numeroRequisicao": "123", - "agenciaDebito": "345", - "contaCorrenteDebito": "678", + "numeroRequisicao": 123, + "agenciaDebito": 345, + "contaCorrenteDebito": 678, "digitoVerificadorContaCorrente": "X", "tipoPagamento": 128, "listaTransferencias": [ { "email": None, "cnpj": None, - "cpf": "11122233300", + "cpf": 11122233300, "dddTelefone": None, "telefone": None, - "data": "19042023", + "data": 19042023, "valor": 11.0, "descricaoPagamento": "Pagamento", "formaIdentificacao": 4, @@ -125,16 +125,16 @@ def test_criar_dados_chave_aleatoria_transferencia_pix(self): } response = PagamentoLoteBBWrapper()._criar_dados_transferencia_chave_pix( - n_requisicao="123", - agencia="345", - conta="678", + n_requisicao=123, + agencia=345, + conta=678, dv_conta="X", - data_transferencia="19042023", + data_transferencia=19042023, valor_transferencia=11, chave="d14d32de-b3b9-4c31-9f89-8df2cec92c50", descricao="Pagamento", tipo_pagamento=128, - documento="11122233300", + documento=11122233300, ) self.assertEqual(expected_json, response) @@ -146,9 +146,9 @@ def test_criar_dados_chave_aleatoria_transferencia_pix_sem_documento(self): """ expected_json = { - "numeroRequisicao": "123", - "agenciaDebito": "345", - "contaCorrenteDebito": "678", + "numeroRequisicao": 123, + "agenciaDebito": 345, + "contaCorrenteDebito": 678, "digitoVerificadorContaCorrente": "X", "tipoPagamento": 128, "listaTransferencias": [ @@ -158,7 +158,7 @@ def test_criar_dados_chave_aleatoria_transferencia_pix_sem_documento(self): "cpf": None, "dddTelefone": None, "telefone": None, - "data": "19042023", + "data": 19042023, "valor": 11.0, "descricaoPagamento": "Pagamento", "formaIdentificacao": 4, @@ -168,11 +168,11 @@ def test_criar_dados_chave_aleatoria_transferencia_pix_sem_documento(self): } response = PagamentoLoteBBWrapper()._criar_dados_transferencia_chave_pix( - n_requisicao="123", - agencia="345", - conta="678", + n_requisicao=123, + agencia=345, + conta=678, dv_conta="X", - data_transferencia="19042023", + data_transferencia=19042023, valor_transferencia=11, chave="d14d32de-b3b9-4c31-9f89-8df2cec92c50", descricao="Pagamento", @@ -189,19 +189,19 @@ def test_criar_dados_telefone_transferencia_pix(self): """ expected_json = { - "numeroRequisicao": "123", - "agenciaDebito": "345", - "contaCorrenteDebito": "678", + "numeroRequisicao": 123, + "agenciaDebito": 345, + "contaCorrenteDebito": 678, "digitoVerificadorContaCorrente": "X", "tipoPagamento": 128, "listaTransferencias": [ { "email": None, "cnpj": None, - "cpf": "11122233300", - "dddTelefone": "11", - "telefone": "985732102", - "data": "19042023", + "cpf": 11122233300, + "dddTelefone": 11, + "telefone": 985732102, + "data": 19042023, "valor": 11.0, "descricaoPagamento": "Pagamento", "formaIdentificacao": 1, @@ -211,16 +211,16 @@ def test_criar_dados_telefone_transferencia_pix(self): } response = PagamentoLoteBBWrapper()._criar_dados_transferencia_chave_pix( - n_requisicao="123", - agencia="345", - conta="678", + n_requisicao=123, + agencia=345, + conta=678, dv_conta="X", - data_transferencia="19042023", + data_transferencia=19042023, valor_transferencia=11, chave="11985732102", descricao="Pagamento", tipo_pagamento=128, - documento="11122233300", + documento=11122233300, ) self.assertEqual(expected_json, response) @@ -232,19 +232,19 @@ def test_criar_dados_email_transferencia_pix(self): """ expected_json = { - "numeroRequisicao": "123", - "agenciaDebito": "345", - "contaCorrenteDebito": "678", + "numeroRequisicao": 123, + "agenciaDebito": 345, + "contaCorrenteDebito": 678, "digitoVerificadorContaCorrente": "X", "tipoPagamento": 128, "listaTransferencias": [ { "email": "teste@imo.com", "cnpj": None, - "cpf": "11122233300", + "cpf": 11122233300, "dddTelefone": None, "telefone": None, - "data": "19042023", + "data": 19042023, "valor": 11.0, "descricaoPagamento": "Pagamento", "formaIdentificacao": 2, @@ -254,11 +254,11 @@ def test_criar_dados_email_transferencia_pix(self): } response = PagamentoLoteBBWrapper()._criar_dados_transferencia_chave_pix( - n_requisicao="123", - agencia="345", - conta="678", + n_requisicao=123, + agencia=345, + conta=678, dv_conta="X", - data_transferencia="19042023", + data_transferencia=19042023, valor_transferencia=11, chave="teste@imo.com", descricao="Pagamento", @@ -276,11 +276,11 @@ def test_criar_dados_com_email_invalido(self): with self.assertRaises(ValueError) as ctx: PagamentoLoteBBWrapper()._criar_dados_transferencia_chave_pix( - n_requisicao="123", - agencia="345", - conta="678", + n_requisicao=123, + agencia=345, + conta=678, dv_conta="X", - data_transferencia="19042023", + data_transferencia=19042023, valor_transferencia=11, chave="teste@...", descricao="Pagamento", @@ -299,19 +299,19 @@ def test_criar_dados_cpf_transferencia_pix(self): """ expected_json = { - "numeroRequisicao": "123", - "agenciaDebito": "345", - "contaCorrenteDebito": "678", + "numeroRequisicao": 123, + "agenciaDebito": 345, + "contaCorrenteDebito": 678, "digitoVerificadorContaCorrente": "X", "tipoPagamento": 128, "listaTransferencias": [ { "email": None, "cnpj": None, - "cpf": "28779295827", + "cpf": 28779295827, "dddTelefone": None, "telefone": None, - "data": "19042023", + "data": 19042023, "valor": 11.0, "descricaoPagamento": "Pagamento", "formaIdentificacao": 3, @@ -321,11 +321,11 @@ def test_criar_dados_cpf_transferencia_pix(self): } response = PagamentoLoteBBWrapper()._criar_dados_transferencia_chave_pix( - n_requisicao="123", - agencia="345", - conta="678", + n_requisicao=123, + agencia=345, + conta=678, dv_conta="X", - data_transferencia="19042023", + data_transferencia=19042023, valor_transferencia=11, chave="28779295827", descricao="Pagamento", @@ -342,19 +342,19 @@ def test_criar_dados_cnpj_transferencia_pix(self): """ expected_json = { - "numeroRequisicao": "123", - "agenciaDebito": "345", - "contaCorrenteDebito": "678", + "numeroRequisicao": 123, + "agenciaDebito": 345, + "contaCorrenteDebito": 678, "digitoVerificadorContaCorrente": "X", "tipoPagamento": 128, "listaTransferencias": [ { "email": None, - "cnpj": "95127446000198", + "cnpj": 95127446000198, "cpf": None, "dddTelefone": None, "telefone": None, - "data": "19042023", + "data": 19042023, "valor": 11.0, "descricaoPagamento": "Pagamento", "formaIdentificacao": 3, @@ -364,11 +364,11 @@ def test_criar_dados_cnpj_transferencia_pix(self): } response = PagamentoLoteBBWrapper()._criar_dados_transferencia_chave_pix( - n_requisicao="123", - agencia="345", - conta="678", + n_requisicao=123, + agencia=345, + conta=678, dv_conta="X", - data_transferencia="19042023", + data_transferencia=19042023, valor_transferencia=11, chave="95127446000198", descricao="Pagamento", @@ -738,15 +738,15 @@ def test_criar_transferencia_pix_chave_aleatoria(self): "lotes-transferencias-pix" ) expected_json = { - "numeroRequisicao": "123", - "agenciaDebito": "345", - "contaCorrenteDebito": "678", + "numeroRequisicao": 123, + "agenciaDebito": 345, + "contaCorrenteDebito": 678, "digitoVerificadorContaCorrente": "X", "tipoPagamento": 128, "listaTransferencias": [ { - "data": "19042023", - "valor": "11", + "data": 19042023, + "valor": 11, "descricaoPagamento": "Pagamento", "formaIdentificacao": 4, "identificacaoAleatoria": "d14d32de-b3b9-4c31-9f89-8df2cec92c50", @@ -761,12 +761,12 @@ def test_criar_transferencia_pix_chave_aleatoria(self): ) response = PagamentoLoteBBWrapper().criar_transferencia_por_chave_pix( - "123", - "345", - "678", + 123, + 345, + 678, "X", - "19042023", - "11", + 19042023, + 11, "d14d32de-b3b9-4c31-9f89-8df2cec92c50", "Pagamento", ) @@ -786,15 +786,15 @@ def test_criar_transferencia_pix_email(self): "lotes-transferencias-pix" ) expected_json = { - "numeroRequisicao": "123", - "agenciaDebito": "345", - "contaCorrenteDebito": "678", + "numeroRequisicao": 123, + "agenciaDebito": 345, + "contaCorrenteDebito": 678, "digitoVerificadorContaCorrente": "X", "tipoPagamento": 128, "listaTransferencias": [ { - "data": "19042023", - "valor": "12", + "data": 19042023, + "valor": 12, "descricaoPagamento": "Teste transfer", "formaIdentificacao": 2, "email": "testqrcode01@bb.com.br", @@ -809,11 +809,11 @@ def test_criar_transferencia_pix_email(self): ) response = PagamentoLoteBBWrapper().criar_transferencia_por_chave_pix( - "123", - "345", - "678", + 123, + 345, + 678, "X", - "19042023", + 19042023, 12, "testqrcode01@bb.com.br", "Teste transfer", @@ -834,17 +834,17 @@ def test_criar_transferencia_pix_telefone(self): "lotes-transferencias-pix" ) expected_json = { - "numeroRequisicao": "123", - "agenciaDebito": "345", - "contaCorrenteDebito": "678", + "numeroRequisicao": 123, + "agenciaDebito": 345, + "contaCorrenteDebito": 678, "digitoVerificadorContaCorrente": "X", "tipoPagamento": 128, "listaTransferencias": [ { - "data": "19042023", - "ddd": "11", - "telefone": "985732102", - "valor": "12", + "data": 19042023, + "ddd": 11, + "telefone": 985732102, + "valor": 12, "descricaoPagamento": "Teste telefone", "formaIdentificacao": 1, } @@ -858,13 +858,13 @@ def test_criar_transferencia_pix_telefone(self): ) response = PagamentoLoteBBWrapper().criar_transferencia_por_chave_pix( - "123", - "345", - "678", + 123, + 345, + 678, "X", - "19042023", - "11", - "11985732102", + 19042023, + 11, + 11985732102, "Teste telefone", ) @@ -883,16 +883,16 @@ def test_criar_transferencia_pix_cpf(self): "lotes-transferencias-pix" ) expected_json = { - "numeroRequisicao": "123", - "agenciaDebito": "345", - "contaCorrenteDebito": "678", + "numeroRequisicao": 123, + "agenciaDebito": 345, + "contaCorrenteDebito": 678, "digitoVerificadorContaCorrente": "X", "tipoPagamento": 128, "listaTransferencias": [ { - "data": "19042023", - "cpf": "28779295827", - "valor": "12", + "data": 19042023, + "cpf": 28779295827, + "valor": 12, "descricaoPagamento": "Teste CPF", "formaIdentificacao": 3, } @@ -906,7 +906,7 @@ def test_criar_transferencia_pix_cpf(self): ) response = PagamentoLoteBBWrapper().criar_transferencia_por_chave_pix( - "123", "345", "678", "X", "19042023", 12, "28779295827", "Teste CPF" + 123, 345, 678, "X", 19042023, 12, 28779295827, "Teste CPF" ) self.assertEqual(request_url, response.url) @@ -924,16 +924,16 @@ def test_criar_transferencia_pix_cnpj(self): "lotes-transferencias-pix" ) expected_json = { - "numeroRequisicao": "123", - "agenciaDebito": "345", - "contaCorrenteDebito": "678", + "numeroRequisicao": 123, + "agenciaDebito": 345, + "contaCorrenteDebito": 678, "digitoVerificadorContaCorrente": "X", "tipoPagamento": 128, "listaTransferencias": [ { - "data": "19042023", - "cnpj": "95127446000198", - "valor": "12", + "data": 19042023, + "cnpj": 95127446000198, + "valor": 12, "descricaoPagamento": "Teste CNPJ", "formaIdentificacao": 3, } @@ -947,7 +947,7 @@ def test_criar_transferencia_pix_cnpj(self): ) response = PagamentoLoteBBWrapper().criar_transferencia_por_chave_pix( - "123", "345", "678", "X", "19042023", "11", "95127446000198", "Teste CNPJ" + 123, 345, 678, "X", 19042023, 11, 95127446000198, "Teste CNPJ" ) self.assertEqual(request_url, response.url) @@ -967,23 +967,23 @@ def test_criar_transferencia_pix_dados_bancarios(self): ) expected_json = { - "numeroRequisicao": "123", - "agenciaDebito": "345", - "contaCorrenteDebito": "678", + "numeroRequisicao": 123, + "agenciaDebito": 345, + "contaCorrenteDebito": 678, "digitoVerificadorContaCorrente": "X", "tipoPagamento": 128, "listaTransferencias": [ { - "data": "19042023", - "valor": "50", + "data": 19042023, + "valor": 50, "descricaoPagamento": "Uma transferência via dados bancários", "formaIdentificacao": 5, "tipoConta": 1, "agencia": 1234, "conta": 12345, "digitoVerificadorConta": "X", - "numeroISPB": "360305", - "cpf": "28779295827", + "numeroISPB": 360305, + "cpf": 28779295827, } ], } @@ -996,20 +996,20 @@ def test_criar_transferencia_pix_dados_bancarios(self): ) response = PagamentoLoteBBWrapper().criar_transferencia_por_dados_bancarios_pix( - n_requisicao="123", - agencia="345", - conta="678", + n_requisicao=123, + agencia=345, + conta=678, dv_conta="X", - data_transferencia="19042023", + data_transferencia=19042023, valor_transferencia=12, tipo_conta_favorecido=1, agencia_favorecido=1234, conta_favorecido=12345, digito_verificador_conta="X", conta_pagamento=None, - numero_ispb="360305", + numero_ispb=360305, descricao="Uma transferência via dados bancários", - documento="28779295827", + documento=28779295827, ) self.assertEqual(request_url, response.url) @@ -1018,7 +1018,7 @@ def test_criar_transferencia_pix_dados_bancarios(self): self.assertEqual(2, self.total_requests()) self.mock_responses.assert_call_count(request_url, 1) - def test_criar_transferencia_pix_dados_bancarios2(self): + def test_criar_transferencia_pix_dados_bancarios_2(self): """ Teste para verificar a URL da requisição e dados de transferência PIX por dados bancarios @@ -1029,21 +1029,21 @@ def test_criar_transferencia_pix_dados_bancarios2(self): ) expected_json = { - "numeroRequisicao": "123", - "agenciaDebito": "345", - "contaCorrenteDebito": "678", + "numeroRequisicao": 123, + "agenciaDebito": 345, + "contaCorrenteDebito": 678, "digitoVerificadorContaCorrente": "X", "tipoPagamento": 128, "listaTransferencias": [ { - "data": "19042023", - "valor": "50", + "data": 19042023, + "valor": 50, "descricaoPagamento": "Uma transferência via dados bancários", "formaIdentificacao": 5, "tipoConta": 1, "contaPagamento": 12345678, - "numeroISPB": "360305", - "cpf": "28779295827", + "numeroISPB": 360305, + "cpf": 28779295827, } ], } @@ -1056,17 +1056,17 @@ def test_criar_transferencia_pix_dados_bancarios2(self): ) response = PagamentoLoteBBWrapper().criar_transferencia_por_dados_bancarios_pix( - n_requisicao="123", - agencia="345", - conta="678", + n_requisicao=123, + agencia=345, + conta=678, dv_conta="X", - data_transferencia="19042023", + data_transferencia=19042023, valor_transferencia=12, tipo_conta_favorecido=1, conta_pagamento=12345678, - numero_ispb="360305", + numero_ispb=360305, descricao="Uma transferência via dados bancários", - documento="28779295827", + documento=28779295827, ) self.assertEqual(request_url, response.url) From 3ef005e91153990b0154568452d88abd95da0ed7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=F0=9F=A5=B6=20Pedro=20Fonseca?= Date: Wed, 31 Jan 2024 18:27:29 -0300 Subject: [PATCH 134/139] ajustar testes --- bb_wrapper/services/pix.py | 6 +++--- tests/services/test_pix.py | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/bb_wrapper/services/pix.py b/bb_wrapper/services/pix.py index f0f5bff7..8823df3a 100644 --- a/bb_wrapper/services/pix.py +++ b/bb_wrapper/services/pix.py @@ -66,8 +66,8 @@ def verify_email(self, email: str, raise_exception=True): return is_email_valid def verify_document(self, key, values): - key_value = cpfcnpj.clear_punctuation(key) + key_value = cpfcnpj.clear_punctuation(str(key)) if len(key_value) == 11: - values["cpf"] = key_value + values["cpf"] = int(key_value) else: - values["cnpj"] = key_value + values["cnpj"] = int(key_value) diff --git a/tests/services/test_pix.py b/tests/services/test_pix.py index cad00c6a..9e89fd3d 100644 --- a/tests/services/test_pix.py +++ b/tests/services/test_pix.py @@ -193,7 +193,7 @@ def test_verify_document_cpf(self): - uma chave '43166663045' """ ): - cpf = "43166663045" + cpf = 43166663045 with self.when( """ @@ -236,5 +236,5 @@ def test_verify_document_cnpj(self): """ ): - expected = {"cnpj": cnpj} + expected = {"cnpj": 3794722000153} self.assertEqual(data, expected) From ded5afbea71c5254275ad368ae1bcfc89ebe5894 Mon Sep 17 00:00:00 2001 From: rodrigondec Date: Thu, 1 Feb 2024 15:17:49 -0300 Subject: [PATCH 135/139] adiciona logging no exemplo! --- examples/lotes_pagamento/transferencia_pix_cpf.py | 7 ++++++- .../lotes_pagamento/transferencia_pix_dados_bancarios.py | 7 ++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/examples/lotes_pagamento/transferencia_pix_cpf.py b/examples/lotes_pagamento/transferencia_pix_cpf.py index f21311ab..b1bd0b1d 100644 --- a/examples/lotes_pagamento/transferencia_pix_cpf.py +++ b/examples/lotes_pagamento/transferencia_pix_cpf.py @@ -2,9 +2,14 @@ from datetime import date from examples.utils import dump_response +import logging + from bb_wrapper.wrapper import PagamentoLoteBBWrapper +logging.basicConfig(level=logging.DEBUG) + + c = PagamentoLoteBBWrapper(cert=("./certs/cert.pem", "./certs/key.pem")) @@ -13,7 +18,7 @@ lote_data = { - "n_requisicao": 9931219, + "n_requisicao": 9499944, "agencia": 1607, "conta": 99738672, "dv_conta": "X", diff --git a/examples/lotes_pagamento/transferencia_pix_dados_bancarios.py b/examples/lotes_pagamento/transferencia_pix_dados_bancarios.py index 602f2579..b7c0d956 100644 --- a/examples/lotes_pagamento/transferencia_pix_dados_bancarios.py +++ b/examples/lotes_pagamento/transferencia_pix_dados_bancarios.py @@ -2,9 +2,13 @@ from datetime import date from examples.utils import dump_response +import logging from bb_wrapper.wrapper import PagamentoLoteBBWrapper + +logging.basicConfig(level=logging.DEBUG) + c = PagamentoLoteBBWrapper(cert=("./certs/cert.pem", "./certs/key.pem")) @@ -13,7 +17,7 @@ lote_data = { - "n_requisicao": 11489, + "n_requisicao": 9499946, "agencia": 1607, "conta": 99738672, "dv_conta": "X", @@ -34,4 +38,5 @@ response = c.criar_transferencia_por_dados_bancarios_pix( **lote_data, **transferencia_data ) + dump_response(response, os.path.realpath(__file__)) From d1ea125de76f200f96e5aeb4633c2435ce29952c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=F0=9F=A5=B6=20Pedro=20Fonseca?= Date: Thu, 1 Feb 2024 17:19:54 -0300 Subject: [PATCH 136/139] ajustes --- bb_wrapper/models/pagamentos.py | 8 ++++++++ tests/wrapper/test_pagamentos.py | 3 --- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/bb_wrapper/models/pagamentos.py b/bb_wrapper/models/pagamentos.py index c664a6f5..68d68abd 100644 --- a/bb_wrapper/models/pagamentos.py +++ b/bb_wrapper/models/pagamentos.py @@ -103,6 +103,10 @@ def _set_data(cls, values): documento = values.pop("documento", None) if documento is not None: PixService().verify_document(documento, values) + if values.get("cpf") is None: + del values["cpf"] + if values.get("cnpj") is None: + del values["cnpj"] values.pop("chave") return values @@ -146,6 +150,10 @@ def _set_data(cls, values): documento = values.pop("documento", None) if documento is not None: PixService().verify_document(documento, values) + if values.get("cpf") is None: + del values["cpf"] + if values.get("cnpj") is None: + del values["cnpj"] return values diff --git a/tests/wrapper/test_pagamentos.py b/tests/wrapper/test_pagamentos.py index af12a436..bfb9f13b 100644 --- a/tests/wrapper/test_pagamentos.py +++ b/tests/wrapper/test_pagamentos.py @@ -111,7 +111,6 @@ def test_criar_dados_chave_aleatoria_transferencia_pix(self): "listaTransferencias": [ { "email": None, - "cnpj": None, "cpf": 11122233300, "dddTelefone": None, "telefone": None, @@ -197,7 +196,6 @@ def test_criar_dados_telefone_transferencia_pix(self): "listaTransferencias": [ { "email": None, - "cnpj": None, "cpf": 11122233300, "dddTelefone": 11, "telefone": 985732102, @@ -240,7 +238,6 @@ def test_criar_dados_email_transferencia_pix(self): "listaTransferencias": [ { "email": "teste@imo.com", - "cnpj": None, "cpf": 11122233300, "dddTelefone": None, "telefone": None, From 9f62125d4d1fa8ecf81b02c6f9d16191815875a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=F0=9F=A5=B6=20Pedro=20Fonseca?= Date: Fri, 2 Feb 2024 10:39:24 -0300 Subject: [PATCH 137/139] removendo valores nulos --- bb_wrapper/models/pagamentos.py | 12 ++++-------- bb_wrapper/services/pix.py | 7 ++++++- bb_wrapper/wrapper/pagamento_lote.py | 2 +- tests/wrapper/test_pagamentos.py | 25 ------------------------- 4 files changed, 11 insertions(+), 35 deletions(-) diff --git a/bb_wrapper/models/pagamentos.py b/bb_wrapper/models/pagamentos.py index 68d68abd..d8212ab1 100644 --- a/bb_wrapper/models/pagamentos.py +++ b/bb_wrapper/models/pagamentos.py @@ -103,10 +103,8 @@ def _set_data(cls, values): documento = values.pop("documento", None) if documento is not None: PixService().verify_document(documento, values) - if values.get("cpf") is None: - del values["cpf"] - if values.get("cnpj") is None: - del values["cnpj"] + + PixService().remove_null_values(values) values.pop("chave") return values @@ -150,10 +148,8 @@ def _set_data(cls, values): documento = values.pop("documento", None) if documento is not None: PixService().verify_document(documento, values) - if values.get("cpf") is None: - del values["cpf"] - if values.get("cnpj") is None: - del values["cnpj"] + + PixService().remove_null_values(values) return values diff --git a/bb_wrapper/services/pix.py b/bb_wrapper/services/pix.py index 8823df3a..958f1604 100644 --- a/bb_wrapper/services/pix.py +++ b/bb_wrapper/services/pix.py @@ -65,9 +65,14 @@ def verify_email(self, email: str, raise_exception=True): raise ValueError("Email inválido!") return is_email_valid - def verify_document(self, key, values): + def verify_document(self, key, values: dict): key_value = cpfcnpj.clear_punctuation(str(key)) if len(key_value) == 11: values["cpf"] = int(key_value) else: values["cnpj"] = int(key_value) + + def remove_null_values(self, values: dict): + keys_to_remove = [k for k, v in values.items() if v is None] + for key in keys_to_remove: + del values[key] diff --git a/bb_wrapper/wrapper/pagamento_lote.py b/bb_wrapper/wrapper/pagamento_lote.py index 3f0f192d..d8fb65de 100644 --- a/bb_wrapper/wrapper/pagamento_lote.py +++ b/bb_wrapper/wrapper/pagamento_lote.py @@ -500,7 +500,7 @@ def _criar_dados_transferencia_chave_pix( chave, descricao, tipo_pagamento, - documento, + documento=None, ): lote_data = { "numeroRequisicao": n_requisicao, diff --git a/tests/wrapper/test_pagamentos.py b/tests/wrapper/test_pagamentos.py index bfb9f13b..67d53881 100644 --- a/tests/wrapper/test_pagamentos.py +++ b/tests/wrapper/test_pagamentos.py @@ -110,10 +110,7 @@ def test_criar_dados_chave_aleatoria_transferencia_pix(self): "tipoPagamento": 128, "listaTransferencias": [ { - "email": None, "cpf": 11122233300, - "dddTelefone": None, - "telefone": None, "data": 19042023, "valor": 11.0, "descricaoPagamento": "Pagamento", @@ -152,11 +149,6 @@ def test_criar_dados_chave_aleatoria_transferencia_pix_sem_documento(self): "tipoPagamento": 128, "listaTransferencias": [ { - "email": None, - "cnpj": None, - "cpf": None, - "dddTelefone": None, - "telefone": None, "data": 19042023, "valor": 11.0, "descricaoPagamento": "Pagamento", @@ -176,7 +168,6 @@ def test_criar_dados_chave_aleatoria_transferencia_pix_sem_documento(self): chave="d14d32de-b3b9-4c31-9f89-8df2cec92c50", descricao="Pagamento", tipo_pagamento=128, - documento=None, ) self.assertEqual(expected_json, response) @@ -195,7 +186,6 @@ def test_criar_dados_telefone_transferencia_pix(self): "tipoPagamento": 128, "listaTransferencias": [ { - "email": None, "cpf": 11122233300, "dddTelefone": 11, "telefone": 985732102, @@ -203,7 +193,6 @@ def test_criar_dados_telefone_transferencia_pix(self): "valor": 11.0, "descricaoPagamento": "Pagamento", "formaIdentificacao": 1, - "identificacaoAleatoria": None, } ], } @@ -239,13 +228,10 @@ def test_criar_dados_email_transferencia_pix(self): { "email": "teste@imo.com", "cpf": 11122233300, - "dddTelefone": None, - "telefone": None, "data": 19042023, "valor": 11.0, "descricaoPagamento": "Pagamento", "formaIdentificacao": 2, - "identificacaoAleatoria": None, } ], } @@ -303,16 +289,11 @@ def test_criar_dados_cpf_transferencia_pix(self): "tipoPagamento": 128, "listaTransferencias": [ { - "email": None, - "cnpj": None, "cpf": 28779295827, - "dddTelefone": None, - "telefone": None, "data": 19042023, "valor": 11.0, "descricaoPagamento": "Pagamento", "formaIdentificacao": 3, - "identificacaoAleatoria": None, } ], } @@ -327,7 +308,6 @@ def test_criar_dados_cpf_transferencia_pix(self): chave="28779295827", descricao="Pagamento", tipo_pagamento=128, - documento=None, ) self.assertEqual(expected_json, response) @@ -346,16 +326,11 @@ def test_criar_dados_cnpj_transferencia_pix(self): "tipoPagamento": 128, "listaTransferencias": [ { - "email": None, "cnpj": 95127446000198, - "cpf": None, - "dddTelefone": None, - "telefone": None, "data": 19042023, "valor": 11.0, "descricaoPagamento": "Pagamento", "formaIdentificacao": 3, - "identificacaoAleatoria": None, } ], } From 45f0277976f343c0b469fa5b2a7f05397459fcab Mon Sep 17 00:00:00 2001 From: rodrigondec Date: Tue, 6 Feb 2024 19:15:49 -0300 Subject: [PATCH 138/139] adiciona tratamento do COMPE e cpf/cnpj dos dados. --- bb_wrapper/models/pagamentos.py | 11 +++++------ bb_wrapper/wrapper/pagamento_lote.py | 10 ++++++++-- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/bb_wrapper/models/pagamentos.py b/bb_wrapper/models/pagamentos.py index d8212ab1..2dc7784d 100644 --- a/bb_wrapper/models/pagamentos.py +++ b/bb_wrapper/models/pagamentos.py @@ -113,7 +113,8 @@ def _set_data(cls, values): class TransferenciaDadosBancariosPIX(BaseModel): data: int valor: float - documento: int + cpf: Optional[int] + cnpj: Optional[int] tipoConta: TipoContaPIX agencia: Optional[int] conta: Optional[int] @@ -123,7 +124,7 @@ class TransferenciaDadosBancariosPIX(BaseModel): cpf: Optional[int] cnpj: Optional[int] contaPagamento: Optional[str] - numeroISPB: int + numeroCOMPE: int # noinspection PyMethodParameters @root_validator @@ -145,11 +146,9 @@ def _set_data(cls, values): else: values.pop("contaPagamento") - documento = values.pop("documento", None) - if documento is not None: - PixService().verify_document(documento, values) - PixService().remove_null_values(values) + if "cnpj" not in values and "cpf" not in values: + raise ValueError("É necessário inserir o CNPj ou CPF") return values diff --git a/bb_wrapper/wrapper/pagamento_lote.py b/bb_wrapper/wrapper/pagamento_lote.py index d8fb65de..a691b023 100644 --- a/bb_wrapper/wrapper/pagamento_lote.py +++ b/bb_wrapper/wrapper/pagamento_lote.py @@ -593,7 +593,6 @@ def _criar_dados_transferencia_dados_bancarios_pix( "tipoPagamento": tipo_pagamento, } transferencia_data = { - "documento": documento_favorecido, "data": data_transferencia, "valor": valor_transferencia, "descricaoPagamento": descricao, @@ -602,9 +601,16 @@ def _criar_dados_transferencia_dados_bancarios_pix( "conta": conta_favorecido, "digitoVerificadorConta": digito_verificador_conta_favorecido, "contaPagamento": conta_pagamento_favorecido, - "numeroISPB": numero_ispb_favorecido, + "numeroCOMPE": numero_ispb_favorecido, } + from bb_wrapper.services.document import DocumentoService, TipoInscricaoEnum + tipo_documento = DocumentoService().identifica_tipo(documento_favorecido) + if tipo_documento == TipoInscricaoEnum.cpf: + transferencia_data['cpf'] = documento_favorecido + else: + transferencia_data['cnpj'] = documento_favorecido + transferencia_data = TransferenciaDadosBancariosPIX(**transferencia_data).dict() return {**lote_data, "listaTransferencias": [transferencia_data]} From 28f68298daba8c5ce4e2d602b975d53088dd60aa Mon Sep 17 00:00:00 2001 From: Rodrigo Castro Date: Mon, 13 May 2024 17:06:33 -0300 Subject: [PATCH 139/139] ajustes --- bb_wrapper/wrapper/pagamento_lote.py | 9 +++++++++ bb_wrapper/wrapper/request.py | 1 + examples/lotes_pagamento/liberar_pagamentos.py | 10 ++++++++-- examples/lotes_pagamento/resgatar_lote.py | 12 ++++++++---- examples/lotes_pagamento/transferencia_pix_cpf.py | 4 +++- .../transferencia_pix_dados_bancarios.py | 4 +++- 6 files changed, 32 insertions(+), 8 deletions(-) diff --git a/bb_wrapper/wrapper/pagamento_lote.py b/bb_wrapper/wrapper/pagamento_lote.py index a691b023..2f70cdf8 100644 --- a/bb_wrapper/wrapper/pagamento_lote.py +++ b/bb_wrapper/wrapper/pagamento_lote.py @@ -686,3 +686,12 @@ def consultar_pix(self, _id): url = self._construct_url("pix", _id) response = self._get(url) return response + + def consultar_solicitacao_lote_pix(self, number): + """ + - Consulta os dados de um pagamento efetuado na modalidade PIX. + """ + + url = self._construct_url("lotes-transferencias-pix", number, "solicitacao") + response = self._get(url) + return response diff --git a/bb_wrapper/wrapper/request.py b/bb_wrapper/wrapper/request.py index f9b556d1..b23d1d36 100644 --- a/bb_wrapper/wrapper/request.py +++ b/bb_wrapper/wrapper/request.py @@ -70,6 +70,7 @@ def _process_response(response) -> requests.Response: except JSONDecodeError: response.data = {} response.reason = response.data + logger.debug(response.request.body) response.raise_for_status() return response diff --git a/examples/lotes_pagamento/liberar_pagamentos.py b/examples/lotes_pagamento/liberar_pagamentos.py index 01e8f3fc..aeda8c2a 100644 --- a/examples/lotes_pagamento/liberar_pagamentos.py +++ b/examples/lotes_pagamento/liberar_pagamentos.py @@ -4,9 +4,15 @@ from bb_wrapper.wrapper import PagamentoLoteBBWrapper -c = PagamentoLoteBBWrapper(cert=("./certs/cert.pem", "./certs/key.pem")) +import logging -number = "579175" +logging.basicConfig(level=logging.DEBUG) + +c = PagamentoLoteBBWrapper( + cert=("./certs/imobanco_cert.pem", "./certs/imobanco_key.pem") +) + +number = "9999986" response = c.liberar_pagamentos(number) diff --git a/examples/lotes_pagamento/resgatar_lote.py b/examples/lotes_pagamento/resgatar_lote.py index bbde88b5..7d667d33 100644 --- a/examples/lotes_pagamento/resgatar_lote.py +++ b/examples/lotes_pagamento/resgatar_lote.py @@ -3,15 +3,19 @@ from examples.utils import dump_response from bb_wrapper.wrapper import PagamentoLoteBBWrapper +import logging -c = PagamentoLoteBBWrapper(cert=("./certs/cert.pem", "./certs/key.pem")) +logging.basicConfig(level=logging.DEBUG) -_id = "579145" # BOLETO -# _id = "579144" # TED -# _id = "579143" # TRIBUTO +c = PagamentoLoteBBWrapper( + cert=("./certs/imobanco_cert.pem", "./certs/imobanco_key.pem") +) + +_id = "9999988" response = c.resgatar_lote( _id, ) +print(response.data) dump_response(response, os.path.realpath(__file__)) diff --git a/examples/lotes_pagamento/transferencia_pix_cpf.py b/examples/lotes_pagamento/transferencia_pix_cpf.py index b1bd0b1d..a21b8d61 100644 --- a/examples/lotes_pagamento/transferencia_pix_cpf.py +++ b/examples/lotes_pagamento/transferencia_pix_cpf.py @@ -10,7 +10,9 @@ logging.basicConfig(level=logging.DEBUG) -c = PagamentoLoteBBWrapper(cert=("./certs/cert.pem", "./certs/key.pem")) +c = PagamentoLoteBBWrapper( + cert=("./certs/imobanco_cert.pem", "./certs/imobanco_key.pem") +) today = date.today() diff --git a/examples/lotes_pagamento/transferencia_pix_dados_bancarios.py b/examples/lotes_pagamento/transferencia_pix_dados_bancarios.py index b7c0d956..2ab25bcc 100644 --- a/examples/lotes_pagamento/transferencia_pix_dados_bancarios.py +++ b/examples/lotes_pagamento/transferencia_pix_dados_bancarios.py @@ -9,7 +9,9 @@ logging.basicConfig(level=logging.DEBUG) -c = PagamentoLoteBBWrapper(cert=("./certs/cert.pem", "./certs/key.pem")) +c = PagamentoLoteBBWrapper( + cert=("./certs/imobanco_cert.pem", "./certs/imobanco_key.pem") +) today = date.today()