This commit is contained in:
2026-10-29 18:43:29 +02:00
parent f77900e198
commit 78e89a51d2
75 changed files with 2881 additions and 14 deletions
@@ -93,6 +93,7 @@ final class DocumentPreparation
$data = array_intersect_key($input, array_flip($fields));
if ($scope['unit_id']) {
$this->workflow->scope($kind, $actor, 'view');
\App\Modules\Workshop\WorkshopCommercialState::assertCurrent($kind, $id);
abort_if($kind === 'billing_drafts' && DB::table('b_internal_confirmations')->where('billing_draft_id', $id)->exists(), 409, 'A fotografia e o rascunho B1 estão bloqueados.');
abort_unless((int) $target->version === $input['draft_version'], 409, 'O rascunho mudou; reveja a preparação.');
$draftData = json_decode($target->data, true, 32, JSON_THROW_ON_ERROR);
@@ -37,6 +37,7 @@ final class InternalConfirmation
$this->context->selectFor($actor, $scope['tenant_id'], $scope['company_id'], $scope['unit_id']);
$this->workflow->scope('billing_drafts', $actor, 'view');
$this->permissions->require($actor, $scope['tenant_id'], $scope['company_id'], self::PERMISSION, $scope['unit_id']);
\App\Modules\Workshop\WorkshopCommercialState::assertCurrent('billing_drafts', $draft);
$old = DB::table('a_commands')->where('tenant_id', $scope['tenant_id'])->where('company_id', $scope['company_id'])->where('command_key', $key)->first();
if ($old) {
abort_unless((int) $old->actor_id === $actor && hash_equals($old->request_hash, $hash), 409, 'Chave repetida com conteúdo ou autor diferente.');
+5 -2
View File
@@ -55,6 +55,9 @@ final class ServiceWorkflow
$result = (array) $row;
$result['data'] = json_decode($row->data, true, 32, JSON_THROW_ON_ERROR);
$result['version'] = (int) $row->version;
if (in_array($area, ['service_drafts','billing_drafts'], true)) {
$result['workshop_commercial_state'] = \App\Modules\Workshop\WorkshopCommercialState::state($area, (int)$row->id);
}
if ($area === 'billing_drafts') {
$confirmationId = DB::table('b_internal_confirmations')->where('billing_draft_id', $row->id)->value('id');
$result['internal_confirmation'] = $confirmationId ? ['reference' => 'INT-B1-'.$confirmationId, 'label' => InternalConfirmation::LABEL] : null;
@@ -86,7 +89,7 @@ final class ServiceWorkflow
abort_unless($old, 403, 'Registo fora do âmbito autorizado.');
if (in_array($area, ['service_drafts','billing_drafts'], true) && \Illuminate\Support\Facades\Schema::hasTable('wb_generations')) {
$column = $area === 'service_drafts' ? 'service_draft_id' : 'billing_draft_id';
abort_if(DB::table('wb_generations')->where($column, $id)->exists(),409,'Rascunho ligado a oficina: correcção comercial própria necessária; a proposta revista não pode ser alterada por edição directa.');
abort_if(\App\Modules\Workshop\WorkshopCommercialState::linked($area, $id),409,'Rascunho ligado a oficina: correcção comercial própria necessária; a proposta revista não pode ser alterada por edição directa.');
}
abort_if($area === 'billing_drafts' && DB::table('b_internal_confirmations')->where('billing_draft_id', $id)->exists(), 409, 'Confirmado internamente — sem validade fiscal. O registo está bloqueado para edição.');
abort_unless((int) $old->version === (int) ($input['version'] ?? 0), 409, 'O registo mudou. Reabra-o antes de guardar.');
@@ -142,7 +145,7 @@ final class ServiceWorkflow
if ($area === 'billing_drafts') {
$sourceId = $old ? $old->source_id : $input['source_id'];
if (!$old && \Illuminate\Support\Facades\Schema::hasTable('wb_generations')) {
abort_if(DB::table('wb_generations')->where('service_draft_id', $sourceId)->exists(),409,'Prestação de oficina já convertida: não pode gerar um segundo rascunho por outro percurso.');
abort_if(\App\Modules\Workshop\WorkshopCommercialState::linked('service_drafts', (int)$sourceId),409,'Prestação de oficina já convertida: não pode gerar um segundo rascunho por outro percurso.');
}
$source = DB::table('a_service_drafts')->where('tenant_id', $scope['tenant_id'])->where('company_id', $scope['company_id'])->where('unit_id', $scope['unit_id'])->where('id', $sourceId)->first();
abort_unless($source, 403, 'Prestação fora da unidade autorizada.');