Files
SGF/app/Modules/Purchasing/ComposedFinanceController.php
T
2026-11-11 09:00:17 +02:00

38 lines
3.7 KiB
PHP

<?php
namespace App\Modules\Purchasing;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Tempo\Finance\Payables\Payables;
use Tempo\Purchasing\Embedded\Models\{Invoice,AuditLog};
use Tempo\Purchasing\Embedded\Services\RequisitionWorkflow;
final class ComposedFinanceController
{
public function index(Request $r,ComposedFinance $finance)
{
$d=$r->validate(['document_id'=>'sometimes|integer|min:1','page'=>'sometimes|integer|min:1|max:100000','payments_page'=>'sometimes|integer|min:1|max:100000','allocation_proposals_page'=>'sometimes|integer|min:1|max:100000','allocations_page'=>'sometimes|integer|min:1|max:100000','payment_events_page'=>'sometimes|integer|min:1|max:100000','payment_per_page'=>'sometimes|integer|in:25,100','payment_q'=>'sometimes|string|max:100','payment_state'=>'sometimes|in:all,proposed,confirmed,rejected']);abort_if(array_diff(array_keys($r->query()),array_keys($d)),422);
return $finance->run('view',function($engine,$settlements,$actor,$origin,$orders)use($r,$d){
$q=Invoice::where('tenant_id',$actor->tenant_id)->whereIn('purchase_order_id',$orders->select('id'));if(isset($d['document_id']))$q->where('id',(int)$d['document_id']);$page=$q->orderBy('id')->paginate(25,['id','number'],'page',(int)($d['page']??1));if(isset($d['document_id']))abort_unless($page->total()===1,403,'Documento fora da origem financeira autorizada.');
$base=$engine->positionsPage(array_column($page->items(),'id'));$money=$settlements->listingPage(array_diff_key($d,['page'=>true,'document_id'=>true]));
$numbers=DB::table('pa_sources as s')->join('invoices as i','i.id','=','s.local_source_id')->where('s.tenant_id',$actor->tenant_id)->whereIn('s.id',array_column($base['obligations'],'source_id'))->pluck('i.number','s.id');
foreach($base['obligations'] as &$o)$o['document_number']=$numbers->get($o['source_id']);unset($o);
$data=['obligations'=>$base['obligations'],'money'=>$money,'profile'=>$origin['profile'],'pagination'=>['page'=>$page->currentPage(),'last_page'=>$page->lastPage()]];
if($r->is('api/*'))return response()->json($data)->header('Cache-Control','no-store');
return response()->view('finance.composed-payables',['data'=>$data,'context'=>$r->session()->get('company_context.token'),'csrf'=>csrf_token()])->header('Cache-Control','no-store');
});
}
public function command(string $action,Request $r,ComposedFinance $finance)
{
$key=strtolower((string)$r->header('Idempotency-Key'));abort_unless(preg_match('/^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$/D',$key),422);$data=$r->all();abort_if(strlen(json_encode($data))>65536,422);
try{return $finance->run($action,function($engine,$settlements,$actor,$origin)use($action,$key,$data){
$hash=hash('sha256',Payables::canonical([$action,$data]));$old=AuditLog::where('tenant_id',$actor->tenant_id)->where('action','sgf.finance.command')->where('after->operation_key',$key)->first();
if($old)abort_unless(($old->after['sgf_context_key']??null)===$origin['sgf_context_key']&&($old->after['request_hash']??null)===$hash,409,'Chave pertence a outro contexto/conteúdo.');
$result=$settlements->command($action,$data,$key);
if(!$old)app(RequisitionWorkflow::class)->audit($actor,'sgf.finance.command',null,null,$origin+['operation_key'=>$key,'request_hash'=>$hash,'command'=>$action,'result'=>$result,'reason'=>$data['reason']??'']);
return response()->json($result)->header('Cache-Control','no-store');
});}catch(\InvalidArgumentException $e){abort(422,$e->getMessage());}catch(\DomainException $e){abort(409,$e->getMessage());}
}
}