Files
rkm-conectasus-ci-sandbox/api/app/Services/Almoxarifado/RequisicaoAberturaFechamentoService.php
Antonio Lopes dos Santos afec302c3e
All checks were successful
build-api-image / build (push) Successful in 51s
init commit
2026-08-04 16:52:02 -03:00

924 lines
39 KiB
PHP

<?php
namespace App\Services\Almoxarifado;
use App\Enums\Almoxarifado\RequisicaoRespostaItemMotivo;
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\RequisicaoPermissao;
use App\Models\Almoxarifado\RequisicaoRespostaItem;
use App\Models\Cadastro\Estabelecimento\CentroCusto;
use App\Models\Cadastro\Estabelecimento\Unidade;
use App\Models\Cadastro\Material\Material;
use App\Services\Cadastro\Material\MaterialService;
use App\Services\Service;
use Carbon\Carbon;
use Illuminate\Support\Facades\DB;
use Illuminate\Validation\Rule;
class RequisicaoAberturaFechamentoService extends Service
{
public static function datatable()
{
$requisicoes = DB::table('almoxarifado_requisicao as requisicao')
->join(
'cadastro_centro_custo as centro_custo',
'centro_custo.id',
'requisicao.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.created_centro_custo_id', self::getCurrentCentroCusto()->id)
->where('requisicao.status_id', '<>', RequisicaoStatus::FINALIZADA)
->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 usuario_requisitante',
'requisicao.numero',
DB::raw("IF(requisicao.status_id = " . RequisicaoStatus::RESPOSTA_INICIADA . ", 1, 0) as iniciou_resposta"),
)
->addSelect([
'possui_novo_envio' => 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)
->limit(1);
},
'data_ultimo_recebimento' => function ($query) {
$query->select(DB::raw("DATE_FORMAT(resposta.recebida_em, '%d/%m/%Y')"))
->from('almoxarifado_requisicao_resposta as resposta')
->whereColumn('resposta.requisicao_id', 'requisicao.id')
->where('resposta.status_id', RequisicaoRespostaStatus::RECEBIDA)
->orderByDesc('resposta.recebida_em')
->limit(1);
},
]);
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 getEstoque($materialId, $centroCustoAlmoxarifadoId)
{
$estoque = MaterialService::getEstoque($materialId)['total'];
$estoqueMaximo = null;
$permiteRequisitar = null;
$permissao = RequisicaoPermissao::where('created_centro_custo_id', $centroCustoAlmoxarifadoId)
->where('centro_custo_requisitante_id', self::getCurrentCentroCusto()->id)
->where('material_id', $materialId)
->first();
if ($permissao && !is_null($permissao->estoque_maximo)) {
$estoqueMaximo = (int) $permissao->estoque_maximo;
$permiteRequisitar = $estoque > $estoqueMaximo ? 0 : $estoqueMaximo - $estoque;
}
$prazo = ParametrizacaoService::getParametrizacaoRequisicao()['prazo_validade'];
return [
'estoque' => $estoque,
'estoque_maximo' => $estoqueMaximo,
'permite_requisitar' => $permiteRequisitar,
'prazo' => $prazo,
'vencimento' => !empty(self::getValidades($materialId, $prazo)),
];
}
private static function getValidades($id, $prazo)
{
$hoje = Carbon::now()->startOfDay();
$dataFim = $hoje->copy()->addDays($prazo); // Crie uma cópia para não modificar $hoje
return EntradaItem::whereHas('entrada', fn($q) => $q->where('centro_custo_id', self::getCurrentCentroCusto()->id))
->where('material_id', $id)
->whereNull('estornado_em')
->whereBetween('validade_lote', [$hoje->format('Y-m-d'), $dataFim->format('Y-m-d')])
->get()
->map(function($q) {
return [
'validade' => Carbon::parse($q->validade_lote)->format('Y-m-d')
];
})->values()->all();
}
public static function getMateriaisPermitidos($centroCustoAlmoxarifadoId)
{
$permiteRequisitarSemEstoque = ParametrizacaoService::getParametrizacaoRequisicao()
['permite_requisitar_materiais_sem_estoque'];
$materiais = DB::table('cadastro_material')
->join(
'cadastro_apresentacao',
'cadastro_apresentacao.id',
'cadastro_material.apresentacao_id'
)
->join(
'cadastro_grupo',
'cadastro_grupo.id',
'cadastro_material.grupo_id'
)
->join(
'almoxarifado_requisicao_permissao',
'almoxarifado_requisicao_permissao.material_id',
'cadastro_material.id'
)
->leftJoin(
'cadastro_unidade_medida as apresentacao_unidade_medida',
'apresentacao_unidade_medida.id',
'cadastro_material.apresentacao_unidade_medida_id'
)
->leftJoin(
'cadastro_subgrupo',
'cadastro_subgrupo.id',
'cadastro_material.subgrupo_id'
)
->where('cadastro_material.is_ativo', true)
->where('almoxarifado_requisicao_permissao.centro_custo_requisitante_id', self::getCurrentCentroCusto()->id)
->where('almoxarifado_requisicao_permissao.created_centro_custo_id', $centroCustoAlmoxarifadoId)
->whereNull('cadastro_material.deleted_at')
->when(!$permiteRequisitarSemEstoque, function ($query) use ($centroCustoAlmoxarifadoId) {
$query->whereRaw("COALESCE((
SELECT SUM(
COALESCE(almoxarifado_entrada_item.quantidade, 0)
-
COALESCE((
SELECT SUM(almoxarifado_saida_item_entrada_item.quantidade_saida)
FROM almoxarifado_saida_item_entrada_item
JOIN almoxarifado_saida_item
ON almoxarifado_saida_item.id = almoxarifado_saida_item_entrada_item.saida_item_id
JOIN almoxarifado_saida
ON almoxarifado_saida.id = almoxarifado_saida_item.saida_id
WHERE almoxarifado_saida_item_entrada_item.entrada_item_id = almoxarifado_entrada_item.id
AND almoxarifado_saida.finalizada = 1
), 0)
-
COALESCE((
SELECT SUM(almoxarifado_reserva_item_entrada_item.quantidade_saida)
FROM almoxarifado_reserva_item_entrada_item
JOIN almoxarifado_reserva_item
ON almoxarifado_reserva_item.id = almoxarifado_reserva_item_entrada_item.reserva_item_id
WHERE almoxarifado_reserva_item_entrada_item.entrada_item_id = almoxarifado_entrada_item.id
), 0)
)
FROM almoxarifado_entrada_item
JOIN almoxarifado_entrada
ON almoxarifado_entrada.id = almoxarifado_entrada_item.entrada_id
WHERE almoxarifado_entrada.finalizada = 1
AND almoxarifado_entrada_item.material_id = cadastro_material.id
AND almoxarifado_entrada.centro_custo_id = {$centroCustoAlmoxarifadoId}
), 0) > 0");
})
->select(
'cadastro_material.id',
'cadastro_material.codigo_material',
DB::raw(MaterialService::getDescricaoCompletaRaw(
'cadastro_material',
'cadastro_apresentacao',
'apresentacao_unidade_medida'
) . " as descricao"),
'cadastro_grupo.id as grupo_id',
'cadastro_grupo.nome as grupo_nome',
'cadastro_subgrupo.nome as subgrupo',
'almoxarifado_requisicao_permissao.estoque_maximo'
)
->addSelect([
'requisicao_que_nao_concluiu_entrega' => function ($query) use ($centroCustoAlmoxarifadoId) {
$query->select(DB::raw('GROUP_CONCAT(DISTINCT almoxarifado_requisicao.numero ORDER BY almoxarifado_requisicao.numero SEPARATOR ", ")'))
->from('almoxarifado_requisicao_item')
->join(
'almoxarifado_requisicao',
'almoxarifado_requisicao.id',
'almoxarifado_requisicao_item.requisicao_id',
)
->whereColumn('almoxarifado_requisicao_item.material_id', 'cadastro_material.id')
->where('almoxarifado_requisicao.centro_custo_id', $centroCustoAlmoxarifadoId)
->where('almoxarifado_requisicao.created_centro_custo_id', self::getCurrentCentroCusto()->id)
->whereIn('almoxarifado_requisicao.status_id', [
RequisicaoStatus::ABERTA,
RequisicaoStatus::RESPOSTA_INICIADA,
])
->whereNotExists(function ($query) {
$query->select(DB::raw(1))
->from('almoxarifado_requisicao_resposta_item')
->join(
'almoxarifado_requisicao_resposta',
'almoxarifado_requisicao_resposta.id',
'almoxarifado_requisicao_resposta_item.requisicao_resposta_id',
)
->whereColumn(
'almoxarifado_requisicao_resposta_item.requisicao_item_id',
'almoxarifado_requisicao_item.id'
)
->where(
'almoxarifado_requisicao_resposta.status_id',
RequisicaoRespostaStatus::RECEBIDA
)
->where(function ($query) {
$query
->whereNull('almoxarifado_requisicao_resposta_item.motivo_id')
->orWhereNotIn('almoxarifado_requisicao_resposta_item.motivo_id', [
RequisicaoRespostaItemMotivo::ENTREGA_PARCIAL,
RequisicaoRespostaItemMotivo::PENDENTE_DE_ENTREGA,
]);
});
});
},
'estoque' => function ($query) {
$query->selectRaw("COALESCE((
SELECT SUM(
COALESCE(almoxarifado_entrada_item.quantidade, 0)
-
COALESCE((
SELECT SUM(almoxarifado_saida_item_entrada_item.quantidade_saida)
FROM almoxarifado_saida_item_entrada_item
JOIN almoxarifado_saida_item
ON almoxarifado_saida_item.id = almoxarifado_saida_item_entrada_item.saida_item_id
JOIN almoxarifado_saida
ON almoxarifado_saida.id = almoxarifado_saida_item.saida_id
WHERE almoxarifado_saida_item_entrada_item.entrada_item_id = almoxarifado_entrada_item.id
AND almoxarifado_saida.finalizada = 1
), 0)
-
COALESCE((
SELECT SUM(almoxarifado_reserva_item_entrada_item.quantidade_saida)
FROM almoxarifado_reserva_item_entrada_item
JOIN almoxarifado_reserva_item
ON almoxarifado_reserva_item.id = almoxarifado_reserva_item_entrada_item.reserva_item_id
WHERE almoxarifado_reserva_item_entrada_item.entrada_item_id = almoxarifado_entrada_item.id
), 0)
)
FROM almoxarifado_entrada_item
JOIN almoxarifado_entrada
ON almoxarifado_entrada.id = almoxarifado_entrada_item.entrada_id
WHERE almoxarifado_entrada.finalizada = 1
AND almoxarifado_entrada_item.material_id = cadastro_material.id
AND almoxarifado_entrada.centro_custo_id = " . self::getCurrentCentroCusto()->id . "
), 0)");
}
])
->distinct()
->get()
->all();
$grupos = collect();
$prazo = ParametrizacaoService::getParametrizacaoRequisicao()['prazo_validade'];
foreach ($materiais as $material) {
$estoqueMaximo = null;
$permiteRequisitar = null;
if (!is_null($material->estoque_maximo)) {
$estoqueMaximo = (int) $material->estoque_maximo;
$permiteRequisitar = $material->estoque > $estoqueMaximo
? 0 : $estoqueMaximo - $material->estoque;
}
$material->permite_requisitar = $permiteRequisitar;
$material->quantidade = null;
$material->prazo_vencimento = $prazo === null ? false : !empty(self::getValidades($material->id, $prazo));
$grupo = $grupos->where('id', $material->grupo_id)->first();
if (is_null($grupo)) {
$grupo = (object) [
'id' => $material->grupo_id,
'nome' => $material->grupo_nome,
'materiais' => collect()
];
$grupos->push($grupo);
}
unset($material->grupo_id, $material->grupo_nome);
$grupo->materiais->push($material);
}
return $grupos;
}
public static function create()
{
return [
'additionals' => self::getAdditionalsData(),
'form' => self::getFormData(),
'model' => [
'possui_novo_envio' => false,
'tem_recebimento_parcial' => false,
'centro_custo_id' => null,
'numero' => ParametrizacaoService::getParametrizacaoRequisicao()['numero_requisicao_automatico']
? ParametrizacaoService::getNovoNumeroRequisicao() : null,
'itens' => [],
]
];
}
public static function store()
{
self::validateStore();
$requisicao = new Requisicao();
DB::transaction(function () use ($requisicao) {
$requisicao->fill(request()->all());
$requisicao->status_id = RequisicaoStatus::ABERTA;
$requisicao->save();
$requisicao->itens()->createMany(request()->itens);
});
return $requisicao->fresh();
}
public static function validateStore()
{
$rules = [
'centro_custo_id' => [
'required',
'integer',
Rule::exists(CentroCusto::class, 'id'),
],
'numero' => [
'required',
'digits_between:1,20',
Rule::unique(Requisicao::class, 'numero')
],
'itens' => [
'required',
'array',
],
'itens.*.material_id' => [
'required',
'integer',
Rule::exists(Material::class, 'id'),
],
'itens.*.quantidade' => [
'required',
'integer',
'min:1',
'max:99999999'
],
];
$messages = [
'numero.unique' => 'O número da requisição já foi inserido anteriormente.',
];
request()->validate($rules, $messages);
}
public static function edit($id)
{
$requisicao = Requisicao::findOrFail($id);
$envio = self::getPrimeiraRespostaEnviada($requisicao);
$ultimoRecebimento = $requisicao->respostas()
->where('status_id', RequisicaoRespostaStatus::RECEBIDA)
->orderByDesc('id')
->first();
$itens = $requisicao->itens;
if ($ultimoRecebimento) {
$itens = $itens->filter(function ($item) use ($ultimoRecebimento) {
$ultimoRecebimentoItem = $ultimoRecebimento->itens()
->where('requisicao_item_id', $item->id)
->first();
return !is_null($ultimoRecebimentoItem) && collect([
RequisicaoRespostaItemMotivo::ENTREGA_PARCIAL,
RequisicaoRespostaItemMotivo::PENDENTE_DE_ENTREGA,
])->contains($ultimoRecebimentoItem->motivo_id);
});
}
return [
'additionals' => self::getAdditionalsData(),
'form' => self::getFormData($requisicao),
'model' => [
'possui_novo_envio' => !is_null($envio),
'tem_recebimento_parcial' => is_null($envio) ? false : $envio->itens()
->whereIn('motivo_id', [
RequisicaoRespostaItemMotivo::ENTREGA_PARCIAL,
RequisicaoRespostaItemMotivo::PENDENTE_DE_ENTREGA,
])
->exists(),
'centro_custo_id' => $requisicao->centro_custo_id,
'numero' => ParametrizacaoService::getParametrizacaoRequisicao()['numero_requisicao_automatico']
? ParametrizacaoService::getNovoNumeroRequisicao() : null,
'itens' => $itens->map(function ($item) {
$data = [
'material' => [
'id' => $item->material->id,
'codigo' => $item->material->codigo_material,
'descricao_completa' => $item->material->descricao_completa,
],
];
$respostaItemEnviada = $item->respostaItens()
->whereHas('requisicaoResposta', function ($query) {
$query->where('status_id', RequisicaoRespostaStatus::ENVIADA);
})
->orderBy('id')
->first();
$respostaItensRecebidas = $item->respostaItens()
->whereHas('requisicaoResposta', function ($query) {
$query->where('status_id', RequisicaoRespostaStatus::RECEBIDA);
})
->get();
$data['possui_entrada_com_lote'] = is_null($respostaItemEnviada)
|| is_null($respostaItemEnviada->saidaItem) ? false
: $respostaItemEnviada->saidaItem->entradaItens()->whereNotNull('lote')->exists();
if (is_null($respostaItemEnviada)) {
if ($respostaItensRecebidas->isEmpty()) {
$data['quantidade'] = $item->quantidade;
}
else {
$data['recebeu_anteriormente'] = $respostaItensRecebidas->sum('quantidade_recebimento');
$data['restante_requisitado'] = $item->quantidade - $data['recebeu_anteriormente'];
}
}
else {
$data['resposta_item_id'] = $respostaItemEnviada->id;
if ($respostaItensRecebidas->isEmpty()) {
$data['requisitado'] = $item->quantidade;
}
else {
$data['recebeu_anteriormente'] = $respostaItensRecebidas->sum('quantidade_recebimento');
$data['restante_requisitado'] = $item->quantidade - $data['recebeu_anteriormente'];
}
if ($data['possui_entrada_com_lote']) {
$data['entrada_itens'] = $respostaItemEnviada->saidaItem
? $respostaItemEnviada->saidaItem->entradaItens->map(fn ($entradaItem) => [
'entrada_item_id' => $entradaItem->id,
'enviado' => $entradaItem->pivotSaidaItemEntradaItem->quantidade_saida,
'recebido' => $entradaItem->pivotSaidaItemEntradaItem->quantidade_saida,
'lote' => $entradaItem->lote,
'validade_lote' => $entradaItem->validade_lote
? $entradaItem->validade_lote->format('d/m/Y') : null,
'possui_lote' => !is_null($entradaItem->lote),
]) : [];
}
else {
$data['enviado'] = $respostaItemEnviada->saidaItem
? $respostaItemEnviada->saidaItem->quantidade : 0;
$data['recebido'] = $data['enviado'];
}
}
return $data;
})->values()
]
];
}
private static function getPrimeiraRespostaEnviada($requisicao)
{
return $requisicao->respostas()
->where('status_id', RequisicaoRespostaStatus::ENVIADA)
->orderBy('id')
->first();
}
private static function getAdditionalsData()
{
$parametrizacaoRequisicao = ParametrizacaoService::getParametrizacaoRequisicao();
return [
'is_numero_requisicao_automatico' => $parametrizacaoRequisicao['numero_requisicao_automatico'],
'permite_requisitar_materiais_sem_estoque' => $parametrizacaoRequisicao['permite_requisitar_materiais_sem_estoque'],
];
}
private static function getFormData($requisicao = null)
{
$centroCustoLogadoId = self::getCurrentCentroCusto()->id;
$recebimentos = [];
if ($requisicao) {
$recebimentos = $requisicao->respostas()
->whereNotNull('recebida_em')
->orderBy('recebida_em')
->get();
$recebido = [];
$recebimentos = $recebimentos->map(function ($resposta, $i) use (&$recebido) {
$numeroRecebimento = $i + 1;
$itens = $resposta->itens->map(function ($respostaItem) use ($numeroRecebimento, &$recebido) {
$material = $respostaItem->requisicaoItem->material;
if (!isset($recebido[$material->id])) {
$recebido[$material->id] = 0;
}
$item = [
'material' => [
'codigo' => $material->codigo_material,
'descricao_completa' => $material->descricao_completa,
],
];
if ($numeroRecebimento === 1) {
$item['requisitado'] = $respostaItem->requisicaoItem->quantidade;
}
else {
$item['recebeu_anteriormente'] = $recebido[$material->id];
$item['restante_requisitado'] = $respostaItem->requisicaoItem->quantidade - $recebido[$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(function ($entradaItem) use ($respostaItem) {
$recebimento = $respostaItem->recebimentos()
->where('entrada_item_origem_id', $entradaItem->id)
->first();
$loteDiferente = $recebimento->lote !== $entradaItem->lote;
$validadeLoteDiferente = !is_null($recebimento->validade_lote)
&& !is_null($entradaItem->validade_lote)
? $recebimento->validade_lote->format('d/m/Y')
!== $entradaItem->validade_lote->format('d/m/Y')
: false;
return [
'enviado' => $entradaItem->pivotSaidaItemEntradaItem->quantidade_saida,
'recebido' => $recebimento->quantidade,
'lote' => $loteDiferente
? "{$entradaItem->lote} (Enviado) | {$recebimento->lote} (Recebido)"
: $recebimento->lote,
'validade_lote' => $entradaItem->validade_lote ? ($validadeLoteDiferente
? "{$entradaItem->validade_lote->format('d/m/Y')} (Enviado) | "
. "{$recebimento->validade_lote->format('d/m/Y')} (Recebido)"
: $recebimento->validade_lote->format('d/m/Y')) : null,
];
})
: [];
$recebido[$material->id] += collect($item['entrada_itens'])->sum('recebido');
}
else {
$item['enviado'] = $respostaItem->saidaItem ? $respostaItem->saidaItem->quantidade : 0;
$item['recebido'] = $respostaItem->quantidade_recebimento;
$recebido[$material->id] += $item['recebido'];
}
return $item;
});
return [
'numero_recebimento' => $numeroRecebimento,
'data_hora' => $resposta->recebida_em->format('d/m/Y H:i'),
'itens' => $itens,
];
});
}
return [
'unidades' => Unidade::orderBy('nome_fantasia')
->whereHas('infraestruturas', function ($query) use ($centroCustoLogadoId) {
$query->whereHas('centrosCusto', function ($query) use ($centroCustoLogadoId) {
$query
->where('id', '<>', $centroCustoLogadoId)
->whereHas('almoxarifadoRequisicaoPermissoesAlmoxarifado',
function ($query) use ($centroCustoLogadoId) {
$query->where('centro_custo_requisitante_id', $centroCustoLogadoId);
});
});
})
->get()
->map(fn ($unidade) => [
'id' => $unidade->id,
'nome_fantasia' => $unidade->nome_fantasia,
'infraestruturas' => $unidade->infraestruturas()
->whereHas('centrosCusto', function ($query) use ($centroCustoLogadoId) {
$query
->where('id', '<>', $centroCustoLogadoId)
->whereHas('almoxarifadoRequisicaoPermissoesAlmoxarifado',
function ($query) use ($centroCustoLogadoId) {
$query->where('centro_custo_requisitante_id', $centroCustoLogadoId);
});
})
->get()
->sortBy('nome')
->map(fn ($infraestrutura) => [
'id' => $infraestrutura->id,
'nome' => $infraestrutura->nome,
'centros_custo' => $infraestrutura->centrosCusto()
->where('id', '<>', $centroCustoLogadoId)
->whereHas('almoxarifadoRequisicaoPermissoesAlmoxarifado',
function ($query) use ($centroCustoLogadoId) {
$query->where('centro_custo_requisitante_id', $centroCustoLogadoId);
})
->get()
->map(fn ($centroCusto) => [
'id' => $centroCusto->id,
'setor_nome' => $centroCusto->setor->nome,
])
->sortBy('setor_nome')
->values()
])
->values()
]),
'modos' => [
['value' => 'padrao', 'text' => 'PADRÃO'],
['value' => 'sequencial', 'text' => 'SEQUENCIAL'],
],
'modo_value' => 'padrao',
'unidade_id' => $requisicao ? $requisicao->centroCusto->infraestrutura->unidade_id : null,
'infraestrutura_id' => $requisicao ? $requisicao->centroCusto->infraestrutura->id : null,
'usuario_requisitante_nome' => $requisicao ? $requisicao->createdLotacao->usuario->cidadao->nome : null,
'recebimentos' => collect($recebimentos)->sortByDesc('numero_recebimento')->values(),
];
}
public static function update($id)
{
self::validateUpdate();
$requisicao = Requisicao::findOrFail($id);
DB::transaction(function () use ($requisicao) {
$respostaItem = null;
$entradaItensData = collect();
$finalizouEntrega = true;
$motivosDeEntregaNaoFinalizada = collect([
RequisicaoRespostaItemMotivo::ENTREGA_PARCIAL,
RequisicaoRespostaItemMotivo::PENDENTE_DE_ENTREGA
]);
foreach (request()->itens as $item) {
$respostaItem = RequisicaoRespostaItem::findOrFail($item['resposta_item_id']);
$material = $respostaItem->requisicaoItem->material;
$controlaEstoque = ParametrizacaoService::controlaEstoque($material->id);
$possuiEntradaComLote = false;
if (isset($item['entrada_itens'])) {
collect($item['entrada_itens'])->each(function ($entradaItem) use (&$possuiEntradaComLote) {
if (!is_null(EntradaItem::findOrFail($entradaItem['entrada_item_id'])->lote)) {
$possuiEntradaComLote = true;
return false;
}
});
}
if ($possuiEntradaComLote) {
$entradaItens = collect();
foreach ($item['entrada_itens'] as $entradaItemData) {
$data = [
'entrada_item_origem_id' => $entradaItemData['entrada_item_id'],
'lote' => $entradaItemData['lote'],
'validade_lote' => $entradaItemData['validade_lote']
? Carbon::createFromFormat('d/m/Y', $entradaItemData['validade_lote'])
: null,
'quantidade' => $entradaItemData['recebido'],
'controlava_estoque' => $controlaEstoque,
];
$respostaItem->recebimentos()->create($data);
if ($entradaItemData['recebido'] > 0) {
$entradaItens->push($data);
}
}
if ($entradaItens->isNotEmpty() && $controlaEstoque) {
$entradaItensData->push([
'saida_item_id' => $respostaItem->saida_item_id,
'possui_entrada_com_lote' => $possuiEntradaComLote,
'entrada_itens' => $entradaItens,
]);
}
}
else {
$data = [
'saida_item_id' => $respostaItem->saida_item_id,
'possui_entrada_com_lote' => $possuiEntradaComLote,
'quantidade' => $item['recebido'],
'controlava_estoque' => $controlaEstoque,
];
$respostaItem->recebimentos()->create($data);
if ($item['recebido'] > 0 && $controlaEstoque) {
$entradaItensData->push($data);
}
}
if ($motivosDeEntregaNaoFinalizada->contains($respostaItem->motivo_id)) {
$finalizouEntrega = false;
}
}
if ($entradaItensData->isNotEmpty()) {
$entradasItensSaved = AlmoxarifadoService::saveEntradasDeRequisicao($entradaItensData);
$entradasItensSaved->each(function ($entradaItem) {
RequisicaoRespostaItem::firstWhere('saida_item_id', $entradaItem['saida_item_id'])
->entradaItens()
->attach($entradaItem['entrada_item_id']);
});
}
$respostaItem->requisicaoResposta()->update([
'status_id' => RequisicaoRespostaStatus::RECEBIDA,
'recebida_em' => Carbon::now(),
]);
if ($finalizouEntrega) {
$requisicao->update(['status_id' => RequisicaoStatus::FINALIZADA]);
}
});
$requisicao->refresh();
$requisicao->possui_novo_envio = !is_null(self::getPrimeiraRespostaEnviada($requisicao));
return $requisicao;
}
public static function validateUpdate()
{
$rules = [
'itens' => [
'required',
'array',
],
'itens.*.resposta_item_id' => [
'required',
'integer',
Rule::exists(RequisicaoRespostaItem::class, 'id'),
],
'itens.*.recebido' => [
'integer',
],
'itens.*.entrada_itens' => [
'array',
],
'itens.*.entrada_itens.*.entrada_item_id' => [
'required',
'integer',
Rule::exists(EntradaItem::class, 'id'),
],
'itens.*.entrada_itens.*.recebido' => [
'required',
'integer',
],
'itens.*.entrada_itens.*.possui_lote' => [
'required',
'boolean',
],
'itens.*.entrada_itens.*.lote' => [
'required_if:itens.*.entrada_itens.*.possui_lote,true',
'nullable',
'string',
'max:15',
],
'itens.*.entrada_itens.*.validade_lote' => [
'required_if:itens.*.entrada_itens.*.possui_lote,true',
'nullable',
'date_format:d/m/Y',
],
];
$messages = [];
request()->validate($rules, $messages);
}
public static function destroy($id)
{
Requisicao::findOrFail($id)->delete();
return null;
}
}