diff --git a/packages/v1/sequencia/actions/g_sequencia/checkout_action.py b/packages/v1/sequencia/actions/g_sequencia/checkout_action.py new file mode 100644 index 0000000..03e849b --- /dev/null +++ b/packages/v1/sequencia/actions/g_sequencia/checkout_action.py @@ -0,0 +1,14 @@ +from packages.v1.sequencia.repositories.g_sequencia.checkout import Checkout +from packages.v1.sequencia.schemas.g_sequencia import GSequenciaSchema +from abstracts.action import BaseAction + + +class CheckoutAction(BaseAction): + + def execute(self, sequencia_schema : GSequenciaSchema): + + # Instânciamento de repositório + checkout = Checkout() + + # Execução do repositório + return checkout.execute(sequencia_schema) \ No newline at end of file diff --git a/packages/v1/sequencia/repositories/g_sequencia/checkout.py b/packages/v1/sequencia/repositories/g_sequencia/checkout.py new file mode 100644 index 0000000..b288d8e --- /dev/null +++ b/packages/v1/sequencia/repositories/g_sequencia/checkout.py @@ -0,0 +1,67 @@ +from packages.v1.sequencia.schemas.g_sequencia import GSequenciaSchema +from abstracts.repository import BaseRepository +from fastapi import HTTPException, status + + +class Checkout(BaseRepository): + + def execute(self, sequencia_schema: GSequenciaSchema): + + # 1) Descobre o nome da PK a partir dos metadados + sql = """ + SELECT + sg.RDB$FIELD_NAME AS primary_key + FROM RDB$RELATION_CONSTRAINTS rc + JOIN RDB$INDEX_SEGMENTS sg + ON rc.RDB$INDEX_NAME = sg.RDB$INDEX_NAME + WHERE rc.RDB$CONSTRAINT_TYPE = 'PRIMARY KEY' + AND rc.RDB$RELATION_NAME = UPPER(:tabela) + ORDER BY sg.RDB$FIELD_POSITION + """ + params = {"tabela": sequencia_schema.tabela} + pk_result = self.fetch_one(sql, params) + + if not pk_result: + raise Exception(f"Tabela {sequencia_schema.tabela} não possui chave primária") + + pk_field = pk_result["primary_key"].strip() # Nome da coluna PK (ex: "ID") + + + # 2) Monta dinamicamente a query para buscar o último ID + sql = f"SELECT MAX({pk_field}) AS last_id FROM {sequencia_schema.tabela}" + + # Importante: aqui não dá para usar :param para nome de tabela/coluna + last_id = self.fetch_one(sql) + + # 3) Verifica se a tabela foi cadastrada no G_SEQUENCIA + sql = """ + SELECT * + FROM G_SEQUENCIA + WHERE TABELA = :tabela + + """ + params = {"tabela": sequencia_schema.tabela} + gSequenciaResult = self.fetch_one(sql, params) + + # 4) Se não houver registro no g_sequencia, cadastro um novo + if not gSequenciaResult: + # Insere o registro na tabela de controle de sequência + sql = """ + INSERT INTO G_SEQUENCIA (TABELA, SEQUENCIA) + VALUES (:tabela, :sequencia) + """ + params = { + "tabela": sequencia_schema.tabela, + "sequencia": last_id["last_id"] if last_id["last_id"] is not None else 0 + } + self.run(sql, params) + + # Verifico se a quantidade atual de sequencia é igual a quantidade da tabela + elif gSequenciaResult["sequencia"] != last_id["last_id"]: + + # Caso a sequencia seja diferente do ultimo ID da tabela, retorno uma exceção + raise HTTPException( + status_code=status.HTTP_422_UNPROCESSABLE_ENTITY, + detail=f"A sequência atual ({gSequenciaResult['sequencia']}) está divergente do último ID da tabela ({last_id['last_id']})" + ) + diff --git a/packages/v1/sequencia/services/g_sequencia/checkout_service.py b/packages/v1/sequencia/services/g_sequencia/checkout_service.py new file mode 100644 index 0000000..656a303 --- /dev/null +++ b/packages/v1/sequencia/services/g_sequencia/checkout_service.py @@ -0,0 +1,25 @@ +from packages.v1.sequencia.actions.g_sequencia.checkout_action import CheckoutAction +from packages.v1.sequencia.schemas.g_sequencia import GSequenciaSchema +from fastapi import HTTPException, status + + +class GenerateService: + + def execute(self, sequencia_schema : GSequenciaSchema): + + # Instânciamento de Action + checkoutAction = CheckoutAction() + + # Atualiza a sequência atual + data = checkoutAction.execute(sequencia_schema) + + # Verifica se foi localizado o registro + if not data: + # Retorna uma exceção + raise HTTPException( + status_code=status.HTTP_404_NOT_FOUND, + detail='Não foi possível localizar a tabela para verificação de sequência' + ) + + # Retorna a informação localizada + return data diff --git a/packages/v1/sequencia/services/g_sequencia/generate_service.py b/packages/v1/sequencia/services/g_sequencia/generate_service.py index ca9e549..90a077c 100644 --- a/packages/v1/sequencia/services/g_sequencia/generate_service.py +++ b/packages/v1/sequencia/services/g_sequencia/generate_service.py @@ -1,6 +1,6 @@ from packages.v1.sequencia.actions.g_sequencia.get_action import GetAction -from packages.v1.sequencia.actions.g_sequencia.save_action import \ - SaveAction +from packages.v1.sequencia.actions.g_sequencia.save_action import SaveAction +from packages.v1.sequencia.actions.g_sequencia.checkout_action import CheckoutAction from packages.v1.sequencia.schemas.g_sequencia import GSequenciaSchema @@ -11,6 +11,10 @@ class GenerateService: # Instânciamento de Action getAction = GetAction() saveAction = SaveAction() + checkoutAction = CheckoutAction() + + # Verifico se a tabela existe no G_SEQUENCIA e se a sequência está correta + checkoutAction.execute(sequencia_schema) # Busco a sequência atual sequencia_result = getAction.execute(sequencia_schema)