init commit
All checks were successful
build-api-image / build (push) Successful in 51s

This commit is contained in:
Antonio Lopes dos Santos
2026-08-04 16:52:02 -03:00
commit afec302c3e
11594 changed files with 1636728 additions and 0 deletions

View File

@@ -0,0 +1,964 @@
<?php
namespace App\Services\Almoxarifado;
use App\Enums\Almoxarifado\RequisicaoRespostaItemMotivo as RequisicaoRespostaItemMotivoEnum;
use App\Enums\Almoxarifado\RequisicaoRespostaStatus;
use App\Enums\Almoxarifado\RequisicaoStatus;
use App\Models\Almoxarifado\EntradaItem;
use App\Models\Almoxarifado\ParametrizacaoRequisicao;
use App\Models\Almoxarifado\Requisicao;
use App\Models\Almoxarifado\RequisicaoItem;
use App\Models\Almoxarifado\RequisicaoPermissao;
use App\Models\Almoxarifado\RequisicaoRespostaItemMotivo;
use App\Models\Cadastro\Estabelecimento\CentroCusto;
use App\Models\Cadastro\Estabelecimento\Unidade;
use App\Models\Cadastro\Material\Material;
use App\Services\Service;
use Carbon\Carbon;
use Illuminate\Support\Facades\DB;
use Illuminate\Validation\Rule;
class RequisicaoPendentePermissaoService extends Service
{
public static function datatable()
{
$requisicoes = DB::table('almoxarifado_requisicao as requisicao')
->join(
'cadastro_centro_custo as centro_custo',
'centro_custo.id',
'requisicao.created_centro_custo_id'
)
->join(
'cadastro_infraestrutura as infraestrutura',
'infraestrutura.id',
'centro_custo.infraestrutura_id'
)
->join(
'cadastro_unidade as unidade',
'unidade.id',
'infraestrutura.unidade_id'
)
->join(
'cadastro_setor as setor',
'setor.id',
'centro_custo.setor_id'
)
->join(
'cadastro_lotacao as lotacao',
'lotacao.id',
'requisicao.created_lotacao_id'
)
->join(
'cadastro_usuario as usuario',
'usuario.id',
'lotacao.usuario_id'
)
->join(
'cadastro_cidadao as cidadao',
'cidadao.id',
'usuario.cidadao_id'
)
->where('requisicao.status_id', '<>', RequisicaoStatus::FINALIZADA)
->where('requisicao.centro_custo_id', self::getCurrentCentroCusto()->id)
->where(function ($query) {
$query->whereNotExists(function ($query) {
$query->select(DB::raw(1))
->from('almoxarifado_requisicao_resposta as resposta')
->whereColumn('resposta.requisicao_id', 'requisicao.id')
->where('resposta.status_id', RequisicaoRespostaStatus::ENVIADA);
})->orWhereRaw("EXISTS (
SELECT 1
FROM almoxarifado_requisicao_resposta_item as resposta_item
WHERE resposta_item.requisicao_resposta_id = (
SELECT resposta.id
FROM almoxarifado_requisicao_resposta as resposta
WHERE resposta.requisicao_id = requisicao.id
AND resposta.status_id = " . RequisicaoRespostaStatus::ENVIADA . "
ORDER BY resposta.id DESC
LIMIT 1
)
AND resposta_item.motivo_id IN (
" . RequisicaoRespostaItemMotivoEnum::ENTREGA_PARCIAL . ",
" . RequisicaoRespostaItemMotivoEnum::PENDENTE_DE_ENTREGA . "
)
)");
})
->select(
'requisicao.id',
DB::raw("DATE_FORMAT(requisicao.created_at, '%d/%m/%Y') as data_requisicao"),
'unidade.nome_fantasia as unidade_nome_fantasia',
DB::raw("COALESCE(infraestrutura.nome, unidade.nome_fantasia) AS infraestrutura_nome"),
'setor.nome as setor_nome',
'cidadao.nome as usuarioNome',
'requisicao.numero',
DB::raw("IF(requisicao.status_id = " . RequisicaoStatus::RESPOSTA_INICIADA . ", 1, 0) as iniciou_resposta"),
)
->addSelect([
'possui_envio_pendente' => function ($query) {
$query->selectRaw("COALESCE((
SELECT 1
FROM almoxarifado_requisicao_resposta_item as resposta_item
WHERE resposta_item.requisicao_resposta_id = (
SELECT resposta.id
FROM almoxarifado_requisicao_resposta as resposta
WHERE resposta.requisicao_id = requisicao.id
AND resposta.enviada_em IS NOT NULL
ORDER BY resposta.id DESC
LIMIT 1
)
AND resposta_item.motivo_id IN (
" . RequisicaoRespostaItemMotivoEnum::ENTREGA_PARCIAL . ",
" . RequisicaoRespostaItemMotivoEnum::PENDENTE_DE_ENTREGA . "
)
LIMIT 1
), 0)");
}
]);
return datatables()
->of($requisicoes)
->filterColumn('requisicao.created_at', function ($query, $keyword) {
$query->whereRaw("DATE_FORMAT(requisicao.created_at, '%d/%m/%Y') like ?", ["%{$keyword}%"])
->orWhereRaw(
"CONCAT(
SUBSTR(requisicao.created_at,9,2),
SUBSTR(requisicao.created_at,6,2),
SUBSTR(requisicao.created_at,1,4)
) like ?",
["%{$keyword}%"]
);
})
->filterColumn('infraestrutura.nome', function ($query, $keyword) {
$query->whereRaw("COALESCE(infraestrutura.nome, unidade.nome_fantasia) like ?", ["%{$keyword}%"]);
})
->skipTotalRecords()
->toJson();
}
public static function datatablePermissao()
{
$centrosCusto = DB::table('cadastro_centro_custo as centro_custo')
->join(
'cadastro_infraestrutura as infraestrutura',
'infraestrutura.id',
'centro_custo.infraestrutura_id'
)
->join(
'cadastro_unidade as unidade',
'unidade.id',
'infraestrutura.unidade_id'
)
->join(
'cadastro_setor as setor',
'setor.id',
'centro_custo.setor_id'
)
->whereNull('centro_custo.deleted_at')
->where('centro_custo.id', '<>', self::getCurrentCentroCusto()->id)
->select(
'centro_custo.id',
'unidade.cnes',
'unidade.nome_fantasia as unidade_nome_fantasia',
DB::raw("COALESCE(infraestrutura.nome, unidade.nome_fantasia) AS infraestrutura_nome"),
'setor.nome as setor_nome',
);
return datatables()
->of($centrosCusto)
->filterColumn('infraestrutura.nome', function ($query, $keyword) {
$query->whereRaw("COALESCE(infraestrutura.nome, unidade.nome_fantasia) like ?", ["%{$keyword}%"]);
})
->skipTotalRecords()
->toJson();
}
public static function getMateriais($centroCustoRequisitanteId)
{
$centroCustoLogadoId = self::getCurrentCentroCusto()->id;
$grupos = self::getCurrentCentroCusto()
->almoxarifadoParametrizacoesControleEstoqueGrupo
->map(fn ($parametrizacaoGrupo) => [
'id' => $parametrizacaoGrupo->grupo->id,
'nome' => $parametrizacaoGrupo->grupo->nome,
'materiais' => $parametrizacaoGrupo->grupo->materiais()
->where('is_ativo', true)
->where(function ($query) use ($parametrizacaoGrupo) {
$query
->whereDoesntHave('subgrupo')
->orWhereHas('subgrupo', function ($query) use ($parametrizacaoGrupo) {
$query->whereHas('almoxarifadoParametrizacoesControleEstoqueSubgrupo',
function ($query) use ($parametrizacaoGrupo) {
$query->where('parametrizacao_controle_estoque_grupo_id', $parametrizacaoGrupo->id);
}
);
});
})
->get()
->map(function ($material) use ($centroCustoLogadoId, $centroCustoRequisitanteId) {
$permissao = $material->almoxarifadoRequisicaoPermissoes()
->where('created_centro_custo_id', $centroCustoLogadoId)
->where('centro_custo_requisitante_id', $centroCustoRequisitanteId)
->first();
return [
'id' => $material->id,
'permite_requisitar' => !is_null($permissao),
'codigo' => $material->codigo_material,
'descricao_completa' => $material->descricao_completa,
'subgrupo_nome' => $material->subgrupo->nome ?? null,
'estoque_maximo' => $permissao->estoque_maximo ?? null,
];
}),
])
->all();
foreach ($grupos as &$grupo) {
$grupo['permite_requisitar'] = collect($grupo['materiais'])
->contains('permite_requisitar', true);
}
unset($grupo);
return $grupos;
}
public static function datatableHistorico()
{
$requisicoes = DB::table('almoxarifado_requisicao as requisicao')
->join(
'cadastro_centro_custo as centro_custo',
'centro_custo.id',
'requisicao.created_centro_custo_id'
)
->join(
'cadastro_infraestrutura as infraestrutura',
'infraestrutura.id',
'centro_custo.infraestrutura_id'
)
->join(
'cadastro_unidade as unidade',
'unidade.id',
'infraestrutura.unidade_id'
)
->join(
'cadastro_setor as setor',
'setor.id',
'centro_custo.setor_id'
)
->join(
'cadastro_lotacao as lotacao',
'lotacao.id',
'requisicao.created_lotacao_id'
)
->join(
'cadastro_usuario as usuario',
'usuario.id',
'lotacao.usuario_id'
)
->join(
'cadastro_cidadao as cidadao',
'cidadao.id',
'usuario.cidadao_id'
)
->where('requisicao.centro_custo_id', self::getCurrentCentroCusto()->id)
->where('unidade.id', request()->unidade_requisitante_id)
->whereExists(function ($query) {
$query->select(DB::raw(1))
->from('almoxarifado_requisicao_item as item')
->join(
'almoxarifado_requisicao_resposta_item as resposta_item',
'resposta_item.requisicao_item_id',
'item.id'
)
->whereColumn('item.requisicao_id', 'requisicao.id')
->where('item.material_id', request()->material_id)
->whereNotNull('saida_item_id');
})
->select(
'requisicao.id',
'requisicao.numero',
DB::raw("DATE_FORMAT(requisicao.created_at, '%d/%m/%Y') as data_requisicao"),
DB::raw("COALESCE(infraestrutura.nome, unidade.nome_fantasia) AS infraestrutura_nome"),
'setor.nome as setor_nome',
'cidadao.nome as usuario_nome',
)
->addSelect([
'concedido' => function ($query) {
$query->select(DB::raw('SUM(saida_item_entrada_item.quantidade_saida)'))
->from('almoxarifado_saida_item_entrada_item as saida_item_entrada_item')
->join(
'almoxarifado_saida_item as saida_item',
'saida_item.id',
'saida_item_entrada_item.saida_item_id'
)
->join(
'almoxarifado_requisicao_resposta_item as resposta_item',
'resposta_item.saida_item_id',
'saida_item.id'
)
->join(
'almoxarifado_requisicao_item as requisicao_item',
'requisicao_item.id',
'resposta_item.requisicao_item_id'
)
->whereColumn('requisicao_item.requisicao_id', 'requisicao.id')
->where('requisicao_item.material_id', request()->material_id);
}
]);
return datatables()
->of($requisicoes)
->filterColumn('requisicao.created_at', function ($query, $keyword) {
$query->whereRaw("DATE_FORMAT(requisicao.created_at, '%d/%m/%Y') like ?", ["%{$keyword}%"]);
})
->filterColumn('infraestrutura.nome', function ($query, $keyword) {
$query->whereRaw("COALESCE(infraestrutura.nome, unidade.nome_fantasia) like ?", ["%{$keyword}%"]);
})
->toJson();
}
public static function storePermissoes()
{
self::validatePermissao();
DB::transaction(function () {
RequisicaoPermissao::where('created_centro_custo_id', self::getCurrentCentroCusto()->id)
->where('centro_custo_requisitante_id', request()->centro_custo_requisitante_id)
->whereNotIn('material_id', collect(request()->materiais)->pluck('id'))
->delete();
foreach (request()->materiais as $material) {
RequisicaoPermissao::updateOrCreate(
[
'created_centro_custo_id' => self::getCurrentCentroCusto()->id,
'centro_custo_requisitante_id' => request()->centro_custo_requisitante_id,
'material_id' => $material['id'],
],
[
'estoque_maximo' => $material['estoque_maximo'],
]
);
}
});
}
private static function validatePermissao()
{
$rules = [
'centro_custo_requisitante_id' => [
'required',
'integer',
Rule::exists(CentroCusto::class, 'id'),
],
'materiais' => [
'present',
'array',
],
'materiais.*.id' => [
'required',
'integer',
Rule::exists(Material::class, 'id'),
],
'materiais.*.estoque_maximo' => [
'nullable',
'integer',
'max:99999999',
]
];
$messages = [];
request()->validate($rules, $messages);
}
public static function createImportacao($centroCustoDestinoId)
{
$centroCustoLogadoId = self::getCurrentCentroCusto()->id;
return [
'form' => [
'unidades' => Unidade::orderBy('nome_fantasia')
->whereHas('infraestruturas', function ($query) use ($centroCustoDestinoId, $centroCustoLogadoId) {
$query->whereHas('centrosCusto', function ($query) use ($centroCustoDestinoId, $centroCustoLogadoId) {
$query
->where('id', '<>', $centroCustoDestinoId)
->whereHas('almoxarifadoRequisicaoPermissoesRequisitante', function ($query) use ($centroCustoLogadoId) {
$query->where('created_centro_custo_id', $centroCustoLogadoId);
});
});
})
->get()
->map(fn ($unidade) => [
'id' => $unidade->id,
'nome_fantasia' => $unidade->nome_fantasia,
'infraestruturas' => $unidade->infraestruturas()
->whereHas('centrosCusto', function ($query) use ($centroCustoDestinoId, $centroCustoLogadoId) {
$query
->where('id', '<>', $centroCustoDestinoId)
->whereHas('almoxarifadoRequisicaoPermissoesRequisitante', function ($query) use ($centroCustoLogadoId) {
$query->where('created_centro_custo_id', $centroCustoLogadoId);
});
})
->get()
->sortBy('nome')
->map(fn ($infraestrutura) => [
'id' => $infraestrutura->id,
'nome' => $infraestrutura->nome,
'centros_custo' => $infraestrutura->centrosCusto()
->where('id', '<>', $centroCustoDestinoId)
->whereHas('almoxarifadoRequisicaoPermissoesRequisitante', function ($query) use ($centroCustoLogadoId) {
$query->where('created_centro_custo_id', $centroCustoLogadoId);
})
->get()
->map(fn ($centroCusto) => [
'id' => $centroCusto->id,
'setor_nome' => $centroCusto->setor->nome,
])
->sortBy('setor_nome')
->values()
])
->values()
]),
'unidade_id' => null,
'infraestrutura_id' => null,
],
'model' => [
'centro_custo_origem_id' => null,
],
];
}
public static function storeImportacao()
{
self::validateImportacao();
DB::transaction(function () {
RequisicaoPermissao::where('created_centro_custo_id', self::getCurrentCentroCusto()->id)
->where('centro_custo_requisitante_id', request()->centro_custo_destino_id)
->delete();
RequisicaoPermissao::where('created_centro_custo_id', self::getCurrentCentroCusto()->id)
->where('centro_custo_requisitante_id', request()->centro_custo_origem_id)
->get()
->each(function ($permissao) {
if ($permissao->material->is_ativo) {
RequisicaoPermissao::create([
'centro_custo_requisitante_id' => request()->centro_custo_destino_id,
'material_id' => $permissao->material_id,
'estoque_maximo' => request()->importar_estoque_maximo ? $permissao->estoque_maximo : null,
]);
}
});
});
}
private static function validateImportacao()
{
$rules = [
'centro_custo_origem_id' => [
'required',
'integer',
Rule::exists(CentroCusto::class, 'id'),
],
'centro_custo_destino_id' => [
'required',
'integer',
Rule::exists(CentroCusto::class, 'id'),
],
'importar_estoque_maximo' => [
'required',
'boolean',
]
];
$messages = [];
request()->validate($rules, $messages);
}
public static function edit($id)
{
$requisicao = Requisicao::findOrFail($id);
$ultimoEnvio = $requisicao->respostas()
->whereNotNull('enviada_em')
->orderByDesc('id')
->first();
$respostaIniciada = $requisicao->respostas()
->where('status_id', RequisicaoRespostaStatus::INICIADA)
->first();
$itens = $requisicao->itens()->withAggregate('material', 'descricao')
->when(request()->has('sort') && request()->sort !== 'null', function ($query) {
return $query->orderBy('material_descricao', request()->sort);
})
->get();
if ($ultimoEnvio) {
$itens = $itens->filter(function ($item) use ($ultimoEnvio) {
$ultimoEnvioItem = $ultimoEnvio->itens()->where('requisicao_item_id', $item->id)->first();
return !is_null($ultimoEnvioItem) && collect([
RequisicaoRespostaItemMotivoEnum::ENTREGA_PARCIAL,
RequisicaoRespostaItemMotivoEnum::PENDENTE_DE_ENTREGA,
])->contains($ultimoEnvioItem->motivo_id);
});
}
return [
'form' => self::getFormData($requisicao),
'model' => [
'itens' => $itens->map(function ($item) use ($respostaIniciada) {
$respostaItemIniciada = $respostaIniciada
? $respostaIniciada->itens()->where('requisicao_item_id', $item->id)->first()
: null;
$estoque = AlmoxarifadoService::getEstoque(
$item->material->id,
null,
$respostaItemIniciada->reserva_item_id ?? null
);
$estoqueTotal = $estoque['total'];
$reservas = AlmoxarifadoService::getReservas($item->material->id)['agrupadas'];
$estoqueTotalRequisitante = AlmoxarifadoService::getEstoque(
$item->material->id,
$item->requisicao->created_centro_custo_id
)['total'];
$respostaItemEnviadas = $item->respostaItens()
->whereHas('requisicaoResposta', function ($query) {
$query->whereNotNull('enviada_em');
})
->get();
$entregue = $respostaItemEnviadas ? $respostaItemEnviadas
->map(fn ($respostaItemEnviada) => $respostaItemEnviada->saidaItem->quantidade ?? 0)
->sum() : 0;
$restanteRequisitado = $item->quantidade - $entregue;
$concedido = 0;
$escolheuEntradaItemManualmente = false;
$entradaItens = [];
$motivoId = null;
if ($respostaItemIniciada) {
$entradaItensReservados = [];
if ($respostaItemIniciada->reservaItem) {
$concedido = $respostaItemIniciada->reservaItem->quantidade;
$escolheuEntradaItemManualmente = $respostaItemIniciada->reservaItem
->escolheu_entrada_item_manualmente;
$entradaItensReservados = $respostaItemIniciada->reservaItem->entradaItens
->map(fn ($entradaItem) => [
'entrada_item_id' => $entradaItem->id,
'quantidade_saida' => $entradaItem->pivotReservaItemEntradaItem->quantidade_saida,
]);
}
$entradaItens = collect($estoque['por_entrada'])
->map(function ($entradaItem) use ($entradaItensReservados) {
$entradaItem['quantidade_saida'] = collect($entradaItensReservados)
->where('entrada_item_id', $entradaItem['entrada_item_id'])
->first()['quantidade_saida'] ?? 0;
return $entradaItem;
});
$motivoId = $respostaItemIniciada->motivo_id;
}
else {
$quantidade = $respostaItemEnviadas->isEmpty() ? $item->quantidade : $restanteRequisitado;
$concedido = $quantidade > $estoqueTotal ? $estoqueTotal : $quantidade;
$entradaItensData = AlmoxarifadoService::getEntradaItensData(
$item->material->id,
[
'escolheu_entrada_item_manualmente' => false,
'quantidade' => $concedido,
]
);
$entradaItensAutomaticos = [];
foreach ($entradaItensData as $entradaItemId => $entradaItemData) {
$entradaItensAutomaticos[] = [
'entrada_item_id' => $entradaItemId,
'quantidade_saida' => $entradaItemData['quantidade_saida'],
];
}
$entradaItens = collect($estoque['por_entrada'])
->map(function ($entradaItem) use ($entradaItensAutomaticos) {
$entradaItem['quantidade_saida'] = collect($entradaItensAutomaticos)
->where('entrada_item_id', $entradaItem['entrada_item_id'])
->first()['quantidade_saida'] ?? 0;
return $entradaItem;
});
$motivoId = $estoqueTotal === 0 ? RequisicaoRespostaItemMotivoEnum::SEM_ESTOQUE : null;
}
$possuiEntradaComLote = !is_null(collect($entradaItens)->whereNotNull('lote')->first());
$data = [
'requisicao_item_id' => $item->id,
'unidade_requisitante' => [
'id' => $item->requisicao->createdCentroCusto->infraestrutura->unidade->id,
'nome_fantasia' => $item->requisicao->createdCentroCusto->infraestrutura->unidade->nome_fantasia
],
'material' => [
'id' => $item->material->id,
'codigo' => $item->material->codigo_material,
'descricao_completa' => $item->material->descricao_completa,
],
'possui_entrada_com_lote' => $possuiEntradaComLote,
'estoque_disponivel' => $estoqueTotal,
'reservas' => $reservas,
'estoque_requisitante' => $estoqueTotalRequisitante,
'concedido' => $concedido,
'escolheu_entrada_item_manualmente' => $escolheuEntradaItemManualmente,
'entrada_itens' => $entradaItens,
'motivo_id' => $motivoId,
'motivo_outro' => $respostaItemIniciada->motivo_outro ?? null,
];
if ($respostaItemEnviadas->isEmpty()) {
$data['requisitado'] = $item->quantidade;
}
else {
$data['entregue'] = $entregue;
$data['restante_requisitado'] = $restanteRequisitado;
}
return $data;
})->values(),
'observacoes' => $respostaIniciada->observacoes ?? null,
]
];
}
private static function getFormData($requisicao)
{
$parametrizacao = ParametrizacaoRequisicao::first();
return [
'data_requisicao' => (new Carbon($requisicao->created_at))->format('d/m/Y'),
'numero' => $requisicao->numero,
'requisitante' => [
'unidade_nome_fantasia' => $requisicao->createdCentroCusto->infraestrutura->unidade->nome_fantasia,
'infraestrutura_nome' => $requisicao->createdCentroCusto->infraestrutura->nome,
'setor_nome' => $requisicao->createdCentroCusto->setor->nome,
'usuario_nome' => $requisicao->createdLotacao->usuario->cidadao->nome,
],
'envios' => self::getEnvios($requisicao),
'motivos' => RequisicaoRespostaItemMotivo::orderBy('nome')->get(['id', 'nome']),
'motivo_obrigatorio' => $parametrizacao->motivo_obrigatorio ?? false
];
}
private static function getEnvios($requisicao)
{
$envios = $requisicao->respostas()
->whereNotNull('enviada_em')
->orderBy('enviada_em')
->get();
$entregue = [];
$envios = $envios->map(function ($resposta, $i) use (&$entregue) {
$numeroEnvio = $i + 1;
$itens = $resposta->itens->map(function ($respostaItem) use ($numeroEnvio, &$entregue) {
$material = $respostaItem->requisicaoItem->material;
if (!isset($entregue[$material->id])) {
$entregue[$material->id] = 0;
}
$item = [
'material' => [
'codigo' => $material->codigo_material,
'descricao_completa' => $material->descricao_completa,
],
'motivo_nome' => $respostaItem->motivo->nome ?? null,
'motivo_outro' => $respostaItem->motivo_outro,
];
if ($numeroEnvio === 1) {
$item['requisitado'] = $respostaItem->requisicaoItem->quantidade;
}
else {
$item['entregue'] = $entregue[$material->id];
$item['restante_requisitado'] = $respostaItem->requisicaoItem->quantidade - $entregue[$material->id];
}
$item['possui_entrada_com_lote'] = is_null($respostaItem->saidaItem) ? false
: $respostaItem->saidaItem->entradaItens()->whereNotNull('lote')->exists();
if ($item['possui_entrada_com_lote']) {
$item['entrada_itens'] = $respostaItem->saidaItem
? $respostaItem->saidaItem->entradaItens->map(fn ($entradaItem) => [
'concedido' => $entradaItem->pivotSaidaItemEntradaItem->quantidade_saida,
'lote' => $entradaItem->lote,
'validade_lote' => $entradaItem->validade_lote
? $entradaItem->validade_lote->format('d/m/Y')
: null,
]) : [];
$entregue[$material->id] += collect($item['entrada_itens'])->sum('concedido');
}
else {
$item['concedido'] = $respostaItem->saidaItem ? $respostaItem->saidaItem->quantidade : 0;
$entregue[$material->id] += $item['concedido'];
}
return $item;
});
return [
'numero_envio' => $numeroEnvio,
'data_hora' => $resposta->enviada_em->format('d/m/Y H:i'),
'usuario' => $resposta->enviadaLotacao->usuario->cidadao->nome ?? null,
'itens' => $itens,
'observacoes' => $resposta->observacoes,
];
});
return collect($envios)->sortByDesc('numero_envio')->values();
}
public static function update($id)
{
self::validate();
$requisicao = Requisicao::findOrFail($id);
DB::transaction(function () use ($requisicao) {
$resposta = $requisicao->respostas()->updateOrCreate(
['status_id' => RequisicaoRespostaStatus::INICIADA],
['observacoes' => request()->observacoes]
);
$reservaAnteriorId = $resposta->reserva_id;
$resposta->update(['reserva_id' => null]);
$resposta->itens->each(fn ($i) => $i->update(['reserva_item_id' => null]));
$itens = request()->itens;
foreach ($itens as &$item) {
$requisicaoItem = RequisicaoItem::findOrFail($item['requisicao_item_id']);
$item['material_id'] = $requisicaoItem->material_id;
}
unset($item);
$itensComQuantidadeConcedida = collect($itens)
->filter(fn ($i) => $i['concedido'] > 0)
->map(fn ($item) => [
'material_id' => $item['material_id'],
'quantidade' => $item['concedido'],
'escolheu_entrada_item_manualmente' => $item['escolheu_entrada_item_manualmente'],
'entrada_itens' => $item['entrada_itens'],
]);
if (request()->enviar_resposta) {
$saida = AlmoxarifadoService::saveSaidaDeRequisicao(
$itensComQuantidadeConcedida,
$reservaAnteriorId
);
$resposta->update([
'saida_id' => $saida->id ?? null,
'status_id' => RequisicaoRespostaStatus::ENVIADA,
'enviada_em' => Carbon::now(),
'enviada_lotacao_id' => self::getCurrentLotacao()->id,
]);
foreach ($itens as $item) {
$saidaItemId = null;
if ($saida) {
$saidaItemId = $saida->itens()
->where('material_id', $item['material_id'])
->first()->id ?? null;
}
$resposta->itens()->updateOrCreate(
['requisicao_item_id' => $item['requisicao_item_id']],
array_merge(self::getItemData($item), [
'saida_item_id' => $saidaItemId,
])
);
}
}
else {
$reserva = AlmoxarifadoService::saveReservaDeRequisicao(
$itensComQuantidadeConcedida,
$reservaAnteriorId
);
if ($reserva) {
$resposta->update(['reserva_id' => $reserva->id]);
}
foreach ($itens as $item) {
$reservaItemId = null;
if ($reserva) {
$reservaItemId = $reserva->itens()
->where('material_id', $item['material_id'])
->first()->id ?? null;
}
$resposta->itens()->updateOrCreate(
['requisicao_item_id' => $item['requisicao_item_id']],
array_merge(self::getItemData($item), [
'reserva_item_id' => $reservaItemId,
])
);
}
}
if ($requisicao->status_id !== RequisicaoStatus::RESPOSTA_INICIADA) {
$requisicao->update(['status_id' => RequisicaoStatus::RESPOSTA_INICIADA]);
}
});
return $requisicao->fresh();
}
private static function getItemData($item)
{
return [
'motivo_id' => $item['motivo_id'],
'motivo_outro' => $item['motivo_id'] === RequisicaoRespostaItemMotivoEnum::OUTRO
? $item['motivo_outro'] : null,
];
}
public static function validate()
{
$rules = [
'enviar_resposta' => [
'required',
'boolean',
],
'observacoes' => [
'nullable',
'string',
'max:1000',
],
'itens' => [
'required',
'array',
],
'itens.*.requisicao_item_id' => [
'required',
'integer',
Rule::exists(RequisicaoItem::class, 'id'),
],
'itens.*.concedido' => [
'required',
'integer',
],
'itens.*.escolheu_entrada_item_manualmente' => [
'required',
'boolean',
],
'itens.*.entrada_itens' => [
'present',
'array',
],
'itens.*.entrada_itens.*.entrada_item_id' => [
'required',
'integer',
Rule::exists(EntradaItem::class, 'id'),
],
'itens.*.entrada_itens.*.quantidade_saida' => [
'required',
'integer',
'min:1',
],
'itens.*.motivo_id' => [
'nullable',
'integer',
Rule::exists(RequisicaoRespostaItemMotivo::class, 'id'),
],
'itens.*.motivo_outro' => [
'nullable',
'string',
'max:300',
],
];
$messages = [];
request()->validate($rules, $messages);
}
}