init commit
All checks were successful
build-api-image / build (push) Successful in 51s

This commit is contained in:
Antonio Lopes dos Santos
2026-08-04 16:52:02 -03:00
commit afec302c3e
11594 changed files with 1636728 additions and 0 deletions

View File

@@ -0,0 +1,219 @@
<?php
namespace App\Services\WebService\Almoxarifado\Cliente;
use App\Enums\Almoxarifado\DocumentoTipo as AlmoxarifadoDocumentoTipo;
use App\Enums\WebService\Almoxarifado\Cliente\EntradaDocumentoTipo;
use App\Enums\WebService\Almoxarifado\Cliente\EntradaStatus as EntradaStatusEnum;
use App\Exceptions\WebService\Almoxarifado\Cliente\Entrada\BalanceteConectaSusClosedException;
use App\Exceptions\WebService\Almoxarifado\Cliente\Entrada\EntradaNotFoundException;
use App\Models\Almoxarifado\ParametrizacaoControleEstoqueGrupo;
use App\Models\WebService\Almoxarifado\Cliente\Entrada;
use App\Services\Almoxarifado\AlmoxarifadoService;
use App\Services\Almoxarifado\BalanceteService;
use App\Services\Service;
use Carbon\Carbon;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;
class AprovacaoEntradaService extends Service
{
public static function list()
{
return [
'additionals' => [
'data_atual' => Carbon::today()->format('d/m/Y'),
],
'model' => [
'periodo' => ['start' => null, 'end' => null],
],
];
}
public static function edit($id)
{
$entrada = self::getEntradaModel($id);
$centroCustoGrupos = collect();
$centroCustoSubgrupos = collect();
if (!is_null($entrada->unidade->conectasus_centro_custo_id)) {
ParametrizacaoControleEstoqueGrupo::where('centro_custo_id', $entrada->unidade->conectasus_centro_custo_id)
->get()
->each(function ($parametrizacaoGrupo) use ($centroCustoGrupos, $centroCustoSubgrupos) {
$centroCustoGrupos->push($parametrizacaoGrupo->grupo_id);
$parametrizacaoGrupo->subgrupos->each(function ($parametrizacaoSubgrupo) use ($centroCustoSubgrupos) {
$centroCustoSubgrupos->push($parametrizacaoSubgrupo->subgrupo_id);
});
});
}
$model = [
'unidade_id' => $entrada->unidade->id,
'unidade_nome' => $entrada->unidade->nome,
'is_centro_custo_conectasus_pendente' => is_null($entrada->unidade->conectasus_centro_custo_id),
'fornecedor_id' => $entrada->fornecedor->id,
'fornecedor_nome' => $entrada->fornecedor->nome,
'is_fornecedor_conectasus_pendente' => is_null($entrada->fornecedor->conectasus_fornecedor_id),
'codigo_nota' => $entrada->codigo_nota,
'documento_tipo_nome' => $entrada->documentoTipo->nome,
'data_documento' => $entrada->data_documento->format('d/m/Y'),
'numero_documento' => $entrada->numero_documento,
'numero_pedido' => $entrada->numero_pedido,
'status_nome' => $entrada->status->nome,
'itens' => $entrada->itens->map(fn ($item) => [
'material_id' => $item->material->id,
'material_nome' => $item->material->nome,
'is_material_conectasus_pendente' => is_null($item->material->conectasus_material_id),
'is_material_conectasus_parametrizacao_controle_estoque_pendente' => is_null($item->material->conectasus_material_id)
? false
: (is_null($item->material->conectasusMaterial->subgrupo_id)
? !$centroCustoGrupos->contains($item->material->conectasusMaterial->grupo_id)
: !$centroCustoSubgrupos->contains($item->material->conectasusMaterial->subgrupo_id)
),
'lote' => $item->lote,
'validade_lote' => $item->validade_lote,
'valor_unitario' => $item->valor_unitario_formatted,
'quantidade' => $item->quantidade,
'fabricante_id' => $item->fabricante->id,
'fabricante_nome' => $item->fabricante->nome,
'is_fabricante_conectasus_pendente' => is_null($item->fabricante->conectasus_fabricante_id),
]),
];
$hasPendenciasMateriais = $model['itens']
->filter(fn ($i) => $i['is_material_conectasus_pendente']
|| $i['is_material_conectasus_parametrizacao_controle_estoque_pendente']
|| $i['is_fabricante_conectasus_pendente']
)
->isNotEmpty();
return [
'additionals' => [
'allow_update' => $entrada->status_id === EntradaStatusEnum::PENDENTE,
'has_pendencias' => $model['is_centro_custo_conectasus_pendente']
|| $model['is_fornecedor_conectasus_pendente']
|| $hasPendenciasMateriais,
'has_pendencias_materiais' => $hasPendenciasMateriais
],
'model' => $model,
];
}
public static function approve($id)
{
$entrada = self::getEntradaModel($id);
if (self::isDataDocumentoEmBalanceteDoAlmoxarifadoFechado($entrada->data_documento)) {
throw new BalanceteConectaSusClosedException();
}
DB::transaction(function () use ($entrada) {
$almoxarifadoEntrada = AlmoxarifadoService::saveEntradaManualWebService(
$entrada->unidade->conectasus_centro_custo_id,
[
'documento' => [
'fornecedor_id' => $entrada->fornecedor->conectasus_fornecedor_id,
'tipo_id' => self::getAlmoxarifadoDocumentoTipoId($entrada->documento_tipo_id),
'numero_pedido' => $entrada->numero_pedido,
'numero' => $entrada->numero_documento,
'data' => $entrada->data_documento,
],
'itens' => $entrada->itens->map(fn ($item) => [
'id' => null,
'material_id' => $item->material->conectasus_material_id,
'quantidade' => $item->quantidade,
'lote' => Str::upper($item->lote),
'validade_lote' => $item->validade_lote,
'valor_unitario' => $item->valor_unitario,
'valor_total' => $item->valor_unitario * $item->quantidade,
'numero_empenho' => null,
'despesas' => null,
'numero_autorizacao_fornecimento' => null,
'fabricante_id' => $item->fabricante->conectasus_fabricante_id,
'codigo_barras' => null,
])
]
);
$entrada->conectasus_entrada_id = $almoxarifadoEntrada->id;
$entrada->status_id = EntradaStatusEnum::APROVADA;
$entrada->save();
});
}
private static function getAlmoxarifadoDocumentoTipoId($documentoTipoId)
{
switch ($documentoTipoId) {
case EntradaDocumentoTipo::NOTA_FISCAL: {
return AlmoxarifadoDocumentoTipo::NOTA_FISCAL;
}
case EntradaDocumentoTipo::DOACAO: {
return AlmoxarifadoDocumentoTipo::DOACAO;
}
case EntradaDocumentoTipo::OUTROS: {
return AlmoxarifadoDocumentoTipo::OUTRAS;
}
}
}
private static function isDataDocumentoEmBalanceteDoAlmoxarifadoFechado($dataDocumento)
{
return BalanceteService::checkDate($dataDocumento->format('Y-m-d'))['mes_fechado'];
}
public static function reject($id)
{
$entrada = self::getEntradaModel($id);
$entrada->update(['status_id' => EntradaStatusEnum::RECUSADA]);
}
public static function datatable($request)
{
return DB::table('web_service_almoxarifado_cliente_entrada AS entrada')
->join('web_service_almoxarifado_cliente_unidade AS unidade', 'unidade.id', 'entrada.unidade_id')
->join('web_service_almoxarifado_cliente_fornecedor AS fornecedor', 'fornecedor.id', 'entrada.fornecedor_id')
->join(
'web_service_almoxarifado_cliente_entrada_documento_tipo AS documento_tipo',
'documento_tipo.id',
'entrada.documento_tipo_id'
)
->join('web_service_almoxarifado_cliente_entrada_status AS status', 'status.id', 'entrada.status_id')
->whereBetween('entrada.data_documento', [$request->periodo['start'], $request->periodo['end']])
->select([
'entrada.id',
'unidade.nome AS unidade_nome',
'fornecedor.nome AS fornecedor_nome',
'entrada.codigo_nota',
'documento_tipo.nome AS documento_tipo_nome',
DB::raw("DATE_FORMAT(entrada.data_documento, '%d/%m/%Y') AS data_documento"),
'entrada.numero_documento',
'entrada.numero_pedido',
'status.nome as status_nome',
]);
}
private static function getEntradaModel($id)
{
$entrada = Entrada::find($id);
if (is_null($entrada)) {
throw new EntradaNotFoundException();
}
return $entrada;
}
}

View File

