diff -Nru ../workshop399/allocation/scheduled/classes/observer.php ./allocation/scheduled/classes/observer.php
--- ../workshop399/allocation/scheduled/classes/observer.php	2021-07-29 11:01:07.000000000 +0900
+++ ./allocation/scheduled/classes/observer.php	2022-05-14 21:16:06.560066622 +0900
@@ -81,4 +81,41 @@
         }
         return true;
     }
+
+    /**
+     * Called when the '\mod_workshop\event\phase_automatically_switched' event is triggered.
+     *
+     * This observer handles the phase_automatically_switched event triggered when phaseswithassesment is active
+     * and the phase is automatically switched.
+     *
+     * When this happens, this situation can occur:
+     *
+     *     * cron_task transition the workshop to PHASE_ASESSMENT.
+     *     * scheduled_allocator task executes.
+     *     * scheduled_allocator task cannot allocate parcipants because workshop is not
+     *       in PHASE_SUBMISSION state (it's in PHASE_ASSESMENT).
+     *
+     * @param \mod_workshop\event\phase_automatically_switched $event
+     */
+    public static function phase_automatically_switched(\mod_workshop\event\phase_automatically_switched $event) {
+        if ($event->other['previousworkshopphase'] != \workshop::PHASE_SUBMISSION) {
+            return;
+        }
+        if ($event->other['targetworkshopphase'] != \workshop::PHASE_ASSESSMENT) {
+            return;
+        }
+
+        $workshop = $event->get_record_snapshot('workshop', $event->objectid);
+        $course   = $event->get_record_snapshot('course', $event->courseid);
+        $cm       = $event->get_record_snapshot('course_modules', $event->contextinstanceid);
+
+        $workshop = new \workshop($workshop, $cm, $course);
+        if ($workshop->phase != \workshop::PHASE_ASSESSMENT) {
+            return;
+        }
+
+        $allocator = $workshop->allocator_instance('scheduled');
+        // We know that we come from PHASE_SUBMISSION so we tell the allocator not to test for the PHASE_SUBMISSION state.
+        $allocator->execute(false);
+    }
 }
diff -Nru ../workshop399/allocation/scheduled/db/events.php ./allocation/scheduled/db/events.php
--- ../workshop399/allocation/scheduled/db/events.php	2021-07-29 11:01:07.000000000 +0900
+++ ./allocation/scheduled/db/events.php	2022-05-14 21:16:06.560066622 +0900
@@ -31,5 +31,10 @@
     array(
         'eventname' => '\mod_workshop\event\course_module_viewed',
         'callback'  => '\workshopallocation_scheduled\observer::workshop_viewed',
+    ),
+
+    array(
+        'eventname' => '\mod_workshop\event\phase_automatically_switched',
+        'callback' => '\workshopallocation_scheduled\observer::phase_automatically_switched'
     )
 );
diff -Nru ../workshop399/allocation/scheduled/lib.php ./allocation/scheduled/lib.php
--- ../workshop399/allocation/scheduled/lib.php	2021-07-29 11:01:07.000000000 +0900
+++ ./allocation/scheduled/lib.php	2022-05-14 21:16:06.560066622 +0900
@@ -128,71 +128,97 @@
     /**
      * Executes the allocation
      *
+     * @param bool $checksubmissionphase Check that the workshop is in submission phase before doing anything else.
      * @return workshop_allocation_result
      */
