can('client','read') && !$myUser->can('client_sheet','read',0,array('contains'=>true))) throw new Exception("Permission non accordée");
			require_once(__DIR__.SLASH.'Client.class.php');
			
			
			// OPTIONS DE RECHERCHE, A ACTIVER POUR UNE RECHERCHE AVANCEE
			$query = 'SELECT DISTINCT main.*,phone.value as phone,mail.value as mail,parent.id parentId,parent.label parentLabel,address.street,address.complement,address.zip,address.city,'.Firm::joinString('fi').','.Dictionary::joinString('category').' FROM {{table}} main
			LEFT JOIN '.Client::tableName().' parent ON main.parent=parent.id 
			LEFT JOIN '.Firm::tableName().' fi ON main.firm=fi.id 
			LEFT JOIN '.Dictionary::tableName().' category ON main.category=category.id 
			LEFT JOIN '.Contact::tableName().' phone ON phone.uid=main.id AND phone.scope="client" AND phone.type="mobile" 
			LEFT JOIN '.Contact::tableName().' mail ON mail.uid=main.id AND mail.scope="client" AND mail.type="professional_mail" 
			LEFT JOIN '.Address::tableName().' address ON address.uid=main.id AND address.scope="client" AND address.type="'.Address::MAIN.'" 
			WHERE 1';
			$data = array();
			
			$allowedFields = array();
			$fields = array();
			$hasDynamicPlugin = $myFirm->has_plugin('fr.core.dynamicform') || ($myFirm->id==-1 && Plugin::is_active('fr.core.dynamicform'));
			//ajout des champs dynamiques dans la recherche
			if($hasDynamicPlugin){
				Plugin::need('dynamicform/DynamicForm');
				
				//le premier argument contient le slug du formulaire contenant toutes les colonnes possibles, le second les colonnes non choisies,la requete, l'alias si nécessaire
				$dynamicFields = DynamicForm::list('client-sheet-custom',array('firm'=>$myFirm->id));
				DynamicForm::query_column_add($dynamicFields,$query,'main');
				//On récupère les types de champs qui possèdent une propriété onLoad afin de l'appliquer si on a un champ dynamique
				$fieldTypes = array();
				$fieldCustom = array();
				foreach($dynamicFields as $field){
					$fieldTypes[$field['slug']] = $field['type'];
					$fieldCustom[$field['slug']] = $field;
					$allowedFields[] = 'dynamicField_'.$field['id'].'.value';
				}
			}
			//selection des colonnes à récuperer
			// le premier argument contient toutes les colonnes possibles, le second les colonnes non choisies
			column_secure_query(Client::fields(),$_,$query);
			//Recherche simple
			if(!empty($_['filters']['keyword'])){
				$query .= ' AND ( (main.type=? AND (main.label LIKE ? OR main.pseudonym LIKE ?) ) OR (main.type=? AND (main.name LIKE ? OR main.firstname LIKE ?)) OR main.comment LIKE ?)';
				$data[] = 'firm';
				$data[] = '%'.$_['filters']['keyword'].'%';
				$data[] = '%'.$_['filters']['keyword'].'%';
				$data[] = 'individual';
				$data[] = '%'.$_['filters']['keyword'].'%';
				$data[] = '%'.$_['filters']['keyword'].'%';
				$data[] = '%'.$_['filters']['keyword'].'%';
			}
			if(isset($_['selected'])){
				$query .= ' AND main.id IN ('.implode(',',array_fill(0, count($_['selected']), '?')).')';
				foreach ($_['selected'] as $selected) 
					$data[] = $selected;
			}
			$query .= ' AND main.state != ?';
			$data[] = Client::INACTIVE;
			
			
			//on vérifie les droits spéciaux qui peuvent bypasser
			//récuperation des droits spéciaux sur les fiches
			//on initialise a 0 pour eviter le plantage si aucun droit
			$rights = array(0);
			if(isset($myUser->rights['client_sheet'][0])) $rights += $myUser->rights['client_sheet'][0];
			if(isset($myUser->rights['client_sheet'][$myFirm->id])) $rights += $myUser->rights['client_sheet'][$myFirm->id];
			//tableau des id deletables
			$deletableSheets = array();
			//var_dump($rights);
			foreach($rights as $uid => $right){
				$data[] = $uid;
				if(isset($right['delete']) && $right['delete']===true) $deletableSheets[] =  $uid;
			}
		 	
		 	$query .= ' AND (main.id IN('.implode(',',array_fill(0, count($rights), '?')).') OR main.firm IN(?,?) ) ';
			$data[] = 0;
			$data[] = $myFirm->id;
			Plugin::callHook('client_search',array(&$query,&$data));
			//Recherche avancée
			if(isset($_['filters']['advanced'])){
			
					//traitement filtre custom pour recherche par contact interne
					$_['filters']['advanced'] = filter_alteration($_['filters']['advanced'],'internal_contact',function($filter) use(&$query,&$data){
						global $_;
						switch($filter['operator']){
							case '=':
							case '!=':
								$query.=' AND main.id '.($filter['operator']=='!='?' NOT ':'').' IN (SELECT uid FROM '.ContactPerson::tablename().' cp WHERE cp.scope="client" AND type="user" AND account=?) ';
								$data[] = $filter['value'][0];
							break;
							case 'null':
							case 'not null':
								$query.=' AND  (SELECT count(id) FROM '.ContactPerson::tablename().' cp WHERE cp.scope="client" AND type="user" AND uid=main.id) '.($filter['operator']=='null'?'=':'!=').' 0 ';
							break;
						}
						return null;
					});
					filter_secure_query($_['filters']['advanced'],array_merge($allowedFields,array('main.id','main.label','address.city','address.zip','main.type','main.condition','main.creator','main.job','main.code','main.siret','main.created','mail.value','phone.value','main.comment','fi.id')),$query,$data);
				
			}
			//Tri des colonnes
			if(isset($_['sort'])) sort_secure_query($_['sort'],array_merge($allowedFields,array('main.label','main.condition','main.type','main.state','mail.value','address.city','phone.value','fi.label')),$query,$data);
			//Pagination
			$itemPerPage = 20;
			if($_['export'] == 'true') $itemPerPage = 5000;
			$response['pagination'] = Client::paginate($itemPerPage,(!empty($_['page'])?$_['page']:0),$query,$data,'main');
			$clients = Client::staticQuery($query,$data,true,1);
			
			$ids = array();
			foreach($clients as $client)
				$ids[]= $client->id; 
			
			$subsites = array();
			if(!empty($ids)){
				foreach(Client::loadAll(array('parent:IN'=>$ids,'state'=>Client::ACTIVE)) as $subsite){
					if(!isset($subsites[$subsite->parent])) $subsites[$subsite->parent] = array();
					$subsites[$subsite->parent][] = $subsite->toArray();
				}
			}
			foreach($clients as $client){
				$row = $client->toArray();
				$row['deletable'] = true;
				if($myFirm->id!=$client->firm && !in_array($client->id, $deletableSheets)) $row['deletable'] = false;
				if(!$myUser->can('client','delete')) $row['deletable'] = false;
				$row['phone'] = $client->foreign('phone');
				$row['mail'] = $client->foreign('mail');
				$row['category'] = $client->join('category');
				$firm = $client->firm!= 0 ? $client->join('firm') : new Firm();
				$row['firm'] = $firm->toArray();
				
				$mainAddress = new Address();
				$mainAddress->street = $client->foreign('street');
				$mainAddress->complement = $client->foreign('complement');
				$mainAddress->zip = $client->foreign('zip');
				$mainAddress->city = $client->foreign('city');
				$row['address'] = $mainAddress->toArray();
				$row['address']['mapurl'] = $mainAddress->mapUrl();
				$row['type'] = $client->type();
				$row['condition'] = $client->condition();
				$row['logo'] = $client->logo();
				$row['holding'] = false;
				
				$row['affiliate'] = false;
				$row['meta'] = $client->meta();
				if($client->parent != 0){
					$holding = new Client();
					$holding->id = $client->foreign('parentId');
					$holding->label = $client->foreign('parentLabel');
					if($_['export'] == 'true'){
						$row['holding']  = $holding->toArray();
					}else{
						$row['parent'] = $holding->label;
					}
				}
				if($_['export'] == 'true'){
					$row['created'] = date('d-m-Y',$row['created']);
					$row['updated'] = date('d-m-Y',$row['updated']);
					$row['state'] = $row['state'] == Client::ACTIVE ? 'Actif' : 'Supprimé' ;
				}
				//Gestion des champs dynamiques
				if($hasDynamicPlugin){
					DynamicForm::search_values($row,array(
						'slugs'=> $client->foreign(),
						'types'=> $fieldTypes,
						'scope' => 'client',
						'force-raw' => $_['export'] == 'true' 
					));
				}
				if(isset($subsites[$client->id])){
					$row['affiliate']['rows'] = $subsites[$client->id];
					$row['affiliate']['count'] = count($subsites[$client->id]);
				}
				
				$response['rows']['client-'.$client->id] = $row;
			}
			
			/* Mode export */
			if($_['export'] == 'true'){
				$fieldsMapping = array();
				foreach (Client::fields(false) as $key => $value) 
					$fieldsMapping[$value['label']] = $key ;
				if($myFirm->has_plugin('fr.core.dynamicform')){
					foreach ($fieldCustom as $slug => $value) 
						$fieldsMapping[$value['label']] = $slug;
				}
				$fieldsMapping['E-mail'] = 'mail';
				$fieldsMapping['Téléphone'] = 'phone';
			
				
				$stream = Excel::exportArray($response['rows'],$fieldsMapping,'Export');
				File::downloadStream($stream,'export-clients-'.date('d-m-Y').'.xlsx');
				exit();
			}
		});
	
