Skip to content

Commit 5ea7d04

Browse files
Merge customers - closes #2188
1 parent ad18369 commit 5ea7d04

File tree

7 files changed

+182
-3
lines changed

7 files changed

+182
-3
lines changed

app/Customer.php

+79-1
Original file line numberDiff line numberDiff line change
@@ -454,7 +454,7 @@ class Customer extends Model
454454
*
455455
* @var [type]
456456
*/
457-
protected $fillable = ['first_name', 'last_name', 'company', 'job_title', 'address', 'city', 'state', 'zip', 'country', 'photo_url', 'age', 'gender', 'notes', 'channel', 'channel_id', 'social_profiles'];
457+
protected $fillable = ['first_name', 'last_name', 'company', 'job_title', 'address', 'city', 'state', 'zip', 'country', 'photo_url', 'notes', 'channel', 'channel_id', 'social_profiles'];
458458

459459
/**
460460
* Fields stored as JSON.
@@ -1287,6 +1287,84 @@ public static function getPhotoUrlByFileName($file_name)
12871287
return Storage::url(self::PHOTO_DIRECTORY.DIRECTORY_SEPARATOR.$file_name);
12881288
}
12891289

1290+
/**
1291+
* Merge customerю
1292+
*/
1293+
public function mergeWith(Customer $customer2)
1294+
{
1295+
$user = auth()->user();
1296+
1297+
$customer2->conversations()->update(['customer_id' => $this->id]);
1298+
1299+
// do {
1300+
// $conversations = $customer2->conversations()->limit(1000);
1301+
// foreach ($conversations as $conversation) {
1302+
// $conversation->changeCustomer($customer_email, $this, $user);
1303+
// }
1304+
// } while (count($conversations) > 0);
1305+
1306+
// Move emails.
1307+
$customer2->emails()->update(['customer_id' => $this->id]);
1308+
1309+
// Merge attributes
1310+
// if (in_array('phone', $keepAttributes) && !$this->phone) {
1311+
// $this->phone = $customerToMerge->phone;
1312+
// }
1313+
foreach ($this->fillable as $attr_name) {
1314+
// Skip some attribues.
1315+
if (in_array($attr_name, ['channel', 'channel_id'])) {
1316+
continue;
1317+
}
1318+
if (!$this->$attr_name) {
1319+
$this->$attr_name = $customer2->$attr_name;
1320+
}
1321+
}
1322+
1323+
// Merge Phones.
1324+
$phones = self::mergeTypeValueLists($this->getPhones(), $customer2->getPhones());
1325+
if (count($phones) != count($this->getPhones())) {
1326+
$this->setPhones($phones);
1327+
}
1328+
1329+
// Merge websites.
1330+
$websites = array_merge($this->getWebsites(), $customer2->getWebsites());
1331+
$this->setWebsites(array_unique($websites));
1332+
1333+
// Merge social profiles.
1334+
$social = self::mergeTypeValueLists($this->getSocialProfiles(), $customer2->getSocialProfiles());
1335+
if (count($social) != count($this->getSocialProfiles())) {
1336+
$this->setSocialProfiles($social);
1337+
}
1338+
1339+
$this->save();
1340+
1341+
\Eventy::action('customer.merged', $this, $customer2, $user);
1342+
1343+
$customer2->delete();
1344+
}
1345+
1346+
public static function mergeTypeValueLists($list1, $list2)
1347+
{
1348+
foreach ($list2 as $data2) {
1349+
if (empty($data2['type']) || empty($data2['value'])) {
1350+
continue;
1351+
}
1352+
$exists = false;
1353+
foreach ($list1 as $data) {
1354+
if (!empty($data['type']) && !empty($data['value'])
1355+
&& $data['type'] == $data2['type'] && $data['value'] == $data2['value']
1356+
) {
1357+
$exists = true;
1358+
break;
1359+
}
1360+
}
1361+
if (!$exists) {
1362+
$list1[] = $data2;
1363+
}
1364+
}
1365+
return $list1;
1366+
}
1367+
12901368
/**
12911369
* Resize and save photo.
12921370
*/

app/Http/Controllers/CustomersController.php

+38-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ public function __construct()
2323
/**
2424
* Edit customer.
2525
*/
26-
public function update($id)
26+
public function update(Request $request, $id)
2727
{
2828
$customer = Customer::findOrFail($id);
2929

@@ -438,4 +438,41 @@ public function ajax(Request $request)
438438

439439
return \Response::json($response);
440440
}
441+
442+
public function merge(Request $request, $id)
443+
{
444+
$customer = Customer::findOrFail($id);
445+
446+
$customers = Customer::where('id', '!=', $id)
447+
->orderBy('first_name')
448+
->orderBy('last_name')
449+
->get();
450+
451+
return view('customers/merge', ['customer' => $customer, 'customers' => $customers]);
452+
}
453+
454+
/**
455+
* Merge handling function.
456+
*/
457+
public function mergeSave(Request $request, $id)
458+
{
459+
$request->validate([
460+
'customer2_id' => 'required|exists:customers,id',
461+
//'keep_attributes' => 'array'
462+
]);
463+
464+
$customer = Customer::findOrFail($id);
465+
$customer2 = Customer::find($request->customer2_id);
466+
467+
// Ensure customers are different
468+
if ($id === $customer2->id) {
469+
return redirect()->back()->with('error', __('Cannot merge the same customer'));
470+
}
471+
472+
$customer->mergeWith($customer2/*, $request->keep_attributes ?? []*/);
473+
474+
\Session::flash('flash_success_floating', __('Customers merged successfully'));
475+
476+
return redirect()->route('customers.update', ['id' => $id]);
477+
}
441478
}

