Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 8dd0270

Browse files
feat: #72 create iteration when import
1 parent 8d970e9 commit 8dd0270

File tree

3 files changed

+91
-16
lines changed

3 files changed

+91
-16
lines changed

‎app/Commands/IssueImportCommand.php

Lines changed: 34 additions & 14 deletions
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
}

‎tests/Feature/IssueImportCommandTest.php

Lines changed: 55 additions & 2 deletions
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
}

‎tests/data/coding/scrum-issue-5.csv

Lines changed: 2 additions & 0 deletions
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)

AltStyle によって変換されたページ (->オリジナル) /