Action::register('client_client_mail_copy',function(&$response){
			global $myUser,$_;
			if(!$myUser->can('client','read')) throw new Exception('Vous n\'avez pas la permission de copier cet e-mail');
			if(count($_['ids'])==0) return;
			$response['mails'] = array();
			foreach(Contact::loadAll(array('scope'=>'client','uid:IN'=>$_['ids'],'type'=>'professional_mail')) as $contact){
				$response['mails'][] = $contact->value;
			}
		});
		
	
	//Fusion de deux clients
	Action::register('client_client_merge',function(&$response){
		global $myUser,$_,$conf;
		User::check_access('client','configure');
		require_once(__DIR__.SLASH.'Client.class.php');
		$response['rows'] = array();
		if(empty($_['left'])) throw new Exception($conf->get('client_label_singular')." de base non définis");
		if(empty($_['right'])) throw new Exception($conf->get('client_label_singular')." a fusionner non définis");
		
		if($_['right'] == $_['left']) throw new Exception("Vous ne pouvez pas fusionner un ".$conf->get('client_label_singular')." avec lui même");
		
		$left = Client::getById($_['left']);
		$right = Client::getById($_['right']);
		
		if(empty($left->id)) throw new Exception($conf->get('client_label_singular')." de base introuvable");
		if(empty($right->id)) throw new Exception($conf->get('client_label_singular')." de a fusionner introuvable");
		if(empty($_['keep'])) throw new Exception("Tableau d'écrasement non définis");
		$response['logs'] = $left->merge($right,$_['keep']);
	});
	
	//Vérifie les duplicatas possibles avec les clients existants
	Action::register('client_client_check_duplicate',function(&$response){
		global $myUser,$_;
		if(!$myUser->can('client','read')) throw new Exception("Permission non accordée");
		require_once(__DIR__.SLASH.'Client.class.php');
		$response['rows'] = array();
		if(empty($_['label'])) return $response;
		if(!empty($_['id'])) return $response;
		$response['rows'] = Client::check_duplicate($_['field'],$_['label'], isset($_['id'])?$_['id']:null );
	});
	
Action::register('client_relation_add',function(&$response){
			global $myUser,$_,$conf;
			if(!$myUser->can('client','read')) throw new Exception("Permission non accordée");
			require_once(__DIR__.SLASH.'Client.class.php');
			if(empty($_['id'])) throw new Exception($conf->get('client_label_singular')." non spécifié");
			if(empty($_['relation'])) throw new Exception("Relation non spécifiée");
			if(empty($_['level'])) throw new Exception("Type de relation non spécifiée");
			$site = Client::getById($_['id']);
			$relation = Client::getById($_['relation']);
			if(!$site || $site->id == 0) throw new Exception($conf->get('client_label_singular')." introuvable en base de donnée");
			if(!$relation || $relation->id == 0) throw new Exception($conf->get('client_label_singular')." à lier introuvable en base de donnée");
			
			if($_['level'] == 'holding'){
				if($relation->parent == $site->id) throw new Exception("Impossible d'ajouter en holding un établissement déjà filiale");
				$site->parent = $relation->id;
				$site->save();
			}else{
				if($site->parent == $relation->id) throw new Exception("Impossible d'ajouter en filiale un établissement déjà holding");
				$relation->parent = $site->id;
				$relation->save();
			}
		});
	
