Location: PHPKode > projects > PhpBMS > phpbms/modules/recurringinvoices/scheduler_recurr.php
<?php
//uncomment if need debug
//if(!class_exists("appError"))
//	include_once("../../include/session.php");


class recurr{

	function recurr($db){
		$this->db = $db;
	}


	function getInvoicesToRepeat($dateToCheck = NULL){
		if($dateToCheck == NULL)
			$dateToCheck = mktime(0,0,0);

		$invoiceList = array();

		$querystatement = "
			SELECT
				`invoiceid`,
				`invoices`.`invoicedate`,
				`firstrepeat`,
				`lastrepeat`,
				`recurringinvoices`.`type`,
				`eachlist`,`every`,
				`ontheday`,`ontheweek`
			FROM
				`recurringinvoices` INNER JOIN `invoices` ON `recurringinvoices`.`invoiceid` = `invoices`.`uuid`
			WHERE
				`invoices`.`invoicedate` <= '".dateToString($dateToCheck,"SQL")."'
				AND
				(`recurringinvoices`.`until` IS NULL OR `recurringinvoices`.`until` >= '".dateToString($dateToCheck,"SQL")."')
				AND
				(`recurringinvoices`.`times` IS NULL OR `recurringinvoices`.`times` > `recurringinvoices`.`timesrepeated`)";

		$queryresult = $this->db->query($querystatement);

		while($therecord = $this->db->fetchArray($queryresult)){

			if($therecord["lastrepeat"])
				$startDate = stringToDate($therecord["lastrepeat"],"SQL");
			else
				$startDate = stringToDate($therecord["invoicedate"],"SQL");

			$dateArray = $this->getValidInRange($startDate,$dateToCheck,$therecord);

			if( in_array($dateToCheck, $dateArray))
				$invoiceList[] = $therecord["invoiceid"];

		}//end while

		return $invoiceList;

	}//end method


	function getValidInRange($startDate,$endDate,$therecord){
		$nextDate = $startDate;

		//should pad the end date to make sure we get all weekly repeats
		$endDate = strtotime("+7 days",$endDate);

		$validDates = array();

		while($nextDate <= $endDate){

			switch($therecord["type"]){
				case "Daily":
					//==================================================================================
					$validDates[] = $nextDate;
					$nextDate = strtotime("+".$therecord["every"]." days",$nextDate);
					break;

				case "Weekly":
					//==================================================================================
					$weekDayArray = explode("::",$therecord["eachlist"]);

					//need to start from the sunday of the current week
					$tempDate = strtotime(nl_langinfo( constant("DAY_1") ),$nextDate);
					$tempDate = strtotime("-7 days",$tempDate);

					foreach($weekDayArray as $weekday){
						if($weekday == 7)
							$validDates[]=$tempDate;
						else{
							$weekday++;
							$validDates[] = strtotime(nl_langinfo( constant("DAY_".$weekday) ),$tempDate);
						}
					}// endforeach


					$nextDate = strtotime("+".$therecord["every"]." week",$nextDate);

					break;

				case "Monthly":
					//==================================================================================
					$dateArray = localtime($nextDate,true);

					if($therecord["eachlist"]){
						$dayArray = explode("::",$therecord["eachlist"]);

						foreach($dayArray as $theday)
							$validDates[] = mktime(0,0,0,$dateArray["tm_mon"]+1,$theday,$dateArray["tm_year"]+1900);

					} else{
						// check for things like second tuesday or last friday;
						$tempDate = mktime(0,0,0,$dateArray["tm_mon"]+1,1,$dateArray["tm_year"]+1900);
						$weekday = $therecord["ontheday"];
						$weekday = ($weekday == 7)? 1: ($weekday+1);
						if($therecord["ontheday"] != @strftime("%u",$tempDate));
							$tempDate = strtotime(nl_langinfo( constant("DAY_".$weekday) ),$tempDate);

						while(date("n",$tempDate) == ($dateArray["tm_mon"]+1)){

							if($therecord["ontheweek"] == 5){
								// 5 is the "last" option, so we just need to see if
								// the date falls in the last 6 days
								if($daysInMonth - date("d",$tempDate) < 7)
									$validDates[] = $tempDate;

							} else {
								if( ceil(date("d",$tempDate)/7) == $therecord["ontheweek"])
									$validDates[] = $tempDate;
							}// endif

							$tempDate = strtotime("+7 days",$tempDate);

						}// endwhile
					}//endif

					$nextDate = strtotime("+".$therecord["every"]." months",$nextDate);
					break;

				case "Yearly":
					//==================================================================================
					$monthArray = explode("::",$therecord["eachlist"]);
					foreach($monthArray as $monthNum){
						$dateArray = localtime($nextDate,true);
						$daysInMonth = date("d", mktime(0,0,0,$monthNum,0,$dateArray["tm_year"]+1900) );

						if(!$therecord["ontheday"]){
							$tempDay = ($dateArray["tm_mday"] > $daysInMonth)? $daysInMonth :$dateArray["tm_mday"];
							$validDates[] = mktime(0,0,0,$monthNum,$tempDay,$dateArray["tm_year"]+1900);

						} else {
							// check for things like second tuesday or last friday;
							$tempDate = mktime(0,0,0,$monthNum,1,$dateArray["tm_year"]+1900);

							$weekday = $therecord["ontheday"];
							$weekday = ($weekday == 7)? 1: ($weekday+1);
							if($therecord["ontheday"] != @strftime("%u",$tempDate));
								$tempDate = strtotime(nl_langinfo( constant("DAY_".$weekday) ),$tempDate);


							while(date("n",$tempDate) == $monthNum){
								if($therecord["ontheweek"] == 5){
									// 5 is the "last" option, so we just need to see if
									// the date falls in the last 6 days
									if($daysInMonth - date("d",$tempDate) < 7)
										$validDates[] = $tempDate;

								} else {
									if( ceil(date("d",$tempDate)/7) == $therecord["ontheweek"])
										$validDates[] = $tempDate;
								}// endif

								$tempDate = strtotime("+7 days",$tempDate);

							}// endwhile

						}//endif

					}//endforeach

					$nextDate = strtotime("+".$therecord["every"]." years",$nextDate);

					break;
			}//endswitch

		}//end while

		return $validDates;

	}//end method


