1212use Illuminate \Support \Facades \DB ;
1313use Illuminate \Support \Facades \Log ;
1414use Illuminate \Support \Facades \Schema ;
15+ use InvalidArgumentException ;
1516use Illuminate \Support \Str ;
1617use PDOException ;
1718use ProcessMaker \Facades \WorkflowManager ;
@@ -203,10 +204,11 @@ private function processTaskWithAtomicClaim(ScheduledTask $task, DateTime $today
203204 {
204205 try {
205206 $ config = json_decode ($ task ->configuration );
206- $ lastExecution = new DateTime ($ task ->last_execution , new DateTimeZone ('UTC ' ));
207207
208- if ($ lastExecution === null ) {
209- return ;
208+ // SCHEDULED_JOB rows use last_execution = null until first run; BPMN timers always set last_execution.
209+ $ lastExecution = null ;
210+ if ($ task ->last_execution !== null && $ task ->last_execution !== '' ) {
211+ $ lastExecution = new DateTime ($ task ->last_execution , new DateTimeZone ('UTC ' ));
210212 }
211213
212214 $ owner = $ task ->processRequestToken ?: $ task ->processRequest ?: $ task ->process ;
@@ -888,6 +890,9 @@ public function scheduleCycle(
888890 */
889891 public function scheduleCycleJob ($ interval , array $ config ): ScheduledTask
890892 {
893+ if (!isset ($ config ['job ' ])) {
894+ throw new InvalidArgumentException ('$config["job"] is required ' );
895+ }
891896 $ configuration = [
892897 'type ' => 'TimeCycle ' ,
893898 'interval ' => $ interval ,
@@ -904,6 +909,36 @@ public function scheduleCycleJob($interval, array $config): ScheduledTask
904909 return $ scheduledTask ;
905910 }
906911
912+ /**
913+ * Schedule a job for a specific datetime
914+ *
915+ * @param string $datetime in ISO-8601 format
916+ * @param array $config configuration
917+ *
918+ * @return ScheduledTask
919+ */
920+ public function scheduleDateJob ($ datetime , array $ config ): ScheduledTask
921+ {
922+ if (!isset ($ config ['job ' ])) {
923+ throw new InvalidArgumentException ('$config["job"] is required ' );
924+ }
925+
926+ // Must use "interval" so nextDate(TimeDate) picks up the target datetime (same shape as BPMN timer tasks).
927+ $ configuration = [
928+ 'type ' => 'TimeDate ' ,
929+ ...$ config ,
930+ 'interval ' => $ datetime ,
931+ ];
932+
933+ $ scheduledTask = new ScheduledTask ();
934+ $ scheduledTask ->configuration = json_encode ($ configuration );
935+ $ scheduledTask ->type = 'SCHEDULED_JOB ' ;
936+ $ scheduledTask ->last_execution = null ;
937+ $ scheduledTask ->save ();
938+
939+ return $ scheduledTask ;
940+ }
941+
907942 /**
908943 * Schedule a job execution after a time duration for the given BPMN element,
909944 * event definition and an optional Token object
0 commit comments