Fix merge of thirdparties (pb when merging codes and error management)
This commit is contained in:
parent
a6f12eebe3
commit
14ecdce650
@ -5849,7 +5849,7 @@ abstract class CommonObject
|
||||
* @param int $dest_id New thirdparty id (the thirdparty that will received element of the other)
|
||||
* @param string[] $tables Tables that need to be changed
|
||||
* @param int $ignoreerrors Ignore errors. Return true even if errors. We need this when replacement can fails like for categories (categorie of old thirdparty may already exists on new one)
|
||||
* @return bool
|
||||
* @return bool True if success, False if error
|
||||
*/
|
||||
public static function commonReplaceThirdparty(DoliDB $db, $origin_id, $dest_id, array $tables, $ignoreerrors=0)
|
||||
{
|
||||
|
||||
@ -119,7 +119,7 @@ if (empty($reshook))
|
||||
{
|
||||
$object->fetch($socid);
|
||||
|
||||
$errors = 0;
|
||||
$error = 0;
|
||||
$soc_origin_id = GETPOST('soc_origin', 'int');
|
||||
$soc_origin = new Societe($db);
|
||||
|
||||
@ -131,13 +131,13 @@ if (empty($reshook))
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!$errors && $soc_origin->fetch($soc_origin_id) < 1)
|
||||
if (!$error && $soc_origin->fetch($soc_origin_id) < 1)
|
||||
{
|
||||
setEventMessages($langs->trans('ErrorRecordNotFound'), null, 'errors');
|
||||
$errors++;
|
||||
$error++;
|
||||
}
|
||||
|
||||
if (!$errors)
|
||||
if (!$error)
|
||||
{
|
||||
// TODO Move the merge function into class of object.
|
||||
|
||||
@ -184,48 +184,67 @@ if (empty($reshook))
|
||||
$suppcats = $static_cat->containing($soc_origin->id, 'supplier', 'id');
|
||||
$object->setCategories($suppcats, 'supplier');
|
||||
|
||||
// If thirdparty has a new code that is same than origin, we clean origin code to avoid duplicate key from database unique keys.
|
||||
if ($soc_origin->code_client == $object->code_client
|
||||
|| $soc_origin->code_fournisseur == $object->code_fournisseur
|
||||
|| $soc_origin->barcode == $object->barcode)
|
||||
{
|
||||
dol_syslog("We clean customer and supplier code so we will be able to make the update of target");
|
||||
$soc_origin->code_client = '';
|
||||
$soc_origin->code_fournisseur = '';
|
||||
$soc_origin->barcode = '';
|
||||
$soc_origin->update($soc_origin->id, $user, 0, 1, 1, 'merge');
|
||||
}
|
||||
|
||||
// Update
|
||||
$object->update($object->id, $user, 0);
|
||||
$object->update($object->id, $user, 0, 1, 1, 'merge');
|
||||
if ($result < 0)
|
||||
{
|
||||
$error++;
|
||||
}
|
||||
|
||||
// Move links
|
||||
$objects = array(
|
||||
'Adherent' => '/adherents/class/adherent.class.php',
|
||||
'Societe' => '/societe/class/societe.class.php',
|
||||
'Categorie' => '/categories/class/categorie.class.php',
|
||||
'ActionComm' => '/comm/action/class/actioncomm.class.php',
|
||||
'Propal' => '/comm/propal/class/propal.class.php',
|
||||
'Commande' => '/commande/class/commande.class.php',
|
||||
'Facture' => '/compta/facture/class/facture.class.php',
|
||||
'FactureRec' => '/compta/facture/class/facture-rec.class.php',
|
||||
'LignePrelevement' => '/compta/prelevement/class/ligneprelevement.class.php',
|
||||
'Contact' => '/contact/class/contact.class.php',
|
||||
'Contrat' => '/contrat/class/contrat.class.php',
|
||||
'Expedition' => '/expedition/class/expedition.class.php',
|
||||
'Fichinter' => '/fichinter/class/fichinter.class.php',
|
||||
'CommandeFournisseur' => '/fourn/class/fournisseur.commande.class.php',
|
||||
'FactureFournisseur' => '/fourn/class/fournisseur.facture.class.php',
|
||||
'SupplierProposal' => '/supplier_proposal/class/supplier_proposal.class.php',
|
||||
'ProductFournisseur' => '/fourn/class/fournisseur.product.class.php',
|
||||
'Livraison' => '/livraison/class/livraison.class.php',
|
||||
'Product' => '/product/class/product.class.php',
|
||||
'Project' => '/projet/class/project.class.php',
|
||||
'User' => '/user/class/user.class.php',
|
||||
);
|
||||
|
||||
//First, all core objects must update their tables
|
||||
foreach ($objects as $object_name => $object_file)
|
||||
if (! $error)
|
||||
{
|
||||
require_once DOL_DOCUMENT_ROOT.$object_file;
|
||||
$objects = array(
|
||||
'Adherent' => '/adherents/class/adherent.class.php',
|
||||
'Societe' => '/societe/class/societe.class.php',
|
||||
'Categorie' => '/categories/class/categorie.class.php',
|
||||
'ActionComm' => '/comm/action/class/actioncomm.class.php',
|
||||
'Propal' => '/comm/propal/class/propal.class.php',
|
||||
'Commande' => '/commande/class/commande.class.php',
|
||||
'Facture' => '/compta/facture/class/facture.class.php',
|
||||
'FactureRec' => '/compta/facture/class/facture-rec.class.php',
|
||||
'LignePrelevement' => '/compta/prelevement/class/ligneprelevement.class.php',
|
||||
'Contact' => '/contact/class/contact.class.php',
|
||||
'Contrat' => '/contrat/class/contrat.class.php',
|
||||
'Expedition' => '/expedition/class/expedition.class.php',
|
||||
'Fichinter' => '/fichinter/class/fichinter.class.php',
|
||||
'CommandeFournisseur' => '/fourn/class/fournisseur.commande.class.php',
|
||||
'FactureFournisseur' => '/fourn/class/fournisseur.facture.class.php',
|
||||
'SupplierProposal' => '/supplier_proposal/class/supplier_proposal.class.php',
|
||||
'ProductFournisseur' => '/fourn/class/fournisseur.product.class.php',
|
||||
'Livraison' => '/livraison/class/livraison.class.php',
|
||||
'Product' => '/product/class/product.class.php',
|
||||
'Project' => '/projet/class/project.class.php',
|
||||
'User' => '/user/class/user.class.php',
|
||||
);
|
||||
|
||||
if (!$errors && !$object_name::replaceThirdparty($db, $soc_origin->id, $object->id))
|
||||
//First, all core objects must update their tables
|
||||
foreach ($objects as $object_name => $object_file)
|
||||
{
|
||||
$errors++;
|
||||
setEventMessages($db->lasterror(), null, 'errors');
|
||||
require_once DOL_DOCUMENT_ROOT.$object_file;
|
||||
|
||||
if (!$error && !$object_name::replaceThirdparty($db, $soc_origin->id, $object->id))
|
||||
{
|
||||
$error++;
|
||||
setEventMessages($db->lasterror(), null, 'errors');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//External modules should update their ones too
|
||||
if (!$errors)
|
||||
// External modules should update their ones too
|
||||
if (! $error)
|
||||
{
|
||||
$reshook = $hookmanager->executeHooks('replaceThirdparty', array(
|
||||
'soc_origin' => $soc_origin->id,
|
||||
@ -235,7 +254,7 @@ if (empty($reshook))
|
||||
if ($reshook < 0)
|
||||
{
|
||||
setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
|
||||
$errors++;
|
||||
$error++;
|
||||
}
|
||||
}
|
||||
|
||||
@ -254,16 +273,16 @@ if (empty($reshook))
|
||||
// End call triggers
|
||||
}
|
||||
|
||||
if (!$errors)
|
||||
if (!$error)
|
||||
{
|
||||
//We finally remove the old thirdparty
|
||||
if ($soc_origin->delete($soc_origin->id, $user) < 1)
|
||||
{
|
||||
$errors++;
|
||||
$error++;
|
||||
}
|
||||
}
|
||||
|
||||
if (!$errors)
|
||||
if (!$error)
|
||||
{
|
||||
setEventMessages($langs->trans('ThirdpartiesMergeSuccess'), null, 'mesgs');
|
||||
$db->commit();
|
||||
|
||||
@ -243,6 +243,218 @@ class Thirdparties extends DolibarrApi
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Merge a thirdparty into another one.
|
||||
*
|
||||
* Merge content (properties, notes) and objects (like invoices, events, orders, proposals, ...) of a thirdparty into a target thirdparty,
|
||||
* then delete the merged thirdparty.
|
||||
* If a property has a defined value both in thirdparty to delete and thirdparty to keep, the value into the thirdparty to
|
||||
* delete will be ignored, the value of target thirdparty will remain, except for notes (content is concatenated).
|
||||
*
|
||||
* @param int $id ID of thirdparty to keep (the target thirdparty)
|
||||
* @param int $idtodelete ID of thirdparty to remove (the thirdparty to delete), once data has been merged into the target thirdparty.
|
||||
* @return int
|
||||
*
|
||||
* @url PUT {id}/merge/{idtodelete}
|
||||
*/
|
||||
function merge($id, $idtodelete)
|
||||
{
|
||||
global $db, $hookmanager;
|
||||
|
||||
if ($id == $idtodelete)
|
||||
{
|
||||
throw new RestException(400, 'Try to merge a thirdparty into itself');
|
||||
}
|
||||
|
||||
if(! DolibarrApiAccess::$user->rights->societe->creer) {
|
||||
throw new RestException(401);
|
||||
}
|
||||
|
||||
$result = $this->company->fetch($id); // include the fetch of extra fields
|
||||
if( ! $result ) {
|
||||
throw new RestException(404, 'Thirdparty not found');
|
||||
}
|
||||
|
||||
if( ! DolibarrApi::_checkAccessToResource('societe',$this->company->id)) {
|
||||
throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
|
||||
}
|
||||
|
||||
$this->companytoremove = new Societe($db);
|
||||
|
||||
$result = $this->companytoremove->fetch($idtodelete); // include the fetch of extra fields
|
||||
if( ! $result ) {
|
||||
throw new RestException(404, 'Thirdparty not found');
|
||||
}
|
||||
|
||||
if( ! DolibarrApi::_checkAccessToResource('societe',$this->companytoremove->id)) {
|
||||
throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
|
||||
}
|
||||
|
||||
$soc_origin = $this->companytoremove;
|
||||
$object = $this->company;
|
||||
$user = DolibarrApiAccess::$user;
|
||||
|
||||
|
||||
// Call same code than into action 'confirm_merge'
|
||||
|
||||
|
||||
$db->begin();
|
||||
|
||||
// Recopy some data
|
||||
$object->client = $object->client | $soc_origin->client;
|
||||
$object->fournisseur = $object->fournisseur | $soc_origin->fournisseur;
|
||||
$listofproperties=array(
|
||||
'address', 'zip', 'town', 'state_id', 'country_id', 'phone', 'phone_pro', 'fax', 'email', 'skype', 'url', 'barcode',
|
||||
'idprof1', 'idprof2', 'idprof3', 'idprof4', 'idprof5', 'idprof6',
|
||||
'tva_intra', 'effectif_id', 'forme_juridique', 'remise_percent', 'mode_reglement_supplier_id', 'cond_reglement_supplier_id', 'name_bis',
|
||||
'stcomm_id', 'outstanding_limit', 'price_level', 'parent', 'default_lang', 'ref', 'ref_ext', 'import_key', 'fk_incoterms', 'fk_multicurrency',
|
||||
'code_client', 'code_fournisseur', 'code_compta', 'code_compta_fournisseur',
|
||||
'model_pdf', 'fk_projet'
|
||||
);
|
||||
foreach ($listofproperties as $property)
|
||||
{
|
||||
if (empty($object->$property)) $object->$property = $soc_origin->$property;
|
||||
}
|
||||
|
||||
// Concat some data
|
||||
$listofproperties=array(
|
||||
'note_public', 'note_private'
|
||||
);
|
||||
foreach ($listofproperties as $property)
|
||||
{
|
||||
$object->$property = dol_concatdesc($object->$property, $soc_origin->$property);
|
||||
}
|
||||
|
||||
// Merge extrafields
|
||||
if (is_array($soc_origin->array_options))
|
||||
{
|
||||
foreach ($soc_origin->array_options as $key => $val)
|
||||
{
|
||||
if (empty($object->array_options[$key])) $object->array_options[$key] = $val;
|
||||
}
|
||||
}
|
||||
|
||||
// Merge categories
|
||||
$static_cat = new Categorie($db);
|
||||
$custcats = $static_cat->containing($soc_origin->id, 'customer', 'id');
|
||||
$object->setCategories($custcats, 'customer');
|
||||
$suppcats = $static_cat->containing($soc_origin->id, 'supplier', 'id');
|
||||
$object->setCategories($suppcats, 'supplier');
|
||||
|
||||
// If thirdparty has a new code that is same than origin, we clean origin code to avoid duplicate key from database unique keys.
|
||||
if ($soc_origin->code_client == $object->code_client
|
||||
|| $soc_origin->code_fournisseur == $object->code_fournisseur
|
||||
|| $soc_origin->barcode == $object->barcode)
|
||||
{
|
||||
dol_syslog("We clean customer and supplier code so we will be able to make the update of target");
|
||||
$soc_origin->code_client = '';
|
||||
$soc_origin->code_fournisseur = '';
|
||||
$soc_origin->barcode = '';
|
||||
$soc_origin->update($soc_origin->id, $user, 0, 1, 1, 'merge');
|
||||
}
|
||||
|
||||
// Update
|
||||
$result = $object->update($object->id, $user, 0, 1, 1, 'merge');
|
||||
if ($result < 0)
|
||||
{
|
||||
$error++;
|
||||
}
|
||||
|
||||
// Move links
|
||||
if (! $error)
|
||||
{
|
||||
$objects = array(
|
||||
'Adherent' => '/adherents/class/adherent.class.php',
|
||||
'Societe' => '/societe/class/societe.class.php',
|
||||
'Categorie' => '/categories/class/categorie.class.php',
|
||||
'ActionComm' => '/comm/action/class/actioncomm.class.php',
|
||||
'Propal' => '/comm/propal/class/propal.class.php',
|
||||
'Commande' => '/commande/class/commande.class.php',
|
||||
'Facture' => '/compta/facture/class/facture.class.php',
|
||||
'FactureRec' => '/compta/facture/class/facture-rec.class.php',
|
||||
'LignePrelevement' => '/compta/prelevement/class/ligneprelevement.class.php',
|
||||
'Contact' => '/contact/class/contact.class.php',
|
||||
'Contrat' => '/contrat/class/contrat.class.php',
|
||||
'Expedition' => '/expedition/class/expedition.class.php',
|
||||
'Fichinter' => '/fichinter/class/fichinter.class.php',
|
||||
'CommandeFournisseur' => '/fourn/class/fournisseur.commande.class.php',
|
||||
'FactureFournisseur' => '/fourn/class/fournisseur.facture.class.php',
|
||||
'SupplierProposal' => '/supplier_proposal/class/supplier_proposal.class.php',
|
||||
'ProductFournisseur' => '/fourn/class/fournisseur.product.class.php',
|
||||
'Livraison' => '/livraison/class/livraison.class.php',
|
||||
'Product' => '/product/class/product.class.php',
|
||||
'Project' => '/projet/class/project.class.php',
|
||||
'User' => '/user/class/user.class.php',
|
||||
);
|
||||
|
||||
//First, all core objects must update their tables
|
||||
foreach ($objects as $object_name => $object_file)
|
||||
{
|
||||
require_once DOL_DOCUMENT_ROOT.$object_file;
|
||||
|
||||
if (!$errors && !$object_name::replaceThirdparty($db, $soc_origin->id, $object->id))
|
||||
{
|
||||
$errors++;
|
||||
//setEventMessages($db->lasterror(), null, 'errors');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// External modules should update their ones too
|
||||
if (!$errors)
|
||||
{
|
||||
$reshook = $hookmanager->executeHooks('replaceThirdparty', array(
|
||||
'soc_origin' => $soc_origin->id,
|
||||
'soc_dest' => $object->id
|
||||
), $soc_dest, $action);
|
||||
|
||||
if ($reshook < 0)
|
||||
{
|
||||
//setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
|
||||
$errors++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (! $error)
|
||||
{
|
||||
$object->context=array('merge'=>1, 'mergefromid'=>$soc_origin->id);
|
||||
|
||||
// Call trigger
|
||||
$result=$object->call_trigger('COMPANY_MODIFY',$user);
|
||||
if ($result < 0)
|
||||
{
|
||||
//setEventMessages($object->error, $object->errors, 'errors');
|
||||
$error++;
|
||||
}
|
||||
// End call triggers
|
||||
}
|
||||
|
||||
if (! $error)
|
||||
{
|
||||
//We finally remove the old thirdparty
|
||||
if ($soc_origin->delete($soc_origin->id, $user) < 1)
|
||||
{
|
||||
$errors++;
|
||||
}
|
||||
}
|
||||
|
||||
// End of merge
|
||||
|
||||
if ($error)
|
||||
{
|
||||
$db->rollback();
|
||||
|
||||
throw new RestException(500, 'Error failed to merged thirdparty '.$this->companytoremove->id.' into '.$id.'. Enable and read log file for more information.');
|
||||
}
|
||||
else
|
||||
{
|
||||
$db->commit();
|
||||
}
|
||||
|
||||
return $this->get($id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete thirdparty
|
||||
*
|
||||
|
||||
@ -738,7 +738,7 @@ class Societe extends CommonObject
|
||||
* @param int $call_trigger 0=no, 1=yes
|
||||
* @param int $allowmodcodeclient Inclut modif code client et code compta
|
||||
* @param int $allowmodcodefournisseur Inclut modif code fournisseur et code compta fournisseur
|
||||
* @param string $action 'add' or 'update'
|
||||
* @param string $action 'add' or 'update' or 'merge'
|
||||
* @param int $nosyncmember Do not synchronize info of linked member
|
||||
* @return int <0 if KO, >=0 if OK
|
||||
*/
|
||||
@ -867,7 +867,12 @@ class Societe extends CommonObject
|
||||
// Check name is required and codes are ok or unique.
|
||||
// If error, this->errors[] is filled
|
||||
$result = 0;
|
||||
if ($action != 'add') $result = $this->verify(); // We don't check when update called during a create because verify was already done
|
||||
if ($action != 'add' && $action != 'merge')
|
||||
{
|
||||
// We don't check when update called during a create because verify was already done.
|
||||
// For a merge, we suppose source data is clean and a customer code of a deleted thirdparty must be accepted into a target thirdparty with empty code without duplicate error
|
||||
$result = $this->verify();
|
||||
}
|
||||
|
||||
if ($result >= 0)
|
||||
{
|
||||
@ -3767,16 +3772,22 @@ class Societe extends CommonObject
|
||||
* Function used to replace a thirdparty id with another one.
|
||||
* It must be used within a transaction to avoid trouble
|
||||
*
|
||||
* @param DoliDB $db Database handler
|
||||
* @param int $origin_id Old thirdparty id
|
||||
* @param int $dest_id New thirdparty id
|
||||
* @return bool
|
||||
* @param DoliDB $db Database handler
|
||||
* @param int $origin_id Old thirdparty id (will be removed)
|
||||
* @param int $dest_id New thirdparty id
|
||||
* @return bool True if success, False if error
|
||||
*/
|
||||
public static function replaceThirdparty(DoliDB $db, $origin_id, $dest_id)
|
||||
{
|
||||
if ($origin_id == $id)
|
||||
{
|
||||
dol_syslog('Error: Try to merge a thirdparty into itself');
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Thirdparty commercials cannot be the same in both thirdparties so we look for them and remove some
|
||||
* Because this function is meant to be executed within a transaction, we won't take care of it.
|
||||
* Thirdparty commercials cannot be the same in both thirdparties so we look for them and remove some to avoid duplicate.
|
||||
* Because this function is meant to be executed within a transaction, we won't take care of begin/commit.
|
||||
*/
|
||||
$sql = 'SELECT rowid FROM '.MAIN_DB_PREFIX.'societe_commerciaux ';
|
||||
$sql .= ' WHERE fk_soc = '.(int) $dest_id.' AND fk_user IN ( ';
|
||||
|
||||
@ -62,7 +62,7 @@ if (! empty($conf->global->MAIN_HTML_TITLE) && preg_match('/thirdpartynameonly/'
|
||||
$help_url='EN:Module_Third_Parties|FR:Module_Tiers|ES:Empresas';
|
||||
llxHeader('',$title,$help_url);
|
||||
|
||||
if ($id > 0)
|
||||
if ($object->id > 0)
|
||||
{
|
||||
/*
|
||||
* Affichage onglets
|
||||
@ -120,6 +120,11 @@ if ($id > 0)
|
||||
|
||||
dol_fiche_end();
|
||||
}
|
||||
else
|
||||
{
|
||||
$langs->load("errors");
|
||||
print $langs->trans("ErrorRecordNotFound");
|
||||
}
|
||||
|
||||
llxFooter();
|
||||
$db->close();
|
||||
|
||||
Loading…
Reference in New Issue
Block a user