diff --git a/src/controllers/CommandController.ts b/src/controllers/CommandController.ts index 0b2c1b12..3f1f1858 100644 --- a/src/controllers/CommandController.ts +++ b/src/controllers/CommandController.ts @@ -6632,18 +6632,28 @@ export class CommandController extends Controller { }[]; }, ) { + console.log("[Excexute/CreateOfficerProfile] Starting CreateOfficeProfileExcecute"); + console.log("[Excexute/CreateOfficerProfile] Request body count:", body.data?.length); const roleKeycloak = await this.roleKeycloakRepo.findOne({ where: { name: Like("USER") }, }); + console.log("[Excexute/CreateOfficerProfile] roleKeycloak found:", !!roleKeycloak); const list = await getRoles(); - if (!Array.isArray(list)) throw new Error("Failed. Cannot get role(s) data from the server."); + console.log("[Excexute/CreateOfficerProfile] Roles list retrieved, length:", Array.isArray(list) ? list.length : "not array"); + if (!Array.isArray(list)) { + console.error("[Excexute/CreateOfficerProfile] Failed - Cannot get role(s) data from the server"); + throw new Error("Failed. Cannot get role(s) data from the server."); + } let _posNumCodeSit: string = ""; let _posNumCodeSitAbb: string = ""; + console.log("[Excexute/CreateOfficerProfile] Getting command data"); const _command = await this.commandRepository.findOne({ where: { id: body.data.find((x) => x.bodySalarys?.commandId)?.bodySalarys?.commandId ?? "" }, }); + console.log("[Excexute/CreateOfficerProfile] Command found:", !!_command, "isBangkok:", _command?.isBangkok); if (_command) { if (_command?.isBangkok?.toLocaleUpperCase() == "OFFICE") { + console.log("[Excexute/CreateOfficerProfile] Setting position codes for OFFICE"); const orgRootDeputy = await this.orgRootRepository.findOne({ where: { isDeputy: true, @@ -6656,10 +6666,14 @@ export class CommandController extends Controller { }); _posNumCodeSit = orgRootDeputy ? orgRootDeputy?.orgRootName : "สำนักปลัดกรุงเทพมหานคร"; _posNumCodeSitAbb = orgRootDeputy ? orgRootDeputy?.orgRootShortName : "สนป."; + console.log("[Excexute/CreateOfficerProfile] OFFICE position codes set:", _posNumCodeSit, _posNumCodeSitAbb); } else if (_command?.isBangkok?.toLocaleUpperCase() == "BANGKOK") { + console.log("[Excexute/CreateOfficerProfile] Setting position codes for BANGKOK"); _posNumCodeSit = "กรุงเทพมหานคร"; _posNumCodeSitAbb = "กทม."; + console.log("[Excexute/CreateOfficerProfile] BANGKOK position codes set:", _posNumCodeSit, _posNumCodeSitAbb); } else { + console.log("[Excexute/CreateOfficerProfile] Setting position codes from admin profile"); let _profileAdmin = await this.profileRepository.findOne({ where: { keycloak: _command?.createdUserId.toString(), @@ -6678,6 +6692,7 @@ export class CommandController extends Controller { _posNumCodeSitAbb = _profileAdmin?.current_holders.find((x) => x.orgRoot.orgRootShortName)?.orgRoot .orgRootShortName ?? ""; + console.log("[Excexute/CreateOfficerProfile] Admin profile position codes set:", _posNumCodeSit, _posNumCodeSitAbb); } } const before = null; @@ -6689,8 +6704,10 @@ export class CommandController extends Controller { createdAt: new Date(), lastUpdatedAt: new Date(), }; + console.log("[Excexute/CreateOfficerProfile] Starting to process", body.data.length, "profile(s)"); await Promise.all( - body.data.map(async (item) => { + body.data.map(async (item, index) => { + console.log("[Excexute/CreateOfficerProfile] Processing item", index + 1, "of", body.data.length); const _null: any = null; if (item.bodyProfile.posLevelId === "") item.bodyProfile.posLevelId = null; if (item.bodyProfile.posTypeId === "") item.bodyProfile.posTypeId = null; @@ -6698,15 +6715,18 @@ export class CommandController extends Controller { item.bodyProfile.posLevelId && !(await this.posLevelRepo.findOneBy({ id: item.bodyProfile.posLevelId })) ) { + console.error("[Excexute/CreateOfficerProfile] ไม่พบข้อมูลระดับตำแหน่งนี้ posLevelId:", item.bodyProfile.posLevelId); throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูลระดับตำแหน่งนี้"); } if ( item.bodyProfile.posTypeId && !(await this.posTypeRepo.findOneBy({ id: item.bodyProfile.posTypeId })) ) { + console.error("[Excexute/CreateOfficerProfile] ไม่พบข้อมูลประเภทตำแหน่งนี้ posTypeId:", item.bodyProfile.posTypeId); throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูลประเภทตำแหน่งนี้"); } + console.log("[Excexute/CreateOfficerProfile] Processing citizenId:", item.bodyProfile.citizenId); let registrationProvinceId = await this.provinceRepo.findOneBy({ id: item.bodyProfile.registrationProvinceId ?? "", }); @@ -6725,6 +6745,7 @@ export class CommandController extends Controller { let currentSubDistrictId = await this.subDistrictRepo.findOneBy({ id: item.bodyProfile.currentSubDistrictId ?? "", }); + console.log("[Excexute/CreateOfficerProfile] Address validation completed"); let _dateRetire = item.bodyProfile.birthDate == null @@ -6737,8 +6758,11 @@ export class CommandController extends Controller { let userKeycloakId: any; let result: any; + console.log("[Excexute/CreateOfficerProfile] Checking Keycloak user for citizenId:", item.bodyProfile.citizenId); const checkUser = await getUserByUsername(item.bodyProfile.citizenId); + console.log("[Excexute/CreateOfficerProfile] Keycloak user exists:", checkUser.length > 0); if (checkUser.length == 0) { + console.log("[Excexute/CreateOfficerProfile] Creating new Keycloak user"); let password = item.bodyProfile.citizenId; if (item.bodyProfile.birthDate != null) { const _date = new Date(item.bodyProfile.birthDate.toDateString()) @@ -6751,10 +6775,17 @@ export class CommandController extends Controller { const _year = new Date(item.bodyProfile.birthDate.toDateString()).getFullYear() + 543; password = `${_date}${_month}${_year}`; } + console.log("[Excexute/CreateOfficerProfile] Calling createUser for:", item.bodyProfile.citizenId); + console.log("[Excexute/CreateOfficerProfile] createUser data - firstName:", item.bodyProfile.firstName, "lastName:", item.bodyProfile.lastName); userKeycloakId = await createUser(item.bodyProfile.citizenId, password, { firstName: item.bodyProfile.firstName, lastName: item.bodyProfile.lastName, }); + if (userKeycloakId && typeof userKeycloakId === "object" && userKeycloakId.errorMessage) { + console.error("[Excexute/CreateOfficerProfile] createUser FAILED - field:", userKeycloakId.field, "errorMessage:", userKeycloakId.errorMessage, "params:", userKeycloakId.params); + throw new HttpError(HttpStatus.BAD_REQUEST, `Keycloak validation failed: ${userKeycloakId.field} - ${userKeycloakId.errorMessage}`); + } + console.log("[Excexute/CreateOfficerProfile] User created in Keycloak, userKeycloakId:", userKeycloakId); result = await addUserRoles( userKeycloakId, list @@ -6764,14 +6795,18 @@ export class CommandController extends Controller { name: x.name, })), ); + console.log("[Excexute/CreateOfficerProfile] USER role assigned to new user, result:", result); } else { + console.log("[Excexute/CreateOfficerProfile] Updating existing Keycloak user"); userKeycloakId = checkUser[0].id; + console.log("[Excexute/CreateOfficerProfile] Existing userKeycloakId:", userKeycloakId); const rolesData = await getRoleMappings(userKeycloakId); if (rolesData) { const _delRole = rolesData.map((x: any) => ({ id: x.id, name: x.name, })); + console.log("[Excexute/CreateOfficerProfile] Removing old roles:", _delRole.length); await removeUserRoles(userKeycloakId, _delRole); } result = await addUserRoles( @@ -6783,22 +6818,27 @@ export class CommandController extends Controller { name: x.name, })), ); + console.log("[Excexute/CreateOfficerProfile] USER role assigned to existing user"); } let profile: any = await this.profileRepository.findOne({ where: { citizenId: item.bodyProfile.citizenId /*, isActive: true */ }, relations: ["roleKeycloaks", "profileInsignias", "profileAvatars"], }); + console.log("[Excexute/CreateOfficerProfile] Profile found:", !!profile, "for citizenId:", item.bodyProfile.citizenId); let _oldInsigniaIds: string[] = []; let _oldSalaries: any[] = []; //ลูกจ้างประจำ หรือ บุคคลภายนอก if (!profile) { + console.log("[Excexute/CreateOfficerProfile] No existing profile found, creating new profile"); //กรณีลูกจ้างประจำมาสอบเป็นข้าราชการ ต้อง update สถานะโปรไฟล์เดิม let profileEmployee: any = await this.profileEmployeeRepository.findOne({ where: { citizenId: item.bodyProfile.citizenId }, relations: ["profileInsignias", "roleKeycloaks"], }); + console.log("[Excexute/CreateOfficerProfile] Employee profile found:", !!profileEmployee); if (profileEmployee) { + console.log("[Excexute/CreateOfficerProfile] Converting employee profile to officer profile"); const _order = await this.salaryRepo.findOne({ where: { profileEmployeeId: profileEmployee.id }, order: { order: "DESC" }, @@ -6885,21 +6925,26 @@ export class CommandController extends Controller { profile.bloodGroup = item.bodyProfile.bloodGroup ?? null; profile.phone = item.bodyProfile.phone ?? null; + console.log("[Excexute/CreateOfficerProfile] Saving new profile"); await this.profileRepository.save(profile); + console.log("[Excexute/CreateOfficerProfile] New profile saved, profileId:", profile.id); // update user attribute in keycloak await updateUserAttributes(profile.keycloak ?? "", { profileId: [profile.id], prefix: [profile.prefix || ""], }); + console.log("[Excexute/CreateOfficerProfile] Keycloak attributes updated"); setLogDataDiff(req, { before, after: profile }); } //ขรก.ในระบบ หรือ ขรก.ในระบบที่สถานะพ้นจากราชการ else { + console.log("[Excexute/CreateOfficerProfile] Existing profile found, isLeave:", profile.isLeave, "leaveType:", profile.leaveType); //สร้างโปรไฟล์ใหม่ ถ้าสถานะพ้นราชการ คำสั่งโอนออกหรือคำสั่งขอลาออก if ( profile.isLeave && ["PLACEMENT_TRANSFER", "RETIRE_RESIGN"].includes(profile.leaveType) ) { + console.log("[Excexute/CreateOfficerProfile] Profile is leaving with eligible leave type, creating new profile record"); //ดึง profileSalary เดิม _oldSalaries = await this.salaryRepo.find({ where: { profileId: profile.id }, @@ -6949,8 +6994,10 @@ export class CommandController extends Controller { profile.bloodGroup = item.bodyProfile.bloodGroup ?? null; profile.phone = item.bodyProfile.phone ?? null; await this.profileRepository.save(profile); + console.log("[Excexute/CreateOfficerProfile] New profile record saved for leaving officer, profileId:", profile.id); setLogDataDiff(req, { before, after: profile }); } else { + console.log("[Excexute/CreateOfficerProfile] Updating existing active profile"); profile.roleKeycloaks = result && roleKeycloak ? [roleKeycloak] : []; profile.keycloak = userKeycloakId && typeof userKeycloakId === "string" ? userKeycloakId : ""; @@ -7037,13 +7084,16 @@ export class CommandController extends Controller { ? item.bodyProfile.phone : profile.phone; await this.profileRepository.save(profile); + console.log("[Excexute/CreateOfficerProfile] Existing active profile updated, profileId:", profile.id); setLogDataDiff(req, { before, after: profile }); } } if (profile && profile.id) { + console.log("[Excexute/CreateOfficerProfile] Processing additional data for profileId:", profile.id); //Educations if (item.bodyEducations && item.bodyEducations.length > 0) { + console.log("[Excexute/CreateOfficerProfile] Processing educations, count:", item.bodyEducations.length); await Promise.all( item.bodyEducations.map(async (education) => { const profileEdu = new ProfileEducation(); @@ -7066,6 +7116,7 @@ export class CommandController extends Controller { } //Certificates if (item.bodyCertificates && item.bodyCertificates.length > 0) { + console.log("[Excexute/CreateOfficerProfile] Processing certificates, count:", item.bodyCertificates.length); await Promise.all( item.bodyCertificates.map(async (cer) => { const profileCer = new ProfileCertificate(); @@ -7082,6 +7133,7 @@ export class CommandController extends Controller { } //FamilyCouple if (item.bodyMarry != null) { + console.log("[Excexute/CreateOfficerProfile] Processing couple/marry data"); const profileCouple = new ProfileFamilyCouple(); const data = { profileId: profile.id, @@ -7103,6 +7155,7 @@ export class CommandController extends Controller { } //FamilyFather if (item.bodyFather != null) { + console.log("[Excexute/CreateOfficerProfile] Processing father data"); const profileFather = new ProfileFamilyFather(); const data = { profileId: profile.id, @@ -7123,6 +7176,7 @@ export class CommandController extends Controller { } //FamilyMother if (item.bodyMother != null) { + console.log("[Excexute/CreateOfficerProfile] Processing mother data"); const profileMother = new ProfileFamilyMother(); const data = { profileId: profile.id, @@ -7144,6 +7198,7 @@ export class CommandController extends Controller { //Salary //insert profileSalary อันเก่า กรณีพ้นราชการแล้วกลับมาบรรจุ if (_oldSalaries.length > 0) { + console.log("[Excexute/CreateOfficerProfile] Restoring old salaries, count:", _oldSalaries.length); await Promise.all( _oldSalaries.map(async (oldSal) => { const profileSal: any = new ProfileSalary(); @@ -7160,6 +7215,7 @@ export class CommandController extends Controller { } //insert item.bodySalarys ต่อจากที่ insert เดิมไปแล้ว if (item.bodySalarys && item.bodySalarys != null) { + console.log("[Excexute/CreateOfficerProfile] Processing new salary data"); const dest_item = await this.salaryRepo.findOne({ where: { profileId: profile.id }, order: { order: "DESC" }, @@ -7184,7 +7240,9 @@ export class CommandController extends Controller { } //Position if (item.bodyPosition && item.bodyPosition != null) { + console.log("[Excexute/CreateOfficerProfile] Processing position assignment"); // STEP 1: หา posMaster ที่จะใช้งานตาม id ที่ส่งมา (อาจเป็นตำแหน่งเก่าหรือใหม่ก็ได้) + console.log("[Excexute/CreateOfficerProfile] STEP 1: Finding posMaster, posmasterId:", item.bodyPosition.posmasterId); let posMaster = await this.posMasterRepository.findOne({ where: { id: item.bodyPosition.posmasterId, @@ -7198,14 +7256,17 @@ export class CommandController extends Controller { orgChild4: true, }, }); + console.log("[Excexute/CreateOfficerProfile] posMaster found:", !!posMaster); // เช็คว่า posMaster ที่หามาอยู่ในโครงสร้างปัจจุบันหรือไม่ const isCurrent = posMaster?.orgRevision?.orgRevisionIsCurrent === true && posMaster?.orgRevision?.orgRevisionIsDraft === false; + console.log("[Excexute/CreateOfficerProfile] posMaster isCurrent:", isCurrent); // ถ้าไม่อยู่ในโครงสร้างปัจจุบัน ให้หาตัวใหม่จาก ancestorDNA if (!isCurrent && posMaster?.ancestorDNA) { + console.log("[Excexute/CreateOfficerProfile] Finding current posMaster from ancestorDNA"); posMaster = await this.posMasterRepository.findOne({ where: { ancestorDNA: posMaster.ancestorDNA, @@ -7223,16 +7284,18 @@ export class CommandController extends Controller { orgChild4: true, }, }); + console.log("[Excexute/CreateOfficerProfile] Current posMaster from ancestorDNA found:", !!posMaster); } if (posMaster == null) { console.error( - `[CreateOfficerProfile] not found posMasterId: ${item.bodyPosition.posmasterId}` + `[Excexute/CreateOfficerProfile] not found posMasterId: ${item.bodyPosition.posmasterId}` ); throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลตำแหน่งนี้"); } // STEP 2: เคลียร์ข้อมูลตำแหน่งเก่าที่ครองอยู่ ในโครงสร้างปัจจุบัน + console.log("[Excexute/CreateOfficerProfile] STEP 2: Clearing old position data"); const posMasterOld = await this.posMasterRepository.findOne({ where: { current_holderId: profile.id, @@ -7258,6 +7321,7 @@ export class CommandController extends Controller { } // STEP 3: เคลียร์ position ที่เลือกไว้อื่นๆ ใน posMaster ตัวใหม่ + console.log("[Excexute/CreateOfficerProfile] STEP 3: Clearing other selected positions in new posMaster"); const checkPosition = await this.positionRepository.find({ where: { posMasterId: posMaster.id, @@ -7273,6 +7337,7 @@ export class CommandController extends Controller { } // STEP 4: กำหนดคนครองใหม่ให้กับ posMaster + console.log("[Excexute/CreateOfficerProfile] STEP 4: Assigning new holder to posMaster"); posMaster.current_holderId = profile.id; posMaster.lastUpdatedAt = new Date(); // posMaster.conditionReason = _null; @@ -7282,8 +7347,10 @@ export class CommandController extends Controller { await CreatePosMasterHistoryOfficer(posMasterOld.id, req); } await this.posMasterRepository.save(posMaster); + console.log("[Excexute/CreateOfficerProfile] posMaster saved with new holder"); // STEP 5: กำหนด position ใหม่ + console.log("[Excexute/CreateOfficerProfile] STEP 5: Determining position to assign"); // Match position ตามลำดับ priority: // Condition 1: match จาก positionId // Condition 2: match 7 ฟิลด์ (positionName, posTypeId, posLevelId, positionField, positionArea, positionExecutiveField, posExecutiveId) @@ -7295,6 +7362,7 @@ export class CommandController extends Controller { // ═══════════════════════════════════════════════════════════ // CONDITION 1: เช็คจาก positionId ตรง // ═══════════════════════════════════════════════════════════ + console.log("[Excexute/CreateOfficerProfile] CONDITION 1: Checking by positionId:", item.bodyPosition?.positionId); if (item.bodyPosition?.positionId) { const positionById = await this.positionRepository.findOne({ where: { @@ -7306,6 +7374,7 @@ export class CommandController extends Controller { if (positionById) { positionNew = positionById; + console.log("[Excexute/CreateOfficerProfile] CONDITION 1 matched, positionId:", positionById.id); } } @@ -7313,6 +7382,7 @@ export class CommandController extends Controller { // CONDITION 2: Match 7 ฟิลด์ (ถ้า Condition 1 ไม่ match) // ═══════════════════════════════════════════════════════════ if (!positionNew && item.bodyPosition) { + console.log("[Excexute/CreateOfficerProfile] CONDITION 1 not matched, trying CONDITION 2: Match 7 fields"); // สร้าง where clause แบบ dynamic - ใส่เฉพาะฟิลด์ที่ไม่ใช่ null const whereCondition: any = { posMasterId: posMaster.id, @@ -7342,6 +7412,7 @@ export class CommandController extends Controller { if (positionBy7Fields) { positionNew = positionBy7Fields; + console.log("[Excexute/CreateOfficerProfile] CONDITION 2 matched with 7 fields, positionId:", positionBy7Fields.id); } } @@ -7349,6 +7420,7 @@ export class CommandController extends Controller { // CONDITION 3: Match 3 ฟิลด์ (ถ้า Condition 2 ไม่ match) // ═══════════════════════════════════════════════════════════ if (!positionNew && item.bodyPosition) { + console.log("[Excexute/CreateOfficerProfile] CONDITION 2 not matched, trying CONDITION 3: Match 3 fields"); const positionBy3Fields = await this.positionRepository.findOne({ where: { posMasterId: posMaster.id, @@ -7362,6 +7434,9 @@ export class CommandController extends Controller { if (positionBy3Fields) { positionNew = positionBy3Fields; + console.log("[Excexute/CreateOfficerProfile] CONDITION 3 matched with 3 fields, positionId:", positionBy3Fields.id); + } else { + console.log("[Excexute/CreateOfficerProfile] No position matched for profileId:", profile.id); } } @@ -7387,6 +7462,7 @@ export class CommandController extends Controller { // ถ้าไม่ใช่ตำแหน่งนั่งทับ (isSit = false) ถึงจะอัพเดทตำแหน่งในทะเบียนประวัติ if (positionNew != null) { + console.log("[Excexute/CreateOfficerProfile] Final position assignment, isSit:", posMaster.isSit, "positionId:", positionNew.id); positionNew.positionIsSelected = true; // อัพเดท org และ posMasterNo ตลอดไม่ต้องดัก isSit profile.posMasterNo = getPosMasterNo(posMaster); @@ -7412,6 +7488,7 @@ export class CommandController extends Controller { } // Insignia if (_oldInsigniaIds.length > 0) { + console.log("[Excexute/CreateOfficerProfile] Processing old insignias, count:", _oldInsigniaIds.length); const _insignias = await this.insigniaRepo.find({ where: { id: In(_oldInsigniaIds), isDeleted: false }, order: { createdAt: "ASC" }, @@ -7446,6 +7523,7 @@ export class CommandController extends Controller { } // เพิ่มรูปภาพโปรไฟล์ if (item.bodyProfile.objectRefId) { + console.log("[Excexute/CreateOfficerProfile] Processing profile avatar image, objectRefId:", item.bodyProfile.objectRefId); const _profileAvatar = new ProfileAvatar(); Object.assign(_profileAvatar, { ...meta, @@ -7489,6 +7567,7 @@ export class CommandController extends Controller { } }), ); + console.log("[Excexute/CreateOfficerProfile] CreateOfficeProfileExcecute completed successfully"); return new HttpSuccess(); }