mirror of
https://github.com/solidtime-io/solidtime.git
synced 2026-08-16 12:12:15 +01:00
Migrated endpoints from user to member; Renamed membership to member
This commit is contained in:
@@ -4,7 +4,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace App\Service;
|
||||
|
||||
use App\Models\Membership;
|
||||
use App\Models\Member;
|
||||
use App\Models\Organization;
|
||||
use App\Models\Project;
|
||||
use App\Models\ProjectMember;
|
||||
@@ -36,13 +36,13 @@ class BillableRateService
|
||||
}
|
||||
}
|
||||
// Member rate
|
||||
/** @var Membership|null $membership */
|
||||
$membership = Membership::query()
|
||||
/** @var Member|null $member */
|
||||
$member = Member::query()
|
||||
->where('user_id', '=', $timeEntry->user_id)
|
||||
->where('organization_id', '=', $timeEntry->organization_id)
|
||||
->first();
|
||||
if ($membership !== null && $membership->billable_rate !== null) {
|
||||
return $membership->billable_rate;
|
||||
if ($member !== null && $member->billable_rate !== null) {
|
||||
return $member->billable_rate;
|
||||
}
|
||||
|
||||
// Organization rate
|
||||
|
||||
@@ -335,20 +335,22 @@ class DashboardService
|
||||
}
|
||||
|
||||
/**
|
||||
* Rhe 4 most recently active members of your team with user_id, name, description of the latest time entry, time_entry_id, task_id and a boolean status if the team member is currently working
|
||||
* Rhe 4 most recently active members of your team with member_id, name, description of the latest time entry, time_entry_id, task_id and a boolean status if the team member is currently working
|
||||
*
|
||||
* @return array<int, array{user_id: string, name: string, description: string|null, time_entry_id: string, task_id: string|null, status: bool }>
|
||||
* @return array<int, array{member_id: string, name: string, description: string|null, time_entry_id: string, task_id: string|null, status: bool }>
|
||||
*/
|
||||
public function latestTeamActivity(Organization $organization): array
|
||||
{
|
||||
$timeEntries = TimeEntry::query()
|
||||
->select(DB::raw('distinct on (user_id) user_id, description, id, task_id, start, "end"'))
|
||||
->select(DB::raw('distinct on (member_id) member_id, description, id, task_id, start, "end"'))
|
||||
->whereBelongsTo($organization, 'organization')
|
||||
->orderBy('user_id')
|
||||
->orderBy('member_id')
|
||||
->orderBy('start', 'desc')
|
||||
// Note: limit here does not work because of the distinct on
|
||||
->with([
|
||||
'user',
|
||||
'member' => [
|
||||
'user',
|
||||
],
|
||||
])
|
||||
->get()
|
||||
->sortByDesc('start')
|
||||
@@ -358,8 +360,8 @@ class DashboardService
|
||||
|
||||
foreach ($timeEntries as $timeEntry) {
|
||||
$response[] = [
|
||||
'user_id' => $timeEntry->user_id,
|
||||
'name' => $timeEntry->user->name,
|
||||
'member_id' => $timeEntry->member_id,
|
||||
'name' => $timeEntry->member->user->name,
|
||||
'description' => $timeEntry->description,
|
||||
'time_entry_id' => $timeEntry->id,
|
||||
'task_id' => $timeEntry->task_id,
|
||||
|
||||
@@ -56,6 +56,10 @@ class ClockifyTimeEntriesImporter extends DefaultImporter
|
||||
'timezone' => 'UTC',
|
||||
'is_placeholder' => true,
|
||||
]);
|
||||
$memberId = $this->memberImportHelper->getKey([
|
||||
'user_id' => $userId,
|
||||
'organization_id' => $this->organization->getKey(),
|
||||
]);
|
||||
$clientId = null;
|
||||
if ($record['Client'] !== '') {
|
||||
$clientId = $this->clientImportHelper->getKey([
|
||||
@@ -83,6 +87,7 @@ class ClockifyTimeEntriesImporter extends DefaultImporter
|
||||
}
|
||||
$timeEntry = new TimeEntry();
|
||||
$timeEntry->user_id = $userId;
|
||||
$timeEntry->member_id = $memberId;
|
||||
$timeEntry->task_id = $taskId;
|
||||
$timeEntry->project_id = $projectId;
|
||||
$timeEntry->organization_id = $this->organization->id;
|
||||
|
||||
@@ -6,6 +6,7 @@ namespace App\Service\Import\Importers;
|
||||
|
||||
use App\Enums\Role;
|
||||
use App\Models\Client;
|
||||
use App\Models\Member;
|
||||
use App\Models\Organization;
|
||||
use App\Models\Project;
|
||||
use App\Models\ProjectMember;
|
||||
@@ -26,6 +27,11 @@ abstract class DefaultImporter implements ImporterContract
|
||||
*/
|
||||
protected ImportDatabaseHelper $userImportHelper;
|
||||
|
||||
/**
|
||||
* @var ImportDatabaseHelper<Member>
|
||||
*/
|
||||
protected ImportDatabaseHelper $memberImportHelper;
|
||||
|
||||
/**
|
||||
* @var ImportDatabaseHelper<Project>
|
||||
*/
|
||||
@@ -77,6 +83,10 @@ abstract class DefaultImporter implements ImporterContract
|
||||
'timezone:all',
|
||||
],
|
||||
]);
|
||||
$this->memberImportHelper = new ImportDatabaseHelper(Member::class, ['user_id', 'organization_id'], true, function (Builder $builder) {
|
||||
/** @var Builder<Member> $builder */
|
||||
return $builder->whereBelongsTo($this->organization, 'organization');
|
||||
});
|
||||
$this->projectImportHelper = new ImportDatabaseHelper(Project::class, ['name', 'organization_id'], true, function (Builder $builder) {
|
||||
/** @var Builder<Project> $builder */
|
||||
return $builder->where('organization_id', $this->organization->id);
|
||||
@@ -90,7 +100,7 @@ abstract class DefaultImporter implements ImporterContract
|
||||
'integer',
|
||||
],
|
||||
]);
|
||||
$this->projectMemberImportHelper = new ImportDatabaseHelper(ProjectMember::class, ['project_id', 'user_id'], true, function (Builder $builder) {
|
||||
$this->projectMemberImportHelper = new ImportDatabaseHelper(ProjectMember::class, ['project_id', 'member_id'], true, function (Builder $builder) {
|
||||
/** @var Builder<ProjectMember> $builder */
|
||||
return $builder->whereBelongsToOrganization($this->organization);
|
||||
}, validate: [
|
||||
|
||||
@@ -74,13 +74,17 @@ class TogglDataImporter extends DefaultImporter
|
||||
}
|
||||
|
||||
foreach ($workspaceUsers as $workspaceUser) {
|
||||
$this->userImportHelper->getKey([
|
||||
$userId = $this->userImportHelper->getKey([
|
||||
'email' => $workspaceUser->email,
|
||||
], [
|
||||
'name' => $workspaceUser->name,
|
||||
'timezone' => $workspaceUser->timezone ?? 'UTC',
|
||||
'is_placeholder' => true,
|
||||
], (string) $workspaceUser->uid);
|
||||
$memberId = $this->memberImportHelper->getKey([
|
||||
'user_id' => $userId,
|
||||
'organization_id' => $this->organization->getKey(),
|
||||
], [], $userId);
|
||||
}
|
||||
|
||||
foreach ($projects as $project) {
|
||||
@@ -114,10 +118,12 @@ class TogglDataImporter extends DefaultImporter
|
||||
}
|
||||
$projectMembers = json_decode($projectMembersFileContent);
|
||||
foreach ($projectMembers as $projectMember) {
|
||||
$userId = $this->userImportHelper->getKeyByExternalIdentifier((string) $projectMember->user_id);
|
||||
$this->projectMemberImportHelper->getKey([
|
||||
'project_id' => $projectId,
|
||||
'user_id' => $this->userImportHelper->getKeyByExternalIdentifier((string) $projectMember->user_id),
|
||||
'member_id' => $this->memberImportHelper->getKeyByExternalIdentifier($userId),
|
||||
], [
|
||||
'user_id' => $userId,
|
||||
'billable_rate' => $projectMember->rate !== null ? (int) ($projectMember->rate * 100) : null,
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -56,6 +56,10 @@ class TogglTimeEntriesImporter extends DefaultImporter
|
||||
'timezone' => 'UTC',
|
||||
'is_placeholder' => true,
|
||||
]);
|
||||
$memberId = $this->memberImportHelper->getKey([
|
||||
'user_id' => $userId,
|
||||
'organization_id' => $this->organization->getKey(),
|
||||
]);
|
||||
$clientId = null;
|
||||
if ($record['Client'] !== '') {
|
||||
$clientId = $this->clientImportHelper->getKey([
|
||||
@@ -83,6 +87,7 @@ class TogglTimeEntriesImporter extends DefaultImporter
|
||||
}
|
||||
$timeEntry = new TimeEntry();
|
||||
$timeEntry->user_id = $userId;
|
||||
$timeEntry->member_id = $memberId;
|
||||
$timeEntry->task_id = $taskId;
|
||||
$timeEntry->project_id = $projectId;
|
||||
$timeEntry->organization_id = $this->organization->id;
|
||||
|
||||
@@ -4,6 +4,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace App\Service;
|
||||
|
||||
use App\Models\Member;
|
||||
use App\Models\TimeEntry;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Support\Carbon;
|
||||
@@ -59,12 +60,25 @@ class TimeEntryFilter
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function addUserIdFilter(?string $userId): self
|
||||
public function addMemberIdFilter(?Member $member): self
|
||||
{
|
||||
if ($userId === null) {
|
||||
if ($member === null) {
|
||||
return $this;
|
||||
}
|
||||
$this->builder->where('user_id', $userId);
|
||||
$this->builder->where('member_id', $member->getKey());
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string>|null $memberIds
|
||||
*/
|
||||
public function addMemberIdsFilter(?array $memberIds): self
|
||||
{
|
||||
if ($memberIds === null) {
|
||||
return $this;
|
||||
}
|
||||
$this->builder->whereIn('member_id', $memberIds);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ declare(strict_types=1);
|
||||
namespace App\Service;
|
||||
|
||||
use App\Enums\Role;
|
||||
use App\Models\Membership;
|
||||
use App\Models\Member;
|
||||
use App\Models\Organization;
|
||||
use App\Models\ProjectMember;
|
||||
use App\Models\TimeEntry;
|
||||
@@ -19,12 +19,22 @@ class UserService
|
||||
*/
|
||||
public function assignOrganizationEntitiesToDifferentUser(Organization $organization, User $fromUser, User $toUser): void
|
||||
{
|
||||
/** @var Member|null $toMember */
|
||||
$toMember = Member::query()
|
||||
->whereBelongsTo($organization, 'organization')
|
||||
->whereBelongsTo($toUser, 'user')
|
||||
->first();
|
||||
if ($toMember === null) {
|
||||
throw new \InvalidArgumentException('User is not a member of the organization');
|
||||
}
|
||||
|
||||
// Time entries
|
||||
TimeEntry::query()
|
||||
->whereBelongsTo($organization, 'organization')
|
||||
->whereBelongsTo($fromUser, 'user')
|
||||
->update([
|
||||
'user_id' => $toUser->getKey(),
|
||||
'member_id' => $toMember->getKey(),
|
||||
]);
|
||||
|
||||
// Project members
|
||||
@@ -33,6 +43,7 @@ class UserService
|
||||
->whereBelongsTo($fromUser, 'user')
|
||||
->update([
|
||||
'user_id' => $toUser->getKey(),
|
||||
'member_id' => $toMember->getKey(),
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -45,13 +56,17 @@ class UserService
|
||||
$organization->update([
|
||||
'user_id' => $newOwner->getKey(),
|
||||
]);
|
||||
$userMembership = Membership::query()
|
||||
/** @var Member|null $userMembership */
|
||||
$userMembership = Member::query()
|
||||
->whereBelongsTo($organization, 'organization')
|
||||
->whereBelongsTo($newOwner, 'user')
|
||||
->first();
|
||||
if ($userMembership === null) {
|
||||
throw new \InvalidArgumentException('User is not a member of the organization');
|
||||
}
|
||||
$userMembership->role = Role::Owner->value;
|
||||
$userMembership->save();
|
||||
$oldOwners = Membership::query()
|
||||
$oldOwners = Member::query()
|
||||
->whereBelongsTo($organization, 'organization')
|
||||
->where('role', '=', Role::Owner->value)
|
||||
->where('user_id', '!=', $newOwner->getKey())
|
||||
|
||||
Reference in New Issue
Block a user