Action::register('client_relation_delete',function(&$response){
			global $myUser,$_,$conf;
			User::check_access('client','read');
			require_once(__DIR__.SLASH.'Client.class.php');
			if(empty($_['id'])) throw new Exception($conf->get('client_label_singular')." non spécifié");
			if(empty($_['relation'])) throw new Exception("Relation non spécifiée");
			if(empty($_['level'])) throw new Exception("Type de relation non spécifiée");
			
			
			switch($_['level']){
				case 'holding':
					$site = Client::getById($_['id']);
					$relation = Client::getById($_['relation']);
					if(!$site || $site->id == 0) throw new Exception($conf->get('client_label_singular')." introuvable en base de donnée");
					if(!$relation || $relation->id == 0) throw new Exception($conf->get('client_label_singular')." à lier introuvable en base de donnée");
					$site->parent = null;
					$site->save();
				break;
				case 'subsite':
					$site = Client::getById($_['id']);
					$relation = Client::getById($_['relation']);
					if(!$site || $site->id == 0) throw new Exception($conf->get('client_label_singular')." introuvable en base de donnée");
					if(!$relation || $relation->id == 0) throw new Exception($conf->get('client_label_singular')." à lier introuvable en base de donnée");
					$relation->parent = null;
					$relation->save();
				break;
				case 'memberof':
					ContactPerson::remove($_['relation']);
				break;
			}
			
		});
	
	//Retourne la liste des relations  (filiales et holding)
	Action::register('client_relation_search',function(&$response){
		global $myUser,$_,$myFirm;
		
		if(!$myUser->can('client','read') && $_['client']!=0 && !$myUser->can('client_sheet','read',$_['client'])) throw new Exception("Permission non accordée sur cette fiche");
		require_once(__DIR__.SLASH.'Client.class.php');
		$response['rows'] = array();
		if(empty($_['client'])) return $response['rows'];
		$filters = array('parent'=>$_['client'],'firm:IN'=>array(0,$myFirm->id),'state'=>Client::ACTIVE);
		//si l'user n'est pas en acces tout client, on ne lui affiche que les relation client auxquelles il a acces
		if(!$myUser->can('client','read')){
			$allowedSheets  = array();
			foreach($myUser->rights['client_sheet'] as $firm => $rights){
				foreach($rights as $uid=>$right){
					if($right['read']) $allowedSheets[] = $uid;
				}
			}
			
			$filters['id:IN'] = $allowedSheets;
		}
		$clients = Client::loadAll($filters,array('label'));
		foreach($clients as $client){
			$row = $client->toArray();
			$addresses = $client->addresses('global');
			$row['address'] = isset($addresses[0]) ? $addresses[0] : new Address();
			$row['level'] = 'subsite';
			$response['rows'][] = $row;
		}
		$client = Client::getById($_['client']);
		
		if(!empty($client->parent)){
			$holdingObject = $client->holding();
			$holding = $holdingObject->toArray();
			$addresses = $holdingObject->addresses('global');
			$holding['address'] = isset($addresses[0]) ? $addresses[0] : new Address();
			$holding['level'] = 'holding';
			$response['rows'][] = $holding;
		}
		foreach(Client::staticQuery('SELECT c.*,cp.id as relation_id FROM '.ContactPerson::tablename().' cp LEFT JOIN {{table}} c ON c.id=cp.uid WHERE cp.account=? AND cp.scope=? and cp.type=?',array($_['client'],'client','client'),true) as $client){
			$row = $client->toArray();
			$addresses = $client->addresses('global');
			$row['address'] = isset($addresses[0]) ? $addresses[0] : new Address();
			$row['level'] = 'memberof';
			$row['id'] =  $client->foreign('relation_id');
			$response['rows'][] = $row;
		}
	});
	
	Action::register('client_api_search',function(&$response){
		global $myUser,$_,$conf;
		if(!$myUser->can('client','read')) throw new Exception("Permission non accordée");
		require_once(__DIR__.SLASH.'Client.class.php');
		
		if(empty($conf->get('client_api_search_url'))) throw new Exception("L'api de recherche ".$conf->get('client_label_singular')." n'est pas configurée, merci de contacter un administrateur");
		
		//ex : https://entreprise.data.gouv.fr/api/sirene/v1/full_text/toxgen
		$url = str_replace('{{label}}',rawurlencode($_['label']),$conf->get('client_api_search_url')); 
		$ch = curl_init();
		curl_setopt($ch, CURLOPT_URL, $url);
		curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
		curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
		curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
		$stream = curl_exec($ch);
		$info = curl_getinfo($ch);
		curl_close($ch);
		$json = json_decode($stream,true);
		if(!$json) throw new Exception("Impossible de contacter l'api de recherche ".$conf->get('client_label_singular'));
		
		if($info['http_code'] == 404 || !isset($json['etablissement']) || count($json['etablissement']) ==0 ) throw new Exception($conf->get('client_label_singular')." non trouvé avec ce libellé.");
		foreach ($json['etablissement'] as $row) {
			$line = array();
			$line['label'] = $row['nom_raison_sociale'];
			$line['siren'] = $row['siren'];
			$line['siret'] = $row['siret'];
			$line['created'] = $row['date_creation'];
			if(strlen($line['created'])== 8){
				$line['created'] = substr($line['created'], -2).'/'.substr($line['created'], -4,2).'/'.substr($line['created'], 0,4);
			}else{
				$line['created'] = '';
			}
			$line['street'] = $row['numero_voie'].' '.$row['type_voie'].' '.$row['libelle_voie'];
			$line['city'] = $row['libelle_commune'];
			$line['zip'] = $row['code_postal'];
			$line['size'] = $row['categorie_entreprise'];
			$line['status'] = $row['libelle_nature_juridique_entreprise'];
			$line['employees'] = $row['tranche_effectif_salarie'];
			$line['job'] = $row['libelle_activite_principale'];
			$response['rows'][] = $line;
		}
		 
	});
		
	
	Action::register('client_tab_load',function(&$response){
		global $myUser,$_;
		if(!$myUser->can('client','read') && $_['id']!=0 && !$myUser->can('client_sheet','read',$_['id'])) throw new Exception("Permission non accordée sur cette fiche");
		$tab = $_['tab'];
		Plugin::callHook('client_page',array($tab));
		exit();
	});
	//Ajout ou modification d'élément client
	Action::register('client_client_save',function(&$response){
			global $myUser, $_, $conf,$myFirm;
			User::check_access('client','edit');
			require_once(__DIR__.SLASH.'Client.class.php');
			$item = Client::provide();
			$oldItem = clone $item;
			if($item->id!=0 && $item->firm!=$myFirm->id && !$myUser->can('client_sheet','edit',$item->id) ) throw new Exception("Vous n'avez pas la permission pour editer cette fiche");
			if(empty($_['label'])) throw new Exception("Libellé obligatoire");
				
			$item->label = $_['label'];
			if(isset($_['firstname']) && !empty($_['firstname'])) $item->firstname =  ucfirst(mb_strtolower(trim($_['firstname'])));
			if(isset($_['name']) && !empty($_['name'])) $item->name = mb_strtoupper(trim($_['name']));
			if(isset($_['rate']) && !empty($_['rate'])) $item->rate = $_['rate'];
			if(isset($_['siret'])) $item->siret = $_['siret'];
			if(isset($_['comment'])) $item->comment = trim($_['comment']);
			if(isset($_['parent']) && !empty($_['parent'])) $item->parent = $_['parent'];
			if(isset($_['type']) && !empty($_['type'])) $item->type = $_['type'];
			if(!empty($conf->get('client_condition')) && $conf->get('client_condition')!='both'){
				 $item->condition = $conf->get('client_condition');
			}else{
				if(isset($_['condition']) && !empty($_['condition'])) $item->condition = $_['condition'];
			}
			
			
			if(isset($_['category'])) $item->category = $_['category'];
			if(isset($_['job'])) $item->job = $_['job'];
			if(isset($_['pseudonym'])) $item->pseudonym = $_['pseudonym'];
			$item->state = Client::ACTIVE;
			$item->firm = $myFirm->id;
			Plugin::callHook('client_save',array(&$item,$oldItem));
			$item->save();
			Plugin::callHook('client_saved',array(&$item,$oldItem));
			//Gestion des champs dynamiques
			if($myFirm->has_plugin('fr.core.dynamicform')){
				Plugin::need('dynamicform/DynamicForm');
				Dynamicform::record('client-sheet-custom',array(
					'scope'=>'client',
					'uid'=>$item->id
				),$_);
			}
			
			//trigger pour utilisation sur le workflow
			if($myFirm->has_plugin('fr.core.workflow')){
				Plugin::need('workflow/WorkflowEvent');
				WorkflowEvent::trigger('client-client-'.($oldItem->id==0?'create':'update'),array('old'=>$oldItem,'current'=>$item));
			}
		
			$history = new History();
			$history->scope = 'client';
			$history->uid = $item->id;
			if(empty($_['id'])){
				$history->comment = "Création ".$conf->get('client_label_singular');
				$history->save();
			}else{
				$history->comment = "Modification ".$conf->get('client_label_singular')." :";
				$differences = Entity::compare($oldItem,$item);
				$fields = Client::fields(false);
				foreach ($differences as $difference) {
					$field = $difference['field'];
					if(isset($fields[$difference['field']])) $field = $fields[$difference['field']]['label'];
					$history->comment.="\n".$field.' : de '.truncate($difference['value1']).' à '.truncate($difference['value2'].'');
				}
				if(count($differences)>0) $history->save();
			}
			
			
		
			if(!empty($_FILES['logo'])){
				//Suppression ancien logo
				foreach (glob($item->dir()."logo.*") as $filename)
					unlink($filename);
				$logo = File::upload('logo','client'.SLASH.$item->id.SLASH.'logo.{{ext}}',104857060,array('jpg','png','jpeg','gif'));
				Image::resize($logo['absolute'],150,150);
			}
			if(!empty($_FILES['cover'])){
				//Suppression ancienne bannière
				foreach (glob($item->dir()."cover.*") as $filename)
					unlink($filename);
				$cover = File::upload('cover','client'.SLASH.$item->id.SLASH.'cover.{{ext}}',104857060,array('jpg','png','jpeg','gif'));
				$path = Image::toJpg($cover['absolute']);
				Image::resize($path,500,500,true,false);
			}
			$response = $item->toArray();
			if(isset($_['phone']) || isset($_['mail'])){
				$contacts = $item->contacts();
				
				if(isset($_['phone'])){
					$phone = isset($contacts[Contact::MOBILE]) ? $contacts[Contact::MOBILE] : new Contact();
					if(empty($_['phone']) && $phone->id !=0){
							Contact::deleteById($phone->id);
					}else{
						
						$phone->type = Contact::MOBILE;
						$phone->state = Contact::ACTIVE;
						$phone->value = str_replace(' ', '', $_['phone']);
						$phone->uid = $item->id ;
						$phone->scope = 'client' ;
						$phone->save();
					}
				}
				if(isset($_['mail'])){
					$mail = isset($contacts[Contact::PROFESSIONAL_MAIL]) ? $contacts[Contact::PROFESSIONAL_MAIL] : new Contact();
					if(empty($_['mail']) && $mail->id !=0){
						Contact::deleteById($mail->id);
					}else{
						$mail->type = Contact::PROFESSIONAL_MAIL;
						$mail->state = Contact::ACTIVE;
						$mail->value = trim($_['mail']);
						$mail->uid = $item->id ;
						$mail->scope = 'client' ;
						$mail->save();
					}
				}
			}
		});
	
	
	//Ajout ou modification d'élément client
