Hiệu chỉnh 1 số lỗi chức năng sprint review
This commit is contained in:
parent
790d7cf60f
commit
26282bbe8e
|
|
@ -12,6 +12,7 @@ use App\Traits\HasSearchRequest;
|
|||
use Carbon\Carbon;
|
||||
use Carbon\CarbonPeriod;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Modules\Admin\app\Models\Criteria;
|
||||
use Modules\Admin\app\Models\Sprint;
|
||||
use Modules\Admin\app\Models\SprintCriteria;
|
||||
|
|
@ -46,6 +47,7 @@ class CriteriasController extends Controller
|
|||
*/
|
||||
public function getCriteriasForSprint($sprintId)
|
||||
{
|
||||
$userInfo = auth('admins')->user();
|
||||
$sprint = Sprint::with('criterias')->find($sprintId);
|
||||
if (!$sprint) {
|
||||
$allUser = self::getAllUserJira();
|
||||
|
|
@ -78,7 +80,7 @@ class CriteriasController extends Controller
|
|||
}, $filteredObjects);
|
||||
|
||||
// Get criteria for sprint and member
|
||||
$criterias = Criteria::where('type', "SPRINT")->get();
|
||||
$criteriasSprint = Criteria::where('type', "SPRINT")->get()->toArray();
|
||||
$members = Criteria::where('type', "MEMBER")->get()->toArray();
|
||||
|
||||
// Merge user information with criteria
|
||||
|
|
@ -90,7 +92,7 @@ class CriteriasController extends Controller
|
|||
}
|
||||
|
||||
// Map result to final format
|
||||
$users = array_map(function ($item) {
|
||||
$users = array_map(function ($item) use ($userInfo) {
|
||||
return [
|
||||
"user_id" => $item['accountId'],
|
||||
"user" => $item['displayName'],
|
||||
|
|
@ -98,21 +100,49 @@ class CriteriasController extends Controller
|
|||
"criteria_id" => $item['id'],
|
||||
"point" => "",
|
||||
"note" => "",
|
||||
"created_by" => "",
|
||||
"created_by" => $userInfo->name,
|
||||
"name" => $item['name'],
|
||||
"criteria_description" => $item['description'],
|
||||
];
|
||||
}, $result);
|
||||
|
||||
// Prepare final data
|
||||
|
||||
$criterias = array_map(function ($item) {
|
||||
$item["expect"] = "";
|
||||
$item["actual"] = "";
|
||||
$item["note"] = "";
|
||||
$item["point"] = "";
|
||||
return $item;
|
||||
}, $criteriasSprint);
|
||||
|
||||
$data = [
|
||||
"criterias" => $criterias,
|
||||
"users" => $users
|
||||
];
|
||||
} else {
|
||||
$users = $sprint->users()->get();
|
||||
$data = $sprint;
|
||||
$data->users = $users;
|
||||
// echo json_encode($sprint);
|
||||
// dd();
|
||||
$criterias = array_map(function ($item) {
|
||||
$item["expect"] = $item["pivot"]["expect_result"];
|
||||
$item["actual"] = $item["pivot"]["actual_result"];
|
||||
$item["note"] = $item["pivot"]["note"];
|
||||
$item["point"] = $item["pivot"]["point"];
|
||||
unset($item["pivot"]); // Use unset() instead of delete
|
||||
return $item;
|
||||
}, $sprint->criterias->toArray());
|
||||
|
||||
$data = [
|
||||
"id" => $sprint->id,
|
||||
"name" => $sprint->name,
|
||||
"point" => $sprint->point,
|
||||
"project_id" => $sprint->project_id,
|
||||
"start_date" => $sprint->start_date,
|
||||
"end_date" => $sprint->end_date,
|
||||
"complete_date" => $sprint->complete_date,
|
||||
"criterias" => $criterias,
|
||||
"users" => $users
|
||||
];
|
||||
}
|
||||
return AbstractController::ResultSuccess($data);
|
||||
}
|
||||
|
|
@ -204,7 +234,7 @@ class CriteriasController extends Controller
|
|||
* - user_note (optional): The note of the user (default is the same as note)
|
||||
* @return bool True if successful, false otherwise
|
||||
*/
|
||||
public function updateCriteriasForSprint($sprintId, Request $request)
|
||||
public function updateCriteriasForSprint2($sprintId, Request $request)
|
||||
{
|
||||
$user = auth('admins')->user();
|
||||
|
||||
|
|
@ -265,4 +295,77 @@ class CriteriasController extends Controller
|
|||
|
||||
return AbstractController::ResultSuccess("");
|
||||
}
|
||||
|
||||
|
||||
public function updateCriteriasForSprint($sprintId, Request $request)
|
||||
{
|
||||
// Validate dữ liệu đầu vào
|
||||
$validated = $request->validate([
|
||||
'name' => 'required|string',
|
||||
'finalPoint' => 'required|string',
|
||||
'project_id' => 'required|integer',
|
||||
'criterias' => 'required|array',
|
||||
'users' => 'required|array',
|
||||
]);
|
||||
// $sprintId = (int)$sprintId;
|
||||
// Sử dụng transaction để đảm bảo tính toàn vẹn dữ liệu
|
||||
DB::beginTransaction();
|
||||
try {
|
||||
// Kiểm tra xem Sprint có tồn tại không
|
||||
$sprint = Sprint::find($sprintId);
|
||||
|
||||
if ($sprint) {
|
||||
// Nếu tồn tại, xóa các liên kết hiện tại
|
||||
$sprint->sprintsCriterias()->delete();
|
||||
$sprint->usersCriterias()->delete();
|
||||
|
||||
// Cập nhật thông tin Sprint nếu cần
|
||||
$sprint->update([
|
||||
'name' => $validated['name'],
|
||||
'project_id' => $validated['project_id'],
|
||||
'point' => $validated['finalPoint'] ?? "",
|
||||
// Cập nhật các trường khác nếu có
|
||||
]);
|
||||
} else {
|
||||
// Nếu không tồn tại, tạo mới Sprint
|
||||
$sprint = Sprint::create([
|
||||
'id' => $sprintId,
|
||||
'name' => $validated['name'],
|
||||
'project_id' => $validated['project_id'],
|
||||
'point' => $validated['finalPoint'] ?? "",
|
||||
// Thêm các trường khác nếu có
|
||||
]);
|
||||
}
|
||||
|
||||
// Thêm lại các liên kết sprints_criterias
|
||||
foreach ($validated['criterias'] as $criteria) {
|
||||
SprintCriteria::create([
|
||||
'sprint_id' => $sprint->id,
|
||||
'criteria_id' => $criteria['id'],
|
||||
'point' => $criteria['point'] ?? "",
|
||||
'expect_result' => $criteria['expect'] ?? "",
|
||||
'actual_result' => $criteria['actual'] ?? "",
|
||||
'note' => $criteria['note'] ?? "",
|
||||
]);
|
||||
}
|
||||
|
||||
// Thêm lại các liên kết users_criterias
|
||||
foreach ($validated['users'] as $userCriteria) {
|
||||
UserCriteria::create([
|
||||
'user_email' => $userCriteria['user_email'],
|
||||
'criteria_id' => $userCriteria['criteria_id'],
|
||||
'sprint_id' => $sprint->id,
|
||||
'point' => $userCriteria['point'] ?? "",
|
||||
'note' => $userCriteria['note'] ?? "",
|
||||
]);
|
||||
}
|
||||
|
||||
DB::commit();
|
||||
return AbstractController::ResultSuccess("Update sprint success");
|
||||
} catch (\Exception $e) {
|
||||
DB::rollBack();
|
||||
|
||||
return AbstractController::ResultError("Update sprint failed: " . $e->getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ use Illuminate\Database\Eloquent\Model;
|
|||
class Sprint extends Model
|
||||
{
|
||||
protected $table = 'sprint';
|
||||
protected $fillable = ['name', 'point', 'project_id', 'start_date', 'end_date', 'complete_date'];
|
||||
protected $fillable = ['id', 'name', 'point', 'project_id', 'start_date', 'end_date', 'complete_date'];
|
||||
|
||||
public function criterias()
|
||||
{
|
||||
|
|
@ -53,4 +53,13 @@ class Sprint extends Model
|
|||
{
|
||||
return $this->hasMany(UserCriteria::class);
|
||||
}
|
||||
|
||||
public function sprintsCriterias()
|
||||
{
|
||||
return $this->hasMany(SprintCriteria::class, 'sprint_id');
|
||||
}
|
||||
public function usersCriterias()
|
||||
{
|
||||
return $this->hasMany(UserCriteria::class, 'sprint_id');
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -64,7 +64,7 @@ export const getAllSprintByIdBoard =
|
|||
export const getAllIssuesByIdSprint =
|
||||
API_URL + 'v1/admin/jira/get-all-issue-by-id-sprint'
|
||||
|
||||
export const updateSprintReview = API_URL + 'v1/admin/sprint-review/update'
|
||||
export const updateSprintReview = API_URL + 'v1/admin/criterias/sprints'
|
||||
|
||||
//TestReport
|
||||
export const getAllTestCase = API_URL + 'v1/admin/criterias/test-cases/getAll'
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ import {
|
|||
Select,
|
||||
Table,
|
||||
Text,
|
||||
Textarea,
|
||||
TextInput,
|
||||
Title,
|
||||
} from '@mantine/core'
|
||||
|
|
@ -197,31 +198,35 @@ const SprintReview = () => {
|
|||
setLoading(false)
|
||||
}
|
||||
}, [filter])
|
||||
console.log(criteriaSprint, 'criteriaSprint')
|
||||
// console.log(criteriaSprint, 'criteriaSprint')
|
||||
// console.log(criteriaUsers, 'criteriaUsers')
|
||||
|
||||
// const handleCreate = async (values: TUser) => {
|
||||
// try {
|
||||
// const { id, ...data } = values
|
||||
// const res = await post(createOrUpdateUser, data)
|
||||
// if (res.status === true) {
|
||||
// // setAction('review')
|
||||
// form.reset()
|
||||
// // getAll()
|
||||
// // setInfo(JSON.stringify(res.data, null, 2))
|
||||
// }
|
||||
// } catch (error) {
|
||||
// console.log(error)
|
||||
// }
|
||||
// }
|
||||
const getAll = () => {
|
||||
const fetchData = async () => {
|
||||
const result = await getListCriteriasBySprint(filter.sprint)
|
||||
if (result) {
|
||||
setCriteriaSprint(result.criterias ?? [])
|
||||
setCriteriaUsers(result.users ?? [])
|
||||
setFinalPoint(result.point ?? '')
|
||||
setLoading(false)
|
||||
}
|
||||
}
|
||||
fetchData()
|
||||
}
|
||||
|
||||
const handleUpdate = async () => {
|
||||
const values = {}
|
||||
const values = {
|
||||
name: dataSprint.find((item: any) => item.id == filter.sprint)?.name,
|
||||
project_id: filter.project,
|
||||
criterias: criteriaSprint,
|
||||
users: criteriaUsers,
|
||||
finalPoint: finalPoint,
|
||||
}
|
||||
try {
|
||||
const res = await update(
|
||||
updateSprintReview,
|
||||
`${updateSprintReview}/${filter.sprint}`,
|
||||
values,
|
||||
// , getAll
|
||||
getAll,
|
||||
)
|
||||
if (res === true) {
|
||||
setAction('')
|
||||
|
|
@ -304,6 +309,7 @@ const SprintReview = () => {
|
|||
Project:
|
||||
</Text>
|
||||
<Select
|
||||
searchable
|
||||
clearable
|
||||
w="60%"
|
||||
value={filter.project}
|
||||
|
|
@ -326,6 +332,7 @@ const SprintReview = () => {
|
|||
Sprint:
|
||||
</Text>
|
||||
<Select
|
||||
searchable
|
||||
clearable
|
||||
w="40%"
|
||||
value={filter.sprint}
|
||||
|
|
@ -419,12 +426,13 @@ const SprintReview = () => {
|
|||
<Table.Tr key={index} style={rowStyle}>
|
||||
{/* TextInput cho trường name */}
|
||||
<Table.Td>
|
||||
<TextInput
|
||||
{/* <TextInput
|
||||
value={item.name}
|
||||
onChange={(e) =>
|
||||
handleInputChange(index, 'name', e.target.value)
|
||||
}
|
||||
/>
|
||||
/> */}
|
||||
{item.name}
|
||||
</Table.Td>
|
||||
{/* TextInput cho trường expect */}
|
||||
<Table.Td>
|
||||
|
|
@ -446,11 +454,15 @@ const SprintReview = () => {
|
|||
</Table.Td>
|
||||
{/* TextInput cho trường note */}
|
||||
<Table.Td>
|
||||
<TextInput
|
||||
<Textarea
|
||||
autosize
|
||||
placeholder="Good performance"
|
||||
value={item.note}
|
||||
onChange={(e) =>
|
||||
handleInputChange(index, 'note', e.target.value)
|
||||
}
|
||||
minRows={2}
|
||||
maxRows={4}
|
||||
/>
|
||||
</Table.Td>
|
||||
<Table.Td>
|
||||
|
|
@ -562,20 +574,25 @@ const SprintReview = () => {
|
|||
)}
|
||||
|
||||
<Table.Td>
|
||||
<TextInput
|
||||
{item.name}
|
||||
{/* <TextInput
|
||||
value={item.name}
|
||||
onChange={(e) =>
|
||||
handleInputChangeUsers(index, 'name', e.target.value)
|
||||
}
|
||||
/>
|
||||
/> */}
|
||||
</Table.Td>
|
||||
|
||||
<Table.Td>
|
||||
<TextInput
|
||||
<Textarea
|
||||
autosize
|
||||
placeholder="Good performance"
|
||||
value={item.note}
|
||||
onChange={(e) =>
|
||||
handleInputChangeUsers(index, 'note', e.target.value)
|
||||
}
|
||||
minRows={2}
|
||||
maxRows={4}
|
||||
/>
|
||||
</Table.Td>
|
||||
|
||||
|
|
@ -620,7 +637,7 @@ const SprintReview = () => {
|
|||
position={{ top: 30, right: 10 }}
|
||||
>
|
||||
<Text className={classes.dialogText} size="sm" mb="xs" fw={500}>
|
||||
Do you want to delete this record?
|
||||
Do you want to update?
|
||||
<Group justify="center" m={10}>
|
||||
<Button
|
||||
disabled={activeBtn}
|
||||
|
|
@ -628,6 +645,7 @@ const SprintReview = () => {
|
|||
size="xs"
|
||||
variant="light"
|
||||
onClick={async () => {
|
||||
setLoading(true)
|
||||
setActiveBtn(true)
|
||||
await handleUpdate()
|
||||
setActiveBtn(false)
|
||||
|
|
|
|||
|
|
@ -298,6 +298,7 @@ const TestReport = () => {
|
|||
Project:
|
||||
</Text>
|
||||
<Select
|
||||
searchable
|
||||
clearable
|
||||
w="60%"
|
||||
value={filter.project}
|
||||
|
|
@ -320,6 +321,7 @@ const TestReport = () => {
|
|||
Sprint:
|
||||
</Text>
|
||||
<Select
|
||||
searchable
|
||||
clearable
|
||||
w="40%"
|
||||
value={filter.sprint}
|
||||
|
|
@ -484,12 +486,20 @@ const TestReport = () => {
|
|||
/>
|
||||
|
||||
<Textarea
|
||||
style={{ marginTop: '10px' }}
|
||||
autosize
|
||||
minRows={2}
|
||||
maxRows={4}
|
||||
label="Input"
|
||||
required
|
||||
value={form.values.input}
|
||||
onChange={(e) => form.setFieldValue('input', e.target.value)}
|
||||
/>
|
||||
<Textarea
|
||||
style={{ marginTop: '10px' }}
|
||||
autosize
|
||||
minRows={2}
|
||||
maxRows={4}
|
||||
label="Expect Output"
|
||||
required
|
||||
value={form.values.expect_output}
|
||||
|
|
@ -498,6 +508,10 @@ const TestReport = () => {
|
|||
}
|
||||
/>
|
||||
<Textarea
|
||||
style={{ marginTop: '10px' }}
|
||||
autosize
|
||||
minRows={2}
|
||||
maxRows={4}
|
||||
label="Actual Output"
|
||||
required
|
||||
value={form.values.actual_output}
|
||||
|
|
@ -506,7 +520,7 @@ const TestReport = () => {
|
|||
}
|
||||
/>
|
||||
|
||||
<Box display={'flex'}>
|
||||
<Box display={'flex'} style={{ marginTop: '10px' }}>
|
||||
<Box style={{ display: 'flex', flexFlow: 'column' }} w={'45%'}>
|
||||
<TextInput
|
||||
label="Issue ID On Jira"
|
||||
|
|
@ -533,6 +547,10 @@ const TestReport = () => {
|
|||
</Box>
|
||||
</Box>
|
||||
<Textarea
|
||||
style={{ marginTop: '10px' }}
|
||||
autosize
|
||||
minRows={2}
|
||||
maxRows={4}
|
||||
label="Note"
|
||||
required
|
||||
value={form.values.note}
|
||||
|
|
@ -583,25 +601,34 @@ const TestReport = () => {
|
|||
|
||||
<Textarea
|
||||
readOnly
|
||||
style={{ pointerEvents: 'none' }}
|
||||
style={{ marginTop: '10px' }}
|
||||
autosize
|
||||
minRows={2}
|
||||
maxRows={4}
|
||||
label="Input"
|
||||
value={item.input}
|
||||
/>
|
||||
|
||||
<Textarea
|
||||
readOnly
|
||||
style={{ pointerEvents: 'none' }}
|
||||
style={{ marginTop: '10px' }}
|
||||
label="Expect Output"
|
||||
value={item.expect_output}
|
||||
autosize
|
||||
minRows={2}
|
||||
maxRows={4}
|
||||
/>
|
||||
|
||||
<Textarea
|
||||
readOnly
|
||||
style={{ pointerEvents: 'none' }}
|
||||
style={{ marginTop: '10px' }}
|
||||
autosize
|
||||
minRows={2}
|
||||
maxRows={4}
|
||||
label="Actual Output"
|
||||
value={item.actual_output}
|
||||
/>
|
||||
<Box display={'flex'}>
|
||||
<Box display={'flex'} style={{ marginTop: '10px' }}>
|
||||
<Box style={{ display: 'flex', flexFlow: 'column' }} w={'45%'}>
|
||||
<TextInput
|
||||
readOnly
|
||||
|
|
@ -627,7 +654,10 @@ const TestReport = () => {
|
|||
</Box>
|
||||
<Textarea
|
||||
readOnly
|
||||
style={{ pointerEvents: 'none' }}
|
||||
style={{ marginTop: '10px' }}
|
||||
autosize
|
||||
minRows={2}
|
||||
maxRows={4}
|
||||
label="Note"
|
||||
value={item.note}
|
||||
/>
|
||||
|
|
|
|||
Loading…
Reference in New Issue