NEW Add a method doAutoRenewContracts that can be used as a cron task
This commit is contained in:
parent
e9b370e7c0
commit
7b395f9f0f
@ -2600,6 +2600,177 @@ class Contrat extends CommonObject
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Action executed by scheduler
|
||||
* CAN BE A CRON TASK
|
||||
* Loop on each contract lines and update the end of date. Do not execute the update if there is one pending invoice linked to contract.
|
||||
*
|
||||
* @param int $thirdparty_id Thirdparty id
|
||||
* @param int $delayindaysshort To renew the resources x day before (positive value) or after (negative value) the end of date (default is 0)
|
||||
* @return int 0 if OK, <>0 if KO (this function is used also by cron so only 0 is OK)
|
||||
*/
|
||||
public function doAutoRenewContracts($thirdparty_id = 0, $delayindaysshort = 0)
|
||||
{
|
||||
global $langs, $user;
|
||||
|
||||
$langs->load("agenda");
|
||||
|
||||
$now = dol_now();
|
||||
|
||||
$enddatetoscan = dol_time_plus_duree($now, -1 * abs($delayindaysshort), 'd');
|
||||
|
||||
$error = 0;
|
||||
$this->output = '';
|
||||
$this->error='';
|
||||
|
||||
$contractlineprocessed = array();
|
||||
$contractignored = array();
|
||||
$contracterror = array();
|
||||
|
||||
dol_syslog(__METHOD__, LOG_DEBUG);
|
||||
|
||||
$sql = 'SELECT c.rowid, c.ref_customer, cd.rowid as lid, cd.date_fin_validite, p.duration';
|
||||
$sql.= ' FROM '.MAIN_DB_PREFIX.'contrat as c, '.MAIN_DB_PREFIX.'contratdet as cd';
|
||||
$sql.= ' LEFT JOIN '.MAIN_DB_PREFIX.'product as p ON p.rowid = cd.fk_product';
|
||||
$sql.= ' WHERE cd.fk_contrat = c.rowid';
|
||||
$sql.= " AND date_format(cd.date_fin_validite, '%Y-%m-%d') <= date_format('".$this->db->idate($enddatetoscan)."', '%Y-%m-%d')";
|
||||
$sql.= " AND cd.statut = 4";
|
||||
if ($thirdparty_id > 0) $sql.=" AND c.fk_soc = ".((int) $thirdparty_id);
|
||||
//print $sql;
|
||||
|
||||
$resql = $this->db->query($sql);
|
||||
if ($resql) {
|
||||
$num = $this->db->num_rows($resql);
|
||||
|
||||
include_once DOL_DOCUMENT_ROOT.'/core/class/html.formmail.class.php';
|
||||
|
||||
$i=0;
|
||||
while ($i < $num) {
|
||||
$obj = $this->db->fetch_object($resql);
|
||||
if ($obj) {
|
||||
if (! empty($contractlineprocessed[$obj->lid]) || ! empty($contractignored[$obj->rowid]) || ! empty($contracterror[$obj->rowid])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Load contract
|
||||
$object = new Contrat($this->db);
|
||||
$object->fetch($obj->rowid); // fetch also lines
|
||||
$object->fetch_thirdparty();
|
||||
|
||||
if ($object->id <= 0) {
|
||||
$error++;
|
||||
$this->errors[] = 'Failed to load contract with id='.$obj->rowid;
|
||||
continue;
|
||||
}
|
||||
|
||||
dol_syslog("* Process contract line in doRenewalContracts for contract id=".$object->id." ref=".$object->ref." ref_customer=".$object->ref_customer." contract line id=".$obj->lid);
|
||||
|
||||
// Update expiration date of line
|
||||
$expirationdate = $this->db->jdate($obj->date_fin_validite);
|
||||
$duration_value = preg_replace('/[^0-9]/', '', $obj->duration);
|
||||
$duration_unit = preg_replace('/\d/', '', $obj->duration);
|
||||
//var_dump($expirationdate.' '.$enddatetoscan);
|
||||
|
||||
// Test if there is pending invoice
|
||||
$object->fetchObjectLinked(null, '', null, '', 'OR', 1, 'sourcetype', 1);
|
||||
|
||||
if (is_array($object->linkedObjects['facture']) && count($object->linkedObjects['facture']) > 0) {
|
||||
usort($object->linkedObjects['facture'], "cmp");
|
||||
|
||||
//dol_sort_array($contract->linkedObjects['facture'], 'date');
|
||||
$someinvoicenotpaid=0;
|
||||
foreach ($object->linkedObjects['facture'] as $idinvoice => $invoice) {
|
||||
if ($invoice->statut == Facture::STATUS_DRAFT) continue; // Draft invoice are not invoice not paid
|
||||
|
||||
if (empty($invoice->paye)) {
|
||||
$someinvoicenotpaid++;
|
||||
}
|
||||
}
|
||||
if ($someinvoicenotpaid) {
|
||||
$this->output .= 'Contract '.$object->ref.' is qualified for renewal but there is '.$someinvoicenotpaid.' invoice(s) unpayed so we cancel renewal'."\n";
|
||||
$contractignored[$object->id]=$object->ref;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if ($expirationdate && $expirationdate < $enddatetoscan) {
|
||||
dol_syslog("Define the newdate of end of services from expirationdate=".$expirationdate);
|
||||
$newdate = $expirationdate;
|
||||
$protecti=0; //$protecti is to avoid infinite loop
|
||||
while ($newdate < $enddatetoscan && $protecti < 1000) {
|
||||
$newdate = dol_time_plus_duree($newdate, $duration_value, $duration_unit);
|
||||
$protecti++;
|
||||
}
|
||||
|
||||
if ($protecti < 1000) { // If not, there is a pb
|
||||
// We will update the end of date of contrat, so first we refresh contract data
|
||||
dol_syslog("We will update the end of date of contract with newdate = ".dol_print_date($newdate, 'dayhourrfc'));
|
||||
|
||||
$this->db->begin();
|
||||
|
||||
$errorforlocaltransaction = 0;
|
||||
|
||||
$label = 'Renewal of contrat '.$object->ref.' line '.$obj->lid;
|
||||
$comment = 'Renew date of contract '.$object->ref.' line '.$obj->lid.' by doAutoRenewContracts';
|
||||
|
||||
$sqlupdate = 'UPDATE '.MAIN_DB_PREFIX."contratdet SET date_fin_validite = '".$this->db->idate($newdate)."'";
|
||||
$sqlupdate.= ' WHERE rowid = '.((int) $obj->lid);
|
||||
$resqlupdate = $this->db->query($sqlupdate);
|
||||
if ($resqlupdate) {
|
||||
$contractlineprocessed[$obj->lid]=$object->ref;
|
||||
|
||||
$actioncode = 'RENEW_CONTRACT';
|
||||
$now = dol_now();
|
||||
|
||||
// Create an event
|
||||
$actioncomm = new ActionComm($this->db);
|
||||
$actioncomm->type_code = 'AC_OTH_AUTO'; // Type of event ('AC_OTH', 'AC_OTH_AUTO', 'AC_XXX'...)
|
||||
$actioncomm->code = 'AC_'.$actioncode;
|
||||
$actioncomm->label = $label;
|
||||
$actioncomm->datep = $now;
|
||||
$actioncomm->datef = $now;
|
||||
$actioncomm->percentage = -1; // Not applicable
|
||||
$actioncomm->socid = $object->thirdparty->id;
|
||||
$actioncomm->authorid = $user->id; // User saving action
|
||||
$actioncomm->userownerid = $user->id; // Owner of action
|
||||
$actioncomm->fk_element = $object->id;
|
||||
$actioncomm->elementtype = 'contract';
|
||||
$actioncomm->note_private = $comment;
|
||||
|
||||
$ret = $actioncomm->create($user); // User creating action
|
||||
} else {
|
||||
$contracterror[$object->id]=$object->ref;
|
||||
|
||||
$error++;
|
||||
$errorforlocaltransaction++;
|
||||
$this->error = $this->db->lasterror();
|
||||
}
|
||||
|
||||
if (! $errorforlocaltransaction) {
|
||||
$this->db->commit();
|
||||
} else {
|
||||
$this->db->rollback();
|
||||
}
|
||||
} else {
|
||||
$error++;
|
||||
$this->error = "Bad value for newdate in doAutoRenewContracts - expirationdate=".$expirationdate." enddatetoscan=".$enddatetoscan." duration_value=".$duration_value." duration_unit=".$duration_value;
|
||||
dol_syslog($this->error, LOG_ERR);
|
||||
}
|
||||
}
|
||||
}
|
||||
$i++;
|
||||
}
|
||||
} else {
|
||||
$error++;
|
||||
$this->error = $this->db->lasterror();
|
||||
}
|
||||
|
||||
$this->output .= count($contractlineprocessed).' contract line(s) with end date before '.dol_print_date($enddatetoscan, 'day').' were renewed'.(count($contractlineprocessed)>0 ? ' : '.join(',', $contractlineprocessed) : '');
|
||||
|
||||
return ($error ? 1: 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user