Skip to content

Commit da1e462

Browse files
committed
feat: #72 create iteration when import
1 parent 8312c85 commit da1e462

File tree

3 files changed

+91
-16
lines changed

3 files changed

+91
-16
lines changed

Diff for: app/Commands/IssueImportCommand.php

+34-14
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
namespace App\Commands;
44

55
use App\Coding\Issue;
6+
use App\Coding\Iteration;
67
use App\Coding\Project;
78
use LaravelZero\Framework\Commands\Command;
89
use Rap2hpoutre\FastExcel\Facades\FastExcel;
@@ -31,11 +32,14 @@ class IssueImportCommand extends Command
3132
*/
3233
protected $description = '导入事项';
3334

35+
protected array $iterationMap = [];
36+
protected array $issueTypes = [];
37+
3438
/**
3539
* Execute the console command.
3640
*
3741
*/
38-
public function handle(Issue $codingIssue, Project $codingProject): int
42+
public function handle(Issue $codingIssue, Project $codingProject, Iteration $iteration): int
3943
{
4044
$this->setCodingApi();
4145

@@ -45,29 +49,45 @@ public function handle(Issue $codingIssue, Project $codingProject): int
4549
return 1;
4650
}
4751

48-
$result = $codingProject->getIssueTypes($this->codingToken, $this->codingProjectUri);
49-
$issueTypes = [];
50-
foreach ($result as $item) {
51-
$issueTypes[$item['Name']] = $item;
52-
}
5352
$rows = FastExcel::import($filePath);
5453
foreach ($rows as $row) {
55-
$data = [
56-
'Type' => $issueTypes[$row['事项类型']]['IssueType'],
57-
'IssueTypeId' => $issueTypes[$row['事项类型']]['Id'],
58-
'Name' => $row['标题'],
59-
'Priority' => \App\Models\Issue::PRIORITY_MAP[$row['优先级']],
60-
];
6154
try {
62-
$result = $codingIssue->create($this->codingToken, $this->codingProjectUri, $data);
55+
$iterationResult = $this->createByRow($codingProject, $codingIssue, $iteration, $row);
6356
} catch (\Exception $e) {
6457
$this->error('Error: ' . $e->getMessage());
6558
return 1;
6659
}
6760
$this->info("https://{$this->codingTeamDomain}.coding.net/p/{$this->codingProjectUri}" .
68-
"/all/issues/${result['Code']}");
61+
"/all/issues/${iterationResult['Code']}");
6962
}
7063

7164
return 0;
7265
}
66+
67+
private function createByRow(Project $codingProject, Issue $issue, Iteration $iteration, array $row)
68+
{
69+
if (empty($this->issueTypes)) {
70+
$result = $codingProject->getIssueTypes($this->codingToken, $this->codingProjectUri);
71+
foreach ($result as $item) {
72+
$this->issueTypes[$item['Name']] = $item;
73+
}
74+
}
75+
$data = [
76+
'Type' => $this->issueTypes[$row['事项类型']]['IssueType'],
77+
'IssueTypeId' => $this->issueTypes[$row['事项类型']]['Id'],
78+
'Name' => $row['标题'],
79+
'Priority' => \App\Models\Issue::PRIORITY_MAP[$row['优先级']],
80+
'IterationCode' => $row['所属迭代'] ? $this->getIterationCode($iteration, $row['所属迭代']) : null,
81+
];
82+
return $issue->create($this->codingToken, $this->codingProjectUri, $data);
83+
}
84+
85+
private function getIterationCode(Iteration $iteration, string $name)
86+
{
87+
if (!isset($this->iterationMap[$name])) {
88+
$result = $iteration->create($this->codingToken, $this->codingProjectUri, ['name' => $name]);
89+
$this->iterationMap[$name] = $result['Code'];
90+
}
91+
return $this->iterationMap[$name];
92+
}
7393
}

Diff for: tests/Feature/IssueImportCommandTest.php

+55-2
Original file line numberDiff line numberDiff line change
@@ -3,19 +3,21 @@
33
namespace Tests\Feature;
44

55
use App\Coding\Issue;
6+
use App\Coding\Iteration;
67
use App\Coding\Project;
78
use Tests\TestCase;
89

