Skip to content

Commit f1a1d2a

Browse files
committed
Project name is now unique per client and organization
1 parent f5efbad commit f1a1d2a

14 files changed

+192
-17
lines changed

app/Http/Requests/V1/Project/ProjectStoreRequest.php

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
use Illuminate\Contracts\Validation\ValidationRule;
1212
use Illuminate\Database\Eloquent\Builder;
1313
use Illuminate\Foundation\Http\FormRequest;
14+
use Illuminate\Support\Str;
1415
use Korridor\LaravelModelValidationRules\Rules\ExistsEloquent;
1516
use Korridor\LaravelModelValidationRules\Rules\UniqueEloquent;
1617

@@ -27,14 +28,21 @@ class ProjectStoreRequest extends FormRequest
2728
public function rules(): array
2829
{
2930
return [
31+
// Name of the project, the name needs to be unique per client and organization
3032
'name' => [
3133
'required',
3234
'string',
3335
'min:1',
3436
'max:255',
3537
UniqueEloquent::make(Project::class, 'name', function (Builder $builder): Builder {
3638
/** @var Builder<Project> $builder */
37-
return $builder->whereBelongsTo($this->organization, 'organization');
39+
$clientId = $this->input('client_id');
40+
if (! is_string($clientId) || ! Str::isUuid($clientId)) {
41+
$clientId = null;
42+
}
43+
44+
return $builder->whereBelongsTo($this->organization, 'organization')
45+
->where('client_id', $clientId);
3846
})->withCustomTranslation('validation.project_name_already_exists'),
3947
],
4048
'color' => [
@@ -55,6 +63,7 @@ public function rules(): array
5563
],
5664
// ID of the client
5765
'client_id' => [
66+
'present',
5867
'nullable',
5968
ExistsEloquent::make(Client::class, null, function (Builder $builder): Builder {
6069
/** @var Builder<Client> $builder */

app/Http/Requests/V1/Project/ProjectUpdateRequest.php

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
use Illuminate\Contracts\Validation\ValidationRule;
1212
use Illuminate\Database\Eloquent\Builder;
1313
use Illuminate\Foundation\Http\FormRequest;
14+
use Illuminate\Support\Str;
1415
use Korridor\LaravelModelValidationRules\Rules\ExistsEloquent;
1516
use Korridor\LaravelModelValidationRules\Rules\UniqueEloquent;
1617

@@ -34,7 +35,13 @@ public function rules(): array
3435
'max:255',
3536
UniqueEloquent::make(Project::class, 'name', function (Builder $builder): Builder {
3637
/** @var Builder<Project> $builder */
37-
return $builder->whereBelongsTo($this->organization, 'organization');
38+
$clientId = $this->input('client_id');
39+
if (! is_string($clientId) || ! Str::isUuid($clientId)) {
40+
$clientId = null;
41+
}
42+
43+
return $builder->whereBelongsTo($this->organization, 'organization')
44+
->where('client_id', $clientId);
3845
})->ignore($this->project?->getKey())->withCustomTranslation('validation.project_name_already_exists'),
3946
],
4047
'color' => [
@@ -54,6 +61,7 @@ public function rules(): array
5461
'boolean',
5562
],
5663
'client_id' => [
64+
'present',
5765
'nullable',
5866
ExistsEloquent::make(Client::class, null, function (Builder $builder): Builder {
5967
/** @var Builder<Client> $builder */

app/Service/Import/Importers/ClockifyProjectsImporter.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,9 @@ public function importData(string $data, string $timezone): void
3737
if ($record['Project'] !== '') {
3838
$projectId = $this->projectImportHelper->getKey([
3939
'name' => $record['Project'],
40+
'client_id' => $clientId,
4041
'organization_id' => $this->organization->id,
4142
], [
42-
'client_id' => $clientId,
4343
'color' => $this->colorService->getRandomColor(),
4444
'is_billable' => $record['Billability'] === 'Yes',
4545
'billable_rate' => $billableRateKey !== null && $record[$billableRateKey] !== '' ? (int) (((float) $record[$billableRateKey]) * 100) : null,

app/Service/Import/Importers/ClockifyTimeEntriesImporter.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,9 +83,9 @@ public function importData(string $data, string $timezone): void
8383
if ($record['Project'] !== '') {
8484
$projectId = $this->projectImportHelper->getKey([
8585
'name' => $record['Project'],
86+
'client_id' => $clientId,
8687
'organization_id' => $this->organization->id,
8788
], [
88-
'client_id' => $clientId,
8989
'color' => $this->colorService->getRandomColor(),
9090
'is_billable' => false,
9191
]);

app/Service/Import/Importers/DefaultImporter.php

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ public function init(Organization $organization): void
9797
'in:placeholder',
9898
],
9999
]);
100-
$this->projectImportHelper = new ImportDatabaseHelper(Project::class, ['name', 'organization_id'], true, function (Builder $builder) {
100+
$this->projectImportHelper = new ImportDatabaseHelper(Project::class, ['name', 'client_id', 'organization_id'], true, function (Builder $builder) {
101101
/** @var Builder<Project> $builder */
102102
return $builder->where('organization_id', $this->organization->id);
103103
}, validate: [
@@ -114,6 +114,11 @@ public function init(Organization $organization): void
114114
'integer',
115115
'max:2147483647',
116116
],
117+
'client_id' => [
118+
'nullable',
119+
'string',
120+
'uuid',
121+
],
117122
], beforeSave: function (Project $project): void {
118123
if ($project->billable_rate === 0) {
119124
$project->billable_rate = null;

app/Service/Import/Importers/GenericProjectsImporter.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,12 +55,12 @@ public function importData(string $data, string $timezone): void
5555
}
5656
$this->projectImportHelper->getKey([
5757
'name' => $record['name'],
58+
'client_id' => $clientId,
5859
'organization_id' => $this->organization->id,
5960
], [
6061
'color' => isset($record['color']) && $record['color'] !== '' ? $record['color'] : app(ColorService::class)->getRandomColor(),
6162
'billable_rate' => isset($record['billable_rate']) && $record['billable_rate'] !== '' ? (int) $record['billable_rate'] : null,
6263
'is_public' => isset($record['is_public']) && $record['is_public'] === 'true',
63-
'client_id' => $clientId,
6464
'is_billable' => isset($record['billable_default']) && $record['billable_default'] === 'true',
6565
'estimated_time' => isset($record['estimated_time']) && $record['estimated_time'] !== '' && is_numeric($record['estimated_time']) && ((int) $record['estimated_time'] !== 0) ? (int) $record['estimated_time'] : null,
6666
'archived_at' => $archivedAt,

app/Service/Import/Importers/GenericTimeEntriesImporter.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,9 +99,9 @@ public function importData(string $data, string $timezone): void
9999
if ($record['project'] !== '') {
100100
$projectId = $this->projectImportHelper->getKey([
101101
'name' => $record['project'],
102+
'client_id' => $clientId,
102103
'organization_id' => $this->organization->id,
103104
], [
104-
'client_id' => $clientId,
105105
'is_billable' => false,
106106
'color' => $this->colorService->getRandomColor(),
107107
]);

app/Service/Import/Importers/HarvestProjectsImporter.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,10 +60,10 @@ public function importData(string $data, string $timezone): void
6060
$billableHours = $billableHoursField !== '' && is_numeric($billableHoursField) ? (int) ((float) $billableHoursField) : null;
6161
$this->projectImportHelper->getKey([
6262
'name' => $record['Project'],
63+
'client_id' => $clientId,
6364
'organization_id' => $this->organization->id,
6465
], [
6566
'color' => $this->colorService->getRandomColor(),
66-
'client_id' => $clientId,
6767
'estimated_time' => $estimatedTime,
6868
'is_billable' => $billableHours > 0,
6969
]);

app/Service/Import/Importers/HarvestTimeEntriesImporter.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,9 +78,9 @@ public function importData(string $data, string $timezone): void
7878
if ($record['Project'] !== '') {
7979
$projectId = $this->projectImportHelper->getKey([
8080
'name' => $record['Project'],
81+
'client_id' => $clientId,
8182
'organization_id' => $this->organization->id,
8283
], [
83-
'client_id' => $clientId,
8484
'color' => $this->colorService->getRandomColor(),
8585
'is_billable' => true,
8686
]);

app/Service/Import/Importers/SolidtimeImporter.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -176,12 +176,12 @@ public function importData(string $data, string $timezone): void
176176

177177
$this->projectImportHelper->getKey([
178178
'name' => $project['name'],
179+
'client_id' => $clientId,
179180
'organization_id' => $this->organization->getKey(),
180181
], [
181182
'color' => $project['color'],
182183
'billable_rate' => $project['billable_rate'] === '' ? null : (int) $project['billable_rate'],
183184
'is_public' => $project['is_public'] === 'true',
184-
'client_id' => $clientId,
185185
'is_billable' => $project['is_billable'] === 'true',
186186
'archived_at' => $project['archived_at'] !== '' ? Carbon::createFromFormat('Y-m-d\TH:i:s\Z', $project['archived_at'], 'UTC') : null,
187187
], $project['id']);

0 commit comments

Comments
 (0)