mirror of
https://github.com/solidtime-io/solidtime.git
synced 2026-08-17 04:32:15 +01:00
Enhanced imports with billable rates and project members; Fixed error handling and import structure
This commit is contained in:
committed by
Constantin Graf
parent
7433648077
commit
a8ce994f08
@@ -23,6 +23,7 @@ use Illuminate\Database\Eloquent\Relations\HasMany;
|
|||||||
* @property-read Organization $organization
|
* @property-read Organization $organization
|
||||||
* @property-read Client|null $client
|
* @property-read Client|null $client
|
||||||
* @property-read Collection<int, Task> $tasks
|
* @property-read Collection<int, Task> $tasks
|
||||||
|
* @property-read Collection<int, ProjectMember> $members
|
||||||
*
|
*
|
||||||
* @method Builder<Project> visibleByUser(User $user)
|
* @method Builder<Project> visibleByUser(User $user)
|
||||||
* @method static ProjectFactory factory()
|
* @method static ProjectFactory factory()
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ declare(strict_types=1);
|
|||||||
namespace App\Service\Import\Importers;
|
namespace App\Service\Import\Importers;
|
||||||
|
|
||||||
use Exception;
|
use Exception;
|
||||||
|
use Illuminate\Support\Str;
|
||||||
use League\Csv\Exception as CsvException;
|
use League\Csv\Exception as CsvException;
|
||||||
use League\Csv\Reader;
|
use League\Csv\Reader;
|
||||||
|
|
||||||
@@ -22,6 +23,7 @@ class ClockifyProjectsImporter extends DefaultImporter
|
|||||||
$reader->setDelimiter(',');
|
$reader->setDelimiter(',');
|
||||||
$header = $reader->getHeader();
|
$header = $reader->getHeader();
|
||||||
$this->validateHeader($header);
|
$this->validateHeader($header);
|
||||||
|
$billableRateKey = $this->getBillableRateKey($header);
|
||||||
$records = $reader->getRecords();
|
$records = $reader->getRecords();
|
||||||
foreach ($records as $record) {
|
foreach ($records as $record) {
|
||||||
$clientId = null;
|
$clientId = null;
|
||||||
@@ -32,18 +34,19 @@ class ClockifyProjectsImporter extends DefaultImporter
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
$projectId = null;
|
$projectId = null;
|
||||||
if ($record['Name'] !== '') {
|
if ($record['Project'] !== '') {
|
||||||
$projectId = $this->projectImportHelper->getKey([
|
$projectId = $this->projectImportHelper->getKey([
|
||||||
'name' => $record['Name'],
|
'name' => $record['Project'],
|
||||||
'organization_id' => $this->organization->id,
|
'organization_id' => $this->organization->id,
|
||||||
], [
|
], [
|
||||||
'client_id' => $clientId,
|
'client_id' => $clientId,
|
||||||
'color' => $this->colorService->getRandomColor(),
|
'color' => $this->colorService->getRandomColor(),
|
||||||
|
'billable_rate' => $billableRateKey !== null && $record[$billableRateKey] !== '' ? (int) (((float) $record[$billableRateKey]) * 100) : null,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($record['Tasks'] !== '') {
|
if ($record['Task'] !== '') {
|
||||||
$tasks = explode(', ', $record['Tasks']);
|
$tasks = explode(', ', $record['Task']);
|
||||||
foreach ($tasks as $task) {
|
foreach ($tasks as $task) {
|
||||||
$this->taskImportHelper->getKey([
|
$this->taskImportHelper->getKey([
|
||||||
'name' => $task,
|
'name' => $task,
|
||||||
@@ -71,12 +74,12 @@ class ClockifyProjectsImporter extends DefaultImporter
|
|||||||
private function validateHeader(array $header): void
|
private function validateHeader(array $header): void
|
||||||
{
|
{
|
||||||
$requiredFields = [
|
$requiredFields = [
|
||||||
'Name',
|
'Project',
|
||||||
'Client',
|
'Client',
|
||||||
'Status',
|
'Status',
|
||||||
'Visibility',
|
'Visibility',
|
||||||
'Billability',
|
'Billability',
|
||||||
'Tasks',
|
'Task',
|
||||||
];
|
];
|
||||||
foreach ($requiredFields as $requiredField) {
|
foreach ($requiredFields as $requiredField) {
|
||||||
if (! in_array($requiredField, $header, true)) {
|
if (! in_array($requiredField, $header, true)) {
|
||||||
@@ -85,6 +88,22 @@ class ClockifyProjectsImporter extends DefaultImporter
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param array<string> $header
|
||||||
|
*/
|
||||||
|
private function getBillableRateKey(array $header): ?string
|
||||||
|
{
|
||||||
|
$billableRateKey = null;
|
||||||
|
foreach ($header as $value) {
|
||||||
|
if (Str::startsWith($value, 'Billable Rate (')) {
|
||||||
|
$billableRateKey = $value;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $billableRateKey;
|
||||||
|
}
|
||||||
|
|
||||||
#[\Override]
|
#[\Override]
|
||||||
public function getName(): string
|
public function getName(): string
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -4,9 +4,11 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace App\Service\Import\Importers;
|
namespace App\Service\Import\Importers;
|
||||||
|
|
||||||
|
use App\Enums\Role;
|
||||||
use App\Models\Client;
|
use App\Models\Client;
|
||||||
use App\Models\Organization;
|
use App\Models\Organization;
|
||||||
use App\Models\Project;
|
use App\Models\Project;
|
||||||
|
use App\Models\ProjectMember;
|
||||||
use App\Models\Tag;
|
use App\Models\Tag;
|
||||||
use App\Models\Task;
|
use App\Models\Task;
|
||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
@@ -50,6 +52,11 @@ abstract class DefaultImporter implements ImporterContract
|
|||||||
|
|
||||||
protected TimezoneService $timezoneService;
|
protected TimezoneService $timezoneService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var ImportDatabaseHelper<ProjectMember>
|
||||||
|
*/
|
||||||
|
protected ImportDatabaseHelper $projectMemberImportHelper;
|
||||||
|
|
||||||
public function init(Organization $organization): void
|
public function init(Organization $organization): void
|
||||||
{
|
{
|
||||||
$this->organization = $organization;
|
$this->organization = $organization;
|
||||||
@@ -58,7 +65,7 @@ abstract class DefaultImporter implements ImporterContract
|
|||||||
return $builder->belongsToOrganization($this->organization);
|
return $builder->belongsToOrganization($this->organization);
|
||||||
}, function (User $user) {
|
}, function (User $user) {
|
||||||
$user->organizations()->attach($this->organization, [
|
$user->organizations()->attach($this->organization, [
|
||||||
'role' => 'placeholder',
|
'role' => Role::Placeholder->value,
|
||||||
]);
|
]);
|
||||||
}, validate: [
|
}, validate: [
|
||||||
'name' => [
|
'name' => [
|
||||||
@@ -71,12 +78,26 @@ abstract class DefaultImporter implements ImporterContract
|
|||||||
],
|
],
|
||||||
]);
|
]);
|
||||||
$this->projectImportHelper = new ImportDatabaseHelper(Project::class, ['name', 'organization_id'], true, function (Builder $builder) {
|
$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);
|
return $builder->where('organization_id', $this->organization->id);
|
||||||
}, validate: [
|
}, validate: [
|
||||||
'name' => [
|
'name' => [
|
||||||
'required',
|
'required',
|
||||||
'max:255',
|
'max:255',
|
||||||
],
|
],
|
||||||
|
'billable_rate' => [
|
||||||
|
'nullable',
|
||||||
|
'integer',
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
$this->projectMemberImportHelper = new ImportDatabaseHelper(ProjectMember::class, ['project_id', 'user_id'], true, function (Builder $builder) {
|
||||||
|
/** @var Builder<ProjectMember> $builder */
|
||||||
|
return $builder->whereBelongsToOrganization($this->organization);
|
||||||
|
}, validate: [
|
||||||
|
'billable_rate' => [
|
||||||
|
'nullable',
|
||||||
|
'integer',
|
||||||
|
],
|
||||||
]);
|
]);
|
||||||
$this->tagImportHelper = new ImportDatabaseHelper(Tag::class, ['name', 'organization_id'], true, function (Builder $builder) {
|
$this->tagImportHelper = new ImportDatabaseHelper(Tag::class, ['name', 'organization_id'], true, function (Builder $builder) {
|
||||||
return $builder->where('organization_id', $this->organization->id);
|
return $builder->where('organization_id', $this->organization->id);
|
||||||
|
|||||||
@@ -28,24 +28,36 @@ class TogglDataImporter extends DefaultImporter
|
|||||||
$temporaryDirectory = TemporaryDirectory::make();
|
$temporaryDirectory = TemporaryDirectory::make();
|
||||||
$zip->extractTo($temporaryDirectory->path());
|
$zip->extractTo($temporaryDirectory->path());
|
||||||
$zip->close();
|
$zip->close();
|
||||||
|
if (! file_exists($temporaryDirectory->path('clients.json'))) {
|
||||||
|
throw new ImportException('File "clients.json" missing in ZIP');
|
||||||
|
}
|
||||||
$clientsFileContent = file_get_contents($temporaryDirectory->path('clients.json'));
|
$clientsFileContent = file_get_contents($temporaryDirectory->path('clients.json'));
|
||||||
if ($clientsFileContent === false) {
|
if ($clientsFileContent === false) {
|
||||||
throw new ImportException('File clients.json missing in ZIP');
|
throw new ImportException('File "clients.json" can not be opened');
|
||||||
}
|
}
|
||||||
$clients = json_decode($clientsFileContent);
|
$clients = json_decode($clientsFileContent);
|
||||||
|
if (! file_exists($temporaryDirectory->path('projects.json'))) {
|
||||||
|
throw new ImportException('File "projects.json" missing in ZIP');
|
||||||
|
}
|
||||||
$projectsFileContent = file_get_contents($temporaryDirectory->path('projects.json'));
|
$projectsFileContent = file_get_contents($temporaryDirectory->path('projects.json'));
|
||||||
if ($projectsFileContent === false) {
|
if ($projectsFileContent === false) {
|
||||||
throw new ImportException('File projects.json missing in ZIP');
|
throw new ImportException('File "projects.json" can not be opened');
|
||||||
}
|
}
|
||||||
$projects = json_decode($projectsFileContent);
|
$projects = json_decode($projectsFileContent);
|
||||||
|
if (! file_exists($temporaryDirectory->path('tags.json'))) {
|
||||||
|
throw new ImportException('File "tags.json" missing in ZIP');
|
||||||
|
}
|
||||||
$tagsFileContent = file_get_contents($temporaryDirectory->path('tags.json'));
|
$tagsFileContent = file_get_contents($temporaryDirectory->path('tags.json'));
|
||||||
if ($tagsFileContent === false) {
|
if ($tagsFileContent === false) {
|
||||||
throw new ImportException('File tags.json missing in ZIP');
|
throw new ImportException('File "tags.json" can not be opened');
|
||||||
}
|
}
|
||||||
$tags = json_decode($tagsFileContent);
|
$tags = json_decode($tagsFileContent);
|
||||||
|
if (! file_exists($temporaryDirectory->path('workspace_users.json'))) {
|
||||||
|
throw new ImportException('File "workspace_users.json" missing in ZIP');
|
||||||
|
}
|
||||||
$workspaceUsersFileContent = file_get_contents($temporaryDirectory->path('workspace_users.json'));
|
$workspaceUsersFileContent = file_get_contents($temporaryDirectory->path('workspace_users.json'));
|
||||||
if ($workspaceUsersFileContent === false) {
|
if ($workspaceUsersFileContent === false) {
|
||||||
throw new ImportException('File workspace_users.json missing in ZIP');
|
throw new ImportException('File "workspace_users.json" can not be opened');
|
||||||
}
|
}
|
||||||
$workspaceUsers = json_decode($workspaceUsersFileContent);
|
$workspaceUsers = json_decode($workspaceUsersFileContent);
|
||||||
foreach ($clients as $client) {
|
foreach ($clients as $client) {
|
||||||
@@ -61,6 +73,16 @@ class TogglDataImporter extends DefaultImporter
|
|||||||
], [], (string) $tag->id);
|
], [], (string) $tag->id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
foreach ($workspaceUsers as $workspaceUser) {
|
||||||
|
$this->userImportHelper->getKey([
|
||||||
|
'email' => $workspaceUser->email,
|
||||||
|
], [
|
||||||
|
'name' => $workspaceUser->name,
|
||||||
|
'timezone' => $workspaceUser->timezone ?? 'UTC',
|
||||||
|
'is_placeholder' => true,
|
||||||
|
], (string) $workspaceUser->uid);
|
||||||
|
}
|
||||||
|
|
||||||
foreach ($projects as $project) {
|
foreach ($projects as $project) {
|
||||||
$clientId = null;
|
$clientId = null;
|
||||||
if ($project->client_id !== null) {
|
if ($project->client_id !== null) {
|
||||||
@@ -74,28 +96,40 @@ class TogglDataImporter extends DefaultImporter
|
|||||||
throw new ImportException('Invalid color');
|
throw new ImportException('Invalid color');
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->projectImportHelper->getKey([
|
$projectId = $this->projectImportHelper->getKey([
|
||||||
'name' => $project->name,
|
'name' => $project->name,
|
||||||
'organization_id' => $this->organization->getKey(),
|
'organization_id' => $this->organization->getKey(),
|
||||||
], [
|
], [
|
||||||
'client_id' => $clientId,
|
'client_id' => $clientId,
|
||||||
'color' => $project->color,
|
'color' => $project->color,
|
||||||
|
'billable_rate' => $project->rate !== null ? (int) ($project->rate * 100) : null,
|
||||||
], (string) $project->id);
|
], (string) $project->id);
|
||||||
}
|
|
||||||
foreach ($workspaceUsers as $workspaceUser) {
|
if (! file_exists($temporaryDirectory->path('projects_users/'.$project->id.'.json'))) {
|
||||||
$this->userImportHelper->getKey([
|
throw new ImportException('File "projects_users/'.$project->id.'.json" missing in ZIP');
|
||||||
'email' => $workspaceUser->email,
|
}
|
||||||
], [
|
$projectMembersFileContent = file_get_contents($temporaryDirectory->path('projects_users/'.$project->id.'.json'));
|
||||||
'name' => $workspaceUser->name,
|
if ($projectMembersFileContent === false) {
|
||||||
'timezone' => $workspaceUser->timezone ?? 'UTC',
|
throw new ImportException('File "projects_users/'.$project->id.'.json" can not be opened');
|
||||||
'is_placeholder' => true,
|
}
|
||||||
], (string) $workspaceUser->id);
|
$projectMembers = json_decode($projectMembersFileContent);
|
||||||
|
foreach ($projectMembers as $projectMember) {
|
||||||
|
$this->projectMemberImportHelper->getKey([
|
||||||
|
'project_id' => $projectId,
|
||||||
|
'user_id' => $this->userImportHelper->getKeyByExternalIdentifier((string) $projectMember->user_id),
|
||||||
|
], [
|
||||||
|
'billable_rate' => $projectMember->rate !== null ? (int) ($projectMember->rate * 100) : null,
|
||||||
|
]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
$projectIds = $this->projectImportHelper->getExternalIds();
|
$projectIds = $this->projectImportHelper->getExternalIds();
|
||||||
foreach ($projectIds as $projectIdExternal) {
|
foreach ($projectIds as $projectIdExternal) {
|
||||||
|
if (! file_exists($temporaryDirectory->path('tasks/'.$projectIdExternal.'.json'))) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
$tasksFileContent = file_get_contents($temporaryDirectory->path('tasks/'.$projectIdExternal.'.json'));
|
$tasksFileContent = file_get_contents($temporaryDirectory->path('tasks/'.$projectIdExternal.'.json'));
|
||||||
if ($tasksFileContent === false) {
|
if ($tasksFileContent === false) {
|
||||||
throw new ImportException('File tasks/'.$projectIdExternal.'.json missing in ZIP');
|
throw new ImportException('File "tasks/'.$projectIdExternal.'.json" can not be opened');
|
||||||
}
|
}
|
||||||
$tasks = json_decode($tasksFileContent);
|
$tasks = json_decode($tasksFileContent);
|
||||||
foreach ($tasks as $task) {
|
foreach ($tasks as $task) {
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
"Name","Client","Status","Visibility","Billability","Tasks","Tracked (h)","Estimated (h)","Remaining (h)","Overage (h)","Progress(%)","Billable (h)","Non-billable (h)","Billable Rate (USD)","Amount (USD)","Project members","Project manager","Note"
|
"Project","Client","Status","Visibility","Billability","Task","Tracked (h)","Estimated (h)","Remaining (h)","Overage (h)","Progress(%)","Billable (h)","Non-billable (h)","Billable Rate (USD)","Amount (USD)","Project members","Project manager","Note"
|
||||||
"Project for Big Company","Big Company","Active","Public","Yes","Task 1, Task 2, Task 3","0.00","","","","","0.00","0.00","","0.00","Constantin Graf","",""
|
"Project for Big Company","Big Company","Active","Public","Yes","Task 1, Task 2, Task 3","0.00","","","","","0.00","0.00","100.01","0.00","Constantin Graf","",""
|
||||||
"Project without Client","","Active","Public","Yes","","0.00","","","","","0.00","0.00","","0.00","Constantin Graf","",""
|
"Project without Client","","Active","Public","Yes","","0.00","","","","","0.00","0.00","","0.00","Constantin Graf","",""
|
||||||
|
|||||||
|
@@ -44,7 +44,7 @@
|
|||||||
"id": 402,
|
"id": 402,
|
||||||
"is_private": true,
|
"is_private": true,
|
||||||
"name": "Project for Big Company",
|
"name": "Project for Big Company",
|
||||||
"rate": null,
|
"rate": 100.01,
|
||||||
"rate_last_updated": null,
|
"rate_last_updated": null,
|
||||||
"recurring": false,
|
"recurring": false,
|
||||||
"recurring_parameters": null,
|
"recurring_parameters": null,
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
[]
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"gid": null,
|
||||||
|
"group_id": null,
|
||||||
|
"id": 801,
|
||||||
|
"labour_cost": null,
|
||||||
|
"manager": true,
|
||||||
|
"project_id": 402,
|
||||||
|
"rate": 100.02,
|
||||||
|
"rate_last_updated": null,
|
||||||
|
"user_id": 2001,
|
||||||
|
"workspace_id": 0
|
||||||
|
}
|
||||||
|
]
|
||||||
@@ -12,7 +12,7 @@
|
|||||||
"rate_last_updated": null,
|
"rate_last_updated": null,
|
||||||
"role": "admin",
|
"role": "admin",
|
||||||
"timezone": "Europe/Vienna",
|
"timezone": "Europe/Vienna",
|
||||||
"uid": 0,
|
"uid": 2001,
|
||||||
"wid": 0,
|
"wid": 0,
|
||||||
"working_hours_in_minutes": null
|
"working_hours_in_minutes": null
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ class ImporterTestAbstract extends TestCase
|
|||||||
/**
|
/**
|
||||||
* @return object{user1: User, project1: Project, project2: Project, tag1: Tag, tag2: Tag}
|
* @return object{user1: User, project1: Project, project2: Project, tag1: Tag, tag2: Tag}
|
||||||
*/
|
*/
|
||||||
protected function checkTestScenarioAfterImportExcludingTimeEntries(): object
|
protected function checkTestScenarioAfterImportExcludingTimeEntries(bool $detailed = false): object
|
||||||
{
|
{
|
||||||
$users = User::all();
|
$users = User::all();
|
||||||
$this->assertCount(2, $users);
|
$this->assertCount(2, $users);
|
||||||
@@ -32,7 +32,7 @@ class ImporterTestAbstract extends TestCase
|
|||||||
$this->assertCount(1, $clients);
|
$this->assertCount(1, $clients);
|
||||||
$client1 = $clients->firstWhere('name', 'Big Company');
|
$client1 = $clients->firstWhere('name', 'Big Company');
|
||||||
$this->assertNotNull($client1);
|
$this->assertNotNull($client1);
|
||||||
$projects = Project::all();
|
$projects = Project::with(['members'])->get();
|
||||||
$this->assertCount(2, $projects);
|
$this->assertCount(2, $projects);
|
||||||
$project1 = $projects->firstWhere('name', 'Project without Client');
|
$project1 = $projects->firstWhere('name', 'Project without Client');
|
||||||
$this->assertNotNull($project1);
|
$this->assertNotNull($project1);
|
||||||
@@ -40,6 +40,13 @@ class ImporterTestAbstract extends TestCase
|
|||||||
$project2 = $projects->firstWhere('name', 'Project for Big Company');
|
$project2 = $projects->firstWhere('name', 'Project for Big Company');
|
||||||
$this->assertNotNull($project2);
|
$this->assertNotNull($project2);
|
||||||
$this->assertSame($client1->getKey(), $project2->client_id);
|
$this->assertSame($client1->getKey(), $project2->client_id);
|
||||||
|
if ($detailed) {
|
||||||
|
$this->assertSame(10001, $project2->billable_rate);
|
||||||
|
$projectMembersOfProject2 = $project2->members;
|
||||||
|
$this->assertCount(1, $projectMembersOfProject2);
|
||||||
|
$this->assertSame($user1->getKey(), $projectMembersOfProject2->first()->user_id);
|
||||||
|
$this->assertSame(10002, $projectMembersOfProject2->first()->billable_rate);
|
||||||
|
}
|
||||||
$tasks = Task::all();
|
$tasks = Task::all();
|
||||||
$this->assertCount(1, $tasks);
|
$this->assertCount(1, $tasks);
|
||||||
$task1 = $tasks->firstWhere('name', 'Task 1');
|
$task1 = $tasks->firstWhere('name', 'Task 1');
|
||||||
@@ -76,6 +83,7 @@ class ImporterTestAbstract extends TestCase
|
|||||||
$this->assertNull($project1->client_id);
|
$this->assertNull($project1->client_id);
|
||||||
$project2 = $projects->firstWhere('name', 'Project for Big Company');
|
$project2 = $projects->firstWhere('name', 'Project for Big Company');
|
||||||
$this->assertNotNull($project2);
|
$this->assertNotNull($project2);
|
||||||
|
$this->assertSame(10001, $project2->billable_rate);
|
||||||
$this->assertSame($client1->getKey(), $project2->client_id);
|
$this->assertSame($client1->getKey(), $project2->client_id);
|
||||||
$tasks = Task::all();
|
$tasks = Task::all();
|
||||||
$this->assertCount(3, $tasks);
|
$this->assertCount(3, $tasks);
|
||||||
|
|||||||
@@ -62,7 +62,7 @@ class TogglDataImporterTest extends ImporterTestAbstract
|
|||||||
$report = $importer->getReport();
|
$report = $importer->getReport();
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
$this->checkTestScenarioAfterImportExcludingTimeEntries();
|
$this->checkTestScenarioAfterImportExcludingTimeEntries(true);
|
||||||
$this->assertSame(0, $report->timeEntriesCreated);
|
$this->assertSame(0, $report->timeEntriesCreated);
|
||||||
$this->assertSame(2, $report->tagsCreated);
|
$this->assertSame(2, $report->tagsCreated);
|
||||||
$this->assertSame(1, $report->tasksCreated);
|
$this->assertSame(1, $report->tasksCreated);
|
||||||
@@ -88,7 +88,7 @@ class TogglDataImporterTest extends ImporterTestAbstract
|
|||||||
$report = $importer->getReport();
|
$report = $importer->getReport();
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
$this->checkTestScenarioAfterImportExcludingTimeEntries();
|
$this->checkTestScenarioAfterImportExcludingTimeEntries(true);
|
||||||
$this->assertSame(0, $report->timeEntriesCreated);
|
$this->assertSame(0, $report->timeEntriesCreated);
|
||||||
$this->assertSame(0, $report->tagsCreated);
|
$this->assertSame(0, $report->tagsCreated);
|
||||||
$this->assertSame(0, $report->tasksCreated);
|
$this->assertSame(0, $report->tasksCreated);
|
||||||
|
|||||||
Reference in New Issue
Block a user