diff --git a/ChangeLog b/ChangeLog index 9b5eef7aca5..32d73692354 100644 --- a/ChangeLog +++ b/ChangeLog @@ -23,6 +23,8 @@ Following changes may create regressions for some external modules, but were nec follow page naming conventions (so default filter/sort order features can also work). * The trigger ORDER_SUPPLIER_STATUS_ONPROCESS was renamed into ORDER_SUPPLIER_STATUS_ORDERED * The trigger ORDER_SUPPLIER_STATUS_RECEIVED_ALL was renamed into ORDER_SUPPLIER_STATUS_RECEIVED_COMPLETELY +* The parameter note into method cloture() is added at end of private note (previously in v6, it replaced) +* The parameter $user is now mandatory for method createFromOrder and createFromPropal. ***** ChangeLog for 6.0.2 compared to 6.0.1 ***** diff --git a/htdocs/comm/propal/card.php b/htdocs/comm/propal/card.php index 48756a8828c..7de5c0e25ce 100644 --- a/htdocs/comm/propal/card.php +++ b/htdocs/comm/propal/card.php @@ -612,14 +612,14 @@ if (empty($reshook)) // Close proposal else if ($action == 'setstatut' && $user->rights->propal->cloturer && ! GETPOST('cancel','alpha')) { - if (! GETPOST('statut')) { + if (! GETPOST('statut','int')) { setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("CloseAs")), null, 'errors'); $action = 'statut'; } else { // prevent browser refresh from closing proposal several times if ($object->statut == Propal::STATUS_VALIDATED) { - $result=$object->cloture($user, GETPOST('statut','int'), GETPOST('note_private','alpha')); + $result=$object->cloture($user, GETPOST('statut','int'), GETPOST('note_private','none')); if ($result < 0) { setEventMessages($object->error, $object->errors, 'errors'); @@ -1687,8 +1687,8 @@ if ($action == 'create') //Form to close proposal (signed or not) $formquestion = array( array('type' => 'select','name' => 'statut','label' => $langs->trans("CloseAs"),'values' => array(2=>$object->labelstatut [2],3=>$object->labelstatut [3])), - //array('type' => 'other','name' => 'note_private', 'label' => $langs->trans("Note"),'value' => '')); - array('type' => 'text', 'name' => 'note_private', 'label' => $langs->trans("Note"),'value' => $object->note_private)); + array('type' => 'text', 'name' => 'note_private', 'label' => $langs->trans("Note"),'value' => '') // Field to complete private note (not replace) + ); if (! empty($conf->notification->enabled)) { require_once DOL_DOCUMENT_ROOT . '/core/class/notify.class.php'; diff --git a/htdocs/comm/propal/class/api_proposals.class.php b/htdocs/comm/propal/class/api_proposals.class.php index b49baf164ca..ea03bc0eb71 100644 --- a/htdocs/comm/propal/class/api_proposals.class.php +++ b/htdocs/comm/propal/class/api_proposals.class.php @@ -90,7 +90,7 @@ class Proposals extends DolibarrApi * @param string $sortorder Sort order * @param int $limit Limit for list * @param int $page Page number - * @param string $thirdparty_ids Thirdparty ids to filter commercial proposal of. Example: '1' or '1,2,3' {@pattern /^[0-9,]*$/i} + * @param string $thirdparty_ids Thirdparty ids to filter commercial proposal of. Example: '1' or '1,2,3' {@pattern /^2|3$/i} * @param string $sqlfilters Other criteria to filter answers separated by a comma. Syntax example "(t.ref:like:'SO-%') and (t.datec:<:'20160101')" * @return array Array of order objects */ @@ -507,6 +507,49 @@ class Proposals extends DolibarrApi ); } + /** + * Close (Accept or refuse) a quote / commercial proposal + * + * @param int $id Commercial proposal ID + * @param int $status Must be 2 (accepted) or 3 (refused) {@min 2}{@max 3} + * @param string $note_private Add this mention at end of private note + * @param int $notrigger Disabled triggers + * + * @url POST {id}/close + * + * @return array + */ + function close($id, $status, $note_private='', $notrigger=0) + { + if(! DolibarrApiAccess::$user->rights->propal->creer) { + throw new RestException(401); + } + $result = $this->propal->fetch($id); + if( ! $result ) { + throw new RestException(404, 'Commercial Proposal not found'); + } + + if( ! DolibarrApi::_checkAccessToResource('propal',$this->propal->id)) { + throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + } + + $result = $this->propal->cloture(DolibarrApiAccess::$user, $status, $note_private, $notrigger); + if ($result == 0) { + throw new RestException(500, 'Error nothing done. May be object is already closed'); + } + if ($result < 0) { + throw new RestException(500, 'Error when closing Commercial Proposal: '.$this->propal->error); + } + + return array( + 'success' => array( + 'code' => 200, + 'message' => 'Commercial Proposal closed (Ref='.$this->propal->ref.')' + ) + ); + } + + /** * Validate fields before create or update object * @@ -526,6 +569,7 @@ class Proposals extends DolibarrApi return $propal; } + /** * Clean sensible object datas * diff --git a/htdocs/comm/propal/class/propal.class.php b/htdocs/comm/propal/class/propal.class.php index cd5f81783b7..322deadfee3 100644 --- a/htdocs/comm/propal/class/propal.class.php +++ b/htdocs/comm/propal/class/propal.class.php @@ -1505,48 +1505,6 @@ class Propal extends CommonObject } } - /** - * Update value of extrafields on the proposal - * - * @param User $user Object user that modify - * @return int <0 if ko, >0 if ok - */ - function update_extrafields($user) - { - global $conf, $hookmanager; - - $action='update'; - $error = 0; - - // Actions on extra fields (by external module or standard code) - // TODO le hook fait double emploi avec le trigger !! - $hookmanager->initHooks(array('propaldao')); - $parameters=array('id'=>$this->id); - $reshook=$hookmanager->executeHooks('insertExtraFields',$parameters,$this,$action); // Note that $action and $object may have been modified by some hooks - if (empty($reshook)) - { - if (empty($conf->global->MAIN_EXTRAFIELDS_DISABLED)) // For avoid conflicts if trigger used - { - $result=$this->insertExtraFields(); - if ($result < 0) - { - $error++; - } - } - } - else if ($reshook < 0) $error++; - - if (!$error) - { - return 1; - } - else - { - return -1; - } - - } - /** * Set status to validated * @@ -2257,8 +2215,8 @@ class Propal extends CommonObject * * @param User $user Object user that close * @param int $statut Statut - * @param string $note Comment - * @param int $notrigger 1=Does not execute triggers, 0= execute triggers + * @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 */ function cloture($user, $statut, $note, $notrigger=0) @@ -2270,8 +2228,10 @@ class Propal extends CommonObject $this->db->begin(); + $newprivatenote = dol_concatdesc($this->note_private, $note); + $sql = "UPDATE ".MAIN_DB_PREFIX."propal"; - $sql.= " SET fk_statut = ".$statut.", note_private = '".$this->db->escape($note)."', date_cloture='".$this->db->idate($now)."', fk_user_cloture=".$user->id; + $sql.= " SET fk_statut = ".$statut.", 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); @@ -2297,7 +2257,7 @@ class Propal extends CommonObject return -2; } } - if ($statut == self::STATUS_BILLED) + if ($statut == self::STATUS_BILLED) // Why this ? { $trigger_name='PROPAL_CLASSIFY_BILLED'; } diff --git a/htdocs/commande/class/commande.class.php b/htdocs/commande/class/commande.class.php index 79109ff511a..4cda7e931d4 100644 --- a/htdocs/commande/class/commande.class.php +++ b/htdocs/commande/class/commande.class.php @@ -1077,11 +1077,12 @@ class Commande extends CommonOrder * Load an object from a proposal and create a new order into database * * @param Object $object Object source + * @param User $user User making creation * @return int <0 if KO, 0 if nothing done, 1 if OK */ - function createFromProposal($object) + function createFromProposal($object, User $user) { - global $conf,$user,$hookmanager; + global $conf, $hookmanager; dol_include_once('/core/class/extrafields.class.php'); @@ -3048,48 +3049,6 @@ class Commande extends CommonOrder } } - /** - * Update value of extrafields on order - * - * @param User $user Object user that modify - * @return int <0 if ko, >0 if ok - */ - function update_extrafields($user) - { - global $hookmanager, $conf; - - $action='create'; - $error = 0; - - // Actions on extra fields (by external module or standard code) - // TODO le hook fait double emploi avec le trigger !! - $hookmanager->initHooks(array('orderdao')); - $parameters=array('id'=>$this->id); - $reshook=$hookmanager->executeHooks('insertExtraFields',$parameters,$this,$action); // Note that $action and $object may have been modified by some hooks - if (empty($reshook)) - { - if (empty($conf->global->MAIN_EXTRAFIELDS_DISABLED)) // For avoid conflicts if trigger used - { - $result=$this->insertExtraFields(); - if ($result < 0) - { - $error++; - } - } - } - else if ($reshook < 0) $error++; - - if (!$error) - { - return 1; - } - else - { - return -1; - } - - } - /** * Delete the customer order * diff --git a/htdocs/compta/facture/class/facture.class.php b/htdocs/compta/facture/class/facture.class.php index 6452c689215..826d13fecd6 100644 --- a/htdocs/compta/facture/class/facture.class.php +++ b/htdocs/compta/facture/class/facture.class.php @@ -747,7 +747,7 @@ class Facture extends CommonInvoice * @param int $invertdetail Reverse sign of amounts for lines * @return int <0 if KO, >0 if OK */ - function createFromCurrent($user,$invertdetail=0) + function createFromCurrent(User $user, $invertdetail=0) { global $conf; @@ -948,11 +948,12 @@ class Facture extends CommonInvoice * Load an object from an order and create a new invoice into database * * @param Object $object Object source + * @param User $user Object user * @return int <0 if KO, 0 if nothing done, 1 if OK */ - function createFromOrder($object) + function createFromOrder($object, User $user) { - global $user,$hookmanager; + global $hookmanager; $error=0; diff --git a/htdocs/core/lib/security.lib.php b/htdocs/core/lib/security.lib.php index 11232f37ea7..308327ba331 100644 --- a/htdocs/core/lib/security.lib.php +++ b/htdocs/core/lib/security.lib.php @@ -387,8 +387,12 @@ function checkUserAccessToObject($user, $featuresarray, $objectid=0, $tableandsh $nocheck = array('barcode','stock','fournisseur'); // No test $checkdefault = 'all other not already defined'; // Test on entity and link to third party. Not allowed if link is empty (Ex: invoice, orders...). - // If dbtable not defined, we use same name for table than module name - if (empty($dbtablename)) $dbtablename = $feature; + // If dbtablename not defined, we use same name for table than module name + if (empty($dbtablename)) + { + $dbtablename = $feature; + $sharedelement = (! empty($params[1]) ? $params[1] : $dbtablename); // We change dbtablename, so we set sharedelement too. + } // Check permission for object with entity if (in_array($feature,$check)) diff --git a/htdocs/core/triggers/interface_20_modWorkflow_WorkflowManager.class.php b/htdocs/core/triggers/interface_20_modWorkflow_WorkflowManager.class.php index bfa0efad8e6..c25e1ae9ad7 100644 --- a/htdocs/core/triggers/interface_20_modWorkflow_WorkflowManager.class.php +++ b/htdocs/core/triggers/interface_20_modWorkflow_WorkflowManager.class.php @@ -65,7 +65,7 @@ class InterfaceWorkflowManager extends DolibarrTriggers $newobject->context['origin'] = $object->element; $newobject->context['origin_id'] = $object->id; - $ret=$newobject->createFromProposal($object); + $ret=$newobject->createFromProposal($object, $user); if ($ret < 0) { $this->error=$newobject->error; $this->errors[]=$newobject->error; } return $ret; } @@ -84,7 +84,7 @@ class InterfaceWorkflowManager extends DolibarrTriggers $newobject->context['origin'] = $object->element; $newobject->context['origin_id'] = $object->id; - $ret=$newobject->createFromOrder($object); + $ret=$newobject->createFromOrder($object, $user); if ($ret < 0) { $this->error=$newobject->error; $this->errors[]=$newobject->error; } return $ret; } @@ -117,11 +117,11 @@ class InterfaceWorkflowManager extends DolibarrTriggers } } - // classify billed order & billed propososal + // classify billed order & billed propososal if ($action == 'BILL_VALIDATE') { dol_syslog( "Trigger '".$this->name."' for action '$action' launched by ".__FILE__.". id=".$object->id ); - + // First classify billed the order to allow the proposal classify process if (! empty($conf->commande->enabled) && ! empty($conf->global->WORKFLOW_INVOICE_AMOUNT_CLASSIFY_BILLED_ORDER)) { @@ -144,7 +144,7 @@ class InterfaceWorkflowManager extends DolibarrTriggers } return $ret; } - + // Second classify billed the proposal. if (! empty($conf->propal->enabled) && ! empty($conf->global->WORKFLOW_INVOICE_CLASSIFY_BILLED_PROPAL)) { @@ -167,7 +167,7 @@ class InterfaceWorkflowManager extends DolibarrTriggers } return $ret; } - + } // Invoice classify billed order @@ -234,7 +234,7 @@ class InterfaceWorkflowManager extends DolibarrTriggers } } } - + //Build array of quantity ordered by product if (is_array($order->lines) && count($order->lines)>0) { foreach($order->lines as $orderline) { diff --git a/htdocs/product/list.php b/htdocs/product/list.php index 07a9da3bdb0..c18935ec845 100644 --- a/htdocs/product/list.php +++ b/htdocs/product/list.php @@ -893,7 +893,7 @@ else print ''; if (! $i) $totalarray['nbfield']++; } - // Stock + // Stock real if (! empty($arrayfields['p.stock']['checked'])) { print '