Action::register('client_assets_load',function(&$response){
			global $myUser,$_;
			if(!$myUser->can('client','read') && !$myUser->can('client_sheet','read',0,array('contains'=>true)))  throw new Exception("Permission non accordée");
			require_once(__DIR__.SLASH.'Client.class.php');
			
			switch($_['type']){
				case 'logo': 
					$client = new Client;
					if(isset($_['client']) && !empty($_['client'])) $client->id = $_['client'];
					$path = $client->logo(true);
				break;
				case 'cover': 
					$client = new Client;
					if(isset($_['client']) && !empty($_['client'])) $client->id = $_['client'];
					$path = $client->cover(true);
				break;
				case 'contact': 
					$contact = ContactPerson::getById($_['contact']);
					$path = $contact->avatar();
				break;
				default: 
					$path = '';
				break;
			}
			File::downloadFile($path);
});
	
	//Suppression d'élement client
Action::register('client_client_delete',function(&$response){
			global $myUser,$_,$myFirm;
			User::check_access('client','delete');
			require_once(__DIR__.SLASH.'Client.class.php');
			
			$client = Client::getById($_['id']);
			if($client->firm!=$myFirm->id && !$myUser->can('client_sheet','delete',$client->id) ) throw new Exception("Vous n'avez pas la permission pour supprimer cette fiche");
			$client->remove($_['recursive']==1);
		});
	
	
	//Sauvegarde des configurations de client
Action::register('client_setting_save',function(&$response){
			global $myUser,$_,$conf;
			User::check_access('client','configure');
			//Si input file "multiple", possibilité de normlaiser le
			//tableau $_FILES récupéré avec la fonction => normalize_php_files();
			
			foreach(Configuration::setting('client') as $key=>$value){
				if(!is_array($value)) continue;
				$allowed[] = $key;
			}
			foreach ($_['fields'] as $key => $value) {
				
				if(in_array($key, $allowed))
					$conf->put($key,$value);
			}
		});
	
	
	
	/** CLIENTCONTACT **/
	//Récuperation d'une liste de clientcontact
