Files
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

368 lines
14 KiB
PHP

<?php
namespace App\Services\Almoxarifado;
use App\Enums\Almoxarifado\SaidaTipo;
use App\Models\Almoxarifado\EntradaItem;
use App\Models\Almoxarifado\Saida;
use App\Models\Almoxarifado\SaidaItem;
use App\Models\Almoxarifado\SaidaRequisicao;
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\Models\Almoxarifado\BalanceteFechamento;
use App\Services\Service;
use Carbon\Carbon;
use Illuminate\Support\Facades\DB;
use Illuminate\Validation\Rule;
class SaidaService extends Service
{
public static function datatable()
{
$saidas = DB::table('almoxarifado_saida')
->join(
'almoxarifado_saida_requisicao',
'almoxarifado_saida_requisicao.saida_id',
'almoxarifado_saida.id'
)
->join(
'cadastro_centro_custo',
'cadastro_centro_custo.id',
'almoxarifado_saida_requisicao.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_requisicao.usuario_id'
)
->join(
'cadastro_cidadao',
'cadastro_cidadao.id',
'cadastro_usuario.cidadao_id'
)
->select(
'almoxarifado_saida.id',
DB::raw("DATE_FORMAT(almoxarifado_saida_requisicao.data, '%d/%m/%Y') as data_requisicao"),
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',
'almoxarifado_saida_requisicao.numero',
DB::raw("DATE_FORMAT(almoxarifado_saida.created_at, '%d/%m/%Y') as data_saida"),
'almoxarifado_saida.finalizada',
)
->where('almoxarifado_saida.tipo_id', SaidaTipo::MANUAL)
->where('almoxarifado_saida.centro_custo_id', self::getCurrentCentroCusto()->id);
return datatables()
->of($saidas)
->filterColumn('almoxarifado_saida_requisicao.data', function ($query, $keyword) {
$query->whereRaw("DATE_FORMAT(almoxarifado_saida_requisicao.data, '%d/%m/%Y') like ?", ["%{$keyword}%"])
->orWhereRaw(
"CONCAT(
SUBSTR(almoxarifado_saida_requisicao.data,9,2),
SUBSTR(almoxarifado_saida_requisicao.data,6,2),
SUBSTR(almoxarifado_saida_requisicao.data,1,4)
) like ?",
["%{$keyword}%"]
);
})
->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 [
'additionals' => self::getAdditionalsData(),
'form' => self::getFormData(),
'model' => [
'finalizada' => false,
'requisicao' => [
'centro_custo_id' => null,
'usuario' => null,
'numero' => ParametrizacaoService::getParametrizacaoRequisicao()['numero_requisicao_automatico']
? ParametrizacaoService::getNovoNumeroRequisicao() : null,
'data' => null,
],
'itens' => [],
]
];
}
public static function store()
{
self::validate();
$saida = null;
DB::transaction(function () use (&$saida) {
$saida = AlmoxarifadoService::saveSaidaManual(self::getParams());
});
return $saida;
}
public static function edit($id)
{
$saida = Saida::findOrFail($id);
return [
'additionals' => self::getAdditionalsData(),
'form' => self::getFormData($saida),
'model' => [
'finalizada' => $saida->finalizada,
'requisicao' => [
'centro_custo_id' => $saida->requisicao->centroCusto->id,
'usuario' => [
'id' => $saida->requisicao->usuario->id,
'cidadao_nome' => $saida->requisicao->usuario->cidadao->nome,
],
'numero' => $saida->requisicao->numero,
'data' => $saida->requisicao->data->format('d/m/Y'),
],
'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,
])
]
];
}
private static function getFormData($saida = null)
{
$centroCustoLogadoId = self::getCurrentCentroCusto()->id;
return [
'requisicao' => [
'unidades' => Unidade::orderBy('nome_fantasia')
->whereHas('infraestruturas', function ($query) use ($centroCustoLogadoId) {
$query->whereHas('centrosCusto', function ($query) use ($centroCustoLogadoId) {
$query->where('id', '<>', $centroCustoLogadoId)
->whereDoesntHave('almoxarifadoParametrizacoesControleEstoqueGrupo');
});
})
->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)
->whereDoesntHave('almoxarifadoParametrizacoesControleEstoqueGrupo');
})
->get()
->sortBy('nome')
->map(fn ($infraestrutura) => [
'id' => $infraestrutura->id,
'nome' => $infraestrutura->nome,
'centros_custo' => $infraestrutura->centrosCusto()
->where('id', '<>', $centroCustoLogadoId)
->whereDoesntHave('almoxarifadoParametrizacoesControleEstoqueGrupo')
->get()
->map(fn ($centroCusto) => [
'id' => $centroCusto->id,
'setor_nome' => $centroCusto->setor->nome,
])
->sortBy('setor_nome')
->values()
])
->values()
]),
'unidade_id' => $saida ? $saida->requisicao->centroCusto->infraestrutura->unidade_id : null,
'infraestrutura_id' => $saida ? $saida->requisicao->centroCusto->infraestrutura->id : null,
'balancete_lastest' => BalanceteFechamento::select('id','mes','ano')->orderBy('id','desc')->first() ?? null,
]
];
}
private static function getAdditionalsData()
{
return [
'data_atual' => Carbon::now()->format('d/m/Y'),
'is_numero_requisicao_automatico' => ParametrizacaoService::getParametrizacaoRequisicao()
['numero_requisicao_automatico'],
];
}
public static function update($id)
{
self::validate();
$saida = Saida::findOrFail($id);
DB::transaction(function () use (&$saida) {
$saida = AlmoxarifadoService::saveSaidaManual(self::getParams(), $saida->id);
});
return $saida;
}
private static function getParams()
{
return [
'finalizada' => request()->finalizada,
'requisicao' => [
'centro_custo_id' => request()->requisicao['centro_custo_id'],
'usuario_id' => request()->requisicao['usuario_id'],
'numero' => request()->requisicao['numero'],
'data' => Carbon::createFromFormat('d/m/Y', request()->requisicao['data']),
],
'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',
],
'requisicao.centro_custo_id' => [
'required',
'integer',
Rule::exists(CentroCusto::class, 'id'),
],
'requisicao.usuario_id' => [
'required',
'integer',
Rule::exists(Usuario::class, 'id'),
],
'requisicao.numero' => [
'required',
'digits_between:1,20',
Rule::unique(SaidaRequisicao::class, 'numero')->ignore(request()->route('saida'), 'saida_id'),
],
'requisicao.data' => [
'required',
'date_format:d/m/Y',
'before_or_equal:now',
],
'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 = [
'requisicao.numero.unique' => 'O número da requisição já foi inserido anteriormente.',
];
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;
}
}