// 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; } };