From c78997ed235cc37c9fa9178f869a094b04206635 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 16 Feb 2016 00:31:05 +0100 Subject: [PATCH] Tons of fixes and enhancement on recurring invoice generation --- .../facture/class/facture-rec.class.php | 123 +++++++--- htdocs/compta/facture/class/facture.class.php | 79 ++---- htdocs/compta/facture/fiche-rec.php | 229 +++++++++++------- htdocs/compta/facture/list.php | 18 +- htdocs/core/class/commonobject.class.php | 4 +- htdocs/core/lib/date.lib.php | 2 +- htdocs/core/modules/modFacture.class.php | 2 +- htdocs/cron/card.php | 45 ++-- htdocs/cron/class/cronjob.class.php | 19 +- htdocs/cron/list.php | 42 ++-- htdocs/langs/en_US/bills.lang | 11 +- htdocs/langs/en_US/cron.lang | 4 +- 12 files changed, 343 insertions(+), 235 deletions(-) diff --git a/htdocs/compta/facture/class/facture-rec.class.php b/htdocs/compta/facture/class/facture-rec.class.php index b0a7bab2899..14ec77600c7 100644 --- a/htdocs/compta/facture/class/facture-rec.class.php +++ b/htdocs/compta/facture/class/facture-rec.class.php @@ -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; } /** diff --git a/htdocs/compta/facture/class/facture.class.php b/htdocs/compta/facture/class/facture.class.php index dd1d9b6ca8c..8b3f43fd26e 100644 --- a/htdocs/compta/facture/class/facture.class.php +++ b/htdocs/compta/facture/class/facture.class.php @@ -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) * diff --git a/htdocs/compta/facture/fiche-rec.php b/htdocs/compta/facture/fiche-rec.php index 350682ec619..adcdeb64744 100644 --- a/htdocs/compta/facture/fiche-rec.php +++ b/htdocs/compta/facture/fiche-rec.php @@ -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 '
'; print ''; @@ -542,7 +549,7 @@ else print ''; $linkback = '' . $langs->trans("BackToList") . ''; - + // Ref print ''; print ''; @@ -669,7 +676,6 @@ else print ""; print ''; - print "
' . $langs->trans('Ref') . ''; @@ -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 '
"; print '
'; @@ -716,77 +722,90 @@ else } print ''; - //if (! empty($object->frequency)) // If no frequency defined, it is not a recurring template invoice - //{ - // Date when - print ''; - 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 ''; - 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 ''; - print ''; - - - // Max period / Rest period - print ''; - 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 ''; - 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 ''; - print ''; - - print ''.$langs->trans("RestPeriodNumber").''; - print ''; - if ($object->frequency > 0) - { - print ($object->nb_gen_max-$object->nb_gen_done); - } - print ''; - - // Status of generated invoices - print ''; - 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 ''; - $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 ''; - print ''; - //} + // Date when + print ''; + 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 ''; + 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 ''; + print ''; + + // Max period / Rest period + print ''; + 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 ''; + 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 ''; + print ''; + + // Status of generated invoices + print ''; + 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 ''; + $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 ''; + print ''; print ''; - print '
'; - + print '
'; + + if ($object->frequency > 0) + { + + print ''; + + // Nb of generation already done + print ''; + print ''; + print ''; + + // Date last + print ''; + print ''; + + print '
'.$langs->trans("NbOfGenerationDone").''; + print $object->nb_gen_done?$object->nb_gen_done:''; + print '
'; + print $langs->trans("DateLastGeneration"); + print ''; + print dol_print_date($object->date_last_gen, 'dayhour'); + print '
'; + + print '
'; + } + /* * Lines */ @@ -886,9 +905,23 @@ else */ print '
'; - if ($object->statut == Facture::STATUS_DRAFT && $user->rights->facture->creer) + if ($object->statut == Facture::STATUS_DRAFT) { - echo ''; + if ($user->rights->facture->creer) + { + if (empty($object->frequency) || $object->date_when <= $today) + { + print ''; + } + else + { + print ''; + } + } + else + { + print ''; + } } 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 ''."\n"; + if ($optioncss != '') print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + + print_barre_liste($langs->trans("RepeatableInvoices"),$page,$_SERVER['PHP_SELF'],$param,$sortfield,$sortorder,'',$num,$nbtotalofrecord,'title_accountancy.png',0,'','',$limit); print $langs->trans("ToCreateAPredefinedInvoice").'

