From 0b8aa1bb9a7e27d60bb0b47002b0402da4e46375 Mon Sep 17 00:00:00 2001 From: Kenio de Souza Date: Tue, 23 Sep 2025 16:01:21 -0300 Subject: [PATCH 1/5] [MVPTN-11] feat(CRUD): Crud completo da tabela g_tb_documentotipo --- Orius.postman_collection.json | 1190 ++++++++++++++++- .../g_tb_documentotipo_delete_action.py | 26 + ...b_documentotipo_get_by_descricao_action.py | 29 + .../g_tb_documentotipo_index_action.py | 24 + .../g_tb_documentotipo_save_action.py | 28 + .../g_tb_documentotipo_show_action.py | 28 + .../g_tb_documentotipo_update_action.py | 26 + .../g_tb_documentotipo_controller.py | 113 ++ .../endpoints/g_tb_documentotipo_endpoint.py | 108 ++ .../g_tb_documentotipo_delete_repository.py | 41 + ...cumentotipo_get_by_descricao_repository.py | 37 + .../g_tb_documentotipo_index_repository.py | 31 + .../g_tb_documentotipo_save_repository.py | 71 + .../g_tb_documentotipo_show_repository.py | 46 + .../g_tb_documentotipo_update_repository.py | 85 ++ .../schemas/g_tb_documentotipo_schema.py | 148 ++ .../go/g_tb_documentotipo_delete_service.py | 27 + ..._documentotipo_get_by_descricao_service.py | 38 + .../go/g_tb_documentotipo_index_service.py | 32 + .../go/g_tb_documentotipo_save_service.py | 70 + .../go/g_tb_documentotipo_show_service.py | 35 + .../go/g_tb_documentotipo_update_service.py | 23 + packages/v1/api.py | 6 + 23 files changed, 2256 insertions(+), 6 deletions(-) create mode 100644 packages/v1/administrativo/actions/g_tb_documentotipo/g_tb_documentotipo_delete_action.py create mode 100644 packages/v1/administrativo/actions/g_tb_documentotipo/g_tb_documentotipo_get_by_descricao_action.py create mode 100644 packages/v1/administrativo/actions/g_tb_documentotipo/g_tb_documentotipo_index_action.py create mode 100644 packages/v1/administrativo/actions/g_tb_documentotipo/g_tb_documentotipo_save_action.py create mode 100644 packages/v1/administrativo/actions/g_tb_documentotipo/g_tb_documentotipo_show_action.py create mode 100644 packages/v1/administrativo/actions/g_tb_documentotipo/g_tb_documentotipo_update_action.py create mode 100644 packages/v1/administrativo/controllers/g_tb_documentotipo_controller.py create mode 100644 packages/v1/administrativo/endpoints/g_tb_documentotipo_endpoint.py create mode 100644 packages/v1/administrativo/repositories/g_tb_documentotipo/g_tb_documentotipo_delete_repository.py create mode 100644 packages/v1/administrativo/repositories/g_tb_documentotipo/g_tb_documentotipo_get_by_descricao_repository.py create mode 100644 packages/v1/administrativo/repositories/g_tb_documentotipo/g_tb_documentotipo_index_repository.py create mode 100644 packages/v1/administrativo/repositories/g_tb_documentotipo/g_tb_documentotipo_save_repository.py create mode 100644 packages/v1/administrativo/repositories/g_tb_documentotipo/g_tb_documentotipo_show_repository.py create mode 100644 packages/v1/administrativo/repositories/g_tb_documentotipo/g_tb_documentotipo_update_repository.py create mode 100644 packages/v1/administrativo/schemas/g_tb_documentotipo_schema.py create mode 100644 packages/v1/administrativo/services/g_tb_documentotipo/go/g_tb_documentotipo_delete_service.py create mode 100644 packages/v1/administrativo/services/g_tb_documentotipo/go/g_tb_documentotipo_get_by_descricao_service.py create mode 100644 packages/v1/administrativo/services/g_tb_documentotipo/go/g_tb_documentotipo_index_service.py create mode 100644 packages/v1/administrativo/services/g_tb_documentotipo/go/g_tb_documentotipo_save_service.py create mode 100644 packages/v1/administrativo/services/g_tb_documentotipo/go/g_tb_documentotipo_show_service.py create mode 100644 packages/v1/administrativo/services/g_tb_documentotipo/go/g_tb_documentotipo_update_service.py diff --git a/Orius.postman_collection.json b/Orius.postman_collection.json index 2f7056a..e24e4f3 100644 --- a/Orius.postman_collection.json +++ b/Orius.postman_collection.json @@ -5461,7 +5461,8 @@ "" ], "type": "text/javascript", - "packages": {} + "packages": {}, + "requests": {} } } ], @@ -5486,7 +5487,7 @@ "urlencoded": [] }, "url": { - "raw": "{{BaseUrlV1}}administrativo/g_tb_tipologradouro/descricao?descricao=eu", + "raw": "{{BaseUrlV1}}administrativo/g_tb_tipologradouro/descricao?descricao=Sítios", "host": [ "{{BaseUrlV1}}administrativo" ], @@ -5497,7 +5498,7 @@ "query": [ { "key": "descricao", - "value": "eu" + "value": "Sítios" } ] } @@ -5683,6 +5684,1155 @@ } ] }, + { + "name": "Medida tipo", + "item": [ + { + "name": "GET", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code é 201 ou 200\", function () {\r", + " pm.expect(pm.response.code).to.be.oneOf([200, 201]);\r", + "});\r", + "\r", + "pm.test(\"Resposta contém ID ou confirmação\", function () {\r", + " const jsonData = pm.response.json();\r", + " pm.expect(jsonData).to.have.any.keys(\"id\", \"message\", \"status\");\r", + "});\r", + "\r", + "pm.test(\"Mensagem indica sucesso\", function () {\r", + " const jsonData = pm.response.json();\r", + " pm.expect(jsonData.message || \"\").to.match(/sucesso|criado|registrado/i);\r", + "});\r", + "" + ], + "type": "text/javascript", + "packages": {}, + "requests": {} + } + } + ], + "request": { + "auth": { + "type": "bearer", + "bearer": [ + { + "key": "token", + "value": "{{BearerToken}}", + "type": "string" + } + ] + }, + "method": "GET", + "header": [], + "url": { + "raw": "{{BaseUrlV1}}administrativo/g_medida_tipo", + "host": [ + "{{BaseUrlV1}}administrativo" + ], + "path": [ + "g_medida_tipo" + ] + } + }, + "response": [] + }, + { + "name": "POST", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "const response = pm.response.json();\r", + "\r", + "// Salvando em variáveis da *collection*\r", + "pm.collectionVariables.set(\"medidaTipoId\", response.data.medida_tipo_id);\r", + "\r", + "pm.test(\"Status code é 201 ou 200\", function () {\r", + " pm.expect(pm.response.code).to.be.oneOf([200, 201]);\r", + "});\r", + "\r", + "pm.test(\"Resposta contém ID ou confirmação\", function () {\r", + " const jsonData = pm.response.json();\r", + " pm.expect(jsonData).to.have.any.keys(\"id\", \"message\", \"status\");\r", + "});\r", + "\r", + "pm.test(\"Mensagem indica sucesso\", function () {\r", + " const jsonData = pm.response.json();\r", + " pm.expect(jsonData.message || \"\").to.match(/sucesso|criado|registrado/i);\r", + "});\r", + "" + ], + "type": "text/javascript", + "packages": {}, + "requests": {} + } + }, + { + "listen": "prerequest", + "script": { + "exec": [ + "" + ], + "type": "text/javascript", + "packages": {}, + "requests": {} + } + } + ], + "request": { + "auth": { + "type": "bearer", + "bearer": [ + { + "key": "token", + "value": "{{BearerToken}}", + "type": "string" + } + ] + }, + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\r\n \"descricao\": \"{{$randomFullName}}\",\r\n \"sigla\": \"{{login_aleatorio}}\"\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{BaseUrlV1}}administrativo/g_medida_tipo", + "host": [ + "{{BaseUrlV1}}administrativo" + ], + "path": [ + "g_medida_tipo" + ] + } + }, + "response": [] + }, + { + "name": "GET DESCRIÇÃO", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code é 201 ou 200\", function () {\r", + " pm.expect(pm.response.code).to.be.oneOf([200, 201]);\r", + "});\r", + "\r", + "pm.test(\"Resposta contém ID ou confirmação\", function () {\r", + " const jsonData = pm.response.json();\r", + " pm.expect(jsonData).to.have.any.keys(\"id\", \"message\", \"status\");\r", + "});\r", + "\r", + "pm.test(\"Mensagem indica sucesso\", function () {\r", + " const jsonData = pm.response.json();\r", + " pm.expect(jsonData.message || \"\").to.match(/sucesso|criado|registrado/i);\r", + "});\r", + "" + ], + "type": "text/javascript", + "packages": {}, + "requests": {} + } + } + ], + "protocolProfileBehavior": { + "disableBodyPruning": true + }, + "request": { + "auth": { + "type": "bearer", + "bearer": [ + { + "key": "token", + "value": "{{BearerToken}}", + "type": "string" + } + ] + }, + "method": "GET", + "header": [], + "body": { + "mode": "raw", + "raw": "" + }, + "url": { + "raw": "{{BaseUrlV1}}administrativo/g_medida_tipo/descricao?descricao=Braça", + "host": [ + "{{BaseUrlV1}}administrativo" + ], + "path": [ + "g_medida_tipo", + "descricao" + ], + "query": [ + { + "key": "descricao", + "value": "Braça" + } + ] + } + }, + "response": [] + }, + { + "name": "GET ID", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code é 201 ou 200\", function () {\r", + " pm.expect(pm.response.code).to.be.oneOf([200, 201]);\r", + "});\r", + "\r", + "pm.test(\"Resposta contém ID ou confirmação\", function () {\r", + " const jsonData = pm.response.json();\r", + " pm.expect(jsonData).to.have.any.keys(\"id\", \"message\", \"status\");\r", + "});\r", + "\r", + "pm.test(\"Mensagem indica sucesso\", function () {\r", + " const jsonData = pm.response.json();\r", + " pm.expect(jsonData.message || \"\").to.match(/sucesso|criado|registrado/i);\r", + "});\r", + "" + ], + "type": "text/javascript", + "packages": {}, + "requests": {} + } + } + ], + "request": { + "auth": { + "type": "bearer", + "bearer": [ + { + "key": "token", + "value": "{{BearerToken}}", + "type": "string" + } + ] + }, + "method": "GET", + "header": [], + "url": { + "raw": "{{BaseUrlV1}}administrativo/g_medida_tipo/{{medidaTipoId}}", + "host": [ + "{{BaseUrlV1}}administrativo" + ], + "path": [ + "g_medida_tipo", + "{{medidaTipoId}}" + ] + } + }, + "response": [] + }, + { + "name": "PUT", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code é 201 ou 200\", function () {\r", + " pm.expect(pm.response.code).to.be.oneOf([200, 201]);\r", + "});\r", + "\r", + "pm.test(\"Resposta contém ID ou confirmação\", function () {\r", + " const jsonData = pm.response.json();\r", + " pm.expect(jsonData).to.have.any.keys(\"id\", \"message\", \"status\");\r", + "});\r", + "\r", + "pm.test(\"Mensagem indica sucesso\", function () {\r", + " const jsonData = pm.response.json();\r", + " pm.expect(jsonData.message || \"\").to.match(/sucesso|criado|registrado/i);\r", + "});\r", + "" + ], + "type": "text/javascript", + "packages": {}, + "requests": {} + } + } + ], + "request": { + "auth": { + "type": "bearer", + "bearer": [ + { + "key": "token", + "value": "{{BearerToken}}", + "type": "string" + } + ] + }, + "method": "PUT", + "header": [], + "body": { + "mode": "raw", + "raw": "{\r\n \"descricao\": \"{{$randomFullName}}\",\r\n \"sigla\": \"{{login_aleatorio}}\"\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{BaseUrlV1}}administrativo/g_medida_tipo/{{medidaTipoId}}", + "host": [ + "{{BaseUrlV1}}administrativo" + ], + "path": [ + "g_medida_tipo", + "{{medidaTipoId}}" + ] + } + }, + "response": [] + }, + { + "name": "DELETE", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code é 201 ou 200\", function () {\r", + " pm.expect(pm.response.code).to.be.oneOf([200, 201]);\r", + "});\r", + "\r", + "pm.test(\"Resposta contém ID ou confirmação\", function () {\r", + " const jsonData = pm.response.json();\r", + " pm.expect(jsonData).to.have.any.keys(\"id\", \"message\", \"status\");\r", + "});\r", + "\r", + "pm.test(\"Mensagem indica sucesso\", function () {\r", + " const jsonData = pm.response.json();\r", + " pm.expect(jsonData.message || \"\").to.match(/sucesso|criado|registrado/i);\r", + "});\r", + "" + ], + "type": "text/javascript", + "packages": {}, + "requests": {} + } + } + ], + "request": { + "auth": { + "type": "bearer", + "bearer": [ + { + "key": "token", + "value": "{{BearerToken}}", + "type": "string" + } + ] + }, + "method": "DELETE", + "header": [], + "body": { + "mode": "raw", + "raw": "", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{BaseUrlV1}}administrativo/g_medida_tipo/{{medidaTipoId}}", + "host": [ + "{{BaseUrlV1}}administrativo" + ], + "path": [ + "g_medida_tipo", + "{{medidaTipoId}}" + ] + } + }, + "response": [] + } + ] + }, + { + "name": "Minutas", + "item": [ + { + "name": "GET", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code é 201 ou 200\", function () {\r", + " pm.expect(pm.response.code).to.be.oneOf([200, 201]);\r", + "});\r", + "\r", + "pm.test(\"Resposta contém ID ou confirmação\", function () {\r", + " const jsonData = pm.response.json();\r", + " pm.expect(jsonData).to.have.any.keys(\"id\", \"message\", \"status\");\r", + "});\r", + "\r", + "pm.test(\"Mensagem indica sucesso\", function () {\r", + " const jsonData = pm.response.json();\r", + " pm.expect(jsonData.message || \"\").to.match(/sucesso|criado|registrado/i);\r", + "});\r", + "" + ], + "type": "text/javascript", + "packages": {}, + "requests": {} + } + } + ], + "request": { + "auth": { + "type": "bearer", + "bearer": [ + { + "key": "token", + "value": "{{BearerToken}}", + "type": "string" + } + ] + }, + "method": "GET", + "header": [], + "url": { + "raw": "{{BaseUrlV1}}administrativo/t_minuta", + "host": [ + "{{BaseUrlV1}}administrativo" + ], + "path": [ + "t_minuta" + ] + } + }, + "response": [] + }, + { + "name": "POST", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "const response = pm.response.json();\r", + "\r", + "// Salvando em variáveis da *collection*\r", + "pm.collectionVariables.set(\"minutaId\", response.data.minuta_id);\r", + "\r", + "pm.test(\"Status code é 201 ou 200\", function () {\r", + " pm.expect(pm.response.code).to.be.oneOf([200, 201]);\r", + "});\r", + "\r", + "pm.test(\"Resposta contém ID ou confirmação\", function () {\r", + " const jsonData = pm.response.json();\r", + " pm.expect(jsonData).to.have.any.keys(\"id\", \"message\", \"status\");\r", + "});\r", + "\r", + "pm.test(\"Mensagem indica sucesso\", function () {\r", + " const jsonData = pm.response.json();\r", + " pm.expect(jsonData.message || \"\").to.match(/sucesso|criado|registrado/i);\r", + "});\r", + "" + ], + "type": "text/javascript", + "packages": {}, + "requests": {} + } + }, + { + "listen": "prerequest", + "script": { + "exec": [ + "" + ], + "type": "text/javascript", + "packages": {}, + "requests": {} + } + } + ], + "request": { + "auth": { + "type": "bearer", + "bearer": [ + { + "key": "token", + "value": "{{BearerToken}}", + "type": "string" + } + ] + }, + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\r\n \"ato_tipo_id\": {{AtoTipoId}},\r\n \"natureza_id\": {{AtoTipoId}},\r\n \"descricao\": \"{{$randomFullName}}\",\r\n \"texto\": \"TG9yZW0gSXBzdW0gaXMgc2ltcGx5IGR1bW15IHRleHQgb2YgdGhlIHByaW50aW5nIGFuZCB0eXBlc2V0dGluZyBpbmR1c3RyeS4gTG9yZW0gSXBzdW0gaGFzIGJlZW4gdGhlIGluZHVzdHJ5J3Mgc3RhbmRhcmQgZHVtbXkgdGV4dCBldmVyIHNpbmNlIHRoZSAxNTAwcywgd2hlbiBhbiB1bmtub3duIHByaW50ZXIgdG9vayBhIGdhbGxleSBvZiB0eXBlIGFuZCBzY3JhbWJsZWQgaXQgdG8gbWFrZSBhIHR5cGUgc3BlY2ltZW4gYm9vay4gSXQgaGFzIHN1cnZpdmVkIG5vdCBvbmx5IGZpdmUgY2VudHVyaWVzLCBidXQgYWxzbyB0aGUgbGVhcCBpbnRvIGVsZWN0cm9uaWMgdHlwZXNldHRpbmcsIHJlbWFpbmluZyBlc3NlbnRpYWxseSB1bmNoYW5nZWQuIEl0IHdhcyBwb3B1bGFyaXNlZCBpbiB0aGUgMTk2MHMgd2l0aCB0aGUgcmVsZWFzZSBvZiBMZXRyYXNldCBzaGVldHMgY29udGFpbmluZyBMb3JlbSBJcHN1bSBwYXNzYWdlcywgYW5kIG1vcmUgcmVjZW50bHkgd2l0aCBkZXNrdG9wIHB1Ymxpc2hpbmcgc29mdHdhcmUgbGlrZSBBbGR1cyBQYWdlTWFrZXIgaW5jbHVkaW5nIHZlcnNpb25zIG9mIExvcmVtIElwc3VtLg==\",\r\n \"protegida\": \"{{useEmail}}\",\r\n \"situacao\": \"{{status}}\"\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{BaseUrlV1}}administrativo/t_minuta", + "host": [ + "{{BaseUrlV1}}administrativo" + ], + "path": [ + "t_minuta" + ] + } + }, + "response": [] + }, + { + "name": "GET DESCRIÇÃO", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code é 201 ou 200\", function () {\r", + " pm.expect(pm.response.code).to.be.oneOf([200, 201]);\r", + "});\r", + "\r", + "pm.test(\"Resposta contém ID ou confirmação\", function () {\r", + " const jsonData = pm.response.json();\r", + " pm.expect(jsonData).to.have.any.keys(\"id\", \"message\", \"status\");\r", + "});\r", + "\r", + "pm.test(\"Mensagem indica sucesso\", function () {\r", + " const jsonData = pm.response.json();\r", + " pm.expect(jsonData.message || \"\").to.match(/sucesso|criado|registrado/i);\r", + "});\r", + "" + ], + "type": "text/javascript", + "packages": {}, + "requests": {} + } + } + ], + "protocolProfileBehavior": { + "disableBodyPruning": true + }, + "request": { + "auth": { + "type": "bearer", + "bearer": [ + { + "key": "token", + "value": "{{BearerToken}}", + "type": "string" + } + ] + }, + "method": "GET", + "header": [], + "body": { + "mode": "raw", + "raw": "" + }, + "url": { + "raw": "{{BaseUrlV1}}administrativo/t_minuta/descricao?descricao=PROCURAÇÃO AD JUDICIA", + "host": [ + "{{BaseUrlV1}}administrativo" + ], + "path": [ + "t_minuta", + "descricao" + ], + "query": [ + { + "key": "descricao", + "value": "PROCURAÇÃO AD JUDICIA" + } + ] + } + }, + "response": [] + }, + { + "name": "GET ID", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code é 201 ou 200\", function () {\r", + " pm.expect(pm.response.code).to.be.oneOf([200, 201]);\r", + "});\r", + "\r", + "pm.test(\"Resposta contém ID ou confirmação\", function () {\r", + " const jsonData = pm.response.json();\r", + " pm.expect(jsonData).to.have.any.keys(\"id\", \"message\", \"status\");\r", + "});\r", + "\r", + "pm.test(\"Mensagem indica sucesso\", function () {\r", + " const jsonData = pm.response.json();\r", + " pm.expect(jsonData.message || \"\").to.match(/sucesso|criado|registrado/i);\r", + "});\r", + "" + ], + "type": "text/javascript", + "packages": {}, + "requests": {} + } + } + ], + "request": { + "auth": { + "type": "bearer", + "bearer": [ + { + "key": "token", + "value": "{{BearerToken}}", + "type": "string" + } + ] + }, + "method": "GET", + "header": [], + "url": { + "raw": "{{BaseUrlV1}}administrativo/t_minuta/{{minutaId}}", + "host": [ + "{{BaseUrlV1}}administrativo" + ], + "path": [ + "t_minuta", + "{{minutaId}}" + ] + } + }, + "response": [] + }, + { + "name": "PUT", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code é 201 ou 200\", function () {\r", + " pm.expect(pm.response.code).to.be.oneOf([200, 201]);\r", + "});\r", + "\r", + "pm.test(\"Resposta contém ID ou confirmação\", function () {\r", + " const jsonData = pm.response.json();\r", + " pm.expect(jsonData).to.have.any.keys(\"id\", \"message\", \"status\");\r", + "});\r", + "\r", + "pm.test(\"Mensagem indica sucesso\", function () {\r", + " const jsonData = pm.response.json();\r", + " pm.expect(jsonData.message || \"\").to.match(/sucesso|criado|registrado/i);\r", + "});\r", + "" + ], + "type": "text/javascript", + "packages": {}, + "requests": {} + } + } + ], + "request": { + "auth": { + "type": "bearer", + "bearer": [ + { + "key": "token", + "value": "{{BearerToken}}", + "type": "string" + } + ] + }, + "method": "PUT", + "header": [], + "body": { + "mode": "raw", + "raw": "{\r\n \"descricao\": \"{{$randomFullName}}\",\r\n \"sigla\": \"{{login_aleatorio}}\"\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{BaseUrlV1}}administrativo/t_minuta/{{minutaId}}", + "host": [ + "{{BaseUrlV1}}administrativo" + ], + "path": [ + "t_minuta", + "{{minutaId}}" + ] + } + }, + "response": [] + }, + { + "name": "DELETE", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code é 201 ou 200\", function () {\r", + " pm.expect(pm.response.code).to.be.oneOf([200, 201]);\r", + "});\r", + "\r", + "pm.test(\"Resposta contém ID ou confirmação\", function () {\r", + " const jsonData = pm.response.json();\r", + " pm.expect(jsonData).to.have.any.keys(\"id\", \"message\", \"status\");\r", + "});\r", + "\r", + "pm.test(\"Mensagem indica sucesso\", function () {\r", + " const jsonData = pm.response.json();\r", + " pm.expect(jsonData.message || \"\").to.match(/sucesso|criado|registrado/i);\r", + "});\r", + "" + ], + "type": "text/javascript", + "packages": {}, + "requests": {} + } + } + ], + "request": { + "auth": { + "type": "bearer", + "bearer": [ + { + "key": "token", + "value": "{{BearerToken}}", + "type": "string" + } + ] + }, + "method": "DELETE", + "header": [], + "body": { + "mode": "raw", + "raw": "", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{BaseUrlV1}}administrativo/t_minuta/{{minutaId}}", + "host": [ + "{{BaseUrlV1}}administrativo" + ], + "path": [ + "t_minuta", + "{{minutaId}}" + ] + } + }, + "response": [] + } + ] + }, + { + "name": "Documento tipo", + "item": [ + { + "name": "GET", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code é 201 ou 200\", function () {\r", + " pm.expect(pm.response.code).to.be.oneOf([200, 201]);\r", + "});\r", + "\r", + "pm.test(\"Resposta contém ID ou confirmação\", function () {\r", + " const jsonData = pm.response.json();\r", + " pm.expect(jsonData).to.have.any.keys(\"id\", \"message\", \"status\");\r", + "});\r", + "\r", + "pm.test(\"Mensagem indica sucesso\", function () {\r", + " const jsonData = pm.response.json();\r", + " pm.expect(jsonData.message || \"\").to.match(/sucesso|criado|registrado/i);\r", + "});\r", + "" + ], + "type": "text/javascript", + "packages": {}, + "requests": {} + } + } + ], + "request": { + "auth": { + "type": "bearer", + "bearer": [ + { + "key": "token", + "value": "{{BearerToken}}", + "type": "string" + } + ] + }, + "method": "GET", + "header": [], + "url": { + "raw": "{{BaseUrlV1}}administrativo/g_tb_documentotipo", + "host": [ + "{{BaseUrlV1}}administrativo" + ], + "path": [ + "g_tb_documentotipo" + ] + } + }, + "response": [] + }, + { + "name": "POST", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "const response = pm.response.json();\r", + "\r", + "// Salvando em variáveis da *collection*\r", + "pm.collectionVariables.set(\"tBdocumentotipoId\", response.data.tb_documentotipo_id);\r", + "\r", + "pm.test(\"Status code é 201 ou 200\", function () {\r", + " pm.expect(pm.response.code).to.be.oneOf([200, 201]);\r", + "});\r", + "\r", + "pm.test(\"Resposta contém ID ou confirmação\", function () {\r", + " const jsonData = pm.response.json();\r", + " pm.expect(jsonData).to.have.any.keys(\"id\", \"message\", \"status\");\r", + "});\r", + "\r", + "pm.test(\"Mensagem indica sucesso\", function () {\r", + " const jsonData = pm.response.json();\r", + " pm.expect(jsonData.message || \"\").to.match(/sucesso|criado|registrado/i);\r", + "});\r", + "" + ], + "type": "text/javascript", + "packages": {}, + "requests": {} + } + }, + { + "listen": "prerequest", + "script": { + "exec": [ + "" + ], + "type": "text/javascript", + "packages": {}, + "requests": {} + } + } + ], + "request": { + "auth": { + "type": "bearer", + "bearer": [ + { + "key": "token", + "value": "{{BearerToken}}", + "type": "string" + } + ] + }, + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\r\n \"descricao\": \"{{$randomFullName}}\",\r\n \"texto\": \"TG9yZW0gSXBzdW0gaXMgc2ltcGx5IGR1bW15IHRleHQgb2YgdGhlIHByaW50aW5nIGFuZCB0eXBlc2V0dGluZyBpbmR1c3RyeS4gTG9yZW0gSXBzdW0gaGFzIGJlZW4gdGhlIGluZHVzdHJ5J3Mgc3RhbmRhcmQgZHVtbXkgdGV4dCBldmVyIHNpbmNlIHRoZSAxNTAwcywgd2hlbiBhbiB1bmtub3duIHByaW50ZXIgdG9vayBhIGdhbGxleSBvZiB0eXBlIGFuZCBzY3JhbWJsZWQgaXQgdG8gbWFrZSBhIHR5cGUgc3BlY2ltZW4gYm9vay4gSXQgaGFzIHN1cnZpdmVkIG5vdCBvbmx5IGZpdmUgY2VudHVyaWVzLCBidXQgYWxzbyB0aGUgbGVhcCBpbnRvIGVsZWN0cm9uaWMgdHlwZXNldHRpbmcsIHJlbWFpbmluZyBlc3NlbnRpYWxseSB1bmNoYW5nZWQuIEl0IHdhcyBwb3B1bGFyaXNlZCBpbiB0aGUgMTk2MHMgd2l0aCB0aGUgcmVsZWFzZSBvZiBMZXRyYXNldCBzaGVldHMgY29udGFpbmluZyBMb3JlbSBJcHN1bSBwYXNzYWdlcywgYW5kIG1vcmUgcmVjZW50bHkgd2l0aCBkZXNrdG9wIHB1Ymxpc2hpbmcgc29mdHdhcmUgbGlrZSBBbGR1cyBQYWdlTWFrZXIgaW5jbHVkaW5nIHZlcnNpb25zIG9mIExvcmVtIElwc3VtLg==\",\r\n \"situacao\": \"{{status}}\",\r\n \"possui_numeracao\": \"{{useEmail}}\",\r\n \"orgao_padrao\": \"SSPGO\",\r\n \"descricao_simplificada\": \"CNH\",\r\n \"tipo\": \"{{$randomFullName}}\",\r\n \"descricao_sinter\": \"{{$randomFullName}}\"\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{BaseUrlV1}}administrativo/g_tb_documentotipo", + "host": [ + "{{BaseUrlV1}}administrativo" + ], + "path": [ + "g_tb_documentotipo" + ] + } + }, + "response": [] + }, + { + "name": "GET DESCRIÇÃO", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code é 201 ou 200\", function () {\r", + " pm.expect(pm.response.code).to.be.oneOf([200, 201]);\r", + "});\r", + "\r", + "pm.test(\"Resposta contém ID ou confirmação\", function () {\r", + " const jsonData = pm.response.json();\r", + " pm.expect(jsonData).to.have.any.keys(\"id\", \"message\", \"status\");\r", + "});\r", + "\r", + "pm.test(\"Mensagem indica sucesso\", function () {\r", + " const jsonData = pm.response.json();\r", + " pm.expect(jsonData.message || \"\").to.match(/sucesso|criado|registrado/i);\r", + "});\r", + "" + ], + "type": "text/javascript", + "packages": {}, + "requests": {} + } + } + ], + "protocolProfileBehavior": { + "disableBodyPruning": true + }, + "request": { + "auth": { + "type": "bearer", + "bearer": [ + { + "key": "token", + "value": "{{BearerToken}}", + "type": "string" + } + ] + }, + "method": "GET", + "header": [], + "body": { + "mode": "raw", + "raw": "" + }, + "url": { + "raw": "{{BaseUrlV1}}administrativo/g_tb_documentotipo/descricao?descricao=E-TÍTULO", + "host": [ + "{{BaseUrlV1}}administrativo" + ], + "path": [ + "g_tb_documentotipo", + "descricao" + ], + "query": [ + { + "key": "descricao", + "value": "E-TÍTULO" + } + ] + } + }, + "response": [] + }, + { + "name": "GET ID", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code é 201 ou 200\", function () {\r", + " pm.expect(pm.response.code).to.be.oneOf([200, 201]);\r", + "});\r", + "\r", + "pm.test(\"Resposta contém ID ou confirmação\", function () {\r", + " const jsonData = pm.response.json();\r", + " pm.expect(jsonData).to.have.any.keys(\"id\", \"message\", \"status\");\r", + "});\r", + "\r", + "pm.test(\"Mensagem indica sucesso\", function () {\r", + " const jsonData = pm.response.json();\r", + " pm.expect(jsonData.message || \"\").to.match(/sucesso|criado|registrado/i);\r", + "});\r", + "" + ], + "type": "text/javascript", + "packages": {}, + "requests": {} + } + } + ], + "request": { + "auth": { + "type": "bearer", + "bearer": [ + { + "key": "token", + "value": "{{BearerToken}}", + "type": "string" + } + ] + }, + "method": "GET", + "header": [], + "url": { + "raw": "{{BaseUrlV1}}administrativo/g_tb_documentotipo/{{tBdocumentotipoId}}", + "host": [ + "{{BaseUrlV1}}administrativo" + ], + "path": [ + "g_tb_documentotipo", + "{{tBdocumentotipoId}}" + ] + } + }, + "response": [] + }, + { + "name": "PUT", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code é 201 ou 200\", function () {\r", + " pm.expect(pm.response.code).to.be.oneOf([200, 201]);\r", + "});\r", + "\r", + "pm.test(\"Resposta contém ID ou confirmação\", function () {\r", + " const jsonData = pm.response.json();\r", + " pm.expect(jsonData).to.have.any.keys(\"id\", \"message\", \"status\");\r", + "});\r", + "\r", + "pm.test(\"Mensagem indica sucesso\", function () {\r", + " const jsonData = pm.response.json();\r", + " pm.expect(jsonData.message || \"\").to.match(/sucesso|criado|registrado/i);\r", + "});\r", + "" + ], + "type": "text/javascript", + "packages": {}, + "requests": {} + } + } + ], + "request": { + "auth": { + "type": "bearer", + "bearer": [ + { + "key": "token", + "value": "{{BearerToken}}", + "type": "string" + } + ] + }, + "method": "PUT", + "header": [], + "body": { + "mode": "raw", + "raw": "{\r\n \"descricao\": \"{{$randomFullName}}\",\r\n \"texto\": \"TG9yZW0gSXBzdW0gaXMgc2ltcGx5IGR1bW15IHRleHQgb2YgdGhlIHByaW50aW5nIGFuZCB0eXBlc2V0dGluZyBpbmR1c3RyeS4gTG9yZW0gSXBzdW0gaGFzIGJlZW4gdGhlIGluZHVzdHJ5J3Mgc3RhbmRhcmQgZHVtbXkgdGV4dCBldmVyIHNpbmNlIHRoZSAxNTAwcywgd2hlbiBhbiB1bmtub3duIHByaW50ZXIgdG9vayBhIGdhbGxleSBvZiB0eXBlIGFuZCBzY3JhbWJsZWQgaXQgdG8gbWFrZSBhIHR5cGUgc3BlY2ltZW4gYm9vay4gSXQgaGFzIHN1cnZpdmVkIG5vdCBvbmx5IGZpdmUgY2VudHVyaWVzLCBidXQgYWxzbyB0aGUgbGVhcCBpbnRvIGVsZWN0cm9uaWMgdHlwZXNldHRpbmcsIHJlbWFpbmluZyBlc3NlbnRpYWxseSB1bmNoYW5nZWQuIEl0IHdhcyBwb3B1bGFyaXNlZCBpbiB0aGUgMTk2MHMgd2l0aCB0aGUgcmVsZWFzZSBvZiBMZXRyYXNldCBzaGVldHMgY29udGFpbmluZyBMb3JlbSBJcHN1bSBwYXNzYWdlcywgYW5kIG1vcmUgcmVjZW50bHkgd2l0aCBkZXNrdG9wIHB1Ymxpc2hpbmcgc29mdHdhcmUgbGlrZSBBbGR1cyBQYWdlTWFrZXIgaW5jbHVkaW5nIHZlcnNpb25zIG9mIExvcmVtIElwc3VtLg==\",\r\n \"situacao\": \"{{status}}\",\r\n \"possui_numeracao\": \"{{useEmail}}\",\r\n \"orgao_padrao\": \"SSPGO\",\r\n \"descricao_simplificada\": \"CNH\",\r\n \"tipo\": \"{{$randomFullName}}\",\r\n \"descricao_sinter\": \"{{$randomFullName}}\"\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{BaseUrlV1}}administrativo/g_tb_documentotipo/{{tBdocumentotipoId}}", + "host": [ + "{{BaseUrlV1}}administrativo" + ], + "path": [ + "g_tb_documentotipo", + "{{tBdocumentotipoId}}" + ] + } + }, + "response": [] + }, + { + "name": "DELETE", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code é 201 ou 200\", function () {\r", + " pm.expect(pm.response.code).to.be.oneOf([200, 201]);\r", + "});\r", + "\r", + "pm.test(\"Resposta contém ID ou confirmação\", function () {\r", + " const jsonData = pm.response.json();\r", + " pm.expect(jsonData).to.have.any.keys(\"id\", \"message\", \"status\");\r", + "});\r", + "\r", + "pm.test(\"Mensagem indica sucesso\", function () {\r", + " const jsonData = pm.response.json();\r", + " pm.expect(jsonData.message || \"\").to.match(/sucesso|criado|registrado/i);\r", + "});\r", + "" + ], + "type": "text/javascript", + "packages": {}, + "requests": {} + } + } + ], + "request": { + "auth": { + "type": "bearer", + "bearer": [ + { + "key": "token", + "value": "{{BearerToken}}", + "type": "string" + } + ] + }, + "method": "DELETE", + "header": [], + "body": { + "mode": "raw", + "raw": "", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{BaseUrlV1}}administrativo/g_tb_documentotipo/{{tBdocumentotipoId}}", + "host": [ + "{{BaseUrlV1}}administrativo" + ], + "path": [ + "g_tb_documentotipo", + "{{tBdocumentotipoId}}" + ] + } + }, + "response": [] + } + ] + }, { "name": "Andamento Serviço", "item": [ @@ -6040,6 +7190,7 @@ "script": { "type": "text/javascript", "packages": {}, + "requests": {}, "exec": [ "// Lista de valores possíveis\r", "const statusList = [\"A\", \"I\"];\r", @@ -6182,7 +7333,17 @@ "const randOnrTipoLogradouroId = onrTipoLogradouroList[Math.floor(Math.random() * onrTipoLogradouroList.length)];\r", "\r", "// Armazena como variável da collection\r", - "pm.collectionVariables.set(\"onrTipoLogradouroId\", randOnrTipoLogradouroId);" + "pm.collectionVariables.set(\"onrTipoLogradouroId\", randOnrTipoLogradouroId);\r", + "\r", + "\r", + "// Lista de valores possíveis\r", + "const atoTipoId = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20];\r", + "\r", + "// Escolhe um valor aleatório\r", + "const randAtoTipoId = atoTipoId[Math.floor(Math.random() * atoTipoId.length)];\r", + "\r", + "// Armazena como variável da collection\r", + "pm.collectionVariables.set(\"AtoTipoId\", randAtoTipoId);" ] } }, @@ -6191,6 +7352,7 @@ "script": { "type": "text/javascript", "packages": {}, + "requests": {}, "exec": [ "" ] @@ -6304,12 +7466,28 @@ }, { "key": "tBestadoCivilid", - "value": "", - "type": "default" + "value": "" }, { "key": "tBestadoCivilId", "value": "" + }, + { + "key": "medidaTipoId", + "value": "" + }, + { + "key": "AtoTipoId", + "value": "" + }, + { + "key": "minutaId", + "value": "" + }, + { + "key": "tBdocumentotipoId", + "value": "", + "type": "default" } ] } \ No newline at end of file diff --git a/packages/v1/administrativo/actions/g_tb_documentotipo/g_tb_documentotipo_delete_action.py b/packages/v1/administrativo/actions/g_tb_documentotipo/g_tb_documentotipo_delete_action.py new file mode 100644 index 0000000..35c22e9 --- /dev/null +++ b/packages/v1/administrativo/actions/g_tb_documentotipo/g_tb_documentotipo_delete_action.py @@ -0,0 +1,26 @@ +from abstracts.action import BaseAction +from packages.v1.administrativo.schemas.g_tb_documentotipo_schema import GTbDocumentoTipoIdSchema +from packages.v1.administrativo.repositories.g_tb_documentotipo.g_tb_documentotipo_delete_repository import DeleteRepository + + +class DeleteAction(BaseAction): + """ + Serviço responsável por encapsular a lógica de negócio para a operação + de exclusão de um registro na tabela g_tb_documentotipo. + """ + + def execute(self, documento_tipo_schema: GTbDocumentoTipoIdSchema): + """ + Executa a operação de exclusão no banco de dados. + + Args: + documento_tipo_schema (GTbDocumentoTipoIdSchema): O esquema com o ID a ser excluído. + + Returns: + O resultado da operação de exclusão. + """ + # Instanciamento do repositório + delete_repository = DeleteRepository() + + # Execução do repositório + return delete_repository.execute(documento_tipo_schema) \ No newline at end of file diff --git a/packages/v1/administrativo/actions/g_tb_documentotipo/g_tb_documentotipo_get_by_descricao_action.py b/packages/v1/administrativo/actions/g_tb_documentotipo/g_tb_documentotipo_get_by_descricao_action.py new file mode 100644 index 0000000..2ea7cd6 --- /dev/null +++ b/packages/v1/administrativo/actions/g_tb_documentotipo/g_tb_documentotipo_get_by_descricao_action.py @@ -0,0 +1,29 @@ +from abstracts.action import BaseAction +from packages.v1.administrativo.schemas.g_tb_documentotipo_schema import GTbDocumentoTipoDescricaoSchema +from packages.v1.administrativo.repositories.g_tb_documentotipo.g_tb_documentotipo_get_by_descricao_repository import GetByDescricaoRepository + + +class GetByDescricaoAction(BaseAction): + """ + Serviço responsável por encapsular a lógica de negócio para a operação + de busca de um registro na tabela g_tb_documentotipo por descrição. + """ + + def execute(self, documento_tipo_schema: GTbDocumentoTipoDescricaoSchema): + """ + Executa a operação de busca no banco de dados. + + Args: + documento_tipo_schema (GTbDocumentoTipoDescricaoSchema): O esquema com a descrição a ser buscada. + + Returns: + O registro encontrado ou None. + """ + # Instanciamento do repositório + show_repository = GetByDescricaoRepository() + + # Execução do repositório + response = show_repository.execute(documento_tipo_schema) + + # Retorno da informação + return response \ No newline at end of file diff --git a/packages/v1/administrativo/actions/g_tb_documentotipo/g_tb_documentotipo_index_action.py b/packages/v1/administrativo/actions/g_tb_documentotipo/g_tb_documentotipo_index_action.py new file mode 100644 index 0000000..77ca305 --- /dev/null +++ b/packages/v1/administrativo/actions/g_tb_documentotipo/g_tb_documentotipo_index_action.py @@ -0,0 +1,24 @@ +from abstracts.action import BaseAction +from packages.v1.administrativo.repositories.g_tb_documentotipo.g_tb_documentotipo_index_repository import IndexRepository + +class IndexAction(BaseAction): + """ + Serviço responsável por encapsular a lógica de negócio para a operação + de listagem de todos os registros na tabela g_tb_documentotipo. + """ + + def execute(self): + """ + Executa a operação de listagem no banco de dados. + + Returns: + A lista de todos os registros. + """ + # Instanciamento do repositório + index_repository = IndexRepository() + + # Execução do repositório + response = index_repository.execute() + + # Retorno da informação + return response \ No newline at end of file diff --git a/packages/v1/administrativo/actions/g_tb_documentotipo/g_tb_documentotipo_save_action.py b/packages/v1/administrativo/actions/g_tb_documentotipo/g_tb_documentotipo_save_action.py new file mode 100644 index 0000000..ffd8891 --- /dev/null +++ b/packages/v1/administrativo/actions/g_tb_documentotipo/g_tb_documentotipo_save_action.py @@ -0,0 +1,28 @@ +from abstracts.action import BaseAction +from packages.v1.administrativo.schemas.g_tb_documentotipo_schema import GTbDocumentoTipoSaveSchema +from packages.v1.administrativo.repositories.g_tb_documentotipo.g_tb_documentotipo_save_repository import SaveRepository + +class SaveAction(BaseAction): + """ + Serviço responsável por encapsular a lógica de negócio para a operação + de salvar um novo registro na tabela g_tb_documentotipo. + """ + + def execute(self, documento_tipo_schema: GTbDocumentoTipoSaveSchema): + """ + Executa a operação de salvamento. + + Args: + documento_tipo_schema (GTbDocumentoTipoSaveSchema): O esquema com os dados a serem salvos. + + Returns: + O resultado da operação de salvamento. + """ + # Instanciamento do repositório + save_repository = SaveRepository() + + # Execução do repositório + response = save_repository.execute(documento_tipo_schema) + + # Retorno da informação + return response \ No newline at end of file diff --git a/packages/v1/administrativo/actions/g_tb_documentotipo/g_tb_documentotipo_show_action.py b/packages/v1/administrativo/actions/g_tb_documentotipo/g_tb_documentotipo_show_action.py new file mode 100644 index 0000000..2c15427 --- /dev/null +++ b/packages/v1/administrativo/actions/g_tb_documentotipo/g_tb_documentotipo_show_action.py @@ -0,0 +1,28 @@ +from abstracts.action import BaseAction +from packages.v1.administrativo.schemas.g_tb_documentotipo_schema import GTbDocumentoTipoIdSchema +from packages.v1.administrativo.repositories.g_tb_documentotipo.g_tb_documentotipo_show_repository import ShowRepository + +class ShowAction(BaseAction): + """ + Serviço responsável por encapsular a lógica de negócio para a exibição + de um registro na tabela g_tb_documentotipo. + """ + + def execute(self, documento_tipo_schema: GTbDocumentoTipoIdSchema): + """ + Executa a operação de exibição. + + Args: + documento_tipo_schema (GTbDocumentoTipoIdSchema): O esquema com o ID do registro a ser exibido. + + Returns: + O resultado da operação de exibição. + """ + # Instanciamento do repositório + show_repository = ShowRepository() + + # Execução do repositório + response = show_repository.execute(documento_tipo_schema) + + # Retorno da informação + return response \ No newline at end of file diff --git a/packages/v1/administrativo/actions/g_tb_documentotipo/g_tb_documentotipo_update_action.py b/packages/v1/administrativo/actions/g_tb_documentotipo/g_tb_documentotipo_update_action.py new file mode 100644 index 0000000..5177ea9 --- /dev/null +++ b/packages/v1/administrativo/actions/g_tb_documentotipo/g_tb_documentotipo_update_action.py @@ -0,0 +1,26 @@ +from packages.v1.administrativo.schemas.g_tb_documentotipo_schema import GTbDocumentoTipoUpdateSchema +from packages.v1.administrativo.repositories.g_tb_documentotipo.g_tb_documentotipo_update_repository import UpdateRepository + + +class UpdateAction: + """ + Service responsável por encapsular a lógica de negócio para a atualização + de um registro na tabela g_tb_documentotipo. + """ + + def execute(self, documento_tipo_id: int, documento_tipo_schema: GTbDocumentoTipoUpdateSchema): + """ + Executa a operação de atualização. + + Args: + documento_tipo_id (int): O ID do registro a ser atualizado. + documento_tipo_schema (GTbDocumentoTipoUpdateSchema): O esquema com os dados a serem atualizados. + + Returns: + O resultado da operação de atualização. + """ + # Instância o repositório de atualização + update_repository = UpdateRepository() + + # Chama o método de execução do repositório para realizar a atualização + return update_repository.execute(documento_tipo_id, documento_tipo_schema) \ No newline at end of file diff --git a/packages/v1/administrativo/controllers/g_tb_documentotipo_controller.py b/packages/v1/administrativo/controllers/g_tb_documentotipo_controller.py new file mode 100644 index 0000000..b39d9cd --- /dev/null +++ b/packages/v1/administrativo/controllers/g_tb_documentotipo_controller.py @@ -0,0 +1,113 @@ +from actions.dynamic_import.dynamic_import import DynamicImport +from packages.v1.administrativo.schemas.g_tb_documentotipo_schema import ( + GTbDocumentoTipoSchema, + GTbDocumentoTipoSaveSchema, + GTbDocumentoTipoUpdateSchema, + GTbDocumentoTipoIdSchema, + GTbDocumentoTipoDescricaoSchema +) + +class GTbDocumentoTipoController: + + def __init__(self): + # Action responsável por carregar as services de acordo com o estado + self.dynamic_import = DynamicImport() + + # Define o pacote que deve ser carregado + self.dynamic_import.set_package("administrativo") + + # Define a tabela que o pacote pertence + self.dynamic_import.set_table("g_tb_documentotipo") + pass + + # Lista todos os registros de documento_tipo + def index(self): + + # Importação da classe desejada + indexService = self.dynamic_import.service("g_tb_documentotipo_index_service", "IndexService") + + # Instância da classe service + self.indexService = indexService() + + # Lista todos os registros de documento_tipo + return { + 'message': 'Registros de documento_tipo localizados com sucesso', + 'data': self.indexService.execute() + } + + + # Busca um registro de documento_tipo específico pelo ID + def show(self, documento_tipo_schema: GTbDocumentoTipoIdSchema): + + #Importação da classe desejada + show_service = self.dynamic_import.service('g_tb_documentotipo_show_service', 'ShowService') + + # Instância da classe desejada + self.show_service = show_service() + + # Busca e retorna o registro de documento_tipo desejado + return { + 'message': 'Registro de documento_tipo localizado com sucesso', + 'data': self.show_service.execute(documento_tipo_schema) + } + + + # Busca um registro de documento_tipo pela descrição + def get_by_descricao(self, documento_tipo_schema: GTbDocumentoTipoDescricaoSchema): + + #Importação da classe desejada + show_service = self.dynamic_import.service('g_tb_documentotipo_get_by_descricao_service', 'GetByDescricaoService') + + # Instância da classe desejada + self.show_service = show_service() + + # Busca e retorna o registro de documento_tipo desejado + return { + 'message': 'Registro de documento_tipo localizado com sucesso', + 'data': self.show_service.execute(documento_tipo_schema, True) + } + + + # Cadastra um novo registro de documento_tipo + def save(self, documento_tipo_schema: GTbDocumentoTipoSaveSchema): + + #Importação da classe desejada + save_service = self.dynamic_import.service('g_tb_documentotipo_save_service', 'SaveService') + + # Instância da classe desejada + self.save_service = save_service() + # Busca e retorna o registro de documento_tipo desejado + return { + 'message': 'Registro de documento_tipo salvo com sucesso', + 'data': self.save_service.execute(documento_tipo_schema) + } + + # Atualiza os dados de um registro de documento_tipo + def update(self, documento_tipo_id: int, documento_tipo_schema: GTbDocumentoTipoUpdateSchema): + + #Importação da classe desejada + update_service = self.dynamic_import.service('g_tb_documentotipo_update_service', 'UpdateService') + + # Instância da classe desejada + self.update_service = update_service() + + # Busca e retorna o registro de documento_tipo desejado + return { + 'message': 'Registro de documento_tipo atualizado com sucesso', + 'data': self.update_service.execute(documento_tipo_id, documento_tipo_schema) + } + + # Exclui um registro de documento_tipo + def delete(self, documento_tipo_schema: GTbDocumentoTipoIdSchema): + + #Importação da classe desejada + delete_service = self.dynamic_import.service('g_tb_documentotipo_delete_service', 'DeleteService') + + # Instância da classe desejada + self.delete_service = delete_service() + + # Busca e retorna o registro de documento_tipo desejado + return { + 'message': 'Registro de documento_tipo removido com sucesso', + 'data': self.delete_service.execute(documento_tipo_schema) + } \ No newline at end of file diff --git a/packages/v1/administrativo/endpoints/g_tb_documentotipo_endpoint.py b/packages/v1/administrativo/endpoints/g_tb_documentotipo_endpoint.py new file mode 100644 index 0000000..08751f4 --- /dev/null +++ b/packages/v1/administrativo/endpoints/g_tb_documentotipo_endpoint.py @@ -0,0 +1,108 @@ +# Importação de bibliotecas +from typing import Optional +from fastapi import APIRouter, Body, Depends, status +from actions.jwt.get_current_user import get_current_user +from packages.v1.administrativo.controllers.g_tb_documentotipo_controller import GTbDocumentoTipoController +from packages.v1.administrativo.schemas.g_tb_documentotipo_schema import ( + GTbDocumentoTipoSchema, + GTbDocumentoTipoSaveSchema, + GTbDocumentoTipoUpdateSchema, + GTbDocumentoTipoIdSchema +) + +# Inicializa o roteador para as rotas do tipo de reconhecimento +router = APIRouter() + +# Instanciamento do controller desejado +g_tb_documentotipo_controller = GTbDocumentoTipoController() + +# Lista todos os registros de g_tb_documentotipo +@router.get('/', + status_code=status.HTTP_200_OK, + summary='Lista todos os registros de g_tb_documentotipo cadastrados', + response_description='Lista todos os registros de g_tb_documentotipo cadastrados') +async def index(current_user: dict = Depends(get_current_user)): + + # Busca todos os registros de g_tb_documentotipo cadastrados + response = g_tb_documentotipo_controller.index() + + # Retorna os dados localizados + return response + + +# Localiza um registro de g_tb_documentotipo pela descrição +@router.get('/descricao', + status_code=status.HTTP_200_OK, + summary='Busca um registro de g_tb_documentotipo em específico pela descrição', + response_description='Busca um registro de g_tb_documentotipo em específico') +async def get_by_descricao(descricao : str, current_user: dict = Depends(get_current_user)): + + # Cria o schema com os dados recebidos + documento_tipo_schema = GTbDocumentoTipoSchema(descricao=descricao) + + # Busca um registro de g_tb_documentotipo específico pela descrição + response = g_tb_documentotipo_controller.get_by_descricao(documento_tipo_schema) + + # Retorna os dados localizados + return response + + +# Localiza um registro de g_tb_documentotipo pelo ID +@router.get('/{tb_documentotipo_id}', + status_code=status.HTTP_200_OK, + summary='Busca um registro de g_tb_documentotipo em específico pelo ID', + response_description='Busca um registro de g_tb_documentotipo em específico') +async def show(tb_documentotipo_id : int, current_user: dict = Depends(get_current_user)): + + # Cria o schema com os dados recebidos + documento_tipo_schema = GTbDocumentoTipoIdSchema(tb_documentotipo_id=tb_documentotipo_id) + + # Busca um registro de g_tb_documentotipo específico pelo ID + response = g_tb_documentotipo_controller.show(documento_tipo_schema) + + # Retorna os dados localizados + return response + + +# Cadastro de registro de g_tb_documentotipo +@router.post('/', + status_code=status.HTTP_201_CREATED, + summary='Cadastra um registro de g_tb_documentotipo', + response_description='Cadastra um registro de g_tb_documentotipo') +async def save(documento_tipo_schema: GTbDocumentoTipoSaveSchema, current_user: dict = Depends(get_current_user)): + + # Efetua o cadastro no banco de dados + response = g_tb_documentotipo_controller.save(documento_tipo_schema) + + # Retorna os dados localizados + return response + + +# Atualiza os dados de um registro de g_tb_documentotipo +@router.put('/{tb_documentotipo_id}', + status_code=status.HTTP_200_OK, + summary='Atualiza um registro de g_tb_documentotipo', + response_description='Atualiza um registro de g_tb_documentotipo') +async def update(tb_documentotipo_id: int, documento_tipo_schema: GTbDocumentoTipoUpdateSchema, current_user: dict = Depends(get_current_user)): + + # Efetua a atualização dos dados + response = g_tb_documentotipo_controller.update(tb_documentotipo_id, documento_tipo_schema) + + # Retorna os dados localizados + return response + +# Exclui um determinado registro de g_tb_documentotipo +@router.delete('/{tb_documentotipo_id}', + status_code=status.HTTP_200_OK, + summary='Remove um registro de g_tb_documentotipo', + response_description='Remove um registro de g_tb_documentotipo') +async def delete(tb_documentotipo_id: int, current_user: dict = Depends(get_current_user)): + + # Cria o schema com os dados recebidos + documento_tipo_schema = GTbDocumentoTipoIdSchema(tb_documentotipo_id=tb_documentotipo_id) + + # Efetua a exclusão do registro de g_tb_documentotipo + response = g_tb_documentotipo_controller.delete(documento_tipo_schema) + + # Retorna os dados localizados + return response \ No newline at end of file diff --git a/packages/v1/administrativo/repositories/g_tb_documentotipo/g_tb_documentotipo_delete_repository.py b/packages/v1/administrativo/repositories/g_tb_documentotipo/g_tb_documentotipo_delete_repository.py new file mode 100644 index 0000000..08eb085 --- /dev/null +++ b/packages/v1/administrativo/repositories/g_tb_documentotipo/g_tb_documentotipo_delete_repository.py @@ -0,0 +1,41 @@ +from abstracts.repository import BaseRepository +from packages.v1.administrativo.schemas.g_tb_documentotipo_schema import GTbDocumentoTipoIdSchema +from fastapi import HTTPException, status + +class DeleteRepository(BaseRepository): + """ + Repositório para a operação de exclusão de um registro na tabela + g_tb_documentotipo. + """ + + def execute(self, documento_tipo_schema: GTbDocumentoTipoIdSchema): + """ + Executa a consulta SQL para remover um registro pelo ID. + + Args: + documento_tipo_schema (GTbDocumentoTipoIdSchema): O esquema com o ID a ser removido. + + Returns: + O resultado da operação de exclusão. + """ + try: + # Montagem do sql + sql = """ DELETE FROM G_TB_DOCUMENTOTIPO WHERE TB_DOCUMENTOTIPO_ID = :tb_documentotipo_id """ + + # Preenchimento de parâmetros + params = { + "tb_documentotipo_id": documento_tipo_schema.tb_documentotipo_id + } + + # Execução do sql + response = self.run(sql, params) + + # Retorna o resultado + return response + + except Exception as e: + # Informa que houve uma falha na exclusão + raise HTTPException( + status_code=status.HTTP_422_UNPROCESSABLE_ENTITY, + detail=f"Erro ao excluir DOCUMENTOTIPO: {e}" + ) \ No newline at end of file diff --git a/packages/v1/administrativo/repositories/g_tb_documentotipo/g_tb_documentotipo_get_by_descricao_repository.py b/packages/v1/administrativo/repositories/g_tb_documentotipo/g_tb_documentotipo_get_by_descricao_repository.py new file mode 100644 index 0000000..6eefc8f --- /dev/null +++ b/packages/v1/administrativo/repositories/g_tb_documentotipo/g_tb_documentotipo_get_by_descricao_repository.py @@ -0,0 +1,37 @@ +from abstracts.repository import BaseRepository +from packages.v1.administrativo.schemas.g_tb_documentotipo_schema import GTbDocumentoTipoDescricaoSchema + +class GetByDescricaoRepository(BaseRepository): + """ + Repositório para a operação de busca de um registro na tabela + g_tb_documentotipo por descrição. + """ + + def execute(self, documento_tipo_schema: GTbDocumentoTipoDescricaoSchema): + """ + Executa a consulta SQL para buscar um registro pela descrição. + + Args: + documento_tipo_schema (GTbDocumentoTipoDescricaoSchema): O esquema com a descrição a ser buscada. + + Returns: + Um dicionário contendo os dados do registro ou None se não for encontrado. + """ + # Montagem do SQL + sql = """ SELECT TB_DOCUMENTOTIPO_ID, + DESCRICAO, + SITUACAO, + POSSUI_NUMERACAO, + ORGAO_PADRAO, + DESCRICAO_SIMPLIFICADA, + TIPO, + DESCRICAO_SINTER + FROM G_TB_DOCUMENTOTIPO WHERE DESCRICAO = :descricao """ + + # Preenchimento de parâmetros + params = { + 'descricao': documento_tipo_schema.descricao + } + + # Execução do sql + return self.fetch_one(sql, params) \ No newline at end of file diff --git a/packages/v1/administrativo/repositories/g_tb_documentotipo/g_tb_documentotipo_index_repository.py b/packages/v1/administrativo/repositories/g_tb_documentotipo/g_tb_documentotipo_index_repository.py new file mode 100644 index 0000000..f23cf8b --- /dev/null +++ b/packages/v1/administrativo/repositories/g_tb_documentotipo/g_tb_documentotipo_index_repository.py @@ -0,0 +1,31 @@ +from abstracts.repository import BaseRepository + +class IndexRepository(BaseRepository): + """ + Repositório para a operação de listagem de todos os registros + na tabela G_TB_DOCUMENTOTIPO. + """ + + def execute(self): + """ + Executa a consulta SQL para buscar todos os registros. + + Returns: + Uma lista de dicionários contendo os dados dos registros. + """ + # Montagem do SQL + sql = """ SELECT TB_DOCUMENTOTIPO_ID, + DESCRICAO, + SITUACAO, + POSSUI_NUMERACAO, + ORGAO_PADRAO, + DESCRICAO_SIMPLIFICADA, + TIPO, + DESCRICAO_SINTER + FROM G_TB_DOCUMENTOTIPO """ + + # Execução do sql + response = self.fetch_all(sql) + + # Retorna os dados localizados + return response \ No newline at end of file diff --git a/packages/v1/administrativo/repositories/g_tb_documentotipo/g_tb_documentotipo_save_repository.py b/packages/v1/administrativo/repositories/g_tb_documentotipo/g_tb_documentotipo_save_repository.py new file mode 100644 index 0000000..220c44f --- /dev/null +++ b/packages/v1/administrativo/repositories/g_tb_documentotipo/g_tb_documentotipo_save_repository.py @@ -0,0 +1,71 @@ +from fastapi import HTTPException, status +from abstracts.repository import BaseRepository +from packages.v1.administrativo.schemas.g_tb_documentotipo_schema import GTbDocumentoTipoSaveSchema + + +class SaveRepository(BaseRepository): + """ + Repositório para a operação de salvamento de um novo registro na tabela G_TB_DOCUMENTOTIPO. + """ + + def execute(self, documentotipo_schema: GTbDocumentoTipoSaveSchema): + """ + Executa a operação de salvamento no banco de dados. + + Args: + documentotipo_schema (GtbDocumentotipoSaveSchema): O esquema com os dados a serem salvos. + + Returns: + O registro recém-criado. + + Raises: + HTTPException: Caso ocorra um erro na execução da query. + """ + try: + + # Montagem do SQL + sql = """ INSERT INTO G_TB_DOCUMENTOTIPO( + TB_DOCUMENTOTIPO_ID, + DESCRICAO, + TEXTO, + SITUACAO, + POSSUI_NUMERACAO, + ORGAO_PADRAO, + DESCRICAO_SIMPLIFICADA, + TIPO, + DESCRICAO_SINTER + ) VALUES ( + :tb_documentotipo_id, + :descricao, + :texto, + :situacao, + :possui_numeracao, + :orgao_padrao, + :descricao_simplificada, + :tipo, + :descricao_sinter + ) RETURNING *;""" + + # Preenchimento de parâmetros + params = { + 'tb_documentotipo_id': documentotipo_schema.tb_documentotipo_id, + 'descricao': documentotipo_schema.descricao, + 'texto': documentotipo_schema.texto, + 'situacao': documentotipo_schema.situacao, + 'possui_numeracao': documentotipo_schema.possui_numeracao, + 'orgao_padrao': documentotipo_schema.orgao_padrao, + 'descricao_simplificada': documentotipo_schema.descricao_simplificada, + 'tipo': documentotipo_schema.tipo, + 'descricao_sinter': documentotipo_schema.descricao_sinter + } + + # Execução do sql + return self.run_and_return(sql, params) + + except Exception as e: + + # Informa que houve uma falha no salvamento do registro + raise HTTPException( + status_code=status.HTTP_422_UNPROCESSABLE_ENTITY, + detail=f"Erro ao salvar G_TB_DOCUMENTOTIPO: {e}" + ) \ No newline at end of file diff --git a/packages/v1/administrativo/repositories/g_tb_documentotipo/g_tb_documentotipo_show_repository.py b/packages/v1/administrativo/repositories/g_tb_documentotipo/g_tb_documentotipo_show_repository.py new file mode 100644 index 0000000..0aa1a63 --- /dev/null +++ b/packages/v1/administrativo/repositories/g_tb_documentotipo/g_tb_documentotipo_show_repository.py @@ -0,0 +1,46 @@ +from abstracts.repository import BaseRepository +from packages.v1.administrativo.schemas.g_tb_documentotipo_schema import GTbDocumentoTipoIdSchema +from fastapi import HTTPException, status + +class ShowRepository(BaseRepository): + """ + Repositório para a operação de exibição de um registro na tabela G_TB_DOCUMENTOTIPO. + """ + + def execute(self, documentotipo_schema: GTbDocumentoTipoIdSchema): + """ + Busca um registro específico de G_TB_DOCUMENTOTIPO pelo ID. + + Args: + documentotipo_schema (GtbDocumentotipoIdSchema): O esquema que contém o ID do registro. + + Returns: + O registro encontrado ou None se não existir. + + Raises: + HTTPException: Caso ocorra um erro na execução da query. + """ + try: + # Montagem do SQL + sql = "SELECT * FROM G_TB_DOCUMENTOTIPO WHERE TB_DOCUMENTOTIPO_ID = :tb_documentotipo_id" + + # Preenchimento de parâmetros + params = { + 'tb_documentotipo_id': documentotipo_schema.tb_documentotipo_id + } + + # Execução do SQL + result = self.fetch_one(sql, params) + + if not result: + raise HTTPException( + status_code=status.HTTP_404_NOT_FOUND, + detail="Registro não encontrado" + ) + + return result + except Exception as e: + raise HTTPException( + status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, + detail=f"Erro ao buscar registro: {str(e)}" + ) \ No newline at end of file diff --git a/packages/v1/administrativo/repositories/g_tb_documentotipo/g_tb_documentotipo_update_repository.py b/packages/v1/administrativo/repositories/g_tb_documentotipo/g_tb_documentotipo_update_repository.py new file mode 100644 index 0000000..38f1498 --- /dev/null +++ b/packages/v1/administrativo/repositories/g_tb_documentotipo/g_tb_documentotipo_update_repository.py @@ -0,0 +1,85 @@ +from abstracts.repository import BaseRepository +from packages.v1.administrativo.schemas.g_tb_documentotipo_schema import GTbDocumentoTipoUpdateSchema +from fastapi import HTTPException, status + +class UpdateRepository(BaseRepository): + """ + Repositório para a operação de atualização na tabela G_TB_DOCUMENTOTIPO. + """ + + def execute(self, tb_documentotipo_id: int, documentotipo_schema: GTbDocumentoTipoUpdateSchema): + """ + Executa a atualização de um registro na tabela. + + Args: + tb_documentotipo_id (int): O ID do registro a ser atualizado. + documentotipo_schema (GtbDocumentotipoUpdateSchema): O esquema com os dados a serem atualizados. + + Returns: + O registro atualizado. + + Raises: + HTTPException: Se o registro não for encontrado ou ocorrer um erro na atualização. + """ + try: + updates = [] + params = {} + + if documentotipo_schema.descricao is not None: + updates.append("DESCRICAO = :descricao") + params["descricao"] = documentotipo_schema.descricao + + if documentotipo_schema.texto is not None: + updates.append("TEXTO = :texto") + params["texto"] = documentotipo_schema.texto + + if documentotipo_schema.situacao is not None: + updates.append("SITUACAO = :situacao") + params["situacao"] = documentotipo_schema.situacao + + if documentotipo_schema.possui_numeracao is not None: + updates.append("POSSUI_NUMERACAO = :possui_numeracao") + params["possui_numeracao"] = documentotipo_schema.possui_numeracao + + if documentotipo_schema.orgao_padrao is not None: + updates.append("ORGAO_PADRAO = :orgao_padrao") + params["orgao_padrao"] = documentotipo_schema.orgao_padrao + + if documentotipo_schema.descricao_simplificada is not None: + updates.append("DESCRICAO_SIMPLIFICADA = :descricao_simplificada") + params["descricao_simplificada"] = documentotipo_schema.descricao_simplificada + + if documentotipo_schema.tipo is not None: + updates.append("TIPO = :tipo") + params["tipo"] = documentotipo_schema.tipo + + if documentotipo_schema.descricao_sinter is not None: + updates.append("DESCRICAO_SINTER = :descricao_sinter") + params["descricao_sinter"] = documentotipo_schema.descricao_sinter + + if not updates: + return False + + params["tb_documentotipo_id"] = tb_documentotipo_id + sql = f"UPDATE G_TB_DOCUMENTOTIPO SET {', '.join(updates)} WHERE TB_DOCUMENTOTIPO_ID = :tb_documentotipo_id RETURNING *;" + + # Executa a query + result = self.run_and_return(sql, params) + + if not result: + # Informa que não existe o registro a ser modificado + raise HTTPException( + status_code=status.HTTP_422_UNPROCESSABLE_ENTITY, + detail='Nenhum G_TB_DOCUMENTOTIPO localizado para esta solicitação' + ) + + # Se houver um resultado, a atualização foi bem-sucedida + if result: + return result + + except Exception as e: + # Informa que houve uma falha na atualização + raise HTTPException( + status_code=status.HTTP_422_UNPROCESSABLE_ENTITY, + detail=f"Erro ao atualizar o G_TB_DOCUMENTOTIPO: {e}" + ) \ No newline at end of file diff --git a/packages/v1/administrativo/schemas/g_tb_documentotipo_schema.py b/packages/v1/administrativo/schemas/g_tb_documentotipo_schema.py new file mode 100644 index 0000000..4dcd63f --- /dev/null +++ b/packages/v1/administrativo/schemas/g_tb_documentotipo_schema.py @@ -0,0 +1,148 @@ +from pydantic import BaseModel, field_validator, model_validator +from fastapi import HTTPException, status +from typing import Optional + +# Funções para sanitização de entradas (evitar XSS, SQLi etc.) +from actions.validations.text import Text + +# ---------------------------------------------------- +# Schema base +# ---------------------------------------------------- +class GTbDocumentoTipoSchema(BaseModel): + tb_documentotipo_id: Optional[int] = None + descricao: Optional[str] = None + texto: Optional[bytes] = None + situacao: Optional[str] = None + possui_numeracao: Optional[str] = None + orgao_padrao: Optional[str] = None + descricao_simplificada: Optional[str] = None + tipo: Optional[str] = None + descricao_sinter: Optional[str] = None + + class Config: + from_attributes = True + + +# ---------------------------------------------------- +# Schema para localizar um G_TB_DOCUMENTOTIPO especifico pelo ID (GET) +# ---------------------------------------------------- +class GTbDocumentoTipoIdSchema(BaseModel): + tb_documentotipo_id: int + + +# ---------------------------------------------------- +# Schema para localizar um G_TB_DOCUMENTOTIPO especifico pela descrição (GET) +# ---------------------------------------------------- +class GTbDocumentoTipoDescricaoSchema(BaseModel): + descricao: str + + +# ---------------------------------------------------- +# Schema para criação de novo G_TB_DOCUMENTOTIPO (POST) +# ---------------------------------------------------- +class GTbDocumentoTipoSaveSchema(BaseModel): + tb_documentotipo_id: Optional[int] = None + descricao: str + texto: Optional[bytes] = None + situacao: str + possui_numeracao: str + orgao_padrao: str + descricao_simplificada: str + tipo: str + descricao_sinter: str + + # Sanitiza os inputs enviados + @field_validator('descricao', 'situacao', 'possui_numeracao', 'orgao_padrao', 'descricao_simplificada', 'tipo', 'descricao_sinter') + def sanitize_fields(cls, v): + if v: + return Text.sanitize_input(v) + return v + + # Verifica se os campos obrigatórios foram enviados + @model_validator(mode='after') + def validate_all_fields(self): + errors = [] + + if not self.descricao or len(self.descricao.strip()) == 0: + errors.append({'input': 'descricao', 'message': 'A descrição é obrigatória.'}) + + if not self.situacao or len(self.situacao.strip()) == 0: + errors.append({'input': 'situacao', 'message': 'A situação é obrigatória.'}) + + if not self.possui_numeracao or len(self.possui_numeracao.strip()) == 0: + errors.append({'input': 'possui_numeracao', 'message': 'A informação se possui numeração é obrigatória.'}) + + if not self.orgao_padrao or len(self.orgao_padrao.strip()) == 0: + errors.append({'input': 'orgao_padrao', 'message': 'O orgão padrão é obrigatório.'}) + + if not self.descricao_simplificada or len(self.descricao_simplificada.strip()) == 0: + errors.append({'input': 'descricao_simplificada', 'message': 'A descrição simplificada é obrigatória.'}) + + if not self.tipo or len(self.tipo.strip()) == 0: + errors.append({'input': 'tipo', 'message': 'O tipo é obrigatório.'}) + + if not self.descricao_sinter or len(self.descricao_sinter.strip()) == 0: + errors.append({'input': 'descricao_sinter', 'message': 'A descrição do SINTER é obrigatória.'}) + + if errors: + raise HTTPException( + status_code=status.HTTP_422_UNPROCESSABLE_ENTITY, + detail=errors + ) + + return self + + +# ---------------------------------------------------- +# Schema para atualizar G_TB_DOCUMENTOTIPO (PUT) +# ---------------------------------------------------- +class GTbDocumentoTipoUpdateSchema(BaseModel): + descricao: Optional[str] = None + texto: Optional[bytes] = None + situacao: Optional[str] = None + possui_numeracao: Optional[str] = None + orgao_padrao: Optional[str] = None + descricao_simplificada: Optional[str] = None + tipo: Optional[str] = None + descricao_sinter: Optional[str] = None + + # Sanitiza os inputs enviados + @field_validator('descricao', 'situacao', 'possui_numeracao', 'orgao_padrao', 'descricao_simplificada', 'tipo', 'descricao_sinter') + def sanitize_fields(cls, v): + if v: + return Text.sanitize_input(v) + return v + + # Verifica se os campos obrigatórios foram enviados + @model_validator(mode='after') + def validate_all_fields(self): + errors = [] + + if self.descricao is not None and len(self.descricao.strip()) == 0: + errors.append({'input': 'descricao', 'message': 'A descrição é obrigatória.'}) + + if self.situacao is not None and len(self.situacao.strip()) == 0: + errors.append({'input': 'situacao', 'message': 'A situação é obrigatória.'}) + + if self.possui_numeracao is not None and len(self.possui_numeracao.strip()) == 0: + errors.append({'input': 'possui_numeracao', 'message': 'A informação se possui numeração é obrigatória.'}) + + if self.orgao_padrao is not None and len(self.orgao_padrao.strip()) == 0: + errors.append({'input': 'orgao_padrao', 'message': 'O orgão padrão é obrigatório.'}) + + if self.descricao_simplificada is not None and len(self.descricao_simplificada.strip()) == 0: + errors.append({'input': 'descricao_simplificada', 'message': 'A descrição simplificada é obrigatória.'}) + + if self.tipo is not None and len(self.tipo.strip()) == 0: + errors.append({'input': 'tipo', 'message': 'O tipo é obrigatório.'}) + + if self.descricao_sinter is not None and len(self.descricao_sinter.strip()) == 0: + errors.append({'input': 'descricao_sinter', 'message': 'A descrição do SINTER é obrigatória.'}) + + if errors: + raise HTTPException( + status_code=status.HTTP_422_UNPROCESSABLE_ENTITY, + detail=errors + ) + + return self \ No newline at end of file diff --git a/packages/v1/administrativo/services/g_tb_documentotipo/go/g_tb_documentotipo_delete_service.py b/packages/v1/administrativo/services/g_tb_documentotipo/go/g_tb_documentotipo_delete_service.py new file mode 100644 index 0000000..8822cb0 --- /dev/null +++ b/packages/v1/administrativo/services/g_tb_documentotipo/go/g_tb_documentotipo_delete_service.py @@ -0,0 +1,27 @@ +from packages.v1.administrativo.schemas.g_tb_documentotipo_schema import GTbDocumentoTipoIdSchema +from packages.v1.administrativo.actions.g_tb_documentotipo.g_tb_documentotipo_delete_action import DeleteAction + +class DeleteService: + """ + Serviço responsável por encapsular a lógica de negócio para a operação + de exclusão de um registro na tabela G_TB_DOCUMENTOTIPO. + """ + + def execute(self, documentotipo_schema: GTbDocumentoTipoIdSchema): + """ + Executa a operação de exclusão do registro no banco de dados. + + Args: + documentotipo_schema (GtbDocumentotipoIdSchema): O esquema com o ID do registro a ser excluído. + + Returns: + O resultado da operação de exclusão. + """ + # Instanciamento da ação + delete_action = DeleteAction() + + # Executa a ação em questão + data = delete_action.execute(documentotipo_schema) + + # Retorno da informação + return data \ No newline at end of file diff --git a/packages/v1/administrativo/services/g_tb_documentotipo/go/g_tb_documentotipo_get_by_descricao_service.py b/packages/v1/administrativo/services/g_tb_documentotipo/go/g_tb_documentotipo_get_by_descricao_service.py new file mode 100644 index 0000000..e2e880a --- /dev/null +++ b/packages/v1/administrativo/services/g_tb_documentotipo/go/g_tb_documentotipo_get_by_descricao_service.py @@ -0,0 +1,38 @@ +from fastapi import HTTPException, status +from packages.v1.administrativo.schemas.g_tb_documentotipo_schema import GTbDocumentoTipoDescricaoSchema +from packages.v1.administrativo.actions.g_tb_documentotipo.g_tb_documentotipo_get_by_descricao_action import GetByDescricaoAction + +class GetByDescricaoService: + """ + Serviço responsável por encapsular a lógica de negócio para a operação + de busca de um registro na tabela G_TB_DOCUMENTOTIPO pela sua descrição. + """ + + def execute(self, documentotipo_schema: GTbDocumentoTipoDescricaoSchema, messageValidate: bool): + """ + Executa a operação de busca no banco de dados. + + Args: + documentotipo_schema (GtbDocumentotipoDescricaoSchema): O esquema com a descrição a ser buscada. + messageValidate (bool): Se True, lança uma exceção HTTP caso o registro não seja encontrado. + + Returns: + O registro encontrado ou None. + """ + # Instanciamento da ação + show_action = GetByDescricaoAction() + + # Executa a ação em questão + data = show_action.execute(documentotipo_schema) + + if messageValidate: + + if not data: + # Retorna uma exceção + raise HTTPException( + status_code=status.HTTP_404_NOT_FOUND, + detail='Não foi possível localizar o registro de G_TB_DOCUMENTOTIPO' + ) + + # Retorno da informação + return data \ No newline at end of file diff --git a/packages/v1/administrativo/services/g_tb_documentotipo/go/g_tb_documentotipo_index_service.py b/packages/v1/administrativo/services/g_tb_documentotipo/go/g_tb_documentotipo_index_service.py new file mode 100644 index 0000000..124426c --- /dev/null +++ b/packages/v1/administrativo/services/g_tb_documentotipo/go/g_tb_documentotipo_index_service.py @@ -0,0 +1,32 @@ +from fastapi import HTTPException, status +from packages.v1.administrativo.actions.g_tb_documentotipo.g_tb_documentotipo_index_action import IndexAction + +class IndexService: + """ + Serviço responsável por encapsular a lógica de negócio para a operação + de listagem de registros na tabela G_TB_DOCUMENTOTIPO. + """ + + def execute(self): + """ + Executa a operação de busca de todos os registros no banco de dados. + + Returns: + A lista de registros encontrados. + """ + # Instanciamento da ação + index_action = IndexAction() + + # Executa a busca de todas as ações + data = index_action.execute() + + # Verifica se foram localizados registros + if not data: + # Retorna uma exceção + raise HTTPException( + status_code=status.HTTP_404_NOT_FOUND, + detail='Não foi possível localizar os registros de G_TB_DOCUMENTOTIPO' + ) + + # Retorna as informações localizadas + return data \ No newline at end of file diff --git a/packages/v1/administrativo/services/g_tb_documentotipo/go/g_tb_documentotipo_save_service.py b/packages/v1/administrativo/services/g_tb_documentotipo/go/g_tb_documentotipo_save_service.py new file mode 100644 index 0000000..31d0747 --- /dev/null +++ b/packages/v1/administrativo/services/g_tb_documentotipo/go/g_tb_documentotipo_save_service.py @@ -0,0 +1,70 @@ +from actions.dynamic_import.dynamic_import import DynamicImport +from packages.v1.sequencia.schemas.g_sequencia import GSequenciaSchema +from packages.v1.sequencia.services.g_sequencia.generate_service import GenerateService +from packages.v1.administrativo.schemas.g_tb_documentotipo_schema import GTbDocumentoTipoSaveSchema, GTbDocumentoTipoDescricaoSchema +from packages.v1.administrativo.actions.g_tb_documentotipo.g_tb_documentotipo_save_action import SaveAction +from fastapi import HTTPException, status + +class SaveService: + + def __init__(self): + # Ação responsável por carregar as services de acordo com o estado + self.dynamic_import = DynamicImport() + + # Define o pacote que deve ser carregado + self.dynamic_import.set_package("administrativo") + + # Define a tabela que o pacote pertence + self.dynamic_import.set_table("g_tb_documentotipo") + pass + + # Cadastra o novo G_TB_DOCUMENTOTIPO + def execute(self, documentotipo_schema: GTbDocumentoTipoSaveSchema): + + # Armazena possíveis erros + errors = [] + + # Verifica se a descrição já está sendo utilizada + # Importação de service + descricao_service = self.dynamic_import.service("g_tb_documentotipo_get_by_descricao_service", "GetByDescricaoService") + + # Instanciamento da service + self.descricao_service = descricao_service() + + # Verifica se a descrição já está sendo utilizada + self.response = self.descricao_service.execute(GTbDocumentoTipoDescricaoSchema(descricao=documentotipo_schema.descricao), False) + + # Se houver retorno significa que a descrição já está sendo utilizada + if self.response: + errors.append({'input': 'descricao', 'message': 'a descrição informada já está sendo utilizada.'}) + + # Se houver erros, lança a exceção + if errors: + raise HTTPException( + status_code=status.HTTP_403_FORBIDDEN, + detail=errors + ) + + # Verifica se precisa gerar o ID de sequência + if not documentotipo_schema.tb_documentotipo_id: + + # Crio um objeto de sequencia + sequencia_schema = GSequenciaSchema() + + # Define os dados para atualizar a sequencia + sequencia_schema.tabela = 'G_TB_DOCUMENTOTIPO' + + # Busco a sequência atualizada + generate = GenerateService() + + # Busco a sequência atualizada + sequencia = generate.execute(sequencia_schema) + + # Atualiza os dados da chave primária + documentotipo_schema.tb_documentotipo_id = sequencia.sequencia + + # Instanciamento de ações + save_action = SaveAction() + + # Retorna o resultado da operação + return save_action.execute(documentotipo_schema) \ No newline at end of file diff --git a/packages/v1/administrativo/services/g_tb_documentotipo/go/g_tb_documentotipo_show_service.py b/packages/v1/administrativo/services/g_tb_documentotipo/go/g_tb_documentotipo_show_service.py new file mode 100644 index 0000000..d3919ec --- /dev/null +++ b/packages/v1/administrativo/services/g_tb_documentotipo/go/g_tb_documentotipo_show_service.py @@ -0,0 +1,35 @@ +from fastapi import HTTPException, status +from packages.v1.administrativo.schemas.g_tb_documentotipo_schema import GTbDocumentoTipoIdSchema +from packages.v1.administrativo.actions.g_tb_documentotipo.g_tb_documentotipo_show_action import ShowAction + +class ShowService: + """ + Serviço responsável por encapsular a lógica de negócio para a operação + de busca de um registro na tabela G_TB_DOCUMENTOTIPO. + """ + + def execute(self, documentotipo_schema: GTbDocumentoTipoIdSchema): + """ + Executa a operação de busca no banco de dados. + + Args: + documentotipo_schema (GtbDocumentotipoIdSchema): O esquema com o ID a ser buscado. + + Returns: + O resultado da busca. + """ + # Instanciamento da ação + show_action = ShowAction() + + # Executa a ação em questão + data = show_action.execute(documentotipo_schema) + + if not data: + # Retorna uma exceção + raise HTTPException( + status_code=status.HTTP_404_NOT_FOUND, + detail='Não foi possível localizar o registro de G_TB_DOCUMENTOTIPO' + ) + + # Retorno da informação + return data \ No newline at end of file diff --git a/packages/v1/administrativo/services/g_tb_documentotipo/go/g_tb_documentotipo_update_service.py b/packages/v1/administrativo/services/g_tb_documentotipo/go/g_tb_documentotipo_update_service.py new file mode 100644 index 0000000..8a61bf7 --- /dev/null +++ b/packages/v1/administrativo/services/g_tb_documentotipo/go/g_tb_documentotipo_update_service.py @@ -0,0 +1,23 @@ +from packages.v1.administrativo.schemas.g_tb_documentotipo_schema import GTbDocumentoTipoUpdateSchema +from packages.v1.administrativo.actions.g_tb_documentotipo.g_tb_documentotipo_update_action import UpdateAction + +class UpdateService: + """ + Serviço para a operação de atualização de um registro na tabela + G_TB_DOCUMENTOTIPO. + """ + def execute(self, tb_documentotipo_id : int, documentotipo_schema: GTbDocumentoTipoUpdateSchema): + """ + Executa a operação de atualização no banco de dados. + + Args: + documentotipo_schema (GtbDocumentotipoUpdateSchema): O esquema com os dados a serem atualizados. + + Returns: + O resultado da operação de atualização. + """ + # Instanciamento de ações + update_action = UpdateAction() + + # Retorna o resultado da operação + return update_action.execute(tb_documentotipo_id, documentotipo_schema) \ No newline at end of file diff --git a/packages/v1/api.py b/packages/v1/api.py index 23b2220..f3b8e22 100644 --- a/packages/v1/api.py +++ b/packages/v1/api.py @@ -17,6 +17,7 @@ from packages.v1.administrativo.endpoints import t_censec_qualidade_endpoint from packages.v1.administrativo.endpoints import g_tb_estadocivil_endpoint from packages.v1.administrativo.endpoints import g_medida_tipo_endpoint from packages.v1.administrativo.endpoints import t_minuta_endpoint +from packages.v1.administrativo.endpoints import g_tb_documentotipo_endpoint # Cria uma instância do APIRouter que vai agregar todas as rotas da API api_router = APIRouter() @@ -97,4 +98,9 @@ api_router.include_router( # Inclui as rotas de g_tg_medida_tipob_estadocivil api_router.include_router( t_minuta_endpoint.router, prefix="/administrativo/t_minuta", tags=["Minutas"] +) + +# Inclui as rotas de g_tb_documentotipo +api_router.include_router( + g_tb_documentotipo_endpoint.router, prefix="/administrativo/g_tb_documentotipo", tags=["Documento tipo"] ) \ No newline at end of file From d4cf7bf4be7993ac8ff0953b2ac2e5a4a04f11d8 Mon Sep 17 00:00:00 2001 From: Kenio de Souza Date: Tue, 23 Sep 2025 17:01:51 -0300 Subject: [PATCH 2/5] =?UTF-8?q?[MVPTN-85]=20feat(CRUD):=20Cria=C3=A7=C3=A3?= =?UTF-8?q?o=20de=20CRUD=20completo=20para=20a=20tabela=20g=5Fnatureza?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Orius.postman_collection.json | 387 ++++++++++++++++++ .../g_natureza/g_natureza_delete_action.py | 26 ++ .../g_natureza_get_by_descricao_action.py | 29 ++ .../g_natureza/g_natureza_index_action.py | 24 ++ .../g_natureza/g_natureza_save_action.py | 28 ++ .../g_natureza/g_natureza_show_action.py | 28 ++ .../g_natureza/g_natureza_update_action.py | 26 ++ .../controllers/g_natureza_controller.py | 113 +++++ .../endpoints/g_natureza_endpoint.py | 108 +++++ .../g_natureza_delete_repository.py | 41 ++ .../g_natureza_get_by_descricao_repository.py | 29 ++ .../g_natureza/g_natureza_index_repository.py | 23 ++ .../g_natureza/g_natureza_save_repository.py | 62 +++ .../g_natureza/g_natureza_show_repository.py | 46 +++ .../g_natureza_update_repository.py | 73 ++++ .../schemas/g_natureza_schema.py | 110 +++++ .../go/g_natureza_delete_service.py | 27 ++ .../go/g_natureza_get_descricao_service.py | 38 ++ .../g_natureza/go/g_natureza_index_service.py | 32 ++ .../g_natureza/go/g_natureza_save_service.py | 70 ++++ .../g_natureza/go/g_natureza_show_service.py | 35 ++ .../go/g_natureza_update_service.py | 23 ++ packages/v1/api.py | 6 + 23 files changed, 1384 insertions(+) create mode 100644 packages/v1/administrativo/actions/g_natureza/g_natureza_delete_action.py create mode 100644 packages/v1/administrativo/actions/g_natureza/g_natureza_get_by_descricao_action.py create mode 100644 packages/v1/administrativo/actions/g_natureza/g_natureza_index_action.py create mode 100644 packages/v1/administrativo/actions/g_natureza/g_natureza_save_action.py create mode 100644 packages/v1/administrativo/actions/g_natureza/g_natureza_show_action.py create mode 100644 packages/v1/administrativo/actions/g_natureza/g_natureza_update_action.py create mode 100644 packages/v1/administrativo/controllers/g_natureza_controller.py create mode 100644 packages/v1/administrativo/endpoints/g_natureza_endpoint.py create mode 100644 packages/v1/administrativo/repositories/g_natureza/g_natureza_delete_repository.py create mode 100644 packages/v1/administrativo/repositories/g_natureza/g_natureza_get_by_descricao_repository.py create mode 100644 packages/v1/administrativo/repositories/g_natureza/g_natureza_index_repository.py create mode 100644 packages/v1/administrativo/repositories/g_natureza/g_natureza_save_repository.py create mode 100644 packages/v1/administrativo/repositories/g_natureza/g_natureza_show_repository.py create mode 100644 packages/v1/administrativo/repositories/g_natureza/g_natureza_update_repository.py create mode 100644 packages/v1/administrativo/schemas/g_natureza_schema.py create mode 100644 packages/v1/administrativo/services/g_natureza/go/g_natureza_delete_service.py create mode 100644 packages/v1/administrativo/services/g_natureza/go/g_natureza_get_descricao_service.py create mode 100644 packages/v1/administrativo/services/g_natureza/go/g_natureza_index_service.py create mode 100644 packages/v1/administrativo/services/g_natureza/go/g_natureza_save_service.py create mode 100644 packages/v1/administrativo/services/g_natureza/go/g_natureza_show_service.py create mode 100644 packages/v1/administrativo/services/g_natureza/go/g_natureza_update_service.py diff --git a/Orius.postman_collection.json b/Orius.postman_collection.json index e24e4f3..c32f9f3 100644 --- a/Orius.postman_collection.json +++ b/Orius.postman_collection.json @@ -6833,6 +6833,389 @@ } ] }, + { + "name": "Natureza", + "item": [ + { + "name": "GET", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code é 201 ou 200\", function () {\r", + " pm.expect(pm.response.code).to.be.oneOf([200, 201]);\r", + "});\r", + "\r", + "pm.test(\"Resposta contém ID ou confirmação\", function () {\r", + " const jsonData = pm.response.json();\r", + " pm.expect(jsonData).to.have.any.keys(\"id\", \"message\", \"status\");\r", + "});\r", + "\r", + "pm.test(\"Mensagem indica sucesso\", function () {\r", + " const jsonData = pm.response.json();\r", + " pm.expect(jsonData.message || \"\").to.match(/sucesso|criado|registrado/i);\r", + "});\r", + "" + ], + "type": "text/javascript", + "packages": {}, + "requests": {} + } + } + ], + "request": { + "auth": { + "type": "bearer", + "bearer": [ + { + "key": "token", + "value": "{{BearerToken}}", + "type": "string" + } + ] + }, + "method": "GET", + "header": [], + "url": { + "raw": "{{BaseUrlV1}}administrativo/g_natureza", + "host": [ + "{{BaseUrlV1}}administrativo" + ], + "path": [ + "g_natureza" + ] + } + }, + "response": [] + }, + { + "name": "POST", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "const response = pm.response.json();\r", + "\r", + "// Salvando em variáveis da *collection*\r", + "pm.collectionVariables.set(\"naturezaId\", response.data.natureza_id);\r", + "\r", + "pm.test(\"Status code é 201 ou 200\", function () {\r", + " pm.expect(pm.response.code).to.be.oneOf([200, 201]);\r", + "});\r", + "\r", + "pm.test(\"Resposta contém ID ou confirmação\", function () {\r", + " const jsonData = pm.response.json();\r", + " pm.expect(jsonData).to.have.any.keys(\"id\", \"message\", \"status\");\r", + "});\r", + "\r", + "pm.test(\"Mensagem indica sucesso\", function () {\r", + " const jsonData = pm.response.json();\r", + " pm.expect(jsonData.message || \"\").to.match(/sucesso|criado|registrado/i);\r", + "});\r", + "" + ], + "type": "text/javascript", + "packages": {}, + "requests": {} + } + }, + { + "listen": "prerequest", + "script": { + "exec": [ + "" + ], + "type": "text/javascript", + "packages": {}, + "requests": {} + } + } + ], + "request": { + "auth": { + "type": "bearer", + "bearer": [ + { + "key": "token", + "value": "{{BearerToken}}", + "type": "string" + } + ] + }, + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\r\n \"descricao\": \"{{$randomFullName}}\",\r\n \"situacao\": \"{{status}}\",\r\n \"sistema_id\": {{sistemaId}},\r\n \"pedir_numero_imovel\": \"{{useEmail}}\",\r\n \"controle_frenteverso\": \"{{useEmail}}\"\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{BaseUrlV1}}administrativo/g_natureza", + "host": [ + "{{BaseUrlV1}}administrativo" + ], + "path": [ + "g_natureza" + ] + } + }, + "response": [] + }, + { + "name": "GET DESCRIÇÃO", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code é 201 ou 200\", function () {\r", + " pm.expect(pm.response.code).to.be.oneOf([200, 201]);\r", + "});\r", + "\r", + "pm.test(\"Resposta contém ID ou confirmação\", function () {\r", + " const jsonData = pm.response.json();\r", + " pm.expect(jsonData).to.have.any.keys(\"id\", \"message\", \"status\");\r", + "});\r", + "\r", + "pm.test(\"Mensagem indica sucesso\", function () {\r", + " const jsonData = pm.response.json();\r", + " pm.expect(jsonData.message || \"\").to.match(/sucesso|criado|registrado/i);\r", + "});\r", + "" + ], + "type": "text/javascript", + "packages": {}, + "requests": {} + } + } + ], + "protocolProfileBehavior": { + "disableBodyPruning": true + }, + "request": { + "auth": { + "type": "bearer", + "bearer": [ + { + "key": "token", + "value": "{{BearerToken}}", + "type": "string" + } + ] + }, + "method": "GET", + "header": [], + "body": { + "mode": "raw", + "raw": "" + }, + "url": { + "raw": "{{BaseUrlV1}}administrativo/g_natureza/descricao?descricao=ÓBITO", + "host": [ + "{{BaseUrlV1}}administrativo" + ], + "path": [ + "g_natureza", + "descricao" + ], + "query": [ + { + "key": "descricao", + "value": "ÓBITO" + } + ] + } + }, + "response": [] + }, + { + "name": "GET ID", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code é 201 ou 200\", function () {\r", + " pm.expect(pm.response.code).to.be.oneOf([200, 201]);\r", + "});\r", + "\r", + "pm.test(\"Resposta contém ID ou confirmação\", function () {\r", + " const jsonData = pm.response.json();\r", + " pm.expect(jsonData).to.have.any.keys(\"id\", \"message\", \"status\");\r", + "});\r", + "\r", + "pm.test(\"Mensagem indica sucesso\", function () {\r", + " const jsonData = pm.response.json();\r", + " pm.expect(jsonData.message || \"\").to.match(/sucesso|criado|registrado/i);\r", + "});\r", + "" + ], + "type": "text/javascript", + "packages": {}, + "requests": {} + } + } + ], + "request": { + "auth": { + "type": "bearer", + "bearer": [ + { + "key": "token", + "value": "{{BearerToken}}", + "type": "string" + } + ] + }, + "method": "GET", + "header": [], + "url": { + "raw": "{{BaseUrlV1}}administrativo/g_natureza/{{naturezaId}}", + "host": [ + "{{BaseUrlV1}}administrativo" + ], + "path": [ + "g_natureza", + "{{naturezaId}}" + ] + } + }, + "response": [] + }, + { + "name": "PUT", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code é 201 ou 200\", function () {\r", + " pm.expect(pm.response.code).to.be.oneOf([200, 201]);\r", + "});\r", + "\r", + "pm.test(\"Resposta contém ID ou confirmação\", function () {\r", + " const jsonData = pm.response.json();\r", + " pm.expect(jsonData).to.have.any.keys(\"id\", \"message\", \"status\");\r", + "});\r", + "\r", + "pm.test(\"Mensagem indica sucesso\", function () {\r", + " const jsonData = pm.response.json();\r", + " pm.expect(jsonData.message || \"\").to.match(/sucesso|criado|registrado/i);\r", + "});\r", + "" + ], + "type": "text/javascript", + "packages": {}, + "requests": {} + } + } + ], + "request": { + "auth": { + "type": "bearer", + "bearer": [ + { + "key": "token", + "value": "{{BearerToken}}", + "type": "string" + } + ] + }, + "method": "PUT", + "header": [], + "body": { + "mode": "raw", + "raw": "{\r\n \"descricao\": \"{{$randomFullName}}\",\r\n \"situacao\": \"{{status}}\",\r\n \"sistema_id\": {{sistemaId}},\r\n \"pedir_numero_imovel\": \"{{useEmail}}\",\r\n \"controle_frenteverso\": \"{{useEmail}}\"\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{BaseUrlV1}}administrativo/g_natureza/{{naturezaId}}", + "host": [ + "{{BaseUrlV1}}administrativo" + ], + "path": [ + "g_natureza", + "{{naturezaId}}" + ] + } + }, + "response": [] + }, + { + "name": "DELETE", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code é 201 ou 200\", function () {\r", + " pm.expect(pm.response.code).to.be.oneOf([200, 201]);\r", + "});\r", + "\r", + "pm.test(\"Resposta contém ID ou confirmação\", function () {\r", + " const jsonData = pm.response.json();\r", + " pm.expect(jsonData).to.have.any.keys(\"id\", \"message\", \"status\");\r", + "});\r", + "\r", + "pm.test(\"Mensagem indica sucesso\", function () {\r", + " const jsonData = pm.response.json();\r", + " pm.expect(jsonData.message || \"\").to.match(/sucesso|criado|registrado/i);\r", + "});\r", + "" + ], + "type": "text/javascript", + "packages": {}, + "requests": {} + } + } + ], + "request": { + "auth": { + "type": "bearer", + "bearer": [ + { + "key": "token", + "value": "{{BearerToken}}", + "type": "string" + } + ] + }, + "method": "DELETE", + "header": [], + "body": { + "mode": "raw", + "raw": "", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{BaseUrlV1}}administrativo/g_natureza/{{naturezaId}}", + "host": [ + "{{BaseUrlV1}}administrativo" + ], + "path": [ + "g_natureza", + "{{naturezaId}}" + ] + } + }, + "response": [] + } + ] + }, { "name": "Andamento Serviço", "item": [ @@ -7486,6 +7869,10 @@ }, { "key": "tBdocumentotipoId", + "value": "" + }, + { + "key": "naturezaId", "value": "", "type": "default" } diff --git a/packages/v1/administrativo/actions/g_natureza/g_natureza_delete_action.py b/packages/v1/administrativo/actions/g_natureza/g_natureza_delete_action.py new file mode 100644 index 0000000..35933c3 --- /dev/null +++ b/packages/v1/administrativo/actions/g_natureza/g_natureza_delete_action.py @@ -0,0 +1,26 @@ +from abstracts.action import BaseAction +from packages.v1.administrativo.schemas.g_natureza_schema import GNaturezaIdSchema +from packages.v1.administrativo.repositories.g_natureza.g_natureza_delete_repository import DeleteRepository + + +class DeleteAction(BaseAction): + """ + Serviço responsável por encapsular a lógica de negócio para a operação + de exclusão de um registro na tabela g_natureza. + """ + + def execute(self, natureza_schema: GNaturezaIdSchema): + """ + Executa a operação de exclusão no banco de dados. + + Args: + natureza_schema (GNaturezaIdSchema): O esquema com o ID a ser excluído. + + Returns: + O resultado da operação de exclusão. + """ + # Instanciamento do repositório + delete_repository = DeleteRepository() + + # Execução do repositório + return delete_repository.execute(natureza_schema) \ No newline at end of file diff --git a/packages/v1/administrativo/actions/g_natureza/g_natureza_get_by_descricao_action.py b/packages/v1/administrativo/actions/g_natureza/g_natureza_get_by_descricao_action.py new file mode 100644 index 0000000..cd5bc93 --- /dev/null +++ b/packages/v1/administrativo/actions/g_natureza/g_natureza_get_by_descricao_action.py @@ -0,0 +1,29 @@ +from abstracts.action import BaseAction +from packages.v1.administrativo.schemas.g_natureza_schema import GNaturezaDescricaoSchema +from packages.v1.administrativo.repositories.g_natureza.g_natureza_get_by_descricao_repository import GetByDescricaoRepository + + +class GetByDescricaoAction(BaseAction): + """ + Serviço responsável por encapsular a lógica de negócio para a operação + de busca de um registro na tabela g_natureza por descrição. + """ + + def execute(self, natureza_schema: GNaturezaDescricaoSchema): + """ + Executa a operação de busca no banco de dados. + + Args: + natureza_schema (GNaturezaDescricaoSchema): O esquema com a descrição a ser buscada. + + Returns: + O registro encontrado ou None. + """ + # Instanciamento do repositório + show_repository = GetByDescricaoRepository() + + # Execução do repositório + response = show_repository.execute(natureza_schema) + + # Retorno da informação + return response \ No newline at end of file diff --git a/packages/v1/administrativo/actions/g_natureza/g_natureza_index_action.py b/packages/v1/administrativo/actions/g_natureza/g_natureza_index_action.py new file mode 100644 index 0000000..6802d76 --- /dev/null +++ b/packages/v1/administrativo/actions/g_natureza/g_natureza_index_action.py @@ -0,0 +1,24 @@ +from abstracts.action import BaseAction +from packages.v1.administrativo.repositories.g_natureza.g_natureza_index_repository import IndexRepository + +class IndexAction(BaseAction): + """ + Serviço responsável por encapsular a lógica de negócio para a operação + de listagem de todos os registros na tabela g_natureza. + """ + + def execute(self): + """ + Executa a operação de listagem no banco de dados. + + Returns: + A lista de todos os registros. + """ + # Instanciamento do repositório + index_repository = IndexRepository() + + # Execução do repositório + response = index_repository.execute() + + # Retorno da informação + return response \ No newline at end of file diff --git a/packages/v1/administrativo/actions/g_natureza/g_natureza_save_action.py b/packages/v1/administrativo/actions/g_natureza/g_natureza_save_action.py new file mode 100644 index 0000000..74075b6 --- /dev/null +++ b/packages/v1/administrativo/actions/g_natureza/g_natureza_save_action.py @@ -0,0 +1,28 @@ +from abstracts.action import BaseAction +from packages.v1.administrativo.schemas.g_natureza_schema import GNaturezaSaveSchema +from packages.v1.administrativo.repositories.g_natureza.g_natureza_save_repository import SaveRepository + +class SaveAction(BaseAction): + """ + Serviço responsável por encapsular a lógica de negócio para a operação + de salvar um novo registro na tabela g_natureza. + """ + + def execute(self, natureza_schema: GNaturezaSaveSchema): + """ + Executa a operação de salvamento. + + Args: + natureza_schema (GNaturezaSaveSchema): O esquema com os dados a serem salvos. + + Returns: + O resultado da operação de salvamento. + """ + # Instanciamento do repositório + save_repository = SaveRepository() + + # Execução do repositório + response = save_repository.execute(natureza_schema) + + # Retorno da informação + return response \ No newline at end of file diff --git a/packages/v1/administrativo/actions/g_natureza/g_natureza_show_action.py b/packages/v1/administrativo/actions/g_natureza/g_natureza_show_action.py new file mode 100644 index 0000000..dd3bcdf --- /dev/null +++ b/packages/v1/administrativo/actions/g_natureza/g_natureza_show_action.py @@ -0,0 +1,28 @@ +from abstracts.action import BaseAction +from packages.v1.administrativo.schemas.g_natureza_schema import GNaturezaIdSchema +from packages.v1.administrativo.repositories.g_natureza.g_natureza_show_repository import ShowRepository + +class ShowAction(BaseAction): + """ + Serviço responsável por encapsular a lógica de negócio para a exibição + de um registro na tabela g_natureza. + """ + + def execute(self, natureza_schema: GNaturezaIdSchema): + """ + Executa a operação de exibição. + + Args: + natureza_schema (GNaturezaIdSchema): O esquema com o ID do registro a ser exibido. + + Returns: + O resultado da operação de exibição. + """ + # Instânciamento do repositório + show_repository = ShowRepository() + + # Execução do repositório + response = show_repository.execute(natureza_schema) + + # Retorno da informação + return response \ No newline at end of file diff --git a/packages/v1/administrativo/actions/g_natureza/g_natureza_update_action.py b/packages/v1/administrativo/actions/g_natureza/g_natureza_update_action.py new file mode 100644 index 0000000..fedcb67 --- /dev/null +++ b/packages/v1/administrativo/actions/g_natureza/g_natureza_update_action.py @@ -0,0 +1,26 @@ +from packages.v1.administrativo.schemas.g_natureza_schema import GNaturezaUpdateSchema +from packages.v1.administrativo.repositories.g_natureza.g_natureza_update_repository import UpdateRepository + + +class UpdateAction: + """ + Service responsável por encapsular a lógica de negócio para a atualização + de um registro na tabela g_natureza. + """ + + def execute(self, natureza_id: int, natureza_schema: GNaturezaUpdateSchema): + """ + Executa a operação de atualização. + + Args: + natureza_id (int): O ID do registro a ser atualizado. + natureza_schema (GNaturezaUpdateSchema): O esquema com os dados a serem atualizados. + + Returns: + O resultado da operação de atualização. + """ + # Instância o repositório de atualização + update_repository = UpdateRepository() + + # Chama o método de execução do repositório para realizar a atualização + return update_repository.execute(natureza_id, natureza_schema) \ No newline at end of file diff --git a/packages/v1/administrativo/controllers/g_natureza_controller.py b/packages/v1/administrativo/controllers/g_natureza_controller.py new file mode 100644 index 0000000..8e410af --- /dev/null +++ b/packages/v1/administrativo/controllers/g_natureza_controller.py @@ -0,0 +1,113 @@ +from actions.dynamic_import.dynamic_import import DynamicImport +from packages.v1.administrativo.schemas.g_natureza_schema import ( + GNaturezaSchema, + GNaturezaSaveSchema, + GNaturezaUpdateSchema, + GNaturezaIdSchema, + GNaturezaDescricaoSchema +) + +class GNaturezaController: + + def __init__(self): + # Action responsável por carregar as services de acordo com o estado + self.dynamic_import = DynamicImport() + + # Define o pacote que deve ser carregado + self.dynamic_import.set_package("administrativo") + + # Define a tabela que o pacote pertence + self.dynamic_import.set_table("g_natureza") + pass + + # Lista todos os registros de natureza + def index(self): + + # Importação da classe desejada + indexService = self.dynamic_import.service("g_natureza_index_service", "IndexService") + + # Instância da classe service + self.indexService = indexService() + + # Lista todos os registros de natureza + return { + 'message': 'Registros de natureza localizados com sucesso', + 'data': self.indexService.execute() + } + + + # Busca um registro de natureza específico pelo ID + def show(self, natureza_schema: GNaturezaIdSchema): + + #Importação da classe desejada + show_service = self.dynamic_import.service('g_natureza_show_service', 'ShowService') + + # Instância da classe desejada + self.show_service = show_service() + + # Busca e retorna o registro de natureza desejado + return { + 'message': 'Registro de natureza localizado com sucesso', + 'data': self.show_service.execute(natureza_schema) + } + + + # Busca um registro de natureza pela descrição + def get_by_descricao(self, natureza_schema: GNaturezaDescricaoSchema): + + #Importação da classe desejada + show_service = self.dynamic_import.service('g_natureza_get_descricao_service', 'GetByDescricaoService') + + # Instância da classe desejada + self.show_service = show_service() + + # Busca e retorna o registro de natureza desejado + return { + 'message': 'Registro de natureza localizado com sucesso', + 'data': self.show_service.execute(natureza_schema, True) + } + + + # Cadastra um novo registro de natureza + def save(self, natureza_schema: GNaturezaSaveSchema): + + #Importação da classe desejada + save_service = self.dynamic_import.service('g_natureza_save_service', 'SaveService') + + # Instância da classe desejada + self.save_service = save_service() + # Busca e retorna o registro de natureza desejado + return { + 'message': 'Registro de natureza salvo com sucesso', + 'data': self.save_service.execute(natureza_schema) + } + + # Atualiza os dados de um registro de natureza + def update(self, natureza_id: int, natureza_schema: GNaturezaUpdateSchema): + + #Importação da classe desejada + update_service = self.dynamic_import.service('g_natureza_update_service', 'UpdateService') + + # Instância da classe desejada + self.update_service = update_service() + + # Busca e retorna o registro de natureza desejado + return { + 'message': 'Registro de natureza atualizado com sucesso', + 'data': self.update_service.execute(natureza_id, natureza_schema) + } + + # Exclui um registro de natureza + def delete(self, natureza_schema: GNaturezaIdSchema): + + #Importação da classe desejada + delete_service = self.dynamic_import.service('g_natureza_delete_service', 'DeleteService') + + # Instância da classe desejada + self.delete_service = delete_service() + + # Busca e retorna o registro de natureza desejado + return { + 'message': 'Registro de natureza removido com sucesso', + 'data': self.delete_service.execute(natureza_schema) + } \ No newline at end of file diff --git a/packages/v1/administrativo/endpoints/g_natureza_endpoint.py b/packages/v1/administrativo/endpoints/g_natureza_endpoint.py new file mode 100644 index 0000000..55cd158 --- /dev/null +++ b/packages/v1/administrativo/endpoints/g_natureza_endpoint.py @@ -0,0 +1,108 @@ +# Importação de bibliotecas +from typing import Optional +from fastapi import APIRouter, Body, Depends, status +from actions.jwt.get_current_user import get_current_user +from packages.v1.administrativo.controllers.g_natureza_controller import GNaturezaController +from packages.v1.administrativo.schemas.g_natureza_schema import ( + GNaturezaSchema, + GNaturezaSaveSchema, + GNaturezaUpdateSchema, + GNaturezaIdSchema +) + +# Inicializa o roteador para as rotas do tipo de reconhecimento +router = APIRouter() + +# Instanciamento do controller desejado +g_natureza_controller = GNaturezaController() + +# Lista todos os registros de natureza +@router.get('/', + status_code=status.HTTP_200_OK, + summary='Lista todos os registros de natureza cadastrados', + response_description='Lista todos os registros de natureza cadastrados') +async def index(current_user: dict = Depends(get_current_user)): + + # Busca todos os registros de natureza cadastrados + response = g_natureza_controller.index() + + # Retorna os dados localizados + return response + + +# Localiza um registro de natureza pela descrição +@router.get('/descricao', + status_code=status.HTTP_200_OK, + summary='Busca um registro de natureza em específico pela descrição', + response_description='Busca um registro de natureza em específico') +async def get_by_descricao(descricao : str, current_user: dict = Depends(get_current_user)): + + # Cria o schema com os dados recebidos + natureza_schema = GNaturezaSchema(descricao=descricao) + + # Busca um registro de natureza específico pela descrição + response = g_natureza_controller.get_by_descricao(natureza_schema) + + # Retorna os dados localizados + return response + + +# Localiza um registro de natureza pelo ID +@router.get('/{natureza_id}', + status_code=status.HTTP_200_OK, + summary='Busca um registro de natureza em específico pelo ID', + response_description='Busca um registro de natureza em específico') +async def show(natureza_id : int, current_user: dict = Depends(get_current_user)): + + # Cria o schema com os dados recebidos + natureza_schema = GNaturezaIdSchema(natureza_id=natureza_id) + + # Busca um registro de natureza específico pelo ID + response = g_natureza_controller.show(natureza_schema) + + # Retorna os dados localizados + return response + + +# Cadastro de registro de natureza +@router.post('/', + status_code=status.HTTP_201_CREATED, + summary='Cadastra um registro de natureza', + response_description='Cadastra um registro de natureza') +async def save(natureza_schema: GNaturezaSaveSchema, current_user: dict = Depends(get_current_user)): + + # Efetua o cadastro no banco de dados + response = g_natureza_controller.save(natureza_schema) + + # Retorna os dados localizados + return response + + +# Atualiza os dados de um registro de natureza +@router.put('/{natureza_id}', + status_code=status.HTTP_200_OK, + summary='Atualiza um registro de natureza', + response_description='Atualiza um registro de natureza') +async def update(natureza_id: int, natureza_schema: GNaturezaUpdateSchema, current_user: dict = Depends(get_current_user)): + + # Efetua a atualização dos dados + response = g_natureza_controller.update(natureza_id, natureza_schema) + + # Retorna os dados localizados + return response + +# Exclui um determinado registro de natureza +@router.delete('/{natureza_id}', + status_code=status.HTTP_200_OK, + summary='Remove um registro de natureza', + response_description='Remove um registro de natureza') +async def delete(natureza_id: int, current_user: dict = Depends(get_current_user)): + + # Cria o schema com os dados recebidos + natureza_schema = GNaturezaIdSchema(natureza_id=natureza_id) + + # Efetua a exclusão do registro de natureza + response = g_natureza_controller.delete(natureza_schema) + + # Retorna os dados localizados + return response \ No newline at end of file diff --git a/packages/v1/administrativo/repositories/g_natureza/g_natureza_delete_repository.py b/packages/v1/administrativo/repositories/g_natureza/g_natureza_delete_repository.py new file mode 100644 index 0000000..c70811c --- /dev/null +++ b/packages/v1/administrativo/repositories/g_natureza/g_natureza_delete_repository.py @@ -0,0 +1,41 @@ +from abstracts.repository import BaseRepository +from packages.v1.administrativo.schemas.g_natureza_schema import GNaturezaIdSchema +from fastapi import HTTPException, status + +class DeleteRepository(BaseRepository): + """ + Repositório para a operação de exclusão de um registro na tabela + g_natureza. + """ + + def execute(self, natureza_schema: GNaturezaIdSchema): + """ + Executa a consulta SQL para remover um registro pelo ID. + + Args: + natureza_schema (GNaturezaIdSchema): O esquema com o ID a ser removido. + + Returns: + O resultado da operação de exclusão. + """ + try: + # Montagem do sql + sql = """ DELETE FROM G_NATUREZA WHERE NATUREZA_ID = :natureza_id """ + + # Preenchimento de parâmetros + params = { + "natureza_id": natureza_schema.natureza_id + } + + # Execução do sql + response = self.run(sql, params) + + # Retorna o resultado + return response + + except Exception as e: + # Informa que houve uma falha na exclusão + raise HTTPException( + status_code=status.HTTP_422_UNPROCESSABLE_ENTITY, + detail=f"Erro ao excluir NATUREZA: {e}" + ) \ No newline at end of file diff --git a/packages/v1/administrativo/repositories/g_natureza/g_natureza_get_by_descricao_repository.py b/packages/v1/administrativo/repositories/g_natureza/g_natureza_get_by_descricao_repository.py new file mode 100644 index 0000000..10d0c6b --- /dev/null +++ b/packages/v1/administrativo/repositories/g_natureza/g_natureza_get_by_descricao_repository.py @@ -0,0 +1,29 @@ +from abstracts.repository import BaseRepository +from packages.v1.administrativo.schemas.g_natureza_schema import GNaturezaDescricaoSchema + +class GetByDescricaoRepository(BaseRepository): + """ + Repositório para a operação de busca de um registro na tabela + g_natureza por descrição. + """ + + def execute(self, natureza_schema: GNaturezaDescricaoSchema): + """ + Executa a consulta SQL para buscar um registro pela descrição. + + Args: + natureza_schema (GNaturezaDescricaoSchema): O esquema com a descrição a ser buscada. + + Returns: + Um dicionário contendo os dados do registro ou None se não for encontrado. + """ + # Montagem do SQL + sql = """ SELECT * FROM G_NATUREZA WHERE DESCRICAO = :descricao """ + + # Preenchimento de parâmetros + params = { + 'descricao': natureza_schema.descricao + } + + # Execução do sql + return self.fetch_one(sql, params) \ No newline at end of file diff --git a/packages/v1/administrativo/repositories/g_natureza/g_natureza_index_repository.py b/packages/v1/administrativo/repositories/g_natureza/g_natureza_index_repository.py new file mode 100644 index 0000000..649c18b --- /dev/null +++ b/packages/v1/administrativo/repositories/g_natureza/g_natureza_index_repository.py @@ -0,0 +1,23 @@ +from abstracts.repository import BaseRepository + +class IndexRepository(BaseRepository): + """ + Repositório para a operação de listagem de todos os registros + na tabela g_natureza. + """ + + def execute(self): + """ + Executa a consulta SQL para buscar todos os registros. + + Returns: + Uma lista de dicionários contendo os dados dos registros. + """ + # Montagem do SQL + sql = """ SELECT * FROM G_NATUREZA """ + + # Execução do sql + response = self.fetch_all(sql) + + # Retorna os dados localizados + return response \ No newline at end of file diff --git a/packages/v1/administrativo/repositories/g_natureza/g_natureza_save_repository.py b/packages/v1/administrativo/repositories/g_natureza/g_natureza_save_repository.py new file mode 100644 index 0000000..029ecc61 --- /dev/null +++ b/packages/v1/administrativo/repositories/g_natureza/g_natureza_save_repository.py @@ -0,0 +1,62 @@ +from fastapi import HTTPException, status +from abstracts.repository import BaseRepository +from packages.v1.administrativo.schemas.g_natureza_schema import GNaturezaSaveSchema + + +class SaveRepository(BaseRepository): + """ + Repositório para a operação de salvamento de um novo registro na tabela g_natureza. + """ + + def execute(self, natureza_schema: GNaturezaSaveSchema): + """ + Executa a operação de salvamento no banco de dados. + + Args: + natureza_schema (GNaturezaSaveSchema): O esquema com os dados a serem salvos. + + Returns: + O registro recém-criado. + + Raises: + HTTPException: Caso ocorra um erro na execução da query. + """ + try: + + # Montagem do SQL + sql = """ INSERT INTO G_NATUREZA( + NATUREZA_ID, + DESCRICAO, + SITUACAO, + SISTEMA_ID, + PEDIR_NUMERO_IMOVEL, + CONTROLE_FRENTEVERSO + ) VALUES ( + :natureza_id, + :descricao, + :situacao, + :sistema_id, + :pedir_numero_imovel, + :controle_frenteverso + ) RETURNING *;""" + + # Preenchimento de parâmetros + params = { + 'natureza_id': natureza_schema.natureza_id, + 'descricao': natureza_schema.descricao, + 'situacao': natureza_schema.situacao, + 'sistema_id': natureza_schema.sistema_id, + 'pedir_numero_imovel': natureza_schema.pedir_numero_imovel, + 'controle_frenteverso': natureza_schema.controle_frenteverso + } + + # Execução do sql + return self.run_and_return(sql, params) + + except Exception as e: + + # Informa que houve uma falha no salvamento do registro + raise HTTPException( + status_code=status.HTTP_422_UNPROCESSABLE_ENTITY, + detail=f"Erro ao salvar NATUREZA: {e}" + ) \ No newline at end of file diff --git a/packages/v1/administrativo/repositories/g_natureza/g_natureza_show_repository.py b/packages/v1/administrativo/repositories/g_natureza/g_natureza_show_repository.py new file mode 100644 index 0000000..64c793c --- /dev/null +++ b/packages/v1/administrativo/repositories/g_natureza/g_natureza_show_repository.py @@ -0,0 +1,46 @@ +from abstracts.repository import BaseRepository +from packages.v1.administrativo.schemas.g_natureza_schema import GNaturezaIdSchema +from fastapi import HTTPException, status + +class ShowRepository(BaseRepository): + """ + Repositório para a operação de exibição de um registro na tabela g_natureza. + """ + + def execute(self, natureza_schema: GNaturezaIdSchema): + """ + Busca um registro específico de NATUREZA pelo ID. + + Args: + natureza_schema (GNaturezaIdSchema): O esquema que contém o ID do registro. + + Returns: + O registro encontrado ou None se não existir. + + Raises: + HTTPException: Caso ocorra um erro na execução da query. + """ + try: + # Montagem do SQL + sql = "SELECT * FROM G_NATUREZA WHERE NATUREZA_ID = :natureza_id" + + # Preenchimento de parâmetros + params = { + 'natureza_id': natureza_schema.natureza_id + } + + # Execução do SQL + result = self.fetch_one(sql, params) + + if not result: + raise HTTPException( + status_code=status.HTTP_404_NOT_FOUND, + detail="Registro não encontrado" + ) + + return result + except Exception as e: + raise HTTPException( + status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, + detail=f"Erro ao buscar registro: {str(e)}" + ) \ No newline at end of file diff --git a/packages/v1/administrativo/repositories/g_natureza/g_natureza_update_repository.py b/packages/v1/administrativo/repositories/g_natureza/g_natureza_update_repository.py new file mode 100644 index 0000000..3d40df2 --- /dev/null +++ b/packages/v1/administrativo/repositories/g_natureza/g_natureza_update_repository.py @@ -0,0 +1,73 @@ +from abstracts.repository import BaseRepository +from packages.v1.administrativo.schemas.g_natureza_schema import GNaturezaUpdateSchema +from fastapi import HTTPException, status + +class UpdateRepository(BaseRepository): + """ + Repositório para a operação de atualização na tabela G_NATUREZA. + """ + + def execute(self, natureza_id : int, natureza_schema: GNaturezaUpdateSchema): + """ + Executa a atualização de um registro na tabela. + + Args: + natureza_id (int): O ID do registro a ser atualizado. + natureza_schema (GNaturezaUpdateSchema): O esquema com os dados a serem atualizados. + + Returns: + O registro atualizado. + + Raises: + HTTPException: Se o registro não for encontrado ou ocorrer um erro na atualização. + """ + try: + updates = [] + params = {} + + if natureza_schema.descricao is not None: + updates.append("DESCRICAO = :descricao") + params["descricao"] = natureza_schema.descricao + + if natureza_schema.situacao is not None: + updates.append("SITUACAO = :situacao") + params["situacao"] = natureza_schema.situacao + + if natureza_schema.sistema_id is not None: + updates.append("SISTEMA_ID = :sistema_id") + params["sistema_id"] = natureza_schema.sistema_id + + if natureza_schema.pedir_numero_imovel is not None: + updates.append("PEDIR_NUMERO_IMOVEL = :pedir_numero_imovel") + params["pedir_numero_imovel"] = natureza_schema.pedir_numero_imovel + + if natureza_schema.controle_frenteverso is not None: + updates.append("CONTROLE_FRENTEVERSO = :controle_frenteverso") + params["controle_frenteverso"] = natureza_schema.controle_frenteverso + + if not updates: + return False + + params["natureza_id"] = natureza_id + sql = f"UPDATE G_NATUREZA SET {', '.join(updates)} WHERE natureza_id = :natureza_id RETURNING *;" + + # Executa a query + result = self.run_and_return(sql, params) + + if not result.natureza_id: + # Informa que não existe o registro a ser modificado + raise HTTPException( + status_code=status.HTTP_422_UNPROCESSABLE_ENTITY, + detail='Nenhuma NATUREZA localizada para esta solicitação' + ) + + # Se houver um resultado, a atualização foi bem-sucedida + if result: + return result + + except Exception as e: + # Informa que houve uma falha na atualização + raise HTTPException( + status_code=status.HTTP_422_UNPROCESSABLE_ENTITY, + detail=f"Erro ao atualizar o NATUREZA: {e}" + ) \ No newline at end of file diff --git a/packages/v1/administrativo/schemas/g_natureza_schema.py b/packages/v1/administrativo/schemas/g_natureza_schema.py new file mode 100644 index 0000000..ed1bbcc --- /dev/null +++ b/packages/v1/administrativo/schemas/g_natureza_schema.py @@ -0,0 +1,110 @@ +from pydantic import BaseModel, field_validator, model_validator +from fastapi import HTTPException, status +from typing import Optional + +# Funções para sanitização de entradas (evitar XSS, SQLi etc.) +from actions.validations.text import Text + +# ---------------------------------------------------- +# Schema base +# ---------------------------------------------------- +class GNaturezaSchema(BaseModel): + natureza_id: Optional[int] = None + descricao: Optional[str] = None + situacao: Optional[str] = None + sistema_id: Optional[int] = None + pedir_numero_imovel: Optional[str] = None + controle_frenteverso: Optional[str] = None + + class Config: + from_attributes = True + + +# ---------------------------------------------------- +# Schema para localizar uma NATUREZA especifica pelo ID (GET) +# ---------------------------------------------------- +class GNaturezaIdSchema(BaseModel): + natureza_id: int + + +# ---------------------------------------------------- +# Schema para localizar uma NATUREZA especifica pela descrição (GET) +# ---------------------------------------------------- +class GNaturezaDescricaoSchema(BaseModel): + descricao: str + + +# ---------------------------------------------------- +# Schema para criação de nova NATUREZA (POST) +# ---------------------------------------------------- +class GNaturezaSaveSchema(BaseModel): + natureza_id: Optional[int] = None + descricao: str + situacao: str + sistema_id: Optional[int] = None + pedir_numero_imovel: Optional[str] = None + controle_frenteverso: Optional[str] = None + + # Sanitiza os inputs enviados + @field_validator('descricao', 'situacao', 'pedir_numero_imovel', 'controle_frenteverso') + def sanitize_fields(cls, v): + if v: + return Text.sanitize_input(v) + return v + + # Verifica se os campos obrigatórios foram enviados + @model_validator(mode='after') + def validate_all_fields(self): + errors = [] + + if not self.descricao or len(self.descricao.strip()) == 0: + errors.append({'input': 'descricao', 'message': 'A descrição é obrigatória.'}) + + if not self.situacao or len(self.situacao.strip()) == 0: + errors.append({'input': 'situacao', 'message': 'A situação é obrigatória.'}) + + if errors: + raise HTTPException( + status_code=status.HTTP_422_UNPROCESSABLE_ENTITY, + detail=errors + ) + + return self + + +# ---------------------------------------------------- +# Schema para atualizar NATUREZA (PUT) +# ---------------------------------------------------- +class GNaturezaUpdateSchema(BaseModel): + + descricao: Optional[str] = None + situacao: Optional[str] = None + sistema_id: Optional[int] = None + pedir_numero_imovel: Optional[str] = None + controle_frenteverso: Optional[str] = None + + # Sanitiza os inputs enviados + @field_validator('descricao', 'situacao', 'pedir_numero_imovel', 'controle_frenteverso') + def sanitize_fields(cls, v): + if v: + return Text.sanitize_input(v) + return v + + # Verifica se os campos obrigatórios foram enviados + @model_validator(mode='after') + def validate_all_fields(self): + errors = [] + + # A validação de campos obrigatórios é diferente para atualização, pois os campos são opcionais. + # A lógica para a validação pode ser mais complexa dependendo das regras de negócio. + + # Para este exemplo, não há campos obrigatórios na atualização. + # Se você precisar de validação de campos obrigatórios, pode adicionar aqui. + + if errors: + raise HTTPException( + status_code=status.HTTP_422_UNPROCESSABLE_ENTITY, + detail=errors + ) + + return self \ No newline at end of file diff --git a/packages/v1/administrativo/services/g_natureza/go/g_natureza_delete_service.py b/packages/v1/administrativo/services/g_natureza/go/g_natureza_delete_service.py new file mode 100644 index 0000000..b5b17e4 --- /dev/null +++ b/packages/v1/administrativo/services/g_natureza/go/g_natureza_delete_service.py @@ -0,0 +1,27 @@ +from packages.v1.administrativo.schemas.g_natureza_schema import GNaturezaIdSchema +from packages.v1.administrativo.actions.g_natureza.g_natureza_delete_action import DeleteAction + +class DeleteService: + """ + Serviço responsável por encapsular a lógica de negócio para a operação + de exclusão de um registro na tabela g_natureza. + """ + + def execute(self, natureza_schema: GNaturezaIdSchema): + """ + Executa a operação de exclusão do registro no banco de dados. + + Args: + natureza_schema (GNaturezaIdSchema): O esquema com o ID do registro a ser excluído. + + Returns: + O resultado da operação de exclusão. + """ + # Instanciamento da ação + delete_action = DeleteAction() + + # Executa a ação em questão + data = delete_action.execute(natureza_schema) + + # Retorno da informação + return data \ No newline at end of file diff --git a/packages/v1/administrativo/services/g_natureza/go/g_natureza_get_descricao_service.py b/packages/v1/administrativo/services/g_natureza/go/g_natureza_get_descricao_service.py new file mode 100644 index 0000000..ff48e5f --- /dev/null +++ b/packages/v1/administrativo/services/g_natureza/go/g_natureza_get_descricao_service.py @@ -0,0 +1,38 @@ +from fastapi import HTTPException, status +from packages.v1.administrativo.schemas.g_natureza_schema import GNaturezaDescricaoSchema +from packages.v1.administrativo.actions.g_natureza.g_natureza_get_by_descricao_action import GetByDescricaoAction + +class GetByDescricaoService: + """ + Serviço responsável por encapsular a lógica de negócio para a operação + de busca de um registro na tabela g_natureza pela sua descrição. + """ + + def execute(self, natureza_schema: GNaturezaDescricaoSchema, messageValidate: bool): + """ + Executa a operação de busca no banco de dados. + + Args: + natureza_schema (GNaturezaDescricaoSchema): O esquema com a descrição a ser buscada. + messageValidate (bool): Se True, lança uma exceção HTTP caso o registro não seja encontrado. + + Returns: + O registro encontrado ou None. + """ + # Instanciamento da ação + show_action = GetByDescricaoAction() + + # Executa a ação em questão + data = show_action.execute(natureza_schema) + + if messageValidate: + + if not data: + # Retorna uma exceção + raise HTTPException( + status_code=status.HTTP_404_NOT_FOUND, + detail='Não foi possível localizar o registro de Natureza' + ) + + # Retorno da informação + return data \ No newline at end of file diff --git a/packages/v1/administrativo/services/g_natureza/go/g_natureza_index_service.py b/packages/v1/administrativo/services/g_natureza/go/g_natureza_index_service.py new file mode 100644 index 0000000..23e8ec6 --- /dev/null +++ b/packages/v1/administrativo/services/g_natureza/go/g_natureza_index_service.py @@ -0,0 +1,32 @@ +from fastapi import HTTPException, status +from packages.v1.administrativo.actions.g_natureza.g_natureza_index_action import IndexAction + +class IndexService: + """ + Serviço responsável por encapsular a lógica de negócio para a operação + de listagem de registros na tabela g_natureza. + """ + + def execute(self): + """ + Executa a operação de busca de todos os registros no banco de dados. + + Returns: + A lista de registros encontrados. + """ + # Instanciamento da ação + index_action = IndexAction() + + # Executa a busca de todas as ações + data = index_action.execute() + + # Verifica se foram localizados registros + if not data: + # Retorna uma exceção + raise HTTPException( + status_code=status.HTTP_404_NOT_FOUND, + detail='Não foi possível localizar os registros de Natureza' + ) + + # Retorna as informações localizadas + return data \ No newline at end of file diff --git a/packages/v1/administrativo/services/g_natureza/go/g_natureza_save_service.py b/packages/v1/administrativo/services/g_natureza/go/g_natureza_save_service.py new file mode 100644 index 0000000..9a64fb0 --- /dev/null +++ b/packages/v1/administrativo/services/g_natureza/go/g_natureza_save_service.py @@ -0,0 +1,70 @@ +from actions.dynamic_import.dynamic_import import DynamicImport +from packages.v1.sequencia.schemas.g_sequencia import GSequenciaSchema +from packages.v1.sequencia.services.g_sequencia.generate_service import GenerateService +from packages.v1.administrativo.schemas.g_natureza_schema import GNaturezaSaveSchema, GNaturezaDescricaoSchema +from packages.v1.administrativo.actions.g_natureza.g_natureza_save_action import SaveAction +from fastapi import HTTPException, status + +class SaveService: + + def __init__(self): + # Ação responsável por carregar as services de acordo com o estado + self.dynamic_import = DynamicImport() + + # Define o pacote que deve ser carregado + self.dynamic_import.set_package("administrativo") + + # Define a tabela que o pacote pertence + self.dynamic_import.set_table("g_natureza") + pass + + # Cadastra a nova Natureza + def execute(self, natureza_schema: GNaturezaSaveSchema): + + # Armazena possíveis erros + errors = [] + + # Verifica se a descrição já está sendo utilizada + # Importação de service + descricao_service = self.dynamic_import.service("g_natureza_get_descricao_service", "GetByDescricaoService") + + # Instanciamento da service + self.descricao_service = descricao_service() + + # Verifica se a descrição já está sendo utilizada + self.response = self.descricao_service.execute(GNaturezaDescricaoSchema(descricao=natureza_schema.descricao), False) + + # Se houver retorno significa que a descrição já está sendo utilizada + if self.response: + errors.append({'input': 'descricao', 'message': 'a descrição informada já está sendo utilizada.'}) + + # Se houver erros, lança a exceção + if errors: + raise HTTPException( + status_code=status.HTTP_403_FORBIDDEN, + detail=errors + ) + + # Verifica se precisa gerar o ID de sequência + if not natureza_schema.natureza_id: + + # Crio um objeto de sequencia + sequencia_schema = GSequenciaSchema() + + # Define os dados para atualizar a sequencia + sequencia_schema.tabela = 'G_NATUREZA' + + # Busco a sequência atualizada + generate = GenerateService() + + # Busco a sequência atualizada + sequencia = generate.execute(sequencia_schema) + + # Atualiza os dados da chave primária + natureza_schema.natureza_id = sequencia.sequencia + + # Instanciamento de ações + save_action = SaveAction() + + # Retorna o resultado da operação + return save_action.execute(natureza_schema) \ No newline at end of file diff --git a/packages/v1/administrativo/services/g_natureza/go/g_natureza_show_service.py b/packages/v1/administrativo/services/g_natureza/go/g_natureza_show_service.py new file mode 100644 index 0000000..aaf2084 --- /dev/null +++ b/packages/v1/administrativo/services/g_natureza/go/g_natureza_show_service.py @@ -0,0 +1,35 @@ +from fastapi import HTTPException, status +from packages.v1.administrativo.schemas.g_natureza_schema import GNaturezaIdSchema +from packages.v1.administrativo.actions.g_natureza.g_natureza_show_action import ShowAction + +class ShowService: + """ + Serviço responsável por encapsular a lógica de negócio para a operação + de busca de um registro na tabela g_natureza. + """ + + def execute(self, natureza_schema: GNaturezaIdSchema): + """ + Executa a operação de busca no banco de dados. + + Args: + natureza_schema (GNaturezaIdSchema): O esquema com o ID a ser buscado. + + Returns: + O resultado da busca. + """ + # Instanciamento da ação + show_action = ShowAction() + + # Executa a ação em questão + data = show_action.execute(natureza_schema) + + if not data: + # Retorna uma exceção + raise HTTPException( + status_code=status.HTTP_404_NOT_FOUND, + detail='Não foi possível localizar o registro de Natureza' + ) + + # Retorno da informação + return data \ No newline at end of file diff --git a/packages/v1/administrativo/services/g_natureza/go/g_natureza_update_service.py b/packages/v1/administrativo/services/g_natureza/go/g_natureza_update_service.py new file mode 100644 index 0000000..f230898 --- /dev/null +++ b/packages/v1/administrativo/services/g_natureza/go/g_natureza_update_service.py @@ -0,0 +1,23 @@ +from packages.v1.administrativo.schemas.g_natureza_schema import GNaturezaUpdateSchema +from packages.v1.administrativo.actions.g_natureza.g_natureza_update_action import UpdateAction + +class UpdateService: + """ + Serviço para a operação de atualização de um registro na tabela + g_natureza. + """ + def execute(self, natureza_id : int, natureza_schema: GNaturezaUpdateSchema): + """ + Executa a operação de atualização no banco de dados. + + Args: + natureza_schema (GNaturezaUpdateSchema): O esquema com os dados a serem atualizados. + + Returns: + O resultado da operação de atualização. + """ + # Instanciamento de ações + update_action = UpdateAction() + + # Retorna o resultado da operação + return update_action.execute(natureza_id, natureza_schema) \ No newline at end of file diff --git a/packages/v1/api.py b/packages/v1/api.py index f3b8e22..2f70903 100644 --- a/packages/v1/api.py +++ b/packages/v1/api.py @@ -18,6 +18,7 @@ from packages.v1.administrativo.endpoints import g_tb_estadocivil_endpoint from packages.v1.administrativo.endpoints import g_medida_tipo_endpoint from packages.v1.administrativo.endpoints import t_minuta_endpoint from packages.v1.administrativo.endpoints import g_tb_documentotipo_endpoint +from packages.v1.administrativo.endpoints import g_natureza_endpoint # Cria uma instância do APIRouter que vai agregar todas as rotas da API api_router = APIRouter() @@ -103,4 +104,9 @@ api_router.include_router( # Inclui as rotas de g_tb_documentotipo api_router.include_router( g_tb_documentotipo_endpoint.router, prefix="/administrativo/g_tb_documentotipo", tags=["Documento tipo"] +) + +# Inclui as rotas de g_natureza +api_router.include_router( + g_natureza_endpoint.router, prefix="/administrativo/g_natureza", tags=["Natureza"] ) \ No newline at end of file From bb5e4cf5a33d6dc3bb4542ea34e5b6c6521844ec Mon Sep 17 00:00:00 2001 From: Kenio de Souza Date: Tue, 23 Sep 2025 17:59:47 -0300 Subject: [PATCH 3/5] =?UTF-8?q?[DSAAS-18]=20fix(Auentica=C3=A7=C3=A3o):=20?= =?UTF-8?q?Ajuste=20para=20informar=20se=20o=20usu=C3=A1rio=20foi=20locali?= =?UTF-8?q?zado=20ou=20n=C3=A3o?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../g_usuario/go/g_usuario_authenticate_service.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/packages/v1/administrativo/services/g_usuario/go/g_usuario_authenticate_service.py b/packages/v1/administrativo/services/g_usuario/go/g_usuario_authenticate_service.py index 4aba069..013cc2c 100644 --- a/packages/v1/administrativo/services/g_usuario/go/g_usuario_authenticate_service.py +++ b/packages/v1/administrativo/services/g_usuario/go/g_usuario_authenticate_service.py @@ -14,14 +14,20 @@ class AuthenticateService: get_by_authenticate_action = GetByAuthenticateAction() # Execução e retorno da action - get_by_authenticate_result = get_by_authenticate_action.execute(g_usuario_authenticate_schema) + # Se não encontrou o usuário, lança exceção ou retorna erro + if get_by_authenticate_result is None: + raise HTTPException( + status_code=status.HTTP_422_UNPROCESSABLE_ENTITY, + detail='Usuário ou senha inválidos' + ) + # Verifica se a senha do usuário esta correta if not Security.is_hash(get_by_authenticate_result.senha_api): raise HTTPException( status_code=status.HTTP_422_UNPROCESSABLE_ENTITY, - detail='A senha armazenada é inválida' + detail='A senha informada é inválida' ) # Verifica se a senha do usuário esta correta From 2b4596818bbe80cee0f3a97cc506a01d45b5c7b8 Mon Sep 17 00:00:00 2001 From: Kenio de Souza Date: Fri, 26 Sep 2025 11:38:25 -0300 Subject: [PATCH 4/5] [MVPTN-19] feat(Crud): CRUD completo para a tabela g_cidade --- .../g_cidade/g_cidade_delete_action.py | 26 ++++ .../g_cidade/g_cidade_get_by_nome_action.py | 29 ++++ .../actions/g_cidade/g_cidade_index_action.py | 24 ++++ .../actions/g_cidade/g_cidade_save_action.py | 28 ++++ .../actions/g_cidade/g_cidade_show_action.py | 28 ++++ .../g_cidade/g_cidade_update_action.py | 26 ++++ .../controllers/g_cidade_controller.py | 113 ++++++++++++++++ .../endpoints/g_cidade_endpoint.py | 109 +++++++++++++++ .../g_cidade/g_cidade_delete_repository.py | 41 ++++++ .../g_cidade_get_by_nome_repository.py | 29 ++++ .../g_cidade/g_cidade_index_repository.py | 23 ++++ .../g_cidade/g_cidade_save_repository.py | 59 ++++++++ .../g_cidade/g_cidade_show_repository.py | 46 +++++++ .../g_cidade/g_cidade_update_repository.py | 52 +++++++ .../administrativo/schemas/g_cidade_schema.py | 127 ++++++++++++++++++ .../g_cidade/go/g_cidade_delete_service.py | 27 ++++ .../g_cidade/go/g_cidade_get_nome_service.py | 38 ++++++ .../g_cidade/go/g_cidade_index_service.py | 32 +++++ .../g_cidade/go/g_cidade_save_service.py | 70 ++++++++++ .../g_cidade/go/g_cidade_show_service.py | 35 +++++ .../g_cidade/go/g_cidade_update_service.py | 24 ++++ packages/v1/api.py | 7 + 22 files changed, 993 insertions(+) create mode 100644 packages/v1/administrativo/actions/g_cidade/g_cidade_delete_action.py create mode 100644 packages/v1/administrativo/actions/g_cidade/g_cidade_get_by_nome_action.py create mode 100644 packages/v1/administrativo/actions/g_cidade/g_cidade_index_action.py create mode 100644 packages/v1/administrativo/actions/g_cidade/g_cidade_save_action.py create mode 100644 packages/v1/administrativo/actions/g_cidade/g_cidade_show_action.py create mode 100644 packages/v1/administrativo/actions/g_cidade/g_cidade_update_action.py create mode 100644 packages/v1/administrativo/controllers/g_cidade_controller.py create mode 100644 packages/v1/administrativo/endpoints/g_cidade_endpoint.py create mode 100644 packages/v1/administrativo/repositories/g_cidade/g_cidade_delete_repository.py create mode 100644 packages/v1/administrativo/repositories/g_cidade/g_cidade_get_by_nome_repository.py create mode 100644 packages/v1/administrativo/repositories/g_cidade/g_cidade_index_repository.py create mode 100644 packages/v1/administrativo/repositories/g_cidade/g_cidade_save_repository.py create mode 100644 packages/v1/administrativo/repositories/g_cidade/g_cidade_show_repository.py create mode 100644 packages/v1/administrativo/repositories/g_cidade/g_cidade_update_repository.py create mode 100644 packages/v1/administrativo/schemas/g_cidade_schema.py create mode 100644 packages/v1/administrativo/services/g_cidade/go/g_cidade_delete_service.py create mode 100644 packages/v1/administrativo/services/g_cidade/go/g_cidade_get_nome_service.py create mode 100644 packages/v1/administrativo/services/g_cidade/go/g_cidade_index_service.py create mode 100644 packages/v1/administrativo/services/g_cidade/go/g_cidade_save_service.py create mode 100644 packages/v1/administrativo/services/g_cidade/go/g_cidade_show_service.py create mode 100644 packages/v1/administrativo/services/g_cidade/go/g_cidade_update_service.py diff --git a/packages/v1/administrativo/actions/g_cidade/g_cidade_delete_action.py b/packages/v1/administrativo/actions/g_cidade/g_cidade_delete_action.py new file mode 100644 index 0000000..029ecc69 --- /dev/null +++ b/packages/v1/administrativo/actions/g_cidade/g_cidade_delete_action.py @@ -0,0 +1,26 @@ +from abstracts.action import BaseAction +from packages.v1.administrativo.schemas.g_cidade_schema import GCidadeIdSchema +from packages.v1.administrativo.repositories.g_cidade.g_cidade_delete_repository import DeleteRepository + + +class DeleteAction(BaseAction): + """ + Serviço responsável por encapsular a lógica de negócio para a operação + de exclusão de um registro na tabela G_CIDADE. + """ + + def execute(self, g_cidade_schema: GCidadeIdSchema): + """ + Executa a operação de exclusão no banco de dados. + + Args: + g_cidade_schema (GCidadeIdSchema): O esquema com o ID (CIDADE_ID) a ser excluído. + + Returns: + O resultado da operação de exclusão. + """ + # Instanciamento do repositório + delete_repository = DeleteRepository() + + # Execução do repositório + return delete_repository.execute(g_cidade_schema) \ No newline at end of file diff --git a/packages/v1/administrativo/actions/g_cidade/g_cidade_get_by_nome_action.py b/packages/v1/administrativo/actions/g_cidade/g_cidade_get_by_nome_action.py new file mode 100644 index 0000000..6dac420 --- /dev/null +++ b/packages/v1/administrativo/actions/g_cidade/g_cidade_get_by_nome_action.py @@ -0,0 +1,29 @@ +from abstracts.action import BaseAction +from packages.v1.administrativo.schemas.g_cidade_schema import GCidadeNomeSchema +from packages.v1.administrativo.repositories.g_cidade.g_cidade_get_by_nome_repository import GetByNomeRepository + + +class GetByNomeAction(BaseAction): + """ + Serviço responsável por encapsular a lógica de negócio para a operação + de busca de um registro na tabela G_CIDADE por nome (CIDADE_NOME). + """ + + def execute(self, g_cidade_schema: GCidadeNomeSchema): + """ + Executa a operação de busca no banco de dados. + + Args: + g_cidade_schema (GCidadeNomeSchema): O esquema com o nome da cidade a ser buscada. + + Returns: + O registro encontrado ou None. + """ + # Instanciamento do repositório + show_repository = GetByNomeRepository() + + # Execução do repositório + response = show_repository.execute(g_cidade_schema) + + # Retorno da informação + return response \ No newline at end of file diff --git a/packages/v1/administrativo/actions/g_cidade/g_cidade_index_action.py b/packages/v1/administrativo/actions/g_cidade/g_cidade_index_action.py new file mode 100644 index 0000000..743e82e --- /dev/null +++ b/packages/v1/administrativo/actions/g_cidade/g_cidade_index_action.py @@ -0,0 +1,24 @@ +from abstracts.action import BaseAction +from packages.v1.administrativo.repositories.g_cidade.g_cidade_index_repository import IndexRepository + +class IndexAction(BaseAction): + """ + Serviço responsável por encapsular a lógica de negócio para a operação + de listagem de todos os registros na tabela G_CIDADE. + """ + + def execute(self): + """ + Executa a operação de listagem no banco de dados. + + Returns: + A lista de todos os registros. + """ + # Instanciamento do repositório + index_repository = IndexRepository() + + # Execução do repositório + response = index_repository.execute() + + # Retorno da informação + return response \ No newline at end of file diff --git a/packages/v1/administrativo/actions/g_cidade/g_cidade_save_action.py b/packages/v1/administrativo/actions/g_cidade/g_cidade_save_action.py new file mode 100644 index 0000000..631a931 --- /dev/null +++ b/packages/v1/administrativo/actions/g_cidade/g_cidade_save_action.py @@ -0,0 +1,28 @@ +from abstracts.action import BaseAction +from packages.v1.administrativo.schemas.g_cidade_schema import GCidadeSaveSchema +from packages.v1.administrativo.repositories.g_cidade.g_cidade_save_repository import SaveRepository + +class SaveAction(BaseAction): + """ + Serviço responsável por encapsular a lógica de negócio para a operação + de salvar (inserir ou atualizar) um registro na tabela G_CIDADE. + """ + + def execute(self, g_cidade_schema: GCidadeSaveSchema): + """ + Executa a operação de salvamento. + + Args: + g_cidade_schema (GCidadeSaveSchema): O esquema com os dados a serem salvos. + + Returns: + O resultado da operação de salvamento. + """ + # Instanciamento do repositório + save_repository = SaveRepository() + + # Execução do repositório + response = save_repository.execute(g_cidade_schema) + + # Retorno da informação + return response \ No newline at end of file diff --git a/packages/v1/administrativo/actions/g_cidade/g_cidade_show_action.py b/packages/v1/administrativo/actions/g_cidade/g_cidade_show_action.py new file mode 100644 index 0000000..2302a80 --- /dev/null +++ b/packages/v1/administrativo/actions/g_cidade/g_cidade_show_action.py @@ -0,0 +1,28 @@ +from abstracts.action import BaseAction +from packages.v1.administrativo.schemas.g_cidade_schema import GCidadeIdSchema +from packages.v1.administrativo.repositories.g_cidade.g_cidade_show_repository import ShowRepository + +class ShowAction(BaseAction): + """ + Serviço responsável por encapsular a lógica de negócio para a exibição + de um registro na tabela G_CIDADE, usando o CIDADE_ID. + """ + + def execute(self, g_cidade_schema: GCidadeIdSchema): + """ + Executa a operação de exibição. + + Args: + g_cidade_schema (GCidadeIdSchema): O esquema com o ID (CIDADE_ID) do registro a ser exibido. + + Returns: + O resultado da operação de exibição (o registro encontrado ou None). + """ + # Instanciamento do repositório + show_repository = ShowRepository() + + # Execução do repositório + response = show_repository.execute(g_cidade_schema) + + # Retorno da informação + return response \ No newline at end of file diff --git a/packages/v1/administrativo/actions/g_cidade/g_cidade_update_action.py b/packages/v1/administrativo/actions/g_cidade/g_cidade_update_action.py new file mode 100644 index 0000000..6fb1902 --- /dev/null +++ b/packages/v1/administrativo/actions/g_cidade/g_cidade_update_action.py @@ -0,0 +1,26 @@ +from packages.v1.administrativo.schemas.g_cidade_schema import GCidadeUpdateSchema +from packages.v1.administrativo.repositories.g_cidade.g_cidade_update_repository import UpdateRepository + + +class UpdateAction: + """ + Serviço responsável por encapsular a lógica de negócio para a atualização + de um registro na tabela G_CIDADE. + """ + + def execute(self, cidade_id: int, g_cidade_schema: GCidadeUpdateSchema): + """ + Executa a operação de atualização. + + Args: + cidade_id (int): O ID (CIDADE_ID) do registro a ser atualizado. + g_cidade_schema (GCidadeUpdateSchema): O esquema com os dados a serem atualizados. + + Returns: + O resultado da operação de atualização. + """ + # Instância o repositório de atualização + update_repository = UpdateRepository() + + # Chama o método de execução do repositório para realizar a atualização + return update_repository.execute(cidade_id, g_cidade_schema) \ No newline at end of file diff --git a/packages/v1/administrativo/controllers/g_cidade_controller.py b/packages/v1/administrativo/controllers/g_cidade_controller.py new file mode 100644 index 0000000..67da986 --- /dev/null +++ b/packages/v1/administrativo/controllers/g_cidade_controller.py @@ -0,0 +1,113 @@ +from actions.dynamic_import.dynamic_import import DynamicImport +from packages.v1.administrativo.schemas.g_cidade_schema import ( + GCidadeSchema, + GCidadeSaveSchema, + GCidadeUpdateSchema, + GCidadeIdSchema, + GCidadeNomeSchema +) + +class GCidadeController: + + def __init__(self): + # Action responsável por carregar as services de acordo com o estado + self.dynamic_import = DynamicImport() + + # Define o pacote que deve ser carregado + self.dynamic_import.set_package("administrativo") + + # Define a tabela que o pacote pertence + self.dynamic_import.set_table("g_cidade") + pass + + # Lista todos os registros de cidade + def index(self): + + # Importação da classe desejada + indexService = self.dynamic_import.service("g_cidade_index_service", "IndexService") + + # Instância da classe service + self.indexService = indexService() + + # Lista todos os registros de cidade + return { + 'message': 'Registros de cidade localizados com sucesso', + 'data': self.indexService.execute() + } + + + # Busca um registro de cidade específico pelo ID + def show(self, g_cidade_schema: GCidadeIdSchema): + + #Importação da classe desejada + show_service = self.dynamic_import.service('g_cidade_show_service', 'ShowService') + + # Instância da classe desejada + self.show_service = show_service() + + # Busca e retorna o registro de cidade desejado + return { + 'message': 'Registro de cidade localizado com sucesso', + 'data': self.show_service.execute(g_cidade_schema) + } + + + # Busca um registro de cidade pelo nome (CIDADE_NOME) + def get_by_nome(self, g_cidade_schema: GCidadeNomeSchema): + + #Importação da classe desejada + show_service = self.dynamic_import.service('g_cidade_get_nome_service', 'GetByNomeService') + + # Instância da classe desejada + self.show_service = show_service() + + # Busca e retorna o registro de cidade desejado + return { + 'message': 'Registro de cidade localizado com sucesso', + 'data': self.show_service.execute(g_cidade_schema, True) + } + + + # Cadastra um novo registro de cidade + def save(self, g_cidade_schema: GCidadeSaveSchema): + + #Importação da classe desejada + save_service = self.dynamic_import.service('g_cidade_save_service', 'SaveService') + + # Instância da classe desejada + self.save_service = save_service() + # Busca e retorna o registro de cidade desejado + return { + 'message': 'Registro de cidade salvo com sucesso', + 'data': self.save_service.execute(g_cidade_schema) + } + + # Atualiza os dados de um registro de cidade + def update(self, cidade_id: int, g_cidade_schema: GCidadeUpdateSchema): + + #Importação da classe desejada + update_service = self.dynamic_import.service('g_cidade_update_service', 'UpdateService') + + # Instância da classe desejada + self.update_service = update_service() + + # Busca e retorna o registro de cidade desejado + return { + 'message': 'Registro de cidade atualizado com sucesso', + 'data': self.update_service.execute(cidade_id, g_cidade_schema) + } + + # Exclui um registro de cidade + def delete(self, g_cidade_schema: GCidadeIdSchema): + + #Importação da classe desejada + delete_service = self.dynamic_import.service('g_cidade_delete_service', 'DeleteService') + + # Instância da classe desejada + self.delete_service = delete_service() + + # Busca e retorna o registro de cidade desejado + return { + 'message': 'Registro de cidade removido com sucesso', + 'data': self.delete_service.execute(g_cidade_schema) + } \ No newline at end of file diff --git a/packages/v1/administrativo/endpoints/g_cidade_endpoint.py b/packages/v1/administrativo/endpoints/g_cidade_endpoint.py new file mode 100644 index 0000000..f1224db --- /dev/null +++ b/packages/v1/administrativo/endpoints/g_cidade_endpoint.py @@ -0,0 +1,109 @@ +# Importação de bibliotecas +from typing import Optional +from fastapi import APIRouter, Body, Depends, status +from actions.jwt.get_current_user import get_current_user +from packages.v1.administrativo.controllers.g_cidade_controller import GCidadeController +from packages.v1.administrativo.schemas.g_cidade_schema import ( + GCidadeSchema, + GCidadeSaveSchema, + GCidadeUpdateSchema, + GCidadeIdSchema, + GCidadeNomeSchema +) + +# Inicializa o roteador para as rotas do tipo de reconhecimento +router = APIRouter() + +# Instanciamento do controller desejado +g_cidade_controller = GCidadeController() + +# Lista todos os registros de cidade +@router.get('/', + status_code=status.HTTP_200_OK, + summary='Lista todos os registros de cidade cadastrados', + response_description='Lista todos os registros de cidade cadastrados') +async def index(current_user: dict = Depends(get_current_user)): + + # Busca todos os registros de cidade cadastrados + response = g_cidade_controller.index() + + # Retorna os dados localizados + return response + + +# Localiza um registro de cidade pelo nome (CIDADE_NOME) +@router.get('/nome', + status_code=status.HTTP_200_OK, + summary='Busca um registro de cidade em específico pelo nome', + response_description='Busca um registro de cidade em específico') +async def get_by_nome(cidade_nome : str, current_user: dict = Depends(get_current_user)): + + # Cria o schema com os dados recebidos + g_cidade_schema = GCidadeNomeSchema(cidade_nome=cidade_nome) + + # Busca um registro de cidade específico pelo nome + response = g_cidade_controller.get_by_nome(g_cidade_schema) + + # Retorna os dados localizados + return response + + +# Localiza um registro de cidade pelo ID +@router.get('/{cidade_id}', + status_code=status.HTTP_200_OK, + summary='Busca um registro de cidade em específico pelo ID', + response_description='Busca um registro de cidade em específico') +async def show(cidade_id : int, current_user: dict = Depends(get_current_user)): + + # Cria o schema com os dados recebidos + g_cidade_schema = GCidadeIdSchema(cidade_id=cidade_id) + + # Busca um registro de cidade específico pelo ID + response = g_cidade_controller.show(g_cidade_schema) + + # Retorna os dados localizados + return response + + +# Cadastro de registro de cidade +@router.post('/', + status_code=status.HTTP_201_CREATED, + summary='Cadastra um registro de cidade', + response_description='Cadastra um registro de cidade') +async def save(g_cidade_schema: GCidadeSaveSchema, current_user: dict = Depends(get_current_user)): + + # Efetua o cadastro no banco de dados + response = g_cidade_controller.save(g_cidade_schema) + + # Retorna os dados localizados + return response + + +# Atualiza os dados de um registro de cidade +@router.put('/{cidade_id}', + status_code=status.HTTP_200_OK, + summary='Atualiza um registro de cidade', + response_description='Atualiza um registro de cidade') +async def update(cidade_id: int, g_cidade_schema: GCidadeUpdateSchema, current_user: dict = Depends(get_current_user)): + + # Efetua a atualização dos dados + response = g_cidade_controller.update(cidade_id, g_cidade_schema) + + # Retorna os dados localizados + return response + +# Exclui um determinado registro de cidade +@router.delete('/{cidade_id}', + status_code=status.HTTP_200_OK, + summary='Remove um registro de cidade', + response_description='Remove um registro de cidade') +async def delete(cidade_id: int, current_user: dict = Depends(get_current_user)): + + # Cria o schema com os dados recebidos + g_cidade_schema = GCidadeIdSchema(cidade_id=cidade_id) + + # Efetua a exclusão do registro de cidade + response = g_cidade_controller.delete(g_cidade_schema) + + # Retorna os dados localizados + return response \ No newline at end of file diff --git a/packages/v1/administrativo/repositories/g_cidade/g_cidade_delete_repository.py b/packages/v1/administrativo/repositories/g_cidade/g_cidade_delete_repository.py new file mode 100644 index 0000000..633130f --- /dev/null +++ b/packages/v1/administrativo/repositories/g_cidade/g_cidade_delete_repository.py @@ -0,0 +1,41 @@ +from abstracts.repository import BaseRepository +from packages.v1.administrativo.schemas.g_cidade_schema import GCidadeIdSchema +from fastapi import HTTPException, status + +class DeleteRepository(BaseRepository): + """ + Repositório para a operação de exclusão de um registro na tabela + G_CIDADE. + """ + + def execute(self, g_cidade_schema: GCidadeIdSchema): + """ + Executa a consulta SQL para remover um registro pelo ID (CIDADE_ID). + + Args: + g_cidade_schema (GCidadeIdSchema): O esquema com o ID a ser removido. + + Returns: + O resultado da operação de exclusão. + """ + try: + # Montagem do sql + sql = """ DELETE FROM G_CIDADE WHERE CIDADE_ID = :cidade_id """ + + # Preenchimento de parâmetros + params = { + "cidade_id": g_cidade_schema.cidade_id + } + + # Execução do sql + response = self.run(sql, params) + + # Retorna o resultado + return response + + except Exception as e: + # Informa que houve uma falha na exclusão + raise HTTPException( + status_code=status.HTTP_422_UNPROCESSABLE_ENTITY, + detail=f"Erro ao excluir G_CIDADE: {e}" + ) \ No newline at end of file diff --git a/packages/v1/administrativo/repositories/g_cidade/g_cidade_get_by_nome_repository.py b/packages/v1/administrativo/repositories/g_cidade/g_cidade_get_by_nome_repository.py new file mode 100644 index 0000000..08606b5 --- /dev/null +++ b/packages/v1/administrativo/repositories/g_cidade/g_cidade_get_by_nome_repository.py @@ -0,0 +1,29 @@ +from abstracts.repository import BaseRepository +from packages.v1.administrativo.schemas.g_cidade_schema import GCidadeNomeSchema + +class GetByNomeRepository(BaseRepository): + """ + Repositório para a operação de busca de um registro na tabela + G_CIDADE por nome (CIDADE_NOME). + """ + + def execute(self, g_cidade_schema: GCidadeNomeSchema): + """ + Executa a consulta SQL para buscar um registro pelo nome da cidade. + + Args: + g_cidade_schema (GCidadeNomeSchema): O esquema com o nome da cidade a ser buscada. + + Returns: + Um dicionário contendo os dados do registro ou None se não for encontrado. + """ + # Montagem do SQL + sql = """ SELECT * FROM G_CIDADE WHERE CIDADE_NOME = :cidade_nome """ + + # Preenchimento de parâmetros + params = { + 'cidade_nome': g_cidade_schema.cidade_nome + } + + # Execução do sql + return self.fetch_one(sql, params) \ No newline at end of file diff --git a/packages/v1/administrativo/repositories/g_cidade/g_cidade_index_repository.py b/packages/v1/administrativo/repositories/g_cidade/g_cidade_index_repository.py new file mode 100644 index 0000000..5782998 --- /dev/null +++ b/packages/v1/administrativo/repositories/g_cidade/g_cidade_index_repository.py @@ -0,0 +1,23 @@ +from abstracts.repository import BaseRepository + +class IndexRepository(BaseRepository): + """ + Repositório para a operação de listagem de todos os registros + na tabela G_CIDADE. + """ + + def execute(self): + """ + Executa a consulta SQL para buscar todos os registros. + + Returns: + Uma lista de dicionários contendo os dados dos registros. + """ + # Montagem do SQL + sql = """ SELECT * FROM G_CIDADE """ + + # Execução do sql + response = self.fetch_all(sql) + + # Retorna os dados localizados + return response \ No newline at end of file diff --git a/packages/v1/administrativo/repositories/g_cidade/g_cidade_save_repository.py b/packages/v1/administrativo/repositories/g_cidade/g_cidade_save_repository.py new file mode 100644 index 0000000..4184fb1 --- /dev/null +++ b/packages/v1/administrativo/repositories/g_cidade/g_cidade_save_repository.py @@ -0,0 +1,59 @@ +from fastapi import HTTPException, status +from abstracts.repository import BaseRepository +from packages.v1.administrativo.schemas.g_cidade_schema import GCidadeSaveSchema + + +class SaveRepository(BaseRepository): + """ + Repositório para a operação de salvamento de um novo registro na tabela G_CIDADE. + """ + + def execute(self, g_cidade_schema: GCidadeSaveSchema): + """ + Executa a operação de salvamento no banco de dados. + + Args: + g_cidade_schema (GCidadeSaveSchema): O esquema com os dados a serem salvos. + + Returns: + O registro recém-criado. + + Raises: + HTTPException: Caso ocorra um erro na execução da query. + """ + try: + + # Montagem do SQL + sql = """ INSERT INTO G_CIDADE( + CIDADE_ID, + UF, + CIDADE_NOME, + CODIGO_IBGE, + CODIGO_GYN + ) VALUES ( + :cidade_id, + :uf, + :cidade_nome, + :codigo_ibge, + :codigo_gyn + ) RETURNING *;""" + + # Preenchimento de parâmetros + params = { + 'cidade_id': g_cidade_schema.cidade_id, + 'uf': g_cidade_schema.uf, + 'cidade_nome': g_cidade_schema.cidade_nome, + 'codigo_ibge': g_cidade_schema.codigo_ibge, + 'codigo_gyn': g_cidade_schema.codigo_gyn + } + + # Execução do sql + return self.run_and_return(sql, params) + + except Exception as e: + + # Informa que houve uma falha no salvamento do registro + raise HTTPException( + status_code=status.HTTP_422_UNPROCESSABLE_ENTITY, + detail=f"Erro ao salvar G_CIDADE: {e}" + ) \ No newline at end of file diff --git a/packages/v1/administrativo/repositories/g_cidade/g_cidade_show_repository.py b/packages/v1/administrativo/repositories/g_cidade/g_cidade_show_repository.py new file mode 100644 index 0000000..91c3eae --- /dev/null +++ b/packages/v1/administrativo/repositories/g_cidade/g_cidade_show_repository.py @@ -0,0 +1,46 @@ +from abstracts.repository import BaseRepository +from packages.v1.administrativo.schemas.g_cidade_schema import GCidadeIdSchema +from fastapi import HTTPException, status + +class ShowRepository(BaseRepository): + """ + Repositório para a operação de exibição de um registro na tabela G_CIDADE. + """ + + def execute(self, g_cidade_schema: GCidadeIdSchema): + """ + Busca um registro específico de G_CIDADE pelo ID (CIDADE_ID). + + Args: + g_cidade_schema (GCidadeIdSchema): O esquema que contém o ID do registro. + + Returns: + O registro encontrado ou None se não existir. + + Raises: + HTTPException: Caso ocorra um erro na execução da query. + """ + try: + # Montagem do SQL + sql = "SELECT * FROM G_CIDADE WHERE CIDADE_ID = :cidade_id" + + # Preenchimento de parâmetros + params = { + 'cidade_id': g_cidade_schema.cidade_id + } + + # Execução do SQL + result = self.fetch_one(sql, params) + + if not result: + raise HTTPException( + status_code=status.HTTP_404_NOT_FOUND, + detail="Registro não encontrado" + ) + + return result + except Exception as e: + raise HTTPException( + status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, + detail=f"Erro ao buscar registro: {str(e)}" + ) \ No newline at end of file diff --git a/packages/v1/administrativo/repositories/g_cidade/g_cidade_update_repository.py b/packages/v1/administrativo/repositories/g_cidade/g_cidade_update_repository.py new file mode 100644 index 0000000..be89bdd --- /dev/null +++ b/packages/v1/administrativo/repositories/g_cidade/g_cidade_update_repository.py @@ -0,0 +1,52 @@ +from abstracts.repository import BaseRepository +from packages.v1.administrativo.schemas.g_cidade_schema import GCidadeUpdateSchema +from fastapi import HTTPException, status + + +class UpdateRepository(BaseRepository): + """ + Repositório para a operação de atualização de um registro na tabela G_CIDADE. + """ + + def execute(self, cidade_id: int, g_cidade_schema: GCidadeUpdateSchema): + """ + Executa a operação de atualização no banco de dados. + + Args: + cidade_id (int): O ID (CIDADE_ID) do registro a ser atualizado. + g_cidade_schema (GCidadeUpdateSchema): O esquema com os dados a serem atualizados. + + Returns: + O registro atualizado. + + Raises: + HTTPException: Caso ocorra um erro na execução da query. + """ + try: + # Montagem do SQL + sql = """ UPDATE G_CIDADE SET + UF = :uf, + CIDADE_NOME = :cidade_nome, + CODIGO_IBGE = :codigo_ibge, + CODIGO_GYN = :codigo_gyn + WHERE CIDADE_ID = :cidade_id + RETURNING *;""" + + # Preenchimento de parâmetros + params = { + 'cidade_id': cidade_id, + 'uf': g_cidade_schema.uf, + 'cidade_nome': g_cidade_schema.cidade_nome, + 'codigo_ibge': g_cidade_schema.codigo_ibge, + 'codigo_gyn': g_cidade_schema.codigo_gyn + } + + # Execução do sql + return self.run_and_return(sql, params) + + except Exception as e: + # Informa que houve uma falha na atualização + raise HTTPException( + status_code=status.HTTP_422_UNPROCESSABLE_ENTITY, + detail=f"Erro ao atualizar G_CIDADE: {e}" + ) \ No newline at end of file diff --git a/packages/v1/administrativo/schemas/g_cidade_schema.py b/packages/v1/administrativo/schemas/g_cidade_schema.py new file mode 100644 index 0000000..cc8f50a --- /dev/null +++ b/packages/v1/administrativo/schemas/g_cidade_schema.py @@ -0,0 +1,127 @@ +from pydantic import BaseModel, field_validator, model_validator +from fastapi import HTTPException, status +from typing import Optional + +# Assumindo que esta importação de validação está disponível no ambiente +from actions.validations.text import Text + +# ---------------------------------------------------- +# Schema base +# ---------------------------------------------------- +class GCidadeSchema(BaseModel): + """ + Schema base para a tabela G_CIDADE. + Representa a estrutura completa do registro. + """ + cidade_id: int + uf: Optional[str] = None + cidade_nome: Optional[str] = None + codigo_ibge: Optional[str] = None + codigo_gyn: Optional[str] = None + + class Config: + from_attributes = True + + +# ---------------------------------------------------- +# Schema para localizar um G_CIDADE especifico pelo ID (GET/DELETE) +# ---------------------------------------------------- +class GCidadeIdSchema(BaseModel): + """ + Schema para busca (SHOW) ou exclusão (DELETE) de registro por ID (CIDADE_ID). + """ + cidade_id: int + + +# ---------------------------------------------------- +# Schema para localizar um G_CIDADE especifico pelo nome (GET) +# ---------------------------------------------------- +class GCidadeNomeSchema(BaseModel): + """ + Schema para busca de registro por nome (CIDADE_NOME). + """ + cidade_nome: str + + +# ---------------------------------------------------- +# Schema para criação de novo G_CIDADE (POST) +# ---------------------------------------------------- +class GCidadeSaveSchema(BaseModel): + """ + Schema para salvar (POST) um novo registro de G_CIDADE. + Os campos CIDADE_ID, UF e CIDADE_NOME são considerados obrigatórios. + """ + cidade_id: Optional[int] = None + uf: str + cidade_nome: str + codigo_ibge: Optional[str] = None + codigo_gyn: Optional[str] = None + + # Sanitiza os inputs enviados + @field_validator('uf', 'cidade_nome', 'codigo_ibge', 'codigo_gyn') + def sanitize_fields(cls, v): + if v: + return Text.sanitize_input(v) + return v + + # Verifica se os campos obrigatórios (UF, CIDADE_NOME) foram enviados + @model_validator(mode='after') + def validate_all_fields(self): + errors = [] + + # O campo 'cidade_id' é checado pela tipagem do Pydantic + + if not self.uf or len(self.uf.strip()) == 0: + errors.append({'input': 'uf', 'message': 'O campo UF é obrigatório.'}) + + if not self.cidade_nome or len(self.cidade_nome.strip()) == 0: + errors.append({'input': 'cidade_nome', 'message': 'O nome da cidade é obrigatório.'}) + + if errors: + raise HTTPException( + status_code=status.HTTP_422_UNPROCESSABLE_ENTITY, + detail=errors + ) + + return self + + +# ---------------------------------------------------- +# Schema para atualizar G_CIDADE (PUT) +# ---------------------------------------------------- +class GCidadeUpdateSchema(BaseModel): + """ + Schema para atualizar (PUT) um registro de G_CIDADE. + Todos os campos são opcionais, exceto o ID que virá na rota. + """ + uf: Optional[str] = None + cidade_nome: Optional[str] = None + codigo_ibge: Optional[str] = None + codigo_gyn: Optional[str] = None + + # Sanitiza os inputs enviados + @field_validator('uf', 'cidade_nome', 'codigo_ibge', 'codigo_gyn') + def sanitize_fields(cls, v): + if v: + return Text.sanitize_input(v) + return v + + # Valida se os campos que foram enviados não estão vazios + @model_validator(mode='after') + def validate_all_fields(self): + errors = [] + + # Verifica se o campo foi enviado (self.uf is not None) e se a string está vazia após strip + if self.uf is not None and len(self.uf.strip()) == 0: + errors.append({'input': 'uf', 'message': 'O campo UF não pode ser vazio.'}) + + if self.cidade_nome is not None and len(self.cidade_nome.strip()) == 0: + errors.append({'input': 'cidade_nome', 'message': 'O nome da cidade não pode ser vazio.'}) + + if errors: + raise HTTPException( + status_code=status.HTTP_422_UNPROCESSABLE_ENTITY, + detail=errors + ) + + return self \ No newline at end of file diff --git a/packages/v1/administrativo/services/g_cidade/go/g_cidade_delete_service.py b/packages/v1/administrativo/services/g_cidade/go/g_cidade_delete_service.py new file mode 100644 index 0000000..3fb81cd --- /dev/null +++ b/packages/v1/administrativo/services/g_cidade/go/g_cidade_delete_service.py @@ -0,0 +1,27 @@ +from packages.v1.administrativo.schemas.g_cidade_schema import GCidadeIdSchema +from packages.v1.administrativo.actions.g_cidade.g_cidade_delete_action import DeleteAction + +class DeleteService: + """ + Serviço responsável por encapsular a lógica de negócio para a operação + de exclusão de um registro na tabela G_CIDADE. + """ + + def execute(self, g_cidade_schema: GCidadeIdSchema): + """ + Executa a operação de exclusão do registro no banco de dados. + + Args: + g_cidade_schema (GCidadeIdSchema): O esquema com o ID do registro a ser excluído. + + Returns: + O resultado da operação de exclusão. + """ + # Instanciamento da ação + delete_action = DeleteAction() + + # Executa a ação em questão + data = delete_action.execute(g_cidade_schema) + + # Retorno da informação + return data \ No newline at end of file diff --git a/packages/v1/administrativo/services/g_cidade/go/g_cidade_get_nome_service.py b/packages/v1/administrativo/services/g_cidade/go/g_cidade_get_nome_service.py new file mode 100644 index 0000000..5b89c26 --- /dev/null +++ b/packages/v1/administrativo/services/g_cidade/go/g_cidade_get_nome_service.py @@ -0,0 +1,38 @@ +from fastapi import HTTPException, status +from packages.v1.administrativo.schemas.g_cidade_schema import GCidadeNomeSchema +from packages.v1.administrativo.actions.g_cidade.g_cidade_get_by_nome_action import GetByNomeAction + +class GetByNomeService: + """ + Serviço responsável por encapsular a lógica de negócio para a operação + de busca de um registro na tabela G_CIDADE pelo nome da cidade (CIDADE_NOME). + """ + + def execute(self, g_cidade_schema: GCidadeNomeSchema, messageValidate: bool): + """ + Executa a operação de busca no banco de dados. + + Args: + g_cidade_schema (GCidadeNomeSchema): O esquema com o nome da cidade a ser buscada. + messageValidate (bool): Se True, lança uma exceção HTTP caso o registro não seja encontrado. + + Returns: + O registro encontrado ou None. + """ + # Instanciamento da ação + show_action = GetByNomeAction() + + # Executa a ação em questão + data = show_action.execute(g_cidade_schema) + + if messageValidate: + + if not data: + # Retorna uma exceção + raise HTTPException( + status_code=status.HTTP_404_NOT_FOUND, + detail='Não foi possível localizar o registro de CIDADE' + ) + + # Retorno da informação + return data \ No newline at end of file diff --git a/packages/v1/administrativo/services/g_cidade/go/g_cidade_index_service.py b/packages/v1/administrativo/services/g_cidade/go/g_cidade_index_service.py new file mode 100644 index 0000000..a705692 --- /dev/null +++ b/packages/v1/administrativo/services/g_cidade/go/g_cidade_index_service.py @@ -0,0 +1,32 @@ +from fastapi import HTTPException, status +from packages.v1.administrativo.actions.g_cidade.g_cidade_index_action import IndexAction + +class IndexService: + """ + Serviço responsável por encapsular a lógica de negócio para a operação + de listagem de registros na tabela G_CIDADE. + """ + + def execute(self): + """ + Executa a operação de busca de todos os registros no banco de dados. + + Returns: + A lista de registros encontrados. + """ + # Instanciamento da ação + index_action = IndexAction() + + # Executa a busca de todas as ações + data = index_action.execute() + + # Verifica se foram localizados registros + if not data: + # Retorna uma exceção + raise HTTPException( + status_code=status.HTTP_404_NOT_FOUND, + detail='Não foi possível localizar os registros de CIDADE' + ) + + # Retorna as informações localizadas + return data \ No newline at end of file diff --git a/packages/v1/administrativo/services/g_cidade/go/g_cidade_save_service.py b/packages/v1/administrativo/services/g_cidade/go/g_cidade_save_service.py new file mode 100644 index 0000000..45ce084 --- /dev/null +++ b/packages/v1/administrativo/services/g_cidade/go/g_cidade_save_service.py @@ -0,0 +1,70 @@ +from actions.dynamic_import.dynamic_import import DynamicImport +from packages.v1.sequencia.schemas.g_sequencia import GSequenciaSchema +from packages.v1.sequencia.services.g_sequencia.generate_service import GenerateService +from packages.v1.administrativo.schemas.g_cidade_schema import GCidadeSaveSchema, GCidadeNomeSchema +from packages.v1.administrativo.actions.g_cidade.g_cidade_save_action import SaveAction +from fastapi import HTTPException, status + +class SaveService: + + def __init__(self): + # Action responsável por carregar as services de acordo com o estado + self.dynamic_import = DynamicImport() + + # Define o pacote que deve ser carregado + self.dynamic_import.set_package("administrativo") + + # Define a tabela que o pacote pertence + self.dynamic_import.set_table("g_cidade") + pass + + # Cadastra o novo G_CIDADE + def execute(self, g_cidade_schema: GCidadeSaveSchema): + + # Armazena possíveis erros + errors = [] + + # Verifica se o nome da cidade já está sendo utilizada + # Importação de service + nome_service = self.dynamic_import.service("g_cidade_get_nome_service", "GetByNomeService") + + # Instanciamento da service + self.nome_service = nome_service() + + # Verifica se o nome da cidade já está sendo utilizada + self.response = self.nome_service.execute(GCidadeNomeSchema(cidade_nome=g_cidade_schema.cidade_nome), False) + + # Se houver retorno significa que o nome da cidade já está sendo utilizado + if self.response: + errors.append({'input': 'cidade_nome', 'message': 'O nome da cidade informado já está sendo utilizado.'}) + + # Se houver erros, lança a exceção + if errors: + raise HTTPException( + status_code=status.HTTP_403_FORBIDDEN, + detail=errors + ) + + # Verifica se precisa gerar o ID de sequência + if not g_cidade_schema.cidade_id: + + # Crio um objeto de sequencia + sequencia_schema = GSequenciaSchema() + + # Define os dados para atualizar a sequencia + sequencia_schema.tabela = 'G_CIDADE' # Nome da tabela para a sequência + + # Busco a sequência atualizada + generate = GenerateService() + + # Busco a sequência atualizada + sequencia = generate.execute(sequencia_schema) + + # Atualiza os dados da chave primária + g_cidade_schema.cidade_id = sequencia.sequencia + + # Instanciamento de ações + save_action = SaveAction() + + # Retorna o resultado da operação + return save_action.execute(g_cidade_schema) \ No newline at end of file diff --git a/packages/v1/administrativo/services/g_cidade/go/g_cidade_show_service.py b/packages/v1/administrativo/services/g_cidade/go/g_cidade_show_service.py new file mode 100644 index 0000000..88a6c7f --- /dev/null +++ b/packages/v1/administrativo/services/g_cidade/go/g_cidade_show_service.py @@ -0,0 +1,35 @@ +from fastapi import HTTPException, status +from packages.v1.administrativo.schemas.g_cidade_schema import GCidadeIdSchema +from packages.v1.administrativo.actions.g_cidade.g_cidade_show_action import ShowAction + +class ShowService: + """ + Serviço responsável por encapsular a lógica de negócio para a operação + de busca de um registro na tabela G_CIDADE pelo seu ID (CIDADE_ID). + """ + + def execute(self, g_cidade_schema: GCidadeIdSchema): + """ + Executa a operação de busca no banco de dados. + + Args: + g_cidade_schema (GCidadeIdSchema): O esquema com o ID a ser buscado. + + Returns: + O resultado da busca (o registro encontrado). + """ + # Instanciamento da ação + show_action = ShowAction() + + # Executa a ação em questão + data = show_action.execute(g_cidade_schema) + + if not data: + # Retorna uma exceção se o registro não for encontrado + raise HTTPException( + status_code=status.HTTP_404_NOT_FOUND, + detail='Não foi possível localizar o registro de CIDADE' + ) + + # Retorno da informação + return data \ No newline at end of file diff --git a/packages/v1/administrativo/services/g_cidade/go/g_cidade_update_service.py b/packages/v1/administrativo/services/g_cidade/go/g_cidade_update_service.py new file mode 100644 index 0000000..df88a70 --- /dev/null +++ b/packages/v1/administrativo/services/g_cidade/go/g_cidade_update_service.py @@ -0,0 +1,24 @@ +from packages.v1.administrativo.schemas.g_cidade_schema import GCidadeUpdateSchema +from packages.v1.administrativo.actions.g_cidade.g_cidade_update_action import UpdateAction + +class UpdateService: + """ + Serviço para a operação de atualização de um registro na tabela + G_CIDADE. + """ + def execute(self, cidade_id : int, g_cidade_schema: GCidadeUpdateSchema): + """ + Executa a operação de atualização no banco de dados. + + Args: + cidade_id (int): O ID (CIDADE_ID) do registro a ser atualizado. + g_cidade_schema (GCidadeUpdateSchema): O esquema com os dados a serem atualizados. + + Returns: + O resultado da operação de atualização. + """ + # Instanciamento de ações + update_action = UpdateAction() + + # Retorna o resultado da operação + return update_action.execute(cidade_id, g_cidade_schema) \ No newline at end of file diff --git a/packages/v1/api.py b/packages/v1/api.py index f71a171..0095a87 100644 --- a/packages/v1/api.py +++ b/packages/v1/api.py @@ -19,6 +19,7 @@ from packages.v1.administrativo.endpoints import g_medida_tipo_endpoint from packages.v1.administrativo.endpoints import t_minuta_endpoint from packages.v1.administrativo.endpoints import g_tb_bairro_endpoint from packages.v1.administrativo.endpoints import g_tb_tipologradouro_endpoint +from packages.v1.administrativo.endpoints import g_cidade_endpoint # Cria uma instância do APIRouter que vai agregar todas as rotas da API api_router = APIRouter() @@ -110,4 +111,10 @@ api_router.include_router( # Inclui as rotas de g_tb_tipologradouro api_router.include_router( g_tb_tipologradouro_endpoint.router, prefix="/administrativo/g_tb_tipologradouro", tags=["Tipo logradouro"] +) + + +# Inclui as rotas de g_cidade +api_router.include_router( + g_cidade_endpoint.router, prefix="/administrativo/g_cidade", tags=["Cidades"] ) \ No newline at end of file From 729c374a1cf90c8030c175de01de80831061ad6f Mon Sep 17 00:00:00 2001 From: Kenio de Souza Date: Fri, 26 Sep 2025 13:08:23 -0300 Subject: [PATCH 5/5] =?UTF-8?q?[MVPTN-91]=20feat(Crud):=20Cria=C3=A7=C3=A3?= =?UTF-8?q?o=20do=20endpoint=20que=20retorna=20todos=20os=20estados=20bras?= =?UTF-8?q?ileiros?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../actions/g_uf/g_uf_index_action.py | 24 ++++++++++++++ .../controllers/g_uf_controller.py | 32 +++++++++++++++++++ .../administrativo/endpoints/g_uf_endpoint.py | 25 +++++++++++++++ .../g_uf/g_uf_index_repository.py | 23 +++++++++++++ .../v1/administrativo/schemas/g_uf_schema.py | 18 +++++++++++ .../services/g_uf/go/g_uf_index_service.py | 32 +++++++++++++++++++ packages/v1/api.py | 6 ++++ 7 files changed, 160 insertions(+) create mode 100644 packages/v1/administrativo/actions/g_uf/g_uf_index_action.py create mode 100644 packages/v1/administrativo/controllers/g_uf_controller.py create mode 100644 packages/v1/administrativo/endpoints/g_uf_endpoint.py create mode 100644 packages/v1/administrativo/repositories/g_uf/g_uf_index_repository.py create mode 100644 packages/v1/administrativo/schemas/g_uf_schema.py create mode 100644 packages/v1/administrativo/services/g_uf/go/g_uf_index_service.py diff --git a/packages/v1/administrativo/actions/g_uf/g_uf_index_action.py b/packages/v1/administrativo/actions/g_uf/g_uf_index_action.py new file mode 100644 index 0000000..7ecff70 --- /dev/null +++ b/packages/v1/administrativo/actions/g_uf/g_uf_index_action.py @@ -0,0 +1,24 @@ +from abstracts.action import BaseAction +from packages.v1.administrativo.repositories.g_uf.g_uf_index_repository import IndexRepository + +class IndexAction(BaseAction): + """ + Serviço responsável por encapsular a lógica de negócio para a operação + de listagem de todos os registros na tabela G_UF. + """ + + def execute(self): + """ + Executa a operação de listagem no banco de dados. + + Returns: + A lista de todos os registros. + """ + # Instanciamento do repositório + index_repository = IndexRepository() + + # Execução do repositório + response = index_repository.execute() + + # Retorno da informação + return response \ No newline at end of file diff --git a/packages/v1/administrativo/controllers/g_uf_controller.py b/packages/v1/administrativo/controllers/g_uf_controller.py new file mode 100644 index 0000000..35b0b58 --- /dev/null +++ b/packages/v1/administrativo/controllers/g_uf_controller.py @@ -0,0 +1,32 @@ +from actions.dynamic_import.dynamic_import import DynamicImport +from packages.v1.administrativo.schemas.g_uf_schema import ( + GUfSchema +) + +class GUfController: + + def __init__(self): + # Action responsável por carregar as services de acordo com o estado + self.dynamic_import = DynamicImport() + + # Define o pacote que deve ser carregado + self.dynamic_import.set_package("administrativo") + + # Define a tabela que o pacote pertence + self.dynamic_import.set_table("g_uf") + pass + + # Lista todos os registros de g_uf + def index(self): + + # Importação da classe desejada + indexService = self.dynamic_import.service("g_uf_index_service", "IndexService") + + # Instância da classe service + self.indexService = indexService() + + # Lista todos os registros de g_uf + return { + 'message': 'Registros de g_uf localizados com sucesso', + 'data': self.indexService.execute() + } \ No newline at end of file diff --git a/packages/v1/administrativo/endpoints/g_uf_endpoint.py b/packages/v1/administrativo/endpoints/g_uf_endpoint.py new file mode 100644 index 0000000..adb0c95 --- /dev/null +++ b/packages/v1/administrativo/endpoints/g_uf_endpoint.py @@ -0,0 +1,25 @@ +# Importação de bibliotecas +from typing import Optional +from fastapi import APIRouter, Body, Depends, status +from actions.jwt.get_current_user import get_current_user +from packages.v1.administrativo.controllers.g_uf_controller import GUfController +from packages.v1.administrativo.schemas.g_uf_schema import GUfSchema + +# Inicializa o roteador para as rotas do tipo de reconhecimento +router = APIRouter() + +# Instanciamento do controller desejado +g_uf_controller = GUfController() + +# Lista todos os registros de uf +@router.get('/', + status_code=status.HTTP_200_OK, + summary='Lista todos os registros de UF cadastrados', + response_description='Lista todos os registros de UF cadastrados') +async def index(current_user: dict = Depends(get_current_user)): + + # Busca todos os registros de uf cadastrados + response = g_uf_controller.index() + + # Retorna os dados localizados + return response \ No newline at end of file diff --git a/packages/v1/administrativo/repositories/g_uf/g_uf_index_repository.py b/packages/v1/administrativo/repositories/g_uf/g_uf_index_repository.py new file mode 100644 index 0000000..57db0db --- /dev/null +++ b/packages/v1/administrativo/repositories/g_uf/g_uf_index_repository.py @@ -0,0 +1,23 @@ +from abstracts.repository import BaseRepository + +class IndexRepository(BaseRepository): + """ + Repositório para a operação de listagem de todos os registros + na tabela G_UF. + """ + + def execute(self): + """ + Executa a consulta SQL para buscar todos os registros. + + Returns: + Uma lista de dicionários contendo os dados dos registros. + """ + # Montagem do SQL + sql = """ SELECT * FROM G_UF """ + + # Execução do sql + response = self.fetch_all(sql) + + # Retorna os dados localizados + return response \ No newline at end of file diff --git a/packages/v1/administrativo/schemas/g_uf_schema.py b/packages/v1/administrativo/schemas/g_uf_schema.py new file mode 100644 index 0000000..05c7f68 --- /dev/null +++ b/packages/v1/administrativo/schemas/g_uf_schema.py @@ -0,0 +1,18 @@ +from pydantic import BaseModel, field_validator, model_validator +from fastapi import HTTPException, status +from typing import Optional + +# Funções para sanitização de entradas (evitar XSS, SQLi etc.) +from actions.validations.text import Text + +# ---------------------------------------------------- +# Schema base +# ---------------------------------------------------- +class GUfSchema(BaseModel): + g_uf_id: Optional[int] = None + sigla: Optional[str] = None + nome: Optional[str] = None + cod_uf_ibge: Optional[str] = None + + class Config: + from_attributes = True diff --git a/packages/v1/administrativo/services/g_uf/go/g_uf_index_service.py b/packages/v1/administrativo/services/g_uf/go/g_uf_index_service.py new file mode 100644 index 0000000..bba8a48 --- /dev/null +++ b/packages/v1/administrativo/services/g_uf/go/g_uf_index_service.py @@ -0,0 +1,32 @@ +from fastapi import HTTPException, status +from packages.v1.administrativo.actions.g_uf.g_uf_index_action import IndexAction + +class IndexService: + """ + Serviço responsável por encapsular a lógica de negócio para a operação + de listagem de registros na tabela G_UF. + """ + + def execute(self): + """ + Executa a operação de busca de todos os registros no banco de dados. + + Returns: + A lista de registros encontrados. + """ + # Instanciamento da ação + index_action = IndexAction() + + # Executa a busca de todas as ações + data = index_action.execute() + + # Verifica se foram localizados registros + if not data: + # Retorna uma exceção + raise HTTPException( + status_code=status.HTTP_404_NOT_FOUND, + detail='Não foi possível localizar os registros de UF' + ) + + # Retorna as informações localizadas + return data \ No newline at end of file diff --git a/packages/v1/api.py b/packages/v1/api.py index 0095a87..d187659 100644 --- a/packages/v1/api.py +++ b/packages/v1/api.py @@ -20,6 +20,7 @@ from packages.v1.administrativo.endpoints import t_minuta_endpoint from packages.v1.administrativo.endpoints import g_tb_bairro_endpoint from packages.v1.administrativo.endpoints import g_tb_tipologradouro_endpoint from packages.v1.administrativo.endpoints import g_cidade_endpoint +from packages.v1.administrativo.endpoints import g_uf_endpoint # Cria uma instância do APIRouter que vai agregar todas as rotas da API api_router = APIRouter() @@ -117,4 +118,9 @@ api_router.include_router( # Inclui as rotas de g_cidade api_router.include_router( g_cidade_endpoint.router, prefix="/administrativo/g_cidade", tags=["Cidades"] +) + +# Inclui as rotas de g_uf +api_router.include_router( + g_uf_endpoint.router, prefix="/administrativo/g_uf", tags=["Estados"] ) \ No newline at end of file