	function copyInvoice($invoiceid){
		$querystatement = "
			SELECT
				invoices.*,
				firstrepeat,
				includepaymenttype,
				recurringinvoices.id AS recurrid,
				recurringinvoices.statusid AS newstatusid,
				recurringinvoices.assignedtoid AS newassignedtoid,
				notificationroleid
			FROM
				invoices INNER JOIN recurringinvoices ON invoices.uuid = recurringinvoices.invoiceid
			WHERE
				invoices.uuid = '".$invoiceid."'
		";

		$queryresult = $this->db->query($querystatement);

		$therecord = $this->db->fetchArray($queryresult);

		$fieldList = array();

		foreach($therecord as $name=>$value){
			switch($name){
				case "id":
				case "notificationroleid":
				case "includepaymenttype":
				case "modifiedby":
				case "modifieddate":
				case "createdby":
				case "creationdate":
				case "newstatusid":
				case "newassignedtoid":
				case "firstrepeat":
				case "recurrid":
				case "bankname":
				case "ccnumber":
				case "routingnumber":
				case "ccexpiration":
				case "ccverification":
				case "accountnumber":
					break;

				case "uuid":
					$fieldlist[] = "uuid";
					$therecord["uuid"] = uuid(getUuidPrefix($this->db, "tbld:62fe599d-c18f-3674-9e54-b62c2d6b1883").":");
					break;

				case "checkno":
				case "webconfirmationno":
				case "trackingno":
				case "weborder":
				case "transactionid":
				case "invoicedate":
					$fieldlist[] = $name;
					$therecord[$name] = NULL;
					break;

				case "statusdate":
				case "orderdate":
					$fieldlist[] = $name;
					$therecord[$name] = dateToString(mktime(),"SQL");
					break;

				case "paymenttypeid":
					$fieldlist[] = $name;
					if(!$therecord["includepaymenttype"])
						$therecord[$name] = NULL;
					break;

				case "statusid":
					$fieldlist[] = $name;
					$therecord[$name] = $therecord["newstatusid"];
					break;

				case "assignedtoid":
					$fieldlist[] = $name;
					$therecord[$name] = $therecord["newassignedtoid"];
					break;

				case "amountpaid":
					$fieldlist[] = $name;
					$therecord[$name] = 0;
					break;

				case "type":
					$fieldlist[] = $name;
					$therecord[$name] = "Order";
					break;

				case "readytopost":
					$fieldlist[] = $name;
					$therecord[$name] = 0;
					break;

				default:
					$fieldlist[] = $name;
			}//endswitch
		}//endforeach

		$insertstatement = $this->prepareInsert("invoices",$fieldlist,$therecord);

		$this->db->query($insertstatement);

		$theid = $this->db->insertId();

		$this->copyLineItems($therecord["id"], $theid);

		$this->insertHistory($therecord["uuid"], $therecord["statusid"], $therecord["statusdate"], $therecord["assignedtoid"]);

		$this->updateReccurence($therecord["recurrid"],$therecord["firstrepeat"]);

		if($therecord["notificationroleid"])
			$this->sendNotification($therecord["notificationroleid"],$theid);

	}//end method


