2026-05-10 23:59:55 +00:00
< ? php
/* Copyright ( C ) 2026 Laurent Destailleur < eldy @ users . sourceforge . net >
* Copyright ( C ) 2026 Nick Fragoulis
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation ; either version 3 of the License , or
* ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with this program . If not , see < https :// www . gnu . org / licenses />.
*/
/**
* \file htdocs / ai / tools / thirdparty . class . php
* \ingroup ai
* \brief MCP Server tool for Dolibarr categories .
*/
require_once DOL_DOCUMENT_ROOT . '/societe/class/societe.class.php' ;
require_once DOL_DOCUMENT_ROOT . '/contact/class/contact.class.php' ;
2026-05-22 06:41:28 +00:00
2026-05-10 23:59:55 +00:00
/**
* Class ToolThirdParty
*
* Provides various tools related to Dolibarr categories .
*/
class ToolThirdParty extends McpTool
{
/**
* Constructor
*
* @ param DoliDB $db Database handler
* @ param User $user User object for permission checks
*/
public function __construct ( $db , $user )
{
$this -> db = $db ;
$this -> user = $user ;
}
/**
* Returns an array of tool definitions , including name , description , and input schema .
*
* @ return list < array < string , mixed >> Array of tool definitions .
*/
public function getDefinitions () : array
{
return [
[
" name " => " search_thirdparties " ,
2026-05-21 17:33:50 +00:00
" description " => " Search for a thirdparty by ID, name, alias, code, or email. If a numerical ID is provided alone, it returns an exact match. If a name is provided, it returns a list of matches. " ,
2026-05-10 23:59:55 +00:00
" inputSchema " => [
" type " => " object " ,
" properties " => [
" query " => [ " type " => [ " string " , " integer " ], " description " => " The ID of the thirdparty, or a name/alias/code/email to search for. " ],
" type " => [ " type " => " string " , " enum " => [ " customer " , " prospect " , " supplier " ], " description " => " Filter by type (optional). " ],
2026-05-19 23:27:19 +00:00
" country_code " => [ " type " => " string " , " description " => " ISO 2-letter country code (e.g. US, FR, GR) (optional). " ],
2026-05-10 23:59:55 +00:00
" limit " => [ " type " => " integer " , " default " => 5 ]
],
" required " => [ " query " ]
]
],
2026-05-21 17:33:50 +00:00
[
" name " => " count_thirdparties " ,
" description " => " Count the number of thirdparties matching the search criteria. " ,
" inputSchema " => [
" type " => " object " ,
" properties " => [
" query " => [ " type " => [ " string " , " integer " ], " description " => " A name/alias/code/email to search for. " ],
" type " => [ " type " => " string " , " enum " => [ " customer " , " prospect " , " supplier " ], " description " => " Filter by type (optional). " ],
" country_code " => [ " type " => " string " , " description " => " ISO 2-letter country code (e.g. US, FR, GR) (optional). " ]
],
" required " => [ " query " ]
]
],
2026-05-10 23:59:55 +00:00
[
" name " => " get_thirdparty_details " ,
" description " => " Get full details of a specific thirdparty by ID. " ,
" inputSchema " => [
" type " => " object " ,
" properties " => [
2026-05-17 19:24:23 +00:00
" id " => [ " type " => " integer " , " description " => " The unique numerical ID of the thirdparty. " ]
],
" required " => [ " id " ]
2026-05-10 23:59:55 +00:00
]
],
[
" name " => " create_thirdparty " ,
" description " => " Create a new thirdparty (Using only terms: Customer, Prospect, or Supplier). " ,
" inputSchema " => [
" type " => " object " ,
" properties " => [
2026-05-17 19:24:23 +00:00
" name " => [ " type " => " string " , " description " => " Name of the thirdparty " ],
2026-05-10 23:59:55 +00:00
" type " => [ " type " => " string " , " enum " => [ " customer " , " prospect " , " supplier " , " both " , " none " ], " default " => " customer " , " description " => " Type of thirdparty. 'none' means not a customer or prospect. " ],
" email " => [ " type " => " string " , " description " => " Email address " ],
" phone " => [ " type " => " string " , " description " => " Phone number " ],
" address " => [ " type " => " string " , " description " => " Address " ],
" zip " => [ " type " => " string " , " description " => " Postal code " ],
" town " => [ " type " => " string " , " description " => " Town/City " ],
" country_code " => [ " type " => " string " , " description " => " ISO 2-letter country code (e.g. US, FR, GR) " ],
" code_client " => [ " type " => " string " , " description " => " Customer code (optional, -1 for auto-generation) " ],
" idprof1 " => [ " type " => " string " , " description " => " Professional ID 1 " ],
" idprof2 " => [ " type " => " string " , " description " => " Professional ID 2 " ],
" idprof3 " => [ " type " => " string " , " description " => " Professional ID 3 " ],
" idprof4 " => [ " type " => " string " , " description " => " Professional ID 4 " ]
],
" required " => [ " name " ]
]
],
[
" name " => " update_thirdparty " ,
" description " => " Updates an existing thirdparty's details. " ,
" inputSchema " => [
" type " => " object " ,
" properties " => [
2026-05-17 19:24:23 +00:00
" id " => [ " type " => " integer " , " description " => " The ID of the thirdparty to update. " ],
2026-05-10 23:59:55 +00:00
" name " => [ " type " => " string " , " description " => " The new name for the thirdparty. " ],
" email " => [ " type " => " string " , " description " => " The new email address. " ],
" phone " => [ " type " => " string " , " description " => " The new phone number. " ],
" address " => [ " type " => " string " , " description " => " The new address. " ],
" zip " => [ " type " => " string " , " description " => " The new postal code. " ],
" town " => [ " type " => " string " , " description " => " The new town. " ],
" country_code " => [ " type " => " string " , " description " => " The new ISO 2-letter country code. " ]
],
" required " => [ " id " ]
]
],
[
" name " => " list_thirdparty_contacts " ,
" description " => " Lists all contacts associated with a specific thirdparty. " ,
" inputSchema " => [
" type " => " object " ,
" properties " => [
2026-05-17 19:24:23 +00:00
" id " => [ " type " => " integer " , " description " => " The ID of the thirdparty. " ]
2026-05-10 23:59:55 +00:00
],
" required " => [ " id " ]
]
],
[
" name " => " add_thirdparty_contact " ,
" description " => " Adds a new contact to an existing thirdparty. " ,
" inputSchema " => [
" type " => " object " ,
" properties " => [
" thirdparty_identifier " => [
" type " => [ " string " , " integer " ],
2026-05-17 19:24:23 +00:00
" description " => " The ID or name of the thirdparty to add the contact to. "
2026-05-10 23:59:55 +00:00
],
2026-05-17 19:24:23 +00:00
" firstname " => [ " type " => " string " , " description " => " Contact's first name. " ],
" lastname " => [ " type " => " string " , " description " => " Contact's last name. " ],
2026-05-10 23:59:55 +00:00
" email " => [ " type " => " string " , " description " => " Contact's email address. " ],
" phone " => [ " type " => " string " , " description " => " Contact's phone number. " ],
" role " => [ " type " => " string " , " description " => " Contact's role or position within the company. " ]
],
" required " => [ " thirdparty_identifier " , " firstname " , " lastname " ]
]
]
];
}
/**
* Return categories this tool belongs to .
* Used by the intent parser to filter available tools .
*
* @ return array < string > List of categories ( e . g . , [ 'billing' , 'commercial' ])
*/
public function getCategories () : array
{
return [ 'thirdparty' , 'billing' , 'commercial' , 'project' , 'stock' ];
}
/**
* Executes the requested tool function based on its name .
*
* @ param string $name The name of the tool to execute .
* @ param array < string , mixed > $args The arguments for the tool ( key - value pairs ) .
* @ return mixed The result of the tool execution ( usually an array ) or an error array .
*/
public function execute ( string $name , array $args )
{
switch ( $name ) {
case 'search_thirdparties' :
2026-05-21 17:33:50 +00:00
return $this -> search ( $args , 0 );
case 'count_thirdparties' :
return $this -> search ( $args , 1 );
case 'get_thirdparty_details' : // Get info of agiven thidparty
2026-05-10 23:59:55 +00:00
return $this -> getDetails ( $args );
case 'create_thirdparty' :
return $this -> create ( $args );
case 'update_thirdparty' :
return $this -> update ( $args );
case 'list_thirdparty_contacts' :
return $this -> listContacts ( $args );
case 'add_thirdparty_contact' :
return $this -> addContact ( $args );
default :
return [ " error " => " Tool function ' $name ' not found. " ];
}
}
/**
* Search for third parties based on provided criteria .
*
2026-05-19 23:27:19 +00:00
* @ param array { query : string | int , type ? : string , country_code ? : string , limit ? : int | string } $args Array of arguments :
* - query : Search string or ID
* - country_code : ISO country code on 2 chars ( FR , US , GR ... )
* - type : 'customer' , 'prospect' , 'supplier'
* - limit : Limit results ( default 5 )
2026-05-21 17:33:50 +00:00
* @ param int $count If set to 1 , returns only the count of results .
2026-05-22 06:41:28 +00:00
* @ return array { error : string } | array { count : int } | list < array { id : int , name : string , alias : string , code_cust : string , code_sup : string , email : string , type : string , url : string } >
2026-05-10 23:59:55 +00:00
*/
2026-05-21 17:33:50 +00:00
private function search ( array $args , int $count = 0 )
2026-05-10 23:59:55 +00:00
{
if ( ! $this -> user -> hasRight ( 'societe' , 'lire' )) {
return [ " error " => " Permission Denied " ];
}
$query = $args [ 'query' ];
$type = isset ( $args [ 'type' ]) ? ( string ) $args [ 'type' ] : '' ;
2026-05-19 23:27:19 +00:00
$country_code = isset ( $args [ 'country_code' ]) ? ( string ) $args [ 'country_code' ] : '' ;
2026-05-10 23:59:55 +00:00
$limit = isset ( $args [ 'limit' ]) ? ( int ) $args [ 'limit' ] : 5 ;
// Safety fallback
if ( $limit <= 0 ) {
$limit = 5 ;
}
2026-05-21 17:33:50 +00:00
if ( $limit > 1000 ) {
dol_syslog ( " Search DB Error: Too many record requested " , LOG_ERR );
return [ " error " => " DB Error " ];
}
2026-05-10 23:59:55 +00:00
// Dolibarr SQL construction
2026-05-21 17:33:50 +00:00
if ( $count ) {
$sql = " SELECT COUNT(s.rowid) as nb " ;
} else {
$sql = " SELECT s.rowid, s.nom, s.name_alias, s.code_client, s.code_fournisseur, s.email, s.client, s.fournisseur " ;
}
2026-05-10 23:59:55 +00:00
$sql .= " FROM " . MAIN_DB_PREFIX . " societe as s " ;
2026-05-19 23:27:19 +00:00
if ( $country_code ) {
$sql .= " INNER JOIN " . MAIN_DB_PREFIX . " c_country as c ON s.fk_pays = c.rowid AND c.code = ' " . $this -> db -> escape ( $country_code ) . " ' " ;
}
2026-05-10 23:59:55 +00:00
$sql .= " WHERE s.entity IN ( " . getEntity ( 'societe' ) . " ) " ;
if ( is_numeric ( $query )) {
$sql .= " AND s.rowid = " . ( int ) $query ;
$limit = 1 ;
} else {
2026-05-21 20:40:04 +00:00
$sql .= " AND (s.nom LIKE '% " . $this -> db -> escape ( $query ) . " %' " ;
$sql .= " OR s.name_alias LIKE '% " . $this -> db -> escape ( $query ) . " %' " ;
$sql .= " OR s.code_client LIKE '% " . $this -> db -> escape ( $query ) . " %' " ;
$sql .= " OR s.code_fournisseur LIKE '% " . $this -> db -> escape ( $query ) . " %' " ;
$sql .= " OR s.email LIKE '% " . $this -> db -> escape ( $query ) . " %') " ;
2026-05-10 23:59:55 +00:00
}
if ( $type === 'customer' ) {
$sql .= " AND s.client IN (1, 3) " ;
} elseif ( $type === 'prospect' ) {
$sql .= " AND s.client IN (2, 3) " ;
} elseif ( $type === 'supplier' ) {
$sql .= " AND s.fournisseur = 1 " ;
}
$sql .= " ORDER BY s.nom ASC " ;
2026-05-21 17:33:50 +00:00
$sql .= $this -> db -> plimit ( $limit );
2026-05-10 23:59:55 +00:00
$resql = $this -> db -> query ( $sql );
if ( ! $resql ) {
dol_syslog ( " Search DB Error: " . $this -> db -> lasterror (), LOG_ERR );
return [ " error " => " DB Error " ];
}
$data = [];
while ( $obj = $this -> db -> fetch_object ( $resql )) {
2026-05-21 17:33:50 +00:00
if ( $count ) {
2026-05-22 07:00:38 +00:00
$data = [
2026-05-21 17:33:50 +00:00
" count " => ( int ) $obj -> nb
];
$this -> db -> free ( $resql );
return $data ;
}
2026-05-10 23:59:55 +00:00
$roles = [];
// Cast strictly to ensure type safety in logic
$is_client = ( int ) $obj -> client ;
$is_supplier = ( int ) $obj -> fournisseur ;
if ( $is_client === 1 || $is_client === 3 ) {
$roles [] = " Customer " ;
}
if ( $is_client === 2 || $is_client === 3 ) {
$roles [] = " Prospect " ;
}
if ( $is_supplier === 1 ) {
$roles [] = " Supplier " ;
}
$data [] = [
" id " => ( int ) $obj -> rowid ,
" name " => ( string ) $obj -> nom ,
" alias " => ( string ) $obj -> name_alias ,
" code_cust " => ( string ) $obj -> code_client ,
" code_sup " => ( string ) $obj -> code_fournisseur ,
" email " => ( string ) $obj -> email ,
" type " => implode ( '/' , $roles ),
" url " => DOL_URL_ROOT . " /societe/card.php?socid= " . $obj -> rowid
];
}
$this -> db -> free ( $resql );
return $data ;
}
/**
* Fetch details for a specific third party ( Societe ) .
*
* @ param array { id : int | string } $args Arguments array containing the thirdparty ID .
*
* @ return array { error : string } | array < string , mixed >
*
*/
private function getDetails ( array $args ) : array
{
if ( ! $this -> user -> hasRight ( 'societe' , 'lire' )) {
return [ " error " => " Permission Denied " ];
}
if ( empty ( $args [ 'id' ])) {
return [ " error " => " ID is required " ];
}
$soc = new Societe ( $this -> db );
// Fetch returns > 0 on success, 0 on not found, < 0 on error
$result = $soc -> fetch (( int ) $args [ 'id' ]);
if ( $result > 0 ) {
return [
" id " => ( int ) $soc -> id ,
" name " => ( string ) $soc -> nom ,
" address " => ( string ) $soc -> address ,
" zip " => ( string ) $soc -> zip ,
" city " => ( string ) $soc -> town ,
" country " => ( string ) $soc -> country ,
" email " => ( string ) $soc -> email ,
" phone " => ( string ) $soc -> phone ,
" vat " => ( string ) $soc -> tva_intra ,
// getLibStatut(2) returns the status label (short). Cast to string just in case.
" status " => ( string ) $soc -> getLibStatut ( 2 ),
" url " => DOL_URL_ROOT . " /societe/card.php?socid= " . $soc -> id
];
}
return [ " error " => " Thirdparty not found " ];
}
/**
* Create a new third party ( Societe ) .
*
* @ param array < string , mixed > $args Arguments array . 'name' is mandatory .
*
* @ return array { error : string } | array < string , mixed >
*
*/
private function create ( array $args )
{
global $conf ;
// Check permissions
if ( ! $this -> user -> hasRight ( 'societe' , 'creer' )) {
return [ " error " => " Permission Denied " ];
}
// Validate mandatory fields
if ( empty ( $args [ 'name' ])) {
return [ " error " => " Name is required " ];
}
$soc = new Societe ( $this -> db );
// Assign properties with strict casting to prevent null issues in strict mode
$soc -> nom = ( string ) $args [ 'name' ];
$soc -> email = isset ( $args [ 'email' ]) ? ( string ) $args [ 'email' ] : '' ;
$soc -> phone = isset ( $args [ 'phone' ]) ? ( string ) $args [ 'phone' ] : '' ;
$soc -> address = isset ( $args [ 'address' ]) ? ( string ) $args [ 'address' ] : '' ;
$soc -> zip = isset ( $args [ 'zip' ]) ? ( string ) $args [ 'zip' ] : '' ;
$soc -> town = isset ( $args [ 'town' ]) ? ( string ) $args [ 'town' ] : '' ;
$soc -> code_client = isset ( $args [ 'code_client' ]) ? ( string ) $args [ 'code_client' ] : '' ;
$soc -> idprof1 = isset ( $args [ 'idprof1' ]) ? ( string ) $args [ 'idprof1' ] : '' ;
$soc -> idprof2 = isset ( $args [ 'idprof2' ]) ? ( string ) $args [ 'idprof2' ] : '' ;
$soc -> idprof3 = isset ( $args [ 'idprof3' ]) ? ( string ) $args [ 'idprof3' ] : '' ;
$soc -> idprof4 = isset ( $args [ 'idprof4' ]) ? ( string ) $args [ 'idprof4' ] : '' ;
// Country Handling
if ( ! empty ( $args [ 'country_code' ])) {
require_once DOL_DOCUMENT_ROOT . '/core/lib/company.lib.php' ;
// getCountry returns an array or false/0.
/** @var array{id:int}|false $info */
$info = getCountry ( $args [ 'country_code' ], '1' );
if ( $info && isset ( $info [ 'id' ])) {
$soc -> country_id = ( int ) $info [ 'id' ];
}
}
// Fallback to default country if not set
if ( empty ( $soc -> country_id ) && ! empty ( $conf -> global -> MAIN_INFO_SOCIETE_COUNTRY )) {
$soc -> country_id = ( int ) $conf -> global -> MAIN_INFO_SOCIETE_COUNTRY ;
}
$type = $args [ 'type' ] ? ? 'customer' ;
$soc -> client = 0 ; // Default: not a customer
$soc -> fournisseur = 0 ; // Default: not a supplier
if ( $type === 'customer' ) {
$soc -> client = 1 ;
if ( empty ( $soc -> code_client )) {
$soc -> code_client = '-1' ;
}
} elseif ( $type === 'prospect' ) {
$soc -> client = 2 ;
if ( empty ( $soc -> code_client )) {
$soc -> code_client = '-1' ;
}
} elseif ( $type === 'both' ) {
$soc -> client = 3 ; // Prospect + Customer
if ( empty ( $soc -> code_client )) {
$soc -> code_client = '-1' ;
}
}
if ( $type === 'supplier' || $type === 'both' ) {
$soc -> fournisseur = 1 ;
if ( empty ( $soc -> code_fournisseur )) {
$soc -> code_fournisseur = '-1' ;
}
}
$result = $soc -> create ( $this -> user );
if ( $result > 0 ) {
return [
" status " => " success " ,
" message " => " Thirdparty created " ,
" id " => ( int ) $soc -> id ,
" name " => ( string ) $soc -> name ,
" url " => DOL_URL_ROOT . " /societe/card.php?socid= " . $soc -> id
];
}
return [ " error " => " Create failed: " . ( string ) $soc -> error ];
}
/**
* Update a thirdparty record .
*
* @ param array { id : int | string , name ? : string , email ? : string , phone ? : string , address ? : string , zip ? : string , town ? : string , country_code ? : string } $args Thirdparty fields to update ( ID required ) .
*
* @ return array { status : string , message : string , id : int , url : string } | array { error : string }
*
*/
private function update ( array $args )
{
if ( ! $this -> user -> hasRight ( 'societe' , 'creer' ) && ! $this -> user -> hasRight ( 'societe' , 'modifier' )) {
return [ " error " => " Permission Denied to update. " ];
}
if ( empty ( $args [ 'id' ])) {
return [ " error " => " ID is required for update. " ];
}
$soc = new Societe ( $this -> db );
$result = $soc -> fetch (( int ) $args [ 'id' ]);
if ( $result <= 0 ) {
return [ " error " => " Thirdparty not found with ID: " . $args [ 'id' ]];
}
// Update fields only if provided in arguments (Partial Update)
// We cast to (string) to ensure strict type compliance
if ( isset ( $args [ 'name' ])) {
$soc -> nom = ( string ) $args [ 'name' ];
}
if ( isset ( $args [ 'email' ])) {
$soc -> email = ( string ) $args [ 'email' ];
}
if ( isset ( $args [ 'phone' ])) {
$soc -> phone = ( string ) $args [ 'phone' ];
}
if ( isset ( $args [ 'address' ])) {
$soc -> address = ( string ) $args [ 'address' ];
}
if ( isset ( $args [ 'zip' ])) {
$soc -> zip = ( string ) $args [ 'zip' ];
}
if ( isset ( $args [ 'town' ])) {
$soc -> town = ( string ) $args [ 'town' ];
}
// Handle Country update
if ( ! empty ( $args [ 'country_code' ])) {
require_once DOL_DOCUMENT_ROOT . '/core/lib/company.lib.php' ;
/** @var array{id:int}|false $info */
$info = getCountry ( $args [ 'country_code' ], '1' );
if ( $info && isset ( $info [ 'id' ])) {
$soc -> country_id = ( int ) $info [ 'id' ];
}
}
if ( $soc -> update ( $soc -> id , $this -> user ) > 0 ) {
return [
" status " => " success " ,
" message " => " Thirdparty updated successfully. " ,
" id " => ( int ) $soc -> id ,
" url " => DOL_URL_ROOT . " /societe/card.php?socid= " . $soc -> id
];
}
return [ " error " => " Update failed: " . ( string ) $soc -> error ];
}
/**
* List all contacts for a given thirdparty .
*
* @ param array { id : int | string } $args Arguments array containing the thirdparty ID .
*
* @ return array { error : string } | list < array < string , int | string >>
*
*/
private function listContacts ( array $args )
{
global $langs ;
if ( ! $this -> user -> hasRight ( 'societe' , 'lire' )) {
return [ " error " => " Permission Denied " ];
}
if ( empty ( $args [ 'id' ])) {
return [ " error " => " Thirdparty ID is required " ];
}
$socid = ( int ) $args [ 'id' ];
$langs -> load ( " companies " );
$langs -> load ( " other " );
// Translations
$label_id = $langs -> transnoentitiesnoconv ( " Id " );
$label_firstname = $langs -> transnoentitiesnoconv ( " Firstname " );
$label_lastname = $langs -> transnoentitiesnoconv ( " Lastname " );
$label_email = $langs -> transnoentitiesnoconv ( " Email " );
$label_phone = $langs -> transnoentitiesnoconv ( " Phone " );
$label_role = $langs -> transnoentitiesnoconv ( " PostOrFunction " );
$label_link = $langs -> transnoentitiesnoconv ( " Link " );
$link_text = $langs -> transnoentitiesnoconv ( " Show " );
// Verify thirdparty exists first
$soc = new Societe ( $this -> db );
if ( $soc -> fetch ( $socid ) <= 0 ) {
return [ " error " => " Thirdparty not found with ID: " . $socid ];
}
// Build SQL
$sql = " SELECT t.rowid, t.firstname, t.lastname, t.email, t.phone, t.poste " ;
$sql .= " FROM " . MAIN_DB_PREFIX . " socpeople as t " ;
$sql .= " WHERE t.fk_soc = " . ( int ) $socid ; // Fix: Added explicit (int) cast to satisfy CodingPhpTest static analysis
$sql .= " AND t.entity IN ( " . getEntity ( 'socpeople' ) . " ) " ;
$sql .= " ORDER BY t.lastname ASC, t.firstname ASC " ;
$resql = $this -> db -> query ( $sql );
if ( ! $resql ) {
dol_syslog ( " DB Error in listContacts: " . $this -> db -> lasterror (), LOG_ERR );
return [ " error " => " DB Error " ];
}
$data = [];
while ( $obj = $this -> db -> fetch_object ( $resql )) {
// Absolute URL
$absoluteUrl = DOL_URL_ROOT . " /contact/card.php?id= " . $obj -> rowid ;
$htmlLink = " <a href=' " . $absoluteUrl . " ' target='_blank'> " . $link_text . " </a> " ;
$data [] = [
$label_id => ( int ) $obj -> rowid ,
$label_firstname => ( string ) $obj -> firstname ,
$label_lastname => ( string ) $obj -> lastname ,
$label_email => ( string ) $obj -> email ,
$label_phone => ( string ) $obj -> phone ,
$label_role => ( string ) $obj -> poste ,
$label_link => $htmlLink
];
}
$this -> db -> free ( $resql );
return $data ;
}
/**
* Add a contact linked to a thirdparty .
*
* @ param array { thirdparty_identifier : int | string , firstname : string , lastname : string , email ? : string , phone ? : string } $args Arguments array ( identifier , firstname , lastname required ) .
*
* @ return array { status : string , message : string , id : int , url ? : string } | array { error : string }
*
*
*/
private function addContact ( array $args )
{
if ( ! $this -> user -> hasRight ( 'societe' , 'creer' )) {
return [ " error " => " Permission Denied to create contacts. " ];
}
if ( empty ( $args [ 'thirdparty_identifier' ]) || empty ( $args [ 'firstname' ]) || empty ( $args [ 'lastname' ])) {
return [ " error " => " Thirdparty identifier, firstname and lastname are required. " ];
}
$identifier = $args [ 'thirdparty_identifier' ];
$soc = new Societe ( $this -> db );
$res = 0 ;
// Fetch Thirdparty
if ( is_numeric ( $identifier )) {
// Fetch by RowID
$res = $soc -> fetch (( int ) $identifier );
} else {
// Fetch by Ref/Code (2nd argument of fetch is $ref)
$res = $soc -> fetch ( 0 , ( string ) $identifier );
}
if ( $res <= 0 ) {
return [ " error " => " Thirdparty not found with identifier: " . $identifier ];
}
// Prepare Contact
$contact = new Contact ( $this -> db );
$contact -> socid = $soc -> id ; // Link to the fetched thirdparty
$contact -> firstname = ( string ) ( $args [ 'firstname' ] ? ? '' );
$contact -> lastname = ( string ) $args [ 'lastname' ];
$contact -> email = isset ( $args [ 'email' ]) ? ( string ) $args [ 'email' ] : '' ;
$contact -> phone_pro = isset ( $args [ 'phone' ]) ? ( string ) $args [ 'phone' ] : '' ;
$contact -> poste = isset ( $args [ 'role' ]) ? ( string ) $args [ 'role' ] : '' ;
// Attempt Creation
if ( $contact -> create ( $this -> user ) > 0 ) {
return [
" status " => " success " ,
" message " => " Contact created successfully. " ,
" id " => ( int ) $contact -> id ,
" url " => DOL_URL_ROOT . " /contact/card.php?id= " . $contact -> id
];
}
return [ " error " => " Failed to create contact: " . ( string ) $contact -> error ];
}
}