910
class IssueImportCommandTest extends TestCase
1011
{
12+
private string $codingToken;
1113
private string $codingTeamDomain;
1214
private string $codingProjectUri;
1315

1416
protected function setUp(): void
1517
{
1618
parent::setUp();
17-
$codingToken = $this->faker->md5;
18-
config(['coding.token' => $codingToken]);
19+
$this->codingToken = $this->faker->md5;
20+
config(['coding.token' => $this->codingToken]);
1921
$this->codingTeamDomain = $this->faker->domainWord;
2022
config(['coding.team_domain' => $this->codingTeamDomain]);
2123
$this->codingProjectUri = $this->faker->slug;
@@ -34,6 +36,8 @@ public function testImportSuccess()
3436

3537
$issueMock = \Mockery::mock(Issue::class, [])->makePartial();
3638
$this->instance(Issue::class, $issueMock);
39+
$iterationMock = \Mockery::mock(Iteration::class, [])->makePartial();
40+
$this->instance(Iteration::class, $iterationMock);
3741

3842
$response = json_decode(
3943
file_get_contents($this->dataDir . 'coding/' . 'CreateIssueResponse.json'),
@@ -44,6 +48,11 @@ public function testImportSuccess()
4448
$response['Code'] = $i;
4549
$results[] = $response;
4650
}
51+
$iterationMock->shouldReceive('create')->times(2)->andReturn(json_decode(
52+
file_get_contents($this->dataDir . 'coding/' . 'CreateIterationResponse.json'),
53+
true
54+
)['Response']['Iteration']);
55+
4756
$issueMock->shouldReceive('create')->times(21)->andReturn(...$results);
4857

4958
$this->artisan('issue:import', ['file' => $this->dataDir . 'coding/scrum-issues.csv'])
@@ -54,4 +63,48 @@ public function testImportSuccess()
5463
->expectsOutput("https://$this->codingTeamDomain.coding.net/p/$this->codingProjectUri/all/issues/21")
5564
->assertExitCode(0);
5665
}
66+
67+
public function testImportUserStorySuccess()
68+
{
69+
$mock = \Mockery::mock(Project::class, [])->makePartial();
70+
$this->instance(Project::class, $mock);
71+
72+
$mock->shouldReceive('getIssueTypes')->times(1)->andReturn(json_decode(
73+
file_get_contents($this->dataDir . 'coding/' . 'DescribeProjectIssueTypeListResponse.json'),
74+
true
75+
)['Response']['IssueTypes']);
76+
77+
$issueMock = \Mockery::mock(Issue::class, [])->makePartial();
78+
$this->instance(Issue::class, $issueMock);
79+
$iterationMock = \Mockery::mock(Iteration::class, [])->makePartial();
80+
$this->instance(Iteration::class, $iterationMock);
81+
82+
$response = json_decode(
83+
file_get_contents($this->dataDir . 'coding/' . 'CreateIssueResponse.json'),
84+
true
85+
)['Response']['Issue'];
86+
$response['Code'] = $this->faker->randomNumber();
87+
$result = $response;
88+
$iterationMock->shouldReceive('create')->times(1)->andReturn(json_decode(
89+
file_get_contents($this->dataDir . 'coding/' . 'CreateIterationResponse.json'),
90+
true
91+
)['Response']['Iteration']);
92+
93+
$issueMock->shouldReceive('create')->times(1)->withArgs([
94+
$this->codingToken,
95+
$this->codingProjectUri,
96+
[
97+
'Type' => 'REQUIREMENT',
98+
'IssueTypeId' => 213218,
99+
'Name' => '用户可通过手机号注册账户',
100+
'Priority' => "1",
101+
'IterationCode' => 2746,
102+
]
103+
])->andReturn($result);
104+
105+
$this->artisan('issue:import', ['file' => $this->dataDir . 'coding/scrum-issue-5.csv'])
106+
->expectsOutput("https://$this->codingTeamDomain.coding.net/p/$this->codingProjectUri/all/issues/" .
107+
$result['Code'])
108+
->assertExitCode(0);
109+
}
57110
}

Diff for: tests/data/coding/scrum-issue-5.csv

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
ID,事项类型,标题,描述,状态,创建时间,创建人,更新时间,所属迭代,故事点,处理人,缺陷类型,优先级,截止日期,模块,标签,关注人,开始日期
2+
5,用户故事,用户可通过手机号注册账户,,开发中,2021-10-19 11:26:37,sinkcup,2021-10-19 11:26:37,第 1 次迭代,2,sinkcup,,中,2021-10-21,,,,

0 commit comments

Comments
 (0)