123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372 |
- <?php
- /**
- * Define a client.
- * @author Charles DUBOIS
- * @category Plugin
- * @license MIT
- */
- class Client extends Entity{
- public $id;
- public $label; //Libellé (Texte)
- public $name; //Libellé (Texte)
- public $firstname; //Libellé (Texte)
- public $state; //Etat (Liste classique)
- public $pseudonym; //Pseudonyme, Acronyme... (Texte)
- public $code; //Code client (Texte)
- public $category; //Categorie client (Liste configurable)
- public $siret; //N° SIRET (Texte)
- public $comment; //Commentaire (Texte Long)
- public $slug; //Identifiant unique (Texte)
- public $type; //Type (Particulier ou Entreprise) (Liste classique)
- public $condition; //Condition (prospect ou client) (Liste classique)
- public $parent; //Client parent (Entier)
- public $job; //Métier (Texte)
- public $meta; //Meta (JSON)
- public $firm; //Etablissement (Entier)
- protected $TABLE_NAME = 'client';
- public $entityLabel = 'Client';
- public $fields = array(
- 'id' => array('type'=>'key', 'label' => 'Identifiant'),
- 'label' => array('type'=>'text', 'label' => 'Libellé'),
- 'name' => array('type'=>'text', 'label' => 'Nom'),
- 'firstname' => array('type'=>'text', 'label' => 'Prénom'),
- 'state' => array('type'=>'list', 'label' => 'Etat'),
- 'pseudonym' => array('type'=>'text', 'label' => 'Pseudonyme'),
- 'code' => array('type'=>'text', 'label' => 'Code client'),
- 'category' => array('type'=>'dictionary', 'label' => 'Catégorie','link'=>'class/Dictionary.class.php'),
- 'siret' => array('type'=>'text', 'label' => 'N° SIRET'),
- 'comment' => array('type'=>'textarea', 'label' => 'Commentaire'),
- 'slug' => array('type'=>'text', 'label' => 'Slug'),
- 'type' => array('type'=>'list', 'label' => 'Type (Particulier ou Entreprise)'),
- 'condition' => array('type'=>'list', 'label' => 'Condition (prospect ou client)'),
- 'parent' => array('type'=>'int', 'label' => 'Id client parent','link'=>'plugin/client/Client.class.php'),
- 'meta' => array('type'=>'textarea', 'label' => 'Meta'),
- 'job' => array('type'=>'text', 'label' => 'Métier'),
- 'firm' => array('type'=>'int', 'label' => 'Etablissement','link'=>'class/Firm.class.php')
- );
- //Colonnes indexées
- public $indexes = array('parent','category','type','firm');
- public function __construct(){
- parent::__construct();
- $this->state = self::ACTIVE;
- }
- public function save(){
- if(empty($this->slug)){
- $this->slug = slugify($this->label);
- for($i = 2;$i<1000;$i++){
- if(self::rowCount(array('slug'=>$this->slug)) == 0) break;
- $this->slug = slugify($this->label).'-'.$i;
- }
- }
- parent::save();
- if(empty($this->code)){
- $this->code = self::code($this);
- for($i = 2;$i<1000;$i++){
- if(self::rowCount(array('code'=>$this->code)) == 0) break;
- $this->code = self::code($this).'-'.$i;
- }
- $this->save();
- }
- }
- public function meta($key=null,$value=null){
- $meta = json_decode($this->meta,true);
- $meta = !$meta ? array(): $meta ;
- if(!isset($key) && !isset($value)) return $meta;
- if(!isset($value)) return isset($meta[$key])?$meta[$key]:'';
- $meta[$key] = $value;
- $this->meta = json_encode($meta);
- }
- public function condition(){
- return self::conditions($this->condition);
- }
- public function type(){
- return self::types($this->type);
- }
- public function dir(){
- return File::dir().'client'.SLASH.$this->id.SLASH;
- }
- public function logo($returnPath = false){
- $mask = $this->dir().'logo.*';
- $files = glob($mask);
- if($returnPath) return isset($files[0]) ? $files[0] : __DIR__.SLASH.'img'.SLASH.'default-logo.png';
- return isset($files[0]) ? 'action.php?action=client_assets_load&type=logo&client='.$this->id : 'action.php?action=client_assets_load&type=logo';
- }
- public function cover($returnPath = false){
- $mask = $this->dir().'cover.*';
- $files = glob($mask);
- if($returnPath) return isset($files[0]) ? $files[0] : __DIR__.SLASH.'img'.SLASH.'default-cover.jpg';
- return isset($files[0]) ? 'action.php?action=client_assets_load&type=cover&client='.$this->id : 'action.php?action=client_assets_load&type=cover';
- }
- //Vérification des doublons par libellés
- public static function check_duplicate($field,$label,$omitId = null){
- $rows = array();
- switch($field){
- case 'label':
- $query = 'SELECT * FROM {{table}} WHERE (soundex(?) = soundex(label) OR label=? OR label like ?)';
- $data = array($label,$label,$label);
- if(isset($omitId)){
- $query .= ' AND id!=?';
- $data[] = $omitId;
- }
- $regex = '/\s(d(es?|u)|l(a|es?)|une?|à)\s/i';
- $rows = self::staticQuery($query,$data,true);
- foreach ($rows as $key => $row) {
- $rows[$key] = $rows[$key]->toArray();
- //supression des articles définis/indefinis pour plus de pertinence
- $new = preg_replace($regex,' ',mb_strtolower($label));
- $existing = preg_replace($regex,'',mb_strtolower($rows[$key]['label']));
- $rows[$key]['levenshtein'] = levenshtein($existing,$new);
- if($rows[$key]['levenshtein']>3) unset($rows[$key]);
- }
- //tri par levenstein
- usort($rows,function($a,$b){
- return $a['levenshtein'] > $b['levenshtein'];
- });
- break;
- case 'mail':
- case 'phone':
- $type = $field == 'mail' ? Contact::PROFESSIONAL_MAIL : Contact::MOBILE;
- foreach(Contact::loadAll(array(
- 'type' => $type,
- 'state' => Contact::ACTIVE,
- 'value' => trim($label),
- 'scope' => 'client'
- )) as $item){
- $client = Client::getById($item->uid);
- $row = $client->toArray();
- $row['levenshtein'] = 1;
- $rows[] = $row;
- }
- break;
- case 'siret':
- foreach(Client::loadAll(array(
- 'siret' => trim($label),
- 'state' => Contact::ACTIVE
- )) as $item){
- $row = $item->toArray();
- $row['levenshtein'] = 1;
- $rows[] = $row;
- }
- break;
- default:
- return;
- break;
- }
- return $rows;
- }
- //Fusionne le client spécifié avec l'instance de client depuis lequel est appellé la méthode
- // le tableau keeping définis quel coté écrase l'autre dans le cas ou les deux clients sont renseignés (left = instance, right = parametre client)
- public function merge($client,$keeping = array()){
- $logs = array('Fusion du client '.$client->label().' (#'.$client->id.') sur '.$this->label().' (#'.$this->id.') ');
- Plugin::callHook('client_merge',array($this,$client,&$logs));
- foreach ($keeping as $key => $value) {
- if(!empty($this->$key) && empty($client->$key)){
- $logs[] = $key.' origine : renseigné, fusionné : non renseigné';
- continue;
- }
- if($this->$key == $client->$key){
- $logs[] = $key.' origine et fusionné identiques';
- continue;
- }
- if(empty($this->$key) && !empty($client->$key)){
- $this->$key = $client->$key;
- $logs[] = $key.' origine : non renseigné, fusionné : renseigné';
- continue;
- }
- if(!empty($this->$key) && !empty($client->$key)){
- $logs[] = $key.' origine : renseigné, fusionné : renseigné, utilisation du tableau d\'ecrasement';
- if($value == 'left') continue;
- if($value == 'right') $this->$key = $client->$key;
- }
- }
- $logs[] = 'Sauvegarde du client d\'origine';
- $this->save();
- $logs[] = 'Suppression du client fusionné';
- self::delete(array('id'=>$client->id));
- return $logs;
- }
- public static function conditions($key = null){
- global $conf;
- $conditions = array(
- 'prospect' => array('label' =>'Prospect'),
- 'client' => array('label' => ucFirst($conf->get('client_label_singular'))),
- );
- if(!isset($key)) return $conditions;
- return isset($conditions[$key]) ? $conditions[$key] : array('label' =>'Inconnu');
- }
- public static function types($key = null){
- $types = array(
- 'individual' => array('label' =>'Personne'),
- 'firm' => array('label' =>'Structure'),
- );
- if(!isset($key)) return $types;
- return isset($types[$key]) ? $types[$key] : array('label' =>'Inconnu');
- }
- public static function addressType($key = null){
- $types = array(
- 'global' => array('label' =>'Général','icon'=>'far fa-building'),
- 'invoice' => array('label' =>'Facturation','icon'=>'fas fa-file-invoice-dollar'),
- 'shipping' => array('label' =>'Livraison','icon'=>'fas fa-shipping-fast')
- );
- Plugin::callHook('client_address_type',array($types) );
- if(!isset($key)) return $types;
- return isset($types[$key]) ? $types[$key] : array('label' =>'Inconnu');
- }
- public static function internals($key = null){
- $internals = array(
- 'commercial' => array('label' =>'Commercial'),
- 'technician' => array('label' =>'Technicien')
- );
- if(!isset($key)) return $internals;
- return isset($internals[$key]) ? $internals[$key] : array('label' =>'Inconnu');
- }
- public static function code($client){
- global $conf;
- $mask = empty($conf->get('client_code_mask')) ? '{{label[2]}}-{{Y}}{{M}}-{{id}}' : $conf->get('client_code_mask');
- $data = $client->toArray();
- $data['label'] = $client->label();
- $data['M'] = date('m');
- $data['m'] = date('m');
- $data['Y'] = date('Y');
- $data['y'] = date('y');
- $mask = preg_replace_callback('/{{label\[([0-9]*)\]}}/is', function($matches) use ($client){
- if(count($matches)>=1){
- return strlen($client->label>=$matches[1]) ? substr($client->label, 0,$matches[1]) : $client->label;
- }else{
- return $matches[0];
- }
- }, $mask);
- $mask = preg_replace_callback('/{{rand\(([0-9]*),([0-9]*)\)}}/is', function($matches){
- if(count($matches)>=2){
- return mt_rand($matches[1],$matches[2]);
- }else{
- return $matches[0];
- }
- }, $mask);
- $value = template($mask,$data,true);
- return strtoupper(slugify($value));
- }
- //Récupere les adresses du client, de son parent, de ses enfants et de ses frêres
- public function addresses($type = null,$order='zip',$limit = null, $parent = false, $siblings = false, $childs = false){
- $queryFilters = '';
- $data = array();
- if ($parent) {
- $queryFilters .= ' OR id=(SELECT parent FROM client WHERE id=?) ';
- $data[] = $this->id;
- }
- if ($siblings) {
- $queryFilters .= ' OR parent = (SELECT parent FROM client WHERE id=?) ';
- $data[] = $this->id;
- }
- if ($childs) {
- $queryFilters .= ' OR parent = ? ';
- $data[] = $this->id;
- }
- $query = 'SELECT address.*, client.label FROM `address`
- LEFT JOIN client ON address.uid = client.id
- WHERE uid IN (SELECT id FROM client WHERE id = ? '.$queryFilters.' ) AND scope="client" ';
- $data[] = $this->id;
- if(isset($type))
- $query.= ' AND address.type ="'.$type.'" ';
- if(isset($order))
- $query.= ' ORDER BY '.$order;
- if(isset($limit))
- $query.= ' LIMIT '.$limit;
- //todo gérer + de 1 niveau
- $address = Address::staticQuery($query,$data,true);
- if (isset($order) && $order == 'fullname') {
- usort($address,function($a,$b){
- if($a->fullName() == $b->fullName()) return 0;
- return $a->fullName() > $b->fullName() ? 1 :-1 ;
- });
- }
- return $address;
- }
- public function contacts($key=null){
- $contacts = array();
- $filters = array('uid'=>$this->id,'scope'=>'client') ;
- if(isset($key)) $filters['type'] = $key;
- foreach(Contact::loadAll($filters) as $contact){
- $contacts[$contact->type] = $contact;
- }
- if(!isset($key)) return $contacts;
- return isset($contacts[$key]) ? $contacts[$key] : new Contact();
- }
- public function subsites(){
- return $this->id!=0 ? Client::loadAll(array('parent'=>$this->id)) : array();
- }
- public function holding(){
- return $this->id!=0 && $this->parent!=0 ? Client::getById($this->parent) : new Client();
- }
- public function label(){
- return $this->type=='individual' ? $this->firstname.' '.$this->name : $this->label;
- }
- public function remove($recursive = false){
- $this->state = Client::INACTIVE;
- $this->save();
- if($recursive){
- foreach(Client::loadAll(array('parent'=>$this->id,'state:!='=>Client::INACTIVE)) as $subclient){
- $subclient->remove();
- }
- }
- global $myFirm;
- //Gestion des champs dynamiques
- if($myFirm->has_plugin('fr.core.dynamicform')){
- Plugin::need('dynamicform/DynamicForm');
- Dynamicform::remove('client-sheet-custom',array(
- 'scope'=>'client',
- 'uid'=>$this->id
- ));
- }
- ContactPerson::change(array('state'=>Client::INACTIVE),array('scope'=>'client','uid'=>$this->id));
- Address::delete(array('scope'=>'client','uid'=>$this->id));
- }
- }
- ?>
|