@@ -0,0 +1,341 @@
<?php
namespace App\Services\WebService\Almoxarifado\Cliente;
use App\Enums\WebService\Almoxarifado\Cliente\EntradaDocumentoTipo as ClienteEntradaDocumentoTipo;
use App\Enums\WebService\Almoxarifado\Cliente\EntradaStatus as EntradaStatusEnum;
use App\Exceptions\WebService\Almoxarifado\Cliente\Entrada\BalanceteConectaSusClosedException;
use App\Exceptions\WebService\Almoxarifado\Cliente\Entrada\CannotDeleteEntradaAprovadaException;
use App\Exceptions\WebService\Almoxarifado\Cliente\Entrada\ConflictEntradaException;
use App\Exceptions\WebService\Almoxarifado\Cliente\Entrada\DuplicatedMaterialLoteException;
use App\Exceptions\WebService\Almoxarifado\Cliente\Entrada\EntradaNotFoundException;
use App\Exceptions\WebService\Almoxarifado\Cliente\Entrada\InvalidSearchPeriodException;
use App\Exceptions\WebService\Almoxarifado\Cliente\Entrada\PeriodoContabilClosedException;
use App\Models\WebService\Almoxarifado\Cliente\Entrada;
use App\Models\WebService\Almoxarifado\Cliente\EntradaDocumentoTipo;
use App\Models\WebService\Almoxarifado\Cliente\EntradaStatus;
use App\Models\WebService\Almoxarifado\Cliente\Fabricante;
use App\Models\WebService\Almoxarifado\Cliente\Fornecedor;
use App\Models\WebService\Almoxarifado\Cliente\Material;
use App\Models\WebService\Almoxarifado\Cliente\PeriodoContabil;
use App\Models\WebService\Almoxarifado\Cliente\Unidade;
use App\Services\Almoxarifado\BalanceteService;
use App\Services\Service;
use Carbon\Carbon;
use Illuminate\Support\Facades\DB;
use Illuminate\Validation\Rule;
class EntradaService extends Service
{
public const LIMITE_DIAS_PERIODO_BUSCA = 31;
public static function index($request)
{
self::validateIndex($request);
$entradas = collect();
DB::table('web_service_almoxarifado_cliente_entrada_item AS entrada_item')
->join('web_service_almoxarifado_cliente_entrada AS entrada', 'entrada.id', 'entrada_item.entrada_id')
->whereBetween('entrada.data_documento', [
$request->query('data_documento_inicial'),
$request->query('data_documento_final')
])
->when($request->query('status_id'), fn ($q, $id) => $q->where('entrada.status_id', $id))
->select([
'entrada.id AS entrada_id',
'entrada.unidade_id',
'entrada.fornecedor_id',
'entrada.codigo_nota',
'entrada.documento_tipo_id',
'entrada.data_documento',
'entrada.numero_documento',
'entrada.numero_pedido',
'entrada.status_id',
'entrada_item.material_id',
'entrada_item.fabricante_id',
'entrada_item.lote',
'entrada_item.validade_lote',
'entrada_item.quantidade',
'entrada_item.valor_unitario',
])
->orderBy('entrada.data_documento')
->each(function ($entradaItem) use ($entradas) {
$entrada = $entradas->where('id', $entradaItem->entrada_id)->first();
if (is_null($entrada)) {
$entrada = (object) [
'id' => $entradaItem->entrada_id,
'unidade_id' => $entradaItem->unidade_id,
'fornecedor_id' => $entradaItem->fornecedor_id,
'codigo_nota' => $entradaItem->codigo_nota,
'documento_tipo_id' => $entradaItem->documento_tipo_id,
'data_documento' => $entradaItem->data_documento,
'numero_documento' => $entradaItem->numero_documento,
'numero_pedido' => $entradaItem->numero_pedido,
'status_id' => $entradaItem->status_id,
'itens' => collect(),
];
$entradas->push($entrada);
}
$entrada->itens->push((object) [
'material_id' => $entradaItem->material_id,
'fabricante_id' => $entradaItem->fabricante_id,
'lote' => $entradaItem->lote,
'validade_lote' => $entradaItem->validade_lote,
'quantidade' => $entradaItem->quantidade,
'valor_unitario' => (float) $entradaItem->valor_unitario,
]);
});
return $entradas;
}
private static function validateIndex($request)
{
$request->validate([
'data_documento_inicial' => [
'required',
'date_format:Y-m-d',
'before_or_equal:data_documento_final',
],
'data_documento_final' => [
'required',
'date_format:Y-m-d',
'after_or_equal:data_documento_inicial',
],
'status_id' => [
'integer',
Rule::exists(EntradaStatus::class, 'id'),
]
]);
$dataDocumentoInicial = Carbon::create($request->data_documento_inicial);
$dataDocumentoFinal = Carbon::create($request->data_documento_final);
if ($dataDocumentoInicial->diff($dataDocumentoFinal)->days > self::LIMITE_DIAS_PERIODO_BUSCA) {
throw new InvalidSearchPeriodException();
}
}
public static function show($id)
{
$entrada = self::getEntradaModel($id)->load('itens');
$entrada->itens->each(function ($item) {
$item->valor_unitario = (float) $item->valor_unitario;
});
return $entrada;
}
public static function store($request)
{
self::validate($request);
$data = self::getEntradaData($request);
$entrada = new Entrada();
DB::transaction(function () use ($entrada, $data) {
$entrada->fill($data);
$entrada->save();
$entrada->itens()->createMany($data['itens']);
});
return self::show($entrada->id);
}
private static function getEntradaData($request)
{
$data = $request->only([
'unidade_id',
'fornecedor_id',
'codigo_nota',
'documento_tipo_id',
'data_documento',
'numero_documento',
'numero_pedido',
]);
$data['status_id'] = EntradaStatusEnum::PENDENTE;
$data['itens'] = collect($request->itens)->map(fn ($item) => [
'material_id' => $item['material_id'],
'fabricante_id' => $item['fabricante_id'],
'lote' => $item['lote'],
'validade_lote' => $item['validade_lote'],
'quantidade' => $item['quantidade'],
'valor_unitario' => $item['valor_unitario'],
]);
return $data;
}
public static function destroy($id)
{
$entrada = self::getEntradaModel($id);
if ($entrada->status_id === EntradaStatusEnum::APROVADA) {
throw new CannotDeleteEntradaAprovadaException();
}
$entrada->delete();
}
private static function validate($request)
{
$request->validate([
'unidade_id' => [
'bail',
'required',
'integer',
Rule::exists(Unidade::class, 'id'),
function ($attribute, $value, $fail) {
if (!Unidade::find($value)->is_almoxarifado) {
$fail("O campo {$attribute} não é um almoxarifado.");
}
},
],
'fornecedor_id' => [
'required',
'integer',
Rule::exists(Fornecedor::class, 'id'),
],
'codigo_nota' => [
'required',
'integer',
],
'documento_tipo_id' => [
'required',
'integer',
Rule::exists(EntradaDocumentoTipo::class, 'id'),
],
'data_documento' => [
'bail',
'required',
'date_format:Y-m-d',
'before_or_equal:' . Carbon::today()->format('Y-m-d'),
],
'numero_documento' => [
'nullable',
'present',
'digits_between:1,10',
],
'numero_pedido' => [
'nullable',
'present',
'digits_between:1,20',
],
'itens' => [
'required',
'array',
],
'itens.*.material_id' => [
'required',
'integer',
Rule::exists(Material::class, 'id'),
],
'itens.*.fabricante_id' => [
'required',
'integer',
Rule::exists(Fabricante::class, 'id'),
],
'itens.*.lote' => [
'required',
'string',
'max:15',
],
'itens.*.validade_lote' => [
'bail',
'required',
'date_format:Y-m-d',
'after_or_equal:data_documento',
],
'itens.*.quantidade' => [
'required',
'integer',
'between:1,99999999'
],
'itens.*.valor_unitario' => [
'required',
'numeric',
'min:' . (
(EntradaDocumentoTipo::find($request->documento_tipo_id)->id ?? null) === ClienteEntradaDocumentoTipo::DOACAO
? '0.000000'
: '0.000001'
),
'max:99999999.999999'
],
]);
$hasDuplicatedMaterialLote = collect($request->itens)
->groupBy(['material_id', 'lote'])
->filter(fn ($m) => $m->filter(fn ($l) => $l->count() > 1)->isNotEmpty())
->isNotEmpty();
if ($hasDuplicatedMaterialLote) {
throw new DuplicatedMaterialLoteException();
}
$entradaConflitante = Entrada::where('unidade_id', $request->unidade_id)
->where('fornecedor_id', $request->fornecedor_id)
->where('codigo_nota', $request->codigo_nota)
->where('documento_tipo_id', $request->documento_tipo_id)
->where('data_documento', $request->data_documento)
->where('numero_documento', $request->numero_documento)
->where('numero_pedido', $request->numero_pedido)
->whereIn('status_id', [EntradaStatusEnum::PENDENTE, EntradaStatusEnum::APROVADA])
->exists();
if ($entradaConflitante) {
throw new ConflictEntradaException();
}
if (self::isDataDocumentoEmPeriodoContabilFechado($request->data_documento)) {
throw new PeriodoContabilClosedException();
}
if (self::isDataDocumentoEmBalanceteDoAlmoxarifadoFechado($request->data_documento)) {
throw new BalanceteConectaSusClosedException();
}
}
private static function isDataDocumentoEmPeriodoContabilFechado($dataDocumento)
{
return PeriodoContabil::where('inicio', '<=', $dataDocumento)
->where('fim', '>=', $dataDocumento)
->exists();
}
private static function isDataDocumentoEmBalanceteDoAlmoxarifadoFechado($dataDocumento)
{
return BalanceteService::checkDate($dataDocumento)['mes_fechado'];
}
private static function getEntradaModel($id)
{
$entrada = Entrada::find($id);
if (is_null($entrada)) {
throw new EntradaNotFoundException();
}
return $entrada;
}
}

View File

@@ -0,0 +1,158 @@
<?php
namespace App\Services\WebService\Almoxarifado\Cliente;
use App\Exceptions\WebService\Almoxarifado\Cliente\Fabricante\CannotDeleteFabricanteException;
use App\Exceptions\WebService\Almoxarifado\Cliente\Fabricante\FabricanteNotFoundException;
use App\Models\Cadastro\Fabricante\Fabricante as CadastroFabricante;
use App\Models\WebService\Almoxarifado\Cliente\Fabricante;
use App\Rules\Cnpj;
use App\Services\Service;
use App\Utils\MaskUtil;
use Illuminate\Support\Facades\DB;
use Illuminate\Validation\Rule;
class FabricanteService extends Service
{
public static function index()
{
return DB::table('web_service_almoxarifado_cliente_fabricante AS fabricante')
->select([
'fabricante.id',
'fabricante.conectasus_fabricante_id',
'fabricante.nome',
'fabricante.cnpj',
])
->orderBy('fabricante.nome')
->get();
}
public static function create()
{
return [
'form' => self::getFormData(),
'model' => [
'conectasus_fabricante_id' => null,
'nome' => null,
'cnpj' => null,
],
];
}
public static function store($request)
{
self::validate($request);
return Fabricante::create(self::getFabricanteData($request))->fresh();
}
public static function show($id)
{
return self::getFabricanteModel($id);
}
public static function edit($id)
{
$fabricante = self::getFabricanteModel($id);
return [
'form' => self::getFormData(),
'model' => [
'conectasus_fabricante_id' => $fabricante->conectasus_fabricante_id,
'nome' => $fabricante->nome,
'cnpj' => MaskUtil::getCnpjMasked($fabricante->cnpj),
],
];
}
private static function getFormData()
{
return [
'conectasus_fabricantes' => CadastroFabricante::orderBy('nome')
->get(['id', 'nome', 'cnpj'])
->map(fn ($fabricante) => (object) [
'id' => $fabricante->id,
'descricao' => $fabricante->nome
. ($fabricante->cnpj ? (' - ' . MaskUtil::getCnpjMasked($fabricante->cnpj)) : '')
]),
];
}
public static function update($request, $id)
{
$fabricante = self::getFabricanteModel($id);
self::validate($request);
return tap($fabricante)->update(self::getFabricanteData($request))->fresh();
}
private static function getFabricanteData($request)
{
return $request->only(['conectasus_fabricante_id', 'nome', 'cnpj']);
}
public static function destroy($id)
{
$fabricante = self::getFabricanteModel($id);
if ($fabricante->entradaItens()->exists()) {
throw new CannotDeleteFabricanteException();
}
$fabricante->delete();
}
public static function datatable()
{
return DB::table('web_service_almoxarifado_cliente_fabricante AS fabricante')
->leftJoin(
'cadastro_fabricante as conectasus_fabricante',
'conectasus_fabricante.id',
'fabricante.conectasus_fabricante_id'
)
->select([
'fabricante.id',
'fabricante.nome',
'fabricante.cnpj',
'conectasus_fabricante.nome AS conectasus_fabricante_nome',
]);
}
private static function validate($request)
{
$request->validate([
'conectasus_fabricante_id' => [
'nullable',
'present',
'integer',
Rule::exists(CadastroFabricante::class, 'id'),
],
'nome' => [
'required',
'string',
'between:3,100',
Rule::unique(Fabricante::class, 'nome')->ignore($request->route('id')),
],
'cnpj' => [
'nullable',
'present',
'digits:14',
new Cnpj,
],
]);
}
private static function getFabricanteModel($id)
{
$fabricante = Fabricante::find($id);
if (is_null($fabricante)) {
throw new FabricanteNotFoundException();
}
return $fabricante;
}
}

View File

@@ -0,0 +1,158 @@
<?php
namespace App\Services\WebService\Almoxarifado\Cliente;
use App\Exceptions\WebService\Almoxarifado\Cliente\Fornecedor\CannotDeleteFornecedorException;
use App\Exceptions\WebService\Almoxarifado\Cliente\Fornecedor\FornecedorNotFoundException;
use App\Models\Cadastro\Fornecedor\Fornecedor as CadastroFornecedor;
use App\Models\WebService\Almoxarifado\Cliente\Fornecedor;
use App\Rules\Cnpj;
use App\Services\Service;
use App\Utils\MaskUtil;
use Illuminate\Support\Facades\DB;
use Illuminate\Validation\Rule;
class FornecedorService extends Service
{
public static function index()
{
return DB::table('web_service_almoxarifado_cliente_fornecedor AS fornecedor')
->select([
'fornecedor.id',
'fornecedor.conectasus_fornecedor_id',
'fornecedor.nome',
'fornecedor.cnpj',
])
->orderBy('fornecedor.nome')
->get();
}
public static function create()
{
return [
'form' => self::getFormData(),
'model' => [
'conectasus_fornecedor_id' => null,
'nome' => null,
'cnpj' => null,
],
];
}
public static function store($request)
{
self::validate($request);
return Fornecedor::create(self::getFornecedorData($request))->fresh();
}
public static function show($id)
{
return self::getFornecedorModel($id);
}
public static function edit($id)
{
$fornecedor = self::getFornecedorModel($id);
return [
'form' => self::getFormData(),
'model' => [
'conectasus_fornecedor_id' => $fornecedor->conectasus_fornecedor_id,
'nome' => $fornecedor->nome,
'cnpj' => MaskUtil::getCnpjMasked($fornecedor->cnpj),
],
];
}
private static function getFormData()
{
return [
'conectasus_fornecedores' => CadastroFornecedor::orderBy('nome_fantasia')
->get(['id', 'nome_fantasia', 'cnpj'])
->map(fn ($fornecedor) => (object) [
'id' => $fornecedor->id,
'descricao' => $fornecedor->nome_fantasia
. ($fornecedor->cnpj ? (' - ' . MaskUtil::getCnpjMasked($fornecedor->cnpj)) : '')
]),
];
}
public static function update($request, $id)
{
$fornecedor = self::getFornecedorModel($id);
self::validate($request);
return tap($fornecedor)->update(self::getFornecedorData($request))->fresh();
}
private static function getFornecedorData($request)
{
return $request->only(['conectasus_fornecedor_id', 'nome', 'cnpj']);
}
public static function destroy($id)
{
$fornecedor = self::getFornecedorModel($id);
if ($fornecedor->entradas()->exists()) {
throw new CannotDeleteFornecedorException();
}
$fornecedor->delete();
}
public static function datatable()
{
return DB::table('web_service_almoxarifado_cliente_fornecedor AS fornecedor')
->leftJoin(
'cadastro_fornecedor as conectasus_fornecedor',
'conectasus_fornecedor.id',
'fornecedor.conectasus_fornecedor_id'
)
->select([
'fornecedor.id',
'fornecedor.nome',
'fornecedor.cnpj',
'conectasus_fornecedor.nome_fantasia AS conectasus_fornecedor_nome_fantasia',
]);
}
private static function validate($request)
{
$request->validate([
'conectasus_fornecedor_id' => [
'nullable',
'present',
'integer',
Rule::exists(CadastroFornecedor::class, 'id'),
],
'nome' => [
'required',
'string',
'between:3,100',
Rule::unique(Fornecedor::class, 'nome')->ignore($request->route('id')),
],
'cnpj' => [
'nullable',
'present',
'digits:14',
new Cnpj,
],
]);
}
private static function getFornecedorModel($id)
{
$fornecedor = Fornecedor::find($id);
if (is_null($fornecedor)) {
throw new FornecedorNotFoundException();
}
return $fornecedor;
}
}

