refactor: replace custom CRM with Monica fork
Some checks failed
Build & Push Monica Image to Gitea Registry / build-and-push (push) Failing after 9s
Some checks failed
Build & Push Monica Image to Gitea Registry / build-and-push (push) Failing after 9s
This commit is contained in:
@@ -0,0 +1,88 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Account\Activity\Activity;
|
||||
|
||||
use App\Services\BaseService;
|
||||
use App\Models\Contact\Contact;
|
||||
use App\Models\Account\Activity;
|
||||
|
||||
class AttachContactToActivity extends BaseService
|
||||
{
|
||||
/**
|
||||
* Get the validation rules that apply to the service.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'account_id' => 'required|integer|exists:accounts,id',
|
||||
'activity_id' => 'required|integer|exists:activities,id',
|
||||
'contacts' => 'required|array',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate all datas to execute the service.
|
||||
*
|
||||
* @param array $data
|
||||
* @return bool
|
||||
*/
|
||||
public function validate(array $data): bool
|
||||
{
|
||||
parent::validate($data);
|
||||
|
||||
Activity::where('account_id', $data['account_id'])
|
||||
->findOrFail($data['activity_id']);
|
||||
|
||||
foreach ($data['contacts'] as $contactId) {
|
||||
Contact::where('account_id', $data['account_id'])
|
||||
->findOrFail($contactId);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attach contacts to an activity.
|
||||
*
|
||||
* @param array $data
|
||||
* @return Activity
|
||||
*/
|
||||
public function execute(array $data): Activity
|
||||
{
|
||||
$this->validate($data);
|
||||
|
||||
/** @var Activity */
|
||||
$activity = Activity::find($data['activity_id']);
|
||||
|
||||
$this->attach($data, $activity);
|
||||
|
||||
return $activity;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the association.
|
||||
*
|
||||
* @param array $data
|
||||
* @param Activity $activity
|
||||
* @return void
|
||||
*/
|
||||
private function attach(array $data, Activity $activity)
|
||||
{
|
||||
$attendees = [];
|
||||
foreach ($data['contacts'] as $contact) {
|
||||
$attendees[$contact] = ['account_id' => $activity->account_id];
|
||||
}
|
||||
|
||||
// sync attendees: old contacts will be detached automatically
|
||||
$changes = $activity->contacts()->sync($attendees);
|
||||
|
||||
foreach ($changes as $change) {
|
||||
// detached, attached, and updated attendees
|
||||
foreach ($change as $contactId) {
|
||||
Contact::find($contactId)->calculateActivitiesStatistics();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
127
app/Services/Account/Activity/Activity/CreateActivity.php
Normal file
127
app/Services/Account/Activity/Activity/CreateActivity.php
Normal file
@@ -0,0 +1,127 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Account\Activity\Activity;
|
||||
|
||||
use App\Services\BaseService;
|
||||
use App\Models\Contact\Contact;
|
||||
use App\Models\Account\Activity;
|
||||
use App\Models\Account\ActivityType;
|
||||
use App\Models\Journal\JournalEntry;
|
||||
use App\Models\Instance\Emotion\Emotion;
|
||||
|
||||
class CreateActivity extends BaseService
|
||||
{
|
||||
/**
|
||||
* Get the validation rules that apply to the service.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'account_id' => 'required|integer|exists:accounts,id',
|
||||
'activity_type_id' => 'nullable|integer|exists:activity_types,id',
|
||||
'summary' => 'required|string:255',
|
||||
'description' => 'nullable|string:1000000',
|
||||
'happened_at' => 'required|date|date_format:Y-m-d',
|
||||
'emotions' => 'nullable|array',
|
||||
'contacts' => 'required|array',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate all datas to execute the service.
|
||||
*
|
||||
* @param array $data
|
||||
* @return bool
|
||||
*/
|
||||
public function validate(array $data): bool
|
||||
{
|
||||
parent::validate($data);
|
||||
|
||||
if (count($data['contacts']) > 0) {
|
||||
foreach ($data['contacts'] as $contactId) {
|
||||
Contact::where('account_id', $data['account_id'])
|
||||
->findOrFail($contactId);
|
||||
}
|
||||
}
|
||||
|
||||
if (! empty($data['activity_type_id']) && $data['activity_type_id'] != '') {
|
||||
ActivityType::where('account_id', $data['account_id'])
|
||||
->findOrFail($data['activity_type_id']);
|
||||
}
|
||||
|
||||
if (! empty($data['emotions']) && $data['emotions'] != '') {
|
||||
foreach ($data['emotions'] as $emotionId) {
|
||||
Emotion::findOrFail($emotionId);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an activity.
|
||||
*
|
||||
* @param array $data
|
||||
* @return Activity
|
||||
*/
|
||||
public function execute(array $data): Activity
|
||||
{
|
||||
$this->validate($data);
|
||||
|
||||
$activity = $this->create($data);
|
||||
|
||||
// Log a journal entry
|
||||
JournalEntry::add($activity);
|
||||
|
||||
// Now we associate the activity with each one of the attendees
|
||||
app(AttachContactToActivity::class)->execute([
|
||||
'account_id' => $data['account_id'],
|
||||
'activity_id' => $activity->id,
|
||||
'contacts' => $data['contacts'],
|
||||
]);
|
||||
|
||||
return $activity;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the activity.
|
||||
*
|
||||
* @param array $data
|
||||
* @return Activity
|
||||
*/
|
||||
private function create(array $data): Activity
|
||||
{
|
||||
$activity = Activity::create([
|
||||
'account_id' => $data['account_id'],
|
||||
'activity_type_id' => $this->nullOrValue($data, 'activity_type_id'),
|
||||
'summary' => $data['summary'],
|
||||
'description' => $this->nullOrValue($data, 'description'),
|
||||
'happened_at' => $data['happened_at'],
|
||||
]);
|
||||
|
||||
if (! empty($data['emotions']) && $data['emotions'] != '') {
|
||||
$this->addEmotions($data['emotions'], $activity);
|
||||
}
|
||||
|
||||
return $activity;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add emotions to the activity.
|
||||
*
|
||||
* @param array $emotions
|
||||
* @param Activity $activity
|
||||
* @return void
|
||||
*/
|
||||
private function addEmotions(array $emotions, Activity $activity)
|
||||
{
|
||||
$emotionsSync = [];
|
||||
foreach ($emotions as $emotion) {
|
||||
$emotionsSync[$emotion] = ['account_id' => $activity->account_id];
|
||||
}
|
||||
|
||||
$activity->emotions()->sync($emotionsSync);
|
||||
}
|
||||
}
|
||||
57
app/Services/Account/Activity/Activity/DestroyActivity.php
Normal file
57
app/Services/Account/Activity/Activity/DestroyActivity.php
Normal file
@@ -0,0 +1,57 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Account\Activity\Activity;
|
||||
|
||||
use App\Services\BaseService;
|
||||
use App\Models\Account\Activity;
|
||||
|
||||
class DestroyActivity extends BaseService
|
||||
{
|
||||
/**
|
||||
* Get the validation rules that apply to the service.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'account_id' => 'required|integer|exists:accounts,id',
|
||||
'activity_id' => 'required|integer|exists:activities,id',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate all datas to execute the service.
|
||||
*
|
||||
* @param array $data
|
||||
* @return bool
|
||||
*/
|
||||
public function validate(array $data): bool
|
||||
{
|
||||
parent::validate($data);
|
||||
|
||||
Activity::where('account_id', $data['account_id'])
|
||||
->findOrFail($data['activity_id']);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroy an activity.
|
||||
*
|
||||
* @param array $data
|
||||
* @return bool
|
||||
*/
|
||||
public function execute(array $data): bool
|
||||
{
|
||||
$this->validate($data);
|
||||
|
||||
$activity = Activity::find($data['activity_id']);
|
||||
|
||||
$activity->deleteJournalEntry();
|
||||
|
||||
$activity->delete();
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
131
app/Services/Account/Activity/Activity/UpdateActivity.php
Normal file
131
app/Services/Account/Activity/Activity/UpdateActivity.php
Normal file
@@ -0,0 +1,131 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Account\Activity\Activity;
|
||||
|
||||
use App\Services\BaseService;
|
||||
use App\Models\Contact\Contact;
|
||||
use App\Models\Account\Activity;
|
||||
use App\Models\Account\ActivityType;
|
||||
use App\Models\Journal\JournalEntry;
|
||||
use App\Models\Instance\Emotion\Emotion;
|
||||
|
||||
class UpdateActivity extends BaseService
|
||||
{
|
||||
/**
|
||||
* Get the validation rules that apply to the service.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'account_id' => 'required|integer|exists:accounts,id',
|
||||
'activity_id' => 'required|integer|exists:activities,id',
|
||||
'activity_type_id' => 'nullable|integer|exists:activity_types,id',
|
||||
'summary' => 'required|string:255',
|
||||
'description' => 'nullable|string:1000000',
|
||||
'happened_at' => 'required|date|date_format:Y-m-d',
|
||||
'emotions' => 'nullable|array',
|
||||
'contacts' => 'required|array',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate all datas to execute the service.
|
||||
*
|
||||
* @param array $data
|
||||
* @return bool
|
||||
*/
|
||||
public function validate(array $data): bool
|
||||
{
|
||||
parent::validate($data);
|
||||
|
||||
Activity::where('account_id', $data['account_id'])
|
||||
->findOrFail($data['activity_id']);
|
||||
|
||||
foreach ($data['contacts'] as $contactId) {
|
||||
Contact::where('account_id', $data['account_id'])
|
||||
->findOrFail($contactId);
|
||||
}
|
||||
|
||||
if (! empty($data['activity_type_id']) && $data['activity_type_id'] != '') {
|
||||
ActivityType::where('account_id', $data['account_id'])
|
||||
->findOrFail($data['activity_type_id']);
|
||||
}
|
||||
|
||||
if (! empty($data['emotions']) && $data['emotions'] != '') {
|
||||
foreach ($data['emotions'] as $emotionId) {
|
||||
Emotion::findOrFail($emotionId);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update an activity.
|
||||
*
|
||||
* @param array $data
|
||||
* @return Activity
|
||||
*/
|
||||
public function execute(array $data): Activity
|
||||
{
|
||||
$this->validate($data);
|
||||
|
||||
/** @var Activity */
|
||||
$activity = Activity::find($data['activity_id']);
|
||||
|
||||
$this->update($data, $activity);
|
||||
|
||||
// Log a journal entry but need to delete the previous one first
|
||||
$activity->deleteJournalEntry();
|
||||
JournalEntry::add($activity);
|
||||
|
||||
// Now we update the activity with each one of the attendees
|
||||
app(AttachContactToActivity::class)->execute([
|
||||
'account_id' => $data['account_id'],
|
||||
'activity_id' => $data['activity_id'],
|
||||
'contacts' => $data['contacts'],
|
||||
]);
|
||||
|
||||
return $activity->refresh();
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the activity.
|
||||
*
|
||||
* @param array $data
|
||||
* @param Activity $activity
|
||||
* @return void
|
||||
*/
|
||||
private function update(array $data, Activity $activity)
|
||||
{
|
||||
$activity->update([
|
||||
'activity_type_id' => $this->nullOrValue($data, 'activity_type_id'),
|
||||
'summary' => $data['summary'],
|
||||
'description' => $this->nullOrValue($data, 'description'),
|
||||
'happened_at' => $data['happened_at'],
|
||||
]);
|
||||
|
||||
if (! empty($data['emotions']) && $data['emotions'] != '') {
|
||||
$this->updateEmotions($data['emotions'], $activity);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update activity's emotions.
|
||||
*
|
||||
* @param array $emotions
|
||||
* @param Activity $activity
|
||||
* @return void
|
||||
*/
|
||||
private function updateEmotions(array $emotions, Activity $activity)
|
||||
{
|
||||
$emotionsSync = [];
|
||||
foreach ($emotions as $emotion) {
|
||||
$emotionsSync[$emotion] = ['account_id' => $activity->account_id];
|
||||
}
|
||||
|
||||
$activity->emotions()->sync($emotionsSync);
|
||||
}
|
||||
}
|
||||
125
app/Services/Account/Activity/ActivityStatisticService.php
Normal file
125
app/Services/Account/Activity/ActivityStatisticService.php
Normal file
@@ -0,0 +1,125 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Account\Activity;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use App\Models\Contact\Contact;
|
||||
use Illuminate\Support\Collection;
|
||||
use App\Models\Account\ActivityType;
|
||||
|
||||
class ActivityStatisticService
|
||||
{
|
||||
/**
|
||||
* Return the activities with the contact in a given timeframe.
|
||||
*
|
||||
* @param Contact $contact
|
||||
* @param Carbon $startDate
|
||||
* @param Carbon $endDate
|
||||
* @return Collection
|
||||
*/
|
||||
public function activitiesWithContactInTimeRange(Contact $contact, Carbon $startDate, Carbon $endDate)
|
||||
{
|
||||
return $contact->activities()
|
||||
->where('happened_at', '>=', $startDate)
|
||||
->where('happened_at', '<=', $endDate)
|
||||
->orderBy('happened_at', 'desc')
|
||||
->get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the list of number of activities per year in total done with
|
||||
* the contact.
|
||||
*
|
||||
* @param Contact $contact
|
||||
* @return \Illuminate\Database\Eloquent\Collection<array-key, \App\Models\Account\ActivityStatistic>
|
||||
*/
|
||||
public function activitiesPerYearWithContact(Contact $contact)
|
||||
{
|
||||
return $contact->activityStatistics()->get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the list of activities per month for a given year.
|
||||
*
|
||||
* @param Contact $contact
|
||||
* @param int $year
|
||||
* @return Collection
|
||||
*/
|
||||
public function activitiesPerMonthForYear(Contact $contact, int $year)
|
||||
{
|
||||
$startDate = Carbon::create($year, 1, 1, 0, 0, 0);
|
||||
$endDate = Carbon::create($year, 12, 31);
|
||||
|
||||
$activities = $this->activitiesWithContactInTimeRange($contact, $startDate, $endDate);
|
||||
|
||||
$activitiesPerMonth = collect([]);
|
||||
for ($month = 1; $month < 13; $month++) {
|
||||
$activitiesInMonth = collect([]);
|
||||
|
||||
foreach ($activities as $activity) {
|
||||
if ($activity->happened_at->month === $month) {
|
||||
$activitiesInMonth->push($activity);
|
||||
}
|
||||
}
|
||||
|
||||
$activitiesPerMonth->push([
|
||||
'month' => $month,
|
||||
'occurences' => $activitiesInMonth->count(),
|
||||
'activities' => $activitiesInMonth,
|
||||
]);
|
||||
}
|
||||
|
||||
$maxActivitiesInAMonth = $activitiesPerMonth->max('occurences');
|
||||
|
||||
$activitiesPerMonth->transform(function ($activity) use ($maxActivitiesInAMonth) {
|
||||
if ($activity['occurences'] != 0) {
|
||||
$activity['percent'] = ($activity['occurences'] * 100 / $maxActivitiesInAMonth);
|
||||
} else {
|
||||
$activity['percent'] = 0;
|
||||
}
|
||||
|
||||
return $activity;
|
||||
});
|
||||
|
||||
return $activitiesPerMonth;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the list of unique activity types for activities done with
|
||||
* a contact in a given timeframe, along with the number of occurences.
|
||||
*
|
||||
* @param Contact $contact
|
||||
* @param Carbon $startDate
|
||||
* @param Carbon $endDate
|
||||
* @return Collection
|
||||
*/
|
||||
public function uniqueActivityTypesInTimeRange(Contact $contact, Carbon $startDate, Carbon $endDate)
|
||||
{
|
||||
$activities = $this->activitiesWithContactInTimeRange($contact, $startDate, $endDate);
|
||||
|
||||
// group activities by activity type id
|
||||
$grouped = $activities->groupBy(function ($item, $key) {
|
||||
return $item['activity_type_id'];
|
||||
});
|
||||
|
||||
// remove activity type id that are null
|
||||
$grouped = $grouped->reject(function ($value, $key) {
|
||||
return $key == '';
|
||||
});
|
||||
|
||||
// calculate how many occurences of unique activity type id
|
||||
$activities = $grouped->map(function ($item) {
|
||||
return collect($item)->count();
|
||||
});
|
||||
|
||||
$activityTypes = collect([]);
|
||||
foreach ($activities as $key => $value) {
|
||||
$activityTypes->push([
|
||||
'object' => ActivityType::find($key),
|
||||
'occurences' => $value,
|
||||
]);
|
||||
}
|
||||
|
||||
return $activityTypes;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Account\Activity\ActivityType;
|
||||
|
||||
use App\Services\BaseService;
|
||||
use App\Models\Account\ActivityType;
|
||||
use App\Models\Account\ActivityTypeCategory;
|
||||
|
||||
class CreateActivityType extends BaseService
|
||||
{
|
||||
/**
|
||||
* Get the validation rules that apply to the service.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'account_id' => 'required|integer|exists:accounts,id',
|
||||
'activity_type_category_id' => 'required|integer|exists:activity_type_categories,id',
|
||||
'name' => 'nullable|string|max:255',
|
||||
'translation_key' => 'nullable|string|max:255',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an activity type.
|
||||
*
|
||||
* @param array $data
|
||||
* @return ActivityType
|
||||
*/
|
||||
public function execute(array $data): ActivityType
|
||||
{
|
||||
$this->validate($data);
|
||||
|
||||
ActivityTypeCategory::where('account_id', $data['account_id'])
|
||||
->findOrFail($data['activity_type_category_id']);
|
||||
|
||||
$activityType = ActivityType::create([
|
||||
'account_id' => $data['account_id'],
|
||||
'activity_type_category_id' => $data['activity_type_category_id'],
|
||||
'name' => $this->nullOrValue($data, 'name'),
|
||||
'translation_key' => $this->nullOrValue($data, 'translation_key'),
|
||||
]);
|
||||
|
||||
return ActivityType::find($activityType->id);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Account\Activity\ActivityType;
|
||||
|
||||
use App\Services\BaseService;
|
||||
use App\Models\Account\ActivityType;
|
||||
|
||||
class DestroyActivityType extends BaseService
|
||||
{
|
||||
/**
|
||||
* Get the validation rules that apply to the service.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'account_id' => 'required|integer|exists:accounts,id',
|
||||
'activity_type_id' => 'required|integer|exists:activity_types,id',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroy a activity type.
|
||||
*
|
||||
* @param array $data
|
||||
* @return bool
|
||||
*/
|
||||
public function execute(array $data): bool
|
||||
{
|
||||
$this->validate($data);
|
||||
|
||||
$activityType = ActivityType::where('account_id', $data['account_id'])
|
||||
->findOrFail($data['activity_type_id']);
|
||||
|
||||
$activityType->delete();
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Account\Activity\ActivityType;
|
||||
|
||||
use App\Services\BaseService;
|
||||
use App\Models\Account\ActivityType;
|
||||
use App\Models\Account\ActivityTypeCategory;
|
||||
|
||||
class UpdateActivityType extends BaseService
|
||||
{
|
||||
/**
|
||||
* Get the validation rules that apply to the service.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'account_id' => 'required|integer|exists:accounts,id',
|
||||
'activity_type_category_id' => 'required|integer|exists:activity_type_categories,id',
|
||||
'activity_type_id' => 'required|integer|exists:activity_types,id',
|
||||
'name' => 'nullable|string|max:255',
|
||||
'translation_key' => 'nullable|string|max:255',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Update an activity type.
|
||||
*
|
||||
* @param array $data
|
||||
* @return ActivityType
|
||||
*/
|
||||
public function execute(array $data): ActivityType
|
||||
{
|
||||
$this->validate($data);
|
||||
|
||||
ActivityTypeCategory::where('account_id', $data['account_id'])
|
||||
->findOrFail($data['activity_type_category_id']);
|
||||
|
||||
/** @var ActivityType */
|
||||
$activityType = ActivityType::where('account_id', $data['account_id'])
|
||||
->findOrFail($data['activity_type_id']);
|
||||
|
||||
$activityType->update([
|
||||
'activity_type_category_id' => $data['activity_type_category_id'],
|
||||
'name' => $this->nullOrValue($data, 'name'),
|
||||
'translation_key' => $this->nullOrValue($data, 'translation_key'),
|
||||
]);
|
||||
|
||||
return $activityType;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Account\Activity\ActivityTypeCategory;
|
||||
|
||||
use App\Services\BaseService;
|
||||
use App\Models\Account\ActivityTypeCategory;
|
||||
|
||||
class CreateActivityTypeCategory extends BaseService
|
||||
{
|
||||
/**
|
||||
* Get the validation rules that apply to the service.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'account_id' => 'required|integer|exists:accounts,id',
|
||||
'name' => 'nullable|string|max:255',
|
||||
'translation_key' => 'nullable|string|max:255',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an activity type category.
|
||||
*
|
||||
* @param array $data
|
||||
* @return ActivityTypeCategory
|
||||
*/
|
||||
public function execute(array $data): ActivityTypeCategory
|
||||
{
|
||||
$this->validate($data);
|
||||
|
||||
$activityTypeCategory = ActivityTypeCategory::create([
|
||||
'account_id' => $data['account_id'],
|
||||
'name' => $this->nullOrValue($data, 'name'),
|
||||
'translation_key' => $this->nullOrValue($data, 'translation_key'),
|
||||
]);
|
||||
|
||||
return ActivityTypeCategory::find($activityTypeCategory->id);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Account\Activity\ActivityTypeCategory;
|
||||
|
||||
use App\Services\BaseService;
|
||||
use App\Models\Account\ActivityTypeCategory;
|
||||
|
||||
class DestroyActivityTypeCategory extends BaseService
|
||||
{
|
||||
/**
|
||||
* Get the validation rules that apply to the service.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'account_id' => 'required|integer|exists:accounts,id',
|
||||
'activity_type_category_id' => 'required|integer|exists:activity_type_categories,id',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroy a activity type category.
|
||||
*
|
||||
* @param array $data
|
||||
* @return bool
|
||||
*/
|
||||
public function execute(array $data): bool
|
||||
{
|
||||
$this->validate($data);
|
||||
|
||||
$activityTypeCategory = ActivityTypeCategory::where('account_id', $data['account_id'])
|
||||
->findOrFail($data['activity_type_category_id']);
|
||||
|
||||
$activityTypeCategory->delete();
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Account\Activity\ActivityTypeCategory;
|
||||
|
||||
use App\Services\BaseService;
|
||||
use App\Models\Account\ActivityTypeCategory;
|
||||
|
||||
class UpdateActivityTypeCategory extends BaseService
|
||||
{
|
||||
/**
|
||||
* Get the validation rules that apply to the service.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'account_id' => 'required|integer|exists:accounts,id',
|
||||
'activity_type_category_id' => 'required|integer|exists:activity_type_categories,id',
|
||||
'name' => 'nullable|string|max:255',
|
||||
'translation_key' => 'nullable|string|max:255',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Update an activity type category.
|
||||
*
|
||||
* @param array $data
|
||||
* @return ActivityTypeCategory
|
||||
*/
|
||||
public function execute(array $data): ActivityTypeCategory
|
||||
{
|
||||
$this->validate($data);
|
||||
|
||||
/** @var ActivityTypeCategory */
|
||||
$activityTypeCategory = ActivityTypeCategory::where('account_id', $data['account_id'])
|
||||
->findOrFail($data['activity_type_category_id']);
|
||||
|
||||
$activityTypeCategory->update([
|
||||
'name' => $this->nullOrValue($data, 'name'),
|
||||
'translation_key' => $this->nullOrValue($data, 'translation_key'),
|
||||
]);
|
||||
|
||||
return $activityTypeCategory;
|
||||
}
|
||||
}
|
||||
75
app/Services/Account/Company/CreateCompany.php
Normal file
75
app/Services/Account/Company/CreateCompany.php
Normal file
@@ -0,0 +1,75 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Account\Company;
|
||||
|
||||
use App\Models\User\User;
|
||||
use App\Services\BaseService;
|
||||
use function Safe\json_encode;
|
||||
use App\Models\Account\Company;
|
||||
use Safe\Exceptions\JsonException;
|
||||
use App\Jobs\AuditLog\LogAccountAudit;
|
||||
|
||||
class CreateCompany extends BaseService
|
||||
{
|
||||
/**
|
||||
* Get the validation rules that apply to the service.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'account_id' => 'required|integer|exists:accounts,id',
|
||||
'author_id' => 'required|integer|exists:users,id',
|
||||
'name' => 'required|string|max:255',
|
||||
'website' => 'nullable|string|max:255',
|
||||
'number_of_employees' => 'nullable|integer',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a company.
|
||||
*
|
||||
* @param array $data
|
||||
* @return Company
|
||||
*/
|
||||
public function execute(array $data): Company
|
||||
{
|
||||
$this->validate($data);
|
||||
|
||||
$this->log($data);
|
||||
|
||||
return Company::create([
|
||||
'account_id' => $data['account_id'],
|
||||
'name' => $data['name'],
|
||||
'website' => $this->nullOrValue($data, 'website'),
|
||||
'number_of_employees' => $this->nullOrValue($data, 'number_of_employees'),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an audit log.
|
||||
*
|
||||
* @param array $data
|
||||
* @return void
|
||||
*
|
||||
* @throws JsonException
|
||||
*/
|
||||
private function log(array $data): void
|
||||
{
|
||||
$author = User::find($data['author_id']);
|
||||
|
||||
LogAccountAudit::dispatch([
|
||||
'action' => 'company_created',
|
||||
'account_id' => $data['account_id'],
|
||||
'about_contact_id' => null,
|
||||
'author_id' => $author->id,
|
||||
'author_name' => $author->name,
|
||||
'audited_at' => now(),
|
||||
'should_appear_on_dashboard' => true,
|
||||
'objects' => json_encode([
|
||||
'name' => $data['name'],
|
||||
]),
|
||||
]);
|
||||
}
|
||||
}
|
||||
40
app/Services/Account/Company/DestroyCompany.php
Normal file
40
app/Services/Account/Company/DestroyCompany.php
Normal file
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Account\Company;
|
||||
|
||||
use App\Services\BaseService;
|
||||
use App\Models\Account\Company;
|
||||
|
||||
class DestroyCompany extends BaseService
|
||||
{
|
||||
/**
|
||||
* Get the validation rules that apply to the service.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'account_id' => 'required|integer|exists:accounts,id',
|
||||
'company_id' => 'required|integer|exists:companies,id',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroy a company.
|
||||
*
|
||||
* @param array $data
|
||||
* @return bool
|
||||
*/
|
||||
public function execute(array $data): bool
|
||||
{
|
||||
$this->validate($data);
|
||||
|
||||
$company = Company::where('account_id', $data['account_id'])
|
||||
->findOrFail($data['company_id']);
|
||||
|
||||
$company->delete();
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
48
app/Services/Account/Company/UpdateCompany.php
Normal file
48
app/Services/Account/Company/UpdateCompany.php
Normal file
@@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Account\Company;
|
||||
|
||||
use App\Services\BaseService;
|
||||
use App\Models\Account\Company;
|
||||
|
||||
class UpdateCompany extends BaseService
|
||||
{
|
||||
/**
|
||||
* Get the validation rules that apply to the service.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'account_id' => 'required|integer|exists:accounts,id',
|
||||
'company_id' => 'required|integer|exists:companies,id',
|
||||
'name' => 'required|string|max:255',
|
||||
'website' => 'nullable|string|max:255',
|
||||
'number_of_employees' => 'nullable|integer',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Update a company.
|
||||
*
|
||||
* @param array $data
|
||||
* @return Company
|
||||
*/
|
||||
public function execute(array $data): Company
|
||||
{
|
||||
$this->validate($data);
|
||||
|
||||
/** @var Company */
|
||||
$company = Company::where('account_id', $data['account_id'])
|
||||
->findOrFail($data['company_id']);
|
||||
|
||||
$company->update([
|
||||
'name' => $data['name'],
|
||||
'website' => $this->nullOrValue($data, 'website'),
|
||||
'number_of_employees' => $this->nullOrValue($data, 'number_of_employees'),
|
||||
]);
|
||||
|
||||
return $company;
|
||||
}
|
||||
}
|
||||
44
app/Services/Account/Gender/CreateGender.php
Normal file
44
app/Services/Account/Gender/CreateGender.php
Normal file
@@ -0,0 +1,44 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Account\Gender;
|
||||
|
||||
use App\Services\BaseService;
|
||||
use App\Models\Contact\Gender;
|
||||
use Illuminate\Validation\Rule;
|
||||
|
||||
class CreateGender extends BaseService
|
||||
{
|
||||
/**
|
||||
* Get the validation rules that apply to the service.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'account_id' => 'required|integer|exists:accounts,id',
|
||||
'name' => 'required|string|max:255',
|
||||
'type' => [
|
||||
'required',
|
||||
Rule::in([Gender::MALE, Gender::FEMALE, Gender::OTHER]),
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a gender.
|
||||
*
|
||||
* @param array $data
|
||||
* @return Gender
|
||||
*/
|
||||
public function execute(array $data): Gender
|
||||
{
|
||||
$this->validate($data);
|
||||
|
||||
return Gender::create([
|
||||
'account_id' => $data['account_id'],
|
||||
'name' => $data['name'],
|
||||
'type' => $data['type'],
|
||||
]);
|
||||
}
|
||||
}
|
||||
40
app/Services/Account/Gender/DestroyGender.php
Normal file
40
app/Services/Account/Gender/DestroyGender.php
Normal file
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Account\Gender;
|
||||
|
||||
use App\Services\BaseService;
|
||||
use App\Models\Contact\Gender;
|
||||
|
||||
class DestroyGender extends BaseService
|
||||
{
|
||||
/**
|
||||
* Get the validation rules that apply to the service.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'account_id' => 'required|integer|exists:accounts,id',
|
||||
'gender_id' => 'required|integer|exists:genders,id',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroy a gender.
|
||||
*
|
||||
* @param array $data
|
||||
* @return bool
|
||||
*/
|
||||
public function execute(array $data): bool
|
||||
{
|
||||
$this->validate($data);
|
||||
|
||||
$gender = Gender::where('account_id', $data['account_id'])
|
||||
->findOrFail($data['gender_id']);
|
||||
|
||||
$gender->delete();
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
50
app/Services/Account/Gender/UpdateGender.php
Normal file
50
app/Services/Account/Gender/UpdateGender.php
Normal file
@@ -0,0 +1,50 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Account\Gender;
|
||||
|
||||
use App\Services\BaseService;
|
||||
use App\Models\Contact\Gender;
|
||||
use Illuminate\Validation\Rule;
|
||||
|
||||
class UpdateGender extends BaseService
|
||||
{
|
||||
/**
|
||||
* Get the validation rules that apply to the service.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'account_id' => 'required|integer|exists:accounts,id',
|
||||
'gender_id' => 'required|integer|exists:genders,id',
|
||||
'name' => 'required|string|max:255',
|
||||
'type' => [
|
||||
'required',
|
||||
Rule::in([Gender::MALE, Gender::FEMALE, Gender::OTHER]),
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Update a gender.
|
||||
*
|
||||
* @param array $data
|
||||
* @return Gender
|
||||
*/
|
||||
public function execute(array $data): Gender
|
||||
{
|
||||
$this->validate($data);
|
||||
|
||||
/** @var Gender */
|
||||
$gender = Gender::where('account_id', $data['account_id'])
|
||||
->findOrFail($data['gender_id']);
|
||||
|
||||
$gender->update([
|
||||
'name' => $data['name'],
|
||||
'type' => $data['type'],
|
||||
]);
|
||||
|
||||
return $gender;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Account\LifeEvent\LifeEventType;
|
||||
|
||||
use App\Services\BaseService;
|
||||
use App\Models\Contact\LifeEventType;
|
||||
use App\Models\Contact\LifeEventCategory;
|
||||
|
||||
class CreateLifeEventType extends BaseService
|
||||
{
|
||||
/**
|
||||
* Get the validation rules that apply to the service.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'account_id' => 'required|integer|exists:accounts,id',
|
||||
'life_event_category_id' => 'required|integer|exists:life_event_categories,id',
|
||||
'name' => 'required|string|max:255',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a life event type.
|
||||
*
|
||||
* @param array $data
|
||||
* @return LifeEventType
|
||||
*/
|
||||
public function execute(array $data): LifeEventType
|
||||
{
|
||||
$this->validate($data);
|
||||
|
||||
LifeEventCategory::where('account_id', $data['account_id'])
|
||||
->findOrFail($data['life_event_category_id']);
|
||||
|
||||
$lifeEventType = LifeEventType::create([
|
||||
'account_id' => $data['account_id'],
|
||||
'life_event_category_id' => $data['life_event_category_id'],
|
||||
'name' => $data['name'],
|
||||
'default_life_event_type_key' => null,
|
||||
'core_monica_data' => false,
|
||||
'specific_information_structure' => null,
|
||||
]);
|
||||
|
||||
return LifeEventType::find($lifeEventType->id);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Account\LifeEvent\LifeEventType;
|
||||
|
||||
use App\Services\BaseService;
|
||||
use App\Models\Contact\LifeEventType;
|
||||
|
||||
class DestroyLifeEventType extends BaseService
|
||||
{
|
||||
/**
|
||||
* Get the validation rules that apply to the service.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'account_id' => 'required|integer|exists:accounts,id',
|
||||
'life_event_type_id' => 'required|integer|exists:life_event_types,id',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroy a life event type.
|
||||
*
|
||||
* @param array $data
|
||||
* @return bool
|
||||
*/
|
||||
public function execute(array $data): bool
|
||||
{
|
||||
$this->validate($data);
|
||||
|
||||
$lifeEventType = LifeEventType::where('account_id', $data['account_id'])
|
||||
->findOrFail($data['life_event_type_id']);
|
||||
|
||||
$lifeEventType->delete();
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Account\LifeEvent\LifeEventType;
|
||||
|
||||
use App\Services\BaseService;
|
||||
use App\Models\Contact\LifeEventType;
|
||||
use App\Models\Contact\LifeEventCategory;
|
||||
|
||||
class UpdateLifeEventType extends BaseService
|
||||
{
|
||||
/**
|
||||
* Get the validation rules that apply to the service.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'account_id' => 'required|integer|exists:accounts,id',
|
||||
'life_event_category_id' => 'required|integer|exists:life_event_categories,id',
|
||||
'life_event_type_id' => 'required|integer|exists:life_event_types,id',
|
||||
'name' => 'required|string|max:255',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Update a life event type.
|
||||
*
|
||||
* @param array $data
|
||||
* @return LifeEventType
|
||||
*/
|
||||
public function execute(array $data): LifeEventType
|
||||
{
|
||||
$this->validate($data);
|
||||
|
||||
LifeEventCategory::where('account_id', $data['account_id'])
|
||||
->findOrFail($data['life_event_category_id']);
|
||||
|
||||
/** @var LifeEventType */
|
||||
$lifeEventType = LifeEventType::where('account_id', $data['account_id'])
|
||||
->findOrFail($data['life_event_type_id']);
|
||||
|
||||
$lifeEventType->update([
|
||||
'life_event_category_id' => $data['life_event_category_id'],
|
||||
'name' => $data['name'],
|
||||
]);
|
||||
|
||||
return $lifeEventType;
|
||||
}
|
||||
}
|
||||
46
app/Services/Account/Photo/DestroyPhoto.php
Normal file
46
app/Services/Account/Photo/DestroyPhoto.php
Normal file
@@ -0,0 +1,46 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Account\Photo;
|
||||
|
||||
use App\Models\Account\Photo;
|
||||
use App\Services\BaseService;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
|
||||
class DestroyPhoto extends BaseService
|
||||
{
|
||||
/**
|
||||
* Get the validation rules that apply to the service.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'account_id' => 'required|integer|exists:accounts,id',
|
||||
'photo_id' => 'required|integer|exists:photos,id',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroy a photo.
|
||||
*
|
||||
* @param array $data
|
||||
* @return bool
|
||||
*/
|
||||
public function execute(array $data): bool
|
||||
{
|
||||
$this->validate($data);
|
||||
|
||||
$photo = Photo::where('account_id', $data['account_id'])
|
||||
->findOrFail($data['photo_id']);
|
||||
|
||||
// Delete the physical photo
|
||||
// Throws FileNotFoundException
|
||||
Storage::delete($photo->new_filename);
|
||||
|
||||
// Delete the object in the DB
|
||||
$photo->delete();
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
219
app/Services/Account/Photo/UploadPhoto.php
Normal file
219
app/Services/Account/Photo/UploadPhoto.php
Normal file
@@ -0,0 +1,219 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Account\Photo;
|
||||
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Str;
|
||||
use App\Models\Account\Photo;
|
||||
use App\Services\BaseService;
|
||||
use function Safe\finfo_open;
|
||||
use function Safe\preg_match;
|
||||
use App\Helpers\StorageHelper;
|
||||
use App\Models\Contact\Contact;
|
||||
use function Safe\base64_decode;
|
||||
use Intervention\Image\Facades\Image;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use Intervention\Image\Exception\NotReadableException;
|
||||
|
||||
class UploadPhoto extends BaseService
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
Validator::extend('photo', function ($attribute, $value, $parameters, $validator) {
|
||||
return $this->isValidPhoto($value);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the validation rules that apply to the service.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'account_id' => 'required|integer|exists:accounts,id',
|
||||
'contact_id' => 'required|integer|exists:contacts,id',
|
||||
'photo' => 'required_without:data|file|image',
|
||||
'data' => 'required_without:photo|string|photo',
|
||||
'extension' => 'nullable|string',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Upload a photo.
|
||||
*
|
||||
* @param array $data
|
||||
* @return Photo|null
|
||||
*/
|
||||
public function execute(array $data): ?Photo
|
||||
{
|
||||
$this->validate($data);
|
||||
|
||||
$contact = Contact::where('account_id', $data['account_id'])
|
||||
->findOrFail($data['contact_id']);
|
||||
|
||||
$contact->throwInactive();
|
||||
|
||||
$array = null;
|
||||
if (Arr::has($data, 'photo')) {
|
||||
$array = $this->importPhoto($data);
|
||||
} else {
|
||||
$array = $this->importFile($data);
|
||||
}
|
||||
|
||||
if (! $array) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return tap(Photo::create($array), function ($photo) use ($contact): void {
|
||||
$contact->photos()->syncWithoutDetaching([$photo->id]);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an array with the necessary fields to create the photo object.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function importPhoto($data): array
|
||||
{
|
||||
$photo = $data['photo'];
|
||||
|
||||
return [
|
||||
'account_id' => $data['account_id'],
|
||||
'original_filename' => $photo->getClientOriginalName(),
|
||||
'filesize' => $photo->getSize(),
|
||||
'mime_type' => (new \Mimey\MimeTypes)->getMimeType($photo->guessClientExtension()),
|
||||
'new_filename' => $photo->store('photos', [
|
||||
'disk' => config('filesystems.default'),
|
||||
'visibility' => config('filesystems.default_visibility'),
|
||||
]),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Upload the photo.
|
||||
*
|
||||
* @return array|null
|
||||
*/
|
||||
private function importFile(array $data): ?array
|
||||
{
|
||||
$filename = Str::random(40);
|
||||
|
||||
try {
|
||||
$image = Image::make($data['data']);
|
||||
} catch (NotReadableException $e) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$tempfile = $this->storeImage('local', $image, 'temp/'.$filename);
|
||||
|
||||
try {
|
||||
$storagePath = StorageHelper::disk('local')->path($tempfile);
|
||||
// This sets the basePath to get the filesize later
|
||||
$image = $image->setFileInfoFromPath($storagePath);
|
||||
$extension = (new \Mimey\MimeTypes)->getExtension($image->mime());
|
||||
if (empty($extension)) {
|
||||
$extension = str_replace(' ', '', Arr::get($data, 'extension'));
|
||||
}
|
||||
if (! empty($extension)) {
|
||||
$filename .= '.'.$extension;
|
||||
}
|
||||
|
||||
$array = [
|
||||
'account_id' => $data['account_id'],
|
||||
'original_filename' => $filename,
|
||||
'filesize' => $image->filesize(),
|
||||
'mime_type' => $image->mime(),
|
||||
];
|
||||
|
||||
$array['new_filename'] = $this->storeImage(config('filesystems.default'), $image, 'photos/'.$filename);
|
||||
} finally {
|
||||
$storage = Storage::disk('local');
|
||||
if ($storage->exists($tempfile)) {
|
||||
$storage->delete($tempfile);
|
||||
}
|
||||
}
|
||||
|
||||
return $array;
|
||||
}
|
||||
|
||||
/**
|
||||
* Store the decoded image in the temp file.
|
||||
*
|
||||
* @param string $disk
|
||||
* @param \Intervention\Image\Image $image
|
||||
* @param string $filename
|
||||
* @return string|null
|
||||
*/
|
||||
private function storeImage(string $disk, $image, string $filename): ?string
|
||||
{
|
||||
$result = Storage::disk($disk)
|
||||
->put($path = $filename, (string) $image->stream(), config('filesystems.default_visibility'));
|
||||
|
||||
return $result ? $path : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if the source photo is a valid encoded photo.
|
||||
*
|
||||
* @param string $data
|
||||
* @return bool
|
||||
*/
|
||||
private function isValidPhoto(string $data): bool
|
||||
{
|
||||
return $this->isBinary($data) || $this->isDataUrl($data) || $this->isBase64($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if source data is binary data.
|
||||
*
|
||||
* @param string $data
|
||||
* @return bool
|
||||
*/
|
||||
private function isBinary(string $data): bool
|
||||
{
|
||||
$mime = finfo_buffer(finfo_open(FILEINFO_MIME_TYPE), $data); // @phpstan-ignore-line
|
||||
|
||||
return substr($mime, 0, 4) != 'text' && $mime != 'application/x-empty';
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if source data is data-url format.
|
||||
*
|
||||
* @param string $data
|
||||
* @return bool
|
||||
*/
|
||||
private function isDataUrl(string $data): bool
|
||||
{
|
||||
if (! is_string($data)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$pattern = "/^data:(?:image\/[a-zA-Z\-\.]+)(?:charset=\".+\")?;base64,(?P<data>.+)$/";
|
||||
preg_match($pattern, $data, $matches);
|
||||
|
||||
if (is_array($matches) && Arr::has($matches, 'data')) {
|
||||
return ! empty(base64_decode($matches['data']));
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if source data is base64 encoded.
|
||||
*
|
||||
* @param string $data
|
||||
* @return bool
|
||||
*/
|
||||
private function isBase64(string $data): bool
|
||||
{
|
||||
if (! is_string($data)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return base64_encode(base64_decode($data)) === str_replace(["\n", "\r"], '', $data);
|
||||
}
|
||||
}
|
||||
70
app/Services/Account/Place/CreatePlace.php
Normal file
70
app/Services/Account/Place/CreatePlace.php
Normal file
@@ -0,0 +1,70 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Account\Place;
|
||||
|
||||
use App\Models\Account\Place;
|
||||
use App\Services\BaseService;
|
||||
use App\Jobs\GetGPSCoordinate;
|
||||
|
||||
class CreatePlace extends BaseService
|
||||
{
|
||||
/**
|
||||
* Get the validation rules that apply to the service.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'account_id' => 'required|integer|exists:accounts,id',
|
||||
'street' => 'nullable|string|max:255',
|
||||
'city' => 'nullable|string|max:255',
|
||||
'province' => 'nullable|string|max:255',
|
||||
'postal_code' => 'nullable|string|max:255',
|
||||
'country' => 'nullable|string|max:3',
|
||||
'latitude' => 'nullable|numeric',
|
||||
'longitude' => 'nullable|numeric',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a place.
|
||||
*
|
||||
* @param array $data
|
||||
* @return Place
|
||||
*/
|
||||
public function execute(array $data): Place
|
||||
{
|
||||
$this->validate($data);
|
||||
|
||||
$place = Place::create([
|
||||
'account_id' => $data['account_id'],
|
||||
'street' => $this->nullOrValue($data, 'street'),
|
||||
'city' => $this->nullOrValue($data, 'city'),
|
||||
'province' => $this->nullOrValue($data, 'province'),
|
||||
'postal_code' => $this->nullOrValue($data, 'postal_code'),
|
||||
'country' => $this->nullOrValue($data, 'country'),
|
||||
'latitude' => $this->nullOrValue($data, 'latitude'),
|
||||
'longitude' => $this->nullOrValue($data, 'longitude'),
|
||||
]);
|
||||
|
||||
if (is_null($place->latitude) || is_null($place->longitude)) {
|
||||
$this->getGeocodingInfo($place);
|
||||
}
|
||||
|
||||
return $place;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get geocoding information about the place (lat/longitude).
|
||||
*
|
||||
* @param Place $place
|
||||
* @return void
|
||||
*/
|
||||
private function getGeocodingInfo(Place $place)
|
||||
{
|
||||
if (config('monica.enable_geolocation') && ! is_null(config('monica.location_iq_api_key'))) {
|
||||
GetGPSCoordinate::dispatch($place);
|
||||
}
|
||||
}
|
||||
}
|
||||
40
app/Services/Account/Place/DestroyPlace.php
Normal file
40
app/Services/Account/Place/DestroyPlace.php
Normal file
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Account\Place;
|
||||
|
||||
use App\Models\Account\Place;
|
||||
use App\Services\BaseService;
|
||||
|
||||
class DestroyPlace extends BaseService
|
||||
{
|
||||
/**
|
||||
* Get the validation rules that apply to the service.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'account_id' => 'required|integer|exists:accounts,id',
|
||||
'place_id' => 'required|integer|exists:places,id',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroy a place.
|
||||
*
|
||||
* @param array $data
|
||||
* @return bool
|
||||
*/
|
||||
public function execute(array $data): bool
|
||||
{
|
||||
$this->validate($data);
|
||||
|
||||
$place = Place::where('account_id', $data['account_id'])
|
||||
->findOrFail($data['place_id']);
|
||||
|
||||
$place->delete();
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
74
app/Services/Account/Place/UpdatePlace.php
Normal file
74
app/Services/Account/Place/UpdatePlace.php
Normal file
@@ -0,0 +1,74 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Account\Place;
|
||||
|
||||
use App\Models\Account\Place;
|
||||
use App\Services\BaseService;
|
||||
use App\Jobs\GetGPSCoordinate;
|
||||
|
||||
class UpdatePlace extends BaseService
|
||||
{
|
||||
/**
|
||||
* Get the validation rules that apply to the service.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'account_id' => 'required|integer|exists:accounts,id',
|
||||
'place_id' => 'required|integer|exists:places,id',
|
||||
'street' => 'nullable|string|max:255',
|
||||
'city' => 'nullable|string|max:255',
|
||||
'province' => 'nullable|string|max:255',
|
||||
'postal_code' => 'nullable|string|max:255',
|
||||
'country' => 'nullable|string|max:3',
|
||||
'latitude' => 'nullable|numeric',
|
||||
'longitude' => 'nullable|numeric',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Update a place.
|
||||
*
|
||||
* @param array $data
|
||||
* @return Place
|
||||
*/
|
||||
public function execute(array $data): Place
|
||||
{
|
||||
$this->validate($data);
|
||||
|
||||
/** @var Place */
|
||||
$place = Place::where('account_id', $data['account_id'])
|
||||
->findOrFail($data['place_id']);
|
||||
|
||||
$place->update([
|
||||
'street' => $this->nullOrValue($data, 'street'),
|
||||
'city' => $this->nullOrValue($data, 'city'),
|
||||
'province' => $this->nullOrValue($data, 'province'),
|
||||
'postal_code' => $this->nullOrValue($data, 'postal_code'),
|
||||
'country' => $this->nullOrValue($data, 'country'),
|
||||
'latitude' => $this->nullOrValue($data, 'latitude'),
|
||||
'longitude' => $this->nullOrValue($data, 'longitude'),
|
||||
]);
|
||||
|
||||
if (is_null($place->latitude) || is_null($place->longitude)) {
|
||||
$this->getGeocodingInfo($place);
|
||||
}
|
||||
|
||||
return $place;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get geocoding information about the place (lat/longitude).
|
||||
*
|
||||
* @param Place $place
|
||||
* @return void
|
||||
*/
|
||||
private function getGeocodingInfo(Place $place)
|
||||
{
|
||||
if (config('monica.enable_geolocation') && ! is_null(config('monica.location_iq_api_key'))) {
|
||||
GetGPSCoordinate::dispatch($place);
|
||||
}
|
||||
}
|
||||
}
|
||||
46
app/Services/Account/Settings/ArchiveAllContacts.php
Normal file
46
app/Services/Account/Settings/ArchiveAllContacts.php
Normal file
@@ -0,0 +1,46 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Account\Settings;
|
||||
|
||||
use App\Services\BaseService;
|
||||
use App\Models\Account\Account;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Database\QueryException;
|
||||
|
||||
class ArchiveAllContacts extends BaseService
|
||||
{
|
||||
/**
|
||||
* Get the validation rules that apply to the service.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'account_id' => 'required|integer|exists:accounts,id',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Archive all the contacts in the account.
|
||||
*
|
||||
* This method is used by a user who wants to downgrade his plan.
|
||||
*
|
||||
* @param array $data
|
||||
* @return bool
|
||||
*/
|
||||
public function execute(array $data): bool
|
||||
{
|
||||
$this->validate($data);
|
||||
|
||||
try {
|
||||
DB::table('contacts')
|
||||
->where('account_id', $data['account_id'])
|
||||
->update(['is_active' => 0]);
|
||||
} catch (QueryException $e) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
86
app/Services/Account/Settings/DestroyAccount.php
Normal file
86
app/Services/Account/Settings/DestroyAccount.php
Normal file
@@ -0,0 +1,86 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Account\Settings;
|
||||
|
||||
use App\Services\BaseService;
|
||||
use App\Models\Account\Account;
|
||||
use App\Exceptions\StripeException;
|
||||
|
||||
class DestroyAccount extends BaseService
|
||||
{
|
||||
/**
|
||||
* Get the validation rules that apply to the service.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'account_id' => 'required|integer|exists:accounts,id',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Completely delete an account.
|
||||
*
|
||||
* @param array $data
|
||||
* @return void
|
||||
*
|
||||
* @throws StripeException
|
||||
*/
|
||||
public function execute(array $data): void
|
||||
{
|
||||
$this->validate($data);
|
||||
|
||||
$account = Account::find($data['account_id']);
|
||||
|
||||
$this->destroyDocuments($account);
|
||||
|
||||
$this->destroyPhotos($account);
|
||||
|
||||
$this->cancelStripe($account);
|
||||
|
||||
$account->delete();
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroy the documents.
|
||||
*
|
||||
* @param Account $account
|
||||
* @return void
|
||||
*/
|
||||
private function destroyDocuments(Account $account)
|
||||
{
|
||||
app(DestroyAllDocuments::class)->execute([
|
||||
'account_id' => $account->id,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroy the photos.
|
||||
*
|
||||
* @param Account $account
|
||||
* @return void
|
||||
*/
|
||||
private function destroyPhotos(Account $account)
|
||||
{
|
||||
app(DestroyAllPhotos::class)->execute([
|
||||
'account_id' => $account->id,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Cancel Stripe subscription.
|
||||
*
|
||||
* @param Account $account
|
||||
* @return void
|
||||
*
|
||||
* @throws StripeException
|
||||
*/
|
||||
private function cancelStripe(Account $account)
|
||||
{
|
||||
if ($account->isSubscribed() && ! $account->has_access_to_paid_version_for_free) {
|
||||
$account->subscriptionCancel();
|
||||
}
|
||||
}
|
||||
}
|
||||
41
app/Services/Account/Settings/DestroyAllDocuments.php
Normal file
41
app/Services/Account/Settings/DestroyAllDocuments.php
Normal file
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Account\Settings;
|
||||
|
||||
use App\Services\BaseService;
|
||||
use App\Models\Contact\Document;
|
||||
|
||||
class DestroyAllDocuments extends BaseService
|
||||
{
|
||||
/**
|
||||
* Get the validation rules that apply to the service.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'account_id' => 'required|integer|exists:accounts,id',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroy all documents in an account.
|
||||
*
|
||||
* @param array $data
|
||||
* @return bool
|
||||
*/
|
||||
public function execute(array $data): bool
|
||||
{
|
||||
$this->validate($data);
|
||||
|
||||
$documents = Document::where('account_id', $data['account_id'])
|
||||
->get();
|
||||
|
||||
foreach ($documents as $document) {
|
||||
$document->delete();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
41
app/Services/Account/Settings/DestroyAllPhotos.php
Normal file
41
app/Services/Account/Settings/DestroyAllPhotos.php
Normal file
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Account\Settings;
|
||||
|
||||
use App\Models\Account\Photo;
|
||||
use App\Services\BaseService;
|
||||
|
||||
class DestroyAllPhotos extends BaseService
|
||||
{
|
||||
/**
|
||||
* Get the validation rules that apply to the service.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'account_id' => 'required|integer|exists:accounts,id',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroy all photos in an account.
|
||||
*
|
||||
* @param array $data
|
||||
* @return bool
|
||||
*/
|
||||
public function execute(array $data): bool
|
||||
{
|
||||
$this->validate($data);
|
||||
|
||||
$photos = Photo::where('account_id', $data['account_id'])
|
||||
->get();
|
||||
|
||||
foreach ($photos as $photo) {
|
||||
$photo->delete();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
94
app/Services/Account/Settings/JsonExportAccount.php
Normal file
94
app/Services/Account/Settings/JsonExportAccount.php
Normal file
@@ -0,0 +1,94 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Account\Settings;
|
||||
|
||||
use App\Models\User\User;
|
||||
use Illuminate\Support\Str;
|
||||
use App\Services\BaseService;
|
||||
use function Safe\json_encode;
|
||||
use App\Models\Account\Account;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use App\ExportResources\Account\Account as AccountResource;
|
||||
|
||||
class JsonExportAccount extends BaseService
|
||||
{
|
||||
/** @var string */
|
||||
protected $tempFileName;
|
||||
|
||||
/**
|
||||
* Get the validation rules that apply to the service.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'account_id' => 'required|integer|exists:accounts,id',
|
||||
'user_id' => 'required|integer|exists:users,id',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Export account as Json.
|
||||
*
|
||||
* @param array $data
|
||||
* @return string
|
||||
*/
|
||||
public function execute(array $data): string
|
||||
{
|
||||
$this->validate($data);
|
||||
|
||||
$user = User::findOrFail($data['user_id']);
|
||||
|
||||
$this->tempFileName = 'temp/'.Str::random(40).'.json';
|
||||
|
||||
$this->writeExport($data, $user);
|
||||
|
||||
return $this->tempFileName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Export data in temp file.
|
||||
*
|
||||
* @param array $data
|
||||
* @param User $user
|
||||
*/
|
||||
private function writeExport(array $data, User $user)
|
||||
{
|
||||
$result = [];
|
||||
$result['version'] = '1.0-preview.1';
|
||||
$result['app_version'] = config('monica.app_version');
|
||||
$result['export_date'] = now();
|
||||
$result['url'] = config('app.url');
|
||||
$result['exported_by'] = $user->uuid;
|
||||
$result['account'] = $this->exportAccount($data);
|
||||
|
||||
$this->writeToTempFile(json_encode($result, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_INVALID_UTF8_IGNORE | JSON_UNESCAPED_SLASHES));
|
||||
}
|
||||
|
||||
/**
|
||||
* Write to a temp file.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function writeToTempFile(string $sql)
|
||||
{
|
||||
Storage::disk('local')
|
||||
->append($this->tempFileName, $sql);
|
||||
}
|
||||
|
||||
/**
|
||||
* Export the Account table.
|
||||
*
|
||||
* @param array $data
|
||||
* @return mixed
|
||||
*/
|
||||
private function exportAccount(array $data)
|
||||
{
|
||||
$account = Account::find($data['account_id']);
|
||||
|
||||
$exporter = new AccountResource($account);
|
||||
|
||||
return $exporter->resolve();
|
||||
}
|
||||
}
|
||||
180
app/Services/Account/Settings/ResetAccount.php
Normal file
180
app/Services/Account/Settings/ResetAccount.php
Normal file
@@ -0,0 +1,180 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Account\Settings;
|
||||
|
||||
use App\Services\BaseService;
|
||||
use App\Models\Account\Account;
|
||||
use App\Services\QueuableService;
|
||||
use App\Services\DispatchableService;
|
||||
use App\Services\Contact\Contact\DestroyContact;
|
||||
|
||||
class ResetAccount extends BaseService implements QueuableService
|
||||
{
|
||||
use DispatchableService;
|
||||
|
||||
/**
|
||||
* Get the validation rules that apply to the service.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'account_id' => 'required|integer|exists:accounts,id',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the account.
|
||||
*
|
||||
* @param array $data
|
||||
* @return void
|
||||
*/
|
||||
public function handle(array $data): void
|
||||
{
|
||||
$this->validate($data);
|
||||
|
||||
$account = Account::find($data['account_id']);
|
||||
|
||||
$this->destroyCompanies($account);
|
||||
|
||||
$this->destroyDays($account);
|
||||
|
||||
$this->destroyPlaces($account);
|
||||
|
||||
$this->destroyDocuments($account);
|
||||
|
||||
$this->destroyPhotos($account);
|
||||
|
||||
$this->destroyJournalEntries($account);
|
||||
|
||||
$this->destroyImportJobs($account);
|
||||
|
||||
$this->destroyContacts($account);
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroy the companies.
|
||||
*
|
||||
* @param Account $account
|
||||
* @return void
|
||||
*/
|
||||
private function destroyCompanies(Account $account)
|
||||
{
|
||||
$companies = $account->companies;
|
||||
foreach ($companies as $company) {
|
||||
$company->delete();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroy the days.
|
||||
*
|
||||
* @param Account $account
|
||||
* @return void
|
||||
*/
|
||||
private function destroyDays(Account $account)
|
||||
{
|
||||
$days = $account->days;
|
||||
foreach ($days as $day) {
|
||||
$day->delete();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroy the places.
|
||||
*
|
||||
* @param Account $account
|
||||
* @return void
|
||||
*/
|
||||
private function destroyPlaces(Account $account)
|
||||
{
|
||||
$places = $account->places;
|
||||
foreach ($places as $place) {
|
||||
$place->delete();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroy the documents.
|
||||
*
|
||||
* @param Account $account
|
||||
* @return void
|
||||
*/
|
||||
private function destroyDocuments(Account $account)
|
||||
{
|
||||
app(DestroyAllDocuments::class)->execute([
|
||||
'account_id' => $account->id,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroy the photos.
|
||||
*
|
||||
* @param Account $account
|
||||
* @return void
|
||||
*/
|
||||
private function destroyPhotos(Account $account)
|
||||
{
|
||||
app(DestroyAllPhotos::class)->execute([
|
||||
'account_id' => $account->id,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroy the journal entries associated with all the contacts of this
|
||||
* account.
|
||||
*
|
||||
* @param Account $account
|
||||
* @return void
|
||||
*/
|
||||
private function destroyJournalEntries(Account $account)
|
||||
{
|
||||
$entries = $account->entries;
|
||||
foreach ($entries as $entry) {
|
||||
$entry->delete();
|
||||
}
|
||||
|
||||
$activities = $account->activities;
|
||||
foreach ($activities as $activity) {
|
||||
$entries = $activity->journalEntries;
|
||||
foreach ($entries as $entry) {
|
||||
$entry->delete();
|
||||
}
|
||||
|
||||
$activity->delete();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroy the import jobs.
|
||||
*
|
||||
* @param Account $account
|
||||
* @return void
|
||||
*/
|
||||
private function destroyImportJobs(Account $account)
|
||||
{
|
||||
$importjobs = $account->importjobs;
|
||||
foreach ($importjobs as $importjob) {
|
||||
$importjob->delete();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroy all the contacts associated with this account.
|
||||
*
|
||||
* @param Account $account
|
||||
* @return void
|
||||
*/
|
||||
private function destroyContacts(Account $account)
|
||||
{
|
||||
$contacts = $account->contacts;
|
||||
foreach ($contacts as $contact) {
|
||||
DestroyContact::dispatchSync([
|
||||
'account_id' => $contact->account_id,
|
||||
'contact_id' => $contact->id,
|
||||
'force_delete' => true,
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
1373
app/Services/Account/Settings/SqlExportAccount.php
Normal file
1373
app/Services/Account/Settings/SqlExportAccount.php
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,99 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Auth\Population;
|
||||
|
||||
use App\Services\BaseService;
|
||||
use App\Models\Account\Account;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Database\QueryException;
|
||||
use App\Models\Contact\ContactFieldType;
|
||||
|
||||
/**
|
||||
* Populate the contact field types table for a given account.
|
||||
* This is typically done when a new account is created.
|
||||
*/
|
||||
class PopulateContactFieldTypesTable extends BaseService
|
||||
{
|
||||
/**
|
||||
* Get the validation rules that apply to the service.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'account_id' => 'required|integer|exists:accounts,id',
|
||||
'migrate_existing_data' => 'required|boolean',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the service.
|
||||
*
|
||||
* @param array $data
|
||||
* @return bool
|
||||
*/
|
||||
public function execute(array $data): bool
|
||||
{
|
||||
$this->createEntries($data);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create contact field type entries.
|
||||
*
|
||||
* @param array $data
|
||||
* @return void
|
||||
*/
|
||||
private function createEntries($data)
|
||||
{
|
||||
$defaultContactFieldTypes = $this->getDefaultContactFieldTypes($data);
|
||||
|
||||
foreach ($defaultContactFieldTypes as $defaultContactFieldType) {
|
||||
$this->createEntry($defaultContactFieldType, $data);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the default contact field types.
|
||||
*
|
||||
* @param array $data
|
||||
* @return Collection
|
||||
*
|
||||
* @throws QueryException if the query does not run for some reasons.
|
||||
*/
|
||||
private function getDefaultContactFieldTypes($data)
|
||||
{
|
||||
if ($data['migrate_existing_data'] == 1) {
|
||||
$defaultContactFieldTypes = DB::table('default_contact_field_types')
|
||||
->get();
|
||||
} else {
|
||||
$defaultContactFieldTypes = DB::table('default_contact_field_types')
|
||||
->where('migrated', 0)
|
||||
->get();
|
||||
}
|
||||
|
||||
return $defaultContactFieldTypes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an entry in the life event category table.
|
||||
*
|
||||
* @param object $defaultContactFieldType
|
||||
* @param array $data
|
||||
* @return void
|
||||
*/
|
||||
private function createEntry($defaultContactFieldType, $data)
|
||||
{
|
||||
ContactFieldType::create([
|
||||
'account_id' => $data['account_id'],
|
||||
'name' => $defaultContactFieldType->name,
|
||||
'fontawesome_icon' => (is_null($defaultContactFieldType->fontawesome_icon) ? null : $defaultContactFieldType->fontawesome_icon),
|
||||
'protocol' => (is_null($defaultContactFieldType->protocol) ? null : $defaultContactFieldType->protocol),
|
||||
'delible' => $defaultContactFieldType->delible,
|
||||
'type' => (is_null($defaultContactFieldType->type) ? null : $defaultContactFieldType->type),
|
||||
]);
|
||||
}
|
||||
}
|
||||
170
app/Services/Auth/Population/PopulateLifeEventsTable.php
Normal file
170
app/Services/Auth/Population/PopulateLifeEventsTable.php
Normal file
@@ -0,0 +1,170 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Auth\Population;
|
||||
|
||||
use App\Services\BaseService;
|
||||
use App\Models\Account\Account;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\App;
|
||||
use App\Models\Contact\LifeEventType;
|
||||
use Illuminate\Database\QueryException;
|
||||
use App\Models\Contact\LifeEventCategory;
|
||||
|
||||
/**
|
||||
* Populate life event types and life event categories for a given account.
|
||||
* This is typically done when a new account is created.
|
||||
*/
|
||||
class PopulateLifeEventsTable extends BaseService
|
||||
{
|
||||
/**
|
||||
* Get the validation rules that apply to the service.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'account_id' => 'required|integer|exists:accounts,id',
|
||||
'migrate_existing_data' => 'required|boolean',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* The data needed for the query to be executed.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $data;
|
||||
|
||||
/**
|
||||
* Execute the service.
|
||||
*
|
||||
* @param array $givenData
|
||||
* @return bool
|
||||
*/
|
||||
public function execute(array $givenData): bool
|
||||
{
|
||||
$this->data = $givenData;
|
||||
|
||||
if (! $this->validate($this->data)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$locale = $this->getLocaleOfAccount($this->data['account_id']);
|
||||
if (is_null($locale)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->createEntries($locale);
|
||||
|
||||
$this->markTableAsMigrated();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the locale associated with the account.
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
private function getLocaleOfAccount($accountId)
|
||||
{
|
||||
// get the account
|
||||
$account = Account::findOrFail($accountId);
|
||||
|
||||
return $account->getFirstLocale();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create life event category and life event type entries.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function createEntries($locale)
|
||||
{
|
||||
App::setLocale($locale);
|
||||
|
||||
$defaultLifeEventCategories = $this->getDefaultLifeEventCategories();
|
||||
|
||||
foreach ($defaultLifeEventCategories as $defaultLifeEventCategory) {
|
||||
$lifeEventCategory = $this->feedLifeEventCategory($defaultLifeEventCategory);
|
||||
|
||||
$defaultLifeEventTypes = DB::table('default_life_event_types')
|
||||
->where('default_life_event_category_id', $defaultLifeEventCategory->id)
|
||||
->get();
|
||||
|
||||
foreach ($defaultLifeEventTypes as $defaultLifeEventType) {
|
||||
$this->feedLifeEventType($defaultLifeEventType, $lifeEventCategory);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the default life event categories.
|
||||
*
|
||||
* @return Collection
|
||||
*
|
||||
* @throws QueryException if the query does not run for some reasons.
|
||||
*/
|
||||
private function getDefaultLifeEventCategories()
|
||||
{
|
||||
if ($this->data['migrate_existing_data'] == 1) {
|
||||
$defaultLifeEventCategories = DB::table('default_life_event_categories')
|
||||
->get();
|
||||
} else {
|
||||
$defaultLifeEventCategories = DB::table('default_life_event_categories')
|
||||
->where('migrated', 0)
|
||||
->get();
|
||||
}
|
||||
|
||||
return $defaultLifeEventCategories;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an entry in the life event category table.
|
||||
*
|
||||
* @param object $defaultLifeEventCategory
|
||||
* @return LifeEventCategory
|
||||
*/
|
||||
private function feedLifeEventCategory($defaultLifeEventCategory): LifeEventCategory
|
||||
{
|
||||
return LifeEventCategory::create([
|
||||
'account_id' => $this->data['account_id'],
|
||||
'name' => trans('settings.personalization_life_event_category_'.$defaultLifeEventCategory->translation_key),
|
||||
'core_monica_data' => true,
|
||||
'default_life_event_category_key' => $defaultLifeEventCategory->translation_key,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an entry in the life event type table.
|
||||
*
|
||||
* @param object $defaultLifeEventType
|
||||
* @return void
|
||||
*/
|
||||
private function feedLifeEventType($defaultLifeEventType, $lifeEventCategory)
|
||||
{
|
||||
LifeEventType::create([
|
||||
'account_id' => $this->data['account_id'],
|
||||
'life_event_category_id' => $lifeEventCategory->id,
|
||||
'core_monica_data' => true,
|
||||
'specific_information_structure' => $defaultLifeEventType->specific_information_structure,
|
||||
'default_life_event_type_key' => $defaultLifeEventType->translation_key,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Mark the table as migrated.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function markTableAsMigrated()
|
||||
{
|
||||
DB::table('default_life_event_categories')
|
||||
->update(['migrated' => 1]);
|
||||
|
||||
DB::table('default_life_event_types')
|
||||
->update(['migrated' => 1]);
|
||||
}
|
||||
}
|
||||
107
app/Services/Auth/Population/PopulateModulesTable.php
Normal file
107
app/Services/Auth/Population/PopulateModulesTable.php
Normal file
@@ -0,0 +1,107 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Auth\Population;
|
||||
|
||||
use App\Models\User\Module;
|
||||
use App\Services\BaseService;
|
||||
use App\Models\Account\Account;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Database\QueryException;
|
||||
|
||||
/**
|
||||
* Populate the modules table for a given account.
|
||||
*/
|
||||
class PopulateModulesTable extends BaseService
|
||||
{
|
||||
/**
|
||||
* Get the validation rules that apply to the service.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'account_id' => 'required|integer|exists:accounts,id',
|
||||
'migrate_existing_data' => 'required|boolean',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* The data needed for the query to be executed.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $data;
|
||||
|
||||
/**
|
||||
* Execute the service.
|
||||
*
|
||||
* @param array $givenData
|
||||
* @return bool
|
||||
*/
|
||||
public function execute(array $givenData): bool
|
||||
{
|
||||
$this->data = $givenData;
|
||||
|
||||
if (! $this->validate($this->data)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->createEntries();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create modules entries.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function createEntries()
|
||||
{
|
||||
$defaultModules = $this->getDefaultModules();
|
||||
|
||||
foreach ($defaultModules as $defaultModule) {
|
||||
$this->feedModule($defaultModule);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the default modules.
|
||||
*
|
||||
* @return Collection
|
||||
*
|
||||
* @throws QueryException if the query does not run for some reasons.
|
||||
*/
|
||||
private function getDefaultModules()
|
||||
{
|
||||
if ($this->data['migrate_existing_data'] == 1) {
|
||||
$defaultModules = DB::table('default_contact_modules')
|
||||
->get();
|
||||
} else {
|
||||
$defaultModules = DB::table('default_contact_modules')
|
||||
->where('migrated', 0)
|
||||
->get();
|
||||
}
|
||||
|
||||
return $defaultModules;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an entry in the module table.
|
||||
*
|
||||
* @param object $defaultModule
|
||||
* @return void
|
||||
*/
|
||||
private function feedModule($defaultModule)
|
||||
{
|
||||
Module::create([
|
||||
'account_id' => $this->data['account_id'],
|
||||
'key' => $defaultModule->key,
|
||||
'translation_key' => $defaultModule->translation_key,
|
||||
'delible' => $defaultModule->delible,
|
||||
'active' => $defaultModule->active,
|
||||
]);
|
||||
}
|
||||
}
|
||||
78
app/Services/BaseService.php
Normal file
78
app/Services/BaseService.php
Normal file
@@ -0,0 +1,78 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
|
||||
abstract class BaseService
|
||||
{
|
||||
/**
|
||||
* Get the validation rules that apply to the service.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate all datas to execute the service.
|
||||
*
|
||||
* @param array $data
|
||||
* @return bool
|
||||
*/
|
||||
public function validate(array $data): bool
|
||||
{
|
||||
Validator::make($data, $this->rules())
|
||||
->validate();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the value is empty or null.
|
||||
*
|
||||
* @param mixed $data
|
||||
* @param mixed $index
|
||||
* @return mixed
|
||||
*/
|
||||
public function nullOrValue($data, $index)
|
||||
{
|
||||
$value = Arr::get($data, $index, null);
|
||||
|
||||
return is_null($value) || $value === '' ? null : $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the value is empty or null and returns a date from a string.
|
||||
*
|
||||
* @param mixed $data
|
||||
* @param mixed $index
|
||||
* @return mixed
|
||||
*/
|
||||
public function nullOrDate($data, $index)
|
||||
{
|
||||
$value = Arr::get($data, $index, null);
|
||||
|
||||
return is_null($value) || $value === '' ? null : Carbon::parse($value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value if it's defined, or false otherwise.
|
||||
*
|
||||
* @param mixed $data
|
||||
* @param mixed $index
|
||||
* @return mixed
|
||||
*/
|
||||
public function valueOrFalse($data, $index)
|
||||
{
|
||||
if (empty($data[$index])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $data[$index];
|
||||
}
|
||||
}
|
||||
92
app/Services/Contact/Address/CreateAddress.php
Normal file
92
app/Services/Contact/Address/CreateAddress.php
Normal file
@@ -0,0 +1,92 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Contact\Address;
|
||||
|
||||
use App\Models\Account\Place;
|
||||
use App\Services\BaseService;
|
||||
use App\Models\Contact\Address;
|
||||
use App\Models\Contact\Contact;
|
||||
use App\Services\Account\Place\CreatePlace;
|
||||
use App\Services\Contact\Label\UpdateAddressLabels;
|
||||
|
||||
class CreateAddress extends BaseService
|
||||
{
|
||||
/**
|
||||
* Get the validation rules that apply to the service.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'account_id' => 'required|integer|exists:accounts,id',
|
||||
'contact_id' => 'required|integer|exists:contacts,id',
|
||||
'name' => 'nullable|string|max:255',
|
||||
'street' => 'nullable|string|max:255',
|
||||
'city' => 'nullable|string|max:255',
|
||||
'province' => 'nullable|string|max:255',
|
||||
'postal_code' => 'nullable|string|max:255',
|
||||
'country' => 'nullable|string|max:3',
|
||||
'latitude' => 'nullable|numeric',
|
||||
'longitude' => 'nullable|numeric',
|
||||
'labels' => 'nullable|array',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an address.
|
||||
*
|
||||
* @param array $data
|
||||
* @return Address
|
||||
*/
|
||||
public function execute(array $data): Address
|
||||
{
|
||||
$this->validate($data);
|
||||
|
||||
$contact = Contact::where('account_id', $data['account_id'])
|
||||
->findOrFail($data['contact_id']);
|
||||
|
||||
$contact->throwInactive();
|
||||
|
||||
$place = $this->createPlace($data);
|
||||
|
||||
$address = Address::create([
|
||||
'account_id' => $data['account_id'],
|
||||
'contact_id' => $data['contact_id'],
|
||||
'place_id' => $place->id,
|
||||
'name' => $this->nullOrValue($data, 'name'),
|
||||
]);
|
||||
|
||||
if ($labels = $this->nullOrValue($data, 'labels')) {
|
||||
app(UpdateAddressLabels::class)->execute([
|
||||
'account_id' => $data['account_id'],
|
||||
'address_id' => $address->id,
|
||||
'labels' => $labels,
|
||||
]);
|
||||
}
|
||||
|
||||
return $address;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a place for the given address.
|
||||
*
|
||||
* @param array $data
|
||||
* @return Place
|
||||
*/
|
||||
private function createPlace(array $data)
|
||||
{
|
||||
$request = [
|
||||
'account_id' => $data['account_id'],
|
||||
'street' => $this->nullOrValue($data, 'street'),
|
||||
'city' => $this->nullOrValue($data, 'city'),
|
||||
'province' => $this->nullOrValue($data, 'province'),
|
||||
'postal_code' => $this->nullOrValue($data, 'postal_code'),
|
||||
'country' => $this->nullOrValue($data, 'country'),
|
||||
'latitude' => $this->nullOrValue($data, 'latitude'),
|
||||
'longitude' => $this->nullOrValue($data, 'longitude'),
|
||||
];
|
||||
|
||||
return app(CreatePlace::class)->execute($request);
|
||||
}
|
||||
}
|
||||
48
app/Services/Contact/Address/DestroyAddress.php
Normal file
48
app/Services/Contact/Address/DestroyAddress.php
Normal file
@@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Contact\Address;
|
||||
|
||||
use App\Services\BaseService;
|
||||
use App\Models\Contact\Address;
|
||||
use App\Services\Account\Place\DestroyPlace;
|
||||
|
||||
class DestroyAddress extends BaseService
|
||||
{
|
||||
/**
|
||||
* Get the validation rules that apply to the service.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'account_id' => 'required|integer|exists:accounts,id',
|
||||
'address_id' => 'required|integer|exists:addresses,id',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroy an address.
|
||||
*
|
||||
* @param array $data
|
||||
* @return bool
|
||||
*/
|
||||
public function execute(array $data): bool
|
||||
{
|
||||
$this->validate($data);
|
||||
|
||||
$address = Address::where('account_id', $data['account_id'])
|
||||
->findOrFail($data['address_id']);
|
||||
|
||||
$address->contact->throwInactive();
|
||||
|
||||
app(DestroyPlace::class)->execute([
|
||||
'account_id' => $data['account_id'],
|
||||
'place_id' => $address->place_id,
|
||||
]);
|
||||
|
||||
$address->delete();
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
97
app/Services/Contact/Address/UpdateAddress.php
Normal file
97
app/Services/Contact/Address/UpdateAddress.php
Normal file
@@ -0,0 +1,97 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Contact\Address;
|
||||
|
||||
use App\Models\Account\Place;
|
||||
use App\Services\BaseService;
|
||||
use App\Models\Contact\Address;
|
||||
use App\Models\Contact\Contact;
|
||||
use App\Services\Account\Place\UpdatePlace;
|
||||
use App\Services\Contact\Label\UpdateAddressLabels;
|
||||
|
||||
class UpdateAddress extends BaseService
|
||||
{
|
||||
/**
|
||||
* Get the validation rules that apply to the service.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'account_id' => 'required|integer|exists:accounts,id',
|
||||
'contact_id' => 'required|integer|exists:contacts,id',
|
||||
'address_id' => 'required|integer|exists:addresses,id',
|
||||
'name' => 'nullable|string|max:255',
|
||||
'street' => 'nullable|string|max:255',
|
||||
'city' => 'nullable|string|max:255',
|
||||
'province' => 'nullable|string|max:255',
|
||||
'postal_code' => 'nullable|string|max:255',
|
||||
'country' => 'nullable|string|max:3',
|
||||
'latitude' => 'nullable|numeric',
|
||||
'longitude' => 'nullable|numeric',
|
||||
'labels' => 'nullable|array',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Update an address.
|
||||
*
|
||||
* @param array $data
|
||||
* @return Address
|
||||
*/
|
||||
public function execute(array $data): Address
|
||||
{
|
||||
$this->validate($data);
|
||||
|
||||
/** @var Address */
|
||||
$address = Address::where('account_id', $data['account_id'])
|
||||
->where('contact_id', $data['contact_id'])
|
||||
->findOrFail($data['address_id']);
|
||||
|
||||
$contact = Contact::where('account_id', $data['account_id'])
|
||||
->findOrFail($data['contact_id']);
|
||||
|
||||
$contact->throwInactive();
|
||||
|
||||
$this->updatePlace($data, $address);
|
||||
|
||||
$address->update([
|
||||
'name' => $this->nullOrValue($data, 'name'),
|
||||
]);
|
||||
|
||||
if ($labels = $this->nullOrValue($data, 'labels')) {
|
||||
app(UpdateAddressLabels::class)->execute([
|
||||
'account_id' => $data['account_id'],
|
||||
'address_id' => $address->id,
|
||||
'labels' => $labels,
|
||||
]);
|
||||
}
|
||||
|
||||
return $address;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a place for the given address.
|
||||
*
|
||||
* @param array $data
|
||||
* @param Address $address
|
||||
* @return Place
|
||||
*/
|
||||
private function updatePlace(array $data, Address $address)
|
||||
{
|
||||
$request = [
|
||||
'account_id' => $data['account_id'],
|
||||
'place_id' => $address->place_id,
|
||||
'street' => $this->nullOrValue($data, 'street'),
|
||||
'city' => $this->nullOrValue($data, 'city'),
|
||||
'province' => $this->nullOrValue($data, 'province'),
|
||||
'postal_code' => $this->nullOrValue($data, 'postal_code'),
|
||||
'country' => $this->nullOrValue($data, 'country'),
|
||||
'latitude' => $this->nullOrValue($data, 'latitude'),
|
||||
'longitude' => $this->nullOrValue($data, 'longitude'),
|
||||
];
|
||||
|
||||
return app(UpdatePlace::class)->execute($request);
|
||||
}
|
||||
}
|
||||
120
app/Services/Contact/Avatar/GenerateDefaultAvatar.php
Normal file
120
app/Services/Contact/Avatar/GenerateDefaultAvatar.php
Normal file
@@ -0,0 +1,120 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Contact\Avatar;
|
||||
|
||||
use Illuminate\Support\Str;
|
||||
use App\Services\BaseService;
|
||||
use App\Models\Contact\Contact;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
use Laravolt\Avatar\Facade as Avatar;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Illuminate\Contracts\Filesystem\FileNotFoundException;
|
||||
|
||||
class GenerateDefaultAvatar extends BaseService
|
||||
{
|
||||
/**
|
||||
* Get the validation rules that apply to the service.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'contact_id' => 'required|integer|exists:contacts,id',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate the default image for the avatar, based on the initals of the
|
||||
* contact and returns the filename.
|
||||
*
|
||||
* @param array $data
|
||||
* @return Contact
|
||||
*/
|
||||
public function execute(array $data)
|
||||
{
|
||||
$this->validate($data);
|
||||
|
||||
$contact = Contact::find($data['contact_id']);
|
||||
|
||||
$contact = $this->generateContactUUID($contact);
|
||||
|
||||
// delete existing default avatar
|
||||
$contact = $this->deleteExistingDefaultAvatar($contact);
|
||||
|
||||
// create new avatar
|
||||
$filename = $this->createNewAvatar($contact);
|
||||
|
||||
$contact->avatar_default_url = $filename;
|
||||
$contact->save();
|
||||
|
||||
Cache::forget('etag'.Str::before('?', $filename));
|
||||
|
||||
return $contact;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an uuid for the contact if it does not exist.
|
||||
*
|
||||
* @param Contact $contact
|
||||
* @return Contact
|
||||
*/
|
||||
private function generateContactUUID(Contact $contact)
|
||||
{
|
||||
if (! $contact->uuid) {
|
||||
$contact->uuid = Str::uuid()->toString();
|
||||
$contact->save();
|
||||
}
|
||||
|
||||
return $contact;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new avatar for the contact based on the name of the contact.
|
||||
*
|
||||
* @param Contact $contact
|
||||
* @return string
|
||||
*/
|
||||
private function createNewAvatar(Contact $contact)
|
||||
{
|
||||
$img = null;
|
||||
try {
|
||||
$img = Avatar::create($contact->name)
|
||||
->setBackground($contact->default_avatar_color)
|
||||
->getImageObject()
|
||||
->encode('jpg');
|
||||
|
||||
$filename = 'avatars/'.$contact->uuid.'.jpg';
|
||||
Storage::disk(config('filesystems.default'))
|
||||
->put($filename, $img, config('filesystems.default_visibility'));
|
||||
|
||||
// This will force the browser to reload the new avatar
|
||||
return $filename.'?'.now()->format('U');
|
||||
} finally {
|
||||
if ($img) {
|
||||
$img->destroy();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete the existing default avatar.
|
||||
*
|
||||
* @param Contact $contact
|
||||
* @return Contact
|
||||
*/
|
||||
private function deleteExistingDefaultAvatar(Contact $contact)
|
||||
{
|
||||
if ($contact->avatar_default_url !== null) {
|
||||
try {
|
||||
Storage::disk(config('filesystems.default'))
|
||||
->delete($contact->avatar_default_url);
|
||||
$contact->avatar_default_url = null;
|
||||
} catch (FileNotFoundException $e) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
|
||||
return $contact;
|
||||
}
|
||||
}
|
||||
53
app/Services/Contact/Avatar/GetAdorableAvatarURL.php
Normal file
53
app/Services/Contact/Avatar/GetAdorableAvatarURL.php
Normal file
@@ -0,0 +1,53 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Contact\Avatar;
|
||||
|
||||
use App\Services\BaseService;
|
||||
|
||||
class GetAdorableAvatarURL extends BaseService
|
||||
{
|
||||
/**
|
||||
* Get the validation rules that apply to the service.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'uuid' => 'required|string',
|
||||
'size' => 'nullable|integer|between:1,2000',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an url for an adorable avatar.
|
||||
* - http://avatars.adorable.io/ gives avatars based on a random string.
|
||||
*
|
||||
* @param array $data
|
||||
* @return string|null
|
||||
*/
|
||||
public function execute(array $data)
|
||||
{
|
||||
$this->validate($data);
|
||||
|
||||
$size = $this->size($data);
|
||||
|
||||
return $size.'/'.$data['uuid'].'.png';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the size for the avatar, based on a given parameter. Provides a
|
||||
* default otherwise.
|
||||
*
|
||||
* @param array $data
|
||||
* @return int
|
||||
*/
|
||||
private function size(array $data)
|
||||
{
|
||||
if (isset($data['size'])) {
|
||||
return $data['size'];
|
||||
}
|
||||
|
||||
return (int) config('monica.avatar_size');
|
||||
}
|
||||
}
|
||||
99
app/Services/Contact/Avatar/GetAvatarsFromInternet.php
Normal file
99
app/Services/Contact/Avatar/GetAvatarsFromInternet.php
Normal file
@@ -0,0 +1,99 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Contact\Avatar;
|
||||
|
||||
use Illuminate\Support\Str;
|
||||
use App\Services\BaseService;
|
||||
use App\Models\Contact\Contact;
|
||||
|
||||
class GetAvatarsFromInternet extends BaseService
|
||||
{
|
||||
/**
|
||||
* Get the validation rules that apply to the service.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'contact_id' => 'required|integer|exists:contacts,id',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Query both Gravatar and Adorable Avatars based on the email address of
|
||||
* the contact.
|
||||
*
|
||||
* - http://avatars.adorable.io/ gives avatars based on a random string.
|
||||
* This random string comes from the `avatar_adorable_uuid` field in the
|
||||
* Contact object.
|
||||
* - Gravatar only gives an avatar only if it's set.
|
||||
*
|
||||
* @param array $data
|
||||
* @return Contact
|
||||
*/
|
||||
public function execute(array $data): Contact
|
||||
{
|
||||
$this->validate($data);
|
||||
|
||||
$contact = Contact::findOrFail($data['contact_id']);
|
||||
|
||||
$contact = $this->getAdorable($contact);
|
||||
$contact = $this->getGravatar($contact);
|
||||
|
||||
return $contact;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate the UUID used to identify the contact in the Adorable service.
|
||||
*
|
||||
* @param Contact $contact
|
||||
* @return Contact
|
||||
*/
|
||||
private function generateUUID(Contact $contact)
|
||||
{
|
||||
if (empty($contact->avatar_adorable_uuid)) {
|
||||
$contact->avatar_adorable_uuid = Str::uuid()->toString();
|
||||
$contact->save();
|
||||
}
|
||||
|
||||
return $contact;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the adorable avatar.
|
||||
*
|
||||
* @param Contact $contact
|
||||
* @return Contact
|
||||
*/
|
||||
private function getAdorable(Contact $contact)
|
||||
{
|
||||
// prevent timestamp update
|
||||
$timestamps = $contact->timestamps;
|
||||
$contact->timestamps = false;
|
||||
|
||||
$contact = $this->generateUUID($contact);
|
||||
$contact->avatar_adorable_url = app(GetAdorableAvatarURL::class)->execute([
|
||||
'uuid' => $contact->avatar_adorable_uuid,
|
||||
'size' => 200,
|
||||
]);
|
||||
$contact->save();
|
||||
|
||||
$contact->timestamps = $timestamps;
|
||||
|
||||
return $contact;
|
||||
}
|
||||
|
||||
/**
|
||||
* Query Gravatar (if it exists) for the contact's email address.
|
||||
*
|
||||
* @param Contact $contact
|
||||
* @return Contact
|
||||
*/
|
||||
private function getGravatar(Contact $contact)
|
||||
{
|
||||
return app(GetGravatar::class)->execute([
|
||||
'contact_id' => $contact->id,
|
||||
]);
|
||||
}
|
||||
}
|
||||
110
app/Services/Contact/Avatar/GetGravatar.php
Normal file
110
app/Services/Contact/Avatar/GetGravatar.php
Normal file
@@ -0,0 +1,110 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Contact\Avatar;
|
||||
|
||||
use App\Services\BaseService;
|
||||
use App\Models\Contact\Contact;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
use Illuminate\Database\Eloquent\ModelNotFoundException;
|
||||
|
||||
class GetGravatar extends BaseService
|
||||
{
|
||||
/**
|
||||
* Get the validation rules that apply to the service.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'contact_id' => 'required|integer|exists:contacts,id',
|
||||
];
|
||||
}
|
||||
|
||||
public function execute(array $data): Contact
|
||||
{
|
||||
$this->validate($data);
|
||||
|
||||
/** @var Contact */
|
||||
$contact = Contact::findOrFail($data['contact_id']);
|
||||
|
||||
// prevent timestamp update
|
||||
$timestamps = $contact->timestamps;
|
||||
$contact->timestamps = false;
|
||||
|
||||
$contact = $this->getGravatar($contact);
|
||||
$contact->save();
|
||||
|
||||
$contact->timestamps = $timestamps;
|
||||
|
||||
return $contact;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the emails of the contact, based on the contact fields.
|
||||
*
|
||||
* @param Contact $contact
|
||||
* @return Collection
|
||||
*/
|
||||
private function getEmails(Contact $contact)
|
||||
{
|
||||
$emails = collect();
|
||||
|
||||
$contactFields = $contact->contactFields()
|
||||
->email()
|
||||
->get();
|
||||
foreach ($contactFields as $contactField) {
|
||||
try {
|
||||
$email = $contactField->data;
|
||||
|
||||
Validator::make(['email' => $email], ['email' => 'email'])
|
||||
->validate();
|
||||
|
||||
$emails->push($email);
|
||||
} catch (ModelNotFoundException $e) {
|
||||
// Not found
|
||||
} catch (ValidationException $e) {
|
||||
// Not an email
|
||||
}
|
||||
}
|
||||
|
||||
return $emails;
|
||||
}
|
||||
|
||||
/**
|
||||
* Query Gravatar (if it exists) for the contact's email address.
|
||||
*
|
||||
* @param Contact $contact
|
||||
* @return Contact
|
||||
*/
|
||||
private function getGravatar(Contact $contact)
|
||||
{
|
||||
$emails = $this->getEmails($contact);
|
||||
$gravatarUrl = null;
|
||||
|
||||
foreach ($emails as $email) {
|
||||
$gravatarUrl = app(GetGravatarURL::class)->execute([
|
||||
'email' => $email,
|
||||
'size' => config('monica.avatar_size'),
|
||||
]);
|
||||
if ($gravatarUrl) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ($gravatarUrl) {
|
||||
$contact->avatar_gravatar_url = $gravatarUrl;
|
||||
} else {
|
||||
// in this case we need to make sure that we reset the gravatar URL
|
||||
$contact->avatar_gravatar_url = null;
|
||||
|
||||
if ($contact->avatar_source == 'gravatar') {
|
||||
$contact->avatar_source = 'adorable';
|
||||
}
|
||||
}
|
||||
|
||||
return $contact;
|
||||
}
|
||||
}
|
||||
77
app/Services/Contact/Avatar/GetGravatarURL.php
Normal file
77
app/Services/Contact/Avatar/GetGravatarURL.php
Normal file
@@ -0,0 +1,77 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Contact\Avatar;
|
||||
|
||||
use App\Services\BaseService;
|
||||
use Illuminate\Support\Facades\App;
|
||||
use Creativeorange\Gravatar\Facades\Gravatar;
|
||||
|
||||
class GetGravatarURL extends BaseService
|
||||
{
|
||||
/**
|
||||
* Get the validation rules that apply to the service.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'email' => 'required|email',
|
||||
'size' => 'nullable|integer|between:1,2000',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Gravatar, if it exists.
|
||||
*
|
||||
* @param array $data
|
||||
* @return string|null
|
||||
*/
|
||||
public function execute(array $data): ?string
|
||||
{
|
||||
$this->validate($data);
|
||||
|
||||
if ($this->exists($data)) {
|
||||
$size = $this->size($data);
|
||||
|
||||
return Gravatar::get($data['email'], [
|
||||
'size' => $size,
|
||||
'secure' => App::environment('production'),
|
||||
]);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test given email.
|
||||
*
|
||||
* @param array $data
|
||||
* @return bool
|
||||
*/
|
||||
private function exists(array $data)
|
||||
{
|
||||
try {
|
||||
return Gravatar::exists($data['email']);
|
||||
} catch (\Exception $e) {
|
||||
// catch invalid email
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the size for the gravatar, based on a given parameter. Provides a
|
||||
* default otherwise.
|
||||
*
|
||||
* @param array $data
|
||||
* @return int
|
||||
*/
|
||||
private function size(array $data)
|
||||
{
|
||||
if (isset($data['size'])) {
|
||||
return $data['size'];
|
||||
}
|
||||
|
||||
return (int) config('monica.avatar_size');
|
||||
}
|
||||
}
|
||||
75
app/Services/Contact/Avatar/UpdateAvatar.php
Normal file
75
app/Services/Contact/Avatar/UpdateAvatar.php
Normal file
@@ -0,0 +1,75 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Contact\Avatar;
|
||||
|
||||
use App\Models\Account\Photo;
|
||||
use App\Services\BaseService;
|
||||
use App\Models\Contact\Contact;
|
||||
use Illuminate\Validation\Rule;
|
||||
|
||||
/**
|
||||
* Update the avatar of the contact.
|
||||
*/
|
||||
class UpdateAvatar extends BaseService
|
||||
{
|
||||
/**
|
||||
* Get the validation rules that apply to the service.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'account_id' => 'required|integer|exists:accounts,id',
|
||||
'contact_id' => 'required|integer|exists:contacts,id',
|
||||
'source' => [
|
||||
'required',
|
||||
Rule::in([
|
||||
'default',
|
||||
'adorable',
|
||||
'gravatar',
|
||||
'photo',
|
||||
]),
|
||||
],
|
||||
'photo_id' => 'required_if:source,photo|integer|exists:photos,id',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Update message in a conversation.
|
||||
*
|
||||
* @param array $data
|
||||
* @return Contact
|
||||
*/
|
||||
public function execute(array $data): Contact
|
||||
{
|
||||
$this->validate($data);
|
||||
|
||||
/** @var Contact */
|
||||
$contact = Contact::where('account_id', $data['account_id'])
|
||||
->findOrFail($data['contact_id']);
|
||||
|
||||
$contact->throwInactive();
|
||||
|
||||
if (isset($data['photo_id'])) {
|
||||
Photo::where('account_id', $data['account_id'])
|
||||
->findOrFail($data['photo_id']);
|
||||
}
|
||||
|
||||
$contact->avatar_source = $data['source'];
|
||||
switch ($contact->avatar_source) {
|
||||
case 'photo':
|
||||
// in case of a photo, set the photo as the avatar
|
||||
$contact->avatar_photo_id = $this->nullOrValue($data, 'photo_id');
|
||||
$contact->photos()->syncWithoutDetaching([$this->nullOrValue($data, 'photo_id')]);
|
||||
break;
|
||||
default:
|
||||
$contact->avatar_photo_id = null;
|
||||
break;
|
||||
}
|
||||
|
||||
$contact->save();
|
||||
|
||||
return $contact;
|
||||
}
|
||||
}
|
||||
94
app/Services/Contact/Call/CreateCall.php
Normal file
94
app/Services/Contact/Call/CreateCall.php
Normal file
@@ -0,0 +1,94 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Contact\Call;
|
||||
|
||||
use Illuminate\Support\Arr;
|
||||
use App\Models\Contact\Call;
|
||||
use App\Services\BaseService;
|
||||
use App\Models\Contact\Contact;
|
||||
use App\Models\Instance\Emotion\Emotion;
|
||||
|
||||
class CreateCall extends BaseService
|
||||
{
|
||||
/**
|
||||
* Get the validation rules that apply to the service.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'account_id' => 'required|integer|exists:accounts,id',
|
||||
'contact_id' => 'required|integer',
|
||||
'called_at' => 'required|date',
|
||||
'content' => 'nullable|string',
|
||||
'contact_called' => 'nullable|boolean',
|
||||
'emotions' => 'nullable|array',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a call.
|
||||
*
|
||||
* @param array $data
|
||||
* @return Call
|
||||
*/
|
||||
public function execute(array $data): Call
|
||||
{
|
||||
$this->validate($data);
|
||||
|
||||
$contact = Contact::where('account_id', $data['account_id'])
|
||||
->findOrFail($data['contact_id']);
|
||||
|
||||
$contact->throwInactive();
|
||||
|
||||
// emotions array is left out as they are not attached during this call
|
||||
$call = Call::create(Arr::except($data, ['emotions']));
|
||||
|
||||
$this->updateLastCallInfo($contact, $call);
|
||||
|
||||
if (! empty($data['emotions'])) {
|
||||
if ($data['emotions'] != '') {
|
||||
$this->addEmotions($data['emotions'], $call);
|
||||
}
|
||||
}
|
||||
|
||||
return $call;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add emotions to the call.
|
||||
*
|
||||
* @param array $emotions
|
||||
* @param Call $call
|
||||
* @return void
|
||||
*/
|
||||
private function addEmotions(array $emotions, Call $call)
|
||||
{
|
||||
foreach ($emotions as $emotionId) {
|
||||
$emotion = Emotion::findOrFail($emotionId);
|
||||
$call->emotions()->syncWithoutDetaching([$emotion->id => [
|
||||
'account_id' => $call->account_id,
|
||||
'contact_id' => $call->contact_id,
|
||||
]]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update last call information of the contact.
|
||||
*
|
||||
* @param Contact $contact
|
||||
* @param Call $call
|
||||
* @return void
|
||||
*/
|
||||
private function updateLastCallInfo(Contact $contact, Call $call)
|
||||
{
|
||||
if (is_null($contact->last_talked_to)) {
|
||||
$contact->last_talked_to = $call->called_at;
|
||||
} else {
|
||||
$contact->last_talked_to = $contact->last_talked_to->max($call->called_at);
|
||||
}
|
||||
|
||||
$contact->save();
|
||||
}
|
||||
}
|
||||
64
app/Services/Contact/Call/DestroyCall.php
Normal file
64
app/Services/Contact/Call/DestroyCall.php
Normal file
@@ -0,0 +1,64 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Contact\Call;
|
||||
|
||||
use App\Models\Contact\Call;
|
||||
use App\Services\BaseService;
|
||||
use App\Models\Contact\Contact;
|
||||
|
||||
class DestroyCall extends BaseService
|
||||
{
|
||||
/**
|
||||
* Get the validation rules that apply to the service.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'account_id' => 'required|integer|exists:accounts,id',
|
||||
'call_id' => 'required|integer',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroy a call.
|
||||
*
|
||||
* @param array $data
|
||||
* @return bool
|
||||
*/
|
||||
public function execute(array $data): bool
|
||||
{
|
||||
$this->validate($data);
|
||||
|
||||
$call = Call::where('account_id', $data['account_id'])
|
||||
->findOrFail($data['call_id']);
|
||||
|
||||
$contact = $call->contact;
|
||||
|
||||
$contact->throwInactive();
|
||||
|
||||
// delete all associations with emotions
|
||||
$call->emotions()->sync([]);
|
||||
|
||||
$call->delete();
|
||||
|
||||
$this->updateLastCallInfo($contact);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update last call information of the contact.
|
||||
*
|
||||
* @param Contact $contact
|
||||
* @return void
|
||||
*/
|
||||
private function updateLastCallInfo(Contact $contact)
|
||||
{
|
||||
// look for all the calls of the contact and take the most recent call
|
||||
// as the one we just deleted could have been the most recent call
|
||||
$contact->last_talked_to = optional($contact->calls->first())->called_at;
|
||||
$contact->save();
|
||||
}
|
||||
}
|
||||
102
app/Services/Contact/Call/UpdateCall.php
Normal file
102
app/Services/Contact/Call/UpdateCall.php
Normal file
@@ -0,0 +1,102 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Contact\Call;
|
||||
|
||||
use App\Models\Contact\Call;
|
||||
use App\Services\BaseService;
|
||||
use App\Models\Instance\Emotion\Emotion;
|
||||
|
||||
class UpdateCall extends BaseService
|
||||
{
|
||||
/**
|
||||
* Get the validation rules that apply to the service.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'account_id' => 'required|integer|exists:accounts,id',
|
||||
'call_id' => 'required|integer|exists:calls,id',
|
||||
'called_at' => 'required|date',
|
||||
'content' => 'nullable|string',
|
||||
'contact_called' => 'nullable|boolean',
|
||||
'emotions' => 'nullable|array',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Update a call.
|
||||
*
|
||||
* @param array $data
|
||||
* @return Call
|
||||
*/
|
||||
public function execute(array $data): Call
|
||||
{
|
||||
$this->validate($data);
|
||||
|
||||
/** @var Call */
|
||||
$call = Call::where('account_id', $data['account_id'])
|
||||
->findOrFail($data['call_id']);
|
||||
|
||||
$call->contact->throwInactive();
|
||||
|
||||
$call->update([
|
||||
'called_at' => $data['called_at'],
|
||||
'content' => (empty($data['content']) ? null : $data['content']),
|
||||
'contact_called' => (empty($data['contact_called']) ? null : $data['contact_called']),
|
||||
]);
|
||||
|
||||
// emotions array is left out as they are not attached during this call
|
||||
if (! empty($data['emotions'])) {
|
||||
if ($data['emotions'] != '') {
|
||||
$this->addEmotions($data['emotions'], $call);
|
||||
}
|
||||
}
|
||||
|
||||
$this->updateLastCallInfo($call);
|
||||
|
||||
return $call;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add emotions to the call.
|
||||
*
|
||||
* @param array $emotions
|
||||
* @param Call $call
|
||||
* @return void
|
||||
*/
|
||||
private function addEmotions(array $emotions, Call $call)
|
||||
{
|
||||
// reset current emotions
|
||||
$call->emotions()->sync([]);
|
||||
|
||||
// saving new emotions
|
||||
foreach ($emotions as $emotionId) {
|
||||
$emotion = Emotion::findOrFail($emotionId);
|
||||
$call->emotions()->syncWithoutDetaching([$emotion->id => [
|
||||
'account_id' => $call->account_id,
|
||||
'contact_id' => $call->contact_id,
|
||||
]]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update last call information of the contact.
|
||||
*
|
||||
* @param Call $call
|
||||
* @return void
|
||||
*/
|
||||
private function updateLastCallInfo(Call $call)
|
||||
{
|
||||
/** @var \App\Models\Contact\Contact */
|
||||
$contact = $call->contact;
|
||||
if (is_null($contact->last_talked_to)) {
|
||||
$contact->last_talked_to = $call->called_at;
|
||||
} else {
|
||||
$contact->last_talked_to = $contact->last_talked_to->max($call->called_at);
|
||||
}
|
||||
|
||||
$contact->save();
|
||||
}
|
||||
}
|
||||
262
app/Services/Contact/Contact/CreateContact.php
Normal file
262
app/Services/Contact/Contact/CreateContact.php
Normal file
@@ -0,0 +1,262 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Contact\Contact;
|
||||
|
||||
use Ramsey\Uuid\Uuid;
|
||||
use App\Models\User\User;
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Str;
|
||||
use App\Services\BaseService;
|
||||
use App\Helpers\AccountHelper;
|
||||
use function Safe\json_encode;
|
||||
use App\Models\Account\Account;
|
||||
use App\Models\Contact\Contact;
|
||||
use App\Models\Account\AddressBook;
|
||||
use App\Jobs\AuditLog\LogAccountAudit;
|
||||
use App\Models\Contact\ContactFieldType;
|
||||
use App\Jobs\Avatars\GenerateDefaultAvatar;
|
||||
use App\Jobs\Avatars\GetAvatarsFromInternet;
|
||||
use App\Services\Contact\ContactField\CreateContactField;
|
||||
|
||||
class CreateContact extends BaseService
|
||||
{
|
||||
/**
|
||||
* Get the validation rules that apply to the service.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'account_id' => 'required|integer|exists:accounts,id',
|
||||
'author_id' => 'required|integer|exists:users,id',
|
||||
'uuid' => 'nullable|string',
|
||||
'address_book_id' => 'nullable|integer|exists:addressbooks,id',
|
||||
'first_name' => 'required|string|max:255',
|
||||
'middle_name' => 'nullable|string|max:255',
|
||||
'last_name' => 'nullable|string|max:255',
|
||||
'nickname' => 'nullable|string|max:255',
|
||||
'email' => 'nullable|string|max:255',
|
||||
'gender_id' => 'nullable|integer|exists:genders,id',
|
||||
'description' => 'nullable|string|max:255',
|
||||
'is_partial' => 'nullable|boolean',
|
||||
'is_birthdate_known' => 'required|boolean',
|
||||
'birthdate_day' => 'nullable|integer',
|
||||
'birthdate_month' => 'nullable|integer',
|
||||
'birthdate_year' => 'nullable|integer',
|
||||
'birthdate_is_age_based' => 'nullable|boolean',
|
||||
'birthdate_age' => 'nullable|integer',
|
||||
'birthdate_add_reminder' => 'nullable|boolean',
|
||||
'is_deceased' => 'required|boolean',
|
||||
'is_deceased_date_known' => 'required|boolean',
|
||||
'deceased_date_day' => 'nullable|integer',
|
||||
'deceased_date_month' => 'nullable|integer',
|
||||
'deceased_date_year' => 'nullable|integer',
|
||||
'deceased_date_add_reminder' => 'nullable|boolean',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a contact.
|
||||
*
|
||||
* @param array $data
|
||||
* @return Contact
|
||||
*/
|
||||
public function execute(array $data): Contact
|
||||
{
|
||||
$this->validate($data);
|
||||
|
||||
$account = Account::find($data['account_id']);
|
||||
if (AccountHelper::hasReachedContactLimit($account)
|
||||
&& AccountHelper::hasLimitations($account)
|
||||
&& ! $account->legacy_free_plan_unlimited_contacts) {
|
||||
abort(402);
|
||||
}
|
||||
|
||||
if (Arr::get($data, 'address_book_id')) {
|
||||
AddressBook::where('account_id', $data['account_id'])
|
||||
->findOrFail($data['address_book_id']);
|
||||
}
|
||||
|
||||
$contact = $this->create($data);
|
||||
|
||||
$this->updateBirthDayInformation($data, $contact);
|
||||
$this->updateDeceasedInformation($data, $contact);
|
||||
$this->updateEmail($data, $contact);
|
||||
$this->generateUUID($contact);
|
||||
$this->addAvatars($contact);
|
||||
|
||||
$this->log($data, $contact);
|
||||
|
||||
// we query the DB again to fill the object with all the new properties
|
||||
$contact->refresh();
|
||||
|
||||
return $contact;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the contact.
|
||||
*
|
||||
* @param array $data
|
||||
* @return Contact
|
||||
*/
|
||||
private function create(array $data): Contact
|
||||
{
|
||||
// filter out the data that shall not be updated here
|
||||
$dataOnly = Arr::except(
|
||||
$data,
|
||||
[
|
||||
'author_id',
|
||||
'email',
|
||||
'is_birthdate_known',
|
||||
'birthdate_day',
|
||||
'birthdate_month',
|
||||
'birthdate_year',
|
||||
'birthdate_is_age_based',
|
||||
'birthdate_age',
|
||||
'birthdate_add_reminder',
|
||||
'is_deceased',
|
||||
'is_deceased_date_known',
|
||||
'deceased_date_day',
|
||||
'deceased_date_month',
|
||||
'deceased_date_year',
|
||||
'deceased_date_add_reminder',
|
||||
]
|
||||
);
|
||||
|
||||
if (! empty($uuid = Arr::get($data, 'uuid')) && Uuid::isValid($uuid)) {
|
||||
$dataOnly['uuid'] = $uuid;
|
||||
}
|
||||
|
||||
return Contact::create($dataOnly);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a UUID for this contact.
|
||||
*
|
||||
* @param Contact $contact
|
||||
* @return void
|
||||
*/
|
||||
private function generateUUID(Contact $contact)
|
||||
{
|
||||
if (empty($contact->uuid)) {
|
||||
$contact->uuid = Str::uuid()->toString();
|
||||
$contact->save();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the different default avatars.
|
||||
*
|
||||
* @param Contact $contact
|
||||
* @return void
|
||||
*/
|
||||
private function addAvatars(Contact $contact)
|
||||
{
|
||||
// set the default avatar color
|
||||
$contact->setAvatarColor();
|
||||
$contact->save();
|
||||
|
||||
// populate the avatar from Adorable and grab the Gravatar
|
||||
GetAvatarsFromInternet::dispatch($contact);
|
||||
|
||||
// also generate the default avatar
|
||||
GenerateDefaultAvatar::dispatch($contact);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the information about the birthday.
|
||||
*
|
||||
* @param array $data
|
||||
* @param Contact $contact
|
||||
* @return void
|
||||
*/
|
||||
private function updateBirthDayInformation(array $data, Contact $contact)
|
||||
{
|
||||
app(UpdateBirthdayInformation::class)->execute([
|
||||
'account_id' => $data['account_id'],
|
||||
'contact_id' => $contact->id,
|
||||
'is_date_known' => $data['is_birthdate_known'],
|
||||
'day' => $this->nullOrvalue($data, 'birthdate_day'),
|
||||
'month' => $this->nullOrvalue($data, 'birthdate_month'),
|
||||
'year' => $this->nullOrvalue($data, 'birthdate_year'),
|
||||
'is_age_based' => $this->nullOrvalue($data, 'birthdate_is_age_based'),
|
||||
'age' => $this->nullOrvalue($data, 'birthdate_age'),
|
||||
'add_reminder' => $this->nullOrvalue($data, 'birthdate_add_reminder'),
|
||||
'is_deceased' => $data['is_deceased'],
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a contact field containing the email address.
|
||||
*
|
||||
* @param array $data
|
||||
* @param Contact $contact
|
||||
* @return void
|
||||
*/
|
||||
private function updateEmail(array $data, Contact $contact)
|
||||
{
|
||||
$contactFieldType = ContactFieldType::where([
|
||||
'account_id' => $data['account_id'],
|
||||
'type' => ContactFieldType::EMAIL,
|
||||
])->first();
|
||||
|
||||
if (is_null($contactFieldType) || is_null($this->nullOrvalue($data, 'email'))) {
|
||||
return;
|
||||
}
|
||||
|
||||
app(CreateContactField::class)->execute([
|
||||
'account_id' => $data['account_id'],
|
||||
'contact_id' => $contact->id,
|
||||
'contact_field_type_id' => $contactFieldType->id,
|
||||
'data' => $data['email'],
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the information about the date of death.
|
||||
*
|
||||
* @param array $data
|
||||
* @param Contact $contact
|
||||
* @return void
|
||||
*/
|
||||
private function updateDeceasedInformation(array $data, Contact $contact)
|
||||
{
|
||||
app(UpdateDeceasedInformation::class)->execute([
|
||||
'account_id' => $data['account_id'],
|
||||
'contact_id' => $contact->id,
|
||||
'is_deceased' => $data['is_deceased'],
|
||||
'is_date_known' => $data['is_deceased_date_known'],
|
||||
'day' => $this->nullOrValue($data, 'deceased_date_day'),
|
||||
'month' => $this->nullOrValue($data, 'deceased_date_month'),
|
||||
'year' => $this->nullOrValue($data, 'deceased_date_year'),
|
||||
'add_reminder' => $this->nullOrValue($data, 'deceased_date_add_reminder'),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an audit log.
|
||||
*
|
||||
* @param array $data
|
||||
* @param Contact $contact
|
||||
* @return void
|
||||
*/
|
||||
private function log(array $data, Contact $contact): void
|
||||
{
|
||||
$author = User::find($data['author_id']);
|
||||
|
||||
LogAccountAudit::dispatch([
|
||||
'action' => 'contact_created',
|
||||
'account_id' => $author->account_id,
|
||||
'about_contact_id' => $contact->id,
|
||||
'author_id' => $author->id,
|
||||
'author_name' => $author->name,
|
||||
'audited_at' => now(),
|
||||
'should_appear_on_dashboard' => true,
|
||||
'objects' => json_encode([
|
||||
'contact_name' => $contact->name,
|
||||
'contact_id' => $contact->id,
|
||||
]),
|
||||
]);
|
||||
}
|
||||
}
|
||||
43
app/Services/Contact/Contact/DeleteMeContact.php
Normal file
43
app/Services/Contact/Contact/DeleteMeContact.php
Normal file
@@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Contact\Contact;
|
||||
|
||||
use App\Models\User\User;
|
||||
use App\Services\BaseService;
|
||||
use App\Models\Contact\Contact;
|
||||
|
||||
class DeleteMeContact extends BaseService
|
||||
{
|
||||
/**
|
||||
* Get the validation rules that apply to the service.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'account_id' => 'required|integer|exists:accounts,id',
|
||||
'user_id' => 'required|integer|exists:users,id',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a contact as 'me' contact.
|
||||
*
|
||||
* @param array $data
|
||||
* @return User
|
||||
*/
|
||||
public function execute(array $data): User
|
||||
{
|
||||
$this->validate($data);
|
||||
|
||||
/** @var User */
|
||||
$user = User::where('account_id', $data['account_id'])
|
||||
->findOrFail($data['user_id']);
|
||||
|
||||
$user->me_contact_id = null;
|
||||
$user->save();
|
||||
|
||||
return $user;
|
||||
}
|
||||
}
|
||||
89
app/Services/Contact/Contact/DestroyContact.php
Normal file
89
app/Services/Contact/Contact/DestroyContact.php
Normal file
@@ -0,0 +1,89 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Contact\Contact;
|
||||
|
||||
use App\Services\BaseService;
|
||||
use App\Models\Contact\Contact;
|
||||
use App\Services\QueuableService;
|
||||
use App\Services\DispatchableService;
|
||||
use App\Models\Relationship\Relationship;
|
||||
use App\Services\Contact\Relationship\DestroyRelationship;
|
||||
|
||||
class DestroyContact extends BaseService implements QueuableService
|
||||
{
|
||||
use DispatchableService;
|
||||
|
||||
/**
|
||||
* Get the validation rules that apply to the service.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'account_id' => 'required|integer|exists:accounts,id',
|
||||
'contact_id' => 'required|integer|exists:contacts,id',
|
||||
'force_delete' => 'nullable|boolean',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroy a contact.
|
||||
*
|
||||
* @param array $data
|
||||
* @return void
|
||||
*/
|
||||
public function handle(array $data): void
|
||||
{
|
||||
$this->validate($data);
|
||||
|
||||
$contact = Contact::where('account_id', $data['account_id'])
|
||||
->findOrFail($data['contact_id']);
|
||||
|
||||
$contact->throwInactive();
|
||||
|
||||
$this->destroyRelationships($data, $contact);
|
||||
|
||||
$contact->deleteAvatars();
|
||||
|
||||
if ($this->valueOrFalse($data, 'force_delete') === true) {
|
||||
$contact->forceDelete();
|
||||
} else {
|
||||
$contact->delete();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroy all associated relationships.
|
||||
*
|
||||
* @param array $data
|
||||
* @param Contact $contact
|
||||
* @return void
|
||||
*/
|
||||
private function destroyRelationships(array $data, Contact $contact)
|
||||
{
|
||||
$relationships = Relationship::where('contact_is', $contact->id)->get();
|
||||
$this->destroySpecificRelationships($data, $relationships);
|
||||
|
||||
$relationships = Relationship::where('of_contact', $contact->id)->get();
|
||||
$this->destroySpecificRelationships($data, $relationships);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete specific relationships.
|
||||
*
|
||||
* @param array $data
|
||||
* @param \Illuminate\Support\Collection $relationships
|
||||
* @return void
|
||||
*/
|
||||
private function destroySpecificRelationships(array $data, $relationships)
|
||||
{
|
||||
foreach ($relationships as $relationship) {
|
||||
app(DestroyRelationship::class)
|
||||
->execute([
|
||||
'account_id' => $data['account_id'],
|
||||
'relationship_id' => $relationship->id,
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
53
app/Services/Contact/Contact/SetMeContact.php
Normal file
53
app/Services/Contact/Contact/SetMeContact.php
Normal file
@@ -0,0 +1,53 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Contact\Contact;
|
||||
|
||||
use App\Models\User\User;
|
||||
use App\Services\BaseService;
|
||||
use App\Helpers\AccountHelper;
|
||||
use App\Models\Contact\Contact;
|
||||
|
||||
class SetMeContact extends BaseService
|
||||
{
|
||||
/**
|
||||
* Get the validation rules that apply to the service.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'account_id' => 'required|integer|exists:accounts,id',
|
||||
'user_id' => 'required|integer|exists:users,id',
|
||||
'contact_id' => 'required|integer|exists:contacts,id',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a contact as 'me' contact.
|
||||
*
|
||||
* @param array $data
|
||||
* @return User
|
||||
*/
|
||||
public function execute(array $data): User
|
||||
{
|
||||
$this->validate($data);
|
||||
|
||||
/** @var User */
|
||||
$user = User::where('account_id', $data['account_id'])
|
||||
->findOrFail($data['user_id']);
|
||||
|
||||
if (AccountHelper::hasLimitations($user->account)) {
|
||||
abort(402);
|
||||
}
|
||||
|
||||
/** @var Contact */
|
||||
$contact = Contact::where('account_id', $data['account_id'])
|
||||
->findOrFail($data['contact_id']);
|
||||
|
||||
$user->me_contact_id = $contact->id;
|
||||
$user->save();
|
||||
|
||||
return $user;
|
||||
}
|
||||
}
|
||||
201
app/Services/Contact/Contact/UpdateBirthdayInformation.php
Normal file
201
app/Services/Contact/Contact/UpdateBirthdayInformation.php
Normal file
@@ -0,0 +1,201 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Contact\Contact;
|
||||
|
||||
use App\Helpers\DateHelper;
|
||||
use Illuminate\Support\Arr;
|
||||
use App\Services\BaseService;
|
||||
use App\Models\Contact\Contact;
|
||||
use Illuminate\Validation\Rule;
|
||||
use App\Models\Contact\Reminder;
|
||||
use App\Models\Instance\SpecialDate;
|
||||
use App\Services\Contact\Reminder\CreateReminder;
|
||||
use App\Services\Contact\Reminder\DestroyReminder;
|
||||
|
||||
class UpdateBirthdayInformation extends BaseService
|
||||
{
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
public $data;
|
||||
|
||||
/**
|
||||
* Get the validation rules that apply to the service.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'account_id' => 'required|integer|exists:accounts,id',
|
||||
'contact_id' => 'required|integer|exists:contacts,id',
|
||||
'is_date_known' => 'required|boolean',
|
||||
'is_age_based' => 'nullable|boolean',
|
||||
'day' => [
|
||||
'integer',
|
||||
'nullable',
|
||||
Rule::requiredIf(function () {
|
||||
return Arr::get($this->data, 'is_date_known', false) && ! Arr::get($this->data, 'is_age_based', false);
|
||||
}),
|
||||
],
|
||||
'month' => [
|
||||
'integer',
|
||||
'nullable',
|
||||
Rule::requiredIf(function () {
|
||||
return Arr::get($this->data, 'is_date_known', false) && ! Arr::get($this->data, 'is_age_based', false);
|
||||
}),
|
||||
],
|
||||
'year' => 'nullable|integer',
|
||||
'age' => [
|
||||
'integer',
|
||||
'nullable',
|
||||
Rule::requiredIf(function () {
|
||||
return Arr::get($this->data, 'is_date_known', false) && Arr::get($this->data, 'is_age_based', false);
|
||||
}),
|
||||
],
|
||||
'add_reminder' => 'nullable|boolean',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the information about the birthday.
|
||||
*
|
||||
* @param array $data
|
||||
* @return Contact
|
||||
*/
|
||||
public function execute(array $data)
|
||||
{
|
||||
$this->data = $data;
|
||||
$this->validate($data);
|
||||
|
||||
/** @var Contact */
|
||||
$contact = Contact::where('account_id', $data['account_id'])
|
||||
->findOrFail($data['contact_id']);
|
||||
|
||||
$contact->throwInactive();
|
||||
|
||||
$this->clearRelatedReminder($contact);
|
||||
|
||||
$this->clearRelatedSpecialDate($contact);
|
||||
|
||||
$this->manageBirthday($data, $contact);
|
||||
|
||||
return $contact;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete related reminder.
|
||||
*
|
||||
* @param Contact $contact
|
||||
* @return void
|
||||
*/
|
||||
private function clearRelatedReminder(Contact $contact)
|
||||
{
|
||||
if (is_null($contact->birthday_reminder_id)) {
|
||||
return;
|
||||
}
|
||||
|
||||
app(DestroyReminder::class)->execute([
|
||||
'account_id' => $contact->account_id,
|
||||
'reminder_id' => $contact->birthday_reminder_id,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete related special date.
|
||||
*
|
||||
* @param Contact $contact
|
||||
* @return void
|
||||
*/
|
||||
private function clearRelatedSpecialDate(Contact $contact)
|
||||
{
|
||||
$specialDate = SpecialDate::find($contact->birthday_special_date_id);
|
||||
if (! is_null($specialDate)) {
|
||||
$specialDate->delete();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update birthday information depending on the type of information.
|
||||
*
|
||||
* @param array $data
|
||||
* @param Contact $contact
|
||||
* @return void
|
||||
*/
|
||||
private function manageBirthday(array $data, Contact $contact): void
|
||||
{
|
||||
if (! $data['is_date_known']) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ($data['is_age_based']) {
|
||||
$this->approximate($data, $contact);
|
||||
} else {
|
||||
$this->exact($data, $contact);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Case where the birthday is approximate. That means the birthdate is based
|
||||
* on the estimated age of the contact.
|
||||
*
|
||||
* @param array $data
|
||||
* @param Contact $contact
|
||||
* @return void
|
||||
*/
|
||||
private function approximate(array $data, Contact $contact)
|
||||
{
|
||||
$contact->setSpecialDateFromAge('birthdate', $data['age']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Case where we have a year, month and day for the birthday.
|
||||
*
|
||||
* @param array $data
|
||||
* @param Contact $contact
|
||||
* @return void
|
||||
*/
|
||||
private function exact(array $data, Contact $contact)
|
||||
{
|
||||
$specialDate = $contact->setSpecialDate(
|
||||
'birthdate',
|
||||
(is_null($data['year']) ? 0 : $data['year']),
|
||||
$data['month'],
|
||||
$data['day']
|
||||
);
|
||||
|
||||
$this->setReminder($data, $contact, $specialDate);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a reminder for the given special date, if required.
|
||||
*
|
||||
* @param array $data
|
||||
* @param Contact $contact
|
||||
* @param SpecialDate $specialDate
|
||||
* @return void
|
||||
*/
|
||||
private function setReminder(array $data, Contact $contact, SpecialDate $specialDate)
|
||||
{
|
||||
if (empty($data['add_reminder'])) {
|
||||
return;
|
||||
}
|
||||
|
||||
$reminder = app(CreateReminder::class)->execute([
|
||||
'account_id' => $data['account_id'],
|
||||
'contact_id' => $data['contact_id'],
|
||||
'initial_date' => DateHelper::getDate($specialDate),
|
||||
'frequency_type' => 'year',
|
||||
'frequency_number' => 1,
|
||||
'title' => trans(
|
||||
($data['is_deceased'] ?
|
||||
'people.people_add_birthday_reminder_deceased' : 'people.people_add_birthday_reminder'),
|
||||
['name' => $contact->first_name]
|
||||
),
|
||||
'delible' => false,
|
||||
]);
|
||||
|
||||
$contact->birthday_reminder_id = $reminder->id;
|
||||
$contact->save();
|
||||
}
|
||||
}
|
||||
177
app/Services/Contact/Contact/UpdateContact.php
Normal file
177
app/Services/Contact/Contact/UpdateContact.php
Normal file
@@ -0,0 +1,177 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Contact\Contact;
|
||||
|
||||
use Ramsey\Uuid\Uuid;
|
||||
use Illuminate\Support\Arr;
|
||||
use App\Services\BaseService;
|
||||
use App\Helpers\AccountHelper;
|
||||
use App\Models\Account\Account;
|
||||
use App\Models\Contact\Contact;
|
||||
use App\Jobs\Avatars\GenerateDefaultAvatar;
|
||||
use App\Services\Contact\Description\SetPersonalDescription;
|
||||
use App\Services\Contact\Description\ClearPersonalDescription;
|
||||
|
||||
class UpdateContact extends BaseService
|
||||
{
|
||||
private array $data;
|
||||
private Contact $contact;
|
||||
|
||||
/**
|
||||
* Get the validation rules that apply to the service.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'account_id' => 'required|integer|exists:accounts,id',
|
||||
'author_id' => 'required|integer|exists:users,id',
|
||||
'contact_id' => 'required|integer',
|
||||
'uuid' => 'nullable|string',
|
||||
'first_name' => 'required|string|max:255',
|
||||
'middle_name' => 'nullable|string|max:255',
|
||||
'last_name' => 'nullable|string|max:255',
|
||||
'nickname' => 'nullable|string|max:255',
|
||||
'gender_id' => 'nullable|integer|exists:genders,id',
|
||||
'description' => 'nullable|string|max:255',
|
||||
'is_partial' => 'nullable|boolean',
|
||||
'is_birthdate_known' => 'required|boolean',
|
||||
'birthdate_day' => 'nullable|integer',
|
||||
'birthdate_month' => 'nullable|integer',
|
||||
'birthdate_year' => 'nullable|integer',
|
||||
'birthdate_is_age_based' => 'nullable|boolean',
|
||||
'birthdate_age' => 'nullable|integer',
|
||||
'birthdate_add_reminder' => 'nullable|boolean',
|
||||
'is_deceased' => 'nullable|boolean',
|
||||
'is_deceased_date_known' => 'required|boolean',
|
||||
'deceased_date_day' => 'nullable|integer',
|
||||
'deceased_date_month' => 'nullable|integer',
|
||||
'deceased_date_year' => 'nullable|integer',
|
||||
'deceased_date_add_reminder' => 'nullable|boolean',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Update a contact.
|
||||
*
|
||||
* @param array $data
|
||||
* @return Contact
|
||||
*/
|
||||
public function execute(array $data): Contact
|
||||
{
|
||||
$this->data = $data;
|
||||
$this->validate($this->data);
|
||||
|
||||
/* @var Contact */
|
||||
$this->contact = Contact::where('account_id', $data['account_id'])
|
||||
->findOrFail($data['contact_id']);
|
||||
|
||||
$this->contact->throwInactive();
|
||||
|
||||
// Test is the account is limited and the contact should be updated as real contact
|
||||
$account = Account::find($data['account_id']);
|
||||
if ($this->contact->is_partial
|
||||
&& ! $this->valueOrFalse($this->data, 'is_partial')
|
||||
&& AccountHelper::hasReachedContactLimit($account)
|
||||
&& AccountHelper::hasLimitations($account)
|
||||
&& ! $account->legacy_free_plan_unlimited_contacts) {
|
||||
abort(402);
|
||||
}
|
||||
|
||||
$this->updateGeneralInformation();
|
||||
$this->updateDescription();
|
||||
$this->updateBirthDayInformation();
|
||||
$this->updateDeceasedInformation();
|
||||
|
||||
return $this->contact->refresh();
|
||||
}
|
||||
|
||||
private function updateGeneralInformation(): void
|
||||
{
|
||||
// filter out the data that shall not be updated here
|
||||
$dataOnly = Arr::except(
|
||||
$this->data,
|
||||
[
|
||||
'author_id',
|
||||
'uuid',
|
||||
'is_birthdate_known',
|
||||
'birthdate_day',
|
||||
'birthdate_month',
|
||||
'birthdate_year',
|
||||
'birthdate_is_age_based',
|
||||
'birthdate_age',
|
||||
'birthdate_add_reminder',
|
||||
'is_deceased',
|
||||
'is_deceased_date_known',
|
||||
'deceased_date_day',
|
||||
'deceased_date_month',
|
||||
'deceased_date_year',
|
||||
'deceased_date_add_reminder',
|
||||
'description',
|
||||
]
|
||||
);
|
||||
|
||||
if (! empty($uuid = Arr::get($this->data, 'uuid')) && Uuid::isValid($uuid)) {
|
||||
$dataOnly['uuid'] = $uuid;
|
||||
}
|
||||
|
||||
$oldName = $this->contact->name;
|
||||
$this->contact->update($dataOnly);
|
||||
|
||||
// only update the avatar if the name has changed
|
||||
if ($oldName != $this->contact->name) {
|
||||
GenerateDefaultAvatar::dispatch($this->contact);
|
||||
}
|
||||
}
|
||||
|
||||
private function updateDescription(): void
|
||||
{
|
||||
if (is_null($this->nullOrValue($this->data, 'description'))) {
|
||||
app(ClearPersonalDescription::class)->execute([
|
||||
'account_id' => $this->data['account_id'],
|
||||
'contact_id' => $this->data['contact_id'],
|
||||
'author_id' => $this->data['author_id'],
|
||||
]);
|
||||
} else {
|
||||
if ($this->contact->description != $this->data['description']) {
|
||||
app(SetPersonalDescription::class)->execute([
|
||||
'account_id' => $this->data['account_id'],
|
||||
'contact_id' => $this->data['contact_id'],
|
||||
'author_id' => $this->data['author_id'],
|
||||
'description' => $this->data['description'],
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function updateBirthDayInformation(): void
|
||||
{
|
||||
app(UpdateBirthdayInformation::class)->execute([
|
||||
'account_id' => $this->data['account_id'],
|
||||
'contact_id' => $this->contact->id,
|
||||
'is_date_known' => $this->data['is_birthdate_known'],
|
||||
'day' => $this->nullOrvalue($this->data, 'birthdate_day'),
|
||||
'month' => $this->nullOrvalue($this->data, 'birthdate_month'),
|
||||
'year' => $this->nullOrvalue($this->data, 'birthdate_year'),
|
||||
'is_age_based' => $this->nullOrvalue($this->data, 'birthdate_is_age_based'),
|
||||
'age' => $this->nullOrvalue($this->data, 'birthdate_age'),
|
||||
'add_reminder' => $this->nullOrvalue($this->data, 'birthdate_add_reminder'),
|
||||
'is_deceased' => $this->data['is_deceased'],
|
||||
]);
|
||||
}
|
||||
|
||||
private function updateDeceasedInformation(): void
|
||||
{
|
||||
app(UpdateDeceasedInformation::class)->execute([
|
||||
'account_id' => $this->data['account_id'],
|
||||
'contact_id' => $this->contact->id,
|
||||
'is_deceased' => $this->data['is_deceased'],
|
||||
'is_date_known' => $this->data['is_deceased_date_known'],
|
||||
'day' => $this->nullOrvalue($this->data, 'deceased_date_day'),
|
||||
'month' => $this->nullOrvalue($this->data, 'deceased_date_month'),
|
||||
'year' => $this->nullOrvalue($this->data, 'deceased_date_year'),
|
||||
'add_reminder' => $this->nullOrvalue($this->data, 'deceased_date_add_reminder'),
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Contact\Contact;
|
||||
|
||||
use App\Services\BaseService;
|
||||
use App\Models\Contact\Contact;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
|
||||
class UpdateContactFoodPreferences extends BaseService
|
||||
{
|
||||
/**
|
||||
* Get the validation rules that apply to the service.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'account_id' => 'required|integer|exists:accounts,id',
|
||||
'contact_id' => 'required|integer|exists:contacts,id',
|
||||
'food_preferences' => 'nullable|string|max:65535',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the food preferences of the given contact.
|
||||
*
|
||||
* @param array $data
|
||||
* @return Contact
|
||||
*/
|
||||
public function execute(array $data): Contact
|
||||
{
|
||||
$this->validate($data);
|
||||
|
||||
/** @var Contact */
|
||||
$contact = Contact::where('account_id', $data['account_id'])
|
||||
->findOrFail($data['contact_id']);
|
||||
|
||||
$contact->throwInactive();
|
||||
if ($contact->is_partial) {
|
||||
throw ValidationException::withMessages([
|
||||
'contact_id' => 'The contact can\'t be a partial contact',
|
||||
]);
|
||||
}
|
||||
|
||||
$contact->food_preferences = ! empty($data['food_preferences']) ? $data['food_preferences'] : null;
|
||||
$contact->save();
|
||||
|
||||
// we query the DB again to fill the object with all the new properties
|
||||
$contact->refresh();
|
||||
|
||||
return $contact;
|
||||
}
|
||||
}
|
||||
214
app/Services/Contact/Contact/UpdateContactIntroduction.php
Normal file
214
app/Services/Contact/Contact/UpdateContactIntroduction.php
Normal file
@@ -0,0 +1,214 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Contact\Contact;
|
||||
|
||||
use App\Helpers\DateHelper;
|
||||
use Illuminate\Support\Arr;
|
||||
use App\Services\BaseService;
|
||||
use App\Models\Contact\Contact;
|
||||
use Illuminate\Validation\Rule;
|
||||
use App\Models\Contact\Reminder;
|
||||
use App\Models\Instance\SpecialDate;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
use App\Services\Contact\Reminder\CreateReminder;
|
||||
use App\Services\Contact\Reminder\DestroyReminder;
|
||||
|
||||
class UpdateContactIntroduction extends BaseService
|
||||
{
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
public $data;
|
||||
|
||||
/**
|
||||
* Get the validation rules that apply to the service.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'account_id' => 'required|integer|exists:accounts,id',
|
||||
'contact_id' => 'required|integer|exists:contacts,id',
|
||||
'met_through_contact_id' => 'nullable|integer|exists:contacts,id',
|
||||
'general_information' => 'nullable|string|max:65535',
|
||||
'where' => 'nullable|string|max:255',
|
||||
'is_date_known' => 'required|boolean',
|
||||
'is_age_based' => 'nullable|boolean',
|
||||
'day' => [
|
||||
'integer',
|
||||
'nullable',
|
||||
Rule::requiredIf(function () {
|
||||
return Arr::get($this->data, 'is_date_known', false) && ! Arr::get($this->data, 'is_age_based', false);
|
||||
}),
|
||||
],
|
||||
'month' => [
|
||||
'integer',
|
||||
'nullable',
|
||||
Rule::requiredIf(function () {
|
||||
return Arr::get($this->data, 'is_date_known', false) && ! Arr::get($this->data, 'is_age_based', false);
|
||||
}),
|
||||
],
|
||||
'year' => 'nullable|integer',
|
||||
'age' => [
|
||||
'integer',
|
||||
'nullable',
|
||||
Rule::requiredIf(function () {
|
||||
return Arr::get($this->data, 'is_date_known', false) && Arr::get($this->data, 'is_age_based', false);
|
||||
}),
|
||||
],
|
||||
'add_reminder' => 'nullable|boolean',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the information about how a contact was introduced.
|
||||
*
|
||||
* @param array $data
|
||||
* @return Contact
|
||||
*
|
||||
* @throws ValidationException
|
||||
*/
|
||||
public function execute(array $data): Contact
|
||||
{
|
||||
$this->data = $data;
|
||||
$this->validate($data);
|
||||
|
||||
/** @var Contact */
|
||||
$contact = Contact::where('account_id', $data['account_id'])
|
||||
->findOrFail($data['contact_id']);
|
||||
|
||||
$contact->throwInactive();
|
||||
|
||||
if ($contact->is_partial) {
|
||||
throw ValidationException::withMessages([
|
||||
'contact_id' => 'The contact can\'t be a partial contact',
|
||||
]);
|
||||
}
|
||||
|
||||
if ($metContactId = Arr::get($data, 'met_through_contact_id')) {
|
||||
Contact::where('account_id', $data['account_id'])
|
||||
->findOrFail($metContactId);
|
||||
}
|
||||
|
||||
$this->setMetThroughContact($data, $contact);
|
||||
$this->clearRelatedReminder($contact);
|
||||
$this->manageDate($data, $contact);
|
||||
$this->setInformation($data, $contact);
|
||||
|
||||
// we query the DB again to fill the object with all the new properties
|
||||
$contact->refresh();
|
||||
|
||||
return $contact;
|
||||
}
|
||||
|
||||
private function setMetThroughContact(array $data, Contact $contact): void
|
||||
{
|
||||
$contact->first_met_through_contact_id = Arr::get($data, 'met_through_contact_id');
|
||||
$contact->save();
|
||||
}
|
||||
|
||||
private function setInformation(array $data, Contact $contact): void
|
||||
{
|
||||
$contact->first_met_additional_info = Arr::get($data, 'general_information');
|
||||
$contact->first_met_where = Arr::get($data, 'where');
|
||||
$contact->save();
|
||||
}
|
||||
|
||||
private function clearRelatedReminder(Contact $contact): void
|
||||
{
|
||||
try {
|
||||
app(DestroyReminder::class)->execute([
|
||||
'account_id' => $contact->account_id,
|
||||
'reminder_id' => $contact->first_met_reminder_id,
|
||||
]);
|
||||
} catch (\Exception $e) {
|
||||
// Ignore this error
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update date information depending on the type of information.
|
||||
*
|
||||
* @param array $data
|
||||
* @param Contact $contact
|
||||
* @return void
|
||||
*/
|
||||
private function manageDate(array $data, Contact $contact): void
|
||||
{
|
||||
if (! $data['is_date_known']) {
|
||||
$contact->firstMetDate()->delete();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (Arr::get($data, 'is_age_based')) {
|
||||
$this->approximate($data, $contact);
|
||||
} else {
|
||||
$this->exact($data, $contact);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Case where the date is approximate. That means the date is based
|
||||
* on the estimated age of the contact.
|
||||
*
|
||||
* @param array $data
|
||||
* @param Contact $contact
|
||||
* @return void
|
||||
*/
|
||||
private function approximate(array $data, Contact $contact): void
|
||||
{
|
||||
$contact->setSpecialDateFromAge('first_met', $data['age']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Case where we have a year, month and day for the date.
|
||||
*
|
||||
* @param array $data
|
||||
* @param Contact $contact
|
||||
* @return void
|
||||
*/
|
||||
private function exact(array $data, Contact $contact): void
|
||||
{
|
||||
$specialDate = $contact->setSpecialDate(
|
||||
'first_met',
|
||||
(is_null($data['year']) ? 0 : $data['year']),
|
||||
$data['month'],
|
||||
$data['day']
|
||||
);
|
||||
|
||||
$this->setReminder($data, $contact, $specialDate);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a reminder for the given special date, if required.
|
||||
*
|
||||
* @param array $data
|
||||
* @param Contact $contact
|
||||
* @param SpecialDate $specialDate
|
||||
* @return void
|
||||
*/
|
||||
private function setReminder(array $data, Contact $contact, SpecialDate $specialDate): void
|
||||
{
|
||||
if (empty($data['add_reminder'])) {
|
||||
return;
|
||||
}
|
||||
|
||||
$reminder = app(CreateReminder::class)->execute([
|
||||
'account_id' => $data['account_id'],
|
||||
'contact_id' => $data['contact_id'],
|
||||
'initial_date' => DateHelper::getDate($specialDate),
|
||||
'frequency_type' => 'year',
|
||||
'frequency_number' => 1,
|
||||
'title' => trans(
|
||||
'people.introductions_reminder_title',
|
||||
['name' => $contact->first_name]
|
||||
),
|
||||
'delible' => false,
|
||||
]);
|
||||
|
||||
$contact->first_met_reminder_id = $reminder->id;
|
||||
$contact->save();
|
||||
}
|
||||
}
|
||||
164
app/Services/Contact/Contact/UpdateDeceasedInformation.php
Normal file
164
app/Services/Contact/Contact/UpdateDeceasedInformation.php
Normal file
@@ -0,0 +1,164 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Contact\Contact;
|
||||
|
||||
use App\Helpers\DateHelper;
|
||||
use App\Services\BaseService;
|
||||
use App\Models\Contact\Contact;
|
||||
use App\Models\Instance\SpecialDate;
|
||||
use App\Services\Contact\Reminder\CreateReminder;
|
||||
use App\Services\Contact\Reminder\DestroyReminder;
|
||||
|
||||
class UpdateDeceasedInformation extends BaseService
|
||||
{
|
||||
/**
|
||||
* Get the validation rules that apply to the service.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'account_id' => 'required|integer|exists:accounts,id',
|
||||
'contact_id' => 'required|integer',
|
||||
'is_deceased' => 'required|boolean',
|
||||
'is_date_known' => 'required|boolean',
|
||||
'day' => 'nullable|integer',
|
||||
'month' => 'nullable|integer',
|
||||
'year' => 'nullable|integer',
|
||||
'add_reminder' => 'nullable|boolean',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the information about the deceased date.
|
||||
*
|
||||
* @param array $data
|
||||
* @return Contact
|
||||
*/
|
||||
public function execute(array $data)
|
||||
{
|
||||
$this->validate($data);
|
||||
|
||||
/** @var Contact */
|
||||
$contact = Contact::where('account_id', $data['account_id'])
|
||||
->findOrFail($data['contact_id']);
|
||||
|
||||
$contact->throwInactive();
|
||||
|
||||
$this->clearRelatedReminder($contact);
|
||||
|
||||
$this->clearRelatedSpecialDate($contact);
|
||||
|
||||
$this->manageDeceasedDate($data, $contact);
|
||||
|
||||
return $contact;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete related reminder.
|
||||
*
|
||||
* @param Contact $contact
|
||||
* @return void
|
||||
*/
|
||||
private function clearRelatedReminder(Contact $contact)
|
||||
{
|
||||
if (is_null($contact->deceased_reminder_id)) {
|
||||
return;
|
||||
}
|
||||
|
||||
app(DestroyReminder::class)->execute([
|
||||
'account_id' => $contact->account_id,
|
||||
'reminder_id' => $contact->deceased_reminder_id,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete related special date.
|
||||
*
|
||||
* @param Contact $contact
|
||||
* @return void
|
||||
*/
|
||||
private function clearRelatedSpecialDate(Contact $contact)
|
||||
{
|
||||
$specialDate = SpecialDate::find($contact->deceased_special_date_id);
|
||||
if (! is_null($specialDate)) {
|
||||
$specialDate->delete();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update deceased date information depending on the type of information.
|
||||
*
|
||||
* @param array $data
|
||||
* @param Contact $contact
|
||||
* @return void
|
||||
*/
|
||||
private function manageDeceasedDate(array $data, Contact $contact): void
|
||||
{
|
||||
if (! $data['is_deceased']) {
|
||||
// remove all information about deceased date in the DB
|
||||
$contact->is_dead = false;
|
||||
$contact->deceased_special_date_id = null;
|
||||
$contact->save();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$contact->is_dead = true;
|
||||
$contact->save();
|
||||
|
||||
if ($data['is_date_known']) {
|
||||
$this->exact($data, $contact);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Case where we have a year, month and day for the date.
|
||||
*
|
||||
* @param array $data
|
||||
* @param Contact $contact
|
||||
* @return void
|
||||
*/
|
||||
private function exact(array $data, Contact $contact)
|
||||
{
|
||||
$specialDate = $contact->setSpecialDate(
|
||||
'deceased_date',
|
||||
(is_null($data['year']) ? 0 : $data['year']),
|
||||
$data['month'],
|
||||
$data['day']
|
||||
);
|
||||
|
||||
$this->setReminder($data, $contact, $specialDate);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a reminder for the given special date, if required.
|
||||
*
|
||||
* @param array $data
|
||||
* @param Contact $contact
|
||||
* @param SpecialDate $specialDate
|
||||
* @return void
|
||||
*/
|
||||
private function setReminder(array $data, Contact $contact, SpecialDate $specialDate)
|
||||
{
|
||||
if (empty($data['add_reminder'])) {
|
||||
return;
|
||||
}
|
||||
|
||||
$reminder = app(CreateReminder::class)->execute([
|
||||
'account_id' => $data['account_id'],
|
||||
'contact_id' => $data['contact_id'],
|
||||
'initial_date' => DateHelper::getDate($specialDate),
|
||||
'frequency_type' => 'year',
|
||||
'frequency_number' => 1,
|
||||
'title' => trans(
|
||||
'people.deceased_reminder_title',
|
||||
['name' => $contact->first_name]
|
||||
),
|
||||
]);
|
||||
|
||||
$contact->deceased_reminder_id = $reminder->id;
|
||||
$contact->save();
|
||||
}
|
||||
}
|
||||
87
app/Services/Contact/Contact/UpdateWorkInformation.php
Normal file
87
app/Services/Contact/Contact/UpdateWorkInformation.php
Normal file
@@ -0,0 +1,87 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Contact\Contact;
|
||||
|
||||
use App\Models\User\User;
|
||||
use App\Services\BaseService;
|
||||
use function Safe\json_encode;
|
||||
use App\Models\Contact\Contact;
|
||||
use App\Jobs\AuditLog\LogAccountAudit;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
|
||||
class UpdateWorkInformation extends BaseService
|
||||
{
|
||||
/**
|
||||
* Get the validation rules that apply to the service.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'account_id' => 'required|integer|exists:accounts,id',
|
||||
'author_id' => 'required|integer|exists:users,id',
|
||||
'contact_id' => 'required|integer|exists:contacts,id',
|
||||
'job' => 'nullable|string|max:255',
|
||||
'company' => 'nullable|string|max:255',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Update a contact.
|
||||
*
|
||||
* @param array $data
|
||||
* @return Contact
|
||||
*/
|
||||
public function execute(array $data): Contact
|
||||
{
|
||||
$this->validate($data);
|
||||
|
||||
/** @var Contact */
|
||||
$contact = Contact::where('account_id', $data['account_id'])
|
||||
->findOrFail($data['contact_id']);
|
||||
|
||||
$contact->throwInactive();
|
||||
if ($contact->is_partial) {
|
||||
throw ValidationException::withMessages([
|
||||
'contact_id' => 'The contact can\'t be a partial contact',
|
||||
]);
|
||||
}
|
||||
|
||||
$contact->job = empty($data['job']) ? null : $data['job'];
|
||||
$contact->company = empty($data['company']) ? null : $data['company'];
|
||||
$contact->save();
|
||||
|
||||
$this->log($data, $contact);
|
||||
|
||||
$contact->refresh();
|
||||
|
||||
return $contact;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an audit log.
|
||||
*
|
||||
* @param array $data
|
||||
* @param Contact $contact
|
||||
* @return void
|
||||
*/
|
||||
private function log(array $data, Contact $contact): void
|
||||
{
|
||||
$author = User::find($data['author_id']);
|
||||
|
||||
LogAccountAudit::dispatch([
|
||||
'action' => 'contact_work_updated',
|
||||
'account_id' => $author->account_id,
|
||||
'about_contact_id' => $contact->id,
|
||||
'author_id' => $author->id,
|
||||
'author_name' => $author->name,
|
||||
'audited_at' => now(),
|
||||
'should_appear_on_dashboard' => true,
|
||||
'objects' => json_encode([
|
||||
'contact_name' => $contact->name,
|
||||
'contact_id' => $contact->id,
|
||||
]),
|
||||
]);
|
||||
}
|
||||
}
|
||||
64
app/Services/Contact/ContactField/CreateContactField.php
Normal file
64
app/Services/Contact/ContactField/CreateContactField.php
Normal file
@@ -0,0 +1,64 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Contact\ContactField;
|
||||
|
||||
use App\Services\BaseService;
|
||||
use App\Models\Contact\Contact;
|
||||
use App\Models\Contact\ContactField;
|
||||
use App\Models\Contact\ContactFieldType;
|
||||
use App\Services\Contact\Label\UpdateContactFieldLabels;
|
||||
|
||||
class CreateContactField extends BaseService
|
||||
{
|
||||
/**
|
||||
* Get the validation rules that apply to the service.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'account_id' => 'required|integer|exists:accounts,id',
|
||||
'contact_id' => 'required|integer|exists:contacts,id',
|
||||
'contact_field_type_id' => 'required|integer|exists:contact_field_types,id',
|
||||
'data' => 'required|string|max:255',
|
||||
'labels' => 'nullable|array',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a contact field.
|
||||
*
|
||||
* @param array $data
|
||||
* @return ContactField
|
||||
*/
|
||||
public function execute(array $data): ContactField
|
||||
{
|
||||
$this->validate($data);
|
||||
|
||||
$contact = Contact::where('account_id', $data['account_id'])
|
||||
->findOrFail($data['contact_id']);
|
||||
|
||||
$contact->throwInactive();
|
||||
|
||||
ContactFieldType::where('account_id', $data['account_id'])
|
||||
->findOrFail($data['contact_field_type_id']);
|
||||
|
||||
$contactField = ContactField::create([
|
||||
'account_id' => $data['account_id'],
|
||||
'contact_id' => $data['contact_id'],
|
||||
'contact_field_type_id' => $data['contact_field_type_id'],
|
||||
'data' => $this->nullOrValue($data, 'data'),
|
||||
]);
|
||||
|
||||
if ($labels = $this->nullOrValue($data, 'labels')) {
|
||||
app(UpdateContactFieldLabels::class)->execute([
|
||||
'account_id' => $data['account_id'],
|
||||
'contact_field_id' => $contactField->id,
|
||||
'labels' => $labels,
|
||||
]);
|
||||
}
|
||||
|
||||
return $contactField;
|
||||
}
|
||||
}
|
||||
42
app/Services/Contact/ContactField/DestroyContactField.php
Normal file
42
app/Services/Contact/ContactField/DestroyContactField.php
Normal file
@@ -0,0 +1,42 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Contact\ContactField;
|
||||
|
||||
use App\Services\BaseService;
|
||||
use App\Models\Contact\ContactField;
|
||||
|
||||
class DestroyContactField extends BaseService
|
||||
{
|
||||
/**
|
||||
* Get the validation rules that apply to the service.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'account_id' => 'required|integer|exists:accounts,id',
|
||||
'contact_field_id' => 'required|integer|exists:contact_fields,id',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroy an address.
|
||||
*
|
||||
* @param array $data
|
||||
* @return bool
|
||||
*/
|
||||
public function execute(array $data): bool
|
||||
{
|
||||
$this->validate($data);
|
||||
|
||||
$contactField = ContactField::where('account_id', $data['account_id'])
|
||||
->findOrFail($data['contact_field_id']);
|
||||
|
||||
$contactField->contact->throwInactive();
|
||||
|
||||
$contactField->delete();
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
68
app/Services/Contact/ContactField/UpdateContactField.php
Normal file
68
app/Services/Contact/ContactField/UpdateContactField.php
Normal file
@@ -0,0 +1,68 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Contact\ContactField;
|
||||
|
||||
use App\Services\BaseService;
|
||||
use App\Models\Contact\Contact;
|
||||
use App\Models\Contact\ContactField;
|
||||
use App\Models\Contact\ContactFieldType;
|
||||
use App\Services\Contact\Label\UpdateContactFieldLabels;
|
||||
|
||||
class UpdateContactField extends BaseService
|
||||
{
|
||||
/**
|
||||
* Get the validation rules that apply to the service.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'account_id' => 'required|integer|exists:accounts,id',
|
||||
'contact_field_id' => 'required|integer|exists:contact_fields,id',
|
||||
'contact_id' => 'required|integer|exists:contacts,id',
|
||||
'contact_field_type_id' => 'required|integer|exists:contact_field_types,id',
|
||||
'data' => 'required|string|max:255',
|
||||
'labels' => 'nullable|array',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Update a contact field.
|
||||
*
|
||||
* @param array $data
|
||||
* @return ContactField
|
||||
*/
|
||||
public function execute(array $data): ContactField
|
||||
{
|
||||
$this->validate($data);
|
||||
|
||||
/** @var ContactField */
|
||||
$contactField = ContactField::where('account_id', $data['account_id'])
|
||||
->findOrFail($data['contact_field_id']);
|
||||
|
||||
$contact = Contact::where('account_id', $data['account_id'])
|
||||
->findOrFail($data['contact_id']);
|
||||
|
||||
$contact->throwInactive();
|
||||
|
||||
ContactFieldType::where('account_id', $data['account_id'])
|
||||
->findOrFail($data['contact_field_type_id']);
|
||||
|
||||
$contactField->update([
|
||||
'contact_id' => $data['contact_id'],
|
||||
'contact_field_type_id' => $data['contact_field_type_id'],
|
||||
'data' => $this->nullOrValue($data, 'data'),
|
||||
]);
|
||||
|
||||
if ($labels = $this->nullOrValue($data, 'labels')) {
|
||||
app(UpdateContactFieldLabels::class)->execute([
|
||||
'account_id' => $data['account_id'],
|
||||
'contact_field_id' => $data['contact_field_id'],
|
||||
'labels' => $labels,
|
||||
]);
|
||||
}
|
||||
|
||||
return $contactField;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This is a single action class, totally inspired by
|
||||
* https://medium.com/@remi_collin/keeping-your-laravel-applications-dry-with-single-action-classes-6a950ec54d1d.
|
||||
*/
|
||||
|
||||
namespace App\Services\Contact\Conversation;
|
||||
|
||||
use App\Services\BaseService;
|
||||
use App\Models\Contact\Contact;
|
||||
use App\Models\Contact\Message;
|
||||
use App\Models\Contact\Conversation;
|
||||
|
||||
class AddMessageToConversation extends BaseService
|
||||
{
|
||||
/**
|
||||
* Get the validation rules that apply to the service.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'account_id' => 'required|integer|exists:accounts,id',
|
||||
'contact_id' => 'required|integer|exists:contacts,id',
|
||||
'conversation_id' => 'required|integer|exists:conversations,id',
|
||||
'written_at' => 'required|date',
|
||||
'written_by_me' => 'required|boolean',
|
||||
'content' => 'required|string',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Add message to a conversation.
|
||||
*
|
||||
* @param array $data
|
||||
* @return Message
|
||||
*/
|
||||
public function execute(array $data): Message
|
||||
{
|
||||
$this->validate($data);
|
||||
|
||||
$contact = Contact::where('account_id', $data['account_id'])
|
||||
->findOrFail($data['contact_id']);
|
||||
|
||||
$contact->throwInactive();
|
||||
|
||||
Conversation::where('contact_id', $data['contact_id'])
|
||||
->where('account_id', $data['account_id'])
|
||||
->findOrFail($data['conversation_id']);
|
||||
|
||||
return Message::create($data);
|
||||
}
|
||||
}
|
||||
52
app/Services/Contact/Conversation/CreateConversation.php
Normal file
52
app/Services/Contact/Conversation/CreateConversation.php
Normal file
@@ -0,0 +1,52 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This is a single action class, totally inspired by
|
||||
* https://medium.com/@remi_collin/keeping-your-laravel-applications-dry-with-single-action-classes-6a950ec54d1d.
|
||||
*/
|
||||
|
||||
namespace App\Services\Contact\Conversation;
|
||||
|
||||
use App\Services\BaseService;
|
||||
use App\Models\Contact\Contact;
|
||||
use App\Models\Contact\Conversation;
|
||||
use App\Models\Contact\ContactFieldType;
|
||||
|
||||
class CreateConversation extends BaseService
|
||||
{
|
||||
/**
|
||||
* Get the validation rules that apply to the service.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'happened_at' => 'required|date',
|
||||
'account_id' => 'required|integer|exists:accounts,id',
|
||||
'contact_id' => 'required|integer|exists:contacts,id',
|
||||
'contact_field_type_id' => 'required|integer|exists:contact_field_types,id',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a conversation.
|
||||
*
|
||||
* @param array $data
|
||||
* @return Conversation
|
||||
*/
|
||||
public function execute(array $data): Conversation
|
||||
{
|
||||
$this->validate($data);
|
||||
|
||||
$contact = Contact::where('account_id', $data['account_id'])
|
||||
->findOrFail($data['contact_id']);
|
||||
|
||||
$contact->throwInactive();
|
||||
|
||||
ContactFieldType::where('account_id', $data['account_id'])
|
||||
->findOrFail($data['contact_field_type_id']);
|
||||
|
||||
return Conversation::create($data);
|
||||
}
|
||||
}
|
||||
47
app/Services/Contact/Conversation/DestroyConversation.php
Normal file
47
app/Services/Contact/Conversation/DestroyConversation.php
Normal file
@@ -0,0 +1,47 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This is a single action class, totally inspired by
|
||||
* https://medium.com/@remi_collin/keeping-your-laravel-applications-dry-with-single-action-classes-6a950ec54d1d.
|
||||
*/
|
||||
|
||||
namespace App\Services\Contact\Conversation;
|
||||
|
||||
use App\Services\BaseService;
|
||||
use App\Models\Contact\Conversation;
|
||||
|
||||
class DestroyConversation extends BaseService
|
||||
{
|
||||
/**
|
||||
* Get the validation rules that apply to the service.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'account_id' => 'required|integer|exists:accounts,id',
|
||||
'conversation_id' => 'required|integer|exists:conversations,id',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroy a conversation.
|
||||
*
|
||||
* @param array $data
|
||||
* @return bool
|
||||
*/
|
||||
public function execute(array $data): bool
|
||||
{
|
||||
$this->validate($data);
|
||||
|
||||
$conversation = Conversation::where('account_id', $data['account_id'])
|
||||
->findOrFail($data['conversation_id']);
|
||||
|
||||
$conversation->contact->throwInactive();
|
||||
|
||||
$conversation->delete();
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
53
app/Services/Contact/Conversation/DestroyMessage.php
Normal file
53
app/Services/Contact/Conversation/DestroyMessage.php
Normal file
@@ -0,0 +1,53 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This is a single action class, totally inspired by
|
||||
* https://medium.com/@remi_collin/keeping-your-laravel-applications-dry-with-single-action-classes-6a950ec54d1d.
|
||||
*/
|
||||
|
||||
namespace App\Services\Contact\Conversation;
|
||||
|
||||
use App\Services\BaseService;
|
||||
use App\Models\Contact\Message;
|
||||
use App\Models\Contact\Conversation;
|
||||
|
||||
class DestroyMessage extends BaseService
|
||||
{
|
||||
/**
|
||||
* Get the validation rules that apply to the service.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'account_id' => 'required|integer|exists:accounts,id',
|
||||
'conversation_id' => 'required|integer|exists:conversations,id',
|
||||
'message_id' => 'required|integer|exists:messages,id',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroy a message.
|
||||
*
|
||||
* @param array $data
|
||||
* @return bool
|
||||
*/
|
||||
public function execute(array $data): bool
|
||||
{
|
||||
$this->validate($data);
|
||||
|
||||
Conversation::where('account_id', $data['account_id'])
|
||||
->findOrFail($data['conversation_id']);
|
||||
|
||||
$message = Message::where('account_id', $data['account_id'])
|
||||
->where('conversation_id', $data['conversation_id'])
|
||||
->findOrFail($data['message_id']);
|
||||
|
||||
$message->contact->throwInactive();
|
||||
|
||||
$message->delete();
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
57
app/Services/Contact/Conversation/UpdateConversation.php
Normal file
57
app/Services/Contact/Conversation/UpdateConversation.php
Normal file
@@ -0,0 +1,57 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This is a single action class, totally inspired by
|
||||
* https://medium.com/@remi_collin/keeping-your-laravel-applications-dry-with-single-action-classes-6a950ec54d1d.
|
||||
*/
|
||||
|
||||
namespace App\Services\Contact\Conversation;
|
||||
|
||||
use App\Services\BaseService;
|
||||
use App\Models\Contact\Conversation;
|
||||
use App\Models\Contact\ContactFieldType;
|
||||
|
||||
class UpdateConversation extends BaseService
|
||||
{
|
||||
/**
|
||||
* Get the validation rules that apply to the service.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'account_id' => 'required|integer|exists:accounts,id',
|
||||
'happened_at' => 'required|date',
|
||||
'contact_field_type_id' => 'required|integer',
|
||||
'conversation_id' => 'required|integer|exists:conversations,id',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Update a conversation.
|
||||
*
|
||||
* @param array $data
|
||||
* @return Conversation
|
||||
*/
|
||||
public function execute(array $data): Conversation
|
||||
{
|
||||
$this->validate($data);
|
||||
|
||||
/** @var Conversation */
|
||||
$conversation = Conversation::where('account_id', $data['account_id'])
|
||||
->findOrFail($data['conversation_id']);
|
||||
|
||||
$conversation->contact->throwInactive();
|
||||
|
||||
ContactFieldType::where('account_id', $data['account_id'])
|
||||
->findOrFail($data['contact_field_type_id']);
|
||||
|
||||
$conversation->update([
|
||||
'happened_at' => $data['happened_at'],
|
||||
'contact_field_type_id' => $data['contact_field_type_id'],
|
||||
]);
|
||||
|
||||
return $conversation;
|
||||
}
|
||||
}
|
||||
68
app/Services/Contact/Conversation/UpdateMessage.php
Normal file
68
app/Services/Contact/Conversation/UpdateMessage.php
Normal file
@@ -0,0 +1,68 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This is a single action class, totally inspired by
|
||||
* https://medium.com/@remi_collin/keeping-your-laravel-applications-dry-with-single-action-classes-6a950ec54d1d.
|
||||
*/
|
||||
|
||||
namespace App\Services\Contact\Conversation;
|
||||
|
||||
use App\Services\BaseService;
|
||||
use App\Models\Contact\Contact;
|
||||
use App\Models\Contact\Message;
|
||||
use App\Models\Contact\Conversation;
|
||||
|
||||
class UpdateMessage extends BaseService
|
||||
{
|
||||
/**
|
||||
* Get the validation rules that apply to the service.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'account_id' => 'required|integer|exists:accounts,id',
|
||||
'contact_id' => 'required|integer|exists:contacts,id',
|
||||
'conversation_id' => 'required|integer|exists:conversations,id',
|
||||
'message_id' => 'required|integer|exists:messages,id',
|
||||
'written_at' => 'required|date',
|
||||
'written_by_me' => 'required|boolean',
|
||||
'content' => 'required|string',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Update message in a conversation.
|
||||
*
|
||||
* @param array $data
|
||||
* @return Message
|
||||
*/
|
||||
public function execute(array $data): Message
|
||||
{
|
||||
$this->validate($data);
|
||||
|
||||
$contact = Contact::where('account_id', $data['account_id'])
|
||||
->findOrFail($data['contact_id']);
|
||||
|
||||
$contact->throwInactive();
|
||||
|
||||
Conversation::where('contact_id', $data['contact_id'])
|
||||
->where('account_id', $data['account_id'])
|
||||
->findOrFail($data['conversation_id']);
|
||||
|
||||
/** @var Message */
|
||||
$message = Message::where('contact_id', $data['contact_id'])
|
||||
->where('conversation_id', $data['conversation_id'])
|
||||
->where('account_id', $data['account_id'])
|
||||
->findOrFail($data['message_id']);
|
||||
|
||||
$message->update([
|
||||
'written_at' => $data['written_at'],
|
||||
'written_by_me' => $data['written_by_me'],
|
||||
'content' => $data['content'],
|
||||
]);
|
||||
|
||||
return $message;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Contact\Description;
|
||||
|
||||
use App\Models\User\User;
|
||||
use App\Services\BaseService;
|
||||
use function Safe\json_encode;
|
||||
use App\Models\Contact\Contact;
|
||||
use App\Jobs\AuditLog\LogAccountAudit;
|
||||
|
||||
class ClearPersonalDescription extends BaseService
|
||||
{
|
||||
/**
|
||||
* Get the validation rules that apply to the service.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules(): array
|
||||
{
|
||||
return [
|
||||
'account_id' => 'required|integer|exists:accounts,id',
|
||||
'contact_id' => 'required|integer|exists:contacts,id',
|
||||
'author_id' => 'required|integer|exists:users,id',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear a contact's description.
|
||||
*
|
||||
* @param array $data
|
||||
* @return Contact
|
||||
*/
|
||||
public function execute(array $data): Contact
|
||||
{
|
||||
$this->validate($data);
|
||||
|
||||
/** @var Contact */
|
||||
$contact = Contact::where('account_id', $data['account_id'])
|
||||
->findOrFail($data['contact_id']);
|
||||
|
||||
$contact->throwInactive();
|
||||
|
||||
$contact->description = null;
|
||||
$contact->save();
|
||||
|
||||
$this->log($data, $contact);
|
||||
|
||||
return $contact;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an audit log.
|
||||
*
|
||||
* @param array $data
|
||||
* @param Contact $contact
|
||||
* @return void
|
||||
*/
|
||||
private function log(array $data, Contact $contact): void
|
||||
{
|
||||
$author = User::find($data['author_id']);
|
||||
|
||||
LogAccountAudit::dispatch([
|
||||
'action' => 'contact_description_cleared',
|
||||
'account_id' => $author->account_id,
|
||||
'about_contact_id' => $contact->id,
|
||||
'author_id' => $author->id,
|
||||
'author_name' => $author->name,
|
||||
'audited_at' => now(),
|
||||
'should_appear_on_dashboard' => true,
|
||||
'objects' => json_encode([
|
||||
'contact_name' => $contact->name,
|
||||
'contact_id' => $contact->id,
|
||||
]),
|
||||
]);
|
||||
}
|
||||
}
|
||||
80
app/Services/Contact/Description/SetPersonalDescription.php
Normal file
80
app/Services/Contact/Description/SetPersonalDescription.php
Normal file
@@ -0,0 +1,80 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Contact\Description;
|
||||
|
||||
use App\Models\User\User;
|
||||
use App\Services\BaseService;
|
||||
use function Safe\json_encode;
|
||||
use App\Models\Contact\Contact;
|
||||
use App\Jobs\AuditLog\LogAccountAudit;
|
||||
|
||||
class SetPersonalDescription extends BaseService
|
||||
{
|
||||
/**
|
||||
* Get the validation rules that apply to the service.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules(): array
|
||||
{
|
||||
return [
|
||||
'account_id' => 'required|integer|exists:accounts,id',
|
||||
'contact_id' => 'required|integer|exists:contacts,id',
|
||||
'author_id' => 'required|integer|exists:users,id',
|
||||
'description' => 'nullable|string|max:255',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a contact's description.
|
||||
* The description should be saved as unparsed markdown content, and fetched
|
||||
* as unparsed markdown content. The UI is responsible for parsing and
|
||||
* displaying the proper content.
|
||||
*
|
||||
* @param array $data
|
||||
* @return Contact
|
||||
*/
|
||||
public function execute(array $data): Contact
|
||||
{
|
||||
$this->validate($data);
|
||||
|
||||
/** @var Contact $contact */
|
||||
$contact = Contact::where('account_id', $data['account_id'])
|
||||
->findOrFail($data['contact_id']);
|
||||
|
||||
$contact->throwInactive();
|
||||
|
||||
$contact->description = $data['description'];
|
||||
$contact->save();
|
||||
|
||||
$this->log($data, $contact);
|
||||
|
||||
return $contact->refresh();
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an audit log.
|
||||
*
|
||||
* @param array $data
|
||||
* @param Contact $contact
|
||||
* @return void
|
||||
*/
|
||||
private function log(array $data, Contact $contact): void
|
||||
{
|
||||
$author = User::find($data['author_id']);
|
||||
|
||||
LogAccountAudit::dispatch([
|
||||
'action' => 'contact_description_updated',
|
||||
'account_id' => $author->account_id,
|
||||
'about_contact_id' => $contact->id,
|
||||
'author_id' => $author->id,
|
||||
'author_name' => $author->name,
|
||||
'audited_at' => now(),
|
||||
'should_appear_on_dashboard' => true,
|
||||
'objects' => json_encode([
|
||||
'contact_name' => $contact->name,
|
||||
'contact_id' => $contact->id,
|
||||
]),
|
||||
]);
|
||||
}
|
||||
}
|
||||
46
app/Services/Contact/Document/DestroyDocument.php
Normal file
46
app/Services/Contact/Document/DestroyDocument.php
Normal file
@@ -0,0 +1,46 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Contact\Document;
|
||||
|
||||
use App\Services\BaseService;
|
||||
use App\Models\Contact\Document;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
|
||||
class DestroyDocument extends BaseService
|
||||
{
|
||||
/**
|
||||
* Get the validation rules that apply to the service.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'account_id' => 'required|integer|exists:accounts,id',
|
||||
'document_id' => 'required|integer',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroy a document.
|
||||
*
|
||||
* @param array $data
|
||||
* @return bool
|
||||
*/
|
||||
public function execute(array $data): bool
|
||||
{
|
||||
$this->validate($data);
|
||||
|
||||
$document = Document::where('account_id', $data['account_id'])
|
||||
->findOrFail($data['document_id']);
|
||||
|
||||
// Delete the physical document
|
||||
// Throws FileNotFoundException
|
||||
Storage::delete($document->new_filename);
|
||||
|
||||
// Delete the object in the DB
|
||||
$document->delete();
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
79
app/Services/Contact/Document/UploadDocument.php
Normal file
79
app/Services/Contact/Document/UploadDocument.php
Normal file
@@ -0,0 +1,79 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Contact\Document;
|
||||
|
||||
use App\Services\BaseService;
|
||||
use App\Helpers\AccountHelper;
|
||||
use App\Models\Account\Account;
|
||||
use App\Models\Contact\Contact;
|
||||
use App\Models\Contact\Document;
|
||||
|
||||
class UploadDocument extends BaseService
|
||||
{
|
||||
/**
|
||||
* Get the validation rules that apply to the service.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'account_id' => 'required|integer|exists:accounts,id',
|
||||
'contact_id' => 'required|integer',
|
||||
'document' => 'required|file',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Upload a document.
|
||||
*
|
||||
* @param array $data
|
||||
* @return Document
|
||||
*/
|
||||
public function execute(array $data): Document
|
||||
{
|
||||
$this->validate($data);
|
||||
|
||||
$account = Account::find($data['account_id']);
|
||||
if (AccountHelper::hasLimitations($account)) {
|
||||
abort(402);
|
||||
}
|
||||
|
||||
$contact = Contact::where('account_id', $data['account_id'])
|
||||
->findOrFail($data['contact_id']);
|
||||
|
||||
$contact->throwInactive();
|
||||
|
||||
$array = $this->populateData($data);
|
||||
|
||||
return Document::create($array);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an array with the necessary fields to create the document object.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function populateData($data)
|
||||
{
|
||||
$document = $data['document'];
|
||||
|
||||
$data = [
|
||||
'account_id' => $data['account_id'],
|
||||
'contact_id' => $data['contact_id'],
|
||||
'original_filename' => $document->getClientOriginalName(),
|
||||
'filesize' => $document->getSize(),
|
||||
'type' => $document->guessClientExtension(),
|
||||
'mime_type' => (new \Mimey\MimeTypes)->getMimeType($document->guessClientExtension()),
|
||||
];
|
||||
|
||||
$filename = $document->store('documents', [
|
||||
'disk' => config('filesystems.default'),
|
||||
'visibility' => config('filesystems.default_visibility'),
|
||||
]);
|
||||
|
||||
return array_merge($data, [
|
||||
'new_filename' => $filename,
|
||||
]);
|
||||
}
|
||||
}
|
||||
46
app/Services/Contact/Gift/AssociatePhotoToGift.php
Normal file
46
app/Services/Contact/Gift/AssociatePhotoToGift.php
Normal file
@@ -0,0 +1,46 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Contact\Gift;
|
||||
|
||||
use App\Models\Contact\Gift;
|
||||
use App\Models\Account\Photo;
|
||||
use App\Services\BaseService;
|
||||
|
||||
class AssociatePhotoToGift extends BaseService
|
||||
{
|
||||
/**
|
||||
* Get the validation rules that apply to the service.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'account_id' => 'required|integer|exists:accounts,id',
|
||||
'photo_id' => 'required|integer|exists:photos,id',
|
||||
'gift_id' => 'required|integer|exists:gifts,id',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Link a photo to a gift.
|
||||
*
|
||||
* @param array $data
|
||||
*/
|
||||
public function execute(array $data)
|
||||
{
|
||||
$this->validate($data);
|
||||
|
||||
$photo = Photo::where('account_id', $data['account_id'])
|
||||
->findOrFail($data['photo_id']);
|
||||
|
||||
$gift = Gift::where('account_id', $data['account_id'])
|
||||
->findOrFail($data['gift_id']);
|
||||
|
||||
$gift->contact->throwInactive();
|
||||
|
||||
$gift->photos()->syncWithoutDetaching([$photo->id]);
|
||||
|
||||
return $gift;
|
||||
}
|
||||
}
|
||||
80
app/Services/Contact/Gift/CreateGift.php
Normal file
80
app/Services/Contact/Gift/CreateGift.php
Normal file
@@ -0,0 +1,80 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Contact\Gift;
|
||||
|
||||
use App\Models\Contact\Gift;
|
||||
use App\Services\BaseService;
|
||||
use App\Models\Contact\Contact;
|
||||
use Illuminate\Validation\Rule;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
|
||||
class CreateGift extends BaseService
|
||||
{
|
||||
/**
|
||||
* Get the validation rules that apply to the service.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'account_id' => 'required|integer|exists:accounts,id',
|
||||
'contact_id' => 'required|integer|exists:contacts,id',
|
||||
'name' => 'required|string|max:255',
|
||||
'status' => [
|
||||
'required',
|
||||
Rule::in([
|
||||
'idea',
|
||||
'offered',
|
||||
'received',
|
||||
]),
|
||||
],
|
||||
'comment' => 'string|max:1000000|nullable',
|
||||
'url' => 'string|max:1000000|nullable',
|
||||
'amount' => 'numeric|nullable',
|
||||
'date' => 'date|nullable',
|
||||
'recipient_id' => 'integer|nullable|exists:contacts,id',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a tag.
|
||||
*
|
||||
* @param array $data
|
||||
* @return Gift
|
||||
*/
|
||||
public function execute(array $data): Gift
|
||||
{
|
||||
$this->validate($data);
|
||||
|
||||
$contact = Contact::where('account_id', $data['account_id'])
|
||||
->findOrFail($data['contact_id']);
|
||||
|
||||
$contact->throwInactive();
|
||||
|
||||
if (isset($data['recipient_id'])) {
|
||||
Contact::where('account_id', $data['account_id'])
|
||||
->findOrFail($data['recipient_id']);
|
||||
}
|
||||
|
||||
$array = [
|
||||
'account_id' => $data['account_id'],
|
||||
'contact_id' => $data['contact_id'],
|
||||
'name' => $data['name'],
|
||||
'status' => $data['status'],
|
||||
'comment' => $this->nullOrvalue($data, 'comment'),
|
||||
'url' => $this->nullOrvalue($data, 'url'),
|
||||
'amount' => $this->nullOrvalue($data, 'amount'),
|
||||
'date' => $this->nullOrvalue($data, 'date'),
|
||||
];
|
||||
|
||||
if (Auth::check()) {
|
||||
$array['currency_id'] = Auth::user()->currency->id;
|
||||
}
|
||||
|
||||
return tap(Gift::create($array), function ($gift) use ($data): void {
|
||||
$gift->recipient = $this->nullOrvalue($data, 'recipient_id');
|
||||
$gift->save();
|
||||
});
|
||||
}
|
||||
}
|
||||
44
app/Services/Contact/Gift/DestroyGift.php
Normal file
44
app/Services/Contact/Gift/DestroyGift.php
Normal file
@@ -0,0 +1,44 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Contact\Gift;
|
||||
|
||||
use App\Models\Contact\Gift;
|
||||
use App\Services\BaseService;
|
||||
|
||||
class DestroyGift extends BaseService
|
||||
{
|
||||
/**
|
||||
* Get the validation rules that apply to the service.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'account_id' => 'required|integer|exists:accounts,id',
|
||||
'gift_id' => 'required|integer|exists:gifts,id',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroy a gift.
|
||||
*
|
||||
* @param array $data
|
||||
* @return bool
|
||||
*/
|
||||
public function execute(array $data)
|
||||
{
|
||||
$this->validate($data);
|
||||
|
||||
$gift = Gift::where('account_id', $data['account_id'])
|
||||
->findOrFail($data['gift_id']);
|
||||
|
||||
$gift->contact->throwInactive();
|
||||
|
||||
$gift->photos()->detach();
|
||||
|
||||
$gift->delete();
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
85
app/Services/Contact/Gift/UpdateGift.php
Normal file
85
app/Services/Contact/Gift/UpdateGift.php
Normal file
@@ -0,0 +1,85 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Contact\Gift;
|
||||
|
||||
use App\Models\Contact\Gift;
|
||||
use App\Services\BaseService;
|
||||
use App\Models\Contact\Contact;
|
||||
use Illuminate\Validation\Rule;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
|
||||
class UpdateGift extends BaseService
|
||||
{
|
||||
/**
|
||||
* Get the validation rules that apply to the service.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'account_id' => 'required|integer|exists:accounts,id',
|
||||
'gift_id' => 'required|integer|exists:gifts,id',
|
||||
'contact_id' => 'required|integer|exists:contacts,id',
|
||||
'name' => 'required|string|max:255',
|
||||
'status' => [
|
||||
'required',
|
||||
Rule::in([
|
||||
'idea',
|
||||
'offered',
|
||||
'received',
|
||||
]),
|
||||
],
|
||||
'comment' => 'string|max:1000000|nullable',
|
||||
'url' => 'string|max:1000000|nullable',
|
||||
'amount' => 'numeric|nullable',
|
||||
'date' => 'date|nullable',
|
||||
'recipient_id' => 'integer|nullable|exists:contacts,id',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Update a gift.
|
||||
*
|
||||
* @param array $data
|
||||
* @return Gift
|
||||
*/
|
||||
public function execute(array $data): Gift
|
||||
{
|
||||
$this->validate($data);
|
||||
|
||||
$gift = Gift::where('account_id', $data['account_id'])
|
||||
->findOrFail((int) $data['gift_id']);
|
||||
|
||||
$contact = Contact::where('account_id', $data['account_id'])
|
||||
->findOrFail($data['contact_id']);
|
||||
|
||||
$contact->throwInactive();
|
||||
|
||||
if (isset($data['recipient_id'])) {
|
||||
Contact::where('account_id', $data['account_id'])
|
||||
->findOrFail($data['recipient_id']);
|
||||
}
|
||||
|
||||
$array = [
|
||||
'contact_id' => $data['contact_id'],
|
||||
'name' => $data['name'],
|
||||
'status' => $data['status'],
|
||||
'comment' => $this->nullOrvalue($data, 'comment'),
|
||||
'url' => $this->nullOrvalue($data, 'url'),
|
||||
'amount' => $this->nullOrvalue($data, 'amount'),
|
||||
'date' => $this->nullOrvalue($data, 'date'),
|
||||
];
|
||||
|
||||
if (Auth::check()) {
|
||||
$array['currency_id'] = Auth::user()->currency->id;
|
||||
}
|
||||
|
||||
$gift->update($array);
|
||||
|
||||
return tap($gift, function ($gift) use ($data): void {
|
||||
$gift->recipient = $this->nullOrvalue($data, 'recipient_id');
|
||||
$gift->save();
|
||||
});
|
||||
}
|
||||
}
|
||||
88
app/Services/Contact/Label/UpdateAddressLabels.php
Normal file
88
app/Services/Contact/Label/UpdateAddressLabels.php
Normal file
@@ -0,0 +1,88 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Contact\Label;
|
||||
|
||||
use App\Services\BaseService;
|
||||
use App\Models\Contact\Address;
|
||||
use App\Models\Contact\ContactFieldLabel;
|
||||
|
||||
class UpdateAddressLabels extends BaseService
|
||||
{
|
||||
/**
|
||||
* Get the validation rules that apply to the service.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'account_id' => 'required|integer|exists:accounts,id',
|
||||
'address_id' => 'required|integer|exists:addresses,id',
|
||||
'labels' => 'required|array',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Update address' labels.
|
||||
*
|
||||
* @param array $data
|
||||
* @return void
|
||||
*/
|
||||
public function execute(array $data)
|
||||
{
|
||||
$this->validate($data);
|
||||
|
||||
$address = Address::where('account_id', $data['account_id'])
|
||||
->findOrFail($data['address_id']);
|
||||
|
||||
$address->contact->throwInactive();
|
||||
|
||||
$labelsId = $this->getLabelsId($data);
|
||||
|
||||
$this->updateLabels($labelsId, $address);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get ContactFieldLabel ids.
|
||||
*
|
||||
* @param array $data
|
||||
* @return array
|
||||
*/
|
||||
private function getLabelsId(array $data): array
|
||||
{
|
||||
$labelsId = [];
|
||||
foreach ($data['labels'] as $label) {
|
||||
$label2 = mb_strtolower($label);
|
||||
if (in_array($label2, ContactFieldLabel::$standardLabels)) {
|
||||
$labelsId[] = (ContactFieldLabel::firstOrCreate([
|
||||
'account_id' => $data['account_id'],
|
||||
'label_i18n' => $label2,
|
||||
]))->id;
|
||||
} else {
|
||||
$labelsId[] = (ContactFieldLabel::firstOrCreate([
|
||||
'account_id' => $data['account_id'],
|
||||
'label' => $label,
|
||||
]))->id;
|
||||
}
|
||||
}
|
||||
|
||||
return $labelsId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update contactField's labels.
|
||||
*
|
||||
* @param array $labelsId
|
||||
* @param Address $address
|
||||
* @return void
|
||||
*/
|
||||
private function updateLabels(array $labelsId, Address $address)
|
||||
{
|
||||
$labelsSync = [];
|
||||
foreach ($labelsId as $labelId) {
|
||||
$labelsSync[$labelId] = ['account_id' => $address->account_id];
|
||||
}
|
||||
|
||||
$address->labels()->sync($labelsSync);
|
||||
}
|
||||
}
|
||||
89
app/Services/Contact/Label/UpdateContactFieldLabels.php
Normal file
89
app/Services/Contact/Label/UpdateContactFieldLabels.php
Normal file
@@ -0,0 +1,89 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Contact\Label;
|
||||
|
||||
use App\Services\BaseService;
|
||||
use App\Models\Contact\ContactField;
|
||||
use App\Models\Contact\ContactFieldLabel;
|
||||
|
||||
class UpdateContactFieldLabels extends BaseService
|
||||
{
|
||||
/**
|
||||
* Get the validation rules that apply to the service.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'account_id' => 'required|integer|exists:accounts,id',
|
||||
'contact_field_id' => 'required|integer|exists:contact_fields,id',
|
||||
'labels' => 'required|array',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Update contact field's labels.
|
||||
*
|
||||
* @param array $data
|
||||
* @return void
|
||||
*/
|
||||
public function execute(array $data)
|
||||
{
|
||||
$this->validate($data);
|
||||
|
||||
$contactField = ContactField::where('account_id', $data['account_id'])
|
||||
->findOrFail($data['contact_field_id']);
|
||||
|
||||
$contactField->contact->throwInactive();
|
||||
|
||||
$labelsId = $this->getLabelsId($data);
|
||||
|
||||
$this->updateLabels($labelsId, $contactField);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get ContactFieldLabel ids.
|
||||
*
|
||||
* @param array $data
|
||||
* @return array
|
||||
*/
|
||||
private function getLabelsId(array $data): array
|
||||
{
|
||||
$labelsId = [];
|
||||
foreach ($data['labels'] as $label) {
|
||||
$label2 = mb_strtolower($label);
|
||||
$s = ContactFieldLabel::$standardLabels;
|
||||
if (in_array($label2, ContactFieldLabel::$standardLabels)) {
|
||||
$labelsId[] = (ContactFieldLabel::firstOrCreate([
|
||||
'account_id' => $data['account_id'],
|
||||
'label_i18n' => $label2,
|
||||
]))->id;
|
||||
} else {
|
||||
$labelsId[] = (ContactFieldLabel::firstOrCreate([
|
||||
'account_id' => $data['account_id'],
|
||||
'label' => $label,
|
||||
]))->id;
|
||||
}
|
||||
}
|
||||
|
||||
return $labelsId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update contactField's labels.
|
||||
*
|
||||
* @param array $labelsId
|
||||
* @param ContactField $contactField
|
||||
* @return void
|
||||
*/
|
||||
private function updateLabels(array $labelsId, ContactField $contactField)
|
||||
{
|
||||
$labelsSync = [];
|
||||
foreach ($labelsId as $labelId) {
|
||||
$labelsSync[$labelId] = ['account_id' => $contactField->account_id];
|
||||
}
|
||||
|
||||
$contactField->labels()->sync($labelsSync);
|
||||
}
|
||||
}
|
||||
97
app/Services/Contact/LifeEvent/CreateLifeEvent.php
Normal file
97
app/Services/Contact/LifeEvent/CreateLifeEvent.php
Normal file
@@ -0,0 +1,97 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Contact\LifeEvent;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use App\Services\BaseService;
|
||||
use App\Models\Contact\Contact;
|
||||
use App\Models\Contact\LifeEvent;
|
||||
use App\Models\Contact\LifeEventType;
|
||||
use App\Services\Contact\Reminder\CreateReminder;
|
||||
|
||||
class CreateLifeEvent extends BaseService
|
||||
{
|
||||
/**
|
||||
* Get the validation rules that apply to the service.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'account_id' => 'required|integer|exists:accounts,id',
|
||||
'contact_id' => 'required|integer',
|
||||
'life_event_type_id' => 'required|integer',
|
||||
'happened_at' => 'required|date',
|
||||
'name' => 'nullable|string',
|
||||
'note' => 'nullable|string',
|
||||
'has_reminder' => 'required|boolean',
|
||||
'happened_at_month_unknown' => 'required|boolean',
|
||||
'happened_at_day_unknown' => 'required|boolean',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a life event.
|
||||
*
|
||||
* @param array $data
|
||||
* @return LifeEvent
|
||||
*/
|
||||
public function execute(array $data): LifeEvent
|
||||
{
|
||||
$this->validate($data);
|
||||
|
||||
$contact = Contact::where('account_id', $data['account_id'])
|
||||
->findOrFail($data['contact_id']);
|
||||
|
||||
$contact->throwInactive();
|
||||
|
||||
LifeEventType::where('account_id', $data['account_id'])
|
||||
->findOrFail($data['life_event_type_id']);
|
||||
|
||||
$lifeEvent = new LifeEvent;
|
||||
$lifeEvent->account_id = $data['account_id'];
|
||||
$lifeEvent->contact_id = $data['contact_id'];
|
||||
$lifeEvent->life_event_type_id = $data['life_event_type_id'];
|
||||
$lifeEvent->happened_at = $data['happened_at'];
|
||||
$lifeEvent->name = $data['name'];
|
||||
$lifeEvent->note = $data['note'];
|
||||
$lifeEvent->happened_at_month_unknown = $data['happened_at_month_unknown'];
|
||||
$lifeEvent->happened_at_day_unknown = $data['happened_at_day_unknown'];
|
||||
$lifeEvent->save();
|
||||
|
||||
$this->addYearlyReminder($data, $lifeEvent);
|
||||
|
||||
// Get the newly created object as the Create method doesn't return all
|
||||
// fields by default
|
||||
return LifeEvent::find($lifeEvent->id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add yearly reminder if necessary.
|
||||
*
|
||||
* @param array $data
|
||||
* @param LifeEvent $lifeEvent
|
||||
*/
|
||||
private function addYearlyReminder($data, $lifeEvent)
|
||||
{
|
||||
if ($data['has_reminder']) {
|
||||
$date = Carbon::parse($data['happened_at']);
|
||||
|
||||
$data = [
|
||||
'contact_id' => $data['contact_id'],
|
||||
'account_id' => $data['account_id'],
|
||||
'initial_date' => $date->toDateString(),
|
||||
'frequency_type' => 'year',
|
||||
'frequency_number' => 1,
|
||||
'title' => $lifeEvent->lifeEventType->name,
|
||||
'description' => null,
|
||||
];
|
||||
|
||||
$reminder = app(CreateReminder::class)->execute($data);
|
||||
|
||||
$lifeEvent->reminder_id = $reminder->id;
|
||||
$lifeEvent->save();
|
||||
}
|
||||
}
|
||||
}
|
||||
55
app/Services/Contact/LifeEvent/DestroyLifeEvent.php
Normal file
55
app/Services/Contact/LifeEvent/DestroyLifeEvent.php
Normal file
@@ -0,0 +1,55 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Contact\LifeEvent;
|
||||
|
||||
use App\Services\BaseService;
|
||||
use App\Models\Contact\Reminder;
|
||||
use App\Models\Contact\LifeEvent;
|
||||
|
||||
class DestroyLifeEvent extends BaseService
|
||||
{
|
||||
/**
|
||||
* Get the validation rules that apply to the service.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'account_id' => 'required|integer|exists:accounts,id',
|
||||
'life_event_id' => 'required|integer',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroy a life event.
|
||||
*
|
||||
* @param array $data
|
||||
* @return bool
|
||||
*/
|
||||
public function execute(array $data): bool
|
||||
{
|
||||
$this->validate($data);
|
||||
|
||||
$lifeEvent = LifeEvent::where('account_id', $data['account_id'])
|
||||
->findOrFail($data['life_event_id']);
|
||||
|
||||
$lifeEvent->contact->throwInactive();
|
||||
|
||||
$this->deleteAssociatedReminder($lifeEvent);
|
||||
|
||||
$lifeEvent->delete();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete the associated reminder, if it's set.
|
||||
*/
|
||||
private function deleteAssociatedReminder($lifeEvent)
|
||||
{
|
||||
if ($lifeEvent->reminder_id) {
|
||||
Reminder::where('id', $lifeEvent->reminder_id)->delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
56
app/Services/Contact/LifeEvent/UpdateLifeEvent.php
Normal file
56
app/Services/Contact/LifeEvent/UpdateLifeEvent.php
Normal file
@@ -0,0 +1,56 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Contact\LifeEvent;
|
||||
|
||||
use App\Services\BaseService;
|
||||
use App\Models\Contact\LifeEvent;
|
||||
use App\Models\Contact\LifeEventType;
|
||||
|
||||
class UpdateLifeEvent extends BaseService
|
||||
{
|
||||
/**
|
||||
* Get the validation rules that apply to the service.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'account_id' => 'required|integer|exists:accounts,id',
|
||||
'life_event_id' => 'required|integer',
|
||||
'life_event_type_id' => 'required|integer',
|
||||
'happened_at' => 'required|date',
|
||||
'name' => 'nullable|string',
|
||||
'note' => 'nullable|string',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Update a life event.
|
||||
*
|
||||
* @param array $data
|
||||
* @return LifeEvent
|
||||
*/
|
||||
public function execute(array $data): LifeEvent
|
||||
{
|
||||
$this->validate($data);
|
||||
|
||||
/** @var LifeEvent */
|
||||
$lifeEvent = LifeEvent::where('account_id', $data['account_id'])
|
||||
->findOrFail($data['life_event_id']);
|
||||
|
||||
$lifeEvent->contact->throwInactive();
|
||||
|
||||
LifeEventType::where('account_id', $data['account_id'])
|
||||
->findOrFail($data['life_event_type_id']);
|
||||
|
||||
$lifeEvent->update([
|
||||
'happened_at' => $data['happened_at'],
|
||||
'life_event_type_id' => $data['life_event_type_id'],
|
||||
'name' => $data['name'],
|
||||
'note' => $data['note'],
|
||||
]);
|
||||
|
||||
return $lifeEvent;
|
||||
}
|
||||
}
|
||||
64
app/Services/Contact/Occupation/CreateOccupation.php
Normal file
64
app/Services/Contact/Occupation/CreateOccupation.php
Normal file
@@ -0,0 +1,64 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Contact\Occupation;
|
||||
|
||||
use App\Services\BaseService;
|
||||
use App\Models\Contact\Contact;
|
||||
use Illuminate\Validation\Rule;
|
||||
use App\Models\Contact\Occupation;
|
||||
|
||||
class CreateOccupation extends BaseService
|
||||
{
|
||||
/**
|
||||
* Get the validation rules that apply to the service.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'account_id' => 'required|integer|exists:accounts,id',
|
||||
'contact_id' => 'required|integer|exists:contacts,id',
|
||||
'company_id' => 'required|integer|exists:companies,id',
|
||||
'title' => 'required|string|max:255',
|
||||
'description' => 'nullable|string|max:1000',
|
||||
'salary' => 'nullable|integer',
|
||||
'salary_unit' => [
|
||||
'nullable',
|
||||
Rule::in(Occupation::$salaryUnits),
|
||||
],
|
||||
'currently_works_here' => 'nullable|boolean',
|
||||
'start_date' => 'nullable|date_format:Y-m-d',
|
||||
'end_date' => 'nullable|date_format:Y-m-d',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a occupation.
|
||||
*
|
||||
* @param array $data
|
||||
* @return Occupation
|
||||
*/
|
||||
public function execute(array $data): Occupation
|
||||
{
|
||||
$this->validate($data);
|
||||
|
||||
$contact = Contact::where('account_id', $data['account_id'])
|
||||
->findOrFail($data['contact_id']);
|
||||
|
||||
$contact->throwInactive();
|
||||
|
||||
return Occupation::create([
|
||||
'account_id' => $data['account_id'],
|
||||
'contact_id' => $data['contact_id'],
|
||||
'company_id' => $data['company_id'],
|
||||
'title' => $data['title'],
|
||||
'description' => $this->nullOrValue($data, 'description'),
|
||||
'salary' => $this->nullOrValue($data, 'salary'),
|
||||
'salary_unit' => $this->nullOrValue($data, 'salary_unit'),
|
||||
'currently_works_here' => $this->nullOrValue($data, 'currently_works_here'),
|
||||
'start_date' => $this->nullOrDate($data, 'start_date'),
|
||||
'end_date' => $this->nullOrDate($data, 'end_date'),
|
||||
]);
|
||||
}
|
||||
}
|
||||
40
app/Services/Contact/Occupation/DestroyOccupation.php
Normal file
40
app/Services/Contact/Occupation/DestroyOccupation.php
Normal file
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Contact\Occupation;
|
||||
|
||||
use App\Services\BaseService;
|
||||
use App\Models\Contact\Occupation;
|
||||
|
||||
class DestroyOccupation extends BaseService
|
||||
{
|
||||
/**
|
||||
* Get the validation rules that apply to the service.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'account_id' => 'required|integer|exists:accounts,id',
|
||||
'occupation_id' => 'required|integer|exists:occupations,id',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroy an occupation.
|
||||
*
|
||||
* @param array $data
|
||||
* @return bool
|
||||
*/
|
||||
public function execute(array $data): bool
|
||||
{
|
||||
$this->validate($data);
|
||||
|
||||
$occupation = Occupation::where('account_id', $data['account_id'])
|
||||
->findOrFail($data['occupation_id']);
|
||||
|
||||
$occupation->delete();
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
66
app/Services/Contact/Occupation/UpdateOccupation.php
Normal file
66
app/Services/Contact/Occupation/UpdateOccupation.php
Normal file
@@ -0,0 +1,66 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Contact\Occupation;
|
||||
|
||||
use App\Services\BaseService;
|
||||
use Illuminate\Validation\Rule;
|
||||
use App\Models\Contact\Occupation;
|
||||
|
||||
class UpdateOccupation extends BaseService
|
||||
{
|
||||
/**
|
||||
* Get the validation rules that apply to the service.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'account_id' => 'required|integer|exists:accounts,id',
|
||||
'contact_id' => 'required|integer|exists:contacts,id',
|
||||
'company_id' => 'required|integer|exists:companies,id',
|
||||
'occupation_id' => 'required|integer|exists:occupations,id',
|
||||
'title' => 'required|string|max:255',
|
||||
'description' => 'nullable|string|max:1000',
|
||||
'salary' => 'nullable|integer',
|
||||
'salary_unit' => [
|
||||
'nullable',
|
||||
Rule::in(Occupation::$salaryUnits),
|
||||
],
|
||||
'currently_works_here' => 'nullable|boolean',
|
||||
'start_date' => 'nullable|date_format:Y-m-d',
|
||||
'end_date' => 'nullable|date_format:Y-m-d',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Update a occupation.
|
||||
*
|
||||
* @param array $data
|
||||
* @return Occupation
|
||||
*/
|
||||
public function execute(array $data): Occupation
|
||||
{
|
||||
$this->validate($data);
|
||||
|
||||
/** @var Occupation */
|
||||
$occupation = Occupation::where('account_id', $data['account_id'])
|
||||
->where('contact_id', $data['contact_id'])
|
||||
->where('company_id', $data['company_id'])
|
||||
->findOrFail($data['occupation_id']);
|
||||
|
||||
$occupation->contact->throwInactive();
|
||||
|
||||
$occupation->update([
|
||||
'title' => $data['title'],
|
||||
'description' => $this->nullOrValue($data, 'description'),
|
||||
'salary' => $this->nullOrValue($data, 'salary'),
|
||||
'salary_unit' => $this->nullOrValue($data, 'salary_unit'),
|
||||
'currently_works_here' => $this->nullOrValue($data, 'currently_works_here'),
|
||||
'start_date' => $this->nullOrDate($data, 'start_date'),
|
||||
'end_date' => $this->nullOrDate($data, 'end_date'),
|
||||
]);
|
||||
|
||||
return $occupation;
|
||||
}
|
||||
}
|
||||
77
app/Services/Contact/Relationship/CreateRelationship.php
Normal file
77
app/Services/Contact/Relationship/CreateRelationship.php
Normal file
@@ -0,0 +1,77 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Contact\Relationship;
|
||||
|
||||
use App\Services\BaseService;
|
||||
use App\Models\Contact\Contact;
|
||||
use App\Models\Relationship\Relationship;
|
||||
use App\Models\Relationship\RelationshipType;
|
||||
|
||||
class CreateRelationship extends BaseService
|
||||
{
|
||||
/**
|
||||
* Get the validation rules that apply to the service.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'account_id' => 'required|integer|exists:accounts,id',
|
||||
'contact_is' => 'required|integer|exists:contacts,id',
|
||||
'of_contact' => 'required|integer|exists:contacts,id',
|
||||
'relationship_type_id' => 'required|integer|exists:relationship_types,id',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a relationship between two contacts.
|
||||
*
|
||||
* @param array $data
|
||||
* @return Relationship
|
||||
*/
|
||||
public function execute(array $data): Relationship
|
||||
{
|
||||
$this->validate($data);
|
||||
|
||||
$contact = Contact::where('account_id', $data['account_id'])
|
||||
->findOrFail($data['contact_is']);
|
||||
|
||||
$contact->throwInactive();
|
||||
|
||||
$otherContact = Contact::where('account_id', $data['account_id'])
|
||||
->findOrFail($data['of_contact']);
|
||||
|
||||
$relationshipType = RelationshipType::where('account_id', $data['account_id'])
|
||||
->findOrFail($data['relationship_type_id']);
|
||||
|
||||
// create the relationship
|
||||
$relationship = $this->setRelationship($contact, $otherContact, $relationshipType);
|
||||
|
||||
$reverseRelationshipType = $relationshipType->reverseRelationshipType();
|
||||
if ($reverseRelationshipType) {
|
||||
// create the reverse relationship
|
||||
$this->setRelationship($otherContact, $contact, $reverseRelationshipType);
|
||||
}
|
||||
|
||||
return $relationship;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a relationship between two contacts.
|
||||
*
|
||||
* @param Contact $contact
|
||||
* @param Contact $otherContact
|
||||
* @param RelationshipType $relationshipType
|
||||
* @return Relationship
|
||||
*/
|
||||
public function setRelationship(Contact $contact, Contact $otherContact, RelationshipType $relationshipType): Relationship
|
||||
{
|
||||
return Relationship::create([
|
||||
'account_id' => $relationshipType->account_id,
|
||||
'relationship_type_id' => $relationshipType->id,
|
||||
'contact_is' => $contact->id,
|
||||
'of_contact' => $otherContact->id,
|
||||
]);
|
||||
}
|
||||
}
|
||||
90
app/Services/Contact/Relationship/DestroyRelationship.php
Normal file
90
app/Services/Contact/Relationship/DestroyRelationship.php
Normal file
@@ -0,0 +1,90 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Contact\Relationship;
|
||||
|
||||
use App\Services\BaseService;
|
||||
use App\Models\Contact\Contact;
|
||||
use App\Models\Relationship\Relationship;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use App\Services\Contact\Contact\DestroyContact;
|
||||
|
||||
class DestroyRelationship extends BaseService
|
||||
{
|
||||
/**
|
||||
* Get the validation rules that apply to the service.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'account_id' => 'required|integer|exists:accounts,id',
|
||||
'relationship_id' => 'required|integer|exists:relationships,id',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroy a relationship.
|
||||
*
|
||||
* @param array $data
|
||||
* @return bool
|
||||
*/
|
||||
public function execute(array $data): bool
|
||||
{
|
||||
$this->validate($data);
|
||||
|
||||
$relationship = Relationship::where('account_id', $data['account_id'])
|
||||
->findOrFail($data['relationship_id']);
|
||||
|
||||
$relationship->contactIs->throwInactive();
|
||||
|
||||
$otherContact = $relationship->ofContact;
|
||||
|
||||
$this->deleteRelationship($relationship);
|
||||
|
||||
$this->deletePartialContact($otherContact);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete relationship.
|
||||
*
|
||||
* @param Relationship $relationship
|
||||
*/
|
||||
private function deleteRelationship(Relationship $relationship)
|
||||
{
|
||||
$reverseRelationship = $relationship->reverseRelationship();
|
||||
if ($reverseRelationship) {
|
||||
$reverseRelationship->delete();
|
||||
}
|
||||
|
||||
$relationship->delete();
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete partial contact.
|
||||
*
|
||||
* @param Contact $contact
|
||||
*/
|
||||
private function deletePartialContact(Contact $contact)
|
||||
{
|
||||
// the contact is partial - if the relationship is deleted, the partial
|
||||
// contact has no reason to exist anymore
|
||||
if ($contact->is_partial) {
|
||||
$otherRelations = Relationship::where('account_id', $contact->account_id)
|
||||
->where(function (Builder $query) use ($contact) {
|
||||
return $query->where('of_contact', $contact->id)
|
||||
->orWhere('contact_is', $contact->id);
|
||||
})
|
||||
->count();
|
||||
|
||||
if ($otherRelations == 0) {
|
||||
DestroyContact::dispatch([
|
||||
'account_id' => $contact->account_id,
|
||||
'contact_id' => $contact->id,
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
69
app/Services/Contact/Relationship/UpdateRelationship.php
Normal file
69
app/Services/Contact/Relationship/UpdateRelationship.php
Normal file
@@ -0,0 +1,69 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Contact\Relationship;
|
||||
|
||||
use App\Services\BaseService;
|
||||
use App\Models\Relationship\Relationship;
|
||||
use App\Models\Relationship\RelationshipType;
|
||||
|
||||
class UpdateRelationship extends BaseService
|
||||
{
|
||||
/**
|
||||
* Get the validation rules that apply to the service.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'account_id' => 'required|integer|exists:accounts,id',
|
||||
'relationship_id' => 'required|integer|exists:relationships,id',
|
||||
'relationship_type_id' => 'required|integer|exists:relationship_types,id',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Update a relationship.
|
||||
*
|
||||
* @param array $data
|
||||
* @return Relationship
|
||||
*/
|
||||
public function execute(array $data): Relationship
|
||||
{
|
||||
$this->validate($data);
|
||||
|
||||
$relationship = Relationship::where('account_id', $data['account_id'])
|
||||
->findOrFail($data['relationship_id']);
|
||||
|
||||
$relationship->contactIs->throwInactive();
|
||||
|
||||
$newRelationshipType = RelationshipType::where('account_id', $data['account_id'])
|
||||
->findOrFail($data['relationship_type_id']);
|
||||
|
||||
$reverseRelationship = $relationship->reverseRelationship();
|
||||
if ($reverseRelationship) {
|
||||
$newReverseRelationshipType = $newRelationshipType->reverseRelationshipType();
|
||||
if ($newReverseRelationshipType) {
|
||||
$this->updateRelationship($reverseRelationship, $newReverseRelationshipType);
|
||||
}
|
||||
}
|
||||
|
||||
return $this->updateRelationship($relationship, $newRelationshipType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update one relationship.
|
||||
*
|
||||
* @param Relationship $relationship
|
||||
* @param RelationshipType $relationshipType
|
||||
* @return Relationship
|
||||
*/
|
||||
private function updateRelationship(Relationship $relationship, RelationshipType $relationshipType): Relationship
|
||||
{
|
||||
$relationship->update([
|
||||
'relationship_type_id' => $relationshipType->id,
|
||||
]);
|
||||
|
||||
return $relationship;
|
||||
}
|
||||
}
|
||||
66
app/Services/Contact/Reminder/CreateReminder.php
Normal file
66
app/Services/Contact/Reminder/CreateReminder.php
Normal file
@@ -0,0 +1,66 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Contact\Reminder;
|
||||
|
||||
use App\Services\BaseService;
|
||||
use App\Models\Contact\Contact;
|
||||
use Illuminate\Validation\Rule;
|
||||
use App\Models\Contact\Reminder;
|
||||
|
||||
class CreateReminder extends BaseService
|
||||
{
|
||||
/**
|
||||
* Get the validation rules that apply to the service.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'account_id' => 'required|integer|exists:accounts,id',
|
||||
'contact_id' => 'required|integer|exists:contacts,id',
|
||||
'initial_date' => 'required|date_format:Y-m-d',
|
||||
'frequency_type' => [
|
||||
'required',
|
||||
Rule::in(Reminder::$frequencyTypes),
|
||||
],
|
||||
'frequency_number' => 'required|integer',
|
||||
'title' => 'required|string|max:100000',
|
||||
'description' => 'nullable|max:1000000',
|
||||
'delible' => 'nullable|boolean',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a reminder.
|
||||
*
|
||||
* @param array $data
|
||||
* @return Reminder
|
||||
*/
|
||||
public function execute(array $data): Reminder
|
||||
{
|
||||
$this->validate($data);
|
||||
|
||||
$contact = Contact::where('account_id', $data['account_id'])
|
||||
->findOrFail($data['contact_id']);
|
||||
|
||||
$contact->throwInactive();
|
||||
|
||||
$reminder = Reminder::create([
|
||||
'account_id' => $data['account_id'],
|
||||
'contact_id' => $data['contact_id'],
|
||||
'title' => $data['title'],
|
||||
'description' => $this->nullOrValue($data, 'description'),
|
||||
'initial_date' => $data['initial_date'],
|
||||
'frequency_type' => $data['frequency_type'],
|
||||
'frequency_number' => $data['frequency_number'],
|
||||
'delible' => (isset($data['delible']) ? $data['delible'] : true),
|
||||
]);
|
||||
|
||||
foreach ($contact->account->users as $user) {
|
||||
$reminder->schedule($user);
|
||||
}
|
||||
|
||||
return $reminder;
|
||||
}
|
||||
}
|
||||
43
app/Services/Contact/Reminder/DestroyReminder.php
Normal file
43
app/Services/Contact/Reminder/DestroyReminder.php
Normal file
@@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Contact\Reminder;
|
||||
|
||||
use App\Services\BaseService;
|
||||
use App\Models\Contact\Reminder;
|
||||
|
||||
class DestroyReminder extends BaseService
|
||||
{
|
||||
/**
|
||||
* Get the validation rules that apply to the service.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'account_id' => 'required|integer|exists:accounts,id',
|
||||
'reminder_id' => 'required|integer|exists:reminders,id',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroy a reminder and all scheduled reminders that are associated with
|
||||
* it (in ReminderOutbox table) thanks to foreign keys.
|
||||
*
|
||||
* @param array $data
|
||||
* @return bool
|
||||
*/
|
||||
public function execute(array $data): bool
|
||||
{
|
||||
$this->validate($data);
|
||||
|
||||
$reminder = Reminder::where('account_id', $data['account_id'])
|
||||
->findOrFail($data['reminder_id']);
|
||||
|
||||
$reminder->contact->throwInactive();
|
||||
|
||||
$reminder->delete();
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
70
app/Services/Contact/Reminder/UpdateReminder.php
Normal file
70
app/Services/Contact/Reminder/UpdateReminder.php
Normal file
@@ -0,0 +1,70 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Contact\Reminder;
|
||||
|
||||
use App\Services\BaseService;
|
||||
use App\Models\Contact\Contact;
|
||||
use Illuminate\Validation\Rule;
|
||||
use App\Models\Contact\Reminder;
|
||||
|
||||
class UpdateReminder extends BaseService
|
||||
{
|
||||
/**
|
||||
* Get the validation rules that apply to the service.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'account_id' => 'required|integer|exists:accounts,id',
|
||||
'contact_id' => 'required|integer|exists:contacts,id',
|
||||
'reminder_id' => 'required|integer|exists:reminders,id',
|
||||
'initial_date' => 'required|date_format:Y-m-d',
|
||||
'frequency_type' => [
|
||||
'required',
|
||||
Rule::in(Reminder::$frequencyTypes),
|
||||
],
|
||||
'frequency_number' => 'nullable|integer',
|
||||
'title' => 'required|string|max:100000',
|
||||
'description' => 'nullable|max:1000000',
|
||||
'delible' => 'nullable|boolean',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Update a reminder.
|
||||
*
|
||||
* @param array $data
|
||||
* @return Reminder
|
||||
*/
|
||||
public function execute(array $data): Reminder
|
||||
{
|
||||
$this->validate($data);
|
||||
|
||||
/** @var Reminder */
|
||||
$reminder = Reminder::where('account_id', $data['account_id'])
|
||||
->where('contact_id', $data['contact_id'])
|
||||
->findOrFail($data['reminder_id']);
|
||||
|
||||
$contact = Contact::where('account_id', $data['account_id'])
|
||||
->findOrFail($data['contact_id']);
|
||||
|
||||
$contact->throwInactive();
|
||||
|
||||
$reminder->update([
|
||||
'title' => $data['title'],
|
||||
'description' => $this->nullOrValue($data, 'description'),
|
||||
'initial_date' => $data['initial_date'],
|
||||
'frequency_type' => $data['frequency_type'],
|
||||
'frequency_number' => $this->nullOrValue($data, 'frequency_number'),
|
||||
'delible' => (isset($data['delible']) ? $data['delible'] : true),
|
||||
]);
|
||||
|
||||
foreach ($reminder->account->users as $user) {
|
||||
$reminder->schedule($user);
|
||||
}
|
||||
|
||||
return $reminder;
|
||||
}
|
||||
}
|
||||
100
app/Services/Contact/Tag/AssociateTag.php
Normal file
100
app/Services/Contact/Tag/AssociateTag.php
Normal file
@@ -0,0 +1,100 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Contact\Tag;
|
||||
|
||||
use App\Models\Contact\Tag;
|
||||
use App\Services\BaseService;
|
||||
use App\Models\Contact\Contact;
|
||||
|
||||
class AssociateTag extends BaseService
|
||||
{
|
||||
/**
|
||||
* Get the validation rules that apply to the service.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'account_id' => 'required|integer|exists:accounts,id',
|
||||
'contact_id' => 'required|integer',
|
||||
'name' => 'required|string',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Associate a tag to a contact.
|
||||
*
|
||||
* @param array $data
|
||||
* @return Tag
|
||||
*/
|
||||
public function execute(array $data): Tag
|
||||
{
|
||||
$this->validate($data);
|
||||
|
||||
$contact = Contact::where('account_id', $data['account_id'])
|
||||
->findOrFail($data['contact_id']);
|
||||
|
||||
$contact->throwInactive();
|
||||
|
||||
// check if the tag already exists in the account
|
||||
$tag = $this->tagExistOrCreate($data);
|
||||
|
||||
// associate the tag to the contact
|
||||
$this->associateToContact($tag, $contact);
|
||||
|
||||
return $tag;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the tag already exists in the account.
|
||||
* If it does, returns it.
|
||||
* If it doesn't, create it.
|
||||
*
|
||||
* @return Tag
|
||||
*/
|
||||
private function tagExistOrCreate(array $data): Tag
|
||||
{
|
||||
$tag = Tag::where([
|
||||
'account_id' => $data['account_id'],
|
||||
'name' => $data['name'],
|
||||
])
|
||||
->first();
|
||||
|
||||
if (! $tag) {
|
||||
return $this->createTag($data);
|
||||
}
|
||||
|
||||
return $tag;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the tag.
|
||||
*
|
||||
* @return Tag
|
||||
*/
|
||||
private function createTag(array $data): Tag
|
||||
{
|
||||
return app(CreateTag::class)->execute([
|
||||
'account_id' => $data['account_id'],
|
||||
'name' => $data['name'],
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Associate the tag to the contact.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function associateToContact(Tag $tag, Contact $contact)
|
||||
{
|
||||
// make sure the tag is not associated with the contact already
|
||||
$contact->tags()->detach($tag->id);
|
||||
|
||||
$contact->tags()->syncWithoutDetaching([
|
||||
$tag->id => [
|
||||
'account_id' => $contact->account_id,
|
||||
],
|
||||
]);
|
||||
}
|
||||
}
|
||||
47
app/Services/Contact/Tag/CreateTag.php
Normal file
47
app/Services/Contact/Tag/CreateTag.php
Normal file
@@ -0,0 +1,47 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Contact\Tag;
|
||||
|
||||
use App\Models\Contact\Tag;
|
||||
use Illuminate\Support\Str;
|
||||
use App\Helpers\LocaleHelper;
|
||||
use App\Services\BaseService;
|
||||
|
||||
class CreateTag extends BaseService
|
||||
{
|
||||
/**
|
||||
* Get the validation rules that apply to the service.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'account_id' => 'required|integer|exists:accounts,id',
|
||||
'name' => 'required|string',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a tag.
|
||||
*
|
||||
* @param array $data
|
||||
* @return Tag
|
||||
*/
|
||||
public function execute(array $data): Tag
|
||||
{
|
||||
$this->validate($data);
|
||||
|
||||
$array = [
|
||||
'account_id' => $data['account_id'],
|
||||
'name' => $data['name'],
|
||||
'name_slug' => Str::slug($data['name'], '-', LocaleHelper::getLang()),
|
||||
];
|
||||
|
||||
if (empty($array['name_slug'])) {
|
||||
$array['name_slug'] = htmlentities($data['name']);
|
||||
}
|
||||
|
||||
return Tag::create($array);
|
||||
}
|
||||
}
|
||||
42
app/Services/Contact/Tag/DestroyTag.php
Normal file
42
app/Services/Contact/Tag/DestroyTag.php
Normal file
@@ -0,0 +1,42 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Contact\Tag;
|
||||
|
||||
use App\Models\Contact\Tag;
|
||||
use App\Services\BaseService;
|
||||
|
||||
class DestroyTag extends BaseService
|
||||
{
|
||||
/**
|
||||
* Get the validation rules that apply to the service.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'account_id' => 'required|integer|exists:accounts,id',
|
||||
'tag_id' => 'required|integer',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroy a tag.
|
||||
*
|
||||
* @param array $data
|
||||
* @return bool
|
||||
*/
|
||||
public function execute(array $data)
|
||||
{
|
||||
$this->validate($data);
|
||||
|
||||
$tag = Tag::where('account_id', $data['account_id'])
|
||||
->findOrFail($data['tag_id']);
|
||||
|
||||
$tag->contacts()->detach();
|
||||
|
||||
$tag->delete();
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
45
app/Services/Contact/Tag/DetachTag.php
Normal file
45
app/Services/Contact/Tag/DetachTag.php
Normal file
@@ -0,0 +1,45 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Contact\Tag;
|
||||
|
||||
use App\Models\Contact\Tag;
|
||||
use App\Services\BaseService;
|
||||
use App\Models\Contact\Contact;
|
||||
|
||||
class DetachTag extends BaseService
|
||||
{
|
||||
/**
|
||||
* Get the validation rules that apply to the service.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'account_id' => 'required|integer|exists:accounts,id',
|
||||
'contact_id' => 'required|integer',
|
||||
'tag_id' => 'required|integer',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Detach the tag associated with a contact.
|
||||
*
|
||||
* @param array $data
|
||||
* @return void
|
||||
*/
|
||||
public function execute(array $data)
|
||||
{
|
||||
$this->validate($data);
|
||||
|
||||
$contact = Contact::where('account_id', $data['account_id'])
|
||||
->findOrFail($data['contact_id']);
|
||||
|
||||
$contact->throwInactive();
|
||||
|
||||
Tag::where('account_id', $data['account_id'])
|
||||
->findOrFail($data['tag_id']);
|
||||
|
||||
$contact->tags()->detach($data['tag_id']);
|
||||
}
|
||||
}
|
||||
46
app/Services/Contact/Tag/UpdateTag.php
Normal file
46
app/Services/Contact/Tag/UpdateTag.php
Normal file
@@ -0,0 +1,46 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Contact\Tag;
|
||||
|
||||
use App\Models\Contact\Tag;
|
||||
use Illuminate\Support\Str;
|
||||
use App\Helpers\LocaleHelper;
|
||||
use App\Services\BaseService;
|
||||
|
||||
class UpdateTag extends BaseService
|
||||
{
|
||||
/**
|
||||
* Get the validation rules that apply to the service.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'account_id' => 'required|integer|exists:accounts,id',
|
||||
'tag_id' => 'required|integer',
|
||||
'name' => 'required|string',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Update a tag.
|
||||
*
|
||||
* @param array $data
|
||||
* @return Tag
|
||||
*/
|
||||
public function execute(array $data): Tag
|
||||
{
|
||||
$this->validate($data);
|
||||
|
||||
/** @var Tag */
|
||||
$tag = Tag::where('account_id', $data['account_id'])
|
||||
->findOrFail($data['tag_id']);
|
||||
|
||||
$tag->name = $data['name'];
|
||||
$tag->name_slug = Str::slug($data['name'], '-', LocaleHelper::getLang());
|
||||
$tag->save();
|
||||
|
||||
return $tag;
|
||||
}
|
||||
}
|
||||
91
app/Services/DavClient/CreateAddressBookSubscription.php
Normal file
91
app/Services/DavClient/CreateAddressBookSubscription.php
Normal file
@@ -0,0 +1,91 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\DavClient;
|
||||
|
||||
use Illuminate\Support\Arr;
|
||||
use App\Services\BaseService;
|
||||
use function Safe\preg_replace;
|
||||
use App\Models\Account\AddressBook;
|
||||
use App\Models\Account\AddressBookSubscription;
|
||||
use App\Services\DavClient\Utils\Dav\DavClient;
|
||||
use App\Services\DavClient\Utils\AddressBookGetter;
|
||||
use App\Services\DavClient\Utils\Dav\DavClientException;
|
||||
|
||||
class CreateAddressBookSubscription extends BaseService
|
||||
{
|
||||
/**
|
||||
* Get the validation rules that apply to the service.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'account_id' => 'required|integer|exists:accounts,id',
|
||||
'user_id' => 'required|integer|exists:users,id',
|
||||
'base_uri' => 'required|string|url',
|
||||
'username' => 'required|string',
|
||||
'password' => 'required|string',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a new Adress Book.
|
||||
*
|
||||
* @param array $data
|
||||
* @return AddressBookSubscription|null
|
||||
*/
|
||||
public function execute(array $data): ?AddressBookSubscription
|
||||
{
|
||||
$this->validate($data);
|
||||
|
||||
$addressBookData = $this->getAddressBookData($data);
|
||||
if (! $addressBookData) {
|
||||
throw new DavClientException(__('Could not get address book data.'));
|
||||
}
|
||||
|
||||
$lastAddressBook = AddressBook::where('account_id', $data['account_id'])
|
||||
->orderBy('id', 'desc')
|
||||
->first();
|
||||
|
||||
$lastId = 0;
|
||||
if ($lastAddressBook) {
|
||||
$lastId = intval(preg_replace('/\w+(\d+)/i', '$1', $lastAddressBook->name));
|
||||
}
|
||||
$nextAddressBookName = 'contacts'.($lastId + 1);
|
||||
|
||||
$addressBook = AddressBook::create([
|
||||
'account_id' => $data['account_id'],
|
||||
'user_id' => $data['user_id'],
|
||||
'name' => $nextAddressBookName,
|
||||
'description' => $addressBookData['name'],
|
||||
]);
|
||||
$subscription = AddressBookSubscription::create([
|
||||
'account_id' => $data['account_id'],
|
||||
'user_id' => $data['user_id'],
|
||||
'username' => $data['username'],
|
||||
'address_book_id' => $addressBook->id,
|
||||
'uri' => $addressBookData['uri'],
|
||||
'capabilities' => $addressBookData['capabilities'],
|
||||
]);
|
||||
$subscription->password = $data['password'];
|
||||
$subscription->save();
|
||||
|
||||
return $subscription;
|
||||
}
|
||||
|
||||
private function getAddressBookData(array $data): ?array
|
||||
{
|
||||
$client = $this->getClient($data);
|
||||
|
||||
return app(AddressBookGetter::class)
|
||||
->execute($client);
|
||||
}
|
||||
|
||||
private function getClient(array $data): DavClient
|
||||
{
|
||||
return app(DavClient::class)
|
||||
->setBaseUri(Arr::get($data, 'base_uri'))
|
||||
->setCredentials(Arr::get($data, 'username'), Arr::get($data, 'password'));
|
||||
}
|
||||
}
|
||||
76
app/Services/DavClient/SynchronizeAddressBook.php
Normal file
76
app/Services/DavClient/SynchronizeAddressBook.php
Normal file
@@ -0,0 +1,76 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\DavClient;
|
||||
|
||||
use Illuminate\Support\Arr;
|
||||
use App\Services\BaseService;
|
||||
use App\Helpers\AccountHelper;
|
||||
use App\Models\Account\Account;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use GuzzleHttp\Exception\ClientException;
|
||||
use App\Models\Account\AddressBookSubscription;
|
||||
use App\Services\DavClient\Utils\Dav\DavClient;
|
||||
use App\Services\DavClient\Utils\Model\SyncDto;
|
||||
use App\Services\DavClient\Utils\AddressBookSynchronizer;
|
||||
|
||||
class SynchronizeAddressBook extends BaseService
|
||||
{
|
||||
/**
|
||||
* Get the validation rules that apply to the service.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'account_id' => 'required|integer|exists:accounts,id',
|
||||
'addressbook_subscription_id' => 'required|integer|exists:addressbook_subscriptions,id',
|
||||
'force' => 'nullable|boolean',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $data
|
||||
* @return void
|
||||
*/
|
||||
public function execute(array $data)
|
||||
{
|
||||
$this->validate($data);
|
||||
|
||||
$account = Account::find($data['account_id']);
|
||||
if (AccountHelper::hasReachedContactLimit($account)
|
||||
&& AccountHelper::hasLimitations($account)
|
||||
&& ! $account->legacy_free_plan_unlimited_contacts) {
|
||||
abort(402);
|
||||
}
|
||||
|
||||
$subscription = AddressBookSubscription::where('account_id', $data['account_id'])
|
||||
->findOrFail($data['addressbook_subscription_id']);
|
||||
|
||||
try {
|
||||
$this->sync($data, $subscription);
|
||||
} catch (ClientException $e) {
|
||||
Log::error(__CLASS__.' '.__FUNCTION__.': '.$e->getMessage(), [
|
||||
'body' => $e->hasResponse() ? $e->getResponse()->getBody() : null,
|
||||
$e,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
private function sync(array $data, AddressBookSubscription $subscription)
|
||||
{
|
||||
$client = $this->getDavClient($subscription);
|
||||
$sync = new SyncDto($subscription, $client);
|
||||
$force = Arr::get($data, 'force', false);
|
||||
|
||||
app(AddressBookSynchronizer::class)
|
||||
->execute($sync, $force);
|
||||
}
|
||||
|
||||
private function getDavClient(AddressBookSubscription $subscription): DavClient
|
||||
{
|
||||
return app(DavClient::class)
|
||||
->setBaseUri($subscription->uri)
|
||||
->setCredentials($subscription->username, $subscription->password);
|
||||
}
|
||||
}
|
||||
55
app/Services/DavClient/UpdateSubscriptionLocalSyncToken.php
Normal file
55
app/Services/DavClient/UpdateSubscriptionLocalSyncToken.php
Normal file
@@ -0,0 +1,55 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\DavClient;
|
||||
|
||||
use App\Services\BaseService;
|
||||
use App\Models\Account\AddressBookSubscription;
|
||||
use App\Http\Controllers\DAV\Backend\CardDAV\CardDAVBackend;
|
||||
|
||||
class UpdateSubscriptionLocalSyncToken extends BaseService
|
||||
{
|
||||
/**
|
||||
* Get the validation rules that apply to the service.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'account_id' => 'required|integer|exists:accounts,id',
|
||||
'addressbook_subscription_id' => 'required|integer|exists:addressbook_subscriptions,id',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $data
|
||||
* @return void
|
||||
*/
|
||||
public function execute(array $data): void
|
||||
{
|
||||
$this->validate($data);
|
||||
|
||||
$subscription = AddressBookSubscription::where('account_id', $data['account_id'])
|
||||
->findOrFail($data['addressbook_subscription_id']);
|
||||
|
||||
$this->updateSyncToken($subscription);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the synctoken.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function updateSyncToken(AddressBookSubscription $subscription): void
|
||||
{
|
||||
$backend = app(CardDAVBackend::class)
|
||||
->init($subscription->user);
|
||||
|
||||
$token = $backend->getCurrentSyncToken($subscription->addressbook->name);
|
||||
|
||||
if ($token !== null) {
|
||||
$subscription->localSyncToken = $token->id;
|
||||
$subscription->save();
|
||||
}
|
||||
}
|
||||
}
|
||||
118
app/Services/DavClient/Utils/AddressBookContactsPush.php
Normal file
118
app/Services/DavClient/Utils/AddressBookContactsPush.php
Normal file
@@ -0,0 +1,118 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\DavClient\Utils;
|
||||
|
||||
use App\Jobs\Dav\PushVCard;
|
||||
use Illuminate\Support\Arr;
|
||||
use App\Jobs\Dav\DeleteVCard;
|
||||
use Illuminate\Support\Collection;
|
||||
use App\Services\DavClient\Utils\Model\SyncDto;
|
||||
use App\Services\DavClient\Utils\Model\ContactDto;
|
||||
use App\Services\DavClient\Utils\Traits\WithSyncDto;
|
||||
use App\Services\DavClient\Utils\Model\ContactPushDto;
|
||||
|
||||
class AddressBookContactsPush
|
||||
{
|
||||
use WithSyncDto;
|
||||
|
||||
/**
|
||||
* Push contacts to the distant server.
|
||||
*
|
||||
* @param SyncDto $sync
|
||||
* @param Collection<array-key, ContactDto> $changes
|
||||
* @param array<array-key, string>|null $localChanges
|
||||
* @return Collection
|
||||
*/
|
||||
public function execute(SyncDto $sync, Collection $changes, ?array $localChanges): Collection
|
||||
{
|
||||
$this->sync = $sync;
|
||||
|
||||
$changes = $this->preparePushChangedContacts($changes, Arr::get($localChanges, 'modified', []));
|
||||
$added = $this->preparePushAddedContacts(Arr::get($localChanges, 'added', []));
|
||||
$deleted = $this->prepareDeletedContacts(Arr::get($localChanges, 'deleted', []));
|
||||
|
||||
return $changes
|
||||
->union($added)
|
||||
->union($deleted)
|
||||
->filter(function ($c) {
|
||||
return $c !== null;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get list of requests to push new contacts.
|
||||
*
|
||||
* @param array $contacts
|
||||
* @return Collection
|
||||
*/
|
||||
private function preparePushAddedContacts(array $contacts): Collection
|
||||
{
|
||||
// All added contact must be pushed
|
||||
return collect($contacts)
|
||||
->map(function (string $uri): ?PushVCard {
|
||||
$card = $this->backend()->getCard($this->sync->addressBookName(), $uri);
|
||||
|
||||
return $card === false ? null
|
||||
: new PushVCard($this->sync->subscription,
|
||||
new ContactPushDto(
|
||||
$uri,
|
||||
$card['distant_etag'],
|
||||
$card['carddata'],
|
||||
$card['contact_id']
|
||||
)
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get list of requests to delete contacts.
|
||||
*
|
||||
* @param array $contacts
|
||||
* @return Collection
|
||||
*/
|
||||
private function prepareDeletedContacts(array $contacts): Collection
|
||||
{
|
||||
// All removed contact must be deleted
|
||||
return collect($contacts)
|
||||
->map(function (string $uri): DeleteVCard {
|
||||
return new DeleteVCard($this->sync->subscription, $uri);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get list of requests to push modified contacts.
|
||||
*
|
||||
* @param Collection<array-key, ContactDto> $changes
|
||||
* @param array $contacts
|
||||
* @return Collection
|
||||
*/
|
||||
private function preparePushChangedContacts(Collection $changes, array $contacts): Collection
|
||||
{
|
||||
$backend = $this->backend();
|
||||
|
||||
$refreshIds = $changes->map(function (ContactDto $contact) use ($backend) {
|
||||
return $backend->getUuid($contact->uri);
|
||||
});
|
||||
|
||||
// We don't push contact that have just been pulled
|
||||
return collect($contacts)
|
||||
->reject(function (string $uri) use ($refreshIds, $backend): bool {
|
||||
$uuid = $backend->getUuid($uri);
|
||||
|
||||
return $refreshIds->contains($uuid);
|
||||
})->map(function (string $uri) use ($backend): ?PushVCard {
|
||||
$card = $backend->getCard($this->sync->addressBookName(), $uri);
|
||||
|
||||
return $card === false ? null
|
||||
: new PushVCard($this->sync->subscription,
|
||||
new ContactPushDto(
|
||||
$uri,
|
||||
$card['distant_etag'],
|
||||
$card['carddata'],
|
||||
$card['contact_id'],
|
||||
$card['distant_etag'] !== null ? ContactPushDto::MODE_MATCH_ETAG : ContactPushDto::MODE_MATCH_ANY
|
||||
)
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\DavClient\Utils;
|
||||
|
||||
use App\Jobs\Dav\PushVCard;
|
||||
use Illuminate\Support\Arr;
|
||||
use App\Models\Contact\Contact;
|
||||
use Illuminate\Support\Collection;
|
||||
use App\Services\DavClient\Utils\Model\SyncDto;
|
||||
use App\Services\DavClient\Utils\Model\ContactDto;
|
||||
use App\Services\DavClient\Utils\Traits\WithSyncDto;
|
||||
use App\Services\DavClient\Utils\Model\ContactPushDto;
|
||||
|
||||
class AddressBookContactsPushMissed
|
||||
{
|
||||
use WithSyncDto;
|
||||
|
||||
/**
|
||||
* Push contacts to the distant server.
|
||||
*
|
||||
* @param SyncDto $sync
|
||||
* @param array<array-key, string>|null $localChanges
|
||||
* @param Collection<array-key, ContactDto> $distContacts
|
||||
* @param Collection<array-key, Contact> $localContacts
|
||||
* @return Collection
|
||||
*/
|
||||
public function execute(SyncDto $sync, ?array $localChanges, Collection $distContacts, Collection $localContacts): Collection
|
||||
{
|
||||
$this->sync = $sync;
|
||||
|
||||
$missings = $this->preparePushMissedContacts(Arr::get($localChanges, 'added', []), $distContacts, $localContacts);
|
||||
|
||||
return app(AddressBookContactsPush::class)
|
||||
->execute($sync, collect(), $localChanges)
|
||||
->union($missings);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get list of requests of missed contacts.
|
||||
*
|
||||
* @param array<array-key, string> $added
|
||||
* @param Collection<array-key, ContactDto> $distContacts
|
||||
* @param Collection<array-key, Contact> $localContacts
|
||||
* @return Collection
|
||||
*/
|
||||
private function preparePushMissedContacts(array $added, Collection $distContacts, Collection $localContacts): Collection
|
||||
{
|
||||
$backend = $this->backend();
|
||||
|
||||
$distUuids = $distContacts->map(function (ContactDto $contact) use ($backend): string {
|
||||
return $backend->getUuid($contact->uri);
|
||||
});
|
||||
$addedUuids = collect($added)->map(function (string $uri) use ($backend): string {
|
||||
return $backend->getUuid($uri);
|
||||
});
|
||||
|
||||
return collect($localContacts)
|
||||
->filter(function (Contact $contact) use ($distUuids, $addedUuids) {
|
||||
return ! $distUuids->contains($contact->uuid)
|
||||
&& ! $addedUuids->contains($contact->uuid);
|
||||
})->map(function (Contact $contact) use ($backend): PushVCard {
|
||||
$card = $backend->prepareCard($contact);
|
||||
|
||||
return new PushVCard($this->sync->subscription,
|
||||
new ContactPushDto(
|
||||
$card['uri'],
|
||||
$contact->distant_etag,
|
||||
$card['carddata'],
|
||||
$contact->id,
|
||||
ContactPushDto::MODE_MATCH_ANY
|
||||
)
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
79
app/Services/DavClient/Utils/AddressBookContactsUpdater.php
Normal file
79
app/Services/DavClient/Utils/AddressBookContactsUpdater.php
Normal file
@@ -0,0 +1,79 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\DavClient\Utils;
|
||||
|
||||
use App\Jobs\Dav\GetVCard;
|
||||
use App\Jobs\Dav\DeleteVCard;
|
||||
use App\Jobs\Dav\GetMultipleVCard;
|
||||
use Illuminate\Support\Collection;
|
||||
use App\Jobs\Dav\DeleteMultipleVCard;
|
||||
use App\Services\DavClient\Utils\Model\SyncDto;
|
||||
use App\Services\DavClient\Utils\Model\ContactDto;
|
||||
use App\Services\DavClient\Utils\Traits\WithSyncDto;
|
||||
use App\Services\DavClient\Utils\Traits\HasCapability;
|
||||
use App\Services\DavClient\Utils\Model\ContactDeleteDto;
|
||||
|
||||
class AddressBookContactsUpdater
|
||||
{
|
||||
use HasCapability, WithSyncDto;
|
||||
|
||||
/**
|
||||
* Update local contacts.
|
||||
*
|
||||
* @param SyncDto $sync
|
||||
* @param Collection<array-key, \App\Services\DavClient\Utils\Model\ContactDto> $refresh
|
||||
* @return Collection
|
||||
*/
|
||||
public function execute(SyncDto $sync, Collection $refresh): Collection
|
||||
{
|
||||
$this->sync = $sync;
|
||||
|
||||
return $this->hasCapability('addressbookMultiget')
|
||||
? $this->refreshMultigetContacts($refresh)
|
||||
: $this->refreshSimpleGetContacts($refresh);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get contacts data with addressbook-multiget request.
|
||||
*
|
||||
* @param Collection<array-key, \App\Services\DavClient\Utils\Model\ContactDto> $refresh
|
||||
* @return Collection
|
||||
*/
|
||||
private function refreshMultigetContacts(Collection $refresh): Collection
|
||||
{
|
||||
$updated = $refresh
|
||||
->filter(function ($item): bool {
|
||||
return ! ($item instanceof ContactDeleteDto);
|
||||
})
|
||||
->pluck('uri')->toArray();
|
||||
|
||||
$deleted = $refresh
|
||||
->filter(function ($item): bool {
|
||||
return $item instanceof ContactDeleteDto;
|
||||
})
|
||||
->pluck('uri')->toArray();
|
||||
|
||||
return collect([
|
||||
new GetMultipleVCard($this->sync->subscription, $updated),
|
||||
new DeleteMultipleVCard($this->sync->subscription, $deleted),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get contacts data with request.
|
||||
*
|
||||
* @param Collection<array-key, \App\Services\DavClient\Utils\Model\ContactDto> $refresh
|
||||
* @return Collection
|
||||
*/
|
||||
private function refreshSimpleGetContacts(Collection $refresh): Collection
|
||||
{
|
||||
return $refresh
|
||||
->map(function (ContactDto $contact) {
|
||||
if ($contact instanceof ContactDeleteDto) {
|
||||
return new DeleteVCard($this->sync->subscription, $contact->uri);
|
||||
} else {
|
||||
return new GetVCard($this->sync->subscription, $contact);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user