Fix: task #11248 : there is no DB transaction on products->delete

Qual: Mutualize code to see of an object as child
This commit is contained in:
Laurent Destailleur 2011-08-28 12:30:15 +00:00
parent 8cf42ea921
commit 5823f60fd7
4 changed files with 146 additions and 114 deletions

View File

@ -40,8 +40,9 @@ abstract class CommonObject
/** /**
* \brief Check if ref is used. * Check if ref is used.
* \return int <0 if KO, 0 if not found, >0 if found *
* @return int <0 if KO, 0 if not found, >0 if found
*/ */
function verifyNumRef() function verifyNumRef()
{ {
@ -68,6 +69,7 @@ abstract class CommonObject
/** /**
* Add a link between element $this->element and a contact * Add a link between element $this->element and a contact
*
* @param fk_socpeople Id of contact to link * @param fk_socpeople Id of contact to link
* @param type_contact Type of contact (code or id) * @param type_contact Type of contact (code or id)
* @param source external=Contact extern (llx_socpeople), internal=Contact intern (llx_user) * @param source external=Contact extern (llx_socpeople), internal=Contact intern (llx_user)
@ -159,6 +161,7 @@ abstract class CommonObject
/** /**
* Update a link to contact line * Update a link to contact line
*
* @param rowid Id of line contact-element * @param rowid Id of line contact-element
* @param statut New status of link * @param statut New status of link
* @param type_contact_id Id of contact type (not modified if 0) * @param type_contact_id Id of contact type (not modified if 0)
@ -185,6 +188,7 @@ abstract class CommonObject
/** /**
* Delete a link to contact line * Delete a link to contact line
*
* @param rowid Id of contact link line to delete * @param rowid Id of contact link line to delete
* @param notrigger Disable all triggers * @param notrigger Disable all triggers
* @return int >0 if OK, <0 if KO * @return int >0 if OK, <0 if KO
@ -221,6 +225,7 @@ abstract class CommonObject
/** /**
* Delete all links between an object $this and all its contacts * Delete all links between an object $this and all its contacts
*
* @return int >0 if OK, <0 if KO * @return int >0 if OK, <0 if KO
*/ */
function delete_linked_contact() function delete_linked_contact()
@ -253,6 +258,7 @@ abstract class CommonObject
/** /**
* Get array of all contacts for an object * Get array of all contacts for an object
*
* @param statut int Status of lines to get (-1=all) * @param statut int Status of lines to get (-1=all)
* @param source string Source of contact: external or thirdparty (llx_socpeople) or internal (llx_user) * @param source string Source of contact: external or thirdparty (llx_socpeople) or internal (llx_user)
* @param int list 0:Return array contains all properties, 1:Return array contains just id * @param int list 0:Return array contains all properties, 1:Return array contains just id
@ -358,6 +364,7 @@ abstract class CommonObject
/** /**
* Return array with list of possible values for type of contacts * Return array with list of possible values for type of contacts
*
* @param source internal, external or all if not defined * @param source internal, external or all if not defined
* @param order Sort order by : code or rowid * @param order Sort order by : code or rowid
* @param option 0=Return array id->label, 1=Return array code->label * @param option 0=Return array id->label, 1=Return array code->label
@ -405,6 +412,7 @@ abstract class CommonObject
* Example: contact client de facturation ('external', 'BILLING') * Example: contact client de facturation ('external', 'BILLING')
* Example: contact client de livraison ('external', 'SHIPPING') * Example: contact client de livraison ('external', 'SHIPPING')
* Example: contact interne suivi paiement ('internal', 'SALESREPFOLL') * Example: contact interne suivi paiement ('internal', 'SALESREPFOLL')
*
* @param source 'external' or 'internal' * @param source 'external' or 'internal'
* @param code 'BILLING', 'SHIPPING', 'SALESREPFOLL', ... * @param code 'BILLING', 'SHIPPING', 'SALESREPFOLL', ...
* @param status limited to a certain status * @param status limited to a certain status
@ -453,9 +461,10 @@ abstract class CommonObject
} }
/** /**
* \brief Charge le contact d'id $id dans this->contact * Charge le contact d'id $id dans this->contact
* \param contactid Id du contact *
* \return int <0 if KO, >0 if OK * @param contactid Id du contact
* @return int <0 if KO, >0 if OK
*/ */
function fetch_contact($contactid) function fetch_contact($contactid)
{ {
@ -468,6 +477,7 @@ abstract class CommonObject
/** /**
* Load the third party of object from id $this->socid into this->thirdpary * Load the third party of object from id $this->socid into this->thirdpary
*
* @return int <0 if KO, >0 if OK * @return int <0 if KO, >0 if OK
*/ */
function fetch_thirdparty() function fetch_thirdparty()
@ -492,8 +502,9 @@ abstract class CommonObject
} }
/** /**
* \brief Charge le projet d'id $this->fk_project dans this->projet * Charge le projet d'id $this->fk_project dans this->projet
* \return int <0 if KO, >=0 if OK *
* @return int <0 if KO, >=0 if OK
*/ */
function fetch_projet() function fetch_projet()
{ {
@ -506,9 +517,10 @@ abstract class CommonObject
} }
/** /**
* \brief Charge le user d'id userid dans this->user * Charge le user d'id userid dans this->user
* \param userid Id du contact *
* \return int <0 if KO, >0 if OK * @param userid Id du contact
* @return int <0 if KO, >0 if OK
*/ */
function fetch_user($userid) function fetch_user($userid)
{ {
@ -520,6 +532,7 @@ abstract class CommonObject
/** /**
* Load delivery adresse id into $this->fk_address * Load delivery adresse id into $this->fk_address
*
* @param fk_address Id of address * @param fk_address Id of address
* @return int <0 if KO, >0 if OK * @return int <0 if KO, >0 if OK
*/ */
@ -551,6 +564,7 @@ abstract class CommonObject
/** /**
* Load object from specific field * Load object from specific field
*
* @param table Table element or element line * @param table Table element or element line
* @param field Field selected * @param field Field selected
* @param key Import key * @param key Import key
@ -577,6 +591,7 @@ abstract class CommonObject
/** /**
* Update a specific field from an object * Update a specific field from an object
*
* @param table Table element or element line * @param table Table element or element line
* @param id Object id * @param id Object id
* @param field Field to update * @param field Field to update
@ -605,10 +620,11 @@ abstract class CommonObject
} }
/** /**
* \brief Load properties id_previous and id_next * Load properties id_previous and id_next
* \param filter Optional filter *
* \param fieldid Name of field to use for the select MAX and MIN * @param filter Optional filter
* \return int <0 if KO, >0 if OK * @param fieldid Name of field to use for the select MAX and MIN
* @return int <0 if KO, >0 if OK
*/ */
function load_previous_next_ref($filter='',$fieldid) function load_previous_next_ref($filter='',$fieldid)
{ {
@ -672,9 +688,10 @@ abstract class CommonObject
/** /**
* \brief Return list of id of contacts of project * Return list of id of contacts of project
* \param source Source of contact: external (llx_socpeople) or internal (llx_user) or thirdparty (llx_societe) *
* \return array Array of id of contacts (if source=external or internal) * @param source Source of contact: external (llx_socpeople) or internal (llx_user) or thirdparty (llx_societe)
* @return array Array of id of contacts (if source=external or internal)
* Array of id of third parties with at least one contact on project (if source=thirdparty) * Array of id of third parties with at least one contact on project (if source=thirdparty)
*/ */
function getListContactId($source='external') function getListContactId($source='external')
@ -694,9 +711,10 @@ abstract class CommonObject
/** /**
* \brief Link element with a project * Link element with a project
* \param projid Project id to link element to *
* \return int <0 if KO, >0 if OK * @param projid Project id to link element to
* @return int <0 if KO, >0 if OK
*/ */
function setProject($projectid) function setProject($projectid)
{ {
@ -726,10 +744,11 @@ abstract class CommonObject
/** /**
* \brief Set last model used by doc generator * Set last model used by doc generator
* \param user User object that make change *
* \param modelpdf Modele name * @param user User object that make change
* \return int <0 if KO, >0 if OK * @param modelpdf Modele name
* @return int <0 if KO, >0 if OK
*/ */
function setDocModel($user, $modelpdf) function setDocModel($user, $modelpdf)
{ {
@ -764,6 +783,7 @@ abstract class CommonObject
/** /**
* Stocke un numero de rang pour toutes les lignes de detail d'un element qui n'en ont pas. * Stocke un numero de rang pour toutes les lignes de detail d'un element qui n'en ont pas.
*
* @param renum true to renum all already ordered lines, false to renum only not already ordered lines. * @param renum true to renum all already ordered lines, false to renum only not already ordered lines.
*/ */
function line_order($renum=false, $rowidorder='ASC') function line_order($renum=false, $rowidorder='ASC')
@ -811,6 +831,7 @@ abstract class CommonObject
/** /**
* Update a line to have a lower rank * Update a line to have a lower rank
*
* @param $rowid * @param $rowid
*/ */
function line_up($rowid) function line_up($rowid)
@ -826,6 +847,7 @@ abstract class CommonObject
/** /**
* Update a line to have a higher rank * Update a line to have a higher rank
*
* @param $rowid * @param $rowid
*/ */
function line_down($rowid) function line_down($rowid)
@ -843,7 +865,10 @@ abstract class CommonObject
} }
/** /**
* Update position of line (rang) * Update position of line (rang)
*
* @param rowid
* @param rang
*/ */
function updateRangOfLine($rowid,$rang) function updateRangOfLine($rowid,$rang)
{ {
@ -857,6 +882,8 @@ abstract class CommonObject
/** /**
* Update position of line with ajax (rang) * Update position of line with ajax (rang)
*
* @param roworder
*/ */
function line_ajaxorder($roworder) function line_ajaxorder($roworder)
{ {
@ -870,7 +897,10 @@ abstract class CommonObject
} }
/** /**
* Update position of line up (rang) * Update position of line up (rang)
*
* @param rowid
* @param rang
*/ */
function updateLineUp($rowid,$rang) function updateLineUp($rowid,$rang)
{ {
@ -896,7 +926,11 @@ abstract class CommonObject
} }
/** /**
* Update position of line down (rang) * Update position of line down (rang)
*
* @param rowid
* @param rang
* @param max
*/ */
function updateLineDown($rowid,$rang,$max) function updateLineDown($rowid,$rang,$max)
{ {
@ -923,7 +957,9 @@ abstract class CommonObject
/** /**
* Get position of line (rang) * Get position of line (rang)
* @return int Value of rang in table of lines *
* @param rowid Id of line
* @return int Value of rang in table of lines
*/ */
function getRangOfLine($rowid) function getRangOfLine($rowid)
{ {
@ -939,6 +975,7 @@ abstract class CommonObject
/** /**
* Get rowid of the line relative to its position * Get rowid of the line relative to its position
*
* @return int Rowid of the line * @return int Rowid of the line
*/ */
function getIdOfLine($rang) function getIdOfLine($rang)
@ -956,7 +993,9 @@ abstract class CommonObject
/** /**
* Get max value used for position of line (rang) * Get max value used for position of line (rang)
* @result int Max value of rang in table of lines *
* @param fk_parent_line
* @return int Max value of rang in table of lines
*/ */
function line_max($fk_parent_line=0) function line_max($fk_parent_line=0)
{ {
@ -992,9 +1031,10 @@ abstract class CommonObject
} }
/** /**
* \brief Update private note of element * Update private note of element
* \param note New value for note *
* \return int <0 if KO, >0 if OK * @param note New value for note
* @return int <0 if KO, >0 if OK
*/ */
function update_note($note) function update_note($note)
{ {
@ -1031,9 +1071,9 @@ abstract class CommonObject
} }
/** /**
* \brief Update public note of element * Update public note of element
* \param note_public New value for note * @param note_public New value for note
* \return int <0 if KO, >0 if OK * @return int <0 if KO, >0 if OK
*/ */
function update_note_public($note_public) function update_note_public($note_public)
{ {
@ -1062,6 +1102,7 @@ abstract class CommonObject
/** /**
* Update total_ht, total_ttc and total_vat for an object (sum of lines) * Update total_ht, total_ttc and total_vat for an object (sum of lines)
*
* @param exclspec Exclude special product (product_type=9) * @param exclspec Exclude special product (product_type=9)
* @param roundingadjust -1=Use default method (MAIN_ROUNDOFTOTAL_NOT_TOTALOFROUND or 0), 0=Use total of rounding, 1=Use rounding of total * @param roundingadjust -1=Use default method (MAIN_ROUNDOFTOTAL_NOT_TOTALOFROUND or 0), 0=Use total of rounding, 1=Use rounding of total
* @return int <0 if KO, >0 if OK * @return int <0 if KO, >0 if OK
@ -1174,6 +1215,7 @@ abstract class CommonObject
/** /**
* Add objects linked in llx_element_element. * Add objects linked in llx_element_element.
*
* @return int <=0 if KO, >0 if OK * @return int <=0 if KO, >0 if OK
*/ */
function add_object_linked() function add_object_linked()
@ -1208,6 +1250,7 @@ abstract class CommonObject
/** /**
* Fetch array of objects linked to current object. Links are loaded into this->linked_object array. * Fetch array of objects linked to current object. Links are loaded into this->linked_object array.
*
* @param sourceid * @param sourceid
* @param sourcetype * @param sourcetype
* @param targetid * @param targetid
@ -1322,6 +1365,7 @@ abstract class CommonObject
/** /**
* Set statut of an object * Set statut of an object
*
* @param statut Statut to set * @param statut Statut to set
* @param elementId Id of element to force (use this->id by default) * @param elementId Id of element to force (use this->id by default)
* @param elementType Type of element to force (use ->this->element by default) * @param elementType Type of element to force (use ->this->element by default)
@ -1442,6 +1486,7 @@ abstract class CommonObject
/** /**
* Get special code of line * Get special code of line
*
* @param lineid Id of line * @param lineid Id of line
*/ */
function getSpecialCode($lineid) function getSpecialCode($lineid)
@ -1459,6 +1504,7 @@ abstract class CommonObject
/** /**
* Function to get extra fields of a member into $this->array_options * Function to get extra fields of a member into $this->array_options
*
* @param rowid * @param rowid
* @param optionsArray Array resulting of call of extrafields->fetch_name_optionals_label() * @param optionsArray Array resulting of call of extrafields->fetch_name_optionals_label()
*/ */
@ -1510,6 +1556,52 @@ abstract class CommonObject
} }
/**
* Function to check if an object is used by others
*
* @param id Id of object
* @return int <0 if KO, 0 if not used, >0 if already used
*/
function isObjectUsed($id)
{
// Check parameters
if (! isset($this->childtables) || ! is_array($this->childtables) || count($this->childtables) == 0)
{
dol_print_error('Called isObjectUsed on a class with property this->childtables not defined');
return -1;
}
// Test if child exists
$haschild=0;
foreach($this->childtables as $table)
{
// Check if third party can be deleted
$nb=0;
$sql = "SELECT COUNT(*) as nb from ".MAIN_DB_PREFIX.$table;
$sql.= " WHERE ".$this->fk_element." = ".$id;
$resql=$this->db->query($sql);
if ($resql)
{
$obj=$this->db->fetch_object($resql);
$haschild+=$obj->nb;
//print 'Found into table '.$table;
if ($haschild) break; // We found at least on, we stop here
}
else
{
$this->error=$this->db->lasterror();
dol_syslog(get_class($this)."::delete error -1 ".$this->error, LOG_ERR);
return -1;
}
}
if ($haschild > 0)
{
$this->error="ErrorRecordHasChildren";
return $haschild;
}
else return 0;
}
// -------------------- // --------------------
// TODO: All functions here must be redesigned and moved as they are not business functions but output functions // TODO: All functions here must be redesigned and moved as they are not business functions but output functions

View File

@ -36,10 +36,12 @@ class Product extends CommonObject
{ {
var $db; var $db;
var $error; var $error;
//! Error number
var $errno = 0; var $errno = 0;
var $element='product'; var $element='product';
var $table_element='product'; var $table_element='product';
var $fk_element='fk_product';
var $childtables=array('propaldet','commandedet','facturedet','contratdet','product_fournisseur');
var $isnolinkedbythird = 1; // No field fk_soc var $isnolinkedbythird = 1; // No field fk_soc
var $ismultientitymanaged = 1; // 0=No test on entity, 1=Test with field entity, 2=Test with link by societe var $ismultientitymanaged = 1; // 0=No test on entity, 1=Test with field entity, 2=Test with link by societe
@ -505,45 +507,6 @@ class Product extends CommonObject
} }
} }
/**
* Verification de l'utilisation du produit en base
*
* @param id id du produit
*/
function verif_prod_use($id)
{
$sqr = 0;
$elements = array('propaldet','commandedet','facturedet','contratdet','product_fournisseur');
foreach($elements as $table)
{
$sql = "SELECT rowid";
$sql.= " FROM ".MAIN_DB_PREFIX.$table;
$sql.= " WHERE fk_product = ".$id;
$result = $this->db->query($sql);
if ($result)
{
$num = $this->db->num_rows($result);
if ($num != 0)
{
$sqr++;
}
}
}
if ($sqr == 0)
{
return 0;
}
else
{
return -1;
}
}
/** /**
* Delete a product from database (if not used) * Delete a product from database (if not used)
* *
@ -558,8 +521,8 @@ class Product extends CommonObject
if ($user->rights->produit->supprimer) if ($user->rights->produit->supprimer)
{ {
$prod_use = $this->verif_prod_use($id); $objectisused = $this->isObjectUsed($id);
if (empty($prod_use)) if (empty($objectisused))
{ {
$this->db->begin(); $this->db->begin();
@ -570,6 +533,7 @@ class Product extends CommonObject
$sql.= ' FROM '.MAIN_DB_PREFIX.'product_fournisseur_price_log as pfpl, '.MAIN_DB_PREFIX.'product_fournisseur as pf'; $sql.= ' FROM '.MAIN_DB_PREFIX.'product_fournisseur_price_log as pfpl, '.MAIN_DB_PREFIX.'product_fournisseur as pf';
$sql.= ' WHERE pfpl.fk_product_fournisseur = pf.rowid'; $sql.= ' WHERE pfpl.fk_product_fournisseur = pf.rowid';
$sql.= ' AND pf.fk_product = '.$id; $sql.= ' AND pf.fk_product = '.$id;
dol_syslog(get_class($this).'::delete sql='.$sql, LOG_DEBUG);
$result = $this->db->query($sql); $result = $this->db->query($sql);
if (! $result) if (! $result)
{ {
@ -586,6 +550,7 @@ class Product extends CommonObject
$sql.= ' FROM '.MAIN_DB_PREFIX.'product_fournisseur_price as pfp, '.MAIN_DB_PREFIX.'product_fournisseur as pf'; $sql.= ' FROM '.MAIN_DB_PREFIX.'product_fournisseur_price as pfp, '.MAIN_DB_PREFIX.'product_fournisseur as pf';
$sql.= ' WHERE pfp.fk_product_fournisseur = pf.rowid'; $sql.= ' WHERE pfp.fk_product_fournisseur = pf.rowid';
$sql.= ' AND pf.fk_product = '.$id; $sql.= ' AND pf.fk_product = '.$id;
dol_syslog(get_class($this).'::delete sql='.$sql, LOG_DEBUG);
$result = $this->db->query($sql); $result = $this->db->query($sql);
if (! $result) if (! $result)
{ {
@ -603,7 +568,7 @@ class Product extends CommonObject
{ {
$sql = "DELETE FROM ".MAIN_DB_PREFIX.$table; $sql = "DELETE FROM ".MAIN_DB_PREFIX.$table;
$sql.= " WHERE fk_product = ".$id; $sql.= " WHERE fk_product = ".$id;
dol_syslog(get_class($this).'::delete sql='.$this->error, LOG_ERR); dol_syslog(get_class($this).'::delete sql='.$sql, LOG_DEBUG);
$result = $this->db->query($sql); $result = $this->db->query($sql);
if (! $result) if (! $result)
{ {
@ -666,7 +631,7 @@ class Product extends CommonObject
} }
else else
{ {
$this->db->commit; $this->db->commit();
return 1; return 1;
} }
} }

View File

@ -1217,7 +1217,7 @@ if ($action == '')
} }
} }
$product_is_used = $product->verif_prod_use($product->id); $product_is_used = $product->isObjectUsed($product->id);
if (($product->type == 0 && $user->rights->produit->supprimer) if (($product->type == 0 && $user->rights->produit->supprimer)
|| ($product->type == 1 && $user->rights->service->supprimer)) || ($product->type == 1 && $user->rights->service->supprimer))
{ {

View File

@ -39,8 +39,11 @@ class Societe extends CommonObject
var $db; var $db;
var $error; var $error;
var $errors=array(); var $errors=array();
var $element='societe'; var $element='societe';
var $table_element = 'societe'; var $table_element = 'societe';
var $fk_element='fk_soc';
var $childtables=array("propal","commande","facture","contrat","facture_fourn","commande_fournisseur");
var $ismultientitymanaged = 1; // 0=No test on entity, 1=Test with field entity, 2=Test with link by societe var $ismultientitymanaged = 1; // 0=No test on entity, 1=Test with field entity, 2=Test with link by societe
var $id; var $id;
@ -853,7 +856,8 @@ class Societe extends CommonObject
/** /**
* Delete a third party from database and all its dependencies (contacts, rib...) * Delete a third party from database and all its dependencies (contacts, rib...)
* *
* @param id id of third party to delete * @param id id of third party to delete
* @return int <0 if KO, 0 if nothing done, >0 if OK
*/ */
function delete($id) function delete($id)
{ {
@ -864,41 +868,12 @@ class Societe extends CommonObject
$error = 0; $error = 0;
// Test if child exists // Test if child exists
$listtable=array("propal","commande","facture","contrat","facture_fourn","commande_fournisseur"); $objectisused = $this->isObjectUsed($id);
$haschild=0; if (empty($objectisused))
foreach($listtable as $table) {
{ $this->db->begin();
// Check if third party can be deleted
$nb=0;
$sql = "SELECT COUNT(*) as nb from ".MAIN_DB_PREFIX.$table;
$sql.= " WHERE fk_soc = " . $id;
$resql=$this->db->query($sql);
if ($resql)
{
$obj=$this->db->fetch_object($resql);
if ($obj->nb > 0)
{
$haschild+=$obj->nb;
}
}
else
{
$this->error .= $this->db->lasterror();
dol_syslog(get_class($this)."::delete erreur -1 ".$this->error, LOG_ERR);
return -1;
}
}
if ($haschild > 0)
{
$this->error="ErrorRecordHasChildren";
return -1;
}
if ($this->db->begin())
{
require_once(DOL_DOCUMENT_ROOT."/categories/class/categorie.class.php"); require_once(DOL_DOCUMENT_ROOT."/categories/class/categorie.class.php");
$static_cat = new Categorie($this->db); $static_cat = new Categorie($this->db);
$toute_categs = array(); $toute_categs = array();