View File

@@ -0,0 +1,161 @@
<?php
namespace App\Services\WebService\Almoxarifado\Cliente;
use App\Exceptions\WebService\Almoxarifado\Cliente\Material\CannotDeleteMaterialException;
use App\Exceptions\WebService\Almoxarifado\Cliente\Material\MaterialNotFoundException;
use App\Models\Cadastro\Grupo\Grupo as CadastroGrupo;
use App\Models\Cadastro\Material\Material as CadastroMaterial;
use App\Models\WebService\Almoxarifado\Cliente\Material;
use App\Services\Cadastro\Material\MaterialService as CadastroMaterialService;
use App\Services\Service;
use Illuminate\Support\Facades\DB;
use Illuminate\Validation\Rule;
class MaterialService extends Service
{
public static function index()
{
return DB::table('web_service_almoxarifado_cliente_material AS material')
->select([
'material.id',
'material.conectasus_material_id',
'material.nome',
])
->orderBy('material.nome')
->get();
}
public static function create()
{
return [
'form' => self::getFormData(),
'model' => [
'conectasus_material_grupo_id' => null,
'conectasus_material' => null,
'nome' => null,
],
];
}
public static function store($request)
{
self::validate($request);
return Material::create(self::getMaterialData($request))->fresh();
}
public static function show($id)
{
return self::getMaterialModel($id);
}
public static function edit($id)
{
$material = self::getMaterialModel($id);
return [
'form' => self::getFormData(),
'model' => [
'conectasus_material_grupo_id' => $material->conectasusMaterial->grupo_id ?? null,
'conectasus_material' => $material->conectasusMaterial ? [
'id' => $material->conectasusMaterial->id,
'descricao_completa' => $material->conectasusMaterial->descricao_completa,
] : null,
'nome' => $material->nome,
],
];
}
private static function getFormData()
{
return [
'conectasus_grupos' => CadastroGrupo::orderBy('nome')->get(['id', 'nome']),
];
}
public static function update($request, $id)
{
$material = self::getMaterialModel($id);
self::validate($request);
return tap($material)->update(self::getMaterialData($request))->fresh();
}
private static function getMaterialData($request)
{
return $request->only(['conectasus_material_id', 'nome']);
}
public static function destroy($id)
{
$material = self::getMaterialModel($id);
if ($material->entradaItens()->exists()) {
throw new CannotDeleteMaterialException();
}
$material->delete();
}
public static function datatable()
{
return DB::table('web_service_almoxarifado_cliente_material AS material')
->leftJoin(
'cadastro_material AS conectasus_material',
'conectasus_material.id',
'material.conectasus_material_id'
)
->leftJoin(
'cadastro_apresentacao AS conectasus_material_apresentacao',
'conectasus_material_apresentacao.id',
'conectasus_material.apresentacao_id'
)
->leftJoin(
'cadastro_unidade_medida as conectasus_material_apresentacao_unidade_medida',
'conectasus_material_apresentacao_unidade_medida.id',
'conectasus_material.apresentacao_unidade_medida_id'
)
->select([
'material.id',
'material.nome',
DB::raw(CadastroMaterialService::getDescricaoCompletaRaw(
'conectasus_material',
'conectasus_material_apresentacao',
'conectasus_material_apresentacao_unidade_medida'
) . " AS conectasus_material_descricao_completa"),
]);
}
private static function validate($request)
{
$request->validate([
'conectasus_material_id' => [
'nullable',
'present',
'integer',
Rule::exists(CadastroMaterial::class, 'id'),
],
'nome' => [
'required',
'string',
'between:3,100',
Rule::unique(Material::class, 'nome')->ignore($request->route('id')),
],
]);
}
private static function getMaterialModel($id)
{
$material = Material::find($id);
if (is_null($material)) {
throw new MaterialNotFoundException();
}
return $material;
}
}

View File

@@ -0,0 +1,118 @@
<?php
namespace App\Services\WebService\Almoxarifado\Cliente;
use App\Exceptions\WebService\Almoxarifado\Cliente\PeriodoContabil\ConflictException;
use App\Exceptions\WebService\Almoxarifado\Cliente\PeriodoContabil\InvalidDaysLimitException;
use App\Exceptions\WebService\Almoxarifado\Cliente\PeriodoContabil\PeriodoContabilNotFoundException;
use App\Models\WebService\Almoxarifado\Cliente\PeriodoContabil;
use App\Services\Service;
use Carbon\Carbon;
use Illuminate\Support\Facades\DB;
class PeriodoContabilService extends Service
{
public const LIMITE_DIAS_PERIODO = 31;
public static function index()
{
return DB::table('web_service_almoxarifado_cliente_periodo_contabil AS periodo_contabil')
->select([
'periodo_contabil.id',
'periodo_contabil.inicio',
'periodo_contabil.fim',
])
->orderBy('periodo_contabil.inicio')
->orderBy('periodo_contabil.fim')
->get();
}
public static function create()
{
return [
'model' => [
'periodo_contabil' => ['start' => null, 'end' => null],
],
];
}
public static function store($request)
{
self::validate($request);
return PeriodoContabil::create(self::getPeriodoContabilData($request))->fresh();
}
public static function show($id)
{
return self::getPeriodoContabilModel($id);
}
private static function getPeriodoContabilData($request)
{
return [
'inicio' => $request->inicio,
'fim' => $request->fim,
];
}
public static function destroy($id)
{
self::getPeriodoContabilModel($id)->delete();
}
public static function datatable()
{
return DB::table('web_service_almoxarifado_cliente_periodo_contabil AS periodo_contabil')
->select([
'periodo_contabil.id',
DB::raw("DATE_FORMAT(periodo_contabil.inicio, '%d/%m/%Y') AS inicio"),
DB::raw("DATE_FORMAT(periodo_contabil.fim, '%d/%m/%Y') AS fim"),
]);
}
private static function validate($request)
{
$request->validate([
'inicio' => [
'required',
'date_format:Y-m-d',
'before_or_equal:fim',
],
'fim' => [
'required',
'date_format:Y-m-d',
'after_or_equal:inicio',
],
]);
$inicio = Carbon::create($request->inicio);
$fim = Carbon::create($request->fim);
if ($inicio->diff($fim)->days > self::LIMITE_DIAS_PERIODO) {
throw new InvalidDaysLimitException();
}
$periodoContabilConflitante = PeriodoContabil::whereBetween('inicio', [$request->inicio, $request->fim])
->orWhereBetween('fim', [$request->inicio, $request->fim])
->exists();
if ($periodoContabilConflitante) {
throw new ConflictException();
}
}
private static function getPeriodoContabilModel($id)
{
$periodoContabil = PeriodoContabil::find($id);
if (is_null($periodoContabil)) {
throw new PeriodoContabilNotFoundException();
}
return $periodoContabil;
}
}

View File

@@ -0,0 +1,125 @@
<?php
namespace App\Services\WebService\Almoxarifado\Cliente;
use App\Models\WebService\Almoxarifado\Cliente\Material;
use App\Models\WebService\Almoxarifado\Cliente\Unidade;
use App\Services\Service;
use Illuminate\Support\Facades\DB;
use Illuminate\Validation\Rule;
class PosicaoEstoqueService extends Service
{
public static function index($request)
{
self::validateIndex($request);
$conectaSusCentroCustoId = Unidade::find($request->query('unidade_id'))->conectasus_centro_custo_id;
$posicoesEstoques = DB::table('web_service_almoxarifado_cliente_material AS cliente_material')
->join(
'cadastro_material AS conectasus_material',
'conectasus_material.id',
'cliente_material.conectasus_material_id'
)
->leftJoin('almoxarifado_entrada_item AS entrada_item', fn ($j) => $j
->on('entrada_item.material_id', 'conectasus_material.id')
->whereExists(fn ($q) => $q
->selectRaw(1)
->from('almoxarifado_entrada AS entrada')
->whereColumn('entrada.id', 'entrada_item.entrada_id')
->where('entrada.finalizada', true)
->where('entrada.centro_custo_id', $conectaSusCentroCustoId)
)
)
->where(fn ($q) => $q
->where(fn ($q) => $q
->whereNull('conectasus_material.subgrupo_id')
->whereExists(fn ($q) => $q
->select(DB::raw(1))
->from('almoxarifado_parametrizacao_controle_estoque_grupo AS controle_estoque_grupo')
->whereColumn('controle_estoque_grupo.grupo_id', 'conectasus_material.grupo_id')
->where('controle_estoque_grupo.centro_custo_id', $conectaSusCentroCustoId)
)
)
->orWhere(fn ($q) => $q
->whereNotNull('conectasus_material.subgrupo_id')
->whereExists(fn ($q) => $q
->select(DB::raw(1))
->from('almoxarifado_parametrizacao_controle_estoque_subgrupo AS controle_estoque_subgrupo')
->join(
'almoxarifado_parametrizacao_controle_estoque_grupo AS controle_estoque_grupo',
'controle_estoque_grupo.id',
'controle_estoque_subgrupo.parametrizacao_controle_estoque_grupo_id'
)
->whereColumn('controle_estoque_subgrupo.subgrupo_id', 'conectasus_material.subgrupo_id')
->where('controle_estoque_grupo.centro_custo_id', $conectaSusCentroCustoId)
)
)
)
->when($request->query('material_id'), fn ($q, $id) => $q->where('cliente_material.id', $id))
->select([
'cliente_material.id',
'cliente_material.conectasus_material_id',
'cliente_material.nome',
DB::raw(
"COALESCE(SUM(
COALESCE(entrada_item.quantidade, 0)
-
COALESCE((
SELECT SUM(saida_item_entrada_item.quantidade_saida)
FROM almoxarifado_saida_item_entrada_item AS saida_item_entrada_item
JOIN almoxarifado_saida_item AS saida_item
ON saida_item.id = saida_item_entrada_item.saida_item_id
JOIN almoxarifado_saida AS saida
ON saida.id = saida_item.saida_id
WHERE saida_item_entrada_item.entrada_item_id = entrada_item.id
AND saida.finalizada = 1
), 0)
), 0) AS quantidade"
)
])
->groupBy([
'cliente_material.id',
'cliente_material.conectasus_material_id',
'cliente_material.nome',
])
->get();
return tap($posicoesEstoques)->each(function ($posicaoEstoque) {
$posicaoEstoque->quantidade = (int) $posicaoEstoque->quantidade;
});
}
private static function validateIndex($request)
{
$request->validate([
'unidade_id' => [
'bail',
'required',
'integer',
Rule::exists(Unidade::class, 'id'),
function ($attribute, $value, $fail) {
if (is_null(Unidade::find($value)->conectasus_centro_custo_id)) {
$fail("O campo {$attribute} selecionado não possui vínculo com um centro de custo do ConectaSUS.");
}
},
],
'material_id' => [
'bail',
'integer',
Rule::exists(Material::class, 'id'),
function ($attribute, $value, $fail) {
if (is_null(Material::find($value)->conectasus_material_id)) {
$fail("O campo {$attribute} selecionado não possui vínculo com um material do ConectaSUS.");
}
},
],
]);
}
}

View File

