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
Reference in New Issue
Block a user