Debug mass action after regression on close on proposal

This commit is contained in:
Laurent Destailleur 2021-04-13 19:38:55 +02:00
parent d09be1f86f
commit c93f88e47a
5 changed files with 116 additions and 167 deletions

View File

@ -623,7 +623,7 @@ if (empty($reshook)) {
// Classify billed
$db->begin();
$result = $object->cloture($user, $object::STATUS_BILLED, '');
$result = $object->classifyBilled($user, 0, '');
if ($result < 0) {
setEventMessages($object->error, $object->errors, 'errors');
$error++;
@ -639,12 +639,12 @@ if (empty($reshook)) {
if (!(GETPOST('statut', 'int') > 0)) {
setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("CloseAs")), null, 'errors');
$action = 'closeas';
} else {
} elseif (GETPOST('statut', 'int') == $object::STATUS_SIGNED || GETPOST('statut', 'int') == $object::STATUS_NOTSIGNED) {
// prevent browser refresh from closing proposal several times
if ($object->statut == $object::STATUS_VALIDATED) {
$db->begin();
$result = $object->signature($user, GETPOST('statut', 'int'), GETPOST('note_private', 'restricthtml'));
$result = $object->closeProposal($user, GETPOST('statut', 'int'), GETPOST('note_private', 'restricthtml'));
if ($result < 0) {
setEventMessages($object->error, $object->errors, 'errors');
$error++;

View File

@ -766,7 +766,7 @@ class Proposals extends DolibarrApi
throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
}
$result = $this->propal->cloture(DolibarrApiAccess::$user, $status, $note_private, $notrigger);
$result = $this->propal->closeProposal(DolibarrApiAccess::$user, $status, $note_private, $notrigger);
if ($result == 0) {
throw new RestException(304, 'Error nothing done. May be object is already closed');
}

View File

@ -118,6 +118,13 @@ class Propal extends CommonObject
*/
public $statut;
/**
* Status of the quote
* @var int
* @see Propal::STATUS_DRAFT, Propal::STATUS_VALIDATED, Propal::STATUS_SIGNED, Propal::STATUS_NOTSIGNED, Propal::STATUS_BILLED
*/
public $status;
/**
* @deprecated
* @see $date_creation
@ -2502,15 +2509,15 @@ class Propal extends CommonObject
}
/**
* Sign the commercial proposal
* Close/set the commercial proposal to status signed or refused (fill also date signature)
*
* @param User $user Object user that close
* @param int $statut Status
* @param int $status Status (self::STATUS_BILLED or self::STATUS_REFUSED)
* @param string $note Complete private note with this note
* @param int $notrigger 1=Does not execute triggers, 0=Execute triggers
* @return int <0 if KO, >0 if OK
*/
public function signature($user, $statut, $note = '', $notrigger = 0)
public function closeProposal($user, $status, $note = '', $notrigger = 0)
{
global $langs,$conf;
@ -2522,15 +2529,16 @@ class Propal extends CommonObject
$newprivatenote = dol_concatdesc($this->note_private, $note);
$sql = "UPDATE ".MAIN_DB_PREFIX."propal";
$sql .= " SET fk_statut = ".$statut.", note_private = '".$this->db->escape($newprivatenote)."', date_signature='".$this->db->idate($now)."', fk_user_signature=".$user->id;
$sql .= " SET fk_statut = ".((int) $status).", note_private = '".$this->db->escape($newprivatenote)."', date_signature='".$this->db->idate($now)."', fk_user_signature=".$user->id;
$sql .= " WHERE rowid = ".$this->id;
$resql = $this->db->query($sql);
if ($resql) {
// Status self::STATUS_REFUSED by default
$modelpdf = $conf->global->PROPALE_ADDON_PDF_ODT_CLOSED ? $conf->global->PROPALE_ADDON_PDF_ODT_CLOSED : $this->model_pdf;
$trigger_name = 'PROPAL_CLOSE_REFUSED';
if ($statut == self::STATUS_SIGNED) {
if ($status == self::STATUS_SIGNED) { // Status self::STATUS_SIGNED
$trigger_name = 'PROPAL_CLOSE_SIGNED';
$modelpdf = $conf->global->PROPALE_ADDON_PDF_ODT_TOBILL ? $conf->global->PROPALE_ADDON_PDF_ODT_TOBILL:$this->model_pdf;
@ -2561,7 +2569,8 @@ class Propal extends CommonObject
if (!$error) {
$this->oldcopy= clone $this;
$this->statut = $statut;
$this->statut = $status;
$this->status = $status;
$this->date_signature = $now;
$this->note_private = $newprivatenote;
}
@ -2580,6 +2589,7 @@ class Propal extends CommonObject
return 1;
} else {
$this->statut = $this->oldcopy->statut;
$this->status = $this->oldcopy->statut;
$this->date_signature = $this->oldcopy->date_signature;
$this->note_private = $this->oldcopy->note_private;
@ -2587,100 +2597,6 @@ class Propal extends CommonObject
return -1;
}
} else {
$this->error=$this->db->lasterror();
$this->db->rollback();
return -1;
}
}
/**
* Close the commercial proposal
*
* @param User $user Object user that close
* @param int $status Status
* @param string $note Complete private note with this note
* @param int $notrigger 1=Does not execute triggers, 0=Execute triggers
* @return int <0 if KO, >0 if OK
*/
public function cloture($user, $status, $note = "", $notrigger = 0)
{
global $langs, $conf;
$error = 0;
$now = dol_now();
$this->db->begin();
$newprivatenote = dol_concatdesc($this->note_private, $note);
$sql = "UPDATE ".MAIN_DB_PREFIX."propal";
$sql .= " SET fk_statut = ".((int) $status).", note_private = '".$this->db->escape($newprivatenote)."', date_cloture='".$this->db->idate($now)."', fk_user_cloture=".$user->id;
$sql .= " WHERE rowid = ".$this->id;
$resql = $this->db->query($sql);
if ($resql) {
$modelpdf = $conf->global->PROPALE_ADDON_PDF_ODT_CLOSED ? $conf->global->PROPALE_ADDON_PDF_ODT_CLOSED : $this->model_pdf;
$triggerName = 'PROPAL_CLOSE_REFUSED';
if ($status == self::STATUS_SIGNED) {
$triggerName = 'PROPAL_CLOSE_SIGNED';
$modelpdf = $conf->global->PROPALE_ADDON_PDF_ODT_TOBILL ? $conf->global->PROPALE_ADDON_PDF_ODT_TOBILL : $this->model_pdf;
// The connected company is classified as a client
$soc = new Societe($this->db);
$soc->id = $this->socid;
$result = $soc->set_as_client();
if ($result < 0) {
$this->error = $this->db->lasterror();
$this->db->rollback();
return -2;
}
}
if ($status == self::STATUS_BILLED) { // ->cloture() can also be called when we set it to billed, after setting it to signed
$triggerName = 'PROPAL_CLASSIFY_BILLED';
}
if (empty($conf->global->MAIN_DISABLE_PDF_AUTOUPDATE)) {
// Define output language
$outputlangs = $langs;
if (!empty($conf->global->MAIN_MULTILANGS)) {
$outputlangs = new Translate("", $conf);
$newlang = (GETPOST('lang_id', 'aZ09') ? GETPOST('lang_id', 'aZ09') : $this->thirdparty->default_lang);
$outputlangs->setDefaultLang($newlang);
}
//$ret=$object->fetch($id); // Reload to get new records
$this->generateDocument($modelpdf, $outputlangs);
}
if (!$error) {
$this->oldcopy = clone $this;
$this->statut = $status;
$this->date_cloture = $now;
$this->note_private = $newprivatenote;
}
if (!$notrigger && empty($error)) {
// Call trigger
$result = $this->call_trigger($triggerName, $user);
if ($result < 0) {
$error++;
}
// End call triggers
}
if (!$error) {
$this->db->commit();
return 1;
} else {
$this->statut = $this->oldcopy->statut;
$this->date_cloture = $this->oldcopy->date_cloture;
$this->note_private = $this->oldcopy->note_private;
$this->db->rollback();
return -1;
}
} else {
$this->error = $this->db->lasterror();
$this->db->rollback();
return -1;
@ -2688,36 +2604,66 @@ class Propal extends CommonObject
}
/**
* Class invoiced the Propal
* Classify the proposal to status Billed
*
* @param User $user Object user
* @param int $notrigger 1=Does not execute triggers, 0= execute triggers
* @return int <0 si ko, >0 si ok
* @param string $note Complete private note with this note
* @return int <0 if KO, 0 = nothing done, >0 if OK
*/
public function classifyBilled(User $user, $notrigger = 0)
public function classifyBilled(User $user, $notrigger = 0, $note = '')
{
global $conf, $langs;
$error = 0;
$now = dol_now();
$num = 0;
$triggerName = 'PROPAL_CLASSIFY_BILLED';
$this->db->begin();
$sql = 'UPDATE '.MAIN_DB_PREFIX.'propal SET fk_statut = '.self::STATUS_BILLED;
$sql .= ' WHERE rowid = '.$this->id.' AND fk_statut > '.self::STATUS_DRAFT;
$newprivatenote = dol_concatdesc($this->note_private, $note);
$sql = 'UPDATE '.MAIN_DB_PREFIX.'propal SET fk_statut = '.self::STATUS_BILLED.", ";
$sql .= " note_private = '".$this->db->escape($newprivatenote)."', date_cloture='".$this->db->idate($now)."', fk_user_cloture=".$user->id;
$sql .= ' WHERE rowid = '.$this->id.' AND fk_statut = '.self::STATUS_SIGNED;
dol_syslog(__METHOD__, LOG_DEBUG);
$resql = $this->db->query($sql);
if (!$resql) {
$this->errors[] = $this->db->error();
$error++;
} else {
$num = $this->db->affected_rows($resql);
}
if (!$error) {
$modelpdf = $conf->global->PROPALE_ADDON_PDF_ODT_CLOSED ? $conf->global->PROPALE_ADDON_PDF_ODT_CLOSED : $this->model_pdf;
if (empty($conf->global->MAIN_DISABLE_PDF_AUTOUPDATE)) {
// Define output language
$outputlangs = $langs;
if (!empty($conf->global->MAIN_MULTILANGS)) {
$outputlangs = new Translate("", $conf);
$newlang = (GETPOST('lang_id', 'aZ09') ? GETPOST('lang_id', 'aZ09') : $this->thirdparty->default_lang);
$outputlangs->setDefaultLang($newlang);
}
//$ret=$object->fetch($id); // Reload to get new records
$this->generateDocument($modelpdf, $outputlangs);
}
$this->oldcopy = clone $this;
$this->statut = self::STATUS_BILLED;
$this->date_cloture = $now;
$this->note_private = $newprivatenote;
}
if (!$notrigger && empty($error)) {
// Call trigger
$result = $this->call_trigger('PROPAL_MODIFY', $user);
$result = $this->call_trigger($triggerName, $user);
if ($result < 0) {
$error++;
}
@ -2726,7 +2672,7 @@ class Propal extends CommonObject
if (!$error) {
$this->db->commit();
return 1;
return $num;
} else {
foreach ($this->errors as $errmsg) {
dol_syslog(__METHOD__.' Error: '.$errmsg, LOG_ERR);
@ -2922,7 +2868,7 @@ class Propal extends CommonObject
}
if (count($linkedInvoices) > 0) {
$sql = "SELECT rowid as facid, ref, total, datef as df, fk_user_author, fk_statut, paye";
$sql = "SELECT rowid as facid, ref, total_ht as total, datef as df, fk_user_author, fk_statut, paye";
$sql .= " FROM ".MAIN_DB_PREFIX."facture";
$sql .= " WHERE rowid IN (".$this->db->sanitize(implode(',', $linkedInvoices)).")";

View File

@ -125,11 +125,6 @@ if (!$sortorder) {
$sortorder = 'DESC';
}
$permissiontoread = $user->rights->propal->lire;
$permissiontoadd = $user->rights->propal->write;
$permissiontodelete = $user->rights->propal->supprimer;
$permissiontoclose = $user->rights->propal->cloturer;
// Security check
$module = 'propal';
$dbtable = '';
@ -218,6 +213,12 @@ $arrayfields = array(
// Extra fields
include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_array_fields.tpl.php';
$permissiontoread = $user->rights->propal->lire;
$permissiontoadd = $user->rights->propal->write;
$permissiontodelete = $user->rights->propal->supprimer;
$permissiontoclose = $user->rights->propal->cloturer;
/*
* Actions
@ -295,7 +296,7 @@ if (empty($reshook)) {
include DOL_DOCUMENT_ROOT.'/core/actions_massactions.inc.php';
}
if ($action == 'validate') {
if ($action == 'validate' && $permissiontoadd) {
if (GETPOST('confirm') == 'yes') {
$tmpproposal = new Propal($db);
$db->begin();
@ -325,16 +326,16 @@ if ($action == 'validate') {
}
}
if ($action == "sign") {
if ($action == "sign" && $permissiontoclose) {
if (GETPOST('confirm') == 'yes') {
$tmpproposal = new Propal($db);
$db->begin();
$error = 0;
foreach ($toselect as $checked) {
if ($tmpproposal->fetch($checked)) {
if ($tmpproposal->statut == 1) {
$tmpproposal->statut = 2;
if ($tmpproposal->update($user)) {
if ($tmpproposal->statut == $tmpproposal::STATUS_VALIDATED) {
$tmpproposal->statut = $tmpproposal::STATUS_SIGNED;;
if ($tmpproposal->closeProposal($user, $tmpproposal::STATUS_SIGNED)) {
setEventMessage($tmpproposal->ref." ".$langs->trans('Signed'), 'mesgs');
} else {
dol_print_error($db);
@ -356,16 +357,16 @@ if ($action == "sign") {
}
}
}
if ($action == "nosign") {
if ($action == "nosign" && $permissiontoclose) {
if (GETPOST('confirm') == 'yes') {
$tmpproposal = new Propal($db);
$db->begin();
$error = 0;
foreach ($toselect as $checked) {
if ($tmpproposal->fetch($checked)) {
if ($tmpproposal->statut == 1) {
$tmpproposal->statut = 3;
if ($tmpproposal->update($user)) {
if ($tmpproposal->statut == $tmpproposal::STATUS_VALIDATED) {
$tmpproposal->statut = $tmpproposal::STATUS_NOTSIGNED;
if ($tmpproposal->closeProposal($user, $tmpproposal::STATUS_NOTSIGNED)) {
setEventMessage($tmpproposal->ref." ".$langs->trans('NoSigned'), 'mesgs');
} else {
dol_print_error($db);
@ -388,6 +389,43 @@ if ($action == "nosign") {
}
}
// Closed records
if (!$error && $massaction === 'setbilled' && $permissiontoclose) {
$db->begin();
$objecttmp = new $objectclass($db);
$nbok = 0;
foreach ($toselect as $toselectid) {
$result = $objecttmp->fetch($toselectid);
if ($result > 0) {
$result = $objecttmp->classifyBilled($user, 0);
if ($result <= 0) {
setEventMessages($objecttmp->error, $objecttmp->errors, 'errors');
$error++;
break;
} else {
$nbok++;
}
} else {
setEventMessages($objecttmp->error, $objecttmp->errors, 'errors');
$error++;
break;
}
}
if (!$error) {
if ($nbok > 1) {
setEventMessages($langs->trans("RecordsModified", $nbok), null, 'mesgs');
} else {
setEventMessages($langs->trans("RecordsModified", $nbok), null, 'mesgs');
}
$db->commit();
} else {
$db->rollback();
}
}
/*
* View
@ -776,15 +814,16 @@ if ($resql) {
'builddoc'=>$langs->trans("PDFMerge"),
'presend'=>$langs->trans("SendByMail"),
'prevalidate'=>$langs->trans("Validate"),
'presign'=>$langs->trans("Sign"),
'nopresign'=>$langs->trans("NoSign"),
);
if ($user->rights->propal->cloturer) {
$arrayofmassactions['presign']=$langs->trans("Sign");
$arrayofmassactions['nopresign']=$langs->trans("NoSign");
$arrayofmassactions['setbilled'] = $langs->trans("ClassifyBilled");
}
if ($user->rights->propal->supprimer) {
$arrayofmassactions['predelete'] = '<span class="fa fa-trash paddingrightonly"></span>'.$langs->trans("Delete");
}
if ($user->rights->propal->cloturer) {
$arrayofmassactions['closed'] = $langs->trans("Close");
}
if (in_array($massaction, array('presend', 'predelete', 'closed'))) {
$arrayofmassactions = array();
}

View File

@ -1265,42 +1265,6 @@ if (!$error && $massaction == 'validate' && $permissiontoadd) {
}
}
// Closed records
if (!$error && $massaction == 'closed' && $objectclass == "Propal" && $permissiontoclose) {
$db->begin();
$objecttmp = new $objectclass($db);
$nbok = 0;
foreach ($toselect as $toselectid) {
$result = $objecttmp->fetch($toselectid);
if ($result > 0) {
$result = $objecttmp->cloture($user, 3);
if ($result <= 0) {
setEventMessages($objecttmp->error, $objecttmp->errors, 'errors');
$error++;
break;
} else {
$nbok++;
}
} else {
setEventMessages($objecttmp->error, $objecttmp->errors, 'errors');
$error++;
break;
}
}
if (!$error) {
if ($nbok > 1) {
setEventMessages($langs->trans("RecordsModified", $nbok), null, 'mesgs');
} else {
setEventMessages($langs->trans("RecordsModified", $nbok), null, 'mesgs');
}
$db->commit();
} else {
$db->rollback();
}
}
//var_dump($_POST);var_dump($massaction);exit;
// Delete record from mass action (massaction = 'delete' for direct delete, action/confirm='delete'/'yes' with a confirmation step before)