Files
SGF/packages/general-ledger/src/StockSupplierReturnEvidence.php
T
2026-11-11 09:00:17 +02:00

32 lines
3.3 KiB
PHP

<?php
namespace Tempo\Finance\GeneralLedger;
use Illuminate\Database\ConnectionInterface;
use Tempo\Finance\Payables\Payables;
/** Immutable native review/execution facts; later eligible returns do not rewrite this fact. */
final class StockSupplierReturnEvidence
{
public function __construct(private ConnectionInterface $db,private array $scope){}
public function check(object $m,object $op,array $snapshot):array
{
if(!LedgerSchema::externalHostComposition($this->db)||$op->kind!=='supplier_return')throw new \DomainException('Devolução ao fornecedor fora da composição QA.');
$proof=$snapshot['disposition']??null;
$approved=is_array($proof)?$this->db->table('supply_records')->where(['tenant_id'=>$this->scope['tenant_id'],'id'=>$proof['approved_id']??0,'kind'=>'stock_event','state'=>'approved'])->first():null;
$executed=$approved?$this->db->table('supply_records')->where(['tenant_id'=>$this->scope['tenant_id'],'record_key'=>$approved->record_key,'version'=>$approved->version+1,'state'=>'executed','kind'=>'stock_event'])->first():null;
if(!$approved||!$executed)throw new \DomainException('Faltam aprovação e execução nativas.');
$data=json_decode($approved->data,true,64,JSON_THROW_ON_ERROR);$done=json_decode($executed->data,true,64,JSON_THROW_ON_ERROR);$review=json_decode($approved->snapshot,true,64,JSON_THROW_ON_ERROR);
$source=$review['source']??null;$receiptItem=$source['receipt']['item_id']??null;
$line=is_int($receiptItem)?$this->db->table('goods_receipt_items')->where(['tenant_id'=>$this->scope['tenant_id'],'id'=>$receiptItem])->first():null;
$receipt=$line?$this->db->table('goods_receipts')->where(['tenant_id'=>$this->scope['tenant_id'],'id'=>$line->goods_receipt_id])->first():null;
$total=$this->db->table('stock_movements')->where(['tenant_id'=>$this->scope['tenant_id'],'movement_type'=>'supplier_return'])->where('snapshot->disposition->source->receipt->item_id',$receiptItem)->sum('quantity_milli');
if(!$line||!$receipt||$receipt->confirmed_at===null||$line->stock_item_id!==$m->stock_item_id||$receipt->warehouse_id!==$m->warehouse_id
||($data['kind']??null)!=='supplier_return'||($data['stock_item_id']??null)!==$m->stock_item_id||($data['warehouse_id']??null)!==$m->warehouse_id||($data['receipt_item_id']??null)!==$receiptItem
||($data['quantity_milli']??null)!==abs((int)$m->quantity_milli)||($done['stock_operation_id']??null)!==$op->id||$executed->created_by!==$m->moved_by
||$approved->created_by===$executed->created_by||($review['reviewed_by']??null)!==$approved->created_by||in_array($approved->created_by,$review['contributors']??[],true)
||($proof['record_key']??null)!==$approved->record_key||$op->idempotency_key!==$approved->record_key||($proof['financial_correction_created']??null)!==false
||Payables::canonical($proof['source']??null)!==Payables::canonical($source)||abs((int)$total)>(int)$line->accepted_milli)
throw new \DomainException('Devolução sem origem, quantidade, revisão e execução reconciliadas.');
return ['supplier_return_approved'=>(array)$approved,'supplier_return_executed'=>(array)$executed,'supplier_receipt_item'=>(array)$line,'supplier_receipt'=>(array)$receipt];
}
}