diff --git a/app/core/routes/api.route.js b/app/core/routes/api.route.js index ec753b0..03b4b81 100644 --- a/app/core/routes/api.route.js +++ b/app/core/routes/api.route.js @@ -13,9 +13,4 @@ router.use('/attedances', AbsensRouter) router.use('/branches', BranchRouter) router.use('/user-management', userManagement) - - - - - module.exports = router diff --git a/app/core/routes/auth.route.js b/app/core/routes/auth.route.js index 8c81d62..1a8ca88 100644 --- a/app/core/routes/auth.route.js +++ b/app/core/routes/auth.route.js @@ -33,8 +33,6 @@ router.post("/forgot-password", apiKey, function name(req, res) { controller.resetPassword(req, res, token); }); - - module.exports = router diff --git a/app/core/routes/userManagement.route.js b/app/core/routes/userManagement.route.js index 23af2ee..7a80091 100644 --- a/app/core/routes/userManagement.route.js +++ b/app/core/routes/userManagement.route.js @@ -11,7 +11,6 @@ router.post('/', apiKey, jwt, (req, res) => { controller.create(req, res) }) - router.get('/', apiKey, jwt, (req, res) => { controller.index(req, res) }) diff --git a/app/modules/absensi/services/absensi.service.js b/app/modules/absensi/services/absensi.service.js index 8876b97..af88536 100644 --- a/app/modules/absensi/services/absensi.service.js +++ b/app/modules/absensi/services/absensi.service.js @@ -67,48 +67,85 @@ const create = async (req, res) => { } if (attendance && attendance.clock_in) { - // 🕛 Jika jam antara 12–15 → lunch_in - if (currentHour >= 12 && currentHour < 15 && !attendance.lunch_in) { - attendance.lunch_in = now.toDate(); - await attendance.save({ transaction: t }); - await t.commit(); - return response.success(res, attendance, 'Absen masuk setelah makan siang berhasil'); + // 🕛 Jika branch tidak mengaktifkan absen siang + if (!branch.lunch_attendance) { + // Langsung lewati logika absen siang dan lanjut ke clock_out + if (currentHour >= 15 && !attendance.clock_out) { + attendance.clock_out = now.toDate(); + + const durationMs = moment(attendance.clock_out).diff(moment(attendance.clock_in)); + const hours = Math.floor(durationMs / (1000 * 60 * 60)); + const minutes = Math.floor((durationMs % (1000 * 60 * 60)) / (1000 * 60)); + attendance.work_duration = `${hours} jam ${minutes} menit`; + + await attendance.save({ transaction: t }); + await t.commit(); + + return response.success( + res, + { + ...attendance.toJSON(), + branch_name: branch.name, + clock_in: moment(attendance.clock_in).tz('Asia/Jakarta').format('YYYY-MM-DD HH:mm:ss'), + clock_out: moment(attendance.clock_out).tz('Asia/Jakarta').format('YYYY-MM-DD HH:mm:ss'), + work_duration: attendance.work_duration, + }, + 'Absen pulang berhasil' + ); + } + + if (currentHour < 15 && !attendance.clock_out) { + await t.rollback(); + return response.failed(res, 400, 'Belum waktunya absen pulang'); + } + } else { + // 🕛 Jika branch pakai absen siang + if (currentHour >= 12 && currentHour < 15 && !attendance.lunch_in) { + attendance.lunch_in = now.toDate(); + await attendance.save({ transaction: t }); + await t.commit(); + return response.success(res, attendance, 'Absen masuk setelah makan siang berhasil'); + } + + if (currentHour < 12 && !attendance.lunch_in) { + await t.rollback(); + return response.failed(res, 400, 'Belum waktunya absen setelah makan siang'); + } + + if (currentHour >= 15 && !attendance.clock_out) { + attendance.clock_out = now.toDate(); + + const durationMs = moment(attendance.clock_out).diff(moment(attendance.clock_in)); + const hours = Math.floor(durationMs / (1000 * 60 * 60)); + const minutes = Math.floor((durationMs % (1000 * 60 * 60)) / (1000 * 60)); + attendance.work_duration = `${hours} jam ${minutes} menit`; + + await attendance.save({ transaction: t }); + await t.commit(); + + return response.success( + res, + { + ...attendance.toJSON(), + branch_name: branch.name, + clock_in: moment(attendance.clock_in).tz('Asia/Jakarta').format('YYYY-MM-DD HH:mm:ss'), + clock_out: moment(attendance.clock_out).tz('Asia/Jakarta').format('YYYY-MM-DD HH:mm:ss'), + work_duration: attendance.work_duration, + }, + 'Absen pulang berhasil' + ); + } + + if (currentHour < 15 && attendance.lunch_in && !attendance.clock_out) { + await t.rollback(); + return response.failed(res, 400, 'Belum waktunya absen pulang'); + } } - if (currentHour < 12 && !attendance.lunch_in) { - await t.rollback(); - return response.failed(res, 400, 'Belum waktunya absen setelah makan siang'); - } - - // 🕒 Jika jam >= 15 → otomatis clock_out - if (currentHour >= 15 && !attendance.clock_out) { - attendance.clock_out = now.toDate(); - - const durationMs = moment(attendance.clock_out).diff(moment(attendance.clock_in)); - const hours = Math.floor(durationMs / (1000 * 60 * 60)); - const minutes = Math.floor((durationMs % (1000 * 60 * 60)) / (1000 * 60)); - attendance.work_duration = `${hours} jam ${minutes} menit`; - - await attendance.save({ transaction: t }); - await t.commit(); - - return response.success(res, { - ...attendance.toJSON(), - branch_name: branch.name, - clock_in: moment(attendance.clock_in).tz('Asia/Jakarta').format('YYYY-MM-DD HH:mm:ss'), - clock_out: moment(attendance.clock_out).tz('Asia/Jakarta').format('YYYY-MM-DD HH:mm:ss'), - work_duration: attendance.work_duration, - }, 'Absen pulang berhasil'); - } - if (currentHour < 15 && attendance.lunch_in && !attendance.clock_out) { - await t.rollback(); - return response.failed(res, 400, 'Belum waktunya absen pulang'); - } - + await t.rollback(); return response.failed(res, 400, 'Sudah melakukan absen hari ini'); } - - + // === Jika sudah absen masuk tapi belum pulang === // if (attendance && attendance.clock_in && !attendance.clock_out) { // attendance.clock_out = now.toDate(); // waktu WIB @@ -137,7 +174,6 @@ const create = async (req, res) => { return response.failed(res, 400, `Lokasi di luar area kantor (${distance.toFixed(2)} meter)`); } - let finalPhotoUrl = null; if (req.file) { diff --git a/models/branch.model.js b/models/branch.model.js index c8231e8..7b28a74 100644 --- a/models/branch.model.js +++ b/models/branch.model.js @@ -31,6 +31,11 @@ module.exports = (sequelize) => { type: DataTypes.DECIMAL(20, 15), allowNull: false, }, + lunch_attendance: { + type: DataTypes.BOOLEAN, + defaultValue: false, + allowNull: true + }, created_at: { type: DataTypes.DATE,