commit13
This commit is contained in:
@@ -17,6 +17,10 @@ use Illuminate\Validation\ValidationException;
|
||||
/** Event-driven draft preparation. Never submits, decides, orders, reserves budget or moves stock. */
|
||||
class AutomaticPurchases
|
||||
{
|
||||
public function eligibleRequester(User $user): bool
|
||||
{
|
||||
return in_array('requester', app(OrganizationAccess::class)->permissions($user, app(WorkContext::class)->enforced($user) ? 'procurement.internal' : null), true) && !app(OrganizationAccess::class)->maintenanceOnly($user);
|
||||
}
|
||||
public function ready(): bool
|
||||
{
|
||||
return Schema::hasTable('supply_records') && app(WarehouseReservations::class)->ready();
|
||||
@@ -29,7 +33,7 @@ class AutomaticPurchases
|
||||
$this->check($current !== null && $current->id === $rule->id && $current->tenant_id === $executor->tenant_id && $current->state === 'approved', 'A parametrização automática deixou de estar activa.');
|
||||
$this->check(! app(OrganizationAccess::class)->maintenanceOnly($executor), 'A manutenção não pode executar compras automáticas.');
|
||||
$user = User::query()->where('tenant_id', $executor->tenant_id)->lockForUpdate()->find($rule->data['requester_id']);
|
||||
$this->check($user !== null && in_array('requester', app(OrganizationAccess::class)->permissions($user, 'procurement.internal'), true), 'Requisitante sem competência vigente no contexto de compras internas.');
|
||||
$this->check($user !== null && $this->eligibleRequester($user), 'Requisitante sem competência vigente no contexto de compras internas.');
|
||||
$this->check(CostCenter::query()->whereKey($rule->data['cost_center_id'])->where('department_id', $user->department_id)->exists(), 'Centro de custo incompatível com o departamento actual do requisitante.');
|
||||
$this->check($user->only(['id', 'name', 'department_id']) === $rule->snapshot['requester'], 'O requisitante mudou; reveja a parametrização.');
|
||||
$center = CostCenter::query()->findOrFail($rule->data['cost_center_id']);
|
||||
@@ -69,7 +73,7 @@ class AutomaticPurchases
|
||||
$this->check($basis['policy']['purpose'] === 'internal', 'Esta parametrização destina-se às compras internas do SGC.');
|
||||
$this->check($basis['catalogue']['purchase_type'] === 'consumable', 'Seleccione um consumível publicado; equipamento/peças exigem o seu destino técnico.');
|
||||
$user = User::query()->where('tenant_id', $actor->tenant_id)->findOrFail($values['requester_id']);
|
||||
$this->check(in_array('requester', app(OrganizationAccess::class)->permissions($user, 'procurement.internal'), true), 'Seleccione um requisitante com competência vigente em compras internas.');
|
||||
$this->check($this->eligibleRequester($user), 'Seleccione um requisitante com competência vigente em compras internas.');
|
||||
$center = CostCenter::query()->where('department_id', $user->department_id)->findOrFail($values['cost_center_id']);
|
||||
$snapshot = ['requester' => $user->only(['id', 'name', 'department_id']), 'cost_center' => $center->only(['id', 'code', 'name', 'department_id']), 'prepared_by' => $actor->id,
|
||||
'item' => $basis['item'], 'warehouse' => $basis['warehouse'], 'policy_version' => $basis['policy_version'], 'catalogue' => $basis['catalogue']];
|
||||
@@ -176,7 +180,7 @@ continue;
|
||||
$this->check($line->catalogue_entry_id === $basis['catalogue']['id'] && ($line->catalogue_snapshot['version'] ?? null) === $basis['catalogue']['version'], 'O rascunho automático anterior mudou de artigo; reconcilie a necessidade.');
|
||||
$received = 0;
|
||||
foreach (DB::table('goods_receipt_items as gi')->join('goods_receipts as g', 'g.id', '=', 'gi.goods_receipt_id')->join('purchase_order_items as oi', 'oi.id', '=', 'gi.purchase_order_item_id')->where('gi.tenant_id', $actor->tenant_id)->where('oi.requisition_item_id', $line->id)->where('g.warehouse_id', $warehouse)->where('gi.stock_item_id', $item)->get(['gi.id', 'gi.accepted_milli']) as $receipt) {
|
||||
$voided = collect(app(InventoryReversals::class)->corrections('receipt'))->contains(fn ($correction) => ($correction->snapshot['source']['receipt']['id'] ?? null) === $receipt->id);
|
||||
$voided = collect(app(InventoryReversals::class)->corrections('receipt'))->contains(fn ($correction) => ($correction->snapshot['source']['receipt']['item_id'] ?? null) === $receipt->id);
|
||||
if (! $voided) {
|
||||
$received += (int) $receipt->accepted_milli;
|
||||
}
|
||||
|
||||
@@ -439,7 +439,7 @@ class InventoryLots
|
||||
'data' => $data, 'snapshot' => [...$snapshot, 'actor' => $actor->only(['id', 'name'])], 'reason' => $reason, 'created_by' => $actor->id,
|
||||
'operation_key' => $operation ?? (string) Str::uuid(), 'input_hash' => $hash ?? hash('sha256', json_encode($data, JSON_THROW_ON_ERROR)), 'created_at' => now()]);
|
||||
app(RequisitionWorkflow::class)->audit($actor, 'inventory.'.$kind.'.'.$state, null, $old?->toArray(), $record->toArray());
|
||||
app(AutomaticPurchases::class)->signal($actor,$data['stock_item_id'],$data['warehouse_id']);
|
||||
app(AutomaticPurchases::class)->signal($actor, $data['stock_item_id'], $data['warehouse_id']);
|
||||
|
||||
return $record;
|
||||
}
|
||||
|
||||
@@ -224,7 +224,7 @@ class ReceiptWorkflow
|
||||
]);
|
||||
$sourceInput = collect($inputs)->firstWhere('purchase_order_item_id', $line['purchase_order_item_id']);
|
||||
app(InventoryLots::class)->receive($user, $movement, $sourceInput['lots'] ?? [], $data['received_on']);
|
||||
app(AutomaticPurchases::class)->signal($user,$line['stock_item_id'],$warehouse->id);
|
||||
app(AutomaticPurchases::class)->signal($user, $line['stock_item_id'], $warehouse->id);
|
||||
}
|
||||
}
|
||||
$progress = $this->progress($order);
|
||||
|
||||
Reference in New Issue
Block a user