id); define("INTERNAL_USER_USERNAME", $me->username); define("MFBASE_BYPASS_LOGIN", true); $sql = "WITH first_status_300_plus AS ( SELECT ph.preorder_id, MIN(ph.create) as first_status_300_timestamp FROM PreorderHistory ph INNER JOIN Preorderstatus ps ON CAST(ph.new_value AS UNSIGNED) = ps.id WHERE ph.key = 'status_id' AND ps.code >= 300 AND ph.create <= UNIX_TIMESTAMP(DATE_SUB(NOW(), INTERVAL 8 WEEK)) GROUP BY ph.preorder_id ) SELECT p.id, p.type, p.preordercampaign_id, pc.name as campaign_name, ps_current.code as current_status_code, ps_current.name as current_status_name, FROM_UNIXTIME(fs.first_status_300_timestamp) as first_reached_300_plus, DATEDIFF(NOW(), FROM_UNIXTIME(fs.first_status_300_timestamp)) as days_since_first_300, pcsmt.mailtemplate_id, pcsmt.logical_config FROM Preorder p INNER JOIN Preordercampaign pc ON p.preordercampaign_id = pc.id INNER JOIN PreordercampaignStatusnotificationMailtemplate pcsmt ON pc.id = pcsmt.preordercampaign_id INNER JOIN Preorderstatus ps_current ON p.status_id = ps_current.id INNER JOIN first_status_300_plus fs ON p.id = fs.preorder_id LEFT JOIN PreorderStatusnotificationLog psnl ON p.id = psnl.preorder_id AND psnl.email_type = '300-custom' WHERE p.type = 'order' AND ps_current.code >= 300 AND ps_current.code < 500 AND pcsmt.notification_type = 'logical' AND JSON_EXTRACT(pcsmt.logical_config, '$.type') = '300-custom' AND psnl.id IS NULL -- No existing '300-custom' notification ORDER BY fs.first_status_300_timestamp ASC;"; $db = FronkDB::singleton(); $db = $db->link; $res = $db->query($sql); // exit if no results if ($res->num_rows == 0) { logMessage("No preorders found for custom 300 notification."); exit; } while($row = $res->fetch_assoc()) { logMessage("Processing Preorder ID: " . $row['id']); $preorder_id = $row['id']; $campaign_name = $row['campaign_name']; $current_status_code = $row['current_status_code']; $current_status_name = $row['current_status_name']; $first_reached_300 = $row['first_reached_300_plus']; $days_since_first_300 = $row['days_since_first_300']; $mailtemplate_id = $row['mailtemplate_id']; $logical_config = json_decode($row['logical_config'], true); $preorder = new Preorder($preorder_id); if (!$preorder || !$preorder->id) { logMessage("Preorder with ID $preorder_id not found. Skipping."); continue; } $preordercampaign = new Preordercampaign($preorder->preordercampaign_id); if (!$preordercampaign || !$preordercampaign->id) { logMessage("Preordercampaign with ID {$preorder->preordercampaign_id} not found. Skipping."); continue; } $mailtemplate = new Mailtemplate($mailtemplate_id); if(!$mailtemplate || !$mailtemplate->id) { logMessage("Mailtemplate with ID $mailtemplate_id not found. Skipping."); continue; } logMessage("Preparing to send email for Preorder ID: $preorder_id, Campaign: $campaign_name"); $subject = $mailtemplate->subject; $body = ""; $body .= $mailtemplate->renderBody(); $body .= "\n"; $body_type = $mailtemplate->body_html ? "html" : "text"; $email = new Emailnotification(); $email->setSubject($subject); if($body_type == "html") { $email->setHtmlBody($body); } else { $email->setBody($body); } $email->setFrom($preordercampaign->from_email, $preordercampaign->from_email_name); $email->setTo($preorder->email); $email->setHeader("X-".ucfirst(MFAPPNAME)."-pid", $preorder->id); $email->setHeader("X-".ucfirst(MFAPPNAME)."-ps", '300-custom'); // add attachments try { foreach ($mailtemplate->files as $file) { if (!$file->filename || !$file->file_id || !$file->file->store_filename) continue; logMessage("Adding attachment: " . $file->filename); $email->addAttachment($file->file->getFullPath(), null, $file->filename, $file->file->mimetype ?: null); } $email->send(); logMessage("Email sent successfully for Preorder ID: $preorder_id"); $psn_log = PreorderStatusnotificationLog::create([ "preorder_id" => $preorder_id, "email_type" => "300-custom", "email" => $preorder->email, ]); $psn_log->save(); // Log the notification $log = new PreorderStatusnotificationLog(); } catch (Exception $e) { logMessage("Error sending email for Preorder ID $preorder_id: " . $e->getMessage()); } }