From 12ea6ec05a236c5a723814e715c471894a795dae Mon Sep 17 00:00:00 2001 From: Antoine Le Gonidec Date: Thu, 11 Jul 2024 11:55:29 +0200 Subject: [PATCH] Rely on hooks to link Customers to a Mailbox --- Entities/Customer.php | 94 --- Http/Controllers/CrmController.php | 611 +----------------- Http/Controllers/CustomersController.php | 165 +---- Http/routes.php | 5 - .../MMFRestrictedCustomersServiceProvider.php | 18 +- README.md | 14 +- 6 files changed, 29 insertions(+), 878 deletions(-) diff --git a/Entities/Customer.php b/Entities/Customer.php index fcfcedb..eb6e050 100644 --- a/Entities/Customer.php +++ b/Entities/Customer.php @@ -43,100 +43,6 @@ class Customer extends BaseCustomer { return $this->belongsTo(Mailbox::class); } - /** - * Create customer or get existing and fill empty fields. - * - * @param string $email - * @param array $data [description] - * - * @return [type] [description] - */ - public static function create($email, $data = []) { - $new = false; - - $email = Email::sanitizeEmail($email); - if (!$email) { - return null; - } - $email_obj = Email::where('email', $email)->first(); - if ($email_obj) { - $customer = $email_obj->customer; - - // In case somehow the email has no customer. - if (!$customer) { - // Customer will be saved and connected to the email later. - $customer = new self(); - } - - // Update name if empty. - /*if (empty($customer->first_name) && !empty($data['first_name'])) { - $customer->first_name = $data['first_name']; - if (empty($customer->last_name) && !empty($data['last_name'])) { - $customer->last_name = $data['last_name']; - } - $customer->save(); - }*/ - } else { - $customer = new self(); - $email_obj = new Email(); - $email_obj->email = $email; - - $new = true; - } - // Ensure that the Mailbox relationship is set, if provided. - if ( in_array('mailbox_id', $data) ) - $customer->mailbox_id = $data['mailbox_id']; - - // Set empty fields - if ($customer->setData($data, false) || !$customer->id) { - $customer->save(); - } - - if (empty($email_obj->id) || !$email_obj->customer_id || $email_obj->customer_id != $customer->id) { - // Email may have been set in setData(). - $save_email = true; - if (!empty($data['emails']) && is_array($data['emails'])) { - foreach ($data['emails'] as $data_email) { - if (is_string($data_email) && $data_email == $email) { - $save_email = false; - break; - } - if (is_array($data_email) && !empty($data_email['value']) && $data_email['value'] == $email) { - $save_email = false; - break; - } - } - } - if ($save_email) { - $email_obj->customer()->associate($customer); - $email_obj->save(); - } - } - - // Todo: check phone uniqueness. - - if ($new) { - \Eventy::action('customer.created', $customer); - } - - return $customer; - } - - /** - * Set empty fields. - */ - public function setData($data, $replace_data = true, $save = false) { - // Set the Mailbox this Customer should be linked to. - // TODO: Throw an error if the Mailbox is not set. - if ( isset($data['mailbox']) ) { - // TODO: Check that the current user is allowed to access this Mailbox. - $data['mailbox_id'] = $data['mailbox']; - unset($data['mailbox']); - } - - return parent::setData($data, $replace_data, $save); - } - /** * Only return a Customer instance if it is available to the current User. * diff --git a/Http/Controllers/CrmController.php b/Http/Controllers/CrmController.php index e46c190..817069b 100644 --- a/Http/Controllers/CrmController.php +++ b/Http/Controllers/CrmController.php @@ -6,14 +6,14 @@ namespace Modules\MMFRestrictedCustomers\Http\Controllers; -use App\Conversation; -use Modules\Crm\Entities\CustomerField; -use Modules\Crm\Entities\CustomerCustomerField; use Validator; + use Illuminate\Http\Request; -use Illuminate\Http\Response; -use Illuminate\Routing\Controller; + +use App\Conversation; + use Modules\Crm\Http\Controllers\CrmController as BaseCrmController; + use Modules\MMFRestrictedCustomers\Entities\Customer; use Modules\MMFRestrictedCustomers\Entities\Email; use Modules\MMFRestrictedCustomers\Entities\Mailbox; @@ -34,7 +34,7 @@ class CrmController extends BaseCrmController { } public function createCustomerSave(Request $request) { - // TODO: Find a way to call parent::createCustomerSave while only overriding the Customer class, + // TODO: Find a way to call parent::createCustomerSave while only overriding the Email class, // instead of overriding the whole method here. $validator = Validator::make($request->all(), [ 'first_name' => 'nullable|string|max:255|required_without:emails.0', @@ -152,603 +152,4 @@ class CrmController extends BaseCrmController { return \Response::json($response); } - - /** - * Ajax controller. - */ - public function ajaxAdmin(Request $request) { - // TODO: Find a way to call parent::ajaxAdmin while only overriding the Customer class, - // instead of overriding the whole method here. - $response = [ - 'status' => 'error', - 'msg' => '', // this is error message - ]; - - switch ($request->action) { - - // Create/update saved reply - case 'customer_field_create': - case 'customer_field_update': - - // if (!$user->isAdmin()) { - // $response['msg'] = __('Not enough permissions'); - // } - - if (!$response['msg']) { - $name = $request->name; - - if (!$name) { - $response['msg'] = __('Name is required'); - } - } - - // Check unique name. - if (!$response['msg']) { - $name_exists = CustomerField::where('name', $name); - - if ($request->action == 'customer_field_update') { - $name_exists->where('id', '!=', $request->customer_field_id); - } - $name_exists = $name_exists->first(); - - if ($name_exists) { - $response['msg'] = __('A Customer Field with this name already exists.'); - } - } - - if (!$response['msg']) { - - if ($request->action == 'customer_field_update') { - $customer_field = CustomerField::find($request->customer_field_id); - if (!$customer_field) { - $response['msg'] = __('Customer Field not found'); - } - } else { - $customer_field = new CustomerField(); - $customer_field->setSortOrderLast(); - } - - if (!$response['msg']) { - //$customer_field->mailbox_id = $mailbox->id; - $customer_field->name = $name; - if ($request->action != 'customer_field_update') { - $customer_field->type = $request->type; - } - if ($customer_field->type == CustomerField::TYPE_DROPDOWN) { - - if ($request->action == 'customer_field_create') { - $options = []; - $options_tmp = preg_split('/\r\n|[\r\n]/', $request->options ?? ''); - // Remove empty - $option_index = 1; - foreach ($options_tmp as $i => $value) { - $value = trim($value); - if ($value) { - $options[$option_index] = $value; - $option_index++; - } - } - if (empty($options)) { - $options = [1 => '']; - } - } else { - $options = $request->options; - } - - $customer_field->options = $options; - - // Remove values. - if ($customer_field->id) { - CustomerCustomerField::where('customer_field_id', $customer_field->id) - ->whereNotIn('value', array_keys($request->options)) - ->delete(); - } - } elseif (isset($request->options)) { - $customer_field->options = $request->options; - } else { - $customer_field->options = ''; - } - $customer_field->required = $request->filled('required'); - $customer_field->display = $request->filled('display'); - $customer_field->conv_list = $request->filled('conv_list'); - $customer_field->customer_can_view = $request->filled('customer_can_view'); - $customer_field->customer_can_edit = $request->filled('customer_can_edit'); - $customer_field->save(); - - $response['id'] = $customer_field->id; - $response['name'] = $customer_field->name; - $response['required'] = (int)$customer_field->required; - $response['display'] = (int)$customer_field->display; - $response['conv_list'] = (int)$customer_field->conv_list; - $response['customer_can_view'] = (int)$customer_field->customer_can_view; - $response['customer_can_edit'] = (int)$customer_field->customer_can_edit; - $response['status'] = 'success'; - - if ($request->action == 'customer_field_update') { - $response['msg_success'] = __('Customer field updated'); - } else { - // Flash - \Session::flash('flash_success_floating', __('Customer field created')); - } - } - } - break; - - // Delete - case 'customer_field_delete': - - // if (!$user->isAdmin()) { - // $response['msg'] = __('Not enough permissions'); - // } - - if (!$response['msg']) { - $customer_field = CustomerField::find($request->customer_field_id); - - if (!$customer_field) { - $response['msg'] = __('Customer Field not found'); - } - } - - if (!$response['msg']) { - \Eventy::action('customer_field.before_delete', $customer_field); - $customer_field->delete(); - - // Delete links to customers; - CustomerCustomerField::where('customer_field_id', $request->customer_field_id)->delete(); - - $response['status'] = 'success'; - $response['msg_success'] = __('Customer Field deleted'); - - \Eventy::action('customer_field.after_delete', $request->customer_field_id); - } - break; - - // Update saved reply - case 'customer_field_update_sort_order': - - // if (!$user->isAdmin()) { - // $response['msg'] = __('Not enough permissions'); - // } - - if (!$response['msg']) { - - $customer_fields = CustomerField::whereIn('id', $request->customer_fields)->select('id', 'sort_order')->get(); - - if (count($customer_fields)) { - foreach ($request->customer_fields as $i => $request_customer_field_id) { - foreach ($customer_fields as $customer_field) { - if ($customer_field->id != $request_customer_field_id) { - continue; - } - $customer_field->sort_order = $i+1; - $customer_field->save(); - } - } - $response['status'] = 'success'; - } - } - break; - - // Parse CSV before importing. - case 'import_parse': - if (!$request->hasFile('file') || !$request->file('file')->isValid() || !$request->file) { - $response['msg'] = __('Error occurred uploading file'); - } - - if (!$response['msg']) { - try { - $csv = $this->readCsv($request->file('file')->getPathName(), $request->separator, $request->enclosure, $request->encoding); - } catch (\Exception $e) { - $response['msg'] = __('Error occurred').': '.$e->getMessage(); - } - - if (!$response['msg'] && $csv && is_array($csv)) { - $response['cols'] = []; - foreach ($csv as $r => $row) { - if ($request->skip_header && $r == 0) { - continue; - } - foreach ($row as $c => $value) { - if (!empty($response['cols'][$c]) - && $response['cols'][$c] != __('Column :number', ['number' => $c+1]) - ) { - continue; - } - if ($request->skip_header) { - if ($r == 0) { - if (isset($csv[1][$c]) && $csv[1][$c] != '') { - $response['cols'][$c] = $value . ' ('.$csv[1][$c].')'; - } elseif ($value != '') { - $response['cols'][$c] = $value; - } else { - $response['cols'][$c] = __('Column :number', ['number' => $c+1]); - } - } elseif (isset($csv[0][$c]) && $value) { - $response['cols'][$c] = $csv[0][$c] . ' ('.$value.')'; - } elseif ($value != '') { - $response['cols'][$c] = $value; - } else { - $response['cols'][$c] = __('Column :number', ['number' => $c+1]); - } - } elseif ($value != '') { - $response['cols'][$c] = $value; - } else { - $response['cols'][$c] = __('Column :number', ['number' => $c+1]); - } - } - } - } - if (!$response['msg']) { - if (!empty($response['cols'])) { - $response['status'] = 'success'; - } else { - $response['msg'] = __('Could not parse CSV file.'); - } - } - } - break; - - // Import. - case 'import_import': - if (!$request->hasFile('file') || !$request->file('file')->isValid() || !$request->file) { - $response['msg'] = __('Error occurred uploading file'); - } - - if (!$response['msg']) { - try { - $csv = $this->readCsv($request->file('file')->getPathName(), $request->separator, $request->enclosure, $request->encoding); - $imported = 0; - $errors = []; - $email_conflicts = []; - if ($csv && is_array($csv)) { - foreach ($csv as $r => $row) { - if ($request->skip_header && $r == 0) { - continue; - } - $data = $this->importParseRow($row, json_decode($request->mapping, true)); - - try { - if (!empty($data['emails'])) { - // Try to find customers with emails. - // If found one - update. - // If found more than one customer - it's a conflict. - $customers_count = 0; - $customer_email = ''; - $customer_customer = null; - foreach ($data['emails'] as $email) { - $customer = Customer::getByEmail($email); - if ($customer) { - $customer_email = $email; - $customer_customer = $customer; - $customers_count++; - } - } - if ($customers_count > 1) { - $email_conflicts[] = (int)($r+1); - } elseif ($customers_count == 1 && $customer_customer) { - // Update existing customer. - $imported++; - $customer_customer->setData($this->prepareEmails($data), true, true); - } else { - $customer_customer = Customer::create($data['emails'][0], $this->prepareEmails($data)); - if ($customer_customer) { - $imported++; - } - } - } else { - // Create without email. - if (!empty($data['first_name'])) { - $customer_customer = Customer::createWithoutEmail($this->prepareEmails($data)); - if ($customer_customer) { - $imported++; - } - } else { - $errors[] = '#'.($r+1); - } - } - // Set photo. - if (!empty($data['photo_url']) && $customer_customer) { - try { - $customer_customer->setPhotoFromRemoteFile($data['photo_url']); - $customer_customer->save(); - } catch (\Exception $e) { - - } - } - } catch (\Exception $e) { - $errors[] = '#'.($r+1); - } - } - } - // if ($imported) { - // $flash_type = 'flash_success_floating'; - // } else { - // $flash_type = 'flash_error_floating'; - // } - - $response['result_html'] = __('Imported or updated: :imported customers.', ['imported' => $imported]); - if (count($errors)) { - $response['result_html'] .= '
'.__('Could not import the following CSV rows as they contain not enough data: :errors.', ['errors' => implode(', ', $errors)]); - } - if (count($email_conflicts)) { - $response['result_html'] .= '
'.__('Could not import the following CSV rows as emails specified in those rows belong to different existing customers: :email_conflicts.', ['email_conflicts' => implode(', ', $email_conflicts)]); - } - // \Session::flash($flash_type, __(':imported customer(s) imported, :errors error(s) occurred', ['imported' => $imported, 'errors' => $errors])); - // \Session::reflash(); - } catch (\Exception $e) { - $response['msg'] = __('Error occurred').': '.$e->getMessage(); - } - - if (!$response['msg'] && $csv) { - $response['status'] = 'success'; - } - } - break; - - default: - $response['msg'] = 'Unknown action'; - break; - } - - if ($response['status'] == 'error' && empty($response['msg'])) { - $response['msg'] = 'Unknown error occured'; - } - - return \Response::json($response); - } - - public function importParseRow($row, $mapping) { - // TODO: Find a way to call parent::importParseRow while only overriding the Customer class, - // instead of overriding the whole method here. - $data = []; - foreach ($mapping as $field_name => $field_row_i) { - if (!isset($row[$field_row_i])) { - continue; - } - $data[$field_name] = $row[$field_row_i]; - $data_value = $data[$field_name]; - - switch ($field_name) { - case 'emails': - case 'phones': - case 'websites': - case 'social_profiles': - $data[$field_name] = explode(',', $data[$field_name]); - if (is_array($data[$field_name]) - && count($data[$field_name]) == 1 - && isset($data[$field_name][0]) - && empty($data[$field_name][0]) - ) { - unset($data[$field_name][0]); - } - break; - } - - if ($field_name == 'social_profiles' && is_array($data[$field_name])) { - // Social profiles. - foreach ($data[$field_name] as $i => $value) { - preg_match("/^([^:]+):(.*)/", $value, $m); - if (!empty($m[1]) && !empty($m[2])) { - $social_name = $m[1]; - if (array_search($social_name, Customer::$social_type_names)) { - $data[$field_name][$i] = [ - 'value' => $m[2], - 'type' => array_search($social_name, Customer::$social_type_names), - ]; - } - } - } - } elseif ($field_name == 'country') { - // Country. - if (array_search($data[$field_name], Customer::$countries)) { - $data[$field_name] = array_search($data[$field_name], Customer::$countries); - } - $data[$field_name] = strtoupper(mb_substr($data[$field_name], 0, 2)); - } elseif (\Str::startsWith($field_name, CustomerField::NAME_PREFIX)) { - // Custom field. - $value = $data[$field_name]; - - $field_id = preg_replace("/^".CustomerField::NAME_PREFIX."/", '', $field_name); - $field = CustomerField::find($field_id); - - if ($field) { - $data[$field_name] = CustomerField::sanitizeValue($value, $field); - } - } - } - - return $data; - } - - public function getCustomersWithoutConvQuery() { - // TODO: Find a way to call parent::getCustomersWithoutConvQuery while only overriding the Customer class, - // instead of overriding the whole method here. - return Customer::select('customers.*') - ->leftJoin('conversations', function ($join) { - $join->on('conversations.customer_id', '=', 'customers.id'); - }) - ->leftJoin('threads', function ($join) { - $join->on('threads.created_by_customer_id', '=', 'customers.id'); - }) - ->where('conversations.customer_id', null) - ->where('threads.created_by_customer_id', null); - } - - /** - * Export. - */ - public function export(Request $request) { - // TODO: Find a way to call parent::export while only overriding the Customer class, - // instead of overriding the whole method here. - $fields = $request->fields ?? []; - $export_emails = false; - - $exportable_fields = \Crm::getExportableFields(); - - $fields_regular = []; - - foreach ($fields as $i => $field_name) { - if (array_key_exists($field_name, $exportable_fields)) { - if (!preg_match("/^".CustomerField::NAME_PREFIX."/", $field_name)) { - $fields_regular[] = $field_name; - } - } else { - unset($fields[$i]); - } - if ($field_name == 'emails') { - $export_emails = true; - if (\Helper::isMySql()) { - $fields_regular[count($fields_regular)-1] = \DB::raw("GROUP_CONCAT(emails.email SEPARATOR ', ') as emails"); - } else { - $fields_regular[count($fields_regular)-1] = \DB::raw("string_agg(emails.email, ', ') as emails"); - } - } - } - - $results = []; - - if (count($fields_regular)) { - - if (!in_array('customers.id', $fields_regular)) { - $fields_regular[] = 'customers.id'; - } - - if ($export_emails) { - $query = Customer::select($fields_regular) - ->leftJoin('emails', function ($join) { - $join->on('emails.customer_id', '=', 'customers.id'); - }) - ->groupby('customers.id'); - } else { - $query = Customer::select($fields_regular); - } - - $results = $query->get()->toArray(); - } - - // Add customer fields. - $fields_cf = []; - foreach ($fields as $field_name) { - if (preg_match("/^".CustomerField::NAME_PREFIX."/", $field_name)) { - $fields_cf[] = str_replace(CustomerField::NAME_PREFIX, '', $field_name); - } - } - if (count($fields_cf)) { - $customer_fields = CustomerCustomerField::whereIn('customer_field_id', $fields_cf) - ->get(); - - foreach ($results as $i => $row) { - foreach ($fields_cf as $cf_id) { - $results[$i][CustomerField::NAME_PREFIX.$cf_id] = ''; - foreach ($customer_fields as $cf_row) { - if ($cf_row->customer_id == $row['id'] && $cf_row->customer_field_id == $cf_id) { - $results[$i][CustomerField::NAME_PREFIX.$cf_id] = $cf_row->value; - break; - } - } - } - } - } - - foreach ($results as $i => $row) { - if (!in_array('customers.id', $fields) && isset($row['id'])) { - unset($results[$i]['id']); - } - if (!empty($row['photo_url'])) { - $results[$i]['photo_url'] = Customer::getPhotoUrlByFileName($row['photo_url']); - } - if (!empty($row['phones'])) { - $phones = json_decode($row['phones'], true); - $row['phones'] = ''; - $phones_list = []; - if (is_array($phones) && !empty($phones)) { - foreach ($phones as $phone) { - $phones_list[] = $phone['value']; - } - $results[$i]['phones'] = implode(', ', $phones_list); - } - } - if (!empty($row['websites'])) { - $websites = json_decode($row['websites'], true); - $results[$i]['websites'] = ''; - - if (is_array($websites) && !empty($websites)) { - $results[$i]['websites'] = implode(', ', $websites); - } - } - if (!empty($row['social_profiles'])) { - $social_profiles = json_decode($row['social_profiles'], true); - $row['social_profiles'] = ''; - $social_profiles_list = []; - if (is_array($social_profiles) && !empty($social_profiles)) { - foreach ($social_profiles as $social_profile) { - $sp_formatted = Customer::formatSocialProfile($social_profile); - $social_profiles_list[] = $sp_formatted['type_name'].':'.$social_profile['value']; - } - $results[$i]['social_profiles'] = implode(', ', $social_profiles_list); - } - } - } - - $filename = 'customers_'.date('Y-m-d').'.csv'; - - $encoding = $request->encoding; - $separator = $request->separator; - - if ($separator == 'TAB') { - $separator = "\t"; - } - - // Rename some fields. - foreach ($fields as $i => $field_name) { - // if (strstr($field_name, 'as emails')) { - // $field_name = 'emails'; - // } - - if (!empty($exportable_fields[$field_name])) { - $fields[$i] = $exportable_fields[$field_name]; - } - } - - $schema_insert = '"'.implode('"'.$separator.'"', $fields).'"'; - $out = $schema_insert."\n"; - - foreach($results as $row) { - $schema_insert = ''; - - foreach ($row as $row_value) { - $value_prepared = str_replace('"', '""', $row_value ?? ''); - $value_prepared = str_replace("\t", '', $value_prepared); - $schema_insert .= '"'.$value_prepared.'"'.$separator; - } - - $out .= $schema_insert."\n"; - } - - if (ob_get_contents()) { - ob_clean(); - } - - if ($encoding != 'UTF-8') { - try { - $out = iconv("UTF-8", $encoding, $out); - } catch (\Exception $e) { - // https://github.com/freescout-helpdesk/freescout/issues/2825 - $out = iconv("UTF-8", $encoding.'//IGNORE', $out); - } - if ($encoding == 'UCS-2LE') { - $out = "\xFF\xFE".$out; - } - } else { - // BOM: https://github.com/freescout-helpdesk/freescout/issues/3993 - $out = "\xEF\xBB\xBF".$out; - } - - header("Cache-Control: must-revalidate, no-cache, no-store, private"); - header("Content-Length: " . strlen($out)); - header("Content-type: application/csv; charset=UCS-2LE"); - header("Content-Disposition: attachment; filename=$filename"); - echo $out; - exit; - } } diff --git a/Http/Controllers/CustomersController.php b/Http/Controllers/CustomersController.php index b02bee7..cdf852b 100644 --- a/Http/Controllers/CustomersController.php +++ b/Http/Controllers/CustomersController.php @@ -6,11 +6,13 @@ namespace Modules\MMFRestrictedCustomers\Http\Controllers; -use App\Conversation; -use App\Email; -use Illuminate\Http\Request; use Validator; + +use Illuminate\Http\Request; + +use App\Conversation; use App\Http\Controllers\CustomersController as BaseCustomersController; + use Modules\MMFRestrictedCustomers\Entities\Customer; class CustomersController extends BaseCustomersController { @@ -18,8 +20,6 @@ class CustomersController extends BaseCustomersController { * Edit customer. */ public function update($id) { - // TODO: Find a way to call parent::update while only overriding the Customer class, - // instead of overriding the whole method here. $customer = Customer::findOrFail($id); // Get the list of Mailboxes the current User has access to. @@ -43,161 +43,6 @@ class CustomersController extends BaseCustomersController { ]); } - /** - * Save customer. - * - * @param \Illuminate\Http\Request $request - * - * @return \Illuminate\Http\Response - */ - public function updateSave($id, Request $request) { - // TODO: Find a way to call parent::updateSave while only overriding the Customer class, - // instead of overriding the whole method here. - function mb_ucfirst($string) - { - return mb_strtoupper(mb_substr($string, 0, 1)).mb_strtolower(mb_substr($string, 1)); - } - - $customer = Customer::findOrFail($id); - $flash_message = ''; - - // First name or email must be specified - $validator = Validator::make($request->all(), [ - 'first_name' => 'nullable|string|max:255|required_without:emails.0', - 'last_name' => 'nullable|string|max:255', - 'city' => 'nullable|string|max:255', - 'state' => 'nullable|string|max:255', - 'zip' => 'nullable|string|max:12', - 'country' => 'nullable|string|max:2', - //'emails' => 'array|required_without:first_name', - //'emails.1' => 'nullable|email|required_without:first_name', - 'emails.*' => 'nullable|email|distinct|required_without:first_name', - 'photo_url' => 'nullable|image|mimes:jpeg,png,jpg,gif', - ]); - $validator->setAttributeNames([ - 'photo_url' => __('Photo'), - 'emails.*' => __('Email'), - ]); - - // Photo - $validator->after(function ($validator) use ($customer, $request) { - if ($request->hasFile('photo_url')) { - $path_url = $customer->savePhoto($request->file('photo_url')->getRealPath(), $request->file('photo_url')->getMimeType()); - - if ($path_url) { - $customer->photo_url = $path_url; - } else { - $validator->errors()->add('photo_url', __('Error occurred processing the image. Make sure that PHP GD extension is enabled.')); - } - } - }); - - if ($validator->fails()) { - return redirect()->route('customers.update', ['id' => $id]) - ->withErrors($validator) - ->withInput(); - } - - $new_emails = []; - $new_emails_change_customer = []; - $removed_emails = []; - - // Detect new emails added - $customer_emails = $customer->emails()->pluck('email')->toArray(); - foreach ($request->emails as $email) { - if (!in_array($email, $customer_emails)) { - $new_emails[] = $email; - } - } - - // If new email belongs to another customer, let user know about it in the flash message - foreach ($new_emails as $new_email) { - $email = Email::where('email', $new_email)->first(); - if ($email && $email->customer) { - // If customer whose email is removed does not have first name and other emails - // we have to create first name for this customer - if (!$email->customer->first_name && count($email->customer->emails) == 1) { - if ($request->first_name) { - $email->customer->first_name = $request->first_name; - } elseif ($customer->first_name) { - $email->customer->first_name = $customer->first_name; - } else { - $email->customer->first_name = mb_ucfirst($email->getNameFromEmail()); - } - $email->customer->save(); - } - - $flash_message .= __('Email :tag_email_begin:email:tag_email_end has been moved from another customer: :a_begin:customer:a_end.', [ - 'email' => $email->email, - 'tag_email_begin' => '', - 'tag_email_end' => '', - 'customer' => $email->customer->getFullName(), - 'a_begin' => '', - 'a_end' => '', - ]).' '; - - $new_emails_change_customer[] = $email; - } - } - - // Detect removed emails - foreach ($customer_emails as $email) { - if (!in_array($email, $request->emails)) { - $removed_emails[] = $email; - } - } - - $request_data = $request->all(); - - if (isset($request_data['photo_url'])) { - unset($request_data['photo_url']); - } - - $customer->setData($request_data); - // Websites - // if (!empty($request->websites)) { - // $customer->setWebsites($request->websites); - // } - $customer->save(); - - $customer->syncEmails($request->emails); - - // Update customer_id in all conversations added to the current customer. - foreach ($new_emails_change_customer as $new_email) { - if ($new_email->customer_id) { - $conversations_to_change_customer = Conversation::where('customer_id', $new_email->customer_id)->get(); - } else { - // This does not work for phone conversations. - $conversations_to_change_customer = Conversation::where('customer_email', $new_email->email)->get(); - } - foreach ($conversations_to_change_customer as $conversation) { - // We have to pass user to create line item and let others know that customer has changed. - // Conversation may be even in other mailbox where user does not have an access. - $conversation->changeCustomer($new_email->email, $customer, auth()->user()); - } - } - - // Update customer in conversations for emails removed from current customer. - foreach ($removed_emails as $removed_email) { - $email = Email::where('email', $removed_email)->first(); - if ($email) { - $conversations = Conversation::where('customer_email', $email->email)->get(); - foreach ($conversations as $conversation) { - $conversation->changeCustomer($email->email, $email->customer, auth()->user()); - } - } - } - - \Eventy::action('customer.updated', $customer); - - $flash_message = __('Customer saved successfully.').' '.$flash_message; - \Session::flash('flash_success_unescaped', $flash_message); - - \Session::flash('customer.updated', 1); - - return redirect()->route('customers.update', ['id' => $id]); - } - /** * View customer conversations. * diff --git a/Http/routes.php b/Http/routes.php index 17fd007..894c028 100644 --- a/Http/routes.php +++ b/Http/routes.php @@ -9,7 +9,6 @@ use Illuminate\Support\Facades\Route; Route::group(['middleware' => 'web', 'prefix' => \Helper::getSubdirectory(), 'namespace' => 'Modules\MMFRestrictedCustomers\Http\Controllers'], function() { // Customers Route::get('/customers/{id}/edit', CustomersController::class . '@update')->name('customers.update'); - Route::post('/customers/{id}/edit', CustomersController::class . '@updateSave'); Route::get('/customers/{id}/', CustomersController::class . '@conversations')->name('customers.conversations'); Route::get('/customers/ajax-search', ['uses' => CustomersController::class . '@ajaxSearch', 'laroute' => true])->name('customers.ajax_search'); Route::post('/customers/ajax', ['uses' => CustomersController::class . '@ajax', 'laroute' => true])->name('customers.ajax'); @@ -23,8 +22,4 @@ Route::group(['middleware' => 'web', 'prefix' => \Helper::getSubdirectory(), 'na Route::get('/customers/fields/ajax-search', ['uses' => CrmController::class . '@ajaxSearch', 'laroute' => true])->name('crm.ajax_search'); Route::post('/crm/ajax', ['uses' => CrmController::class . '@ajax', 'laroute' => true])->name('crm.ajax'); }); - Route::group([ 'roles' => ['admin'] ], function() { - Route::post('/customers/export', ['uses' => CrmController::class . '@export'])->name('crm.export'); - Route::post('/crm/ajax-admin', ['uses' => CrmController::class . '@ajaxAdmin', 'laroute' => true])->name('crm.ajax_admin'); - }); }); diff --git a/Providers/MMFRestrictedCustomersServiceProvider.php b/Providers/MMFRestrictedCustomersServiceProvider.php index 510c518..7bd8bdb 100644 --- a/Providers/MMFRestrictedCustomersServiceProvider.php +++ b/Providers/MMFRestrictedCustomersServiceProvider.php @@ -36,7 +36,7 @@ class MMFRestrictedCustomersServiceProvider extends ServiceProvider { * Module hooks. */ public function hooks() { - // When searching for customer, restrict the list to the ones the current user is allowed to see. + // When searching for customers, restrict the list to the ones the current user is allowed to see. Eventy::addFilter('search.customers.apply_filters', function($query_customers) { $user = auth()->user(); // Do not restrict the query if the current user is an admin. @@ -48,6 +48,22 @@ class MMFRestrictedCustomersServiceProvider extends ServiceProvider { } return $query_customers; }); + + // When creating or updating a customer, ensure its mailbox id is set. + Eventy::addAction( + 'customer.set_data', + function($customer, $data, $replace_data) { + if ( isset($data['mailbox']) ) { + // TODO: Check that the current user is allowed to access this Mailbox. + $data['mailbox_id'] = $data['mailbox']; + unset($data['mailbox']); + } + // TODO: Throw an error if the Mailbox is not set. + $customer->mailbox_id = $data['mailbox_id']; + }, + $priority = 20, + $arguments = 3 + ); } /** diff --git a/README.md b/README.md index 0383405..346ed31 100644 --- a/README.md +++ b/README.md @@ -45,7 +45,7 @@ should be replaced with: ```php // Customers Route::get('/customers/{id}/edit', '\Modules\MMFRestrictedCustomers\Http\Controllers\CustomersController@update')->name('customers.update'); -Route::post('/customers/{id}/edit', '\Modules\MMFRestrictedCustomers\Http\Controllers\CustomersController@updateSave'); +Route::post('/customers/{id}/edit', 'CustomersController@updateSave'); Route::get('/customers/{id}/', '\Modules\MMFRestrictedCustomers\Http\Controllers\CustomersController@conversations')->name('customers.conversations'); Route::get('/customers/ajax-search', ['uses' => '\Modules\MMFRestrictedCustomers\Http\Controllers\CustomersController@ajaxSearch', 'laroute' => true])->name('customers.ajax_search'); Route::post('/customers/ajax', ['uses' => '\Modules\MMFRestrictedCustomers\Http\Controllers\CustomersController@ajax', 'laroute' => true])->name('customers.ajax'); @@ -64,12 +64,6 @@ Route::group(['middleware' => ['web', 'auth', 'roles'], 'roles' => ['user', 'adm Route::get('/customers/fields/ajax-search', ['uses' => 'CrmController@ajaxSearch', 'laroute' => true])->name('crm.ajax_search'); Route::post('/crm/ajax', ['uses' => 'CrmController@ajax', 'laroute' => true])->name('crm.ajax'); }); - -Route::group(['middleware' => ['web', 'auth', 'roles'], 'roles' => ['admin'], 'prefix' => \Helper::getSubdirectory(), 'namespace' => 'Modules\Crm\Http\Controllers'], function() -{ - Route::post('/customers/export', ['uses' => 'CrmController@export'])->name('crm.export'); - Route::post('/crm/ajax-admin', ['uses' => 'CrmController@ajaxAdmin', 'laroute' => true])->name('crm.ajax_admin'); -}); ``` should be replaced with: @@ -83,12 +77,6 @@ Route::group(['middleware' => ['web', 'auth', 'roles'], 'roles' => ['user', 'adm Route::get('/customers/fields/ajax-search', ['uses' => '\Modules\MMFRestrictedCustomers\Http\Controllers\CrmController@ajaxSearch', 'laroute' => true])->name('crm.ajax_search'); Route::post('/crm/ajax', ['uses' => '\Modules\MMFRestrictedCustomers\Http\Controllers\CrmController@ajax', 'laroute' => true])->name('crm.ajax'); }); - -Route::group(['middleware' => ['web', 'auth', 'roles'], 'roles' => ['admin'], 'prefix' => \Helper::getSubdirectory(), 'namespace' => '\Modules\MMFRestrictedCustomers\Http\Controllers'], function() -{ - Route::post('/customers/export', ['uses' => '\Modules\MMFRestrictedCustomers\Http\Controllers\CrmController@export'])->name('crm.export'); - Route::post('/crm/ajax-admin', ['uses' => '\Modules\MMFRestrictedCustomers\Http\Controllers\CrmController@ajaxAdmin', 'laroute' => true])->name('crm.ajax_admin'); -}); ``` #### Modules/Crm/Providers/CrmServiceProvider.php