public/js/main.js

+7
Original file line numberDiff line numberDiff line change
@@ -5719,4 +5719,11 @@ function reloadPage()
57195719
function getLocale()
57205720
{
57215721
return $('html:first').attr('lang');
5722+
}
5723+
5724+
function initMergeCustomers()
5725+
{
5726+
$(document).ready(function(){
5727+
$('#merge_customer2_id').select2();
5728+
});
57225729
}
+51
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
@extends('layouts.app')
2+
3+
@section('title_full', $customer->getFullName(true).' - '.__('Customer Profile'))
4+
@section('body_class', 'sidebar-no-height')
5+
6+
@section('body_attrs')@parent data-customer_id="{{ $customer->id }}"@endsection
7+
8+
@section('sidebar')
9+
<div class="profile-preview">
10+
@include('customers/profile_menu')
11+
@include('customers/profile_snippet')
12+
</div>
13+
@endsection
14+
15+
@section('content')
16+
@include('customers/profile_tabs', ['extra_tab' => __('Merge')])
17+
18+
@include('partials/flash_messages')
19+
20+
<div class="container form-container">
21+
<div class="row">
22+
<div class="col-xs-12">
23+
<form action="" method="POST" class="form-horizontal margin-top">
24+
{{ csrf_field() }}
25+
<div class="form-group{{ $errors->has('customer2_id') ? ' has-error' : '' }}">
26+
<label class="col-sm-2 control-label">{{ __('Merge With') }}</label>
27+
<div class="col-sm-6">
28+
<select name="customer2_id" class="form-control input-sized" id="merge_customer2_id" required>
29+
<option value=""></option>
30+
@foreach($customers as $customer)
31+
<option value="{{ $customer->id }}">{{ $customer->getNameAndEmail() }}</option>
32+
@endforeach
33+
</select>
34+
@include('partials/field_error', ['field'=>'customer2_id'])
35+
</div>
36+
</div>
37+
<div class="form-group">
38+
<div class="col-md-6 col-sm-offset-2">
39+
<button type="submit" class="btn btn-primary">{{ __('Merge') }}</button>
40+
</div>
41+
</div>
42+
</form>
43+
</div>
44+
</div>
45+
</div>
46+
@endsection
47+
48+
@section('javascript')
49+
@parent
50+
initMergeCustomers();
51+
@endsection

resources/views/customers/partials/edit_form.blade.php

+2-1
Original file line numberDiff line numberDiff line change
@@ -268,7 +268,8 @@
268268
@else
269269
{{ __('Save Profile') }}
270270
@endif
271-
</button>
271+
</button>
272+
<a href="{{ route('customers.merge', ['id' => $customer->id]) }}" class="btn btn-link">{{ __('Merge') }}</a>
272273
</div>
273274
</div>
274275
</form>
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
<ul class="nav nav-tabs nav-tabs-main margin-top">
22
<li @if (Route::currentRouteName() == 'customers.update')class="active"@endif><a href="{{ route('customers.update', ['id'=>$customer->id]) }}">{{ __('Edit Profile') }}</a></li>
33
<li @if (Route::currentRouteName() == 'customers.conversations')class="active"@endif><a href="{{ route('customers.conversations', ['id'=>$customer->id]) }}">{{ __('Conversations') }}</a></li>
4+
@if (!empty($extra_tab))
5+
<li class="active"><a href="#">{{ $extra_tab }}</a></li>
6+
@endif
47
</ul>

routes/web.php

+2
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,8 @@
9999
Route::get('/customers/{id}/', 'CustomersController@conversations')->name('customers.conversations');
100100
Route::get('/customers/ajax-search', ['uses' => 'CustomersController@ajaxSearch', 'laroute' => true])->name('customers.ajax_search');
101101
Route::post('/customers/ajax', ['uses' => 'CustomersController@ajax', 'laroute' => true])->name('customers.ajax');
102+
Route::get('/customers/{id}/merge', 'CustomersController@merge')->name('customers.merge');
103+
Route::post('/customers/{id}/merge', 'CustomersController@mergeSave');
102104

103105
// Translate
104106
Route::post('/translations/send', ['uses' => 'TranslateController@postSend', 'middleware' => ['auth', 'roles'], 'roles' => ['admin']])->name('translations.send');

0 commit comments

Comments
 (0)