@@ -0,0 +1,182 @@
<?php
namespace App\Services\WebService\Almoxarifado\Cliente;
use App\Enums\Almoxarifado\SaidaTipo;
use App\Exceptions\WebService\Almoxarifado\Cliente\Saida\InvalidSearchPeriodException;
use App\Models\WebService\Almoxarifado\Cliente\Unidade;
use App\Services\Service;
use App\Utils\DataUtil;
use Carbon\Carbon;
use Illuminate\Support\Facades\DB;
use Illuminate\Validation\Rule;
class SaidaService extends Service
{
public const LIMITE_DIAS_PERIODO_BUSCA = 31;
public static function index($request)
{
self::validateIndex($request);
$unidadeAlmoxarifado = Unidade::find($request->unidade_almoxarifado_id);
$unidadeRequisitante = is_null($request->unidade_id) ? null : Unidade::find($request->unidade_id);
$dataInicial = Carbon::create($request->data_inicial)->startOfDay();
$dataFinal = Carbon::create($request->data_final)->endOfDay();
$saidas = DB::table('almoxarifado_saida_item_entrada_item AS saida_item_entrada_item')
->join(
'almoxarifado_entrada_item AS entrada_item',
'entrada_item.id',
'saida_item_entrada_item.entrada_item_id'
)
->join(
'almoxarifado_saida_item AS saida_item',
'saida_item.id',
'saida_item_entrada_item.saida_item_id'
)
->join(
'almoxarifado_saida AS saida',
'saida.id',
'saida_item.saida_id'
)
->join(
'web_service_almoxarifado_cliente_material AS cliente_material',
'cliente_material.conectasus_material_id',
'saida_item.material_id'
)
->leftJoin(
'almoxarifado_saida_requisicao AS saida_requisicao',
'saida_requisicao.saida_id',
'saida.id'
)
->leftJoin(
'almoxarifado_saida_transferencia AS saida_transferencia',
'saida_transferencia.saida_id',
'saida.id'
)
->leftJoin(
'almoxarifado_requisicao_resposta AS requisicao_resposta',
'requisicao_resposta.saida_id',
'saida.id'
)
->leftJoin(
'almoxarifado_requisicao AS requisicao',
'requisicao.id',
'requisicao_resposta.requisicao_id'
)
->leftJoin(
'web_service_almoxarifado_cliente_unidade AS cliente_unidade_requisitante',
'cliente_unidade_requisitante.conectasus_centro_custo_id',
DB::raw("COALESCE(
saida_requisicao.centro_custo_id,
saida_transferencia.centro_custo_id,
requisicao.created_centro_custo_id
)")
)
->where('saida.finalizada', true)
->where('saida.centro_custo_id', $unidadeAlmoxarifado->conectasus_centro_custo_id)
->whereBetween('saida.created_at', [$dataInicial, $dataFinal])
->where('saida.tipo_id', '<>', SaidaTipo::ESTORNO)
->when($unidadeRequisitante->conectasus_centro_custo_id ?? null, fn ($q, $id) => $q->where(fn ($q) => $q
->where('saida_requisicao.centro_custo_id', $id)
->orWhere('saida_transferencia.centro_custo_id', $id)
->orWhere('requisicao.created_centro_custo_id', $id)
))
->when(DataUtil::isStringBoolean($request->query('is_estornada')), fn ($q) => $q
->when(DataUtil::isStringTrue($request->query('is_estornada')),
fn ($q) => $q->whereNotNull('saida_item.estornado_em'),
fn ($q) => $q->whereNull('saida_item.estornado_em')
)
)
->select([
DB::raw("CAST(saida.created_at AS DATE) AS data"),
DB::raw("CAST(saida_item.estornado_em AS DATE) AS data_estorno"),
'cliente_unidade_requisitante.id AS unidade_id',
'cliente_material.id AS material_id',
'entrada_item.lote',
'entrada_item.validade_lote',
DB::raw('IF(saida_item.estornado_em IS NULL, 0, 1) AS is_estornada'),
DB::raw("SUM(saida_item_entrada_item.quantidade_saida) AS quantidade"),
])
->orderBy('saida.created_at')
->orderBy('saida_item.estornado_em')
->groupBy([
DB::raw("CAST(saida.created_at AS DATE)"),
DB::raw("CAST(saida_item.estornado_em AS DATE)"),
'cliente_unidade_requisitante.id',
'cliente_material.id',
'entrada_item.lote',
'entrada_item.validade_lote',
DB::raw('IF(saida_item.estornado_em IS NULL, 0, 1)'),
])
->get();
return tap($saidas)->each(function ($saida) {
$saida->is_estornada = (bool) $saida->is_estornada;
$saida->quantidade = (int) $saida->quantidade;
});
}
private static function validateIndex($request)
{
$request->validate([
'data_inicial' => [
'required',
'date_format:Y-m-d',
'before_or_equal:data_final',
],
'data_final' => [
'required',
'date_format:Y-m-d',
'after_or_equal:data_inicial',
],
'unidade_almoxarifado_id' => [
'bail',
'required',
'integer',
Rule::exists(Unidade::class, 'id'),
function ($attribute, $value, $fail) {
if (!Unidade::find($value)->is_almoxarifado) {
$fail("O campo {$attribute} não é um almoxarifado.");
}
},
function ($attribute, $value, $fail) {
if (is_null(Unidade::find($value)->conectasus_centro_custo_id)) {
$fail("O campo {$attribute} não está vinculado com um centro de custo do ConectaSUS.");
}
},
],
'unidade_id' => [
'bail',
'integer',
Rule::exists(Unidade::class, 'id'),
function ($attribute, $value, $fail) {
if (is_null(Unidade::find($value)->conectasus_centro_custo_id)) {
$fail("O campo {$attribute} não está vinculado com um centro de custo do ConectaSUS.");
}
},
],
'is_estornada' => [
'string',
Rule::in('true', 'false'),
]
]);
$dataInicial = Carbon::create($request->data_inicial);
$dataFinal = Carbon::create($request->data_final);
if ($dataInicial->diff($dataFinal)->days > self::LIMITE_DIAS_PERIODO_BUSCA) {
throw new InvalidSearchPeriodException();
}
}
}

View File

@@ -0,0 +1,268 @@
<?php
namespace App\Services\WebService\Almoxarifado\Cliente;
use App\Exceptions\WebService\Almoxarifado\Cliente\Unidade\CannotDeleteUnidadeException;
use App\Exceptions\WebService\Almoxarifado\Cliente\Unidade\UnidadeNotFoundException;
use App\Models\Cadastro\Estabelecimento\CentroCusto as CadastroCentroCusto;
use App\Models\Cadastro\Estabelecimento\Unidade as CadastroUnidade;
use App\Models\WebService\Almoxarifado\Cliente\Unidade;
use App\Services\Service;
use App\Utils\DataUtil;
use Illuminate\Support\Facades\DB;
use Illuminate\Validation\Rule;
class UnidadeService extends Service
{
public static function list($request)
{
switch ($request->listar) {
case 'infraestruturas': {
return self::getInfraestruturas($request->unidade_id);
}
case 'centros-custo': {
return self::getCentrosCusto($request->infraestrutura_id);
}
}
}
public static function index($request)
{
self::validateIndex($request);
$unidades = DB::table('web_service_almoxarifado_cliente_unidade AS unidade')
->when(DataUtil::isStringBoolean($request->query('is_almoxarifado')), fn ($q) => $q
->where(
'unidade.is_almoxarifado',
DataUtil::getBooleanValueFromStringBoolean($request->query('is_almoxarifado'))
)
)
->select([
'unidade.id',
'unidade.conectasus_centro_custo_id',
'unidade.nome',
'unidade.cnes',
'unidade.is_almoxarifado',
])
->orderBy('unidade.nome')
->get();
$unidades->each(function ($unidade) {
$unidade->is_almoxarifado = (bool) $unidade->is_almoxarifado;
});
return $unidades;
}
private static function validateIndex($request)
{
$request->validate([
'is_almoxarifado' => [
'string',
Rule::in('true', 'false'),
],
]);
}
public static function create()
{
return [
'form' => self::getFormData(),
'model' => [
'conectasus_unidade_id' => null,
'conectasus_infraestrutura_id' => null,
'conectasus_centro_custo_id' => null,
'nome' => null,
'cnes' => null,
'is_almoxarifado' => false,
],
];
}
public static function store($request)
{
self::validate($request);
return Unidade::create(self::getUnidadeData($request))->fresh();
}
public static function show($id)
{
return self::getUnidadeModel($id);
}
public static function edit($id)
{
$unidade = self::getUnidadeModel($id);
return [
'form' => self::getFormData($unidade),
'model' => [
'conectasus_unidade_id' => $unidade->conectasusCentroCusto->infraestrutura->unidade_id ?? null,
'conectasus_infraestrutura_id' => $unidade->conectasusCentroCusto->infraestrutura_id ?? null,
'conectasus_centro_custo_id' => $unidade->conectasus_centro_custo_id,
'nome' => $unidade->nome,
'cnes' => $unidade->cnes,
'is_almoxarifado' => $unidade->is_almoxarifado,
],
];
}
private static function getFormData($unidade = null)
{
$conectaSusInfraestruturas = [];
$conectaSusCentrosCusto = [];
if (isset($unidade->conectasus_centro_custo_id)) {
$conectaSusInfraestruturas = self::getInfraestruturas(
$unidade->conectasusCentroCusto->infraestrutura->unidade_id
);
$conectaSusCentrosCusto = self::getCentrosCusto($unidade->conectasusCentroCusto->infraestrutura_id);
}
return [
'conectasus_unidades' => CadastroUnidade::orderBy('nome_fantasia')->get(['id', 'nome_fantasia']),
'conectasus_infraestruturas' => $conectaSusInfraestruturas,
'conectasus_centros_custo' => $conectaSusCentrosCusto,
];
}
private static function getInfraestruturas($unidadeId)
{
return DB::table('cadastro_infraestrutura AS infraestrutura')
->join('cadastro_unidade AS unidade', 'unidade.id', 'infraestrutura.unidade_id')
->whereNull('infraestrutura.deleted_at')
->where('infraestrutura.unidade_id', $unidadeId)
->orderBy('infraestrutura.nome')
->select([
'infraestrutura.id',
DB::raw("COALESCE(infraestrutura.nome, unidade.nome_fantasia) AS nome"),
])
->get();
}
private static function getCentrosCusto($infraestruturaId)
{
return DB::table('cadastro_centro_custo AS centro_custo')
->join('cadastro_setor AS setor', 'setor.id', 'centro_custo.setor_id')
->whereNull('centro_custo.deleted_at')
->where('centro_custo.infraestrutura_id', $infraestruturaId)
->orderBy('setor.nome')
->select([
'centro_custo.id',
'setor.nome AS setor_nome',
])
->get();
}
public static function update($request, $id)
{
$unidade = self::getUnidadeModel($id);
self::validate($request);
return tap($unidade)->update(self::getUnidadeData($request))->fresh();
}
private static function getUnidadeData($request)
{
return $request->only(['conectasus_centro_custo_id', 'nome', 'cnes', 'is_almoxarifado']);
}
public static function destroy($id)
{
$unidade = self::getUnidadeModel($id);
if ($unidade->entradas()->exists()) {
throw new CannotDeleteUnidadeException();
}
$unidade->delete();
}
public static function datatable()
{
return DB::table('web_service_almoxarifado_cliente_unidade AS unidade')
->leftJoin(
'cadastro_centro_custo AS conectasus_centro_custo',
'conectasus_centro_custo.id',
'unidade.conectasus_centro_custo_id'
)
->leftJoin(
'cadastro_setor AS conectasus_setor',
'conectasus_setor.id',
'conectasus_centro_custo.setor_id'
)
->leftJoin(
'cadastro_infraestrutura AS conectasus_infraestrutura',
'conectasus_infraestrutura.id',
'conectasus_centro_custo.infraestrutura_id'
)
->leftJoin(
'cadastro_unidade AS conectasus_unidade',
'conectasus_unidade.id',
'conectasus_infraestrutura.unidade_id'
)
->select([
'unidade.id',
'unidade.nome',
'unidade.cnes',
DB::raw("CONCAT(
conectasus_unidade.nome_fantasia,
IF(conectasus_infraestrutura.nome IS NOT NULL,
CONCAT(' - ', conectasus_infraestrutura.nome),
''
),
' - ',
conectasus_setor.nome
) AS conectasus_centro_custo_descricao"),
DB::raw("IF(unidade.is_almoxarifado, 'SIM', 'NÃO') AS is_almoxarifado"),
]);
}
private static function validate($request)
{
$request->validate([
'conectasus_centro_custo_id' => [
'nullable',
'present',
'integer',
Rule::exists(CadastroCentroCusto::class, 'id'),
],
'nome' => [
'required',
'string',
'between:3,100',
Rule::unique(Unidade::class, 'nome')->ignore($request->route('id')),
],
'cnes' => [
'nullable',
'present',
'digits:7',
],
'is_almoxarifado' => [
'required',
'boolean',
],
]);
}
private static function getUnidadeModel($id)
{
$unidade = Unidade::find($id);
if (is_null($unidade)) {
throw new UnidadeNotFoundException();
}
return $unidade;
}
}

