473 lines
17 KiB
PHP
473 lines
17 KiB
PHP
<?php
|
|
|
|
namespace App\Services\Almoxarifado;
|
|
|
|
use App\Enums\Almoxarifado\SaidaTipo;
|
|
use App\Exceptions\Almoxarifado\TransferenciaRespondidaPeloDestinoException;
|
|
use App\Models\Almoxarifado\EntradaItem;
|
|
use App\Models\Almoxarifado\Saida;
|
|
use App\Models\Almoxarifado\SaidaItem;
|
|
use App\Models\Almoxarifado\BalanceteFechamento;
|
|
use App\Models\Cadastro\Estabelecimento\CentroCusto;
|
|
use App\Models\Cadastro\Estabelecimento\Unidade;
|
|
use App\Models\Cadastro\Material\Material;
|
|
use App\Models\Cadastro\SujeitoAtencao\Usuario;
|
|
use App\Services\Service;
|
|
use Carbon\Carbon;
|
|
use Illuminate\Support\Facades\DB;
|
|
use Illuminate\Support\Str;
|
|
use Illuminate\Validation\Rule;
|
|
|
|
class TransferenciaService extends Service
|
|
{
|
|
public static function datatableEnviadas()
|
|
{
|
|
$saidas = DB::table('almoxarifado_saida')
|
|
->join(
|
|
'almoxarifado_saida_transferencia',
|
|
'almoxarifado_saida_transferencia.saida_id',
|
|
'almoxarifado_saida.id'
|
|
)
|
|
->join(
|
|
'cadastro_centro_custo',
|
|
'cadastro_centro_custo.id',
|
|
'almoxarifado_saida_transferencia.centro_custo_id'
|
|
)
|
|
->join(
|
|
'cadastro_setor',
|
|
'cadastro_setor.id',
|
|
'cadastro_centro_custo.setor_id'
|
|
)
|
|
->join(
|
|
'cadastro_infraestrutura',
|
|
'cadastro_infraestrutura.id',
|
|
'cadastro_centro_custo.infraestrutura_id'
|
|
)
|
|
->join(
|
|
'cadastro_unidade',
|
|
'cadastro_unidade.id',
|
|
'cadastro_infraestrutura.unidade_id'
|
|
)
|
|
->join(
|
|
'cadastro_usuario',
|
|
'cadastro_usuario.id',
|
|
'almoxarifado_saida_transferencia.usuario_id'
|
|
)
|
|
->join(
|
|
'cadastro_cidadao',
|
|
'cadastro_cidadao.id',
|
|
'cadastro_usuario.cidadao_id'
|
|
)
|
|
->select(
|
|
'almoxarifado_saida.id',
|
|
DB::raw("cadastro_unidade.nome_fantasia AS unidade_nome_fantasia"),
|
|
DB::raw("COALESCE(cadastro_infraestrutura.nome, cadastro_unidade.nome_fantasia) AS infraestrutura_nome"),
|
|
'cadastro_setor.nome as setor_nome',
|
|
'cadastro_cidadao.nome AS usuario_nome',
|
|
DB::raw("DATE_FORMAT(almoxarifado_saida.created_at, '%d/%m/%Y') as data_transferencia"),
|
|
'almoxarifado_saida.finalizada',
|
|
'almoxarifado_saida_transferencia.confirmado',
|
|
'almoxarifado_saida_transferencia.recusado'
|
|
)
|
|
->where('almoxarifado_saida.tipo_id', SaidaTipo::TRANSFERENCIA)
|
|
->where('almoxarifado_saida.centro_custo_id', self::getCurrentCentroCusto()->id);
|
|
|
|
return datatables()
|
|
->of($saidas)
|
|
->filterColumn('almoxarifado_saida.created_at', function ($query, $keyword) {
|
|
|
|
$query->whereRaw("DATE_FORMAT(almoxarifado_saida.created_at, '%d/%m/%Y') like ?", ["%{$keyword}%"])
|
|
->orWhereRaw(
|
|
"CONCAT(
|
|
SUBSTR(almoxarifado_saida.created_at,9,2),
|
|
SUBSTR(almoxarifado_saida.created_at,6,2),
|
|
SUBSTR(almoxarifado_saida.created_at,1,4)
|
|
) like ?",
|
|
["%{$keyword}%"]
|
|
);
|
|
})
|
|
->filterColumn('cadastro_infraestrutura.nome', function ($query, $keyword) {
|
|
|
|
$query->whereRaw("COALESCE(cadastro_infraestrutura.nome, cadastro_unidade.nome_fantasia) like ?", ["%{$keyword}%"]);
|
|
})
|
|
->filterColumn('almoxarifado_saida.finalizada', function ($query, $keyword) {
|
|
|
|
$query->whereRaw("IF(almoxarifado_saida.finalizada = 1, 'SIM', 'NÃO') = ?", [Str::upper($keyword)]);
|
|
})
|
|
->skipTotalRecords()
|
|
->toJson();
|
|
}
|
|
|
|
public static function datatableRecebidas()
|
|
{
|
|
$saidas = DB::table('almoxarifado_saida')
|
|
->join(
|
|
'almoxarifado_saida_transferencia',
|
|
'almoxarifado_saida_transferencia.saida_id',
|
|
'almoxarifado_saida.id'
|
|
)
|
|
->join(
|
|
'cadastro_centro_custo',
|
|
'cadastro_centro_custo.id',
|
|
'almoxarifado_saida.centro_custo_id'
|
|
)
|
|
->join(
|
|
'cadastro_setor',
|
|
'cadastro_setor.id',
|
|
'cadastro_centro_custo.setor_id'
|
|
)
|
|
->join(
|
|
'cadastro_infraestrutura',
|
|
'cadastro_infraestrutura.id',
|
|
'cadastro_centro_custo.infraestrutura_id'
|
|
)
|
|
->join(
|
|
'cadastro_unidade',
|
|
'cadastro_unidade.id',
|
|
'cadastro_infraestrutura.unidade_id'
|
|
)
|
|
->join(
|
|
'cadastro_usuario',
|
|
'cadastro_usuario.id',
|
|
'almoxarifado_saida_transferencia.usuario_id'
|
|
)
|
|
->join(
|
|
'cadastro_cidadao',
|
|
'cadastro_cidadao.id',
|
|
'cadastro_usuario.cidadao_id'
|
|
)
|
|
->select(
|
|
'almoxarifado_saida.id',
|
|
DB::raw("cadastro_unidade.nome_fantasia AS unidade_nome_fantasia"),
|
|
DB::raw("COALESCE(cadastro_infraestrutura.nome, cadastro_unidade.nome_fantasia) AS infraestrutura_nome"),
|
|
'cadastro_setor.nome as setor_nome',
|
|
'cadastro_cidadao.nome AS usuario_nome',
|
|
DB::raw("DATE_FORMAT(almoxarifado_saida.created_at, '%d/%m/%Y') as data_transferencia"),
|
|
'almoxarifado_saida_transferencia.confirmado',
|
|
'almoxarifado_saida_transferencia.recusado'
|
|
)
|
|
->where('almoxarifado_saida.tipo_id', SaidaTipo::TRANSFERENCIA)
|
|
->where('almoxarifado_saida.finalizada', true)
|
|
->where('almoxarifado_saida_transferencia.centro_custo_id', self::getCurrentCentroCusto()->id);
|
|
|
|
return datatables()
|
|
->of($saidas)
|
|
->filterColumn('almoxarifado_saida.created_at', function ($query, $keyword) {
|
|
|
|
$query->whereRaw("DATE_FORMAT(almoxarifado_saida.created_at, '%d/%m/%Y') like ?", ["%{$keyword}%"])
|
|
->orWhereRaw(
|
|
"CONCAT(
|
|
SUBSTR(almoxarifado_saida.created_at,9,2),
|
|
SUBSTR(almoxarifado_saida.created_at,6,2),
|
|
SUBSTR(almoxarifado_saida.created_at,1,4)
|
|
) like ?",
|
|
["%{$keyword}%"]
|
|
);
|
|
})
|
|
->filterColumn('cadastro_infraestrutura.nome', function ($query, $keyword) {
|
|
|
|
$query->whereRaw("COALESCE(cadastro_infraestrutura.nome, cadastro_unidade.nome_fantasia) like ?", ["%{$keyword}%"]);
|
|
})
|
|
->skipTotalRecords()
|
|
->toJson();
|
|
}
|
|
|
|
public static function create()
|
|
{
|
|
return [
|
|
'form' => self::getFormData(),
|
|
'model' => [
|
|
'finalizada' => false,
|
|
'confirmado' => false,
|
|
'recusado' => false,
|
|
'destino' => [
|
|
'centro_custo_id' => null,
|
|
'usuario' => null,
|
|
],
|
|
'itens' => [],
|
|
'ultimo_balancete_fechado' => [BalanceteFechamento::Latest()
|
|
->select('mes', 'ano')
|
|
->first() ?? null, Carbon::now()]
|
|
]
|
|
];
|
|
}
|
|
|
|
public static function store()
|
|
{
|
|
self::validate();
|
|
|
|
$saida = null;
|
|
|
|
DB::transaction(function () use (&$saida) {
|
|
|
|
$saida = AlmoxarifadoService::saveTransferencia(self::getParams());
|
|
});
|
|
|
|
return $saida;
|
|
}
|
|
|
|
public static function edit($id)
|
|
{
|
|
$saida = Saida::findOrFail($id);
|
|
|
|
return [
|
|
'form' => self::getFormData($saida),
|
|
'model' => [
|
|
'finalizada' => $saida->finalizada,
|
|
'confirmado' => $saida->transferencia->confirmado,
|
|
'recusado' => $saida->transferencia->recusado,
|
|
'destino' => [
|
|
'centro_custo_id' => $saida->transferencia->centroCusto->id,
|
|
'usuario' => [
|
|
'id' => $saida->transferencia->usuario->id,
|
|
'cidadao_nome' => $saida->transferencia->usuario->cidadao->nome,
|
|
],
|
|
],
|
|
'itens' => $saida->itens->map(fn ($item) => [
|
|
'id' => $item->id,
|
|
'material' => [
|
|
'id' => $item->material->id,
|
|
'codigo_material' => $item->material->codigo_material,
|
|
'descricao_completa' => $item->material->descricao_completa,
|
|
],
|
|
'quantidade' => $item->quantidade,
|
|
'estorno_salvo' => $item->estornado,
|
|
'estornado' => $item->estornado,
|
|
'entrada_itens' => $item->entradaItens->map(fn ($entradaItem) => [
|
|
'entrada_item_id' => $entradaItem->id,
|
|
'quantidade_saida' => $entradaItem->pivotSaidaItemEntradaItem->quantidade_saida,
|
|
'lote' => $entradaItem->lote,
|
|
'validade_lote' => $entradaItem->validade_lote,
|
|
]),
|
|
'escolheu_entrada_item_manualmente' => $item->escolheu_entrada_item_manualmente,
|
|
]),
|
|
'ultimo_balancete_fechado' => [BalanceteFechamento::Latest()
|
|
->select('mes', 'ano')
|
|
->first() ?? null, Carbon::now()]
|
|
]
|
|
];
|
|
}
|
|
|
|
private static function getFormData($saida = null)
|
|
{
|
|
$centroCustoLogadoId = self::getCurrentCentroCusto()->id;
|
|
|
|
return [
|
|
'destino' => [
|
|
'unidades' => Unidade::orderBy('nome_fantasia')
|
|
->whereHas('infraestruturas', function ($query) use ($centroCustoLogadoId) {
|
|
|
|
$query->whereHas('centrosCusto', function ($query) use ($centroCustoLogadoId) {
|
|
|
|
$query->where('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);
|
|
})
|
|
->get()
|
|
->sortBy('nome')
|
|
->map(fn ($infraestrutura) => [
|
|
'id' => $infraestrutura->id,
|
|
'nome' => $infraestrutura->nome,
|
|
'centros_custo' => $infraestrutura->centrosCusto()
|
|
->where('id', '<>', $centroCustoLogadoId)
|
|
->get()
|
|
->map(fn ($centroCusto) => [
|
|
'id' => $centroCusto->id,
|
|
'setor_nome' => $centroCusto->setor->nome,
|
|
])
|
|
->sortBy('setor_nome')
|
|
->values()
|
|
])
|
|
->values()
|
|
]),
|
|
'unidade_id' => $saida ? $saida->transferencia->centroCusto->infraestrutura->unidade_id : null,
|
|
'infraestrutura_id' => $saida ? $saida->transferencia->centroCusto->infraestrutura->id : null,
|
|
]
|
|
];
|
|
}
|
|
|
|
public static function update($id)
|
|
{
|
|
self::validate();
|
|
|
|
$saida = Saida::findOrFail($id);
|
|
|
|
if ($saida->transferencia->confirmado || $saida->transferencia->recusado) {
|
|
|
|
throw new TransferenciaRespondidaPeloDestinoException();
|
|
}
|
|
|
|
DB::transaction(function () use (&$saida) {
|
|
|
|
$saida = AlmoxarifadoService::saveTransferencia(self::getParams(), $saida->id);
|
|
});
|
|
|
|
return $saida;
|
|
}
|
|
|
|
private static function getParams()
|
|
{
|
|
return [
|
|
'finalizada' => request()->finalizada,
|
|
'destino' => [
|
|
'centro_custo_id' => request()->destino['centro_custo_id'],
|
|
'usuario_id' => request()->destino['usuario_id'],
|
|
],
|
|
'itens' => collect(request()->itens)->map(fn ($item) => [
|
|
'id' => $item['id'],
|
|
'material_id' => $item['material_id'],
|
|
'quantidade' => (int) $item['quantidade'],
|
|
'estornado' => $item['estornado'],
|
|
'entrada_itens' => collect($item['entrada_itens'])->map(fn ($entradaItem) => [
|
|
'entrada_item_id' => $entradaItem['entrada_item_id'],
|
|
'quantidade_saida' => (int) $entradaItem['quantidade_saida'],
|
|
]),
|
|
'escolheu_entrada_item_manualmente' => $item['escolheu_entrada_item_manualmente'],
|
|
])
|
|
];
|
|
}
|
|
|
|
public static function validate()
|
|
{
|
|
$rules = [
|
|
'finalizada' => [
|
|
'required',
|
|
'boolean',
|
|
],
|
|
'destino.centro_custo_id' => [
|
|
'required',
|
|
'integer',
|
|
Rule::exists(CentroCusto::class, 'id'),
|
|
],
|
|
'destino.usuario_id' => [
|
|
'required',
|
|
'integer',
|
|
Rule::exists(Usuario::class, 'id'),
|
|
],
|
|
'itens' => [
|
|
'required',
|
|
'array',
|
|
],
|
|
'itens.*.id' => [
|
|
'nullable',
|
|
'integer',
|
|
Rule::exists(SaidaItem::class, 'id'),
|
|
],
|
|
'itens.*.material_id' => [
|
|
'required',
|
|
'integer',
|
|
Rule::exists(Material::class, 'id'),
|
|
],
|
|
'itens.*.quantidade' => [
|
|
'required',
|
|
'integer',
|
|
'min:1',
|
|
],
|
|
'itens.*.escolheu_entrada_item_manualmente' => [
|
|
'required',
|
|
'boolean',
|
|
],
|
|
'itens.*.estornado' => [
|
|
'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',
|
|
],
|
|
];
|
|
|
|
$messages = [];
|
|
|
|
request()->validate($rules, $messages);
|
|
}
|
|
|
|
public static function destroy($id)
|
|
{
|
|
$saida = Saida::findOrFail($id);
|
|
|
|
DB::transaction(function () use ($saida) {
|
|
|
|
$saida->itens->each(fn ($i) => $i->entradaItens()->detach());
|
|
$saida->delete();
|
|
});
|
|
|
|
return null;
|
|
}
|
|
|
|
public static function getTransferenciaRecebida($id)
|
|
{
|
|
$saida = Saida::findOrFail($id);
|
|
|
|
return [
|
|
'origem' => [
|
|
'unidade_nome_fantasia' => $saida->centroCusto->infraestrutura->unidade->nome_fantasia,
|
|
'infraestrutura_nome' => $saida->centroCusto->infraestrutura->nome,
|
|
'setor_nome' => $saida->centroCusto->setor->nome,
|
|
],
|
|
'itens' => $saida->transferencia->recusado
|
|
? $saida->itensRecusadosTransferencia->map(fn ($item) => [
|
|
'material_descricao' => $item->saidaItem->material->descricao_completa,
|
|
'quantidade' => $item->saidaItem->quantidade,
|
|
])
|
|
: $saida->itens->filter(fn ($i) => !$i->estornado)->map(fn ($item) => [
|
|
'material_descricao' => $item->material->descricao_completa,
|
|
'quantidade' => $item->quantidade,
|
|
])->values()
|
|
];
|
|
}
|
|
|
|
public static function accept($id)
|
|
{
|
|
$saida = Saida::findOrFail($id);
|
|
|
|
DB::transaction(function () use ($saida) {
|
|
|
|
AlmoxarifadoService::saveEntradasDeTransferencia($saida);
|
|
|
|
$saida->transferencia->confirmado = true;
|
|
$saida->transferencia->save();
|
|
});
|
|
}
|
|
|
|
public static function reject($id)
|
|
{
|
|
$saida = Saida::findOrFail($id);
|
|
|
|
DB::transaction(function () use ($saida) {
|
|
|
|
$itensNaoEstornados = collect();
|
|
|
|
$saida->itens->filter(fn ($i) => !$i->estornado)->each(function ($item) use ($saida, $itensNaoEstornados) {
|
|
|
|
$saida->itensRecusadosTransferencia()->create(['saida_item_id' => $item->id]);
|
|
|
|
$itensNaoEstornados->push(['id' => $item->id]);
|
|
});
|
|
|
|
AlmoxarifadoService::saveEstornoDeTransferencia($itensNaoEstornados);
|
|
|
|
$saida->transferencia->recusado = true;
|
|
$saida->transferencia->save();
|
|
});
|
|
}
|
|
}
|