-    public function execute() {
+    public function execute(bool $checksubmissionphase = true) {
         global $DB;
 
         $result = new workshop_allocation_result($this);
 
-        // make sure the workshop itself is at the expected state
-
-        if ($this->workshop->phase != workshop::PHASE_SUBMISSION) {
+        // Execution can occur in multiple places. Ensure we only allocate one at a time.
+        $lockfactory = \core\lock\lock_config::get_lock_factory('mod_workshop_allocation_scheduled_execution');
+        $executionlock = $lockfactory->get_lock($this->workshop->id, 1, 30);
+        if (!$executionlock) {
             $result->set_status(workshop_allocation_result::STATUS_FAILED,
-                get_string('resultfailedphase', 'workshopallocation_scheduled'));
-            return $result;
+                get_string('resultfailed', 'workshopallocation_scheduled'));
         }
 
-        if (empty($this->workshop->submissionend)) {
-            $result->set_status(workshop_allocation_result::STATUS_FAILED,
-                get_string('resultfaileddeadline', 'workshopallocation_scheduled'));
-            return $result;
-        }
+        try {
+            // Make sure the workshop itself is at the expected state.
 
-        if ($this->workshop->submissionend > time()) {
-            $result->set_status(workshop_allocation_result::STATUS_VOID,
-                get_string('resultvoiddeadline', 'workshopallocation_scheduled'));
-            return $result;
-        }
+            if ($checksubmissionphase && $this->workshop->phase != workshop::PHASE_SUBMISSION) {
+                $executionlock->release();
+                $result->set_status(workshop_allocation_result::STATUS_FAILED,
+                    get_string('resultfailedphase', 'workshopallocation_scheduled'));
+                return $result;
+            }
+
+            if (empty($this->workshop->submissionend)) {
+                $executionlock->release();
+                $result->set_status(workshop_allocation_result::STATUS_FAILED,
+                    get_string('resultfaileddeadline', 'workshopallocation_scheduled'));
+                return $result;
+            }
+
+            if ($this->workshop->submissionend > time()) {
+                $executionlock->release();
+                $result->set_status(workshop_allocation_result::STATUS_VOID,
+                    get_string('resultvoiddeadline', 'workshopallocation_scheduled'));
+                return $result;
+            }
+
+            $current = $DB->get_record('workshopallocation_scheduled',
+                array('workshopid' => $this->workshop->id, 'enabled' => 1), '*', IGNORE_MISSING);
+
+            if ($current === false) {
+                $executionlock->release();
+                $result->set_status(workshop_allocation_result::STATUS_FAILED,
+                    get_string('resultfailedconfig', 'workshopallocation_scheduled'));
+                return $result;
+            }
+
+            if (!$current->enabled) {
+                $executionlock->release();
+                $result->set_status(workshop_allocation_result::STATUS_VOID,
+                    get_string('resultdisabled', 'workshopallocation_scheduled'));
+                return $result;
+            }
+
+            if (!is_null($current->timeallocated) and $current->timeallocated >= $this->workshop->submissionend) {
+                $executionlock->release();
+                $result->set_status(workshop_allocation_result::STATUS_VOID,
+                    get_string('resultvoidexecuted', 'workshopallocation_scheduled'));
+                return $result;
+            }
+
+            // So now we know that we are after the submissions deadline and either the scheduled allocation was not
+            // executed yet or it was but the submissions deadline has been prolonged (and hence we should repeat the
+            // allocations).
+
+            $settings = workshop_random_allocator_setting::instance_from_text($current->settings);
+            $randomallocator = $this->workshop->allocator_instance('random');
+            $randomallocator->execute($settings, $result);
+
+            // Store the result in the instance's table.
+            $update = new stdClass();
+            $update->id = $current->id;
+            $update->timeallocated = $result->get_timeend();
+            $update->resultstatus = $result->get_status();
+            $update->resultmessage = $result->get_message();
+            $update->resultlog = json_encode($result->get_logs());
 
-        $current = $DB->get_record('workshopallocation_scheduled',
-            array('workshopid' => $this->workshop->id, 'enabled' => 1), '*', IGNORE_MISSING);
+            $DB->update_record('workshopallocation_scheduled', $update);
 
-        if ($current === false) {
+        } catch (\Exception $e) {
+            $executionlock->release();
             $result->set_status(workshop_allocation_result::STATUS_FAILED,
-                get_string('resultfailedconfig', 'workshopallocation_scheduled'));
-            return $result;
-        }
-
-        if (!$current->enabled) {
-            $result->set_status(workshop_allocation_result::STATUS_VOID,
-                get_string('resultdisabled', 'workshopallocation_scheduled'));
-            return $result;
-        }
+                get_string('resultfailed', 'workshopallocation_scheduled'));
 
-        if (!is_null($current->timeallocated) and $current->timeallocated >= $this->workshop->submissionend) {
-            $result->set_status(workshop_allocation_result::STATUS_VOID,
-                get_string('resultvoidexecuted', 'workshopallocation_scheduled'));
-            return $result;
+            throw $e;
         }
 
-        // so now we know that we are after the submissions deadline and either the scheduled allocation was not
-        // executed yet or it was but the submissions deadline has been prolonged (and hence we should repeat the
-        // allocations)
-
-        $settings = workshop_random_allocator_setting::instance_from_text($current->settings);
-        $randomallocator = $this->workshop->allocator_instance('random');
-        $randomallocator->execute($settings, $result);
-
-        // store the result in the instance's table
-        $update = new stdClass();
-        $update->id = $current->id;
-        $update->timeallocated = $result->get_timeend();
-        $update->resultstatus = $result->get_status();
-        $update->resultmessage = $result->get_message();
-        $update->resultlog = json_encode($result->get_logs());
-
-        $DB->update_record('workshopallocation_scheduled', $update);
+        $executionlock->release();
 
         return $result;
     }
diff -Nru ../workshop399/classes/event/phase_automatically_switched.php ./classes/event/phase_automatically_switched.php
--- ../workshop399/classes/event/phase_automatically_switched.php	1970-01-01 09:00:00.000000000 +0900
+++ ./classes/event/phase_automatically_switched.php	2022-05-14 21:16:06.560066622 +0900
@@ -0,0 +1,110 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace mod_workshop\event;
+
+/**
+ * This event is triggered when a phase is automatically switched, usually from cron_task.
+ *
+ * @property-read array $other {
+ *      Extra information about the event.
+ *
+ *      - int previousworkshopphase: Previous workshop phase.
+ *      - int targetworkshopphase: Target workshop phase.
+ * }
+ *
+ * @package    mod_workshop
+ * @copyright  2020 Universitat Jaume I <https://www.uji.es/>
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class phase_automatically_switched extends \core\event\base {
+
+    /**
+     * Init method.
+     *
+     * @return void
+     */
+    protected function init() {
+        $this->data['crud'] = 'u';
+        $this->data['edulevel'] = self::LEVEL_TEACHING;
+        $this->data['objecttable'] = 'workshop';
+    }
+
+    /**
+     * Returns description of what happened.
+     *
+     * @return string
+     */
+    public function get_description() {
+        return "The phase of the workshop with course module id " .
+            "'$this->contextinstanceid' has been automatically switched from " .
+            "'{$this->other['previousworkshopphase']} to '{$this->other['currentworkshopphase']}'.";
+    }
+
+    /**
+     * Return localised event name.
+     *
+     * @return string
+     */
+    public static function get_name() {
+        return get_string('eventphaseautomaticallyswitched', 'mod_workshop');
+    }
+
+    /**
+     * Get URL related to the action.
+     *
+     * @return \moodle_url
+     */
+    public function get_url() {
+        return new \moodle_url('/mod/workshop/view.php', array('id' => $this->contextinstanceid));
+    }
+
+    /**
+     * Custom validation.
+     *
+     * @return void
+     * @throws \coding_exception
+     */
+    protected function validate_data() {
+        parent::validate_data();
+
+        if (!isset($this->other['previousworkshopphase'])) {
+            throw new \coding_exception('The \'previousworkshopphase\' value must be set in other.');
+        }
+        if (!isset($this->other['targetworkshopphase'])) {
+            throw new \coding_exception('The \'targetworkshopphase\' value must be set in other.');
+        }
+    }
+
+    /**
+     * Map the objectid information in order to restore the event accurately. In this event
+     * objectid is the workshop id.
+     *
+     * @return array
+     */
+    public static function get_objectid_mapping() {
+        return array('db' => 'workshop', 'restore' => 'workshop');
+    }
+
+    /**
+     * No need to map the 'other' field as it only stores phases and they don't need to be mapped.
+     *
+     * @return bool
+     */
+    public static function get_other_mapping() {
+        return false;
+    }
+}
diff -Nru ../workshop399/classes/task/cron_task.php ./classes/task/cron_task.php
--- ../workshop399/classes/task/cron_task.php	2021-07-29 11:01:07.000000000 +0900
+++ ./classes/task/cron_task.php	2022-05-16 00:25:48.875730240 +0900
@@ -53,7 +53,6 @@
 
         mtrace(' processing workshop subplugins ...');
 
