924 lines
39 KiB
PHP
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;
|
|
}
|
|
}
|