'; @@ -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 "\n"; @@ -954,12 +1008,21 @@ else print ''.price($objp->total_vat).''."\n"; print ''.price($objp->total_ttc).''."\n"; print ''.yn($objp->frequency?1:0).''; + print ''.($objp->frequency ? dol_print_date($objp->date_last_gen,'day') : '').''; + print ''.($objp->frequency ? dol_print_date($objp->date_when,'day') : '').''; print ''; if ($user->rights->facture->creer) { - print ''; - print $langs->trans("CreateBill").''; + if (empty($objp->frequency) || $objp->date_when <= $today) + { + print ''; + print $langs->trans("CreateBill").''; + } + else + { + print $langs->trans("DateIsNotEnough"); + } } else { diff --git a/htdocs/compta/facture/list.php b/htdocs/compta/facture/list.php index 38d1ce96f59..b6e6e9fa942 100644 --- a/htdocs/compta/facture/list.php +++ b/htdocs/compta/facture/list.php @@ -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 ''."\n"; + if ($optioncss != '') print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + 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 ''; - print ''; - print ''; - print ''; - print ''; - print ''; - if ($sall) { foreach($fieldstosearchall as $key => $val) $fieldstosearchall[$key]=$langs->trans($val); diff --git a/htdocs/core/class/commonobject.class.php b/htdocs/core/class/commonobject.class.php index 27a1b3c30d4..587a71d6563 100644 --- a/htdocs/core/class/commonobject.class.php +++ b/htdocs/core/class/commonobject.class.php @@ -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 diff --git a/htdocs/core/lib/date.lib.php b/htdocs/core/lib/date.lib.php index b06baaa9288..562dcf9d223 100644 --- a/htdocs/core/lib/date.lib.php +++ b/htdocs/core/lib/date.lib.php @@ -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); diff --git a/htdocs/core/modules/modFacture.class.php b/htdocs/core/modules/modFacture.class.php index b642873c82d..0c1171bb174 100644 --- a/htdocs/core/modules/modFacture.class.php +++ b/htdocs/core/modules/modFacture.class.php @@ -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 diff --git a/htdocs/cron/card.php b/htdocs/cron/card.php index 79b1cfa996c..90a5dd0f2ed 100644 --- a/htdocs/cron/card.php +++ b/htdocs/cron/card.php @@ -543,7 +543,8 @@ else /* * view card */ - + $now = dol_now(); + dol_fiche_head($head, 'card', $langs->trans("CronTask"), 0, 'cron'); $linkback = '' . $langs->trans("BackToList") . ''; @@ -624,12 +625,12 @@ else print ''; print $langs->trans('CronDtStart').""; - if(!empty($object->datestart)) {print dol_print_date($object->datestart,'dayhourtext');} + if(!empty($object->datestart)) {print dol_print_date($object->datestart,'dayhoursec');} print ""; print ""; print $langs->trans('CronDtEnd').""; - if(!empty($object->dateend)) {print dol_print_date($object->dateend,'dayhourtext');} + if(!empty($object->dateend)) {print dol_print_date($object->dateend,'dayhoursec');} print ""; print ""; @@ -647,11 +648,16 @@ else print "".$object->nbrun; print ""; + // Date next run (from) print ''; print $langs->trans('CronDtNextLaunch'); print ' ('.$langs->trans('CronFrom').')'; print ""; - if(!empty($object->datenextrun)) {print dol_print_date($object->datenextrun,'dayhoursec');} else {print $langs->trans('CronNone');} + print ''; + 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 ''; print ""; print ''; @@ -691,20 +697,7 @@ else } else { print ''.$langs->trans("Edit").''; } - if (! $user->rights->cron->delete) { - print ''.$langs->trans("Delete").''; - } else { - print ''.$langs->trans("Delete").''; - } - if (! $user->rights->cron->create) { - print ''.$langs->trans("CronStatusActiveBtn").'/'.$langs->trans("CronStatusInactiveBtn").''; - } else { - if (empty($object->status)) { - print ''.$langs->trans("CronStatusActiveBtn").''; - } else { - print ''.$langs->trans("CronStatusInactiveBtn").''; - } - } + if ((empty($user->rights->cron->execute))) { print ''.$langs->trans("CronExecute").''; @@ -716,6 +709,22 @@ else else { print ''.$langs->trans("CronExecute").''; } + + if (! $user->rights->cron->create) { + print ''.$langs->trans("CronStatusActiveBtn").'/'.$langs->trans("CronStatusInactiveBtn").''; + } else { + if (empty($object->status)) { + print ''.$langs->trans("CronStatusActiveBtn").''; + } else { + print ''.$langs->trans("CronStatusInactiveBtn").''; + } + } + + if (! $user->rights->cron->delete) { + print ''.$langs->trans("Delete").''; + } else { + print ''.$langs->trans("Delete").''; + } print '
'; print '
'; diff --git a/htdocs/cron/class/cronjob.class.php b/htdocs/cron/class/cronjob.class.php index 5a3be50c738..99b17da3899 100644 --- a/htdocs/cron/class/cronjob.class.php +++ b/htdocs/cron/class/cronjob.class.php @@ -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); diff --git a/htdocs/cron/list.php b/htdocs/cron/list.php index a42feafc437..24edb62aac8 100644 --- a/htdocs/cron/list.php +++ b/htdocs/cron/list.php @@ -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 "

"; if ($action == 'delete') @@ -171,6 +173,18 @@ if ($action == 'execute') print ''."\n"; print ''; +if ($optioncss != '') print ''; +print ''; +print ''; +print ''; +print ''; +print ''; + +print_barre_liste($pagetitle, $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, $stringcurrentdate, $num, 0, 'title_setup', 0, '', '', $limit); + +print $langs->trans('CronInfo'); +print "

"; + print ''; print ''; @@ -303,7 +317,7 @@ if ($num > 0) print ''; print ''; // Status diff --git a/htdocs/langs/en_US/bills.lang b/htdocs/langs/en_US/bills.lang index 06f4309acf0..893627641bf 100644 --- a/htdocs/langs/en_US/bills.lang +++ b/htdocs/langs/en_US/bills.lang @@ -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:
Set 7 / day: give a new invoice every 7 days
Set 3 / month: 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 diff --git a/htdocs/langs/en_US/cron.lang b/htdocs/langs/en_US/cron.lang index 57e61b2f381..e90a2d33ee0 100644 --- a/htdocs/langs/en_US/cron.lang +++ b/htdocs/langs/en_US/cron.lang @@ -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).
For exemple to fetch method of Dolibarr Product object /htdocs/product/class/product.class.php, the value of module is product
'; - if(!empty($line->lastoutput)) {print dol_trunc(nl2br($line->lastoutput),100);} + if(!empty($line->lastoutput)) {print dol_trunc(nl2br($line->lastoutput),50);} print '