Files
rkm-conectasus-ci-sandbox/api/app/Services/Almoxarifado/EntradaService.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

432 lines
16 KiB
PHP

<?php
namespace App\Services\Almoxarifado;
use App\Enums\Almoxarifado\DocumentoTipo as AlmoxarifadoDocumentoTipo;
use App\Enums\Almoxarifado\EntradaTipo;
use App\Models\Almoxarifado\DocumentoTipo;
use App\Models\Almoxarifado\Entrada;
use App\Models\Almoxarifado\EntradaItem;
use App\Models\Cadastro\Fabricante\Fabricante;
use App\Models\Cadastro\Fornecedor\Fornecedor;
use App\Models\Cadastro\Material\Material;
use App\Models\Cadastro\OrigemProgramatica;
use App\Services\Service;
use App\Utils\MaskUtil;
use Carbon\Carbon;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;
use Illuminate\Validation\Rule;
class EntradaService extends Service
{
public static function datatable()
{
$entradas = DB::table('almoxarifado_entrada')
->join(
'almoxarifado_entrada_documento',
'almoxarifado_entrada_documento.entrada_id',
'almoxarifado_entrada.id'
)
->join(
'almoxarifado_documento_tipo',
'almoxarifado_documento_tipo.id',
'almoxarifado_entrada_documento.tipo_id'
)
->join(
'cadastro_fornecedor',
'cadastro_fornecedor.id',
'almoxarifado_entrada_documento.fornecedor_id'
)
->leftJoin(
'cadastro_origem_programatica',
'cadastro_origem_programatica.id',
'almoxarifado_entrada_documento.origem_programatica_id'
)
->select(
'almoxarifado_entrada.id',
DB::raw("DATE_FORMAT(almoxarifado_entrada_documento.data, '%d/%m/%Y') as data_documento"),
'cadastro_fornecedor.nome_fantasia AS fornecedor_nome_fantasia',
'cadastro_origem_programatica.nome AS origem_programatica_nome',
'almoxarifado_entrada_documento.numero',
'almoxarifado_entrada_documento.numero_pedido',
DB::raw("(
SELECT SUM(item.valor_total)
FROM almoxarifado_entrada_item item
WHERE item.entrada_id = almoxarifado_entrada.id
) AS valor"),
'almoxarifado_documento_tipo.nome AS tipo_nome',
DB::raw("DATE_FORMAT(almoxarifado_entrada.created_at, '%d/%m/%Y') as data_entrada"),
'almoxarifado_entrada.finalizada',
)
->where('almoxarifado_entrada.tipo_id', EntradaTipo::MANUAL)
->where('almoxarifado_entrada.centro_custo_id', self::getCurrentCentroCusto()->id);
return datatables()
->of($entradas)
->filterColumn('almoxarifado_entrada_documento.data', function ($query, $keyword) {
$query->whereRaw("DATE_FORMAT(almoxarifado_entrada_documento.data, '%d/%m/%Y') like ?", ["%{$keyword}%"])
->orWhereRaw(
"CONCAT(
SUBSTR(almoxarifado_entrada_documento.data,9,2),
SUBSTR(almoxarifado_entrada_documento.data,6,2),
SUBSTR(almoxarifado_entrada_documento.data,1,4)
) like ?",
["%{$keyword}%"]
);
})
->filterColumn('almoxarifado_entrada.created_at', function ($query, $keyword) {
$query->whereRaw("DATE_FORMAT(almoxarifado_entrada.created_at, '%d/%m/%Y') like ?", ["%{$keyword}%"])
->orWhereRaw(
"CONCAT(
SUBSTR(almoxarifado_entrada.created_at,9,2),
SUBSTR(almoxarifado_entrada.created_at,6,2),
SUBSTR(almoxarifado_entrada.created_at,1,4)
) like ?",
["%{$keyword}%"]
);
})
->skipTotalRecords()
->toJson();
}
public static function create()
{
return [
'additionals' => self::getAdditionalsData(),
'form' => self::getFormData(),
'model' => [
'finalizada' => false,
'documento' => [
'tipo_id' => null,
'numero_pedido' => null,
'numero' => null,
'data' => null,
'fornecedor' => null,
'origem_programatica' => null,
],
'itens' => [],
]
];
}
public static function store()
{
self::validate();
$entrada = null;
DB::transaction(function () use (&$entrada) {
$entrada = AlmoxarifadoService::saveEntradaManual(self::getParams());
});
return $entrada;
}
public static function edit($id)
{
$entrada = Entrada::findOrFail($id);
return [
'additionals' => self::getAdditionalsData(),
'form' => self::getFormData(),
'model' => [
'finalizada' => $entrada->finalizada,
'documento' => [
'tipo_id' => $entrada->documento->tipo_id,
'numero_pedido' => $entrada->documento->numero_pedido,
'numero' => $entrada->documento->numero,
'data' => $entrada->documento->data->format('d/m/Y'),
'fornecedor' => $entrada->documento->fornecedor,
'origem_programatica' => $entrada->documento->origemProgramatica,
],
'itens' => $entrada->itens->map(function($item) {
$hasMovimentacao = false;
$hasMovimentacao = DB::table('almoxarifado_saida_item_entrada_item')
->where('entrada_item_id', $item->id)
->exists();
if (!$hasMovimentacao) {
$hasMovimentacao = DB::table('almoxarifado_reserva_item_entrada_item')
->where('entrada_item_id', $item->id)
->exists();
}
if (!$hasMovimentacao) {
$hasMovimentacao = DB::table('integracao_bnafar_posicao_estoque_item')
->where('material_id', $item->material->id)
->exists();
}
return [
'id' => $item->id,
'material' => [
'id' => $item->material->id,
'grupo_tipo_id' => $item->material->grupo->grupo_tipo_id ?? null,
'possui_lote' => $item->material->possui_lote,
'codigo_material' => $item->material->codigo_material,
'descricao_completa' => $item->material->descricao_completa,
'material_bnafar_id' => $item->material->materialBnafar->id ?? null,
'material_bnafar_codigo' => $item->material->materialBnafar->codigo ?? null,
'material_bnafar_descricao' => $item->material->materialBnafar->descricao ?? null,
'material_bnafar_tipo' => $item->material->materialBnafar->tipo ?? null,
],
'quantidade' => $item->quantidade,
'lote' => $item->lote,
'validade_lote' => $item->validade_lote ? $item->validade_lote->format('d/m/Y') : null,
'valor_unitario' => $item->valor_unitario_formatted,
'valor_total' => $item->valor_total_formatted,
'numero_empenho' => $item->numero_empenho,
'despesas' => $item->despesas_formatted,
'numero_autorizacao_fornecimento' => MaskUtil::getNumeroAutorizacaoFornecimentoMasked(
$item->numero_autorizacao_fornecimento
),
'fabricante' => $item->fabricante,
'codigo_barras' => $item->codigo_barras,
'estorno_salvo' => $item->estornado,
'estornado' => $item->estornado,
'integracao_bnafar_medicamento' => $item->integracaoBnafarMedicamento ? [
'medicamento_descricao_id' => $item->integracaoBnafarMedicamento->id,
'medicamento_descricao' => $item->integracaoBnafarMedicamento->descricao,
] : null,
'integracao_bnafar_medicamento_id' => $item->integracaoBnafarMedicamento->id ?? null,
'has_movimentacao' => $hasMovimentacao,
];
})
]
];
}
private static function getAdditionalsData()
{
return [
'data_atual' => Carbon::now()->format('d/m/Y'),
];
}
private static function getFormData()
{
return [
'tipos_documento' => DocumentoTipo::orderBy('nome')->get(['id', 'nome']),
];
}
public static function update($id)
{
self::validate();
$entrada = Entrada::findOrFail($id);
DB::transaction(function () use (&$entrada) {
$entrada = AlmoxarifadoService::saveEntradaManual(self::getParams(), $entrada->id);
});
return $entrada;
}
private static function getParams()
{
return [
'finalizada' => request()->finalizada,
'documento' => [
'fornecedor_id' => request()->documento['fornecedor_id'],
'origem_programatica_id' => request()->documento['origem_programatica_id'],
'tipo_id' => request()->documento['tipo_id'],
'numero_pedido' => request()->documento['numero_pedido'],
'numero' => request()->documento['numero'],
'data' => Carbon::createFromFormat('d/m/Y', request()->documento['data']),
],
'itens' => collect(request()->itens)->map(fn ($item) => [
'id' => $item['id'],
'material_id' => $item['material_id'],
'integracao_bnafar_medicamento_id' => $item['integracao_bnafar_medicamento_id'],
'quantidade' => $item['quantidade'],
'lote' => $item['lote'] ? Str::upper($item['lote']) : null,
'validade_lote' => $item['validade_lote']
? Carbon::createFromFormat('d/m/Y', $item['validade_lote']) : null,
'valor_unitario' => $item['valor_unitario'],
'valor_total' => $item['valor_total'],
'numero_empenho' => $item['numero_empenho'],
'despesas' => $item['despesas'],
'numero_autorizacao_fornecimento' => $item['numero_autorizacao_fornecimento'],
'fabricante_id' => $item['fabricante_id'],
'codigo_barras' => $item['codigo_barras'],
'estornado' => $item['estornado'],
])
];
}
public static function validate()
{
$rules = [
'finalizada' => [
'required',
'boolean',
],
'documento.fornecedor_id' => [
'required',
'integer',
Rule::exists(Fornecedor::class, 'id'),
],
'documento.origem_programatica_id' => [
'nullable',
'integer',
Rule::exists(OrigemProgramatica::class, 'id'),
],
'documento.tipo_id' => [
'required',
'integer',
Rule::exists(DocumentoTipo::class, 'id'),
],
'documento.numero_pedido' => [
'required',
'digits_between:1,20',
],
'documento.numero' => [
'required',
'digits_between:1,10',
],
'documento.data' => [
'required',
'date_format:d/m/Y',
'before_or_equal:now',
],
'itens' => [
'required',
'array',
],
];
$isDocumentoDoacao = (request()->documento['tipo_id'] ?? null) == AlmoxarifadoDocumentoTipo::DOACAO;
foreach ((request()->itens ?? []) as $i => $item) {
$material = is_null($item['material_id']) ? null : Material::find($item['material_id']);
$possuiLote = $material->possui_lote ?? null;
$hasVinculoBnafar = !is_null($material->material_bnafar_id ?? null);
$rules["itens.{$i}.id"] = [
'nullable',
'integer',
Rule::exists(EntradaItem::class, 'id'),
];
$rules["itens.{$i}.material_id"] = [
'bail',
'required',
'integer',
Rule::exists(Material::class, 'id'),
];
$rules["itens.{$i}.quantidade"] = [
'required',
'integer',
'between:1,99999999'
];
$rules["itens.{$i}.lote"] = [
'nullable',
Rule::requiredIf(fn () => is_null($item['id']) && $possuiLote),
'string',
'max:15',
];
$rules["itens.{$i}.validade_lote"] = [
'nullable',
Rule::requiredIf(fn () => is_null($item['id']) && $possuiLote),
'date_format:d/m/Y',
'after_or_equal:documento.data',
];
$rules["itens.{$i}.valor_total"] = [
'required',
'numeric',
'min:' . ($isDocumentoDoacao ? '0.000000' : '0.000001'),
'max:99999999.999999'
];
$rules["itens.{$i}.valor_unitario"] = [
'required',
'numeric',
'min:' . ($isDocumentoDoacao ? '0.000000' : '0.000001'),
'max:99999999.999999'
];
$rules["itens.{$i}.numero_empenho"] = [
'nullable',
'digits_between:1,20',
];
$rules["itens.{$i}.despesas"] = [
'nullable',
'numeric',
'max:99999999.999999'
];
$rules["itens.{$i}.numero_autorizacao_fornecimento"] = [
'nullable',
'digits:9',
];
$rules["itens.{$i}.fabricante_id"] = [
'nullable',
Rule::requiredIf(fn () => $hasVinculoBnafar),
'integer',
Rule::exists(Fabricante::class, 'id'),
];
$rules["itens.{$i}.codigo_barras"] = [
'nullable',
'digits:13',
];
$rules["itens.{$i}.estornado"] = [
'required',
'boolean',
];
}
$messages = [];
request()->validate($rules, $messages);
}
public static function destroy($id)
{
Entrada::findOrFail($id)->delete();
return null;
}
public static function list()
{
switch (request()->listar) {
case 'integracao-bnafar-medicamentos':
return self::getIntegracaoBnafarMedicamentos(request()->material_id);
break;
}
}
private static function getIntegracaoBnafarMedicamentos($materialId)
{
return DB::table('integracao_bnafar_medicamento')
->select([
'integracao_bnafar_medicamento.id AS medicamento_id',
'integracao_bnafar_medicamento.codigo AS medicamento_codigo',
'integracao_bnafar_medicamento.descricao AS medicamento_descricao',
])
->whereExists(function ($query) use ($materialId) {
$query->select(DB::raw(1))
->from('cadastro_material_integracao_bnafar_medicamento')
->where('cadastro_material_integracao_bnafar_medicamento.material_id', $materialId)
->whereColumn('cadastro_material_integracao_bnafar_medicamento.medicamento_id', 'integracao_bnafar_medicamento.id');
})
->get();
}
}