237 lines
7.0 KiB
JavaScript
237 lines
7.0 KiB
JavaScript
// models/odooService.js
|
|
import axios from "axios";
|
|
import { odooConfig } from "../config/odooConfig.js";
|
|
import { toOdooDatetimeFormat } from "../utils/date.js"; // Adjust path if needed
|
|
|
|
const JSON_RPC_URL = `${odooConfig.url}/jsonrpc`;
|
|
|
|
export const authenticate = async () => {
|
|
const payload = {
|
|
jsonrpc: "2.0",
|
|
method: "call",
|
|
params: {
|
|
service: "common",
|
|
method: "login",
|
|
args: [odooConfig.db, odooConfig.email, odooConfig.apiKey],
|
|
},
|
|
id: 1,
|
|
};
|
|
|
|
const { data } = await axios.post(JSON_RPC_URL, payload);
|
|
return data.result;
|
|
};
|
|
|
|
export const fetchEmployees = async () => {
|
|
const uid = await authenticate();
|
|
|
|
const payload = {
|
|
jsonrpc: "2.0",
|
|
method: "call",
|
|
params: {
|
|
service: "object",
|
|
method: "execute_kw",
|
|
args: [
|
|
odooConfig.db,
|
|
uid,
|
|
odooConfig.apiKey,
|
|
"hr.employee",
|
|
"search_read",
|
|
[],
|
|
{ fields: ["id", "name", "work_email"], limit: 10 },
|
|
],
|
|
},
|
|
id: 2,
|
|
};
|
|
|
|
const { data } = await axios.post(JSON_RPC_URL, payload);
|
|
return data.result;
|
|
};
|
|
|
|
export const checkEmployeeExists = async (employee_id) => {
|
|
const uid = await authenticate();
|
|
|
|
const payload = {
|
|
jsonrpc: "2.0",
|
|
method: "call",
|
|
params: {
|
|
service: "object",
|
|
method: "execute_kw",
|
|
args: [
|
|
odooConfig.db,
|
|
uid,
|
|
odooConfig.apiKey,
|
|
"hr.employee",
|
|
"search",
|
|
[[["id", "=", employee_id]]],
|
|
0,
|
|
],
|
|
},
|
|
id: 10,
|
|
};
|
|
|
|
const res = await axios.post(JSON_RPC_URL, payload);
|
|
return res.data.result && res.data.result.length > 0;
|
|
};
|
|
|
|
/**
|
|
* Toggles attendance check-in/check-out for an employee
|
|
* @param {number} employee_id
|
|
* @returns {object} status and attendance record info
|
|
*/
|
|
export const toggleEmployeeAttendance = async (employee_id) => {
|
|
try {
|
|
const uid = await authenticate();
|
|
|
|
if (!uid) {
|
|
throw new Error("Authentication failed: no user ID returned.");
|
|
}
|
|
|
|
// Optional: Verify employee exists
|
|
const checkEmployeePayload = {
|
|
jsonrpc: "2.0",
|
|
method: "call",
|
|
params: {
|
|
service: "object",
|
|
method: "execute_kw",
|
|
args: [
|
|
odooConfig.db,
|
|
uid,
|
|
odooConfig.apiKey,
|
|
"hr.employee",
|
|
"search",
|
|
[[["id", "=", employee_id]]],
|
|
],
|
|
},
|
|
id: 0,
|
|
};
|
|
const empRes = await axios.post(JSON_RPC_URL, checkEmployeePayload);
|
|
if (!empRes.data.result || empRes.data.result.length === 0) {
|
|
throw new Error(`Employee with ID ${employee_id} not found.`);
|
|
}
|
|
|
|
// Step 1: Search for open attendance record (check_out = false)
|
|
const searchPayload = {
|
|
jsonrpc: "2.0",
|
|
method: "call",
|
|
params: {
|
|
service: "object",
|
|
method: "execute_kw",
|
|
args: [
|
|
odooConfig.db,
|
|
uid,
|
|
odooConfig.apiKey,
|
|
"hr.attendance",
|
|
"search_read",
|
|
[
|
|
[
|
|
["employee_id", "=", employee_id],
|
|
["check_out", "=", false],
|
|
],
|
|
],
|
|
{ fields: ["id", "check_in"], limit: 1 },
|
|
],
|
|
},
|
|
id: 3,
|
|
};
|
|
|
|
const searchRes = await axios.post(JSON_RPC_URL, searchPayload);
|
|
const openRecords = searchRes.data.result;
|
|
|
|
if (openRecords.length > 0) {
|
|
// Step 2: Write check_out datetime
|
|
const attendanceId = openRecords[0].id;
|
|
const now = toOdooDatetimeFormat(new Date());
|
|
|
|
const writePayload = {
|
|
jsonrpc: "2.0",
|
|
method: "call",
|
|
params: {
|
|
service: "object",
|
|
method: "execute_kw",
|
|
args: [
|
|
odooConfig.db,
|
|
uid,
|
|
odooConfig.apiKey,
|
|
"hr.attendance",
|
|
"write",
|
|
[[attendanceId], { check_out: now }],
|
|
],
|
|
},
|
|
id: 4,
|
|
};
|
|
|
|
const writeRes = await axios.post(JSON_RPC_URL, writePayload);
|
|
|
|
if (!writeRes.data.result) {
|
|
throw new Error("Failed to write check_out datetime.");
|
|
}
|
|
|
|
return {
|
|
status: "Checked out",
|
|
attendance_id: attendanceId,
|
|
check_out: now,
|
|
odoo_response: writeRes.data,
|
|
};
|
|
} else {
|
|
// Step 3: Create new attendance record with check_in
|
|
const now = toOdooDatetimeFormat(new Date());
|
|
|
|
const createPayload = {
|
|
jsonrpc: "2.0",
|
|
method: "call",
|
|
params: {
|
|
service: "object",
|
|
method: "execute_kw",
|
|
args: [
|
|
odooConfig.db,
|
|
uid,
|
|
odooConfig.apiKey,
|
|
"hr.attendance",
|
|
"create",
|
|
[{ employee_id, check_in: now }],
|
|
],
|
|
},
|
|
id: 5,
|
|
};
|
|
|
|
const createRes = await axios.post(JSON_RPC_URL, createPayload);
|
|
|
|
// DEBUG LOGGING - print entire response from Odoo
|
|
console.log(
|
|
"Create attendance response from Odoo:",
|
|
JSON.stringify(createRes.data, null, 2)
|
|
);
|
|
|
|
if (createRes.data.error) {
|
|
// Odoo returned an error object - log it and throw
|
|
console.error(
|
|
"Odoo error during attendance creation:",
|
|
createRes.data.error
|
|
);
|
|
throw new Error(
|
|
createRes.data.error.message ||
|
|
"Unknown Odoo error during attendance creation"
|
|
);
|
|
}
|
|
|
|
if (!createRes.data.result) {
|
|
throw new Error(
|
|
"Failed to create attendance record - no result returned."
|
|
);
|
|
}
|
|
|
|
const attendanceId = createRes.data.result;
|
|
|
|
return {
|
|
status: "Checked in",
|
|
attendance_id: attendanceId,
|
|
check_in: now,
|
|
odoo_response: createRes.data,
|
|
};
|
|
}
|
|
} catch (error) {
|
|
console.error("toggleEmployeeAttendance error:", error);
|
|
throw error;
|
|
}
|
|
};
|