Action::register('client_contact_search',function(&$response){
			global $myUser,$_,$myFirm;
			require_once(__DIR__.SLASH.'Client.class.php');
			if(!$myUser->can('client','read') && $_['client']!=0 && !$myUser->can('client_sheet','read',$_['client'])) throw new Exception("Permission non accordée sur cette fiche");
			
			if(empty($_['client'])) return $response;
			$client = Client::getById($_['client']);
			//if($client->id!=0 && !in_array($client->firm,array(0,$myFirm->id))) throw new Exception("Ces contacts de fiche ne sont pas disponibles pour votre etablissement");
			//si l'user n'est pas en acces tout client, on ne lui affiche que les relation client auxquelles il a acces
			if(!$myUser->can('client','read')){
					$allowedSheets  = array();
					foreach($myUser->rights['client_sheet'] as $firm => $rights){
						foreach($rights as $uid=>$right){
							if($right['read']) $allowedSheets[] = $uid;
						}
					}
			}
			foreach(ContactPerson::getAll(array('where'=>array('scope'=>'client','uid'=>$client->id))) as $clientcontact){
				if($clientcontact->type=="client" && isset($allowedSheets) && !in_array($clientcontact->account,$allowedSheets)) continue;
				
				$row = $clientcontact->toArray();
				$row['fullName'] =  $clientcontact->fullName();
				$row['avatar'] = 'action.php?action=client_assets_load&type=contact&contact='.$clientcontact->id;
				$row['tag'] = $clientcontact->getTags();
				$row['hasTag'] = !empty($row['tag']);
				switch($clientcontact->type){
					case 'client':
						require_once(__DIR__.SLASH.'Client.class.php');
						$client = Client::getById($clientcontact->account);
						if(!$client) continue 2;
						$row['avatar'] = $client->logo();
						$row['fullName'] = $client->label();
						$row['link'] = 'index.php?module=client&page=sheet.client&id='.$row['account'];
						$contacts = $client->contacts();
						if(isset($contacts['professional_mail'])) $row['mail'] = $contacts['professional_mail']->value;
						if(isset($contacts['professional_mail'])) $row['mobile'] = $contacts['mobile']->value;
						if(!empty($client->job)) $row['job'] = $client->job;
					break;
					case 'user':
						$user = User::byLogin($clientcontact->account);
						$row['avatar'] = $user->getAvatar();
						$row['fullName'] = $user->fullName();
						$row['mobile'] = $user->mobile;
						$row['job'] = $user->function;
						$row['phone'] = $user->phone;
						$row['mail'] = $user->mail;
					break;
				}
				$response['rows'][] = $row;
			}
		});
	
	//Récuperation ou edition d'élément clientcontact
Action::register('client_contact_edit',function(&$response){
			global $myUser,$_;
			User::check_access('client','edit');
			$contact = ContactPerson::provide();
			$contact->meta();
			$response = $contact->toArray();
			$response['tag'] = $contact->getTags();
			
		});
	
	
	//Ajout ou modification d'élément clientcontact
Action::register('client_contact_save',function(&$response){
			global $myUser,$_,$conf;
			User::check_access('client','edit');
			Plugin::need('client/Client');
			
			$item = ContactPerson::provide();
			$oldItem = clone $item;
			$item->type = $_['type'];
			
			//Contact référent utilisteur ou client interne
			if(!empty($_['account'])) $item->account = $_['account'];
			    
			
			if($item->type=='external'){
			    if(empty($_['name']) && empty($_['firstname']) && empty($_['mail']) && empty($_['phone'])) throw new Exception("Au moins l'un des champs Prénom, Nom, Mail ou Téléphone est requis");
			    $item->name = $_['name'];
			    $item->firstname = $_['firstname'];
			    $item->civility = $_['civility'];
			    $item->meta['type'] = 'contact';
		        if(!empty($_['mail']) && !check_mail(trim($_['mail']))) throw new Exception("Mail invalide");
		        $item->mail = trim($_['mail']);
		        if(!empty($_['phone']) && !check_phone_number($_['phone'])) throw new Exception("Téléphone invalide");
		        $item->phone = normalize_phone_number($_['phone']);
		        if(!empty($_['mobile']) && !check_phone_number($_['mobile'])) throw new Exception("Téléphone mobile invalide");
		        $item->mobile = normalize_phone_number($_['mobile']);
			}
			$item->scope = 'client';
			$item->uid = $_['client'];
			$item->job = $_['job'];
			$item->comment = $_['comment'];
			$item->setTags($_['tag']);
			$item->state = ContactPerson::ACTIVE;
			$item->save_all();
			$history = new History();
			$history->scope = 'client';
			$history->uid = $_['client'];
			if(empty($_['id'])){
				$history->comment = "Création du contact ".$conf->get('client_label_singular')." ".$item->fullName();
				$history->save();
			}else{
				$history->comment = "Modification du contact ".$conf->get('client_label_singular')." ".$item->fullName().' : ';
				$differences = Entity::compare($oldItem,$item);
				$fields = Client::fields(false);
				foreach ($differences as $difference) {
					$field = $difference['field'];
					if(isset($fields[$difference['field']])) $field = $fields[$difference['field']]['label'];
					$history->comment.="\n".$field.' : de '.truncate($difference['value1']).' à '.truncate($difference['value2'].'');
				}
				if(count($differences)>0) $history->save();
			}
		});
	
	//Suppression d'élement clientcontact
Action::register('client_contact_delete',function(&$response){
			global $myUser,$_,$conf;
			User::check_access('client','delete');
			$item = ContactPerson::provide();
			$history = new History();
			$history->scope = 'client';
			$history->uid = $item->uid;
			$history->comment = "Suppression du contact ".$conf->get('client_label_singular')." ".$item->fullName();
			$history->save();
			ContactPerson::remove($item->id);
			
		});
	
	//Récupération card d'un contact
Action::register('client_card',function(&$response){
			global $myUser,$myFirm,$_;
			
			require_once(__DIR__.SLASH.'Client.class.php');
			
			$client = Client::provide();
			if(!$myUser->can('client','read') && $client->id!=0 && !$myUser->can('client_sheet','read',$client->id)) throw new Exception("Permission non accordée sur cette fiche");
			ob_start();
			require_once(__DIR__.SLASH.'card.client.php');
			$stream = ob_get_clean();
			$response['content'] = $stream;
		});
	
	//composant client
	Action::register('client_autocomplete',function(&$response){
        	global $myUser,$_,$myFirm;
    		require_once(__DIR__.SLASH.'Client.class.php');
    		if (!$myUser->connected()) throw new Exception("Vous devez être connecté", 401);
    		$response['rows'] = array();
			$data = array("%".$_['keyword']."%","%".$_['keyword']."%",Client::ACTIVE);
			//retourne en priorité les matchs à 100%, pour les match keyword%, puis les autres
				$query = 'SELECT c.*,(SELECT label FROM {{table}} p WHERE p.id=c.parent) parentLabel FROM {{table}} c WHERE (c.label LIKE ? OR pseudonym LIKE ?) AND c.state=? ';
			if(isset($_['data']['parent']) && !empty($_['data']['parent']) && is_numeric($_['data']['parent'])){
				$query .= ' AND c.parent=? ';
				$data[] = $_['data']['parent'];
			}
			$query .= ' AND c.firm=? ';
			if(isset($_['data']['firm']) && !empty($_['data']['firm']) && is_numeric($_['data']['firm'])){
				$data[] = $_['data']['firm'];
			}else{
				$data[] = $myFirm->id;
			}
			$query .= ' ORDER BY
				  CASE
				    WHEN c.label = ? THEN 1
				    WHEN c.label LIKE ? THEN 2
				    ELSE 3
				  END
        		LIMIT 10';
        	$data[] = $_['keyword'];
			$data[] = '%'.$_['keyword'];
        	$clients = Client::staticQuery($query,$data,true);
        	foreach($clients as $client){
                $response['rows'][] = array(
                	'label'=>html_entity_decode($client->label, ENT_QUOTES).(!empty($client->pseudonym) ? ' ('.html_entity_decode($client->pseudonym, ENT_QUOTES).')' :''),
                	'parentLabel'=>html_entity_decode($client->foreign('parentLabel'), ENT_QUOTES),
					'id'=>$client->id,
					'logo' => $client->logo()
				);
        	}
        	if(isset($_['data']) && isset($_['data']['before']) && isset($_['data']['before'])!=''){
        		$list = json_decode(html_entity_decode($_['data']['before']),true);
        		if(is_array($list)){
        			foreach ($list as $key=>$value) {
        				if(preg_match('/'.$_['keyword'].'/i', $value))
        					array_unshift($response['rows'],array('label'=>$value,'id'=>$key));
        			}
        		}
        	}
        });
    
    Action::register('client_by_uid',function(&$response){
        global $myUser,$_;
    	if (!$myUser->connected()) throw new Exception("Vous devez être connecté",401);
    	require_once(__DIR__.SLASH.'Client.class.php');
    	
    	$response['items'] = array();
    	
    	$query = 'SELECT main.*,p.label as parentLabel FROM {{table}} main LEFT JOIN {{table}} p ON main.parent=p.id WHERE main.id IN(';
    	$query .= implode(',', array_fill(0, count($_['items']), '?'));
    	$query .= ')';
    	
    	
	    foreach(Client::staticQuery($query,$_['items'],true) as  $client) {
	       $row = $client->toArray();
	       unset($row['parent']);
	       if(!empty($client->foreign('parentLabel'))) $row['parent'] = array('label'=>$client->foreign('parentLabel'));
    	   $row['label'] =  html_entity_decode($row['label'], ENT_QUOTES);
    	   if(!empty($row['pseudonym'])) $row['label'].= ' ('.html_entity_decode($row['pseudonym'], ENT_QUOTES).')' ;
    	   $response['items'][$row['id']] = $row;
	    }
	    if(isset($_['before']) && $_['before']!=''){
    		$list = json_decode(html_entity_decode($_['before']),true);
    		if(is_array($list)){
    			if(isset($list[$_['id']])) $response['items'][]  = array('label' => $list[$_['id']], 'id'=>$_['id']);
    		}
    	}
        
    });
    
    //ADDRESSES 
    //Récuperation d'une liste d'adresses
Action::register('client_address_search',function(&$response){
			global $myUser,$_,$myFirm;
			require_once(__DIR__.SLASH.'Client.class.php');
			if(!$myUser->can('client','read') && $_['client']!=0 && !$myUser->can('client_sheet','read',$_['client'])) throw new Exception("Permission non accordée sur cette fiche");
			if(empty($_['client'])) return $response;
			$client = Client::getById($_['client']);
			//if($client->id!=0 && !in_array($client->firm,array(0,$myFirm->id))) throw new Exception("Ces addresses de fiche ne sont pas disponibles pour votre etablissement");
			$addresses = Address::loadAll(array('scope'=>'client','uid'=>$_['client']));
			foreach($addresses as $address){
				$row = $address->toArray();
				$row['type'] = Address::types($row['type']);
				$row['type']['slug'] = $address->type;
			
				$response['rows'][] = $row;
			}
		});
	
	
	//Récuperation ou edition d'élément addresse
Action::register('client_address_edit',function(&$response){
			global $myUser,$_;
			User::check_access('client','edit');
			$address = Address::provide();
			if($address->id!=0 && $address->scope != 'client') throw new Exception("Entité non conforme");	
			$response = $address->toArray();
		});
	
	
	//Ajout ou modification d'élément clientcontact
Action::register('client_address_save',function(&$response){
			global $myUser,$_;
			require_once(__DIR__.SLASH.'Client.class.php');
			User::check_access('client','edit');
			
			if(empty($_['client'])) throw new Exception("Client non spécifié");
			if(empty($_['street']) && empty($_['zip']) && empty($_['city'])) throw new Exception("Vous devez spécifier au minimum une ville, un code postal ou une rue");
			
			$address = Address::provide();
			$address->fromArray($_);
			$address->scope = 'client' ;
			$address->uid = $_['client'] ;
			$address->save();
			//Enregistrement des coordonées gps dans les méta client si l'adresse est la principale
			if($address->type==Address::MAIN){
				$coordinates = $address->locationCoordinates();
				$client = Client::getById($address->uid);
				$client->meta('longitude', $coordinates['longitude']);
				$client->meta('latitude', $coordinates['latitude']);
				$client->save();
			}
			History::put('client',$_['client'],(empty($_['id']) ? 'Création ': ' Modification ' )." d'une adresse de type : ".Address::types($address->type)['label'].' : '.$address->fullName());
		});
	
	//Suppression d'élement clientcontact
Action::register('client_address_delete',function(&$response){
			global $myUser,$_;
			User::check_access('client','delete');
			require_once(__DIR__.SLASH.'Client.class.php');
			$address = Address::getById($_['id']);
			if($address->scope!='client') throw new Exception("Entité spécifiée non conforme",403);
			Address::deleteById($address->id);
			History::put('client',$address->uid,"Suppression d'une adresse de type : ".Address::types($address->type)['label']);
		});
	
	/*WIDGET*/
	Action::register('client_widget_load',function(&$response){
		global $myUser,$_;
		if(!$myUser->can('client','read')) throw new Exception("Permission non accordée");
		Plugin::need('dashboard/DashboardWidget');
		$widget = DashboardWidget::current();
		$widget->title = 'Widget Client';
		ob_start();
		//Décommenter après avoir créé widget.php
		require_once(__DIR__.SLASH.'client.widget.php');
		$widget->content = ob_get_clean();
		
		echo json_encode($widget);
		exit;
	});
	
	/** HISTORY **/
	//Récuperation d'une liste de history
Action::register('client_core_history_search',function(&$response){
			global $myUser,$_;
			if(!$myUser->can('client_history','read')) throw new Exception("Permission non accordée sur cette fiche");
			if(!$myUser->can('client','read') && $_['id']!=0 && !$myUser->can('client_sheet','read',$_['id'])) throw new Exception("Permission non accordée sur cette fiche");
			
			// OPTIONS DE RECHERCHE, A ACTIVER POUR UNE RECHERCHE AVANCEE
			$query = 'SELECT * FROM {{table}} WHERE 1';
			$data = array();
			//scopé sur le client
			$query .= ' AND scope = ? AND uid = ?';
			$data[] = 'client';
			$data[] = $_['id'];
			
			//Recherche simple
			if(!empty($_['filters']['keyword'])){
				$query .= ' AND comment LIKE ?';
				$data[] = '%'.$_['filters']['keyword'].'%';
			}
			//Recherche avancée
			if(isset($_['filters']['advanced'])) filter_secure_query($_['filters']['advanced'],array('comment','created','creator'),$query,$data);
			$query .= ' ORDER BY created DESC';
			//Pagination
			$response['pagination'] = History::paginate(20,(!empty($_['page'])?$_['page']:0),$query,$data);
			$historys = History::staticQuery($query,$data,true,0);
			
			foreach($historys as $history){
				$row = $history->toArray();
				$monthName = month_name(date('m',$history->created));
				$row['created'] = array(
					'dayShortName' => day_name(date('N',$history->created)),
					'day' => date('d',$history->created),
					'monthName' => strlen($monthName)>4 ? substr(month_name(date('m',$history->created)), 0, 4).'.' : $monthName,
					'time' => date('H:i',$history->created)
				);
				$row['comment'] = html_entity_decode($row['comment']);
				if($_['export'] == 'true'){
					$row['created'] = date('d-m-Y',$history->created);
					$row['updated'] = date('d-m-Y',$history->updated);
				}
				$creator = User::byLogin($row['creator']);
				$row['creator'] = $creator->toArray();
				$row['editable'] = $row['type'] == History::TYPE_COMMENT ;
				$row['creator']['fullName'] = $creator->fullName();
				$response['rows'][] = $row;
			}
			/* Mode export */
			if($_['export'] == 'true'){
				$fieldsMapping = array();
				foreach (History::fields(false) as $key => $value) 
					$fieldsMapping[$value['label']] = $key ;
		
				$stream = Excel::exportArray($response['rows'],$fieldsMapping,'Export');
				File::downloadStream($stream,'historique-client-'.date('d-m-Y').'.xlsx');
				exit();
			}
			
		});
	
	Action::register('client_core_history_save',function(&$response){
		global $myUser,$_,$myFirm;
		User::check_access('client_history','edit');
		
		if(!isset($_['client'])) throw new Exception('Id client manquant');
		if(!isset($_['comment'])) throw new Exception('Message manquant');
		$history = History::provide();
		$history->scope = 'client';
		$history->uid = $_['client'];
		$history->comment = $_['comment'];
		$history->type = History::TYPE_COMMENT;
		$history->save();
				
	});
	Action::register('client_history_edit',function(&$response){
		global $myUser,$_,$myFirm;
		User::check_access('client_history','edit');
		require_once(__DIR__.SLASH.'Client.class.php');
		
		$history = History::getById($_['id']);
		if($history->scope!='client') throw new Exception('Vous ne pouvez editer ce type d\'historique');
		$response = $history->toArray();
		$response['comment'] = html_entity_decode($response['comment']);
	});
	Action::register('client_core_history_delete',function(&$response){
		global $myUser,$_,$myFirm;
		User::check_access('client_history','delete');
		require_once(__DIR__.SLASH.'Client.class.php');
		
		$history = History::getById($_['id']);
		if($history->scope!='client') throw new Exception('Vous ne pouvez supprimer ce type d\'historique');
		History::deleteById($history->id);
	});
	Action::register('client_import_component',function(&$response){
			global $myUser,$_;
			if(!$myUser->can('client','configure')) throw new Exception("Permission non accordée");
			
			File::handle_component(array(
				'namespace' => 'client', //stockés dans file/client/*.*
				'access' => 'client', // crud sur summary,
				'size' => '1000000000', // taille max
				'extension' => 'csv',
				'storage' => 'client/import/*' //chemin complet vers le fichier stocké
			),$response);
	});
	
	Action::register('client_import',function(&$response){
			global $myUser,$_,$myFirm;
			if(!$myUser->can('client','configure')) throw new Exception("Permission non accordée");
			
			if(count($_['attachments'])==0) throw new Exception("Merci d'envoyer un fichier au format csv avant d'appuyer sur le boutton import");
			if($_['attachments'][0]['extension']!='csv') throw new Exception("Extension invalide (accepté: csv)");
			if($_['attachments'][0]['size'] > 1000000000 ) throw new Exception("Taille trop importante  (max accepté: 1Go)");
			require_once(__DIR__.SLASH.'Client.class.php');
			$clientManager = new Client();
			$keyLabelMap = array();
			
			foreach ($clientManager->fields as $key => $meta) {
				$keyLabelMap[$meta['label']] = $key;
			}
			
			$isDynamic = array();
			if($myFirm->has_plugin('fr.core.dynamicform')){
				Plugin::need('dynamicform/DynamicForm');
				foreach (DynamicForm::list('client-sheet-custom') as $key => $meta) {
					$keyLabelMap[$meta['label']] = $meta['slug'];
					$isDynamic[$meta['slug']] =  $meta;
				}
			}
			$keyLabelMap['Contacts'] = 'contacts';
			$keyLabelMap['Adresses'] = 'addresses';
			$keyLabelMap['Client Parent'] = 'parent';
			$lines = explode("\r\n",utf8_encode(file_get_contents(File::temp().str_replace('/tmp/','',$_['attachments'][0]['path']))));
			if(count($lines)<2) throw new Exception("Le fichier d'import est vide");
			$headers = array_shift($lines);
			$headers = explode(';',$headers);
			$headersColumnMap = array();
			foreach($headers as $i => $header){
				
				if(!isset($keyLabelMap[$header])) continue;
				$headersColumnMap[$i] = $keyLabelMap[html_entity_decode($header)];
			}
			$response['warnings'] = array();
			$transformMapping = array();
			//convertion des types label -> bdd
			$typesLabel = array();
			foreach (Client::types() as $typeKey=>$type) 
				$typesLabel[$type['label']] = $typeKey;
			$transformMapping['type'] = function($value,$client) use ($typesLabel){
				return isset($typesLabel[$value]) ? $typesLabel[$value] : '';
			};
			//convertion des conditions label -> bdd
			$conditionsLabel = array();
			foreach (Client::conditions() as $conditionKey=>$condition) 
				$conditionsLabel[$condition['label']] = $conditionKey;
			$transformMapping['condition'] = function($value,$client) use ($conditionsLabel){
				return isset($conditionsLabel[$value])? $conditionsLabel[$value] : '';
			};
			//convertion des catégories label -> bdd
			$categoriesLabel = array();
			$categoriesDictionary = Dictionary::bySlug('client_category');
			foreach (Dictionary::slugToArray('client_category',true) as $categoryKey=>$category) 
				$categoriesLabel[$category->label] = $categoryKey;
			//Convertion des adresses
			/*
			le format des adresse doit être le suivant dans le csv : add1\nadd2[:type], ex : 
			"122 avenue de saint emilion 33600 Martignas sur jalles
			344 rue frédéric sévène 33400 Talence:facturation"
			*/
			$transformMapping['addresses'] = function($value,$client){
				
				
				//suppression des "" de chaque coté de la valeur si existants
				if(preg_match('/^"(.*)"$/si', $value,$match))
					$value = $match[1];
				
				foreach(explode("\n",$value) as $rawAddress){
					$address = new Address();
					$type = Address::MAIN;
					$rawAddress = explode(':',$rawAddress);
					if(isset($rawAddress[1])) $type = $rawAddress[1];
					$street = '';
					$zip = '';
					$city = '';
					$country = '';
					$complement = '';
					if(preg_match('/([0-9]*)? ?(.*) ([0-9]{5}) ([^,]*),?\s*(.*)?/i', $rawAddress[0],$match)){
						
						if(!empty($match[1]) || !empty($match[2])){
							$street = (!empty($match[1]) ? $match[1] : '').(!empty($match[2]) ? ' '.$match[2] : '');
							if(!empty($match[3])) $zip = $match[3];
							if(!empty($match[4])) $city = $match[4];
							if(!empty($match[5])) $country = $match[5];
						}
					}else{
						//Si on ne parviens pas a parser l'adresse 
						//On essaye de récuperer le CP
						if(preg_match('/ ([0-9]{5}) /i', $rawAddress[0],$match)){
							$zip = $match[1];
						}
						//on stoque tout dans la rue
						$street = $rawAddress[0];
					}
					
					$address->scope = 'client';
					$address->label = '';
					$address->uid = $client->id;
					$address->type = $type;
					$address->street = $street;
					$address->complement = $complement;
					$address->city = $city;
					$address->zip = $zip;
					$address->country = $country;
					$address->state = Address::ACTIVE;
					
					//récuperation latitude et longitude
					//Enregistrement des coordonées gps dans les méta client si l'adresse est la principale
					if($address->type==Address::MAIN && isset($coordinates['longitude']) && isset($coordinates['latitude'])){
						$coordinates = $address->locationCoordinates();
						$client->meta('longitude', $coordinates['longitude']);
						$client->meta('latitude', $coordinates['latitude']);
						$client->save();
					}
					
					$address->save();
				}
				//on returne false pour indiquer de ne pas remplir l'objet client avec cette info
				return false;
			};
			//Convertion des contacts
			/*
			Exemple de format de contact dans la case du csv
			"jessica ALBA:jalba@alba.com:0681129753:0781129753:PDG:beauty,star
			angelina JOLIE:angie@jolie.com"
			*/
			$transformMapping['contacts'] = function($value,$client){
				//suppression des "" de chaque coté de la valeur si existants
				if(preg_match('/^"(.*)"$/si', $value,$match))
					$value = $match[1];
				
				foreach(explode("\n",$value) as $rawContact){
					$contact = new ContactPerson();
				
			
					$rawContact = explode(':',$rawContact);
					if(isset($rawContact[1])) $type = $rawContact[1];
					$nameFirstName = explode(' ',$rawContact[0]);	
					$contact->firstname = $nameFirstName[0];
					if(isset($nameFirstName[1])) $contact->name = $nameFirstName[1];
					if(!empty($rawContact[1])) $contact->mail = $rawContact[1];
					if(!empty($rawContact[2])) $contact->phone = $rawContact[2];
					if(!empty($rawContact[3])) $contact->mobile = $rawContact[3];
					if(!empty($rawContact[4])) $contact->job = $rawContact[4];
					if(!empty($rawContact[5])) $contact->tag = $rawContact[5];
					$contact->scope = 'client';
				
					$contact->uid = $client->id;
					$contact->type = ContactPerson::TYPE_EXTERNAL;
					$contact->state = ContactPerson::ACTIVE;
					$contact->save();
				}
				//on returne false pour indiquer de ne pas remplir l'objet client avec cette info
				return false;
			};
			//transformation du libellé parent en libellé enfant
			$transformMapping['parent'] = function($value,$client){
				if(empty($value)) return '';
				$parent = Client::load(array('label'=>$value));
				if(!$parent) return;
				return $parent->id;
			};
			$transformMapping['category'] = function($value,$client) use ($categoriesLabel,$categoriesDictionary){
				if(!isset($categoriesLabel[$value])){
					$dictionary = new Dictionary();
					$dictionary->label = $value;
					$dictionary->state = Dictionary::ACTIVE;
					$dictionary->slug = $categoriesDictionary->slug.'_'.slugify($value);
					$dictionary->parent = $categoriesDictionary->id;
					$dictionary->save();
					$categoriesLabel[$value] = $dictionary->id;
				}
				return $categoriesLabel[$value];
			};
			
			foreach ($lines as $i=>$line) {
				if(empty($line)) continue;
				try{
					$columns = explode(';',$line);
					if(count($columns)==0) throw new Exception("Colonnes vides");
					
					$newClient = new Client();
					$newClient->save(); //on presave pour obtenir un id
					foreach ($columns as $u=>$column) {
						try{
							if(!isset($headersColumnMap[$u])) throw new Exception("La colonne '".$headers[$u]."' ne correspond a rien dans l'erp");
							$key = $headersColumnMap[$u];
							if(isset($transformMapping[$key])){
								$method = $transformMapping[$key];
								$column = $method($column,$newClient);
								//si false, ne pas remplir l'objet client avec cette info (info relationnelle)
								if($column === false) continue;
							}
							
							if($myFirm->has_plugin('fr.core.dynamicform') && isset($isDynamic[$key]) ){
								Plugin::need('dynamicform/DynamicValue');
								$dynamicValue = new DynamicValue();
								$dynamicValue->field = $isDynamic[$key]['id'];
								if(property_exists($isDynamic[$key]['type'],"fromRawDisplay")){
									$method = $isDynamic[$key]['type']->fromRawDisplay;
									$options = array();
									
									
									if($isDynamic[$key]['type']->slug =='dictionary'){
										$parent = Dictionary::bySlug($isDynamic[$key]['meta']->slug);
										$options['slug'] = $parent->id;
									}
									
									$column = $method($column,$options);
								}
								$dynamicValue->value= $column;
								$dynamicValue->firm = $myFirm->id;
								$dynamicValue->scope = 'client'; 
								$dynamicValue->uid = $newClient->id; 
								$dynamicValue->save();
							}else{
								$newClient->$key = $column;
							}
						}catch(Exception $e){
							$response['warnings'][] = 'L'.($i+1).' Col'.($u+1).':'.$e->getMessage();
						}
					
						if(empty($newClient->code)) $newClient->code = CLient::code($newClient);
						if(empty($newClient->slug)) $newClient->slug = slugify($client->label);
					$newClient->save();
					}
				}catch(Exception $e){
					//si un pb sur la ligne on supprime le client qu'on a commencé a enregistrer en base
					if($newClient->id!=0) Client::deleteById($newClient->id);
					$response['warnings'][] = 'L'.($i+1).':'.$e->getMessage();
				}
			}
	});
	
	Action::register('client_import_model',function(&$response){
		global $myUser,$_,$myFirm;
		if(!$myUser->can('client','configure')) throw new Exception("Permission non accordée");
		require_once(__DIR__.SLASH.'Client.class.php');
		$client = new Client();
		$stream = '';
		foreach ($client->fields as $key => $meta) {
			if( in_array($key, array('id','state','slug','meta'))) continue;
			$stream .= $meta['label'].';';
		}
		$stream .= 'Contacts;';
		$stream .= 'Adresses;';
		$stream .= 'Client Parent;';
		
		if($myFirm->has_plugin('fr.core.dynamicform')){
					Plugin::need('dynamicform/DynamicForm');
			foreach (DynamicForm::list('client-sheet-custom') as $key => $meta) {
				$stream .= $meta['label'].';';
			}
		}
		
		$stream .= PHP_EOL;
		File::downloadStream(utf8_decode($stream),'Trame import client.csv', 'application/octet-stream');
		exit();
	});
	
	
?>