diff --git a/htdocs/societe/class/societe.class.php b/htdocs/societe/class/societe.class.php index 4227cfeaea6..f200671c1cb 100644 --- a/htdocs/societe/class/societe.class.php +++ b/htdocs/societe/class/societe.class.php @@ -2233,15 +2233,144 @@ class Societe extends CommonObject return $rowid; } - // We try to find the thirdparty with exact matching on all fields - // TODO Replace this with step by step search - // Then search on barcode if we have it (+ restriction on is_client and is_supplier) - // Then search on profids with a OR (+ restriction on is_client and is_supplier) - // Then search on email (+ restriction on is_client and is_supplier) - // Then search ref, ref_ext or alias with a OR (+ restriction on is_client and is_supplier) + dol_syslog(get_class($this)."::findNearest", LOG_DEBUG); $tmpthirdparty = new Societe($this->db); - $result = $tmpthirdparty->fetch($rowid, $ref, $ref_ext, $barcode, $idprof1, $idprof2, $idprof3, $idprof4, $idprof5, $idprof6, $email, $ref_alias, $is_client, $is_supplier); + // We try to find the thirdparty with exact matching on all fields + $result = $tmpthirdparty->fetch($rowid, $ref, $ref_ext, $barcode, $idprof1, $idprof2, $idprof3, $idprof4, $idprof5, $idprof6, $email, $ref_alias, $is_client, $is_supplier); + if ($result != 0) { + return $result; + } + + // Then search on barcode if we have it (+ restriction on is_client and is_supplier) + dol_syslog("Thirdparty not found with exact match so we try barcode search", LOG_DEBUG); + if ($barcode) { + $result = $tmpthirdparty->fetch(0, '', '', $barcode, '', '', '', '', '', '', '', '', $is_client, $is_supplier); + if ($result != 0) { + return $result; + } + } + + $sqlstart = "SELECT s.rowid as id FROM ".MAIN_DB_PREFIX."societe as s"; + $sqlstart .= ' WHERE s.entity IN ('.getEntity($this->element).')'; + if ($is_client) { + $sqlstart .= ' AND s.client > 0'; + } + if ($is_supplier) { + $sqlstart .= ' AND s.fournisseur > 0'; + } // if both false, no test (the thirdparty can be client and/or supplier) + + // Then search on profids with a OR (+ restriction on is_client and is_supplier) + dol_syslog("Thirdparty not found with barcode search so we try profids search", LOG_DEBUG); + $sqlprof = ""; + if ($idprof1) { + $sqlprof .= " s.siren = '".$this->db->escape($idprof1)."'"; + } + if ($idprof2) { + if ($sqlprof) { + $sqlprof .= " OR"; + } + $sqlprof .= " s.siret = '".$this->db->escape($idprof2)."'"; + } + if ($idprof3) { + if ($sqlprof) { + $sqlprof .= " OR"; + } + $sqlprof .= " s.ape = '".$this->db->escape($idprof3)."'"; + } + if ($idprof4) { + if ($sqlprof) { + $sqlprof .= " OR"; + } + $sqlprof .= " s.idprof4 = '".$this->db->escape($idprof4)."'"; + } + if ($idprof5) { + if ($sqlprof) { + $sqlprof .= " OR"; + } + $sqlprof .= " s.idprof5 = '".$this->db->escape($idprof5)."'"; + } + if ($idprof6) { + if ($sqlprof) { + $sqlprof .= " OR"; + } + $sqlprof .= " s.idprof6 = '".$this->db->escape($idprof6)."'"; + } + + if ($sqlprof) { + $sqlprofquery = $sqlstart . " AND (".$sqlprof." )"; + $resql = $this->db->query($sqlprofquery); + if ($resql) { + $num = $this->db->num_rows($resql); + if ($num > 1) { + $this->error = 'Fetch found several records. Rename one of thirdparties to avoid duplicate.'; + dol_syslog($this->error, LOG_ERR); + $result = -2; + } elseif ($num) { + $obj = $this->db->fetch_object($resql); + $result = $obj->id; + } else { + $result = 0; + } + } else { + $this->error = $this->db->lasterror(); + $this->errors[] = $this->db->lasterror(); + $result = -3; + } + if ($result != 0) { + return $result; + } + } + + // Then search on email (+ restriction on is_client and is_supplier) + dol_syslog("Thirdparty not found with profids search so we try email search", LOG_DEBUG); + if ($email) { + $result = $tmpthirdparty->fetch(0, '', '', '', '', '', '', '', '', '', $email, '', $is_client, $is_supplier); + if ($result != 0) { + return $result; + } + } + + // Then search ref, ref_ext or alias with a OR (+ restriction on is_client and is_supplier) + dol_syslog("Thirdparty not found with profids search so we try ref, ref_ext or ref_alias search", LOG_DEBUG); + $sqlref = ""; + if ($ref) { + $sqlref .= " s.nom = '".$this->db->escape($ref)."'"; + } + if ($ref_alias) { + if ($sqlref) { + $sqlref .= " OR"; + } + $sqlref .= " s.name_alias = '".$this->db->escape($ref_alias)."'"; + } + if ($ref_ext) { + if ($sqlref) { + $sqlref .= " OR"; + } + $sqlref .= " s.ref_ext = '".$this->db->escape($ref_ext)."'"; + } + + if ($sqlref) { + $sqlrefquery = $sqlstart . " AND (".$sqlref." )"; + $resql = $this->db->query($sqlrefquery); + if ($resql) { + $num = $this->db->num_rows($resql); + if ($num > 1) { + $this->error = 'Fetch found several records. Rename one of thirdparties to avoid duplicate.'; + dol_syslog($this->error, LOG_ERR); + $result = -2; + } elseif ($num) { + $obj = $this->db->fetch_object($resql); + $result = $obj->id; + } else { + $result = 0; + } + } else { + $this->error = $this->db->lasterror(); + $this->errors[] = $this->db->lasterror(); + $result = -3; + } + } return $result; } diff --git a/test/phpunit/SocieteTest.php b/test/phpunit/SocieteTest.php index fdc03ca20de..9b64b2f80ee 100644 --- a/test/phpunit/SocieteTest.php +++ b/test/phpunit/SocieteTest.php @@ -477,8 +477,95 @@ class SocieteTest extends CommonClassTest $result = $soc1->fetch($soc1_id); $this->assertLessThanOrEqual($result, 0); + // Clean data for next tests + $soc1->delete($soc1_id); + $soc2->delete($soc2_id); + print __METHOD__." result=".$result."\n"; return $result; } + + /** + * testFindNearest + * + * @return int + */ + public function testSocieteFindNearest() + { + global $conf,$user,$langs,$db; + $conf = $this->savconf; + $user = $this->savuser; + $langs = $this->savlangs; + $db = $this->savdb; + $localobject = new Societe($db); + + $soc1 = new Societe($db); + $soc1->initAsSpecimen(); + $soc1->name = "Thirdparty Name Specimen"; + $soc1->barcode = "123456"; + $soc1->name_alias = "Thirdparty Name Specimen Alias"; + $soc1->code_client = -1; + $soc1->code_fournisseur = -1; + $soc1_id = $soc1->create($user); + + $result = $localobject->findNearest($soc1_id); + $this->assertEquals($soc1_id, $result); + + // Test on bad values + $result = $localobject->findNearest(0, 'Bad REF', 'Bad REF EXT', 'bad idprof1', 'bad idprof2', 'bad idprof3', 'bad idprof4', 'bad idprof5', 'bad idprof6', 'bad email', 'BAD REF ALIAS', 0, 0); + $this->assertEquals(0, $result); + + // Test on good values + $result = $localobject->findNearest(0, $soc1->name, $soc1->ref_ext, $soc1->barcode, $soc1->idprof1, $soc1->idprof2, $soc1->idprof3, $soc1->idprof4, $soc1->idprof5, $soc1->idprof6, $soc1->email, $soc1->name_alias, $soc1->client, $soc1->fournisseur); + $this->assertEquals($soc1_id, $result); + + // Test with Barcode + $result = $localobject->findNearest(0, '', '', $soc1->barcode); + $this->assertEquals($soc1_id, $result); + + // Test with profids + $result = $localobject->findNearest(0, '', '', '', $soc1->idprof1, 'bad idprof2', 'bad idprof3', 'bad idprof4', 'bad idprof5', 'bad idprof6', '', '', $soc1->client, $soc1->fournisseur); + $this->assertEquals($soc1_id, $result); + $result = $localobject->findNearest(0, '', '', '', 'bad idprof1', $soc1->idprof2, 'bad idprof3', 'bad idprof4', 'bad idprof5', 'bad idprof6', '', '', $soc1->client, $soc1->fournisseur); + $this->assertEquals($soc1_id, $result); + $result = $localobject->findNearest(0, '', '', '', 'bad idprof1', 'bad idprof2', $soc1->idprof3, 'bad idprof4', 'bad idprof5', 'bad idprof6', '', '', $soc1->client, $soc1->fournisseur); + $this->assertEquals($soc1_id, $result); + $result = $localobject->findNearest(0, '', '', '', 'bad idprof1', 'bad idprof2', 'bad idprof3', $soc1->idprof4, 'bad idprof5', 'bad idprof6', '', '', $soc1->client, $soc1->fournisseur); + $this->assertEquals($soc1_id, $result); + $result = $localobject->findNearest(0, '', '', '', 'bad idprof1', 'bad idprof2', 'bad idprof3', 'bad idprof4', $soc1->idprof5, 'bad idprof6', '', '', $soc1->client, $soc1->fournisseur); + $this->assertEquals($soc1_id, $result); + $result = $localobject->findNearest(0, '', '', '', 'bad idprof1', 'bad idprof2', 'bad idprof3', 'bad idprof4', 'bad idprof5', $soc1->idprof6, '', '', $soc1->client, $soc1->fournisseur); + $this->assertEquals($soc1_id, $result); + + // Test with email + $result = $localobject->findNearest(0, '', '', '', '', '', '', '', '', '', $soc1->email, '', $soc1->client, $soc1->fournisseur); + $this->assertEquals($soc1_id, $result); + + // Test with refs + $result = $localobject->findNearest(0, $soc1->name, 'Bad REF EXT', '', '', '', '', '', '', '', '', 'BAD REF ALIAS', $soc1->client, $soc1->fournisseur); + $this->assertEquals($soc1_id, $result); + $result = $localobject->findNearest(0, 'Bad REF', $soc1->ref_ext, '', '', '', '', '', '', '', '', 'BAD REF ALIAS', $soc1->client, $soc1->fournisseur); + $this->assertEquals($soc1_id, $result); + $result = $localobject->findNearest(0, 'Bad REF', 'Bad REF EXT', '', '', '', '', '', '', '', '', $soc1->name_alias, $soc1->client, $soc1->fournisseur); + $this->assertEquals($soc1_id, $result); + + $soc2 = new Societe($db); + $soc2->initAsSpecimen(); + $soc2->name = "Thirdparty Name Specimen"; + $soc2->code_client = -1; + $soc2->code_fournisseur = -1; + $soc2_id = $soc2->create($user); + + // Test on values not precise enough + $result = $localobject->findNearest(0, 'Thirdparty Name Specimen', '', '', '', '', '', '', '', '', '', $soc1->client, $soc1->fournisseur); + $this->assertEquals(-2, $result); + + // Clean data for next tests + $soc1->delete($soc1_id); + $soc2->delete($soc2_id); + + print __METHOD__." result=".$result."\n"; + return $result; + } }