first commit
This commit is contained in:
322
app/Module/Tutor/v0/Controllers/PetController.php
Executable file
322
app/Module/Tutor/v0/Controllers/PetController.php
Executable file
@@ -0,0 +1,322 @@
|
||||
<?php
|
||||
namespace Zampet\Module\Tutor\v0\Controllers;
|
||||
|
||||
use Zampet\Helpers\Sanitizer;
|
||||
use Zampet\Services\JWTService;
|
||||
use AxiumPHP\Helpers\RequestHelper;
|
||||
use Zampet\Module\Tutor\v0\DTO\PetDTO;
|
||||
use Zampet\Module\Tutor\v0\DTO\PetRacaDTO;
|
||||
use Zampet\Module\Tutor\v0\Services\PetService;
|
||||
|
||||
class PetController {
|
||||
/**
|
||||
* Lida com a requisição para listar todas as espécies de pets disponíveis.
|
||||
*
|
||||
* Este método atua como um **controlador** para um endpoint de API. Ele delega a busca da lista completa de espécies para o `PetService` e, em seguida, formata e envia a resposta ao cliente em JSON.
|
||||
*
|
||||
* #### Fluxo de Operação:
|
||||
* 1. **Delegação ao Serviço:** Uma instância de `PetService` é criada, e o método `getAllEspecies` é chamado para obter a lista de espécies. O serviço é responsável pela lógica de busca no modelo.
|
||||
* 2. **Envio da Resposta JSON:** O resultado retornado pelo serviço (`especiesPets`) é formatado para uma resposta JSON padronizada usando **`RequestHelper::sendJsonResponse`**. Os dados da resposta (código HTTP, status, mensagem e lista de espécies) são comunicados ao cliente.
|
||||
*
|
||||
* @return void Este método não retorna um valor, pois seu objetivo é enviar uma resposta JSON e encerrar a execução do script.
|
||||
*/
|
||||
public function getAllEspecies(): void {
|
||||
// Lista as espécies de pets
|
||||
$especiesPets = (new PetService())->getAllEspecies();
|
||||
|
||||
// Retorna a resposta em JSON
|
||||
RequestHelper::sendJsonResponse(
|
||||
response_code: $especiesPets['response_code'],
|
||||
status: $especiesPets['status'],
|
||||
message: $especiesPets['message'],
|
||||
output: $especiesPets['output'] ?? []
|
||||
);
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Lista todos os pets associados ao usuário atualmente autenticado.
|
||||
*
|
||||
* Este método atua como um **controlador** para um endpoint de API, responsável por identificar o usuário autenticado, buscar a lista de seus pets e retornar os dados em formato JSON padronizado.
|
||||
*
|
||||
* #### Fluxo de Operação:
|
||||
* 1. **Obtenção da Identidade do Usuário:** O método primeiro extrai e decodifica o token JWT presente no cabeçalho `Authorization` usando `JWTService::getBearerToken()` e `JWTService::decode()`. O UUID do usuário (tutor) é obtido diretamente do payload decodificado.
|
||||
* 2. **Delegação ao Serviço:** O método `listPetsByTutorUuid` do **`PetService`** é chamado, passando o UUID do usuário para buscar todos os pets associados.
|
||||
* 3. **Envio da Resposta JSON:** O resultado retornado pelo serviço (`petsTutor`) é formatado e enviado de volta ao cliente usando **`RequestHelper::sendJsonResponse`**.
|
||||
* * O código HTTP, status e mensagem são extraídos do array de resposta do serviço, garantindo que a resposta reflita o sucesso ou falha da operação de busca.
|
||||
*
|
||||
* @return void Este método não retorna um valor, pois seu objetivo é enviar uma resposta JSON e encerrar a execução do script.
|
||||
*/
|
||||
public function listMyPets(): void {
|
||||
// Recebe o token JWT do cabeçalho Authorization
|
||||
$decodedToken = JWTService::decode(token: JWTService::getBearerToken());
|
||||
|
||||
// Inicia o serviço de Pet
|
||||
$petsTutor = (new PetService())->listPetsByTutorUuid(uuid: $decodedToken['user_uuid']);
|
||||
|
||||
// Retorna a resposta em JSON
|
||||
RequestHelper::sendJsonResponse(
|
||||
response_code: $petsTutor['response_code'],
|
||||
status: $petsTutor['status'],
|
||||
message: $petsTutor['message'],
|
||||
output: $petsTutor['output'] ?? []
|
||||
);
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Lida com a requisição de criação de uma nova raça de pet.
|
||||
*
|
||||
* Este método atua como um **controlador** de API, responsável por receber os dados da nova raça (descrição) e o UUID da espécie, validar as entradas e orquestrar a criação do novo registro na camada de serviço.
|
||||
*
|
||||
* #### Fluxo de Operação:
|
||||
* 1. **Validação de Presença:** Verifica se os campos obrigatórios (`especie_uuid` e `descricao`) estão presentes. Se não estiverem, retorna uma resposta JSON com o código **400 Bad Request** e encerra a execução.
|
||||
* 2. **Busca e Validação da Espécie:** Chama `PetService::getEspecieByIdentifier` para confirmar a existência da espécie pelo UUID e obter seu ID interno. Se a espécie não for encontrada, retorna um erro `400`.
|
||||
* 3. **Preparação do DTO:** Cria e popula um **`PetRacaDTO`** com o ID interno da espécie e a descrição sanitizada.
|
||||
* 4. **Delegação ao Serviço:** O método `storeRaca` do **`PetService`** é chamado para executar a lógica de persistência e validação de negócio.
|
||||
* 5. **Envio da Resposta JSON:** O resultado do serviço (`serviceResult`) é formatado e enviado de volta ao cliente, comunicando o status (`201 Created` em caso de sucesso) e a mensagem da operação.
|
||||
*
|
||||
* @return void Este método não retorna um valor, pois seu objetivo é enviar uma resposta JSON e encerrar a execução do script.
|
||||
*/
|
||||
public function storeRaca(): void {
|
||||
// Receber dados do formulário de registro
|
||||
$form = RequestHelper::getFilteredInput(form_type: INPUT_POST);
|
||||
|
||||
// Campos Obrigatórios
|
||||
$required_fields = [
|
||||
'especie_uuid',
|
||||
'descricao'
|
||||
];
|
||||
|
||||
// Verificar se todos os campos obrigatórios estão presentes
|
||||
foreach ($required_fields as $field) {
|
||||
if (empty($form[$field])) {
|
||||
RequestHelper::sendJsonResponse(
|
||||
response_code: 400,
|
||||
status: 'error',
|
||||
message: "Field '{$field}' is required"
|
||||
);
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
||||
// Consulta informações da espécie com base no UUID fornecido
|
||||
$getEspecie = (new PetService())->getEspecieByIdentifier(
|
||||
identifier: 'uuid',
|
||||
value: $form['especie_uuid']
|
||||
);
|
||||
if($getEspecie['status'] !== 'success') {
|
||||
RequestHelper::sendJsonResponse(
|
||||
response_code: 400,
|
||||
status: 'error',
|
||||
message: "Espécie não encontrada",
|
||||
output: ['data' => $form]
|
||||
);
|
||||
exit;
|
||||
}
|
||||
$especieData = $getEspecie['output']['data'];
|
||||
|
||||
// Chama o serviço de criar raça
|
||||
$serviceResult = (new PetService())->storeRaca(
|
||||
petRacaDTO: new PetRacaDTO(data: [
|
||||
'especie_id' => $especieData['id'],
|
||||
'descricao' => Sanitizer::string(value: $form['descricao'] ?? '')
|
||||
])
|
||||
);
|
||||
|
||||
// Enviar a resposta JSON
|
||||
RequestHelper::sendJsonResponse(
|
||||
response_code: $serviceResult['response_code'],
|
||||
status: $serviceResult['status'],
|
||||
message: $serviceResult['message'],
|
||||
output: $serviceResult['output'] ?? []
|
||||
);
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Lida com a requisição de criação de um novo pet (animal de estimação).
|
||||
*
|
||||
* Este método atua como um **controlador** de API, responsável por receber os dados do formulário, realizar validações de presença e delegar a lógica de negócio (criação do pet e associação ao tutor) para o `PetService`.
|
||||
*
|
||||
* #### Fluxo de Operação:
|
||||
* 1. **Validação de Presença:** Verifica se os campos obrigatórios (`name`, `raca_uuid`, `birthDate`, `sexo`) estão presentes no formulário. Se algum estiver faltando, retorna um erro **400 Bad Request** e encerra a execução.
|
||||
* 2. **Busca e Validação da Raça/Espécie:** Chama `PetService::getEspecieByIdentifier` (apesar do nome, a lógica sugere que este método deve retornar a raça e a espécie) para validar o `raca_uuid` fornecido e obter os IDs internos. Se a raça não for encontrada ou a busca falhar, retorna um erro **400**.
|
||||
* 3. **Preparação do DTO:** Cria e popula um **`PetDTO`** com os dados sanitizados e os IDs internos da raça e espécie.
|
||||
* 4. **Delegação ao Serviço:** O método `storePet` do **`PetService`** é chamado para executar a lógica de persistência e associação do pet ao tutor autenticado.
|
||||
* 5. **Envio da Resposta JSON:** O resultado do serviço (`serviceResult`) é formatado e enviado de volta ao cliente, comunicando o status (código **201 Created** em caso de sucesso) e a mensagem da operação.
|
||||
*
|
||||
* @return void Este método não retorna um valor, pois seu objetivo é enviar uma resposta JSON e encerrar a execução do script.
|
||||
*/
|
||||
public function storePet(): void {
|
||||
// Receber dados do formulário de registro
|
||||
$form = RequestHelper::getFilteredInput(form_type: INPUT_POST);
|
||||
|
||||
// Campos Obrigatórios
|
||||
$required_fields = [
|
||||
'name',
|
||||
'raca_uuid',
|
||||
'birthDate',
|
||||
'sexo',
|
||||
];
|
||||
|
||||
// Verificar se todos os campos obrigatórios estão presentes
|
||||
foreach ($required_fields as $field) {
|
||||
if (empty($form[$field])) {
|
||||
RequestHelper::sendJsonResponse(
|
||||
response_code: 400,
|
||||
status: 'error',
|
||||
message: "Field '{$field}' is required"
|
||||
);
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
||||
// Consulta informações da raça com base no UUID fornecido
|
||||
$getRaca = (new PetService())->getRacaByIdentifier(
|
||||
identifier: 'uuid',
|
||||
value: $form['raca_uuid']
|
||||
);
|
||||
|
||||
if($getRaca['status'] !== 'success') {
|
||||
RequestHelper::sendJsonResponse(
|
||||
response_code: 400,
|
||||
status: 'error',
|
||||
message: "Raça não encontrada"
|
||||
);
|
||||
exit;
|
||||
}
|
||||
|
||||
// Chama o serviço de criar pet
|
||||
$serviceResult = (new PetService())->storePet(
|
||||
petDTO: new PetDTO(data: [
|
||||
"nome" => Sanitizer::string(value: $form['name'] ?? ''),
|
||||
"data_nascimento" => Sanitizer::string(value: $form['birthDate'] ?? ''),
|
||||
"sexo" => Sanitizer::string(value: $form['sexo'] ?? ''),
|
||||
"raca_id" => $getRaca['output']['data']['id'],
|
||||
"especie_id" => $getRaca['output']['data']['especie_id'],
|
||||
"registro_geral_animal" => Sanitizer::string(value: $form['registro_geral_animal'] ?? NULL),
|
||||
])
|
||||
);
|
||||
|
||||
// Enviar a resposta JSON
|
||||
RequestHelper::sendJsonResponse(
|
||||
response_code: $serviceResult['response_code'],
|
||||
status: $serviceResult['status'],
|
||||
message: $serviceResult['message'],
|
||||
output: $serviceResult['output'] ?? []
|
||||
);
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Lida com a requisição para obter detalhes de um pet específico por seu UUID.
|
||||
*
|
||||
* Este método atua como um **controlador** para um endpoint de API. Ele é responsável por delegar a busca dos dados do pet para o serviço e formatar a resposta para o cliente em JSON.
|
||||
*
|
||||
* #### Fluxo de Operação:
|
||||
* 1. **Busca de Detalhes:** O método chama `PetService::getPetByIdentifier()`, usando o UUID fornecido como identificador. O serviço lida com a lógica de consulta no modelo.
|
||||
* 2. **Envio da Resposta JSON:** O resultado retornado pelo serviço (`petDetails`) é formatado e enviado de volta ao cliente usando **`RequestHelper::sendJsonResponse`**. O código HTTP, status e mensagem são extraídos do array de resposta do serviço, comunicando o resultado da busca (sucesso ou falha).
|
||||
*
|
||||
* @param string $uuid O UUID do pet cujos detalhes devem ser buscados.
|
||||
* @return void Este método não retorna um valor, pois seu objetivo é enviar uma resposta JSON e encerrar a execução do script.
|
||||
*/
|
||||
public function getPetDetails(string $uuid): void {
|
||||
// Consulta detalhes do pet com base no UUID fornecido
|
||||
$petDetails = (new PetService())->getPetByIdentifier(
|
||||
identifier: 'uuid',
|
||||
value: $uuid
|
||||
);
|
||||
|
||||
if($petDetails['status'] !== 'success') {
|
||||
RequestHelper::sendJsonResponse(
|
||||
response_code: $petDetails['response_code'],
|
||||
status: $petDetails['status'],
|
||||
message: $petDetails['message'],
|
||||
output: $petDetails['output'] ?? []
|
||||
);
|
||||
exit;
|
||||
}
|
||||
$pet = $petDetails['output']['data'];
|
||||
$pet['vacinas'] = [
|
||||
[
|
||||
"id" => 1,
|
||||
"nome" => "Antirrábica",
|
||||
"fabricante" => "Zoetis",
|
||||
"lote" => "ZOE-2025-001",
|
||||
"validade" => "2026-02-15",
|
||||
"data_aplicacao" => "2025-02-10",
|
||||
"data_reforco" => "2026-02-10",
|
||||
"veterinario" => "Dr. Carlos Mendes",
|
||||
"created_at" => "2025-02-10 14:30:00",
|
||||
"updated_at" => null,
|
||||
"deleted_at" => null
|
||||
],
|
||||
[
|
||||
"id" => 2,
|
||||
"nome" => "V10",
|
||||
"fabricante" => "Boehringer Ingelheim",
|
||||
"lote" => "BIO-2025-044",
|
||||
"validade" => "2026-06-20",
|
||||
"data_aplicacao" => "2025-03-05",
|
||||
"data_reforco" => "2026-03-05",
|
||||
"veterinario" => "Dra. Fernanda Lopes",
|
||||
"created_at" => "2025-03-05 09:10:00",
|
||||
"updated_at" => null,
|
||||
"deleted_at" => null
|
||||
],
|
||||
[
|
||||
"id" => 3,
|
||||
"nome" => "Giárdia",
|
||||
"fabricante" => "Ceva",
|
||||
"lote" => "CEV-2025-321",
|
||||
"validade" => "2026-08-01",
|
||||
"data_aplicacao" => "2025-04-15",
|
||||
"data_reforco" => "2025-05-15",
|
||||
"veterinario" => "Dr. Rafael Silva",
|
||||
"created_at" => "2025-04-15 11:45:00",
|
||||
"updated_at" => null,
|
||||
"deleted_at" => null
|
||||
],
|
||||
[
|
||||
"id" => 4,
|
||||
"nome" => "Leptospirose",
|
||||
"fabricante" => "MSD",
|
||||
"lote" => "MSD-2025-112",
|
||||
"validade" => "2026-09-30",
|
||||
"data_aplicacao" => "2025-05-20",
|
||||
"data_reforco" => "2026-05-20",
|
||||
"veterinario" => "Dra. Ana Paula",
|
||||
"created_at" => "2025-05-20 10:00:00",
|
||||
"updated_at" => null,
|
||||
"deleted_at" => null
|
||||
],
|
||||
[
|
||||
"id" => 5,
|
||||
"nome" => "Cinomose",
|
||||
"fabricante" => "Vanguard",
|
||||
"lote" => "VAN-2025-210",
|
||||
"validade" => "2026-11-12",
|
||||
"data_aplicacao" => "2025-06-10",
|
||||
"data_reforco" => "2026-06-10",
|
||||
"veterinario" => "Dr. Eduardo Gomes",
|
||||
"created_at" => "2025-06-10 15:20:00",
|
||||
"updated_at" => null,
|
||||
"deleted_at" => null
|
||||
]
|
||||
];
|
||||
|
||||
// Retorna a resposta em JSON
|
||||
RequestHelper::sendJsonResponse(
|
||||
response_code: $petDetails['response_code'],
|
||||
status: $petDetails['status'],
|
||||
message: $petDetails['message'],
|
||||
output: ['data' => $pet] ?? []
|
||||
);
|
||||
exit;
|
||||
}
|
||||
|
||||
public function updatePet(string $uuid, array $params): void {
|
||||
|
||||
}
|
||||
}
|
||||
177
app/Module/Tutor/v0/DTO/PetDTO.php
Executable file
177
app/Module/Tutor/v0/DTO/PetDTO.php
Executable file
@@ -0,0 +1,177 @@
|
||||
<?php
|
||||
namespace Zampet\Module\Tutor\v0\DTO;
|
||||
|
||||
class PetDTO {
|
||||
private ?int $id = null;
|
||||
private ?string $uuid = null;
|
||||
private ?string $nome = null;
|
||||
private ?int $especie_id = null;
|
||||
private ?int $raca_id = null;
|
||||
private ?string $caminho_foto = null;
|
||||
private ?string $registro_geral_animal = null;
|
||||
private ?string $photo_path = null;
|
||||
private ?string $data_nascimento = null;
|
||||
private ?string $data_obito = null;
|
||||
private ?string $sexo = null;
|
||||
private ?string $created_at = null;
|
||||
private ?string $updated_at = null;
|
||||
private ?string $deleted_at = null;
|
||||
|
||||
/**
|
||||
* Construtor do DTO.
|
||||
*
|
||||
* Permite inicializar os atributos do objeto a partir de um array associativo.
|
||||
*
|
||||
* @param array<string, mixed> $data Array associativo opcional para popular os atributos.
|
||||
*/
|
||||
public function __construct(array $data = []) {
|
||||
if (!empty($data)) {
|
||||
$this->fromArray($data);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Popula o DTO a partir de um array.
|
||||
*
|
||||
* @param array<string, mixed> $data
|
||||
* @return void
|
||||
*/
|
||||
public function fromArray(array $data): void {
|
||||
$this->id = $data['id'] ?? $this->id;
|
||||
$this->uuid = $data['uuid'] ?? $this->uuid;
|
||||
$this->nome = $data['nome'] ?? $this->nome;
|
||||
$this->especie_id = $data['especie_id'] ?? $this->especie_id;
|
||||
$this->raca_id = $data['raca_id'] ?? $this->raca_id;
|
||||
$this->caminho_foto = $data['caminho_foto'] ?? $this->caminho_foto;
|
||||
$this->registro_geral_animal = $data['registro_geral_animal'] ?? $this->registro_geral_animal;
|
||||
$this->photo_path = $data['photo_path'] ?? $this->photo_path;
|
||||
$this->data_nascimento = $data['data_nascimento'] ?? $this->data_nascimento;
|
||||
$this->data_obito = $data['data_obito'] ?? $this->data_obito;
|
||||
$this->sexo = $data['sexo'] ?? $this->sexo;
|
||||
$this->created_at = $data['created_at'] ?? $this->created_at;
|
||||
$this->updated_at = $data['updated_at'] ?? $this->updated_at;
|
||||
$this->deleted_at = $data['deleted_at'] ?? $this->deleted_at;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converte o DTO para um array associativo.
|
||||
*
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function toArray(): array {
|
||||
return [
|
||||
'id' => $this->id,
|
||||
'uuid' => $this->uuid,
|
||||
'nome' => $this->nome,
|
||||
'especie_id' => $this->especie_id,
|
||||
'raca_id' => $this->raca_id,
|
||||
'caminho_foto' => $this->caminho_foto,
|
||||
'registro_geral_animal' => $this->registro_geral_animal,
|
||||
'photo_path' => $this->photo_path,
|
||||
'data_nascimento' => $this->data_nascimento,
|
||||
'data_obito' => $this->data_obito,
|
||||
'sexo' => $this->sexo,
|
||||
'created_at' => $this->created_at,
|
||||
'updated_at' => $this->updated_at,
|
||||
'deleted_at' => $this->deleted_at,
|
||||
];
|
||||
}
|
||||
|
||||
public function getId(): ?int {
|
||||
return $this->id;
|
||||
}
|
||||
public function setId(?int $id): void {
|
||||
$this->id = $id;
|
||||
}
|
||||
|
||||
public function getUuid(): ?string {
|
||||
return $this->uuid;
|
||||
}
|
||||
public function setUuid(?string $uuid): void {
|
||||
$this->uuid = $uuid;
|
||||
}
|
||||
|
||||
public function getNome(): ?string {
|
||||
return $this->nome;
|
||||
}
|
||||
public function setNome(?string $nome): void {
|
||||
$this->nome = $nome;
|
||||
}
|
||||
|
||||
public function getEspecieId(): ?int {
|
||||
return $this->especie_id;
|
||||
}
|
||||
public function setEspecieId(?int $especie_id): void {
|
||||
$this->especie_id = $especie_id;
|
||||
}
|
||||
|
||||
public function getRacaId(): ?int {
|
||||
return $this->raca_id;
|
||||
}
|
||||
public function setRacaId(?int $raca_id): void {
|
||||
$this->raca_id = $raca_id;
|
||||
}
|
||||
|
||||
public function getCaminhoFoto(): ?string {
|
||||
return $this->caminho_foto;
|
||||
}
|
||||
public function setCaminhoFoto(?string $caminho_foto): void {
|
||||
$this->caminho_foto = $caminho_foto;
|
||||
}
|
||||
|
||||
public function getRegistroGeralAnimal(): ?string {
|
||||
return $this->registro_geral_animal;
|
||||
}
|
||||
public function setRegistroGeralAnimal(?string $registro_geral_animal): void {
|
||||
$this->registro_geral_animal = $registro_geral_animal;
|
||||
}
|
||||
|
||||
public function getPhotoPath(): ?string {
|
||||
return $this->photo_path;
|
||||
}
|
||||
public function setPhotoPath(?string $photo_path): void {
|
||||
$this->photo_path = $photo_path;
|
||||
}
|
||||
|
||||
public function getDataNascimento(): ?string {
|
||||
return $this->data_nascimento;
|
||||
}
|
||||
public function setDataNascimento(?string $data_nascimento): void {
|
||||
$this->data_nascimento = $data_nascimento;
|
||||
}
|
||||
|
||||
public function getDataObito(): ?string {
|
||||
return $this->data_obito;
|
||||
}
|
||||
public function setDataObito(?string $data_obito): void {
|
||||
$this->data_obito = $data_obito;
|
||||
}
|
||||
|
||||
public function getSexo(): ?string {
|
||||
return $this->sexo;
|
||||
}
|
||||
public function setSexo(?string $sexo): void {
|
||||
$this->sexo = $sexo;
|
||||
}
|
||||
|
||||
public function getCreatedAt(): ?string {
|
||||
return $this->created_at;
|
||||
}
|
||||
public function setCreatedAt(?string $created_at): void {
|
||||
$this->created_at = $created_at;
|
||||
}
|
||||
|
||||
public function getUpdatedAt(): ?string {
|
||||
return $this->updated_at;
|
||||
}
|
||||
public function setUpdatedAt(?string $updated_at): void {
|
||||
$this->updated_at = $updated_at;
|
||||
}
|
||||
|
||||
public function getDeletedAt(): ?string {
|
||||
return $this->deleted_at;
|
||||
}
|
||||
public function setDeletedAt(?string $deleted_at): void {
|
||||
$this->deleted_at = $deleted_at;
|
||||
}
|
||||
}
|
||||
77
app/Module/Tutor/v0/DTO/PetRacaDTO.php
Executable file
77
app/Module/Tutor/v0/DTO/PetRacaDTO.php
Executable file
@@ -0,0 +1,77 @@
|
||||
<?php
|
||||
namespace Zampet\Module\Tutor\v0\DTO;
|
||||
|
||||
class PetRacaDTO {
|
||||
public ?int $id = null;
|
||||
public ?string $uuid = null;
|
||||
public ?int $especie_id = null;
|
||||
public ?string $descricao = null;
|
||||
|
||||
/**
|
||||
* Construtor do DTO.
|
||||
*
|
||||
* Permite inicializar os atributos do objeto a partir de um array associativo.
|
||||
*
|
||||
* @param array<string, mixed> $data Array associativo opcional para popular os atributos.
|
||||
*/
|
||||
public function __construct(array $data = []) {
|
||||
if (!empty($data)) {
|
||||
$this->fromArray($data);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Popula o DTO a partir de um array.
|
||||
*
|
||||
* @param array<string, mixed> $data
|
||||
* @return void
|
||||
*/
|
||||
public function fromArray(array $data): void {
|
||||
$this->id = $data['id'] ?? $this->id;
|
||||
$this->uuid = $data['uuid'] ?? $this->uuid;
|
||||
$this->especie_id = $data['especie_id'] ?? $this->especie_id;
|
||||
$this->descricao = $data['descricao'] ?? $this->descricao;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converte o DTO para um array associativo.
|
||||
*
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function toArray(): array {
|
||||
return [
|
||||
'id' => $this->id,
|
||||
'uuid' => $this->uuid,
|
||||
'especie_id' => $this->especie_id,
|
||||
'descricao' => $this->descricao,
|
||||
];
|
||||
}
|
||||
|
||||
public function getId(): ?int {
|
||||
return $this->id;
|
||||
}
|
||||
public function setId(?int $id): void {
|
||||
$this->id = $id;
|
||||
}
|
||||
|
||||
public function getUuid(): ?string {
|
||||
return $this->uuid;
|
||||
}
|
||||
public function setUuid(?string $uuid): void {
|
||||
$this->uuid = $uuid;
|
||||
}
|
||||
|
||||
public function getEspecieId(): ?int {
|
||||
return $this->especie_id;
|
||||
}
|
||||
public function setEspecieId(?int $especie_id): void {
|
||||
$this->especie_id = $especie_id;
|
||||
}
|
||||
|
||||
public function getDescricao(): ?string {
|
||||
return $this->descricao;
|
||||
}
|
||||
public function setDescricao(?string $descricao): void {
|
||||
$this->descricao = $descricao;
|
||||
}
|
||||
}
|
||||
651
app/Module/Tutor/v0/Models/PetModel.php
Executable file
651
app/Module/Tutor/v0/Models/PetModel.php
Executable file
@@ -0,0 +1,651 @@
|
||||
<?php
|
||||
namespace Zampet\Module\Tutor\v0\Models;
|
||||
|
||||
use Exception;
|
||||
use Zampet\Services\DB;
|
||||
use Zampet\Module\Tutor\v0\DTO\PetDTO;
|
||||
use Zampet\Module\Tutor\v0\DTO\PetRacaDTO;
|
||||
use Zampet\Module\Auth\v0\Models\UsuarioModel;
|
||||
|
||||
class PetModel {
|
||||
protected string $petTable = 'pet';
|
||||
protected string $usuarioPet = 'usuario_pet';
|
||||
protected string $petAuxRacaTable = 'pet_aux_raca';
|
||||
protected string $petAuxEspecieTable = 'pet_aux_especie';
|
||||
|
||||
/**
|
||||
* Lista todos os pets associados a um tutor, buscando o tutor por um identificador flexível.
|
||||
*
|
||||
* Este método busca primeiro o registro do tutor usando um identificador (UUID, ID, e-mail, etc.) e, em seguida, usa o ID interno do tutor para consultar todos os pets a ele associados.
|
||||
*
|
||||
* #### Fluxo de Operação:
|
||||
* 1. **Busca do Tutor:** Utiliza `UsuarioModel::getUsuarioByIdentifier` para buscar os dados do tutor. Se o tutor não for encontrado, lança uma `Exception` com o código 404.
|
||||
* 2. **Consulta dos Pets:** Executa uma consulta `SELECT` que une as tabelas de associação (`up`), pets (`p`), raças (`par`) e espécies (`pae`) para obter uma lista detalhada de todos os pets vinculados ao `usuario_id` do tutor.
|
||||
* 3. **Verificação de Pets:**
|
||||
* * Se a consulta não retornar pets (`empty($petsUsuario)`), retorna um array com `status` 'fail' e uma mensagem informativa.
|
||||
* * Se pets forem encontrados, retorna um array com `status` 'success', código `200 OK` e os dados dos pets na chave `output`.
|
||||
*
|
||||
* #### Tratamento de Erros:
|
||||
* - Qualquer `Exception` lançada durante o processo (como tutor não encontrado ou erro de consulta) é capturada.
|
||||
* - Retorna um array com `status` 'error', o código de resposta HTTP da exceção e uma mensagem descritiva.
|
||||
*
|
||||
* @param string $identifier A coluna da tabela de usuário a ser usada para identificar o tutor (ex: 'uuid', 'id').
|
||||
* @param mixed $value O valor correspondente ao identificador do tutor.
|
||||
* @return array Um array associativo contendo o status da operação, o código HTTP e os dados dos pets (`output['data']`), ou uma mensagem de erro.
|
||||
*/
|
||||
public function listPetsByTutorIdentifier(string $identifier, mixed $value): array {
|
||||
try {
|
||||
$usuarioData = (new UsuarioModel())->getUsuarioByIdentifier(identifier: $identifier, value: $value);
|
||||
if(!$usuarioData) {
|
||||
throw new Exception(message: 'Tutor not found', code: 404);
|
||||
}
|
||||
$usuarioData = $usuarioData['output']['data'];
|
||||
|
||||
$sql =
|
||||
"SELECT
|
||||
p.id,
|
||||
p.uuid,
|
||||
p.nome,
|
||||
p.especie_id,
|
||||
pae.descricao AS especie,
|
||||
p.raca_id,
|
||||
par.descricao AS raca,
|
||||
p.caminho_foto,
|
||||
p.registro_geral_animal,
|
||||
p.photo_path,
|
||||
p.data_nascimento,
|
||||
p.data_obito,
|
||||
p.sexo,
|
||||
p.created_at,
|
||||
p.updated_at,
|
||||
p.deleted_at
|
||||
FROM {$this->usuarioPet} up
|
||||
LEFT JOIN {$this->petTable} p ON up.pet_id = p.id
|
||||
LEFT JOIN {$this->petAuxRacaTable} par ON p.raca_id = par.id
|
||||
LEFT JOIN {$this->petAuxEspecieTable} pae ON p.especie_id = pae.id
|
||||
WHERE up.usuario_id = :usuario_id";
|
||||
|
||||
$params = [
|
||||
':usuario_id' => $usuarioData['id'],
|
||||
];
|
||||
|
||||
$petsUsuario = DB::fetchAll(sql: $sql, params: $params);
|
||||
if(empty($petsUsuario)) {
|
||||
return [
|
||||
'response_code' => 200,
|
||||
'status' => 'success',
|
||||
'message' => 'Você não possui pets cadastrados.',
|
||||
'output' => [
|
||||
'data' => []
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
return [
|
||||
'response_code' => 200,
|
||||
'status' => 'success',
|
||||
'message' => 'Pets encontrados com sucesso.',
|
||||
'output' => [
|
||||
'data' => $petsUsuario
|
||||
]
|
||||
];
|
||||
} catch(Exception $e) {
|
||||
return [
|
||||
'response_code' => $e->getCode() ?? 500,
|
||||
'status' => 'error',
|
||||
'message' => $e->getMessage(),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Lista todas as espécies de pets disponíveis no sistema auxiliar.
|
||||
*
|
||||
* Este método consulta a tabela de espécies (`{$this->petAuxEspecieTable}`) e retorna uma lista de todos os registros (ID e descrição).
|
||||
*
|
||||
* #### Fluxo de Operação:
|
||||
* 1. **Execução da Consulta:** Executa uma consulta `SELECT` para buscar todos os IDs e descrições da tabela auxiliar de espécies.
|
||||
* 2. **Verificação de Resultados:**
|
||||
* - Se a consulta for bem-sucedida, mas **não retornar nenhuma espécie** (`empty($stmt)`), retorna um array com `status` 'fail' e código `200 OK`.
|
||||
* - Se a consulta for bem-sucedida e **retornar espécies**, retorna um array com `status` 'success', código `200 OK` e os dados encontrados na chave `output`.
|
||||
*
|
||||
* #### Tratamento de Erros:
|
||||
* - Qualquer `Exception` capturada durante a consulta retorna um array com `status` 'error', o código de erro da exceção e uma mensagem detalhada de erro.
|
||||
*
|
||||
* @return array Um array associativo contendo o status da operação, o código de resposta HTTP e os dados das espécies (`output['data']`).
|
||||
*/
|
||||
public function getAllEspecies(): array {
|
||||
try {
|
||||
$sql =
|
||||
"SELECT
|
||||
id,
|
||||
uuid,
|
||||
descricao
|
||||
FROM {$this->petAuxEspecieTable}";
|
||||
|
||||
$result = DB::fetchAll(sql: $sql);
|
||||
if(empty($result)) {
|
||||
return [
|
||||
'response_code' => 200,
|
||||
'status' => 'success',
|
||||
'message' => 'Nenhuma espécie encontrada.',
|
||||
'output' => [
|
||||
'data' => []
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
$preparedResult = [];
|
||||
foreach($result as $key => $especie) {
|
||||
$sql =
|
||||
"SELECT
|
||||
uuid,
|
||||
descricao
|
||||
FROM {$this->petAuxRacaTable}
|
||||
WHERE especie_id = :especie_id";
|
||||
|
||||
$params = [
|
||||
':especie_id' => $especie['id']
|
||||
];
|
||||
|
||||
$result = DB::fetchAll(sql: $sql, params: $params);
|
||||
|
||||
$preparedResult[] = [
|
||||
'uuid' => $especie['uuid'],
|
||||
'descricao' => $especie['descricao'],
|
||||
'racas' => $result
|
||||
];
|
||||
}
|
||||
|
||||
return [
|
||||
'response_code' => 200,
|
||||
'status' => 'success',
|
||||
'message' => 'Espécies encontradas com sucesso.',
|
||||
'output' => [
|
||||
'data' => $preparedResult
|
||||
]
|
||||
];
|
||||
} catch(Exception $e) {
|
||||
return [
|
||||
'response_code' => $e->getCode() ?? 500,
|
||||
'status' => 'error',
|
||||
'message' => $e->getMessage(),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Busca uma única espécie de pet no banco de dados por um identificador específico.
|
||||
*
|
||||
* Este método recupera os dados de uma espécie da tabela auxiliar `{$this->petAuxEspecieTable}` de forma flexível, permitindo a busca por qualquer coluna (como 'id' ou 'uuid') e o valor correspondente.
|
||||
*
|
||||
* #### Fluxo de Operação:
|
||||
* 1. **Execução da Consulta:** O método monta e executa uma consulta `SELECT` que usa o `$identifier` de forma dinâmica na cláusula `WHERE` e um parâmetro nomeado seguro (`:value`) para o valor. A consulta utiliza `DB::fetchOne`, indicando que apenas um registro é esperado.
|
||||
* 2. **Verificação de Resultados:**
|
||||
* - Se a consulta for bem-sucedida e **nenhuma espécie for encontrada** (`empty($result)`), retorna um array com **`status` 'fail'** e código **200 OK**.
|
||||
* - Se uma espécie for encontrada, retorna um array com **`status` 'success'**, código **200 OK** e os dados do registro na chave `output`.
|
||||
*
|
||||
* #### Tratamento de Erros:
|
||||
* - Qualquer `Exception` capturada durante a consulta retorna um array com **`status` 'error'**, o código de erro da exceção e uma mensagem de erro detalhada.
|
||||
*
|
||||
* @param string $identifier A coluna da tabela a ser usada como critério de busca (ex: 'id', 'uuid', 'descricao').
|
||||
* @param mixed $value O valor correspondente ao identificador que está sendo buscado.
|
||||
* @return array Um array associativo contendo o status da operação, um código de resposta HTTP e os dados da espécie, se encontrada.
|
||||
*/
|
||||
public function getEspecieByIdentifier(string $identifier, mixed $value): array {
|
||||
try {
|
||||
$sql =
|
||||
"SELECT
|
||||
id,
|
||||
uuid,
|
||||
descricao
|
||||
FROM {$this->petAuxEspecieTable}
|
||||
WHERE {$identifier} = :value
|
||||
ORDER BY descricao ASC";
|
||||
|
||||
$params = [
|
||||
':value' => $value
|
||||
];
|
||||
|
||||
$result = DB::fetchOne(sql: $sql, params: $params);
|
||||
if(empty($result)) {
|
||||
return [
|
||||
'response_code' => 200,
|
||||
'status' => 'success',
|
||||
'message' => 'Espécie não encontrada.',
|
||||
'output' => [
|
||||
'data' => []
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
return [
|
||||
'response_code' => 200,
|
||||
'status' => 'success',
|
||||
'message' => 'Espécie encontrada com sucesso.',
|
||||
'output' => [
|
||||
'data' => $result
|
||||
]
|
||||
];
|
||||
} catch(Exception $e) {
|
||||
return [
|
||||
'response_code' => $e->getCode() ?? 500,
|
||||
'status' => 'error',
|
||||
'message' => $e->getMessage(),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Busca uma única raça de pet no banco de dados por um identificador específico.
|
||||
*
|
||||
* Este método recupera os dados de uma raça da tabela auxiliar `{$this->petAuxRacaTable}` de forma flexível, permitindo a busca por qualquer coluna como identificador (`$identifier`) e o valor correspondente. A consulta retorna apenas um registro e é ordenada pela descrição.
|
||||
*
|
||||
* #### Fluxo de Operação:
|
||||
* 1. **Execução da Consulta:** O método monta e executa uma consulta `SELECT` que usa o `$identifier` de forma dinâmica na cláusula `WHERE` e um parâmetro nomeado seguro (`:value`) para o valor.
|
||||
* 2. **Verificação de Resultados:**
|
||||
* - Se uma raça for encontrada, retorna um array com **`status` 'success'**, código **200 OK** e os dados da raça na chave `output`.
|
||||
* - Se a consulta for bem-sucedida, mas **nenhuma raça for encontrada** (`empty($result)`), retorna um array com **`status` 'success'** (indicando que a consulta foi bem-sucedida) e uma mensagem de "Raça não encontrada.".
|
||||
*
|
||||
* #### Tratamento de Erros:
|
||||
* - Qualquer `Exception` capturada durante a consulta retorna um array com **`status` 'error'**, o código de erro da exceção (ou `500` como fallback) e uma mensagem de erro detalhada.
|
||||
*
|
||||
* @param string $identifier A coluna da tabela a ser usada como critério de busca (ex: 'uuid', 'id', 'descricao').
|
||||
* @param mixed $value O valor correspondente ao identificador que está sendo buscado.
|
||||
* @return array Um array associativo contendo o status da operação, um código de resposta HTTP e os dados da raça, se encontrada.
|
||||
*/
|
||||
public function getRacaByIdentifier(string $identifier, mixed $value): array {
|
||||
try {
|
||||
$sql =
|
||||
"SELECT
|
||||
id,
|
||||
uuid,
|
||||
especie_id,
|
||||
descricao
|
||||
FROM {$this->petAuxRacaTable}
|
||||
WHERE {$identifier} = :value
|
||||
ORDER BY descricao ASC";
|
||||
|
||||
$params = [
|
||||
':value' => $value
|
||||
];
|
||||
|
||||
$result = DB::fetchOne(sql: $sql, params: $params);
|
||||
if(empty($result)) {
|
||||
return [
|
||||
'response_code' => 200,
|
||||
'status' => 'success',
|
||||
'message' => 'Raça não encontrada.',
|
||||
'output' => [
|
||||
'data' => []
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
return [
|
||||
'response_code' => 200,
|
||||
'status' => 'success',
|
||||
'message' => 'Raça encontrada com sucesso.',
|
||||
'output' => [
|
||||
'data' => $result
|
||||
]
|
||||
];
|
||||
} catch(Exception $e) {
|
||||
return [
|
||||
'response_code' => $e->getCode() ?? 500,
|
||||
'status' => 'error',
|
||||
'message' => $e->getMessage(),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Busca todas as raças de pets associadas a uma espécie específica.
|
||||
*
|
||||
* Este método primeiro consulta a espécie usando um identificador (UUID, ID, etc.) e, em seguida, usa o ID interno da espécie para listar todas as raças vinculadas a ela na tabela auxiliar `{$this->petAuxRacaTable}`.
|
||||
*
|
||||
* #### Fluxo de Operação:
|
||||
* 1. **Busca da Espécie:** O método chama `getEspecieByIdentifier` para encontrar o ID da espécie. Se a busca falhar, o resultado de erro é retornado imediatamente.
|
||||
* 2. **Consulta das Raças:** Executa uma consulta `SELECT` que busca todas as raças onde `especie_id` corresponde ao ID da espécie encontrado. Os resultados são ordenados alfabeticamente pela descrição.
|
||||
* 3. **Verificação de Resultados:**
|
||||
* - Se a consulta for bem-sucedida, mas **nenhuma raça for encontrada**, retorna um array com **`status` 'fail'** e código **200 OK**.
|
||||
* - Se raças forem encontradas, retorna um array com **`status` 'success'**, código **200 OK** e os dados encontrados na chave `output`.
|
||||
*
|
||||
* #### Tratamento de Erros:
|
||||
* - Qualquer `Exception` capturada durante o processo (além daquelas tratadas na busca inicial) retorna um array com **`status` 'error'**, o código de erro da exceção e uma mensagem de erro detalhada.
|
||||
*
|
||||
* @param string $identifier A coluna da tabela auxiliar de espécies a ser usada para identificar a espécie (ex: 'uuid', 'id').
|
||||
* @param mixed $value O valor correspondente ao identificador da espécie.
|
||||
* @return array Um array associativo contendo o status da operação, o código de resposta HTTP e os dados das raças (`output['data']`).
|
||||
*/
|
||||
public function getRacasByEspecieIdentifier(string $identifier, mixed $value): array {
|
||||
try {
|
||||
$especieData = $this->getEspecieByIdentifier(identifier: $identifier, value: $value);
|
||||
if($especieData['status'] !== 'success') {
|
||||
return $especieData;
|
||||
}
|
||||
$especieData = $especieData['output']['data'];
|
||||
|
||||
$sql =
|
||||
"SELECT
|
||||
id,
|
||||
uuid,
|
||||
descricao
|
||||
FROM {$this->petAuxRacaTable}
|
||||
WHERE especie_id = :especie_id
|
||||
ORDER BY descricao ASC";
|
||||
|
||||
$params = [
|
||||
':especie_id' => $especieData['id']
|
||||
];
|
||||
|
||||
$racas = DB::fetchAll(sql: $sql, params: $params);
|
||||
if(empty($racas)) {
|
||||
return [
|
||||
'response_code' => 200,
|
||||
'status' => 'success',
|
||||
'message' => 'Nenhuma raça encontrada para a espécie informada.',
|
||||
'output' => [
|
||||
'data' => []
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
return [
|
||||
'response_code' => 200,
|
||||
'status' => 'success',
|
||||
'message' => 'Raças encontradas com sucesso.',
|
||||
'output' => [
|
||||
'data' => $racas
|
||||
]
|
||||
];
|
||||
} catch(Exception $e) {
|
||||
return [
|
||||
'response_code' => $e->getCode() ?? 500,
|
||||
'status' => 'error',
|
||||
'message' => $e->getMessage(),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Armazena uma nova raça de pet no banco de dados.
|
||||
*
|
||||
* Este método insere os dados de uma nova raça na tabela auxiliar `{$this->petAuxRacaTable}`. A raça é associada a uma espécie existente. A operação utiliza um bloco `try-catch` para garantir o tratamento de erros.
|
||||
*
|
||||
* #### Fluxo de Operação:
|
||||
* 1. **Execução da Query:** Prepara e executa a instrução `INSERT` para inserir o novo registro com o UUID, ID da espécie e a descrição.
|
||||
* 2. **Confirmação e Retorno de Sucesso:** Se a inserção for bem-sucedida, retorna um array com **`status` 'success'**, código **201 Created** e uma mensagem de êxito.
|
||||
*
|
||||
* #### Tratamento de Erros:
|
||||
* - Qualquer `Exception` capturada durante o processo retorna um array com **`status` 'error'**, o código de erro da exceção e uma mensagem detalhada de erro.
|
||||
*
|
||||
* @param PetRacaDTO $petRacaDTO O objeto DTO contendo o UUID, o ID da espécie (`especie_id`) e a descrição da raça a ser criada.
|
||||
* @return array Um array associativo contendo o status da operação, o código de resposta HTTP e uma mensagem.
|
||||
*/
|
||||
public function storeRaca(PetRacaDTO $petRacaDTO): array {
|
||||
try {
|
||||
$sql =
|
||||
"INSERT INTO {$this->petAuxRacaTable} (
|
||||
uuid,
|
||||
especie_id,
|
||||
descricao
|
||||
) VALUES (
|
||||
:uuid,
|
||||
:especie_id,
|
||||
:descricao
|
||||
)";
|
||||
|
||||
$params = [
|
||||
':uuid' => $petRacaDTO->getUuid(),
|
||||
':especie_id' => $petRacaDTO->getEspecieId(),
|
||||
':descricao' => $petRacaDTO->getDescricao()
|
||||
];
|
||||
|
||||
DB::execute(sql: $sql, params: $params);
|
||||
|
||||
return [
|
||||
'response_code' => 201,
|
||||
'status' => 'success',
|
||||
'message' => 'Raça armazenada com sucesso.',
|
||||
'output' => [
|
||||
'data' => [
|
||||
'id' => DB::lastInsertId(),
|
||||
'uuid' => $petRacaDTO->getUuid(),
|
||||
'especie_id' => $petRacaDTO->getEspecieId(),
|
||||
'descricao' => $petRacaDTO->getDescricao()
|
||||
]
|
||||
]
|
||||
];
|
||||
} catch(Exception $e) {
|
||||
return [
|
||||
'response_code' => $e->getCode() ?? 500,
|
||||
'status' => 'error',
|
||||
'message' => $e->getMessage(),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Armazena um novo pet no banco de dados.
|
||||
*
|
||||
* Este método insere os dados de um novo pet na tabela `{$this->petTable}`, utilizando um objeto `PetDTO` que encapsula todas as informações relevantes. A operação é atômica e utiliza um bloco `try-catch` para garantir o tratamento de erros.
|
||||
*
|
||||
* #### Fluxo de Operação:
|
||||
* 1. **Execução da Query:** Prepara e executa a instrução `INSERT` para inserir o novo registro com todos os detalhes do pet (UUID, nome, espécie, raça, dados de saúde, foto, etc.).
|
||||
* 2. **Confirmação e Retorno de Sucesso:** Se a inserção for bem-sucedida, retorna um array com **`status` 'success'**, código **201 Created** e uma mensagem de êxito. Os dados do pet recém-criado, incluindo o ID gerado pelo banco, são retornados na chave `output`.
|
||||
*
|
||||
* #### Tratamento de Erros:
|
||||
* - Qualquer `Exception` capturada durante o processo retorna um array com **`status` 'error'**, o código de erro da exceção e uma mensagem detalhada de erro.
|
||||
*
|
||||
* @param PetDTO $petDTO O objeto DTO contendo os dados do pet a ser criado.
|
||||
* @return array Um array associativo contendo o status da operação, o código de resposta HTTP e os dados do pet, se a operação for bem-sucedida.
|
||||
*/
|
||||
public function storePet(PetDTO $petDTO): array {
|
||||
try {
|
||||
$sql =
|
||||
"INSERT INTO {$this->petTable} (
|
||||
uuid,
|
||||
nome,
|
||||
especie_id,
|
||||
raca_id,
|
||||
caminho_foto,
|
||||
registro_geral_animal,
|
||||
photo_path,
|
||||
data_nascimento,
|
||||
data_obito,
|
||||
sexo,
|
||||
created_at,
|
||||
updated_at,
|
||||
deleted_at
|
||||
) VALUES (
|
||||
:uuid,
|
||||
:nome,
|
||||
:especie_id,
|
||||
:raca_id,
|
||||
:caminho_foto,
|
||||
:registro_geral_animal,
|
||||
:photo_path,
|
||||
:data_nascimento,
|
||||
:data_obito,
|
||||
:sexo,
|
||||
:created_at,
|
||||
:updated_at,
|
||||
:deleted_at
|
||||
)";
|
||||
|
||||
$params = [
|
||||
':uuid' => $petDTO->getUuid(),
|
||||
':nome' => $petDTO->getNome(),
|
||||
':especie_id' => $petDTO->getEspecieId(),
|
||||
':raca_id' => $petDTO->getRacaId(),
|
||||
':caminho_foto' => $petDTO->getCaminhoFoto(),
|
||||
':registro_geral_animal' => $petDTO->getRegistroGeralAnimal(),
|
||||
':photo_path' => $petDTO->getPhotoPath(),
|
||||
':data_nascimento' => $petDTO->getDataNascimento(),
|
||||
':data_obito' => $petDTO->getDataObito(),
|
||||
':sexo' => $petDTO->getSexo(),
|
||||
':created_at' => $petDTO->getCreatedAt(),
|
||||
':updated_at' => $petDTO->getUpdatedAt(),
|
||||
':deleted_at' => $petDTO->getDeletedAt()
|
||||
];
|
||||
|
||||
DB::execute(sql: $sql, params: $params);
|
||||
|
||||
return [
|
||||
'response_code' => 201,
|
||||
'status' => 'success',
|
||||
'message' => 'Pet armazenado com sucesso.',
|
||||
'output' => [
|
||||
'data' => [
|
||||
'id' => DB::lastInsertId(),
|
||||
'uuid' => $petDTO->getUuid(),
|
||||
'nome' => $petDTO->getNome(),
|
||||
'especie_id' => $petDTO->getEspecieId(),
|
||||
'raca_id' => $petDTO->getRacaId(),
|
||||
'caminho_foto' => $petDTO->getCaminhoFoto(),
|
||||
'registro_geral_animal' => $petDTO->getRegistroGeralAnimal(),
|
||||
'photo_path' => $petDTO->getPhotoPath(),
|
||||
'data_nascimento' => $petDTO->getDataNascimento(),
|
||||
'data_obito' => $petDTO->getDataObito(),
|
||||
'sexo' => $petDTO->getSexo(),
|
||||
'created_at' => $petDTO->getCreatedAt(),
|
||||
'updated_at' => $petDTO->getUpdatedAt(),
|
||||
'deleted_at' => $petDTO->getDeletedAt()
|
||||
]
|
||||
]
|
||||
];
|
||||
} catch(Exception $e) {
|
||||
return [
|
||||
'response_code' => $e->getCode() ?? 500,
|
||||
'status' => 'error',
|
||||
'message' => $e->getMessage(),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Associa um pet a um usuário (tutor) no banco de dados.
|
||||
*
|
||||
* Este método insere um novo registro na tabela de associação `{$this->usuarioPet}`, estabelecendo a relação de propriedade entre o usuário e o pet.
|
||||
*
|
||||
* #### Fluxo de Operação:
|
||||
* 1. **Execução da Query:** Prepara e executa a instrução `INSERT` para inserir os IDs do usuário e do pet na tabela de associação.
|
||||
* 2. **Retorno de Sucesso:** Se a inserção for bem-sucedida, retorna um array com **`status` 'success'**, código **201 Created** e uma mensagem de êxito.
|
||||
*
|
||||
* #### Tratamento de Erros:
|
||||
* - Qualquer `Exception` capturada durante o processo retorna um array com **`status` 'error'**, o código de erro da exceção (ou `500` como fallback) e uma mensagem detalhada de erro.
|
||||
*
|
||||
* @param int $usuario_id O ID do usuário (tutor) a ser associado.
|
||||
* @param int $pet_id O ID do pet a ser associado.
|
||||
* @return array Um array associativo contendo o status da operação, um código de resposta HTTP e uma mensagem.
|
||||
*/
|
||||
public function storeUsuarioPet(int $usuario_id, int $pet_id): array {
|
||||
try {
|
||||
$sql =
|
||||
"INSERT INTO {$this->usuarioPet} (
|
||||
usuario_id,
|
||||
pet_id
|
||||
) VALUES (
|
||||
:usuario_id,
|
||||
:pet_id
|
||||
)";
|
||||
|
||||
$params = [
|
||||
':usuario_id' => $usuario_id,
|
||||
':pet_id' => $pet_id
|
||||
];
|
||||
|
||||
DB::execute(sql: $sql, params: $params);
|
||||
|
||||
return [
|
||||
'response_code' => 201,
|
||||
'status' => 'success',
|
||||
'message' => 'Associação entre usuário e pet criada com sucesso.'
|
||||
];
|
||||
} catch(Exception $e) {
|
||||
return [
|
||||
'response_code' => $e->getCode() ?? 500,
|
||||
'status' => 'error',
|
||||
'message' => $e->getMessage(),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Busca um único pet no banco de dados por um identificador específico.
|
||||
*
|
||||
* Este método recupera todos os detalhes de um pet da tabela `{$this->petTable}`. A busca é flexível e permite usar qualquer coluna como identificador (`$identifier`) e o valor correspondente.
|
||||
*
|
||||
* #### Fluxo de Operação:
|
||||
* 1. **Execução da Query:** O método monta e executa uma consulta `SELECT` que usa o `$identifier` de forma dinâmica na cláusula `WHERE`. A consulta usa `DB::fetchOne`, indicando que apenas um registro é esperado, e ordena o resultado pelo nome.
|
||||
* 2. **Verificação de Resultados:**
|
||||
* - Se o pet for encontrado, retorna um array com **`status` 'success'**, código **200 OK** e os dados do pet na chave `output`.
|
||||
* - Se o pet **não for encontrado** (`empty($result)`), retorna um array com **`status` 'success'** (indicando que a consulta foi bem-sucedida) e uma mensagem de "Pet não encontrado.".
|
||||
*
|
||||
* #### Tratamento de Erros:
|
||||
* - Qualquer `Exception` capturada durante o processo retorna um array com **`status` 'error'**, o código de erro da exceção (ou `500` como fallback) e uma mensagem de erro detalhada.
|
||||
*
|
||||
* @param string $identifier A coluna da tabela a ser usada como critério de busca (ex: 'uuid', 'id', 'registro_geral_animal').
|
||||
* @param string $value O valor correspondente ao identificador que está sendo buscado.
|
||||
* @return array Um array associativo contendo o status da operação, um código de resposta HTTP e os dados do pet, se encontrado.
|
||||
*/
|
||||
public function getPetByIdentifier(string $identifier, string $value): array {
|
||||
try {
|
||||
$sql =
|
||||
"SELECT
|
||||
p.id,
|
||||
p.uuid,
|
||||
p.nome,
|
||||
p.especie_id,
|
||||
pae.descricao AS especie,
|
||||
p.raca_id,
|
||||
par.descricao AS raca,
|
||||
p.caminho_foto,
|
||||
p.registro_geral_animal,
|
||||
p.photo_path,
|
||||
p.data_nascimento,
|
||||
p.data_obito,
|
||||
p.sexo,
|
||||
p.created_at,
|
||||
p.updated_at,
|
||||
p.deleted_at
|
||||
FROM {$this->petTable} p
|
||||
LEFT JOIN {$this->petAuxRacaTable} par ON p.raca_id = par.id
|
||||
LEFT JOIN {$this->petAuxEspecieTable} pae ON p.especie_id = pae.id
|
||||
WHERE p.{$identifier} = :value
|
||||
ORDER BY p.nome ASC";
|
||||
|
||||
$params = [
|
||||
':value' => $value
|
||||
];
|
||||
|
||||
$result = DB::fetchOne(sql: $sql, params: $params);
|
||||
if(empty($result)) {
|
||||
return [
|
||||
'response_code' => 200,
|
||||
'status' => 'success',
|
||||
'message' => 'Pet não encontrado.',
|
||||
'output' => [
|
||||
'data' => []
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
return [
|
||||
'response_code' => 200,
|
||||
'status' => 'success',
|
||||
'message' => 'Pet encontrado com sucesso.',
|
||||
'output' => [
|
||||
'data' => $result
|
||||
]
|
||||
];
|
||||
} catch(Exception $e) {
|
||||
return [
|
||||
'response_code' => $e->getCode() ?? 500,
|
||||
'status' => 'error',
|
||||
'message' => $e->getMessage(),
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
41
app/Module/Tutor/v0/Routes/PetRoutes.php
Executable file
41
app/Module/Tutor/v0/Routes/PetRoutes.php
Executable file
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
use AxiumPHP\Core\Router;
|
||||
use Zampet\Module\Tutor\v0\Controllers\PetController;
|
||||
|
||||
Router::group(
|
||||
prefix: '/pet',
|
||||
callback: function() {
|
||||
// Rota para listar todos os pets do tutor autenticado
|
||||
Router::GET(
|
||||
uri: '/list-my-pets',
|
||||
handler: [PetController::class, 'listMyPets']
|
||||
);
|
||||
|
||||
// Rota para listar todas as espécies e raças de pets
|
||||
Router::GET(
|
||||
uri: '/especies',
|
||||
handler: [PetController::class, 'getAllEspecies']
|
||||
);
|
||||
|
||||
// Cria Nova Raça
|
||||
Router::POST(
|
||||
uri: '/create-raca',
|
||||
handler: [PetController::class, 'storeRaca']
|
||||
);
|
||||
|
||||
// Cria Novo Pet
|
||||
Router::POST(
|
||||
uri: '/create-pet',
|
||||
handler: [PetController::class, 'storePet']
|
||||
);
|
||||
|
||||
// Consulta Detalhes do Pet
|
||||
Router::GET(
|
||||
uri: '/{pet_uuid}',
|
||||
handler: [PetController::class, 'getPetDetails']
|
||||
);
|
||||
},
|
||||
middlewares: [
|
||||
|
||||
]
|
||||
);
|
||||
9
app/Module/Tutor/v0/Routes/Routes.php
Executable file
9
app/Module/Tutor/v0/Routes/Routes.php
Executable file
@@ -0,0 +1,9 @@
|
||||
<?php
|
||||
use AxiumPHP\Core\Router;
|
||||
|
||||
Router::group(
|
||||
prefix: '/tutor/v0',
|
||||
callback: function() {
|
||||
require 'PetRoutes.php';
|
||||
}
|
||||
);
|
||||
241
app/Module/Tutor/v0/Services/PetService.php
Executable file
241
app/Module/Tutor/v0/Services/PetService.php
Executable file
@@ -0,0 +1,241 @@
|
||||
<?php
|
||||
namespace Zampet\Module\Tutor\v0\Services;
|
||||
|
||||
use DateTime;
|
||||
use Exception;
|
||||
use Ramsey\Uuid\Uuid;
|
||||
use Zampet\Module\Auth\v0\Models\UsuarioModel;
|
||||
use Zampet\Services\DB;
|
||||
use Zampet\Services\JWTService;
|
||||
use Zampet\Helpers\DataValidator;
|
||||
use Zampet\Module\Tutor\v0\DTO\PetDTO;
|
||||
use Zampet\Module\Tutor\v0\DTO\PetRacaDTO;
|
||||
use Zampet\Module\Tutor\v0\Models\PetModel;
|
||||
|
||||
class PetService {
|
||||
/**
|
||||
* Retorna a lista de todas as espécies de pets disponíveis no sistema.
|
||||
*
|
||||
* Este método atua como um **wrapper** (invólucro) para o método de mesmo nome na classe `PetModel`. Ele delega a responsabilidade de buscar a lista completa das espécies de pets cadastradas para a camada de modelo (DAO).
|
||||
*
|
||||
* @return array Um array associativo contendo o status da operação, o código HTTP e os dados das espécies, conforme retornado pelo `PetModel`.
|
||||
*/
|
||||
public function getAllEspecies(): array {
|
||||
return (new PetModel())->getAllEspecies();
|
||||
}
|
||||
|
||||
/**
|
||||
* Lista todos os pets de um tutor específico, buscando pelo UUID do tutor.
|
||||
*
|
||||
* Este método atua como um **wrapper** para o método `listPetsByTutorIdentifier` da classe `PetModel`. Ele delega a responsabilidade de buscar a lista completa e detalhada de pets associados a um tutor, utilizando o UUID como o identificador principal.
|
||||
*
|
||||
* @param string $uuid O UUID do tutor cujos pets devem ser listados.
|
||||
* @return array Um array associativo contendo o status da operação, o código HTTP e os dados dos pets, conforme retornado pelo `PetModel`.
|
||||
*/
|
||||
public function listPetsByTutorUuid(string $uuid): array {
|
||||
return (new PetModel())->listPetsByTutorIdentifier(identifier: 'uuid', value: $uuid);
|
||||
}
|
||||
|
||||
/**
|
||||
* Busca uma espécie de pet no sistema por um identificador específico.
|
||||
*
|
||||
* Este método atua como um **wrapper** para o método de busca de espécies na classe `PetModel`. Ele delega a responsabilidade de consultar a espécie para a camada de modelo (DAO), que lida com a lógica de acesso ao banco de dados.
|
||||
*
|
||||
* @param string $identifier A coluna da tabela a ser usada como critério de busca (ex: 'id', 'uuid', 'descricao').
|
||||
* @param string $value O valor correspondente ao identificador que está sendo buscado.
|
||||
* @return array Um array associativo contendo o status da operação, o código HTTP e os dados da espécie, conforme retornado pelo `PetModel`.
|
||||
*/
|
||||
public function getEspecieByIdentifier(string $identifier, string $value): array {
|
||||
return (new PetModel())->getEspecieByIdentifier(identifier: $identifier, value: $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Busca uma raça de pet no sistema por um identificador específico.
|
||||
*
|
||||
* Este método atua como um **wrapper** (invólucro) para o método de busca de raças na classe `PetModel`. Ele delega a responsabilidade de consultar a raça para a camada de modelo (DAO), que lida com a lógica de acesso ao banco de dados e retorna o resultado.
|
||||
*
|
||||
* @param string $identifier A coluna da tabela a ser usada como critério de busca (ex: 'uuid', 'id', 'descricao').
|
||||
* @param string $value O valor correspondente ao identificador que está sendo buscado.
|
||||
* @return array Um array associativo contendo o status da operação, o código HTTP e os dados da raça, conforme retornado pelo `PetModel`.
|
||||
*/
|
||||
public function getRacaByIdentifier(string $identifier, string $value): array {
|
||||
return (new PetModel())->getRacaByIdentifier(identifier: $identifier, value: $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Busca um pet no sistema por um identificador específico.
|
||||
*
|
||||
* Este método atua como um **wrapper** (invólucro) para o método de busca de pets na classe `PetModel`. Ele delega a responsabilidade de consultar o pet para a camada de modelo (DAO), que lida com a lógica de acesso ao banco de dados.
|
||||
*
|
||||
* @param string $identifier A coluna da tabela a ser usada como critério de busca (ex: 'uuid', 'id', 'nome').
|
||||
* @param string $value O valor correspondente ao identificador que está sendo buscado.
|
||||
* @return array Um array associativo contendo o status da operação, o código HTTP e os dados do pet, conforme retornado pelo `PetModel`.
|
||||
*/
|
||||
public function getPetByIdentifier(string $identifier, string $value): array {
|
||||
return (new PetModel())->getPetByIdentifier(identifier: $identifier, value: $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Cria uma nova raça de pet no sistema após validação.
|
||||
*
|
||||
* Este método orquestra a criação de uma nova raça de pet. Ele realiza a validação dos dados de entrada, define metadados essenciais (UUID) e persiste o registro no banco de dados, garantindo a atomicidade da operação através de uma transação.
|
||||
*
|
||||
* #### Fluxo de Operação:
|
||||
* 1. **Início da Transação:** Inicia uma transação no banco de dados (`DB::beginTransaction()`).
|
||||
* 2. **Validação de Dados:** Utiliza o `DataValidator` para verificar se os campos **'especie_id'** e **'descricao'** foram preenchidos.
|
||||
* 3. **Encerramento em Caso de Falha na Validação:** Se houver erros de validação, a transação é revertida (`DB::rollBack()`) e um array de erro formatado é retornado com o código `400 Bad Request`.
|
||||
* 4. **Preparação Final dos Dados:** Define um **UUID** único para a nova raça.
|
||||
* 5. **Persistência:** Chama o método `storeRaca` do `PetModel` para inserir o registro no banco de dados. Se a persistência falhar, uma `Exception` é lançada com a mensagem de erro do modelo.
|
||||
* 6. **Confirmação e Retorno:** Se a persistência for bem-sucedida, a transação é **confirmada** (`DB::commit()`) e o resultado de sucesso é retornado com o código `201 Created`.
|
||||
*
|
||||
* #### Tratamento de Erros:
|
||||
* - Qualquer `Exception` lançada durante o processo é capturada, e a transação é **revertida** (`DB::rollBack()`).
|
||||
* - Retorna um array de erro formatado contendo o código HTTP e a mensagem da exceção.
|
||||
*
|
||||
* @param PetRacaDTO $petRacaDTO O objeto DTO contendo o ID da espécie e a descrição da nova raça.
|
||||
* @return array Um array associativo contendo o status da operação, o código de resposta HTTP e os dados de saída, ou erros de validação.
|
||||
*/
|
||||
public function storeRaca(PetRacaDTO $petRacaDTO): array {
|
||||
// Inicia transação no banco de dados
|
||||
DB::beginTransaction();
|
||||
|
||||
try {
|
||||
// Valida os dados do DTO
|
||||
$dataValidador = new DataValidator(inputs: $petRacaDTO->toArray());
|
||||
$dataValidador->validate(field: 'especie_id', rule: 'notEmpty', message: 'Espécie é obrigatória.');
|
||||
$dataValidador->validate(field: 'descricao', rule: 'notEmpty', message: 'Descrição é obrigatória.');
|
||||
|
||||
// Se houver erros de validação, retornar resposta de erro
|
||||
if(!$dataValidador->passes()) {
|
||||
DB::rollBack();
|
||||
return [
|
||||
'response_code' => 400,
|
||||
'status' => 'error',
|
||||
'message' => 'Validation errors',
|
||||
'output' => [
|
||||
'errors' => $dataValidador->getErrors()
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
// Define dados adicionais
|
||||
$petRacaDTO->setUuid(uuid: Uuid::uuid7()->toString());
|
||||
|
||||
// Cria a nova raça no banco de dados
|
||||
$storeRaca = (new PetModel())->storeRaca(petRacaDTO: $petRacaDTO);
|
||||
if($storeRaca['status'] !== 'success') {
|
||||
throw new Exception(message: $storeRaca['message'], code: $storeRaca['response_code']);
|
||||
}
|
||||
|
||||
DB::commit();
|
||||
return [
|
||||
'response_code' => 201,
|
||||
'status' => 'success',
|
||||
'message' => 'Raça criada com sucesso.',
|
||||
'output' => $storeRaca['output']
|
||||
];
|
||||
} catch(Exception $e) {
|
||||
DB::rollBack();
|
||||
return [
|
||||
'response_code' => $e->getCode(),
|
||||
'status' => 'error',
|
||||
'message' => $e->getMessage()
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Armazena um novo pet no sistema e o associa ao usuário autenticado.
|
||||
*
|
||||
* Este método é responsável por orquestrar a criação de um novo pet, desde a validação inicial até a persistência do pet e o registro da relação com o tutor. A operação é **atômica** e garante a integridade dos dados através de uma transação de banco de dados.
|
||||
*
|
||||
* #### Fluxo de Operação:
|
||||
* 1. **Início da Transação:** Inicia uma transação no banco de dados (`DB::beginTransaction()`).
|
||||
* 2. **Validação de Dados:** O `DataValidator` verifica a presença e validade dos campos obrigatórios (nome, raça UUID, data de nascimento e sexo). Se falhar, a transação é revertida e um erro `400 Bad Request` é retornado.
|
||||
* 3. **Validação de Duplicidade (RGA):** Se fornecido, o Registro Geral Animal (RGA) é verificado quanto à unicidade. Se um pet com o mesmo RGA for encontrado, uma `Exception` é lançada com o código `409 Conflict`.
|
||||
* 4. **Preparação Final dos Dados:** O UUID do pet e o timestamp de criação são definidos.
|
||||
* 5. **Criação do Pet:** O método `storePet` do `PetModel` é chamado para inserir o registro do pet. Se falhar, uma `Exception` é lançada.
|
||||
* 6. **Associação ao Tutor:** O token JWT é decodificado para obter o UUID do tutor. O ID interno do tutor é buscado, e o pet é associado ao tutor através do método `storeUsuarioPet`. Se o tutor não for encontrado ou a associação falhar, uma `Exception` é lançada.
|
||||
* 7. **Confirmação e Retorno:** Se todas as operações forem bem-sucedidas, a transação é **confirmada** (`DB::commit()`) e o resultado de sucesso é retornado com o código `201 Created`.
|
||||
*
|
||||
* #### Tratamento de Erros:
|
||||
* - Qualquer `Exception` lançada durante o processo é capturada, a transação é **revertida** (`DB::rollBack()`), e um array de erro formatado contendo o código HTTP e a mensagem da exceção é retornado.
|
||||
*
|
||||
* @param PetDTO $petDTO O objeto DTO contendo os dados do novo pet.
|
||||
* @return array Um array associativo com o status da operação, código HTTP e os dados do pet criado.
|
||||
*/
|
||||
public function storePet(PetDTO $petDTO): array {
|
||||
// Inicia transação no banco de dados
|
||||
DB::beginTransaction();
|
||||
|
||||
try {
|
||||
// Valida os dados do DTO
|
||||
$dataValidador = new DataValidator(inputs: $petDTO->toArray());
|
||||
$dataValidador->validate(field: 'nome', rule: 'notEmpty', message: 'Nome do pet é obrigatório.');
|
||||
$dataValidador->validate(field: 'sexo', rule: 'notEmpty', message: 'Sexo do pet é obrigatório.');
|
||||
$dataValidador->validate(field: 'raca_id', rule: 'notEmpty', message: 'Raça do pet é obrigatória.');
|
||||
$dataValidador->validate(field: 'especie_id', rule: 'notEmpty', message: 'Espécie do pet é obrigatória.');
|
||||
$dataValidador->validate(field: 'data_nascimento', rule: 'notEmpty', message: 'Data de nascimento do pet é obrigatória.');
|
||||
|
||||
// Se houver erros de validação, retornar resposta de erro
|
||||
if(!$dataValidador->passes()) {
|
||||
return [
|
||||
'response_code' => 400,
|
||||
'status' => 'error',
|
||||
'message' => 'Validation errors',
|
||||
'output' => [
|
||||
'errors' => $dataValidador->getErrors()
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
// Verifica se o Registro Geral Animal do PET (RGA) é único, se fornecido
|
||||
if(($petDTO->getRegistroGeralAnimal() !== null) && !empty($petDTO->getRegistroGeralAnimal())) {
|
||||
$existingPet = $this->getPetByIdentifier(identifier: 'registro_geral_animal', value: $petDTO->getRegistroGeralAnimal());
|
||||
if($existingPet['status'] === 'success' && !empty($existingPet['output']['data'])) {
|
||||
throw new Exception(message: 'Já existe um pet cadastrado com este Registro Geral Animal (RGA).', code: 409);
|
||||
}
|
||||
}
|
||||
|
||||
// Define dados adicionais
|
||||
$petDTO->setUuid(uuid: Uuid::uuid7()->toString());
|
||||
$petDTO->setCreatedAt(created_at: (new DateTime())->format(format: 'Y-m-d H:i:s'));
|
||||
|
||||
// Cria o novo pet no banco de dados
|
||||
$storePet = (new PetModel())->storePet(petDTO: $petDTO);
|
||||
if($storePet['status'] !== 'success') {
|
||||
throw new Exception(message: $storePet['message'], code: $storePet['response_code']);
|
||||
}
|
||||
|
||||
// Consulta o token JWT
|
||||
$decodedToken = JWTService::decode(token: JWTService::getBearerToken());
|
||||
|
||||
// Consulta o ID do tutor pelo UUID
|
||||
$getTutor = (new UsuarioModel())->getUsuarioByIdentifier(identifier: 'uuid', value: $decodedToken['user_uuid']);
|
||||
if($getTutor['status'] !== 'success' || empty($getTutor['output']['data'])) {
|
||||
throw new Exception(message: 'Tutor não encontrado.', code: 404);
|
||||
}
|
||||
|
||||
// Relaciona o pet ao tutor autenticado
|
||||
$dataValidador = (new PetModel())->storeUsuarioPet(usuario_id: $getTutor['output']['data']['id'], pet_id: $storePet['output']['data']['id']);
|
||||
if($dataValidador['status'] !== 'success') {
|
||||
throw new Exception(message: $dataValidador['message'], code: $dataValidador['response_code']);
|
||||
}
|
||||
|
||||
DB::commit();
|
||||
return [
|
||||
'response_code' => 201,
|
||||
'status' => 'success',
|
||||
'message' => 'Pet criado com sucesso.',
|
||||
'output' => $storePet['output']
|
||||
];
|
||||
} catch(Exception $e) {
|
||||
DB::rollBack();
|
||||
return [
|
||||
'response_code' => $e->getCode(),
|
||||
'status' => 'error',
|
||||
'message' => $e->getMessage()
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
66
app/Module/Tutor/v0/bootstrap.php
Executable file
66
app/Module/Tutor/v0/bootstrap.php
Executable file
@@ -0,0 +1,66 @@
|
||||
<?php
|
||||
namespace Zampet\Module\Tutor;
|
||||
|
||||
use DateTime;
|
||||
use Exception;
|
||||
|
||||
// Caminho do manifest.json
|
||||
$manifestPath = realpath(path: __DIR__ . "/manifest.json");
|
||||
|
||||
if (!$manifestPath || !file_exists(filename: $manifestPath)) {
|
||||
throw new Exception(message: "Arquivo 'manifest.json' não encontrado.");
|
||||
}
|
||||
|
||||
// Lê e decodifica
|
||||
$manifest = json_decode(json: file_get_contents(filename: $manifestPath), associative: true);
|
||||
|
||||
// Verifica estrutura
|
||||
if (!isset($manifest['apis']) || !is_array(value: $manifest['apis'])) {
|
||||
throw new Exception(message: "Estrutura de 'apis' inválida no manifest.");
|
||||
}
|
||||
|
||||
$now = (new DateTime())->format(format: 'Y-m-d');
|
||||
$newApis = [];
|
||||
$updated = false;
|
||||
|
||||
// Checa se tem versão esperando que começa hoje
|
||||
foreach ($manifest['apis'] as $api) {
|
||||
if ($api['status'] === 'planned' && $api['start_date'] === $now) {
|
||||
// Promote a nova
|
||||
$api['status'] = 'active';
|
||||
$newApis[] = $api;
|
||||
$updated = true;
|
||||
} elseif ($api['status'] === 'active' && $api['start_date'] !== $now) {
|
||||
// Ignora versão antiga ativa
|
||||
continue;
|
||||
} else {
|
||||
$newApis[] = $api;
|
||||
}
|
||||
}
|
||||
|
||||
// Atualiza manifest se tiver mudança
|
||||
if ($updated) {
|
||||
$manifest['apis'] = $newApis;
|
||||
file_put_contents(filename: $manifestPath, data: json_encode(value: $manifest, flags: JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE));
|
||||
}
|
||||
|
||||
// Carrega a versão ativa
|
||||
$loaded = false;
|
||||
foreach ($manifest['apis'] as $api) {
|
||||
$startDate = new DateTime(datetime: $api['start_date']);
|
||||
if ($api['status'] === 'active' && $startDate <= new DateTime()) {
|
||||
$routeFile = MODULE_PATH . "/{$manifest['dirName']}/{$api['version']}/Routes/Routes.php";
|
||||
if (file_exists(filename: $routeFile)) {
|
||||
require_once realpath(path: $routeFile);
|
||||
$loaded = true;
|
||||
break;
|
||||
} else {
|
||||
throw new Exception(message: "Arquivo de rotas não encontrado para a versão '{$api['version']}'.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Verifica se carregou
|
||||
if (!$loaded) {
|
||||
throw new Exception(message: "Nenhuma versão ativa da API foi carregada.");
|
||||
}
|
||||
16
app/Module/Tutor/v0/manifest.json
Executable file
16
app/Module/Tutor/v0/manifest.json
Executable file
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"name": "Tutor",
|
||||
"dirName": "Tutor",
|
||||
"slug": "tutor",
|
||||
"description": "Gerencia informações dos tutores e suas interações.",
|
||||
"uuid": "0199b5de-f72c-702a-ba26-1c1d6f6d3dc2",
|
||||
"version": "1.0",
|
||||
"dependencies": [],
|
||||
"apis": [
|
||||
{
|
||||
"version": "v0",
|
||||
"status": "active",
|
||||
"start_date": "2025-08-01"
|
||||
}
|
||||
]
|
||||
}
|
||||
Reference in New Issue
Block a user