	function copyLineItems($oldInvoiceID, $newInvoiceID){

		$querystatement = "SELECT * FROM lineitems WHERE invoiceid = '".$oldInvoiceID."'";
		$queryresult = $this->db->query($querystatement);

		while($therecord = $this->db->fetchArray($queryresult)){

			$fieldlist = array();

			foreach($therecord as $name=>$value){
				switch($name){
					case "id":
					case "modifiedby":
					case "modifieddate":
					case "createdby":
					case "creationdate":
						break;

					case "invoiceid":
						$therecord[$name] = $newInvoiceID;
						$fieldlist[] = $name;
						break;

					default:
						$fieldlist[] = $name;
				}// endswitch
			}// endforeach

			$insertstatement = $this->prepareInsert("lineitems",$fieldlist,$therecord);

			$this->db->query($insertstatement);

		}// endwhile

	}//end method


	function prepareInsert($tablename, $fieldlist, $therecord){
		$insertstatement = "INSERT INTO ".$tablename." (";

		foreach($fieldlist as $name)
			$insertstatement .= "`".$name."`, ";

		$insertstatement .= " createdby,creationdate) VALUES (";

		foreach($fieldlist as $name)
			if($therecord[$name] !== NULL)
				$insertstatement .= "'".$therecord[$name]."', ";
			else
				$insertstatement .= "NULL, ";

		$insertstatement .="-3, NOW());";

		return $insertstatement;
	}//end method


	function insertHistory($invoiceid, $statusid, $statusdate, $assignedtoid){
		$insertstatement = "INSERT INTO invoicestatushistory (invoiceid, invoicestatusid, statusdate, assignedtoid) VALUES (";
		$insertstatement .= "'".$invoiceid."', ";
		$insertstatement .= "'".$statusid."', ";
		$insertstatement .= "'".$statusdate."', ";
		$insertstatement .= "'".$assignedtoid."')";

		$this->db->query($insertstatement);

	}//end method


	function updateReccurence($recurrid, $firstrepeat){
		$updatestatement = "UPDATE recurringinvoices SET timesrepeated = timesrepeated+1, lastrepeat=NOW()";
		if(!$firstrepeat)
			$updatestatement .= ", firstrepeat=NOW()";

		$updatestatement .= " WHERE id = ".$recurrid;

		$this->db->query($updatestatement);

	}


	function sendNotification($roleid, $newInvoiceID){
		if($roleid == -100)
			$whereclause = "users.admin = 1";
		else
			$whereclause = "rolestousers.roleid = '".$roleid."'";

		$querystatement = "SELECT email FROM rolestousers INNER JOIN users ON rolestousers.userid = users.uuid
							WHERE email != '' AND ".$whereclause;

		$queryresult = $this->db->query($querystatement);

		$subject = APPLICATION_NAME." recurring invoice notification.";
		$message = APPLICATION_NAME." has created a new order from a recurring invoice.  The new order id is ".$newInvoiceID;

		while($therecord = $this->db->fetchArray($queryresult)){
			$to = $therecord["email"];
			$headers = "From: ".$to;

			@ mail ($to,$subject,$message,$headers);
		}// endwhile

	}//end method
}//end class



//PROCESSOR
//=============================================================================================
if(!isset($noOutput)){
	$recurr = new recurr($db);
	$invoiceArray = $recurr->getInvoicesToRepeat();
	foreach($invoiceArray as $invoiceid)
		$recurr->copyInvoice($invoiceid);
}
?>
Return current item: PhpBMS