-        // Now when the scheduled allocator had a chance to do its job.
         // Check if there are some workshops to switch into the assessment phase.
         $workshops = $DB->get_records_select("workshop",
             "phase = 20 AND phaseswitchassessment = 1 AND submissionend > 0 AND submissionend < ?", [$now]);
@@ -61,6 +60,7 @@
         if (!empty($workshops)) {
             mtrace('Processing automatic assessment phase switch in ' . count($workshops) . ' workshop(s) ... ', '');
             require_once($CFG->dirroot . '/mod/workshop/locallib.php');
+            require_once($CFG->dirroot . '/mod/workshop/classes/event/phase_automatically_switched.php');
             foreach ($workshops as $workshop) {
                 $cm = get_coursemodule_from_instance('workshop', $workshop->id, $workshop->course, false, MUST_EXIST);
                 $course = $DB->get_record('course', ['id' => $cm->course], '*', MUST_EXIST);
@@ -72,10 +72,11 @@
                     'context' => $workshop->context,
                     'courseid' => $workshop->course->id,
                     'other' => [
-                        'workshopphase' => $workshop->phase
+                        'targetworkshopphase' => $workshop->phase,
+                        'previousworkshopphase' => \workshop::PHASE_SUBMISSION,
                     ]
                 ];
-                $event = \mod_workshop\event\phase_switched::create($params);
+                $event = \mod_workshop\event\phase_automatically_switched::create($params);
                 $event->trigger();
 
                 // Disable the automatic switching now so that it is not executed again by accident.
diff -Nru ../workshop399/lang/en/workshop.php ./lang/en/workshop.php
--- ../workshop399/lang/en/workshop.php	2021-07-29 11:01:07.000000000 +0900
+++ ./lang/en/workshop.php	2022-05-14 21:16:06.561066638 +0900
@@ -125,6 +125,7 @@
 $string['eventsubmissionupdated'] = 'Submission updated';
 $string['eventsubmissiondeleted'] = 'Submission deleted';
 $string['eventsubmissionviewed'] = 'Submission viewed';
+$string['eventphaseautomaticallyswitched'] = 'Phase automatically switched';
 $string['eventphaseswitched'] = 'Phase switched';
 $string['example'] = 'Example submission';
 $string['exampleadd'] = 'Add example submission';
diff -Nru ../workshop399/upgrade.txt ./upgrade.txt
--- ../workshop399/upgrade.txt	2021-07-29 11:01:07.000000000 +0900
+++ ./upgrade.txt	2022-05-14 21:16:06.561066638 +0900
@@ -1,6 +1,15 @@
 This files describes API changes in /mod/workshop - activity modules,
 information provided here is intended especially for developers.
 
+=== 3.11.5  ===
+
+* \mod_workshop\event\phase_automatically_switched event is triggered when the phase is automatically switched within
+  the cron task.
+* A new method \workshopallocation_scheduled::phase_automatically_switched added to handle the
+  \mod_workshop\event\phase_automatically_switched event.
+* A new boolean parameter, $checksubmissionphase, has been added to the workshop_scheduled_allocator::execute() method
+  in order to allow (or not) the allocation of submissions to be done in phases other than the SUBMISSION_PHASE.
+
 === 3.8 ===
 
 * The following functions have been finally deprecated and can not be used anymore:
