can('client','read')) return; $menuItems[] = array( 'sort'=>3, 'url'=>'index.php?module=client', 'label'=>'Clients', 'icon'=> 'fas fa-user-tie', 'color'=> '#3498db' ); } //Cette fonction va generer une page quand on clique sur client dans menu function client_page(){ global $_; if(!isset($_['module']) || $_['module'] !='client') return; $page = !isset($_['page']) ? 'list.client' : $_['page']; $page = str_replace('..','',$page); $file = __DIR__.SLASH.'page.'.$page.'.php'; if(!file_exists($file)) throw new Exception("Page ".$page." inexistante"); require_once($file); } //Fonction executée lors de l'activation du plugin function client_install($id){ if($id != 'fr.core.client') return; global $conf; Entity::install(__DIR__); $conf->put('client_code_mask','{{label[2]}}-{{Y}}{{M}}-{{id}}'); $conf->put('client_enable_map', 1); $conf->put('client_sheet_max_field', 8); $conf->put('client_type', "both"); //Doc sur : https://entreprise.data.gouv.fr/api_doc/sirene $conf->put('client_api_url','https://entreprise.data.gouv.fr/api/sirene/v1/full_text/{{label}}'); $conf->put('client_api_sheet_url','https://entreprise.data.gouv.fr/api/sirene/v3/etablissements/?siren={{siret}}'); $conf->put('client_label_plural','clients'); $conf->put('client_label_singular','client'); $conf->put('client_holding_singular','holding'); $dictionary = new Dictionary(); $dictionary->slug = 'client_category'; $dictionary->label = 'Categorie de client'; $dictionary->parent = 0; $dictionary->state = Dictionary::ACTIVE; $dictionary->save(); $item = new Dictionary(); $item->slug = 'client_category_none'; $item->label = 'Aucune'; $item->parent = $dictionary->id; $item->state = Dictionary::ACTIVE; $item->save(); global $myFirm; if($myFirm->has_plugin('fr.core.export')){ Plugin::need('export/ExportModel'); $model = new ExportModel(); $model->label = 'Export fiche client'; $model->privacy = 'public'; $model->dataset = 'client-sheet'; $model->slug = 'client-sheet'; $model->description= "Modèle d'export PDF utilisé depuis la fiche d'un client"; $model->document_temporary = ''; $model->export_format = 'pdf'; $model->plugin = 'client'; $model->filename = 'Fiche clients.html'; $model->save(); copy(__DIR__.SLASH.'export.html',File::dir().$model->filename); File::move(File::dir().$model->filename, 'export'.SLASH.'documents'.SLASH.'client'.SLASH.$model->id.SLASH.$model->filename); } } //Fonction executée lors de la désactivation du plugin function client_uninstall($id){ if($id != 'fr.core.client') return; Entity::uninstall(__DIR__); } //Déclaration des sections de droits du plugin Right::register("client",array('label'=>"Gestion des droits sur le plugin client")); Right::register("client_history",array('label'=>"Gestion des droits sur historique du plugin client")); //Droits ciblés sur les fiches client Right::register('client_sheet',array( 'label'=>'Gestion des droits sur une fiche client particuliere', 'global'=> false, 'check' => function($action,$right){ global $myUser; if($right->uid <= 0) throw new Exception('Id non spécifié'); if(!$myUser->can('client','edit')) throw new Exception('Seul le un edtieur de client peut définir des droits pour cette fiche'); } )); require_once(__DIR__.SLASH.'action.php'); //Déclaration du menu de réglages function client_menu_setting(&$settingMenu){ global $myUser; if(!$myUser->can('client','configure')) return; $settingMenu[]= array( 'sort' =>1, 'url' => 'setting.php?section=global.client', 'icon' => 'fas fa-angle-right', 'label' => 'Client' ); } //Déclaration des pages de réglages function client_content_setting(){ global $_; if(file_exists(__DIR__.SLASH.'setting.'.$_['section'].'.php')) require_once(__DIR__.SLASH.'setting.'.$_['section'].'.php'); } //Déclaration des settings de base //Types possibles : text,select ( + "values"=> array('1'=>'Val 1'),password,checkbox. Un simple string définit une catégorie. Configuration::setting('client',array( "Général", 'client_code_mask' => array("label"=>"Masque de generation de code", "legend"=>"Macro possibles :
{{id}} : Identifiant unique client
{{label}} : libellé client, possible {{label[x]}} ou x est le nombre de lettres a conserver
{{M}} : Mois sur 2 digits
{{Y}} : Années sur 4 digits
{{y}} : Années sur 2 digits
{{rand(x,y)}} : Chiffre aléatoire entre x et y
", "placeholder"=>"ex: {{label[2]}}-{{Y}}{{M}}-{{id}}","type"=>"text"), 'client_enable_map' => array("label"=>"Afficher la mini-map","type"=>"boolean"), 'client_sheet_max_field' => array("label"=>"Nombre de champs avant résumé","type"=>"number"), 'client_type' => array("label"=>"Type de client","type"=>"list",'values' => array('individual'=>'Particulier','firm'=>'Entreprise','both'=>'Les deux'), 'default'=>'both'), 'client_condition' => array("label"=>"Statut de client","type"=>"list",'values' => array('prospect'=>'Prospect','client'=>'Client','both'=>'Les deux'), 'default'=>'both'), 'client_hide_fields' => array("label"=>"Masquer les uid champs suivants","legend"=>"Uid des champs séparés par saut de ligne (ex: condition siret","type"=>"textarea"), 'Api', 'client_api_search_url' => array("label"=>"Api de recherche client","placeholder"=>"ex: https://entreprise.data.gouv.fr/api/sirene/v1/full_text/{{label}}","type"=>"text"), 'client_api_sheet_url' => array("label"=>"Api de fiche client","placeholder"=>"ex: https://entreprise.data.gouv.fr/api/sirene/v3/etablissements/?siren={{siret}}","type"=>"text"), "Terminologie", 'client_holding_singular' => array("label"=>"Libellé des holdings (singulier)",'placeholder'=>'holding',"type"=>"text"), 'client_label_plural' => array("label"=>"Libellé des clients (pluriel)",'placeholder'=>'clients',"type"=>"text"), 'client_label_singular' => array("label"=>"Libellé des clients (singulier)",'placeholder'=>'client',"type"=>"text"), )); //Affichage du/des widget(s) function client_widget(&$widgets){ global $myUser; require_once(PLUGIN_PATH.'dashboard'.SLASH.'DashboardWidget.class.php'); $modelWidget = new DashboardWidget(); $modelWidget->model = 'client'; $modelWidget->title = 'Client'; $modelWidget->icon = 'fas fa-user-tie'; $modelWidget->background = '#6B5B95'; $modelWidget->load = 'action.php?action=client_widget_load'; $modelWidget->js = [Plugin::url().'/js/widget.js?v=2']; $modelWidget->css = [Plugin::url().'/css/widget.css?v=2']; $modelWidget->description = "Module de gestion des clients et prospects"; $widgets[] = $modelWidget; } function client_tab_menu(&$clientMenu,$client){ $menu = new MenuItem(); $menu->label = 'Accueil'; $menu->url = '#tab=home'; $menu->slug = 'home'; $menu->sort = -1; $clientMenu[] = $menu; } function client_tab_page($slug){ if($slug != 'home') return; require_once(__DIR__.SLASH.'tab.home.php'); } function client_merge($clientBase,$clientToMerge,&$logs){ require_once(__DIR__.SLASH.'Client.class.php'); $logs[] = ' Migration des sous clients attachés '; Client::change(array('parent'=>$clientBase->id),array('parent'=>$clientToMerge->id)); $logs[] = ' Migration des contacts attachés '; ContactPerson::change(array('uid'=>$clientBase->id),array('scope'=>'client','uid'=>$clientToMerge->id)); $logs[] = ' Migration des adresses attachées '; Address::change(array('uid'=>$clientBase->id),array('scope'=>'client','uid'=>$clientToMerge->id)); } //Declaration des évenements et entités workflow Plugin::addHook("workflow_event", function(&$events){ //Evenement entité $events[] = WorkflowEvent::registerEntity(__DIR__.SLASH.'Client.class.php'); //Evenement liste d'entité $events[] = WorkflowEvent::registerList(__DIR__.SLASH.'Client.class.php'); }); global $myFirm; if( $myFirm->has_plugin('fr.core.export')){ require_once(__ROOT__.PLUGIN_PATH.'export'.SLASH.'ExportModel.class.php'); ExportModel::add('client','client-sheet', 'Fiche client', function($parameters){ global $myUser,$myFirm; require_once(__DIR__.SLASH.'Client.class.php'); $client = new Client(); if(isset($parameters['description']) && $parameters['description']!=true && !empty($parameters['id'])) $client = Client::getById($parameters['id']); $data['client'] = ExportModel::fromEntity($client); unset($data['client']['value']['parent']); if(empty($client->comment)) unset($data['client']['value']['comment']['value']); $data['client']['value']['category']['value'] = isset($data['client']['value']['category']) && $data['client']['value']['category']['value']!=0 ? Dictionary::getById($data['client']['value']['category']['value'])->label: 'Aucune'; if(!empty($data['client']['value']['type']['value'])) $data['client']['value']['type']['value'] = Client::types($data['client']['value']['type']['value'])['label']; if(!empty($data['client']['value']['condition']['value'])) $data['client']['value']['condition']['value'] = Client::conditions($data['client']['value']['condition']['value'])['label']; $data['client']['value']['created']['value'] = $data['client']['value']['created']['value']; $data['client']['value']['updated']['value'] = $data['client']['value']['updated']['value']; $data['client']['value']['updater']['value'] = User::byLogin($data['client']['value']['updater']['value'])->fullName(); $data['client']['value']['creator']['value'] = User::byLogin($data['client']['value']['creator']['value'])->fullName(); //export des contacts liés $data['client']['value']['contacts'] = array('label'=>'Liste des contacts', 'type'=>'list','value' => array()); $contacts = $client->id == 0 ? array(new ContactPerson()) :ContactPerson::loadAll(array('scope'=>'client','uid'=>$client->id)); foreach($contacts as $contact){ $contact->meta(); $contactRow = ExportModel::fromEntity($contact)['value']; $contactRow['phone']['value'] = $contact->phone; $contactRow['mobile']['value'] = $contact->mobile; $contactRow['mail']['value'] = $contact->mail; $data['client']['value']['contacts']['value'][] = $contactRow; } //export des adresses liées $data['client']['value']['addresses'] = array('label'=>'Liste des adresses liées', 'type'=>'list','value' => array()); $addresses = $client->id == 0 ? array(new Address()) :$client->addresses(); foreach($addresses as $address){ $data['client']['value']['addresses']['value'][] = ExportModel::fromEntity($address)['value']; } //export des champs custom if($myFirm->has_plugin('fr.core.dynamicform')){ Plugin::need('dynamicform/DynamicForm'); $data['client']['value']['dynamicFields'] = array('label'=>'Champs personnalisés liés', 'type'=>'list','value' => array()); $dynamicFields = DynamicForm::show('client-sheet-custom',array( 'arrayOutput' => true, 'firm' => $myFirm->id, 'uid' => $client->id, 'scope' => 'client' )); $fieldTypes = FieldType::available(); if(is_array($dynamicFields)){ foreach($dynamicFields as $dynamicField){ $value = $dynamicField['value']; if(!isset( $fieldTypes[$dynamicField['type']->slug]) ) continue; $type = $fieldTypes[$dynamicField['type']->slug]; if(!empty($value) && property_exists($type,"onRawDisplay")){ $method = $type->onRawDisplay; $value = $method($value,array('type'=>$type)); } $data['client']['value']['dynamicFields']['value'][] = array( 'value' => array('label' => $dynamicField['label'] , 'value' => $value ) ); } } } $data['client']['value']['logo'] = array( 'label'=>'Logo du client', 'type'=>'image', 'value' => file_get_contents($client->logo(true)) ); if(empty($client->comment)) $data['client']['value']['comment']['value'] = false; $parent = new Client(); $parent->label = 'Aucun'; if(!empty($client->parent)) $parent = Client::getById($client->parent); $data['client']['value']['parent'] = ExportModel::fromEntity($parent); // print_r($data['client']['value']['parent']); // print_r($client->parent); // exit(); return $data; }); } function client_list_action(){ ?> Exporter en excel Copier les e-mails $value) $types[$key] = $value['label']; $conditions = array(); foreach (Client::conditions() as $key => $value) $conditions[$key] = $value['label']; $hideFields = explode("\n",$conf->get('client_hide_fields')); $currentFilters = array( 'id' => '', 'type' => '', 'condition' => '', 'creator' => '', 'label' => '', 'firm' => '', 'created' => '', 'job' => '', 'code' => '', 'siret' => '', 'address.city' => '', 'address.zip' => '', 'mail.value' => '', 'phone.value' => '', 'comment' => '', 'internal_contact' => '' ); foreach($currentFilters as $key=>$filter){ if(in_array($key,$hideFields)) unset($currentFilters[$key]); } $filters = array_merge($filters, $currentFilters); } function client_search_view(&$columns){ global $conf; $hideFields = explode("\n",$conf->get('client_hide_fields')); $mycolumns = array( 'logo' => array( 'head' => '', 'body' => '', ), 'label' => array( 'head' => 'Libellé', 'body' => ' {{{label}}} {{#pseudonym}}({{{pseudonym}}}){{/pseudonym}} {{#holding}}
Sous etablissement de {{{holding.label}}}{{/holding}} {{#affiliate}}
'.$conf->get('client_holding_singular').' de {{affiliate.count}} Etablissement(s){{/affiliate}} {{#job}}
{{{job}}}{{/job}} ', ), 'code' => array( 'head' => 'Code '.($conf->get('client_label_singular')).'', 'body' => '{{code}}', ), 'city' => array( 'head' => 'Ville', 'body' => ' {{address.city}} {{#address.zip}} ({{address.zip}}) {{/address.zip}} ', ), 'type' => array( 'head' => 'Type', 'body' => '{{type.label}}', ), 'category' => array( 'head' => 'Categorie', 'body' => '{{category.label}}', ), 'mail' => array( 'head' => 'E-mail', 'body' => '{{mail}}', ), 'phone' => array( 'head' => 'Téléphone', 'body' => '{{phone}}', ), 'comment' => array( 'head' => 'Commentaire', 'body' => '{{comment}}', ), 'condition' => array( 'head' => 'Statut', 'body' => '{{condition.label}}', ), 'firm' => array( 'head' => 'Etablissement', 'body' => '{{firm.label}}', ) ); foreach($mycolumns as $key=>$column){ if(in_array($key,$hideFields)) continue; $columns[$key]= $column; } } function client_sheet(&$sheet,$client){ global $conf; $contacts = $client->contacts(); $phone = isset($contacts[Contact::MOBILE]) ? $contacts[Contact::MOBILE] : new Contact(); $mail = isset($contacts[Contact::PROFESSIONAL_MAIL]) ? $contacts[Contact::PROFESSIONAL_MAIL] : new Contact(); $sheet = array(); $hideFields = explode("\n",$conf->get('client_hide_fields')); $sheet['label'] = array( 'client-type' => 'firm', 'label' => 'Libellé '.( !empty($client->code) ? '(N°'.$client->code.')':'').'', 'before' => '
', 'after' => '
'.(!empty($conf->get('client_api_search_url')) ? '':'').'
', 'sort' => 10, 'block-class' => 'type-both block-label', 'attributes' => array( 'onchange' => '"client_client_check_duplicate(this)"' ), 'class' => 'text-uppercase', 'value' => html_entity_decode($client->label) ); $sheet['pseudonym'] = array( 'client-type' => 'firm', 'label' => 'Pseudonyme', 'before' => '
', 'after' => '
', 'sort' => 11, 'block-class' => 'type-both block-pseudonym hidden', 'class' => 'text-uppercase', 'value' => html_entity_decode($client->pseudonym) ); if(!in_array('job',$hideFields)) $sheet['job'] = array( 'client-type' => 'firm', 'label' => 'Métier', 'sort' => 20, 'block-class' => 'type-both', 'value' => html_entity_decode($client->job) ); $sheet['firstname'] = array( 'client-type' => 'individual', 'label' => 'Prénom', 'sort' => 8, 'block-class' => 'type-individual', 'attributes' => array( 'onkeyup' => '"client_name_change()"' ), 'value' => html_entity_decode($client->firstname) ); $sheet['name'] = array( 'client-type' => 'individual', 'label' => 'Nom', 'sort' => 9, 'block-class' => 'type-individual', 'class' => 'text-uppercase', 'attributes' => array( 'onkeyup' => '"client_name_change()"' ), 'value' => html_entity_decode($client->name) ); if($conf->get('client_condition') == 'both' || empty($conf->get('client_condition')) ){ $sheet['condition'] = array( 'sort' => 30, 'label' => 'Statut', 'type' => 'choice', 'block-class' => 'condition-block', 'values' => array( 'prospect' => 'Prospect', 'client' => 'Client', ), 'value' => $client->condition == '' ? 'prospect' : $client->condition, ); } if(!in_array('category',$hideFields)) $sheet['category'] = array( 'sort' => 40, 'label' => 'Catégorie', 'block-class' => 'field-block', 'type' => 'dictionary', 'attributes' => array( 'data-slug' => '"client_category"', 'data-value' => '"'.$client->category.'"' ) ); if(!in_array('mail',$hideFields)) $sheet['mail'] = array( 'sort' => 60, 'label' => 'E-Mail', 'before' => '
', 'after' => '
', 'attributes' => array( 'onchange' => '"client_client_check_duplicate(this)"' ), 'value' => html_entity_decode($mail->value) ); if(!in_array('phone',$hideFields)) $sheet['phone'] = array( 'sort' => 70, 'label' => 'Téléphone', 'before' => '
', 'after' => '
', 'attributes' => array( 'onchange' => '"client_client_check_duplicate(this)"' ), 'value' => normalize_phone_number($phone->value) ); if(!in_array('siret',$hideFields)) $sheet['siret'] = array( 'sort' => 80, 'client-type' => 'firm', 'label' => 'N° SIRET', 'block-class' => 'type-firm', 'before' => '
', 'after' => '
', 'attributes' => array( 'onchange' => '"client_client_check_duplicate(this)"' ), 'value' => $client->siret ); if(!in_array('comment',$hideFields)) $sheet['comment'] = array( 'type' => 'textarea', 'label' => 'Commentaire', 'value' => html_entity_decode($client->comment) ); } function client_field_type(&$types){ //User $type = new FieldType(); $type->slug = 'client'; $type->label = 'Client'; $type->sqlType = 'integer'; $type->default_attributes = array( 'class'=>'"form-control"', 'data-type'=>'"client"', 'type'=>'"text"' ); $type->filter = array( 'operators' => array ( '=' =>array('view'=>'client'), '!=' =>array('view'=>'client'), 'null' =>array(), 'not null' =>array() ) ); $type->onInput = $types['text']->onInput; $type->onRawDisplay = function($value,$options = array()){ if(is_null($value) || empty($value)) return; require_once(__DIR__.SLASH.'Client.class.php'); if(empty($value)) return ''; $client = Client::getById($value); return !$client ? '' : $client->label; }; $type->onHtmlDisplay = function($value,$options){ if(is_null($value) || empty($value)) return; require_once(__DIR__.SLASH.'Client.class.php'); $client = Client::getById($value); return ''.$client->label.''; }; $type->icon = 'fab fa-black-tie'; $type->description = 'Autocompletion sur les clients'; $type->default = ''; $types[$type->slug] = $type; } function client_sheet_option(&$options){ global $myUser,$_,$myFirm; if($myUser->can('client','configure')): $options[] = ''; endif; if($myUser->can('export', 'read') && $myFirm->has_plugin('fr.core.export')) : $options[] = '
"client","dataset"=>"client-sheet","id"=>$_['id']))).'\'>
'; endif; if($myUser->can('client','edit') || ($_['id']!=0 && $myUser->can('client_sheet','edit',$_['id']))): $options[] = ''; endif; if($myUser->can('client','delete') || ($_['id']!=0 && $myUser->can('client_sheet','delete',$_['id']))): $options[] = ''; endif; } //Déclation des assets Plugin::addCss("/css/main.css"); Plugin::addJs("/js/main.js"); Plugin::addCss('/css/component.css'); Plugin::addJs('/js/component.js'); //Mapping hook / fonctions Plugin::addHook("install", "client_install"); Plugin::addHook("uninstall", "client_uninstall"); Plugin::addHook("menu_main", "client_menu"); Plugin::addHook("page", "client_page"); Plugin::addHook("menu_setting", "client_menu_setting"); Plugin::addHook("content_setting", "client_content_setting"); Plugin::addHook("widget", "client_widget"); Plugin::addHook("client_merge", "client_merge"); Plugin::addHook("field_types", "client_field_type"); Plugin::addHook("client_sheet_option", "client_sheet_option"); Plugin::addHook("client_list_action","client_list_action"); Plugin::addHook("client_menu", "client_tab_menu"); Plugin::addHook("client_page", "client_tab_page"); Plugin::addHook("client_filter", "client_filter"); Plugin::addHook("client_sheet", "client_sheet"); Plugin::addHook("client_search_view","client_search_view"); ?>