Tons of fixes and enhancement on recurring invoice generation

This commit is contained in:
Laurent Destailleur 2016-02-16 00:31:05 +01:00
parent 9cbbf07351
commit c78997ed23
12 changed files with 343 additions and 235 deletions

View File

@ -52,6 +52,11 @@ class FactureRec extends Facture
var $db_table;
var $propalid;
var $date_last_gen;
var $next_gen;
var $nb_gen_done;
var $nb_gen_max;
var $rang;
var $special_code;
@ -214,17 +219,17 @@ class FactureRec extends Facture
/**
* Recupere l'objet facture et ses lignes de factures
* Load object and lines
*
* @param int $rowid Id of object to load
* @param string $ref Reference of invoice
* @param string $ref Reference of recurring invoice
* @param string $ref_ext External reference of invoice
* @param int $ref_int Internal reference of other object
* @return int >0 if OK, <0 if KO, 0 if not found
*/
function fetch($rowid, $ref='', $ref_ext='', $ref_int='')
{
$sql = 'SELECT f.titre,f.fk_soc,f.amount,f.tva,f.total,f.total_ttc,f.remise_percent,f.remise_absolue,f.remise';
$sql = 'SELECT f.rowid, f.titre, f.fk_soc, f.amount, f.tva, f.total, f.total_ttc, f.remise_percent, f.remise_absolue, f.remise';
$sql.= ', f.date_lim_reglement as dlr';
$sql.= ', f.note_private, f.note_public, f.fk_user_author';
$sql.= ', f.fk_mode_reglement, f.fk_cond_reglement, f.fk_projet';
@ -232,19 +237,18 @@ class FactureRec extends Facture
$sql.= ', f.frequency, f.unit_frequency, f.date_when, f.date_last_gen, f.nb_gen_done, f.nb_gen_max, f.usenewprice, f.auto_validate';
$sql.= ', p.code as mode_reglement_code, p.libelle as mode_reglement_libelle';
$sql.= ', c.code as cond_reglement_code, c.libelle as cond_reglement_libelle, c.libelle_facture as cond_reglement_libelle_doc';
$sql.= ', el.fk_source';
//$sql.= ', el.fk_source';
$sql.= ' FROM '.MAIN_DB_PREFIX.'facture_rec as f';
$sql.= ' LEFT JOIN '.MAIN_DB_PREFIX.'c_payment_term as c ON f.fk_cond_reglement = c.rowid';
$sql.= ' LEFT JOIN '.MAIN_DB_PREFIX.'c_paiement as p ON f.fk_mode_reglement = p.id';
$sql.= " LEFT JOIN ".MAIN_DB_PREFIX."element_element as el ON el.fk_target = f.rowid AND el.targettype = 'facture'";
$sql.= ' WHERE f.rowid='.$rowid;
if ($ref) $sql.= " AND f.titre='".$this->db->escape($ref)."'";
//$sql.= " LEFT JOIN ".MAIN_DB_PREFIX."element_element as el ON el.fk_target = f.rowid AND el.targettype = 'facture'";
if ($rowid) $sql.= ' WHERE f.rowid='.$rowid;
elseif ($ref) $sql.= " WHERE f.titre='".$this->db->escape($ref)."'";
/* This field are not used for template invoice
if ($ref_ext) $sql.= " AND f.ref_ext='".$this->db->escape($ref_ext)."'";
if ($ref_int) $sql.= " AND f.ref_int='".$this->db->escape($ref_int)."'";
*/
dol_syslog(get_class($this)."::fetch rowid=".$rowid, LOG_DEBUG);
$result = $this->db->query($sql);
if ($result)
{
@ -252,7 +256,7 @@ class FactureRec extends Facture
{
$obj = $this->db->fetch_object($result);
$this->id = $rowid;
$this->id = $obj->rowid;
$this->titre = $obj->titre;
$this->ref = $obj->titre;
$this->ref_client = $obj->ref_client;
@ -290,8 +294,8 @@ class FactureRec extends Facture
$this->special_code = $obj->special_code;
$this->frequency = $obj->frequency;
$this->unit_frequency = $obj->unit_frequency;
$this->date_when = $obj->date_when;
$this->date_last_gen = $obj->date_last_gen;
$this->date_when = $this->db->jdate($obj->date_when);
$this->date_last_gen = $this->db->jdate($obj->date_last_gen);
$this->nb_gen_done = $obj->nb_gen_done;
$this->nb_gen_max = $obj->nb_gen_max;
$this->usenewprice = $obj->usenewprice;
@ -305,14 +309,14 @@ class FactureRec extends Facture
$result=$this->fetch_lines();
if ($result < 0)
{
$this->error=$this->db->error();
$this->error=$this->db->lasterror();
return -3;
}
return 1;
}
else
{
$this->error='Bill with id '.$rowid.' not found sql='.$sql;
$this->error='Bill with id '.$rowid.' or ref '.$ref.' not found sql='.$sql;
dol_syslog('Facture::Fetch Error '.$this->error, LOG_ERR);
return -2;
}
@ -336,7 +340,7 @@ class FactureRec extends Facture
$sql.= ' l.remise, l.remise_percent, l.subprice,';
$sql.= ' l.total_ht, l.total_tva, l.total_ttc,';
$sql.= ' l.rang, l.special_code,';
$sql.= ' l.fk_unit,';
$sql.= ' l.fk_unit, l.fk_contract_line,';
$sql.= ' p.ref as product_ref, p.fk_product_type as fk_product_type, p.label as product_label, p.description as product_desc';
$sql.= ' FROM '.MAIN_DB_PREFIX.'facturedet_rec as l';
$sql.= ' LEFT JOIN '.MAIN_DB_PREFIX.'product as p ON l.fk_product = p.rowid';
@ -380,7 +384,8 @@ class FactureRec extends Facture
$line->rang = $objp->rang;
$line->special_code = $objp->special_code;
$line->fk_unit = $objp->fk_unit;
$line->fk_contract_line = $objp->fk_contract_line;
// Ne plus utiliser
$line->price = $objp->price;
$line->remise = $objp->remise;
@ -578,53 +583,101 @@ class FactureRec extends Facture
function getNextDate()
{
if (empty($this->date_when)) return false;
return dol_time_plus_duree(strtotime($this->date_when), $this->frequency, $this->unit_frequency);
return dol_time_plus_duree($this->date_when, $this->frequency, $this->unit_frequency);
}
/**
* Create all recurrents invoices
* Create all recurrents invoices.
* A result may also be provided into this->output
*
* @return int number of created invoices
* @return int 0 if OK, < 0 if KO (this function is used also by cron so only 0 is OK)
*/
function createRecurringInvoices()
{
global $db,$user;
global $langs, $db, $user;
$langs->load("bills");
$nb_create=0;
$today = date('Y-m-d 23:59:59');
$now = dol_now();
$tmparray=dol_getdate($now);
$today = dol_mktime(23,59,59,$tmparray['mon'],$tmparray['mday'],$tmparray['year']); // Today is last second of current day
dol_syslog("createRecurringInvoices");
$sql = 'SELECT rowid FROM '.MAIN_DB_PREFIX.'facture_rec';
$sql.= ' WHERE date_when IS NOT NULL AND frequency > 0';
$sql.= ' AND date_when <= "'.$db->escape($today).'"';
$sql.= ' AND nb_gen_done < nb_gen_max';
$sql.= ' WHERE frequency > 0'; // A recurring invoice is an invoice with a frequency
$sql.= " AND (date_when IS NULL OR date_when <= '".$db->idate($today)."')";
$sql.= ' AND (nb_gen_done < nb_gen_max OR nb_gen_max = 0)';
//print $sql;exit;
$resql = $db->query($sql);
if ($resql)
{
while ($line = $db->fetch_object($resql))
$i=0;
$num = $db->num_rows($resql);
if ($num) $this->output.=$langs->trans("FoundXQualifiedRecurringInvoiceTemplate", $num)."\n";
else $this->output.=$langs->trans("NoQualifiedRecurringInvoiceTemplateFound");
while ($i < $num)
{
$line = $db->fetch_object($resql);
$db->begin();
$facturerec = new FactureRec($db);
$facturerec->fetch($line->rowid);
$facture = new Facture($db);
$result = $facture->createFromRec($user, $facturerec);
// >0 create and validate if auto_validate
// =0 create but not validate if auto_validate
// <0 broken
if ($result >= 0)
dol_syslog("createRecurringInvoices Process invoice template id=".$facturerec->id.", ref=".$facturerec->ref);
$error=0;
$facture = new Facture($db);
$facture->fac_rec = $facturerec->id; // We will create $facture from this recurring invoice
$facture->type = self::TYPE_STANDARD;
$facture->brouillon = 1;
$facture->date = $now;
$facture->socid = $facturerec->socid;
$invoiceidgenerated = $facture->create($user); // This will also update fields of recurring invoice
if ($invoiceidgenerated <= 0)
{
$this->errors = $facture->errors;
$this->error = $facture->error;
$error++;
}
if (! $error && $facturerec->auto_validate)
{
$result = $facture->validate($user);
if ($result <= 0)
{
$this->errors = $facture->errors;
$this->error = $facture->error;
$error++;
}
}
if (! $error && $invoiceidgenerated >= 0)
{
$next_date = $facturerec->getNextDate();
$facturerec->setNextDate($next_date,1);
$db->commit();
dol_syslog("createRecurringInvoices Process invoice template ".$facturerec->ref." is finished with a success generation");
$nb_create++;
$this->output.=$langs->trans("InvoiceGeneratedFromTemplate", $facture->ref, $facturerec->ref)."\n";
}
else
{
$db->rollback();
}
$i++;
}
}
else dol_print_error($db);
return $nb_create;
$this->output=trim($this->output);
return $error?$error:0;
}
/**

View File

@ -217,6 +217,7 @@ class Facture extends CommonInvoice
/**
* Create invoice in database
* Note: this->ref can be set or empty. If empty, we will use "(PROV)"
* Note: this->fac_rec must be set to create from recurring invoice
*
* @param User $user Object user that create
* @param int $notrigger 1=Does not execute triggers, 0 otherwise
@ -270,16 +271,17 @@ class Facture extends CommonInvoice
$this->db->begin();
// Create invoice from a predefined invoice
// Create invoice from a template invoice
if ($this->fac_rec > 0)
{
require_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture-rec.class.php';
$_facrec = new FactureRec($this->db);
$result=$_facrec->fetch($this->fac_rec);
$this->socid = $_facrec->socid;
$this->fk_project = $_facrec->fk_project;
$this->fk_account = $_facrec->fk_account;
$this->note_private = $_facrec->note_private;
$this->cond_reglement_id = $_facrec->cond_reglement_id;
$this->mode_reglement_id = $_facrec->mode_reglement_id;
$this->remise_absolue = $_facrec->remise_absolue;
@ -287,14 +289,31 @@ class Facture extends CommonInvoice
$this->fk_incoterms = $_facrec->fk_incoterms;
$this->location_incoterms= $_facrec->location_incoterms;
$this->note_public = $_facrec->note_public;
$this->note_private = $_facrec->note_private;
// Clean parameters
if (! $this->type) $this->type = self::TYPE_STANDARD;
$this->ref_client=trim($this->ref_client);
$this->note_private=trim($this->note_private);
$this->note_public=trim($this->note_public);
$this->note_private=trim($this->note_private);
$this->note_private=dol_concatdesc($facture->note_private, $langs->trans("GeneratedFromRecurringInvoice", $_facrec->ref));
//if (! $this->remise) $this->remise = 0;
if (! $this->mode_reglement_id) $this->mode_reglement_id = 0;
$this->brouillon = 1;
$forceduedate = $this->calculate_date_lim_reglement();
// Update date and number of last generation of recurring template invoice, before inserting new invoice
if ($_facrec->frequency > 0)
{
$_facrec->nb_gen_done++;
$next_date = $_facrec->getNextDate(); // Calculate next date
$_facrec->setValueFrom('date_last_gen', $now, '', null, 'date');
$_facrec->setValueFrom('nb_gen_done', $_facrec->nb_gen_done + 1);
$_facrec->setNextDate($next_date,1);
}
}
// Define due date if not already defined
@ -919,60 +938,6 @@ class Facture extends CommonInvoice
else return -1;
}
/**
* Create a new invoice in database from facturerec
*
* @param User $user Object user that ask creation
* @param FactureRec $facturerec Object facturerec source
* @return int <0 if KO, 0 if not validate, >0 if OK
*/
function createFromRec($user, $facturerec)
{
// Clean parameters
$this->type = self::TYPE_STANDARD;
$this->brouillon = 1;
// Charge facture source
$facture=new Facture($facturerec->db);
$facture->socid = $facturerec->socid;
$facture->date = dol_mktime(12, 0, 0, date('m'), date('d'), date('Y'));
$facture->note_public = $facturerec->note_public;
$facture->note_private = $facturerec->note_private;
$facture->fk_project = $facturerec->fk_project;
$facture->fk_account = $facturerec->fk_account;
$facture->cond_reglement_id = $facturerec->cond_reglement_id;
$facture->mode_reglement_id = $facturerec->mode_reglement_id;
$new_date_lim_reglement = $facture->calculate_date_lim_reglement();
$facture->date_lim_reglement = $new_date_lim_reglement;
$facture->remise_absolue = $facturerec->remise_absolue;
$facture->remise_percent = $facturerec->remise_percent;
$facture->lines = $facturerec->lines; // Tableau des lignes de factures
// Loop on each line of new invoice
foreach($facture->lines as $i => $line)
{
$facture->lines[$i]->fk_prev_id = $facturerec->lines[$i]->rowid;
}
dol_syslog(get_class($this)."::createFromRec socid=".$this->socid." nboflines=".count($facture->lines));
$facid = $facture->create($user);
if ($facid <= 0) return -1;
if ($facturerec->auto_validate)
{
$result = $facture->validate($user);
if ($result<=0) return 0;
}
return $facid;
}
/**
* Return clicable link of object (with eventually picto)
*

View File

@ -38,6 +38,7 @@ $langs->load('compta');
// Security check
$id=(GETPOST('facid','int')?GETPOST('facid','int'):GETPOST('id','int'));
$ref=GETPOST('ref','alpha');
$action=GETPOST('action', 'alpha');
if ($user->societe_id) $socid=$user->societe_id;
$objecttype = 'facture_rec';
@ -58,9 +59,9 @@ if ($sortfield == "")
$sortfield="f.datef";
$object = new FactureRec($db);
if ($id > 0 && $action != 'create' && $action != 'add')
if (($id > 0 || $ref) && $action != 'create' && $action != 'add')
{
$ret = $object->fetch($id);
$ret = $object->fetch($id, $ref);
if (!$ret)
{
setEventMessages($langs->trans("ErrorRecordNotFound"), null, 'errors');
@ -192,6 +193,7 @@ $permissionnote=$user->rights->facture->creer; // Used by the include of actions
include DOL_DOCUMENT_ROOT.'/core/actions_setnotes.inc.php'; // Must be include, not includ_once
/*
* View
*/
@ -201,6 +203,11 @@ llxHeader('',$langs->trans("RepeatableInvoices"),'ch-facture.html#s-fac-facture-
$form = new Form($db);
$companystatic = new Societe($db);
$now = dol_now();
$tmparray=dol_getdate($now);
$today = dol_mktime(23,59,59,$tmparray['mon'],$tmparray['mday'],$tmparray['year']); // Today is last second of current day
/*
* Create mode
*/
@ -211,7 +218,7 @@ if ($action == 'create')
$object = new Facture($db); // Source invoice
$product_static = new Product($db);
if ($object->fetch($id) > 0)
if ($object->fetch($id, $ref) > 0)
{
print '<form action="fiche-rec.php" method="post">';
print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
@ -542,7 +549,7 @@ else
print '<table class="border" width="100%">';
$linkback = '<a href="' . DOL_URL_ROOT . '/compta/facture/fiche-rec.php' . (! empty($socid) ? '?socid=' . $socid : '') . '">' . $langs->trans("BackToList") . '</a>';
// Ref
print '<tr><td width="20%">' . $langs->trans('Ref') . '</td>';
print '<td colspan="5">';
@ -557,7 +564,7 @@ else
if ($result < 0) {
dol_print_error('', $discount->error);
}*/
print $form->showrefnav($object, 'ref', $linkback, 1, 'facnumber', 'ref', $morehtmlref);
print $form->showrefnav($object, 'ref', $linkback, 1, 'titre', 'titre', $morehtmlref);
print '</td></tr>';
@ -669,7 +676,6 @@ else
print "</td>";
print '</tr>';
print "</table>";
print '<br>';
@ -716,77 +722,90 @@ else
}
print '</td></tr>';
//if (! empty($object->frequency)) // If no frequency defined, it is not a recurring template invoice
//{
// Date when
print '<tr><td>';
if ($action == 'date_when' || $object->frequency > 0)
{
print $form->editfieldkey($langs->trans("NextDateToExecution"), 'date_when', $object->date_when, $object, $user->rights->facture->creer, 'dayhour');
}
else
{
print $langs->trans("NextDateToExecution");
}
print '</td><td colspan="5">';
if ($action == 'date_when' || $object->frequency > 0)
{
print $form->editfieldval($langs->trans("NextDateToExecution"), 'date_when', $object->date_when, $object, $user->rights->facture->creer, 'dayhour');
}
print '</td>';
print '</tr>';
// Max period / Rest period
print '<tr><td>';
if ($action == 'nb_gen_max' || $object->frequency > 0)
{
print $form->editfieldkey($langs->trans("MaxPeriodNumber"), 'nb_gen_max', $object->nb_gen_max, $object, $user->rights->facture->creer);
}
else
{
print $langs->trans("MaxPeriodNumber");
}
print '</td><td colspan="5">';
if ($action == 'nb_gen_max' || $object->frequency > 0)
{
print $form->editfieldval($langs->trans("MaxPeriodNumber"), 'nb_gen_max', $object->nb_gen_max, $object, $user->rights->facture->creer);
}
else
{
print '';
}
print '</td>';
print '</tr>';
print '<tr><td>'.$langs->trans("RestPeriodNumber").'</td>';
print '<td>';
if ($object->frequency > 0)
{
print ($object->nb_gen_max-$object->nb_gen_done);
}
print '</td>';
// Status of generated invoices
print '<tr><td>';
if ($action == 'auto_validate' || $object->frequency > 0)
print $form->editfieldkey($langs->trans("StatusOfGeneratedInvoices"), 'auto_validate', $object->auto_validate, $object, $user->rights->facture->creer);
else
print $langs->trans("StatusOfGeneratedInvoices");
print '</td><td colspan="5">';
$select = 'select;0:'.$langs->trans('BillStatusDraft').',1:'.$langs->trans('BillStatusValidated');
if ($action == 'auto_validate' || $object->frequency > 0)
{
print $form->editfieldval($langs->trans("StatusOfGeneratedInvoices"), 'auto_validate', $object->auto_validate, $object, $user->rights->facture->creer, $select);
}
print '</td>';
print '</tr>';
//}
// Date when
print '<tr><td>';
if ($action == 'date_when' || $object->frequency > 0)
{
print $form->editfieldkey($langs->trans("NextDateToExecution"), 'date_when', $object->date_when, $object, $user->rights->facture->creer, 'day');
}
else
{
print $langs->trans("NextDateToExecution");
}
print '</td><td colspan="5">';
if ($action == 'date_when' || $object->frequency > 0)
{
print $form->editfieldval($langs->trans("NextDateToExecution"), 'date_when', $object->date_when, $object, $user->rights->facture->creer, 'day');
}
print '</td>';
print '</tr>';
// Max period / Rest period
print '<tr><td>';
if ($action == 'nb_gen_max' || $object->frequency > 0)
{
print $form->editfieldkey($langs->trans("MaxPeriodNumber"), 'nb_gen_max', $object->nb_gen_max, $object, $user->rights->facture->creer);
}
else
{
print $langs->trans("MaxPeriodNumber");
}
print '</td><td colspan="5">';
if ($action == 'nb_gen_max' || $object->frequency > 0)
{
print $form->editfieldval($langs->trans("MaxPeriodNumber"), 'nb_gen_max', $object->nb_gen_max?$object->nb_gen_max:'', $object, $user->rights->facture->creer);
}
else
{
print '';
}
print '</td>';
print '</tr>';
// Status of generated invoices
print '<tr><td>';
if ($action == 'auto_validate' || $object->frequency > 0)
print $form->editfieldkey($langs->trans("StatusOfGeneratedInvoices"), 'auto_validate', $object->auto_validate, $object, $user->rights->facture->creer);
else
print $langs->trans("StatusOfGeneratedInvoices");
print '</td><td colspan="5">';
$select = 'select;0:'.$langs->trans('BillStatusDraft').',1:'.$langs->trans('BillStatusValidated');
if ($action == 'auto_validate' || $object->frequency > 0)
{
print $form->editfieldval($langs->trans("StatusOfGeneratedInvoices"), 'auto_validate', $object->auto_validate, $object, $user->rights->facture->creer, $select);
}
print '</td>';
print '</tr>';
print '</table>';
print '<br>';
print '<br>';
if ($object->frequency > 0)
{
print '<table class="border" width="100%">';
// Nb of generation already done
print '<tr><td width="20%">'.$langs->trans("NbOfGenerationDone").'</td>';
print '<td>';
print $object->nb_gen_done?$object->nb_gen_done:'';
print '</td>';
print '</tr>';
// Date last
print '<tr><td>';
print $langs->trans("DateLastGeneration");
print '</td><td colspan="5">';
print dol_print_date($object->date_last_gen, 'dayhour');
print '</td>';
print '</tr>';
print '</table>';
print '<br>';
}
/*
* Lines
*/
@ -886,9 +905,23 @@ else
*/
print '<div class="tabsAction">';
if ($object->statut == Facture::STATUS_DRAFT && $user->rights->facture->creer)
if ($object->statut == Facture::STATUS_DRAFT)
{
echo '<div class="inline-block divButAction"><a class="butAction" href="'.DOL_URL_ROOT.'/compta/facture.php?action=create&amp;socid='.$object->thirdparty->id.'&amp;fac_rec='.$object->id.'">'.$langs->trans("CreateBill").'</a></div>';
if ($user->rights->facture->creer)
{
if (empty($object->frequency) || $object->date_when <= $today)
{
print '<div class="inline-block divButAction"><a class="butAction" href="'.DOL_URL_ROOT.'/compta/facture.php?action=create&amp;socid='.$object->thirdparty->id.'&amp;fac_rec='.$object->id.'">'.$langs->trans("CreateBill").'</a></div>';
}
else
{
print '<div class="inline-block divButAction"><a class="butActionRefused" href="#" title="'.dol_escape_htmltag($langs->trans("DateIsNotEnough")).'">'.$langs->trans("CreateBill").'</a></div>';
}
}
else
{
print '<div class="inline-block divButAction"><a class="butActionRefused" href="#">'.$langs->trans("CreateBill").'</a></div>';
}
}
if ($object->statut == Facture::STATUS_DRAFT && $user->rights->facture->supprimer)
@ -904,20 +937,39 @@ else
/*
* List mode
*/
$sql = "SELECT s.nom as name, s.rowid as socid, f.rowid as facid, f.titre, f.total, f.tva as total_vat, f.total_ttc, f.frequency";
$sql = "SELECT s.nom as name, s.rowid as socid, f.rowid as facid, f.titre, f.total, f.tva as total_vat, f.total_ttc, f.frequency,";
$sql.= " f.date_last_gen, f.date_when";
$sql.= " FROM ".MAIN_DB_PREFIX."societe as s,".MAIN_DB_PREFIX."facture_rec as f";
$sql.= " WHERE f.fk_soc = s.rowid";
$sql.= " AND f.entity = ".$conf->entity;
if ($socid) $sql .= " AND s.rowid = ".$socid;
//$sql .= " ORDER BY $sortfield $sortorder, rowid DESC ";
// $sql .= $db->plimit($limit + 1,$offset);
$nbtotalofrecords = 0;
if (empty($conf->global->MAIN_DISABLE_FULL_SCANLIST))
{
$result = $db->query($sql);
$nbtotalofrecords = $db->num_rows($result);
}
$sql.= $db->plimit($limit+1,$offset);
$resql = $db->query($sql);
if ($resql)
{
$num = $db->num_rows($resql);
print_barre_liste($langs->trans("RepeatableInvoices"),$page,$_SERVER['PHP_SELF'],"&socid=$socid",$sortfield,$sortorder,'',$num,'','title_accountancy.png');
$param='&socid='.$socid;
if ($limit > 0 && $limit != $conf->liste_limit) $param.='&limit='.$limit;
print '<form method="POST" name="searchFormList" action="'.$_SERVER["PHP_SELF"].'">'."\n";
if ($optioncss != '') print '<input type="hidden" name="optioncss" value="'.$optioncss.'">';
print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
print '<input type="hidden" name="action" value="list">';
print '<input type="hidden" name="sortfield" value="'.$sortfield.'">';
print '<input type="hidden" name="sortorder" value="'.$sortorder.'">';
print '<input type="hidden" name="viewstatut" value="'.$viewstatut.'">';
print_barre_liste($langs->trans("RepeatableInvoices"),$page,$_SERVER['PHP_SELF'],$param,$sortfield,$sortorder,'',$num,$nbtotalofrecord,'title_accountancy.png',0,'','',$limit);
print $langs->trans("ToCreateAPredefinedInvoice").'<br><br>';
@ -930,6 +982,8 @@ else
print_liste_field_titre($langs->trans("AmountVAT"),'','','','','align="right"');
print_liste_field_titre($langs->trans("AmountTTC"),'','','','','align="right"');
print_liste_field_titre($langs->trans("RecurringInvoiceTemplate"),'','','','','align="center"');
print_liste_field_titre($langs->trans("DateLastGeneration"),'','','','','align="center"');
print_liste_field_titre($langs->trans("NextDateToExecution"),'','','','','align="center"');
print_liste_field_titre(''); // Field may contains ling text
print "</tr>\n";
@ -954,12 +1008,21 @@ else
print '<td align="right">'.price($objp->total_vat).'</td>'."\n";
print '<td align="right">'.price($objp->total_ttc).'</td>'."\n";
print '<td align="center">'.yn($objp->frequency?1:0).'</td>';
print '<td align="center">'.($objp->frequency ? dol_print_date($objp->date_last_gen,'day') : '').'</td>';
print '<td align="center">'.($objp->frequency ? dol_print_date($objp->date_when,'day') : '').'</td>';
print '<td align="center">';
if ($user->rights->facture->creer)
{
print '<a href="'.DOL_URL_ROOT.'/compta/facture.php?action=create&amp;socid='.$objp->socid.'&amp;fac_rec='.$objp->facid.'">';
print $langs->trans("CreateBill").'</a>';
if (empty($objp->frequency) || $objp->date_when <= $today)
{
print '<a href="'.DOL_URL_ROOT.'/compta/facture.php?action=create&amp;socid='.$objp->socid.'&amp;fac_rec='.$objp->facid.'">';
print $langs->trans("CreateBill").'</a>';
}
else
{
print $langs->trans("DateIsNotEnough");
}
}
else
{

View File

@ -75,9 +75,9 @@ $search_paymentmode=GETPOST('search_paymentmode','int');
$option = GETPOST('option');
if ($option == 'late') $filter = 'paye:0';
$limit = GETPOST('limit')?GETPOST('limit','int'):$conf->liste_limit;
$sortfield = GETPOST("sortfield",'alpha');
$sortorder = GETPOST("sortorder",'alpha');
$limit = GETPOST('limit')?GETPOST('limit','int'):$conf->liste_limit;
$page = GETPOST("page",'int');
if ($page == -1) {
$page = 0;
@ -85,7 +85,6 @@ if ($page == -1) {
$offset = $limit * $page;
if (! $sortorder) $sortorder='DESC';
if (! $sortfield) $sortfield='f.datef';
$pageprev = $page - 1;
$pagenext = $page + 1;
@ -713,6 +712,13 @@ if ($resql)
$i = 0;
print '<form method="POST" name="searchFormList" action="'.$_SERVER["PHP_SELF"].'">'."\n";
if ($optioncss != '') print '<input type="hidden" name="optioncss" value="'.$optioncss.'">';
print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
print '<input type="hidden" name="action" value="list">';
print '<input type="hidden" name="sortfield" value="'.$sortfield.'">';
print '<input type="hidden" name="sortorder" value="'.$sortorder.'">';
print '<input type="hidden" name="viewstatut" value="'.$viewstatut.'">';
print_barre_liste($langs->trans('BillsCustomers').' '.($socid?' '.$soc->name:''),$page,$_SERVER["PHP_SELF"],$param,$sortfield,$sortorder,$massactionbutton,$num,$nbtotalofrecords,'title_accountancy.png',0,'','',$limit);
if ($massaction == 'presend')
@ -811,14 +817,6 @@ if ($resql)
dol_fiche_end();
}
if ($optioncss != '') print '<input type="hidden" name="optioncss" value="'.$optioncss.'">';
print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
print '<input type="hidden" name="action" value="list">';
print '<input type="hidden" name="sortfield" value="'.$sortfield.'">';
print '<input type="hidden" name="sortorder" value="'.$sortorder.'">';
print '<input type="hidden" name="viewstatut" value="'.$viewstatut.'">';
if ($sall)
{
foreach($fieldstosearchall as $key => $val) $fieldstosearchall[$key]=$langs->trans($val);

View File

@ -1185,7 +1185,7 @@ abstract class CommonObject
}
/**
* Load value from specific field
* Getter generic. Load value from a specific field
*
* @param string $table Table of element or element line
* @param int $id Element id
@ -1211,7 +1211,7 @@ abstract class CommonObject
}
/**
* Update a specific field into database
* Setter generic. Update a specific field into database
*
* @param string $field Field to update
* @param mixed $value New value

View File

@ -112,7 +112,7 @@ function getServerTimeZoneInt($refgmtdate='now')
* @param int $duration_unit Unit of added delay (d, m, y, w, h)
* @return int New timestamp
*/
function dol_time_plus_duree($time,$duration_value,$duration_unit)
function dol_time_plus_duree($time, $duration_value, $duration_unit)
{
if ($duration_value == 0) return $time;
if ($duration_unit == 'h') return $time + (3600*$duration_value);

View File

@ -107,7 +107,7 @@ class modFacture extends DolibarrModules
// Cronjobs
$this->cronjobs = array(
0=>array('label'=>'RecurringInvoices', 'jobtype'=>'method', 'class'=>'compta/facture/class/facture-rec.class.php', 'objectname'=>'FactureRec', 'method'=>'generateRecurringInvoices', 'parameters'=>'', 'comment'=>'Generate recurring invoices', 'frequency'=>1, 'unitfrequency'=>3600*24),
0=>array('label'=>'RecurringInvoices', 'jobtype'=>'method', 'class'=>'compta/facture/class/facture-rec.class.php', 'objectname'=>'FactureRec', 'method'=>'createRecurringInvoices', 'parameters'=>'', 'comment'=>'Generate recurring invoices', 'frequency'=>1, 'unitfrequency'=>3600*24),
// 1=>array('label'=>'My label', 'jobtype'=>'command', 'command'=>'', 'parameters'=>'', 'comment'=>'Comment', 'frequency'=>3600, 'unitfrequency'=>3600)
);
// List of cron jobs entries to add

View File

@ -543,7 +543,8 @@ else
/*
* view card
*/
$now = dol_now();
dol_fiche_head($head, 'card', $langs->trans("CronTask"), 0, 'cron');
$linkback = '<a href="' . DOL_URL_ROOT . '/cron/list.php?status=-2">' . $langs->trans("BackToList") . '</a>';
@ -624,12 +625,12 @@ else
print '<tr><td width="30%">';
print $langs->trans('CronDtStart')."</td><td>";
if(!empty($object->datestart)) {print dol_print_date($object->datestart,'dayhourtext');}
if(!empty($object->datestart)) {print dol_print_date($object->datestart,'dayhoursec');}
print "</td></tr>";
print "<tr><td>";
print $langs->trans('CronDtEnd')."</td><td>";
if(!empty($object->dateend)) {print dol_print_date($object->dateend,'dayhourtext');}
if(!empty($object->dateend)) {print dol_print_date($object->dateend,'dayhoursec');}
print "</td></tr>";
print "<tr><td>";
@ -647,11 +648,16 @@ else
print "<td>".$object->nbrun;
print "</td></tr>";
// Date next run (from)
print '<tr><td>';
print $langs->trans('CronDtNextLaunch');
print ' ('.$langs->trans('CronFrom').')';
print "</td><td>";
if(!empty($object->datenextrun)) {print dol_print_date($object->datenextrun,'dayhoursec');} else {print $langs->trans('CronNone');}
print '<strong>';
if (!empty($object->datenextrun)) {print dol_print_date($object->datenextrun,'dayhoursec');} else {print $langs->trans('CronNone');}
if ($object->maxnbrun && $object->nbrun >= $object->maxrun) print img_warning($langs->trans("Finished"));
if ($object->datenextrun && $object->datenextrun < $now) print img_warning($langs->trans("Late"));
print '</strong>';
print "</td></tr>";
print '</table>';
@ -691,20 +697,7 @@ else
} else {
print '<a class="butAction" href="'.$_SERVER['PHP_SELF'].'?action=edit&id='.$object->id.'">'.$langs->trans("Edit").'</a>';
}
if (! $user->rights->cron->delete) {
print '<a class="butActionRefused" href="#" title="'.dol_escape_htmltag($langs->transnoentitiesnoconv("NotEnoughPermissions")).'">'.$langs->trans("Delete").'</a>';
} else {
print '<a class="butAction" href="'.$_SERVER['PHP_SELF'].'?action=delete&id='.$object->id.'">'.$langs->trans("Delete").'</a>';
}
if (! $user->rights->cron->create) {
print '<a class="butActionRefused" href="#" title="'.dol_escape_htmltag($langs->transnoentitiesnoconv("NotEnoughPermissions")).'">'.$langs->trans("CronStatusActiveBtn").'/'.$langs->trans("CronStatusInactiveBtn").'</a>';
} else {
if (empty($object->status)) {
print '<a class="butAction" href="'.$_SERVER['PHP_SELF'].'?action=activate&id='.$object->id.'">'.$langs->trans("CronStatusActiveBtn").'</a>';
} else {
print '<a class="butAction" href="'.$_SERVER['PHP_SELF'].'?action=inactive&id='.$object->id.'">'.$langs->trans("CronStatusInactiveBtn").'</a>';
}
}
if ((empty($user->rights->cron->execute)))
{
print '<a class="butActionRefused" href="#" title="'.dol_escape_htmltag($langs->transnoentitiesnoconv("NotEnoughPermissions")).'">'.$langs->trans("CronExecute").'</a>';
@ -716,6 +709,22 @@ else
else {
print '<a class="butAction" href="'.$_SERVER['PHP_SELF'].'?action=execute&id='.$object->id.'">'.$langs->trans("CronExecute").'</a>';
}
if (! $user->rights->cron->create) {
print '<a class="butActionRefused" href="#" title="'.dol_escape_htmltag($langs->transnoentitiesnoconv("NotEnoughPermissions")).'">'.$langs->trans("CronStatusActiveBtn").'/'.$langs->trans("CronStatusInactiveBtn").'</a>';
} else {
if (empty($object->status)) {
print '<a class="butAction" href="'.$_SERVER['PHP_SELF'].'?action=activate&id='.$object->id.'">'.$langs->trans("CronStatusActiveBtn").'</a>';
} else {
print '<a class="butActionDelete" href="'.$_SERVER['PHP_SELF'].'?action=inactive&id='.$object->id.'">'.$langs->trans("CronStatusInactiveBtn").'</a>';
}
}
if (! $user->rights->cron->delete) {
print '<a class="butActionDeleteRefused" href="#" title="'.dol_escape_htmltag($langs->transnoentitiesnoconv("NotEnoughPermissions")).'">'.$langs->trans("Delete").'</a>';
} else {
print '<a class="butActionDelete" href="'.$_SERVER['PHP_SELF'].'?action=delete&id='.$object->id.'">'.$langs->trans("Delete").'</a>';
}
print '</div>';
print '<br>';

View File

@ -876,7 +876,6 @@ class Cronjob extends CommonObject
dol_syslog(get_class($this)."::run_jobs jobtype=".$this->jobtype." userlogin=".$userlogin, LOG_DEBUG);
// Increase limit of time. Works only if we are not in safe mode
$ExecTimeLimit=600;
if (!empty($ExecTimeLimit))
@ -892,13 +891,12 @@ class Cronjob extends CommonObject
@ini_set('memory_limit', $MemoryLimit);
}
// Update last run date (to track running jobs)
// Update last run date start (to track running jobs)
$this->datelastrun=$now;
$this->lastoutput='';
$this->lastresult='';
$this->nbrun=$this->nbrun + 1;
$result = $this->update($user);
$result = $this->update($user); // This include begin/commit
if ($result<0) {
dol_syslog(get_class($this)."::run_jobs ".$this->error, LOG_ERR);
return -1;
@ -953,7 +951,7 @@ class Cronjob extends CommonObject
if (! $error)
{
dol_syslog(get_class($this)."::run_jobs ".$this->objectname."->".$this->methodename."(".$this->params.");", LOG_DEBUG);
dol_syslog(get_class($this)."::run_jobs START ".$this->objectname."->".$this->methodename."(".$this->params.");", LOG_DEBUG);
// Create Object for the call module
$object = new $this->objectname($this->db);
@ -971,16 +969,17 @@ class Cronjob extends CommonObject
if ($result===false || $result != 0)
{
$langs->load("errors");
dol_syslog(get_class($this)."::run_jobs result=".$result." error=".$object->error, LOG_ERR);
$this->error = $object->error?$object->error:$langs->trans('ErrorUnknown');
$this->lastoutput = $this->error;
dol_syslog(get_class($this)."::run_jobs END result=".$result." error=".$object->error, LOG_ERR);
$this->error = $object->error?$object->error:$langs->trans('ErrorUnknown');
$this->lastoutput = ($object->output?$object->output."\n":"").$this->error;
$this->lastresult = is_numeric($result)?$result:-1;
$retval = $this->lastresult;
$error++;
}
else
{
$this->lastoutput=$object->output;
dol_syslog(get_class($this)."::run_jobs END");
$this->lastoutput=$object->output;
$this->lastresult=var_export($result,true);
$retval = $this->lastresult;
}
@ -1093,7 +1092,7 @@ class Cronjob extends CommonObject
}
$this->lastresult=$retval;
$this->datelastresult=dol_now();
$result = $this->update($user);
$result = $this->update($user); // This include begin/commit
if ($result < 0)
{
dol_syslog(get_class($this)."::run_jobs ".$this->error, LOG_ERR);

View File

@ -39,9 +39,19 @@ $action=GETPOST('action','alpha');
$confirm=GETPOST('confirm','alpha');
$id=GETPOST('id','int');
$sortorder=GETPOST('sortorder','alpha');
$sortfield=GETPOST('sortfield','alpha');
$page=GETPOST('page','int');
$limit = GETPOST('limit')?GETPOST('limit','int'):$conf->liste_limit;
$sortfield = GETPOST("sortfield",'alpha');
$sortorder = GETPOST("sortorder",'alpha');
$page = GETPOST("page",'int');
if ($page == -1) {
$page = 0;
}
$offset = $limit * $page;
if (! $sortorder) $sortorder='ASC';
if (! $sortfield) $sortfield='t.label';
$pageprev = $page - 1;
$pagenext = $page + 1;
$status=GETPOST('status','int');
if ($status == '') $status=-2;
@ -55,11 +65,6 @@ if ($page == -1) {
$page = 0 ;
}
$limit = $conf->global->MAIN_SIZE_LISTE_LIMIT;
$offset = $limit * $page ;
$pageprev = $page - 1;
$pagenext = $page + 1;
/*
* Actions
@ -137,6 +142,7 @@ $pagetitle=$langs->trans("CronList");
llxHeader('',$pagetitle);
// list of jobs created
// TODO Replace this with an embedded select.
$object = new Cronjob($db);
$result=$object->fetch_all($sortorder, $sortfield, $limit, $offset, $status, $filter);
if ($result < 0)
@ -148,12 +154,8 @@ $num=count($object->lines);
$param='&page='.$page.'&status='.$status.'&search_label='.$search_label;
$stringcurrentdate = $langs->trans("CurrentHour").': '.dol_print_date(dol_now(), 'dayhour');
print_barre_liste($pagetitle, $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, '', $num, $nbtotalofrecords, 'title_setup');
print $langs->trans('CronInfo');
print "<br><br>";
if ($action == 'delete')
@ -171,6 +173,18 @@ if ($action == 'execute')
print '<form method="GET" action="'.$url_form.'" name="search_form">'."\n";
print '<input type="hidden" name="status" value="'.$status.'" >';
if ($optioncss != '') print '<input type="hidden" name="optioncss" value="'.$optioncss.'">';
print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
print '<input type="hidden" name="action" value="list">';
print '<input type="hidden" name="sortfield" value="'.$sortfield.'">';
print '<input type="hidden" name="sortorder" value="'.$sortorder.'">';
print '<input type="hidden" name="viewstatut" value="'.$viewstatut.'">';
print_barre_liste($pagetitle, $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, $stringcurrentdate, $num, 0, 'title_setup', 0, '', '', $limit);
print $langs->trans('CronInfo');
print "<br><br>";
print '<table width="100%" class="noborder">';
print '<tr class="liste_titre">';
@ -303,7 +317,7 @@ if ($num > 0)
print '</td>';
print '<td>';
if(!empty($line->lastoutput)) {print dol_trunc(nl2br($line->lastoutput),100);}
if(!empty($line->lastoutput)) {print dol_trunc(nl2br($line->lastoutput),50);}
print '</td>';
// Status

View File

@ -141,6 +141,8 @@ BillFrom=From
BillTo=To
ActionsOnBill=Actions on invoice
RecurringInvoiceTemplate=Recurring invoice
NoQualifiedRecurringInvoiceTemplateFound=No recurring template invoice qualified for generation.
FoundXQualifiedRecurringInvoiceTemplate=Found %s recurring template invoice(s) qualified for generation.
NotARecurringInvoiceTemplate=Not a recurring template invoice
NewBill=New invoice
LastBills=Last %s invoices
@ -313,10 +315,15 @@ FrequencyPer_d=Every %s days
FrequencyPer_m=Every %s months
FrequencyPer_y=Every %s years
toolTipFrequency=Examples:<br /><b>Set 7 / day</b>: give a new invoice every 7 days<br /><b>Set 3 / month</b>: give a new invoice every 3 month
NextDateToExecution=Next date to execution
MaxPeriodNumber=Max period number
NextDateToExecution=Date for next invoice generation
DateLastGeneration=Date of last generation
MaxPeriodNumber=Max nb of invoice generation
RestPeriodNumber=Rest period number
NbOfGenerationDone=Nb of invoice generation already done
InvoiceAutoValidate=Automatically validate invoice
GeneratedFromRecurringInvoice=Generated from template recurring invoice %s
DateIsNotEnough=Date not yet reached
InvoiceGeneratedFromTemplate=Invoice %s generated from recurring template invoice %s
# PaymentConditions
PaymentConditionShortRECEP=Immediate
PaymentConditionRECEP=Immediate

View File

@ -40,7 +40,8 @@ CronNone=None
CronDtStart=Not before
CronDtEnd=Not after
CronDtNextLaunch=Next execution
CronDtLastLaunch=Last execution
CronDtLastLaunch=Start date of last execution
CronDtLastResult=End date of last execution
CronFrequency=Frequency
CronClass=Class
CronMethod=Method
@ -69,7 +70,6 @@ CronErrEndDateStartDt=End date cannot be before start date
CronStatusActiveBtn=Enable
CronStatusInactiveBtn=Disable
CronTaskInactive=This job is disabled
CronDtLastResult=Last result date
CronId=Id
CronClassFile=Classes (filename.class.php)
CronModuleHelp=Name of Dolibarr module directory (also work with external Dolibarr module). <BR> For exemple to fetch method of Dolibarr Product object /htdocs/<u>product</u>/class/product.class.php, the value of module is <i>product</i>