diff --git a/ProcessMaker/Models/CaseNumber.php b/ProcessMaker/Models/CaseNumber.php
new file mode 100644
index 0000000000..7b06ee69e5
--- /dev/null
+++ b/ProcessMaker/Models/CaseNumber.php
@@ -0,0 +1,36 @@
+id);
+ */
+class CaseNumber extends Model
+{
+ use HasFactory;
+
+ protected $fillable = ['process_request_id'];
+
+ /**
+ * Generate a unique sequence for a given name.
+ *
+ * @param int|string $id of the request
+ * @return int The next value in the sequence.
+ */
+ public static function generate($requestId): int
+ {
+ // Create a new sequence with the given name
+ $sequence = self::create(['process_request_id' => $requestId]);
+
+ // Return the id of the sequence as the next value in the sequence
+ return $sequence->id;
+ }
+}
diff --git a/ProcessMaker/Models/ProcessRequest.php b/ProcessMaker/Models/ProcessRequest.php
index bca964b68e..e9edb23641 100644
--- a/ProcessMaker/Models/ProcessRequest.php
+++ b/ProcessMaker/Models/ProcessRequest.php
@@ -40,6 +40,7 @@
* @property string $participant_id
* @property string $name
* @property string $case_title
+ * @property int $case_number
* @property string $status
* @property array $data
* @property string $collaboration_uuid
@@ -61,6 +62,7 @@
* @OA\Property(property="status", type="string", enum={"ACTIVE", "COMPLETED", "ERROR", "CANCELED"}),
* @OA\Property(property="name", type="string"),
* @OA\Property(property="case_title", type="string"),
+ * @OA\Property(property="case_number", type="integer"),
* @OA\Property(property="process_id", type="integer"),
* @OA\Property(property="process", type="object"),
* ),
@@ -934,4 +936,15 @@ public function evaluateCaseTitle(array $data): string
$mustache = new MustacheExpressionEvaluator();
return $mustache->render($mustacheTitle, $data);
}
+
+ public function isSystem()
+ {
+ $systemCategories = ProcessCategory::where('is_system', true)->pluck('id');
+ return DB::table('category_assignments')
+ ->where('assignable_type', Process::class)
+ ->where('assignable_id', $this->process_id)
+ ->where('category_type', ProcessCategory::class)
+ ->whereIn('category_id', $systemCategories)
+ ->exists();
+ }
}
diff --git a/ProcessMaker/Nayra/Managers/WorkflowManagerRabbitMq.php b/ProcessMaker/Nayra/Managers/WorkflowManagerRabbitMq.php
index 4e706c03de..4356ea6677 100644
--- a/ProcessMaker/Nayra/Managers/WorkflowManagerRabbitMq.php
+++ b/ProcessMaker/Nayra/Managers/WorkflowManagerRabbitMq.php
@@ -611,6 +611,7 @@ private function serializeState(ProcessRequest $instance)
return [
'id' => $request->uuid,
+ 'request_id' => $request->getKey(),
'process_version_id' => $request->process_version_id,
'callable_id' => $request->callable_id,
'collaboration_uuid' => $request->collaboration_uuid,
diff --git a/ProcessMaker/Nayra/Repositories/Deserializer.php b/ProcessMaker/Nayra/Repositories/Deserializer.php
index 2560ccc80a..cc4729d9cc 100644
--- a/ProcessMaker/Nayra/Repositories/Deserializer.php
+++ b/ProcessMaker/Nayra/Repositories/Deserializer.php
@@ -194,6 +194,9 @@ public function unserializeInstance(array $serialized): ExecutionInstanceInterfa
// Set process request properties
$properties = array_merge($instance->getProperties(), $properties);
$instance->setProperties($properties);
+ if (isset($properties['parent_request_id'])) {
+ $instance->parent_request_id = $properties['parent_request_id'];
+ }
// Set request data
if (!empty($serialized['data']) && is_array($serialized['data'])) {
diff --git a/ProcessMaker/Observers/ProcessRequestObserver.php b/ProcessMaker/Observers/ProcessRequestObserver.php
index b060e1a15e..7f8fc72910 100644
--- a/ProcessMaker/Observers/ProcessRequestObserver.php
+++ b/ProcessMaker/Observers/ProcessRequestObserver.php
@@ -4,6 +4,7 @@
use ProcessMaker\Events\RequestAction;
use ProcessMaker\Events\RequestError;
+use ProcessMaker\Models\CaseNumber;
use ProcessMaker\Models\ProcessRequest;
use ProcessMaker\Models\ProcessRequestToken;
use ProcessMaker\Models\ScheduledTask;
@@ -64,7 +65,43 @@ public function saving(ProcessRequest $request)
// When data is updated we update the case_title
if ($request->isDirty('data')) {
$data = $request->data;
- $request->case_title = $request->evaluateCaseTitle($data);
+ // If request is a parent process, inherit the case title to the child requests
+ if (!$request->parent_request_id) {
+ $request->case_title = $request->evaluateCaseTitle($data);
+ // Copy the case title to the child requests
+ if (!empty($request->id)) {
+ ProcessRequest::where('parent_request_id', $request->id)
+ ->update(['case_title' => $request->case_title]);
+ }
+ } else {
+ // If request is a subprocess, inherit the case title from the parent
+ $request->case_title = ProcessRequest::whereId($request->parent_request_id)
+ ->select('case_title')
+ ->first()
+ ->case_title;
+ }
+ }
+ }
+
+ public function created(ProcessRequest $request)
+ {
+ // If request is System, don't generate a case number
+ if ($request->isSystem()) {
+ return;
+ }
+ // If request is a subprocess, inherit the case number from the parent
+ if ($request->parent_request_id) {
+ $request->case_number = ProcessRequest::whereId($request->parent_request_id)
+ ->select('case_number')
+ ->first()
+ ->case_number;
+
+ $request->save();
+
+ return;
}
+ // If request is not a subprocess and not a system process, generate a case number
+ $request->case_number = CaseNumber::generate($request->id);
+ $request->save();
}
}
diff --git a/ProcessMaker/Repositories/ExecutionInstanceRepository.php b/ProcessMaker/Repositories/ExecutionInstanceRepository.php
index dfe9da6d59..ec810be5f8 100644
--- a/ProcessMaker/Repositories/ExecutionInstanceRepository.php
+++ b/ProcessMaker/Repositories/ExecutionInstanceRepository.php
@@ -151,6 +151,12 @@ public function persistInstanceCreated(ExecutionInstanceInterface $instance)
return;
}
+ // Check if
+ $parent = $data['_parent'] ?? null;
+ if (!empty($parent) && is_numeric($parent['request_id'])) {
+ $instance->parent_request_id = $parent['request_id'];
+ }
+
// Save process request
$instance->callable_id = $process->getId();
$instance->collaboration_uuid = $instance->getProperty('collaboration_uuid', null);
diff --git a/database/migrations/2023_12_04_100557_create_case_numbers_table.php b/database/migrations/2023_12_04_100557_create_case_numbers_table.php
new file mode 100644
index 0000000000..db4703ebb6
--- /dev/null
+++ b/database/migrations/2023_12_04_100557_create_case_numbers_table.php
@@ -0,0 +1,27 @@
+id();
+ $table->unsignedInteger('process_request_id')->nullable();
+ $table->timestamps();
+ });
+ }
+
+ /**
+ * Reverse the migrations.
+ */
+ public function down(): void
+ {
+ Schema::dropIfExists('case_numbers');
+ }
+};
diff --git a/database/migrations/2023_12_04_115613_add_case_number_to_process_requests_table.php b/database/migrations/2023_12_04_115613_add_case_number_to_process_requests_table.php
new file mode 100644
index 0000000000..917566e453
--- /dev/null
+++ b/database/migrations/2023_12_04_115613_add_case_number_to_process_requests_table.php
@@ -0,0 +1,28 @@
+unsignedInteger('case_number')->nullable();
+ });
+ }
+
+ /**
+ * Reverse the migrations.
+ */
+ public function down(): void
+ {
+ Schema::table('process_requests', function (Blueprint $table) {
+ $table->dropColumn('case_number');
+ });
+ }
+};
diff --git a/resources/js/requests/components/RequestsListing.vue b/resources/js/requests/components/RequestsListing.vue
index 70756a6fb0..4c29b302b3 100644
--- a/resources/js/requests/components/RequestsListing.vue
+++ b/resources/js/requests/components/RequestsListing.vue
@@ -34,6 +34,17 @@
#{{ props.rowData.id }}
+
+
+ #{{ props.rowData.case_number }}
+
+