View File

@@ -0,0 +1,134 @@
<?php
namespace App\Services\WebService\Almoxarifado\ConectaSus;
use App\Exceptions\WebService\Almoxarifado\ConectaSus\CentroCustoNotFoundException;
use App\Models\Cadastro\Estabelecimento\CentroCusto;
use App\Services\Service;
use App\Utils\DataUtil;
use Illuminate\Support\Facades\DB;
use Illuminate\Validation\Rule;
class CentroCustoService extends Service
{
public static function index($request)
{
self::validateIndex($request);
$centrosCusto = collect();
DB::table('cadastro_centro_custo AS centro_custo')
->join('cadastro_setor AS setor', 'setor.id', 'centro_custo.setor_id')
->join('cadastro_infraestrutura AS infraestrutura', 'infraestrutura.id', 'centro_custo.infraestrutura_id')
->join('cadastro_unidade AS unidade', 'unidade.id', 'infraestrutura.unidade_id')
->whereNull('centro_custo.deleted_at')
->when(DataUtil::isStringBoolean($request->query('is_almoxarifado')), fn ($q) => $q
->when(DataUtil::isStringTrue($request->query('is_almoxarifado')),
fn ($q) => $q->whereExists(fn ($q) => $q
->selectRaw(1)
->from('almoxarifado_parametrizacao_controle_estoque_grupo AS controle_estoque_grupo')
->whereColumn('controle_estoque_grupo.centro_custo_id', 'centro_custo.id')
),
fn ($q) => $q->whereNotExists(fn ($q) => $q
->selectRaw(1)
->from('almoxarifado_parametrizacao_controle_estoque_grupo AS controle_estoque_grupo')
->whereColumn('controle_estoque_grupo.centro_custo_id', 'centro_custo.id')
)
)
)
->select([
'centro_custo.id',
'unidade.id as unidade_id',
'unidade.nome_fantasia AS unidade_nome',
'unidade.cnes AS unidade_cnes',
'infraestrutura.id as infraestrutura_id',
DB::raw("COALESCE(infraestrutura.nome, unidade.nome_fantasia) AS infraestrutura_nome"),
'setor.nome AS setor_nome',
])
->orderBy('unidade.nome_fantasia')
->orderByRaw("COALESCE(infraestrutura.nome, unidade.nome_fantasia)")
->orderBy('setor.nome')
->get()
->each(function ($centroCusto) use ($centrosCusto) {
$unidade = $centrosCusto->where('unidade_id', $centroCusto->unidade_id)->first();
if (is_null($unidade)) {
$unidade = (object) [
'unidade_id' => $centroCusto->unidade_id,
'unidade_nome' => $centroCusto->unidade_nome,
'unidade_cnes' => $centroCusto->unidade_cnes,
'locais_atendimento' => collect(),
];
$centrosCusto->push($unidade);
}
$infraestrutura = $unidade->locais_atendimento
->where('infraestrutura_id', $centroCusto->infraestrutura_id)
->first();
if (is_null($infraestrutura)) {
$infraestrutura = (object) [
'infraestrutura_id' => $centroCusto->infraestrutura_id,
'nome' => $centroCusto->infraestrutura_nome,
'setores' => collect(),
];
$unidade->locais_atendimento->push($infraestrutura);
}
$infraestrutura->setores->push((object) [
'centro_custo_id' => $centroCusto->id,
'nome' => $centroCusto->setor_nome,
]);
});
return tap($centrosCusto)->each(function ($centroCusto) {
unset($centroCusto->unidade_id);
$centroCusto->locais_atendimento->each(function ($localAtendimento) {
unset($localAtendimento->infraestrutura_id);
});
});
}
private static function validateIndex($request)
{
$request->validate([
'is_almoxarifado' => [
'string',
Rule::in('true', 'false'),
],
]);
}
public static function show($id)
{
$centroCusto = self::getCentroCustoModel($id);
return (object) [
'id' => $centroCusto->id,
'unidade_nome' => $centroCusto->infraestrutura->unidade->nome_fantasia,
'unidade_cnes' => $centroCusto->infraestrutura->unidade->cnes,
'local_atendimento_nome' => $centroCusto->infraestrutura->nome,
'setor_nome' => $centroCusto->setor->nome,
];
}
private static function getCentroCustoModel($id)
{
$centroCusto = CentroCusto::find($id);
if (is_null($centroCusto)) {
throw new CentroCustoNotFoundException();
}
return $centroCusto;
}
}

View File

@@ -0,0 +1,46 @@
<?php
namespace App\Services\WebService\Almoxarifado\ConectaSus;
use App\Exceptions\WebService\Almoxarifado\ConectaSus\FabricanteNotFoundException;
use App\Models\Cadastro\Fabricante\Fabricante;
use App\Services\Service;
use Illuminate\Support\Facades\DB;
class FabricanteService extends Service
{
public static function index()
{
return DB::table('cadastro_fabricante AS fabricante')
->select([
'fabricante.id',
'fabricante.nome',
'fabricante.cnpj',
])
->orderBy('fabricante.nome')
->get();
}
public static function show($id)
{
$fabricante = self::getFabricanteModel($id);
return (object) [
'id' => $fabricante->id,
'nome' => $fabricante->nome,
'cnpj' => $fabricante->cnpj,
];
}
private static function getFabricanteModel($id)
{
$fabricante = Fabricante::find($id);
if (is_null($fabricante)) {
throw new FabricanteNotFoundException();
}
return $fabricante;
}
}

View File

@@ -0,0 +1,46 @@
<?php
namespace App\Services\WebService\Almoxarifado\ConectaSus;
use App\Exceptions\WebService\Almoxarifado\ConectaSus\FornecedorNotFoundException;
use App\Models\Cadastro\Fornecedor\Fornecedor;
use App\Services\Service;
use Illuminate\Support\Facades\DB;
class FornecedorService extends Service
{
public static function index()
{
return DB::table('cadastro_fornecedor AS fornecedor')
->select([
'fornecedor.id',
'fornecedor.nome_fantasia AS nome',
'fornecedor.cnpj',
])
->orderBy('fornecedor.nome_fantasia')
->get();
}
public static function show($id)
{
$fornecedor = self::getFornecedorModel($id);
return (object) [
'id' => $fornecedor->id,
'nome' => $fornecedor->nome_fantasia,
'cnpj' => $fornecedor->cnpj,
];
}
private static function getFornecedorModel($id)
{
$fornecedor = Fornecedor::find($id);
if (is_null($fornecedor)) {
throw new FornecedorNotFoundException();
}
return $fornecedor;
}
}

View File

