updated absensi

This commit is contained in:
2025-10-15 15:25:11 +07:00
parent 96d206d892
commit 9389edf24d
5 changed files with 108 additions and 15 deletions

View File

@@ -6,6 +6,10 @@ const history = async (req, res) => {
return response;
};
const getAll = async (req, res) => {
const response = await services.getAll(req, res)
}
const create = async (req, res) => {
const response = await services.create(req, res);
return response;
@@ -26,10 +30,17 @@ const destroy = async (req, res) => {
return response;
};
const checkLocation = async (req, res) => {
const response = await services.checkLocation(req, res)
return response
}
module.exports = {
create,
history,
update,
destroy,
clockOut
clockOut,
getAll,
checkLocation
}

View File

@@ -9,10 +9,18 @@ router.get('/history', apiKey, jwt, (req, res) => {
controller.history(req, res);
})
router.get('/', apiKey, (req, res) => {
controller.getAll(req, res)
})
router.post('/', jwt, apiKey, upload.single('attendances'), (req, res) => {
controller.create(req, res)
})
router.get('/check-location', apiKey, jwt, (req, res) => {
controller.checkLocation(req, res)
})
router.post('/clock-out', jwt, apiKey, (req, res) => {
controller.clockOut(req, res)
})

View File

@@ -7,8 +7,6 @@ const moment = require('moment-timezone')
const path = require("path");
const fs = require("fs");
const axios = require("axios");
const User = db.User
const Attedances = db.Attedances
const Branch = db.Branch
@@ -90,6 +88,7 @@ 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) {
@@ -112,8 +111,6 @@ const create = async (req, res) => {
finalPhotoUrl = filePath.replace("public", "").replace(/\\/g, "/");
}
// === Absen masuk ===
attendance = await Attedances.create({
user_id,
@@ -130,6 +127,7 @@ const create = async (req, res) => {
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: attendance.clock_out
? moment(attendance.clock_out).tz('Asia/Jakarta').format('YYYY-MM-DD HH:mm:ss')
@@ -165,6 +163,7 @@ const clockOut = async (req, res) => {
await t.rollback();
return response.failed(res, 400, 'Sudah absen pulang hari ini');
}
const branch = await Branch.findOne({ where: { id: user.branch_id } });
// Set jam pulang (tanpa cek lokasi)
attendance.clock_out = now.toDate();
@@ -180,6 +179,7 @@ const clockOut = async (req, res) => {
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,
@@ -246,7 +246,31 @@ const history = async (req, res) => {
}
};
const getAll = async (req, res) => {
try {
const today = moment().tz('Asia/Jakarta').format('YYYY-MM-DD');
const attendances = await Attedances.findAll({
where: {
date: today
},
include: [
{
model: User,
as: 'user',
attributes: ['id', 'name', 'email']
}
],
order: [['created_at', 'DESC']]
});
return response.success(res, attendances, 'List kehadiran hari ini');
} catch (error) {
console.error(error);
return response.error(res, 'Gagal mengambil data absensi hari ini');
}
};
const update = async (req, res) => {
const t = await sequelize.transaction();
@@ -255,18 +279,18 @@ const update = async (req, res) => {
const user_id = req.user.id;
const body = req.body;
const categories = await Category.findOne({
const attedances = await Attedances.findOne({
where: { id },
transaction: t
});
const categoriesUpdate = await categories.update({
const attedancesUpdate = await attedances.update({
...body,
user_id,
}, { transaction: t });
await t.commit();
return response.success(res, categoriesUpdate, 'Category Berhasil Di update');
return response.success(res, attedancesUpdate, 'Category Berhasil Di update');
} catch (error) {
await t.rollback();
errorHandler(error, req, res);
@@ -278,20 +302,20 @@ const destroy = async (req, res) => {
const t = await sequelize.transaction();
try {
const id = req.params.id;
const category = await Category.findOne({
const attendance = await Attedances.findOne({
where: { id },
transaction: t,
});
if (!category) {
if (!attendance) {
await t.rollback();
return response.failed(res, 404, 'Category tidak ditemukan');
return response.failed(res, 404, 'Attendance tidak ditemukan');
}
await category.destroy({ transaction: t });
await attendance.destroy({ transaction: t });
await t.commit();
return response.success(res, null, 'Category berhasil dihapus');
return response.success(res, null, 'Attendance berhasil dihapus');
} catch (error) {
await t.rollback();
errorHandler(error, req, res);
@@ -299,11 +323,61 @@ const destroy = async (req, res) => {
}
};
const checkLocation = async (req, res) => {
try {
const user_id = req.user.id;
const { lat, lng } = req.query;
if (!lat || !lng) {
return response.failed(res, 400, 'Latitude dan longitude wajib dikirim');
}
const user = await User.findOne({ where: { id: user_id } });
if (!user) return response.failed(res, 404, 'User tidak ditemukan');
const branch = await Branch.findOne({ where: { id: user.branch_id } });
if (!branch) return response.failed(res, 404, 'Data kantor tidak ditemukan');
// Hitung jarak user dengan kantor (dalam meter)
const distanceMeters = getDistance(branch.lat, branch.lng, lat, lng);
// Otomatis ubah ke km jika lebih dari 1000 meter
const isKm = distanceMeters >= 1000;
const distance = isKm ? distanceMeters / 1000 : distanceMeters;
const unit = isKm ? 'km' : 'm';
// Radius tetap pakai meter (biar konsisten)
const allowedRadius = parseFloat(process.env.ABSENCE_RADIUS) || 100;
if (distanceMeters <= allowedRadius) {
return response.success(res, {
inOffice: true,
branch_name: branch.name,
distance: distance.toFixed(2),
unit,
message: `Anda sedang berada di lokasi ${branch.name}, silakan absen.`,
});
}
return response.success(res, {
inOffice: false,
branch_name: branch.name,
distance: distance.toFixed(2),
unit,
message: `Anda berada di luar area kantor ${distance.toFixed(2)} ${unit} dari ${branch.name}.`,
});
} catch (error) {
errorHandler(error, req, res);
return response.failed(res, 500, error.message);
}
};
module.exports = {
create,
destroy,
history,
update,
clockOut
clockOut,
getAll,
checkLocation
}