@@ -0,0 +1,67 @@
<?php
namespace App\Services\WebService\Almoxarifado\ConectaSus;
use App\Exceptions\WebService\Almoxarifado\ConectaSus\MaterialNotFoundException;
use App\Models\Cadastro\Material\Material;
use App\Services\Cadastro\Material\MaterialService as CadastroMaterialService;
use App\Services\Service;
use Illuminate\Support\Facades\DB;
class MaterialService extends Service
{
public static function index()
{
return DB::table('cadastro_material AS material')
->join(
'cadastro_apresentacao AS apresentacao',
'apresentacao.id',
'material.apresentacao_id'
)
->join(
'cadastro_unidade_medida as apresentacao_unidade_medida',
'apresentacao_unidade_medida.id',
'material.apresentacao_unidade_medida_id'
)
->whereNull('material.deleted_at')
->where('material.is_ativo', true)
->select([
'material.id',
'material.codigo_material AS codigo',
DB::raw(CadastroMaterialService::getDescricaoCompletaRaw(
'material',
'apresentacao',
'apresentacao_unidade_medida'
) . " AS descricao"),
])
->orderByRaw(CadastroMaterialService::getDescricaoCompletaRaw(
'material',
'apresentacao',
'apresentacao_unidade_medida'
))
->get();
}
public static function show($id)
{
$material = self::getMaterialModel($id);
return (object) [
'id' => $material->id,
'codigo' => $material->codigo_material,
'descricao' => $material->descricao_completa,
];
}
private static function getMaterialModel($id)
{
$material = Material::find($id);
if (is_null($material)) {
throw new MaterialNotFoundException();
}
return $material;
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,89 @@
<?php
namespace App\Services\WebService\Ambulatorio\ConectaSus;
use App\Exceptions\WebService\Ambulatorio\ConectaSus\PacienteNotFoundException;
use App\Models\Cadastro\SujeitoAtencao\Cidadao;
use App\Services\Service;
use Illuminate\Support\Facades\DB;
use Carbon\Carbon;
class PacienteService extends Service
{
public static function index()
{
return DB::table('cadastro_cidadao')
->leftJoin('cadastro_cidadao_telefone', function ($join) {
$join->on('cadastro_cidadao_telefone.cidadao_id', '=', 'cadastro_cidadao.id')
->where('cadastro_cidadao_telefone.principal', 1);
})
->leftJoin('cadastro_sexo', 'cadastro_sexo.id', 'cadastro_cidadao.sexo_id')
->leftJoin('cadastro_nacionalidade', 'cadastro_nacionalidade.id', 'cadastro_cidadao.nacionalidade_id')
->leftJoin('cadastro_raca_cor', 'cadastro_raca_cor.id', 'cadastro_cidadao.raca_cor_id')
->join('cadastro_paciente', 'cadastro_paciente.cidadao_id', 'cadastro_cidadao.id')
->leftJoin('cadastro_domicilio', 'cadastro_domicilio.id', 'cadastro_cidadao.domicilio_id')
->leftJoin('cadastro_endereco', 'cadastro_endereco.id', 'cadastro_domicilio.endereco_id')
->leftJoin('cadastro_logradouro', 'cadastro_logradouro.id', 'cadastro_endereco.logradouro_id')
->leftJoin('cadastro_logradouro_tipo', 'cadastro_logradouro_tipo.id', 'cadastro_logradouro.tipo_id')
->leftJoin('cadastro_bairro', 'cadastro_bairro.id', 'cadastro_logradouro.bairro_id')
->whereNull('cadastro_cidadao.deleted_at')
->select([
'cadastro_cidadao.cidadao_id',
'cadastro_paciente.id as paciente_id',
'cadastro_cidadao.nome AS name',
'cadastro_cidadao.cns',
'cadastro_cidadao.cpf',
'cadastro_cidadao.data_nascimento AS birthdate',
DB::raw("COALESCE(cadastro_cidadao_telefone.numero, '-') AS phone"),
'cadastro_sexo.descricao AS sex',
DB::raw("COALESCE(cadastro_cidadao.nome_mae, '-') AS motherName"),
DB::raw("COALESCE(cadastro_nacionalidade.descricao, '-') AS nationality"),
DB::raw("COALESCE(cadastro_raca_cor.descricao, '-') AS race"),
'cadastro_logradouro_tipo.descricao as type',
'cadastro_logradouro.nome as street',
'cadastro_endereco.numero as number',
'cadastro_bairro.nome as neighborhood',
'cadastro_logradouro.cep as zipCode'
])
->distinct()
->orderBy('cadastro_cidadao.nome')
->get();
}
public static function show($idPaciente)
{
$paciente = self::getPacienteModel($idPaciente);
return (object) [
'cidadao_id' => $paciente->cidadao_id,
'paciente_id' => $paciente->paciente->id,
'name' => $paciente->nome,
'cns' => $paciente->cns,
'cpf' => $paciente->cpf,
'birthdate' => Carbon::parse($paciente->data_nascimento)->format('Y/m/d'),
'phone' => $paciente->numero ?? '-',
'sex' => $paciente->sexo->descricao,
'motherName' => $paciente->nome_mae ?? '-',
'nationality' => $paciente->nacionalidade->descricao ?? '-',
'race' => $paciente->racaCor->descricao ?? '-',
'address' => [
'street' => $paciente->domicilio->endereco->logradouro->tipo_nome ?? '-',
'number' => $paciente->domicilio->endereco->numero ?? '-',
'neighborhood' => $paciente->domicilio->endereco->logradouro->bairro->nome ?? '-',
'zipCode' => $paciente->domicilio->endereco->logradouro->cep ?? '-',
]
];
}
private static function getPacienteModel($idPaciente)
{
$paciente = Cidadao::find($idPaciente);
if (is_null($paciente)) {
throw new PacienteNotFoundException();
}
return $paciente;
}
}

View File

@@ -0,0 +1,239 @@
<?php
namespace App\Services\WebService\Laboratorio\Cliente;
use App\Enums\WebService\Laboratorio\Cliente\PedidoStatus;
use App\Exceptions\WebService\Laboratorio\Cliente\Exame\CannotDeleteExameException;
use App\Exceptions\WebService\Laboratorio\Cliente\Exame\ExameNotFoundException;
use App\Models\Parametrizacao\Exame\Exame as CadastroExame;
use App\Models\WebService\Laboratorio\Cliente\Exame;
use App\Services\Service;
use Illuminate\Support\Facades\DB;
use Illuminate\Validation\Rule;
class ExameService extends Service
{
public static function index($laboratorioId)
{
$laboratorio = LaboratorioService::getLaboratorioModel($laboratorioId);
return DB::table('web_service_laboratorio_cliente_exame AS exame')
->where('exame.laboratorio_id', $laboratorio->id)
->select([
'exame.id',
'exame.conectasus_exame_id',
'exame.nome',
])
->orderBy('exame.nome')
->get();
}
public static function create()
{
return [
'form' => self::getFormData(),
'model' => [
'laboratorio_id' => null,
'conectasus_exame' => null,
'nome' => null,
],
];
}
public static function store($request, $laboratorioId)
{
$laboratorio = LaboratorioService::getLaboratorioModel($laboratorioId);
self::validate($request);
return Exame::create(self::getExameData($request, $laboratorio))->fresh();
}
public static function show($laboratorioId, $id)
{
$laboratorio = LaboratorioService::getLaboratorioModel($laboratorioId);
return self::getExameModel($id, $laboratorio);
}
public static function edit($id)
{
$exame = self::getExameModel($id);
return [
'form' => self::getFormData(),
'model' => [
'laboratorio_id' => $exame->laboratorio_id,
'conectasus_exame' => $exame->conectasusExame ? (object) [
'id' => $exame->conectasusExame->id,
'nome' => $exame->conectasusExame->nome,
] : null,
'nome' => $exame->nome,
],
];
}
private static function getFormData()
{
return [
'laboratorios' => self::getLaboratorios(),
];
}
private static function getLaboratorios()
{
return DB::table('web_service_laboratorio_cliente_laboratorio AS laboratorio')
->join(
'cadastro_infraestrutura AS conectasus_infraestrutura',
'conectasus_infraestrutura.id',
'laboratorio.conectasus_infraestrutura_id'
)
->join(
'cadastro_unidade AS conectasus_unidade',
'conectasus_unidade.id',
'conectasus_infraestrutura.unidade_id'
)
->select([
'laboratorio.id',
DB::raw("CONCAT(
conectasus_unidade.nome_fantasia,
IF(conectasus_infraestrutura.nome IS NOT NULL,
CONCAT(' - ', conectasus_infraestrutura.nome),
''
)
) AS descricao")
])
->orderByRaw("CONCAT(
conectasus_unidade.nome_fantasia,
IF(conectasus_infraestrutura.nome IS NOT NULL,
CONCAT(' - ', conectasus_infraestrutura.nome),
''
)
)")
->get();
}
public static function update($request, $laboratorioId, $id)
{
$laboratorio = LaboratorioService::getLaboratorioModel($laboratorioId);
$exame = self::getExameModel($id, $laboratorio);
self::validate($request);
return tap($exame)->update(self::getExameData($request, $laboratorio))->fresh();
}
private static function getExameData($request, $laboratorio)
{
$data = $request->only(['conectasus_exame_id', 'nome']);
$data['laboratorio_id'] = $laboratorio->id;
return $data;
}
public static function destroy($laboratorioId, $id)
{
$laboratorio = LaboratorioService::getLaboratorioModel($laboratorioId);
$exame = self::getExameModel($id, $laboratorio);
if (self::hasPedidoEmProcessamento($exame, $laboratorio)) {
throw new CannotDeleteExameException();
}
$exame->delete();
}
private static function hasPedidoEmProcessamento($exame, $laboratorio)
{
return $exame->conectasusExame()
->whereHas('agendamentoExameLaboratorial', fn ($q) => $q
->whereHas('agendamento', fn ($q) => $q
->where('laboratorio_infraestrutura_id', $laboratorio->conectasus_infraestrutura_id)
->where('web_service_laboratorio_cliente_pedido_status_id', '<>', PedidoStatus::AGUARDANDO_PROCESSAMENTO)
)
)
->exists();
}
public static function datatable()
{
return DB::table('web_service_laboratorio_cliente_exame AS exame')
->join(
'web_service_laboratorio_cliente_laboratorio AS laboratorio',
'laboratorio.id',
'exame.laboratorio_id'
)
->join(
'cadastro_infraestrutura AS conectasus_infraestrutura',
'conectasus_infraestrutura.id',
'laboratorio.conectasus_infraestrutura_id'
)
->join(
'cadastro_unidade AS conectasus_unidade',
'conectasus_unidade.id',
'conectasus_infraestrutura.unidade_id'
)
->leftJoin(
'parametrizacao_exame AS conectasus_exame',
'conectasus_exame.id',
'exame.conectasus_exame_id'
)
->select([
'exame.id',
'exame.nome',
'conectasus_exame.nome as conectasus_exame_nome',
'exame.laboratorio_id',
DB::raw("CONCAT(
conectasus_unidade.nome_fantasia,
IF(conectasus_infraestrutura.nome IS NOT NULL,
CONCAT(' - ', conectasus_infraestrutura.nome),
''
)
) AS laboratorio_descricao")
]);
}
private static function validate($request)
{
$request->validate(
[
'conectasus_exame_id' => [
'nullable',
'present',
'integer',
Rule::exists(CadastroExame::class, 'id'),
Rule::unique(Exame::class, 'conectasus_exame_id')
->where('laboratorio_id', $request->route('laboratorioId'))
->ignore($request->route('id')),
],
'nome' => [
'required',
'string',
'between:3,200',
Rule::unique(Exame::class, 'nome')
->where('laboratorio_id', $request->route('laboratorioId'))
->ignore($request->route('id')),
],
],
[
'conectasus_exame_id.exists' => 'O campo Exame (ConectaSUS) selecionado é inválido.',
'conectasus_exame_id.unique' => 'O campo Exame (ConectaSUS) já está em uso para este laboratório.',
]
);
}
private static function getExameModel($id, $laboratorio = null)
{
$exame = Exame::when($laboratorio, fn ($q) => $q->where('laboratorio_id', $laboratorio->id))
->where('id', $id)
->first();
if (is_null($exame)) {
throw new ExameNotFoundException();
}
return $exame;
}
}

View File

@@ -0,0 +1,150 @@
<?php
namespace App\Services\WebService\Laboratorio\Cliente;
use App\Exceptions\WebService\Laboratorio\Cliente\Laboratorio\CannotDeleteLaboratorioException;
use App\Exceptions\WebService\Laboratorio\Cliente\Laboratorio\LaboratorioNotFoundException;
use App\Models\Cadastro\Estabelecimento\Infraestrutura as CadastroInfraestrutura;
use App\Models\WebService\Laboratorio\Cliente\Laboratorio;
use App\Services\Service;
use Illuminate\Support\Facades\DB;
use Illuminate\Validation\Rule;
class LaboratorioService extends Service
{
public static function list()
{
switch (request()->listar) {
case 'conectasus-infraestruturas': {
return [
'conectasus_infraestruturas' => self::getConectaSusInfraestruturas(request()->conectasus_unidade_id),
];
}
}
}
public static function create()
{
return [
'form' => self::getFormData(),
'model' => [
'conectasus_unidade_id' => null,
'conectasus_infraestrutura_id' => null,
],
];
}
public static function store($request)
{
self::validate($request);
return Laboratorio::create(self::getLaboratorioData($request))->fresh();
}
private static function getFormData()
{
return [
'conectasus_unidades' => self::getConectaSusUnidades(),
'conectasus_infraestruturas' => collect(),
];
}
private static function getConectaSusUnidades()
{
return DB::table('cadastro_unidade AS unidade')
->select([
'unidade.id',
'unidade.nome_fantasia'
])
->whereNull('unidade.deleted_at')
->whereExists(fn ($q) => $q
->selectRaw(1)
->from('exame_laboratorial_parametrizacao_unidade AS parametrizacao_unidade')
->whereColumn('parametrizacao_unidade.unidade_id', 'unidade.id')
->where('parametrizacao_unidade.laboratorio', true)
)
->orderBy('unidade.nome_fantasia')
->get();
}
private static function getConectaSusInfraestruturas($unidadeId)
{
return DB::table('cadastro_infraestrutura AS infraestrutura')
->join('cadastro_unidade AS unidade', 'unidade.id', 'infraestrutura.unidade_id')
->select([
'infraestrutura.id',
DB::raw("COALESCE(infraestrutura.nome, unidade.nome_fantasia) AS nome"),
])
->whereNull('infraestrutura.deleted_at')
->where('infraestrutura.unidade_id', $unidadeId)
->whereExists(fn ($q) => $q
->selectRaw(1)
->from('exame_laboratorial_parametrizacao_unidade AS parametrizacao_unidade')
->whereColumn('parametrizacao_unidade.infraestrutura_id', 'infraestrutura.id')
->where('parametrizacao_unidade.laboratorio', true)
)
->orderByRaw("COALESCE(infraestrutura.nome, unidade.nome_fantasia)")
->get();
}
private static function getLaboratorioData($request)
{
return $request->only(['conectasus_infraestrutura_id']);
}
public static function destroy($id)
{
$laboratorio = self::getLaboratorioModel($id);
if ($laboratorio->exames()->exists()) {
throw new CannotDeleteLaboratorioException();
}
$laboratorio->delete();
}
public static function datatable()
{
return DB::table('web_service_laboratorio_cliente_laboratorio AS laboratorio')
->join(
'cadastro_infraestrutura AS conectasus_infraestrutura',
'conectasus_infraestrutura.id',
'laboratorio.conectasus_infraestrutura_id'
)
->join(
'cadastro_unidade AS conectasus_unidade',
'conectasus_unidade.id',
'conectasus_infraestrutura.unidade_id'
)
->select([
'laboratorio.id',
'conectasus_unidade.nome_fantasia AS conectasus_unidade_nome_fantasia',
DB::raw("COALESCE(conectasus_infraestrutura.nome, conectasus_unidade.nome_fantasia) AS conectasus_infraestrutura_nome"),
]);
}
private static function validate($request)
{
$request->validate([
'conectasus_infraestrutura_id' => [
'required',
'integer',
Rule::exists(CadastroInfraestrutura::class, 'id'),
Rule::unique(Laboratorio::class, 'conectasus_infraestrutura_id'),
],
]);
}
public static function getLaboratorioModel($id)
{
$laboratorio = Laboratorio::find($id);
if (is_null($laboratorio)) {
throw new LaboratorioNotFoundException();
}
return $laboratorio;
}
}

View File

@@ -0,0 +1,552 @@
<?php
namespace App\Services\WebService\Laboratorio\Cliente;
use App\Enums\Cadastro\SujeitoAtencao\Sexo;
use App\Enums\Cadastro\SujeitoAtencao\TipoRegistroUsuario;
use App\Enums\ExameLaboratorial\Acao;
use App\Enums\ExameLaboratorial\ParametrizacaoWebServiceTipo;
use App\Enums\ExameLaboratorial\StatusAgendamento;
use App\Enums\WebService\Laboratorio\Cliente\PedidoStatus as PedidoStatusEnum;
use App\Exceptions\WebService\Laboratorio\Cliente\Pedido\CannotChangeStatusException;
use App\Exceptions\WebService\Laboratorio\Cliente\Pedido\IncompleteExameParametrizationException;
use App\Exceptions\WebService\Laboratorio\Cliente\Pedido\PedidoNotFoundException;
use App\Models\ExameLaboratorial\AgendamentoExame\Agendamento as ExameLaboratorialAgendamento;
use App\Models\ExameLaboratorial\AgendamentoExame\AgendamentoLaudo;
use App\Models\ExameLaboratorial\Parametrizacao\WebService as ParametrizacaoWebService;
use App\Models\WebService\Laboratorio\Cliente\PedidoMovimentacao;
use App\Models\WebService\Laboratorio\Cliente\PedidoStatus;
use App\Services\ExameLaboratorial\AgendamentoExameHistoricoService;
use App\Services\Service;
use Carbon\Carbon;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Storage;
use Illuminate\Validation\Rule;
class PedidoService extends Service
{
public static function index($request, $laboratorioId)
{
$laboratorio = LaboratorioService::getLaboratorioModel($laboratorioId);
self::validateIndex($request);
return self::getPedidos($laboratorio, (object) $request->all());
}
private static function validateIndex($request)
{
return $request->validate([
'data_solicitacao' => [
'nullable',
'required_without:data_coleta',
'date_format:Y-m-d',
'before_or_equal:' . Carbon::now()->format('Y-m-d'),
],
'data_coleta' => [
'nullable',
'required_without:data_solicitacao',
'date_format:Y-m-d',
],
'nome_paciente' => [
'nullable',
'string',
'max:150',
],
'status_id' => [
'nullable',
'integer',
Rule::exists(PedidoStatus::class, 'id'),
],
]);
}
public static function show($laboratorioId, $id)
{
$laboratorio = LaboratorioService::getLaboratorioModel($laboratorioId);
$pedido = self::getPedidoModel($laboratorio, $id);
$pedidos = self::getPedidos($laboratorio, (object) ['pedido_id' => $pedido->id]);
if ($pedidos->isEmpty()) {
throw new PedidoNotFoundException();
}
return $pedidos->first();
}
private static function getPedidos($laboratorio, $params)
{
$isIntegracaoParcial = (ParametrizacaoWebService::first()->tipo_id ?? null) === ParametrizacaoWebServiceTipo::PARCIAL;
$pedidos = DB::table('exame_laboratorial_agendamento AS agendamento')
->join('cadastro_paciente AS paciente', 'paciente.id', 'agendamento.paciente_id')
->join('cadastro_cidadao AS paciente_cidadao', 'paciente_cidadao.id', 'paciente.cidadao_id')
->join('cadastro_sexo AS paciente_sexo', 'paciente_sexo.id', 'paciente_cidadao.sexo_id')
->join(
'cadastro_infraestrutura AS infraestrutura_solicitante',
'infraestrutura_solicitante.id',
'agendamento.infraestrutura_id'
)
->join(
'cadastro_unidade AS unidade_solicitante',
'unidade_solicitante.id',
'infraestrutura_solicitante.unidade_id'
)
->join('cadastro_usuario AS usuario_solicitante', 'usuario_solicitante.id', 'agendamento.medico_id')
->join(
'cadastro_cidadao AS usuario_cidadao_solicitante',
'usuario_cidadao_solicitante.id',
'usuario_solicitante.cidadao_id'
)
->leftJoin('cadastro_cidadao_telefone AS paciente_telefone', fn ($q) => $q
->on('paciente_telefone.cidadao_id', 'paciente_cidadao.id')
->where('paciente_telefone.id', fn ($q) => $q
->select('paciente_telefone2.id')
->from('cadastro_cidadao_telefone AS paciente_telefone2')
->whereColumn('paciente_telefone2.cidadao_id', 'paciente_cidadao.id')
->where('paciente_telefone2.principal', true)
->limit(1)
)
)
->leftJoin(
'cadastro_domicilio AS paciente_domicilio',
'paciente_domicilio.id',
'paciente_cidadao.domicilio_id'
)
->leftJoin(
'cadastro_endereco AS paciente_endereco',
'paciente_endereco.id',
'paciente_domicilio.endereco_id'
)
->leftJoin(
'cadastro_logradouro AS paciente_logradouro',
'paciente_logradouro.id',
'paciente_endereco.logradouro_id'
)
->leftJoin(
'cadastro_logradouro_tipo AS paciente_logradouro_tipo',
'paciente_logradouro_tipo.id',
'paciente_logradouro.tipo_id'
)
->leftJoin(
'cadastro_bairro AS paciente_logradouro_bairro',
'paciente_logradouro_bairro.id',
'paciente_logradouro.bairro_id'
)
->leftJoin(
'intranet.cadastro_municipio AS paciente_municipio',
'paciente_municipio.id',
'paciente_logradouro.municipio_id'
)
->leftJoin(
'cadastro_usuario_registro_tipo AS usuario_registro_tipo',
'usuario_registro_tipo.id',
'usuario_solicitante.registro_tipo_id'
)
->where('agendamento.laboratorio_infraestrutura_id', $laboratorio->conectasus_infraestrutura_id)
->where(fn ($q) => $q
->when($params->data_solicitacao ?? null, fn ($q, $data) => $q
->orWhereDate('agendamento.created_at', $data)
)
->when($params->data_coleta ?? null, fn ($q, $data) => $q
->orWhere('agendamento.data', $data)
)
)
->when($params->pedido_id ?? null, fn ($q, $id) => $q->where('agendamento.id', $id))
->when($params->nome_paciente ?? null, fn ($q, $nome) => $q
->where('paciente_cidadao.nome', 'LIKE', "{$nome}%")
)
->when($params->status_id ?? null, fn ($q, $id) => $q
->where('agendamento.web_service_laboratorio_cliente_pedido_status_id', $id)
)
->when($isIntegracaoParcial, fn ($q) => $q
->whereNotExists(fn ($q) => $q
->selectRaw(1)
->from('exame_laboratorial_agendamento_exame AS agendamento_exame')
->whereColumn('agendamento_exame.agendamento_id', 'agendamento.id')
->whereNull('agendamento_exame.data_coleta')
)
)
->select(
'agendamento.id',
'agendamento.agendamento_numero as numero_agendamento',
'agendamento.web_service_laboratorio_cliente_pedido_status_id AS status_id',
DB::raw("CAST(agendamento.created_at AS DATE) AS data_solicitacao"),
'paciente_cidadao.nome AS paciente_nome',
'paciente_cidadao.data_nascimento AS paciente_data_nascimento',
DB::raw("TIMESTAMPDIFF(YEAR, paciente_cidadao.data_nascimento, NOW()) AS paciente_idade"),
'paciente_sexo.id AS paciente_sexo_id',
'paciente_sexo.descricao AS paciente_sexo_descricao',
DB::raw("LPAD(paciente.prontuario, 7, '0') AS paciente_prontuario"),
'agendamento.gestante AS paciente_gestante',
'agendamento.ultima_menstruacao AS paciente_data_ultima_menstruacao',
'paciente_telefone.numero AS paciente_telefone',
DB::raw("CONCAT(paciente_logradouro_tipo.descricao, ' ', paciente_logradouro.nome) AS paciente_logradouro_descricao"),
'paciente_endereco.numero AS paciente_logradouro_numero',
'paciente_logradouro_bairro.nome AS paciente_bairro_nome',
'paciente_logradouro.cep AS paciente_cep',
'paciente_municipio.nome AS paciente_municipio_nome',
'usuario_cidadao_solicitante.nome AS medico_solicitante_nome',
DB::raw("IF(
usuario_solicitante.registro_tipo_id = " . TipoRegistroUsuario::OUTRO . ",
registro_tipo_outro,
usuario_registro_tipo.sigla
) AS conselho_profissional_tipo_sigla"),
'usuario_solicitante.registro_numero AS conselho_profissional_numero',
'unidade_solicitante.id AS unidade_solicitante_id',
'unidade_solicitante.nome_fantasia AS unidade_solicitante_nome_fantasia',
'infraestrutura_solicitante.id AS local_atendimento_solicitante_id',
DB::raw("COALESCE(infraestrutura_solicitante.nome, unidade_solicitante.nome_fantasia) AS local_atendimento_solicitante_nome")
)
->orderBy('agendamento.created_at')
->get();
$pedidos->each(function ($pedido) use ($laboratorio) {
$pedido->itens = self::getPedidoItens($pedido, $laboratorio);
if ($pedido->paciente_sexo_id !== Sexo::FEMININO) {
unset($pedido->paciente_gestante, $pedido->paciente_data_ultima_menstruacao);
}
else {
$pedido->paciente_gestante = (bool) $pedido->paciente_gestante;
}
self::setMovimentacaoFields($pedido);
unset($pedido->paciente_sexo_id);
});
return $pedidos;
}
private static function getPedidoItens($pedido, $laboratorio)
{
return DB::table('exame_laboratorial_agendamento_exame AS agendamento_exame')
->join(
'exame_laboratorial_agendamento AS agendamento',
'agendamento.id',
'agendamento_exame.agendamento_id'
)
->leftJoin('web_service_laboratorio_cliente_exame AS cliente_exame', fn ($q) => $q
->on('cliente_exame.conectasus_exame_id', 'agendamento_exame.exame_id')
->where('cliente_exame.laboratorio_id', $laboratorio->id)
)
->where('agendamento_exame.agendamento_id', $pedido->id)
->select(
'agendamento_exame.exame_id AS conectasus_exame_id',
'cliente_exame.id AS cliente_exame_id',
'agendamento.data AS data_coleta'
)
->orderBy('agendamento_exame.data_coleta')
->get();
}
private static function setMovimentacaoFields($pedido)
{
$pedido->processado_em = null;
$pedido->realizado_em = null;
$pedido->cancelado_em = null;
$pedido->motivo_cancelamento = null;
self::getPedidoMovimentacoes($pedido)->each(function ($movimentacao) use ($pedido) {
if ($movimentacao->status_id === PedidoStatusEnum::PROCESSANDO) {
$pedido->processado_em = $movimentacao->movimentado_em;
}
else if ($movimentacao->status_id === PedidoStatusEnum::REALIZADO) {
$pedido->realizado_em = $movimentacao->movimentado_em;
}
else if ($movimentacao->status_id === PedidoStatusEnum::CANCELADO_PELO_LABORATORIO) {
$pedido->cancelado_em = $movimentacao->movimentado_em;
$pedido->motivo_cancelamento = $movimentacao->motivo;
}
});
}
private static function getPedidoMovimentacoes($pedido)
{
return DB::table('web_service_laboratorio_cliente_pedido_movimentacao AS movimentacao')
->where('movimentacao.conectasus_exame_laboratorial_agendamento_id', $pedido->id)
->select(
'movimentacao.status_id',
'movimentacao.motivo',
'movimentacao.movimentado_em',
)
->orderBy('movimentacao.movimentado_em')
->get();
}
public static function process($laboratorioId, $id)
{
$laboratorio = LaboratorioService::getLaboratorioModel($laboratorioId);
$pedido = self::getPedidoModel($laboratorio, $id);
if ($pedido->web_service_laboratorio_cliente_pedido_status_id !== PedidoStatusEnum::AGUARDANDO_PROCESSAMENTO) {
$mensagemStatus = null;
if ($pedido->web_service_laboratorio_cliente_pedido_status_id === PedidoStatusEnum::CANCELADO_PELO_LABORATORIO) {
$mensagemStatus = 'O status não pode ser alterado pois o pedido foi cancelado pelo laboratório.';
}
else if ($pedido->web_service_laboratorio_cliente_pedido_status_id === PedidoStatusEnum::PROCESSANDO) {
$mensagemStatus = 'O status não pode ser alterado pois o pedido já está em processamento.';
}
else if ($pedido->web_service_laboratorio_cliente_pedido_status_id === PedidoStatusEnum::REALIZADO) {
$mensagemStatus = 'O status não pode ser alterado pois o pedido já está realizado.';
}
throw new CannotChangeStatusException($mensagemStatus);
}
else if (self::vinculoEntreExamesConectasusClienteIncompleto($laboratorio, $pedido)) {
throw new IncompleteExameParametrizationException();
}
DB::transaction(function () use ($pedido) {
$pedido->update(['web_service_laboratorio_cliente_pedido_status_id' => PedidoStatusEnum::PROCESSANDO]);
$pedido->refresh();
self::saveMovimentacao($pedido);
});
}
private static function vinculoEntreExamesConectasusClienteIncompleto($laboratorio, $pedido)
{
return $pedido->agendamentoExame()
->whereHas('exame', fn ($q) => $q
->whereDoesntHave('webServiceLaboratorioClienteExame', fn ($q) => $q
->where('laboratorio_id', $laboratorio->id)
)
)
->exists();
}
public static function cancel($request, $laboratorioId, $id)
{
$laboratorio = LaboratorioService::getLaboratorioModel($laboratorioId);
$pedido = self::getPedidoModel($laboratorio, $id);
self::validateCancel($request);
if ($pedido->web_service_laboratorio_cliente_pedido_status_id !== PedidoStatusEnum::PROCESSANDO) {
$mensagemStatus = null;
if ($pedido->web_service_laboratorio_cliente_pedido_status_id === PedidoStatusEnum::AGUARDANDO_PROCESSAMENTO) {
$mensagemStatus = 'O status não pode ser alterado pois o pedido ainda não está em processamento.';
}
else if ($pedido->web_service_laboratorio_cliente_pedido_status_id === PedidoStatusEnum::CANCELADO_PELO_LABORATORIO) {
$mensagemStatus = 'O status não pode ser alterado pois o pedido já foi cancelado pelo laboratório.';
}
else if ($pedido->web_service_laboratorio_cliente_pedido_status_id === PedidoStatusEnum::REALIZADO) {
$mensagemStatus = 'O status não pode ser alterado pois o pedido já está realizado.';
}
throw new CannotChangeStatusException($mensagemStatus);
}
DB::transaction(function () use ($request, $pedido) {
$pedido->update(['web_service_laboratorio_cliente_pedido_status_id' => PedidoStatusEnum::CANCELADO_PELO_LABORATORIO]);
$pedido->refresh();
self::saveMovimentacao($pedido, ['motivo' => $request->motivo]);
});
}
private static function validateCancel($request)
{
$request->validate([
'motivo' => [
'required',
'string',
'between:3,500',
],
]);
}
public static function storeResult($request, $laboratorioId, $id)
{
$laboratorio = LaboratorioService::getLaboratorioModel($laboratorioId);
$pedido = self::getPedidoModel($laboratorio, $id);
self::validateStoreResult($request);
$allowedStatus = collect([
PedidoStatusEnum::PROCESSANDO,
PedidoStatusEnum::REALIZADO
]);
if (!$allowedStatus->contains($pedido->web_service_laboratorio_cliente_pedido_status_id)) {
$mensagemStatus = null;
if ($pedido->web_service_laboratorio_cliente_pedido_status_id === PedidoStatusEnum::AGUARDANDO_PROCESSAMENTO) {
$mensagemStatus = 'O status não pode ser alterado pois o pedido ainda não está em processamento.';
}
else if ($pedido->web_service_laboratorio_cliente_pedido_status_id === PedidoStatusEnum::CANCELADO_PELO_LABORATORIO) {
$mensagemStatus = 'O status não pode ser alterado pois o pedido já foi cancelado pelo laboratório.';
}
throw new CannotChangeStatusException($mensagemStatus);
}
else if ($pedido->data > Carbon::now()) {
throw new CannotChangeStatusException('O status não pode ser alterado pois a data de coleta do pedido é maior que a data atual.');
}
else if ($pedido->web_service_laboratorio_cliente_pedido_status_id === PedidoStatusEnum::PROCESSANDO && self::hasExameAgendado($pedido)) {
throw new CannotChangeStatusException('O status não pode ser alterado pois o pedido está em processamento e existe um ou mais exames com o status agendado.');
}
DB::transaction(function () use ($request, $pedido) {
$path = 'exame-laboratorial' . DIRECTORY_SEPARATOR . 'laudos' . DIRECTORY_SEPARATOR . app('config')->get('database.default');
$laudo = AgendamentoLaudo::where('agendamento_id', $pedido->id)->where('is_enviado_webservice', true)->first();
if ($laudo) {
if (is_null($laudo->url)) {
if (Storage::disk('local')->exists($path . DIRECTORY_SEPARATOR . $laudo->arquivo)){
Storage::disk('local')->delete($path . DIRECTORY_SEPARATOR . $laudo->arquivo);
}
}
$laudo->delete();
}
$ordem = AgendamentoLaudo::where('agendamento_id', $pedido->id)->max('ordem') + 1;
if (isset($request->url)) {
$urlInfo = pathinfo(parse_url($request->url, PHP_URL_PATH));
AgendamentoLaudo::create([
'agendamento_id' => $pedido->id,
'arquivo' => isset($urlInfo['filename']) && isset($urlInfo['extension'])
? "{$urlInfo['filename']}.{$urlInfo['extension']}"
: $pedido->id . ($ordem === 1 ? '' : "_{$ordem}"),
'url' => $request->url,
'ordem' => $ordem,
'is_enviado_webservice' => true
]);
}
else {
$base64Decoded = str_contains($request->base64, ',')
? base64_decode(explode(',', $request->base64)[1], true)
: base64_decode($request->base64, true);
$finfo = finfo_open();
$mime = finfo_buffer($finfo, $base64Decoded, FILEINFO_MIME_TYPE);
finfo_close($finfo);
$extension = explode('/', $mime)[1];
$fileName = $pedido->id . ($ordem === 1 ? '' : "_{$ordem}") . ".{$extension}";
Storage::disk('local')->put($path . DIRECTORY_SEPARATOR . $fileName, $base64Decoded);
AgendamentoLaudo::create([
'agendamento_id' => $pedido->id,
'arquivo' => $fileName,
'ordem' => $ordem,
'is_enviado_webservice' => true
]);
}
if ($pedido->web_service_laboratorio_cliente_pedido_status_id !== PedidoStatusEnum::REALIZADO) {
$pedido->agendamentoExame->each(function ($agendamentoExame) {
if ($agendamentoExame->status_id === StatusAgendamento::REALIZADO) {
$agendamentoExame->update(['status_id' => StatusAgendamento::ASSINADO]);
$agendamentoExame->refresh();
AgendamentoExameHistoricoService::store($agendamentoExame, $agendamentoExame->agendamento, Acao::ALTERACAO);
}
});
$pedido->update(['web_service_laboratorio_cliente_pedido_status_id' => PedidoStatusEnum::REALIZADO]);
$pedido->refresh();
self::saveMovimentacao($pedido);
}
});
}
private static function validateStoreResult($request)
{
$request->validate([
'url' => [
Rule::requiredIf(fn () => !isset($request->base64)),
'prohibits:base64',
'string',
'max:300',
],
'base64' => [
Rule::requiredIf(fn () => !isset($request->url)),
'prohibits:url',
function ($attribute, $value, $fail) {
$decoded = str_contains($value, ',')
? base64_decode(explode(',', $value)[1], true)
: base64_decode($value, true);
if (!$decoded) {
return $fail('Base64 inválido');
}
$finfo = finfo_open();
$mime = finfo_buffer($finfo, $decoded, FILEINFO_MIME_TYPE);
if ($mime !== 'application/pdf') {
return $fail('O arquivo deve estar em um formato PDF válido');
}
finfo_close($finfo);
}
]
], [
'url.prohibits' => 'O campo url não é permitido se o campo base64 estiver presente',
'base64.prohibits' => 'O campo base64 não é permitido se o campo url estiver presente'
]);
}
private static function hasExameAgendado($pedido)
{
return $pedido->agendamentoExame()->where('status_id', StatusAgendamento::AGENDADO)->exists();
}
private static function getPedidoModel($laboratorio, $id)
{
$pedido = ExameLaboratorialAgendamento::where('laboratorio_infraestrutura_id', $laboratorio->conectasus_infraestrutura_id)
->where('id', $id)
->first();
if (is_null($pedido)) {
throw new PedidoNotFoundException();
}
return $pedido;
}
private static function saveMovimentacao($pedido, $params = [])
{
PedidoMovimentacao::create([
'conectasus_exame_laboratorial_agendamento_id' => $pedido->id,
'status_id' => $pedido->web_service_laboratorio_cliente_pedido_status_id,
'motivo' => $params['motivo'] ?? null,
'movimentado_em' => Carbon::now(),
]);
}
}

View File

@@ -0,0 +1,48 @@
<?php
namespace App\Services\WebService\Laboratorio\ConectaSus;
use App\Enums\Parametrizacao\Exame\Tipo;
use App\Exceptions\WebService\Laboratorio\ConectaSus\ExameNotFoundException;
use App\Models\Parametrizacao\Exame\Exame;
use App\Services\Service;
use Illuminate\Support\Facades\DB;
class ExameService extends Service
{
public static function index()
{
return DB::table('parametrizacao_exame AS exame')
->whereNull('exame.deleted_at')
->where('exame.ativo', true)
->where('exame.tipo_id', Tipo::LABORATORIAL)
->select([
'exame.id',
'exame.nome',
])
->orderBy('exame.nome')
->get();
}
public static function show($id)
{
$exame = self::getExameModel($id);
return (object) [
'id' => $exame->id,
'nome' => $exame->nome,
];
}
private static function getExameModel($id)
{
$exame = Exame::find($id);
if (is_null($exame)) {
throw new ExameNotFoundException();
}
return $exame;
}
}

View File

@@ -0,0 +1,212 @@
<?php
namespace App\Services\WebService;
use App\Exceptions\Externo\InvalidCredentialsException;
use App\Models\WebService\Permissao;
use App\Models\WebService\Usuario;
use App\Services\Service;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Hash;
use Illuminate\Validation\Rule;
class UsuarioService extends Service
{
public static function getAuthorizationToken($request)
{
self::validateGetAuthorizationToken($request);
$credentials = $request->only(['usuario', 'senha']);
$usuario = Usuario::where('usuario', $credentials['usuario'])->first();
if (is_null($usuario) || !Hash::check($credentials['senha'], $usuario->senha)) {
throw new InvalidCredentialsException();
}
auth()->login($usuario);
$token = auth()->claims([
'customer' => $request->header('customer'),
])->refresh();
return [
'expiration' => time() + 60 * auth()->factory()->getTTL(),
'token' => $token,
];
}
public static function validateGetAuthorizationToken($request)
{
$request->validate([
'usuario' => [
'required',
'string',
],
'senha' => [
'required',
'string',
],
]);
}
public static function create()
{
return [
'form' => self::getFormData(),
'model' => [
'nome' => null,
'usuario' => null,
'alterou_senha' => true,
'nova_senha' => null,
'nova_senha_confirmacao' => null,
'permissoes' => [],
],
];
}
public static function store($request)
{
self::validate($request);
$usuario = new Usuario();
$data = self::getUsuarioData($request);
DB::transaction(function () use ($usuario, $data) {
$usuario->fill($data);
$usuario->save();
$usuario->permissoes()->sync($data['permissoes']);
});
return $usuario->fresh();
}
public static function edit($id)
{
$usuario = Usuario::findOrFail($id);
return [
'form' => self::getFormData(),
'model' => [
'nome' => $usuario->nome,
'usuario' => $usuario->usuario,
'alterou_senha' => false,
'nova_senha' => null,
'nova_senha_confirmacao' => null,
'permissoes' => $usuario->permissoes()->pluck('id'),
],
];
}
private static function getFormData()
{
return [
'permissoes' => Permissao::orderBy('nome')->get(['id', 'nome']),
];
}
public static function update($request, $id)
{
$usuario = Usuario::findOrFail($id);
self::validate($request);
$data = self::getUsuarioData($request);
DB::transaction(function () use ($usuario, $data) {
$usuario->fill($data);
$usuario->save();
$usuario->permissoes()->sync($data['permissoes']);
});
return $usuario->fresh();
}
private static function getUsuarioData($request)
{
$data = [
'nome' => $request->nome,
'usuario' => $request->usuario,
'permissoes' => $request->permissoes,
];
if (is_null($request->route('id')) || $request->alterou_senha) {
$data['senha'] = $request->nova_senha;
}
return $data;
}
public static function destroy($id)
{
$usuario = Usuario::findOrFail($id);
$usuario->delete();
}
public static function datatable()
{
return DB::table('web_service_usuario AS usuario')
->leftJoin(
'web_service_usuario_permissao AS usuario_permissao',
'usuario_permissao.usuario_id',
'usuario.id'
)
->leftJoin(
'web_service_permissao AS permissao',
'permissao.id',
'usuario_permissao.permissao_id'
)
->select([
'usuario.id',
'usuario.nome',
DB::raw("GROUP_CONCAT(permissao.nome SEPARATOR '#') AS permissoes")
])
->groupBy([
'usuario.id',
'usuario.nome',
]);
}
private static function validate($request)
{
$request->validate([
'nome' => [
'required',
'string',
'between:6,150',
],
'usuario' => [
'nullable',
'string',
'between:3,100',
Rule::unique(Usuario::class, 'usuario')->ignore($request->route('id')),
],
'alterou_senha' => [
'required',
'boolean',
],
'nova_senha' => [
'nullable',
'required_if:alterou_senha,true',
'min:8',
'max:100',
'regex:/^(?=.*\d)(?=.*[a-zA-Z]).{8,}$/',
],
'permissoes' => [
'present',
'array',
],
'permissoes.*' => [
'required',
'integer',
Rule::exists(Permissao::class, 'id'),
]
]);
}
}