@marcfargas/odoo-client 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/client/odoo-client.d.ts +39 -0
- package/dist/client/odoo-client.d.ts.map +1 -1
- package/dist/client/odoo-client.js +43 -0
- package/dist/client/odoo-client.js.map +1 -1
- package/dist/services/attendance/attendance-service.d.ts +100 -0
- package/dist/services/attendance/attendance-service.d.ts.map +1 -0
- package/dist/services/attendance/attendance-service.js +113 -0
- package/dist/services/attendance/attendance-service.js.map +1 -0
- package/dist/services/attendance/functions.d.ts +72 -0
- package/dist/services/attendance/functions.d.ts.map +1 -0
- package/dist/services/attendance/functions.js +169 -0
- package/dist/services/attendance/functions.js.map +1 -0
- package/dist/services/attendance/index.d.ts +4 -0
- package/dist/services/attendance/index.d.ts.map +1 -0
- package/dist/services/attendance/index.js +12 -0
- package/dist/services/attendance/index.js.map +1 -0
- package/dist/services/attendance/types.d.ts +53 -0
- package/dist/services/attendance/types.d.ts.map +1 -0
- package/dist/services/attendance/types.js +8 -0
- package/dist/services/attendance/types.js.map +1 -0
- package/dist/services/index.d.ts +2 -0
- package/dist/services/index.d.ts.map +1 -1
- package/dist/services/index.js +2 -0
- package/dist/services/index.js.map +1 -1
- package/dist/services/timesheets/functions.d.ts +75 -0
- package/dist/services/timesheets/functions.d.ts.map +1 -0
- package/dist/services/timesheets/functions.js +220 -0
- package/dist/services/timesheets/functions.js.map +1 -0
- package/dist/services/timesheets/index.d.ts +4 -0
- package/dist/services/timesheets/index.d.ts.map +1 -0
- package/dist/services/timesheets/index.js +12 -0
- package/dist/services/timesheets/index.js.map +1 -0
- package/dist/services/timesheets/timesheets-service.d.ts +121 -0
- package/dist/services/timesheets/timesheets-service.d.ts.map +1 -0
- package/dist/services/timesheets/timesheets-service.js +136 -0
- package/dist/services/timesheets/timesheets-service.js.map +1 -0
- package/dist/services/timesheets/types.d.ts +81 -0
- package/dist/services/timesheets/types.d.ts.map +1 -0
- package/dist/services/timesheets/types.js +10 -0
- package/dist/services/timesheets/types.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Types for hr.attendance service.
|
|
3
|
+
*
|
|
4
|
+
* @see https://github.com/odoo/odoo/blob/17.0/addons/hr_attendance/models/hr_attendance.py
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Raw hr.attendance record as returned by Odoo read/search_read.
|
|
8
|
+
*
|
|
9
|
+
* Key fields:
|
|
10
|
+
* - check_in: always set when record exists
|
|
11
|
+
* - check_out: null/false when the employee is still checked in
|
|
12
|
+
* - worked_hours: computed from check_in/check_out (0 when still checked in)
|
|
13
|
+
*/
|
|
14
|
+
export interface AttendanceRecord {
|
|
15
|
+
id: number;
|
|
16
|
+
/** Many2one → hr.employee: [id, display_name] */
|
|
17
|
+
employee_id: [number, string] | false;
|
|
18
|
+
/** Datetime string (UTC): when the employee checked in */
|
|
19
|
+
check_in: string;
|
|
20
|
+
/** Datetime string (UTC) or false: when the employee checked out */
|
|
21
|
+
check_out: string | false;
|
|
22
|
+
/** Computed: hours worked (check_out - check_in), 0 if still checked in */
|
|
23
|
+
worked_hours: number;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Options for listing attendance records.
|
|
27
|
+
*/
|
|
28
|
+
export interface AttendanceListOptions {
|
|
29
|
+
/** Filter by employee ID */
|
|
30
|
+
employeeId?: number;
|
|
31
|
+
/** Start date (inclusive, YYYY-MM-DD) */
|
|
32
|
+
dateFrom?: string;
|
|
33
|
+
/** End date (inclusive, YYYY-MM-DD) */
|
|
34
|
+
dateTo?: string;
|
|
35
|
+
/** Max records to return */
|
|
36
|
+
limit?: number;
|
|
37
|
+
/** Offset for pagination */
|
|
38
|
+
offset?: number;
|
|
39
|
+
/** Sort order (default: 'check_in desc') */
|
|
40
|
+
order?: string;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Attendance status for an employee.
|
|
44
|
+
*/
|
|
45
|
+
export interface AttendanceStatus {
|
|
46
|
+
/** Whether the employee is currently checked in */
|
|
47
|
+
checkedIn: boolean;
|
|
48
|
+
/** The current (open) attendance record, or null if checked out */
|
|
49
|
+
currentAttendance: AttendanceRecord | null;
|
|
50
|
+
/** Employee info: [id, display_name] */
|
|
51
|
+
employee: [number, string];
|
|
52
|
+
}
|
|
53
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/services/attendance/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;;;;;;GAOG;AACH,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,MAAM,CAAC;IACX,iDAAiD;IACjD,WAAW,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,KAAK,CAAC;IACtC,0DAA0D;IAC1D,QAAQ,EAAE,MAAM,CAAC;IACjB,oEAAoE;IACpE,SAAS,EAAE,MAAM,GAAG,KAAK,CAAC;IAC1B,2EAA2E;IAC3E,YAAY,EAAE,MAAM,CAAC;CACtB;AAED;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC,4BAA4B;IAC5B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,yCAAyC;IACzC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,uCAAuC;IACvC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,4BAA4B;IAC5B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,4BAA4B;IAC5B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,4CAA4C;IAC5C,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,mDAAmD;IACnD,SAAS,EAAE,OAAO,CAAC;IACnB,mEAAmE;IACnE,iBAAiB,EAAE,gBAAgB,GAAG,IAAI,CAAC;IAC3C,wCAAwC;IACxC,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC5B"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/services/attendance/types.ts"],"names":[],"mappings":";AAAA;;;;GAIG"}
|
package/dist/services/index.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/services/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,cAAc,QAAQ,CAAC;AACvB,cAAc,WAAW,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/services/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,cAAc,QAAQ,CAAC;AACvB,cAAc,WAAW,CAAC;AAC1B,cAAc,cAAc,CAAC;AAC7B,cAAc,cAAc,CAAC"}
|
package/dist/services/index.js
CHANGED
|
@@ -35,4 +35,6 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
36
|
__exportStar(require("./mail"), exports);
|
|
37
37
|
__exportStar(require("./modules"), exports);
|
|
38
|
+
__exportStar(require("./attendance"), exports);
|
|
39
|
+
__exportStar(require("./timesheets"), exports);
|
|
38
40
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/services/index.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;GAkBG;;;;;;;;;;;;;;;;AAEH,yCAAuB;AACvB,4CAA0B"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/services/index.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;GAkBG;;;;;;;;;;;;;;;;AAEH,yCAAuB;AACvB,4CAA0B;AAC1B,+CAA6B;AAC7B,+CAA6B"}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Timesheet standalone functions — timer start/stop and time logging.
|
|
3
|
+
*
|
|
4
|
+
* Timer concept in Odoo timesheets is simple:
|
|
5
|
+
* - A running clock = account.analytic.line with unit_amount = 0 (no duration)
|
|
6
|
+
* - A stopped clock = account.analytic.line with unit_amount > 0 (duration filled)
|
|
7
|
+
*
|
|
8
|
+
* This is standard hr_timesheet behavior. The OCA module
|
|
9
|
+
* `project_timesheet_time_control` adds UI buttons for this workflow,
|
|
10
|
+
* but the data model needs nothing beyond the base module.
|
|
11
|
+
*
|
|
12
|
+
* We use create_date to compute elapsed time when stopping a timer.
|
|
13
|
+
*
|
|
14
|
+
* @see https://github.com/odoo/odoo/blob/17.0/addons/hr_timesheet/models/account_analytic_line.py
|
|
15
|
+
* @see https://github.com/OCA/project/tree/17.0/project_timesheet_time_control
|
|
16
|
+
*/
|
|
17
|
+
import type { OdooClient } from '../../client/odoo-client';
|
|
18
|
+
import type { TimesheetEntry, TimerStartOptions, LogTimeOptions, TimesheetListOptions } from './types';
|
|
19
|
+
/**
|
|
20
|
+
* Start a timesheet timer — creates a line with no duration.
|
|
21
|
+
*
|
|
22
|
+
* An entry with unit_amount = 0 represents a running clock.
|
|
23
|
+
* Call stopTimer() to compute elapsed time and fill in the duration.
|
|
24
|
+
*
|
|
25
|
+
* @param client - Authenticated OdooClient
|
|
26
|
+
* @param options - Timer options (description, projectId, optional taskId/employeeId)
|
|
27
|
+
* @returns The created timesheet entry (unit_amount = 0)
|
|
28
|
+
*
|
|
29
|
+
* @throws OdooValidationError if description or projectId missing
|
|
30
|
+
*/
|
|
31
|
+
export declare function startTimer(client: OdooClient, options: TimerStartOptions): Promise<TimesheetEntry>;
|
|
32
|
+
/**
|
|
33
|
+
* Stop a running timesheet timer.
|
|
34
|
+
*
|
|
35
|
+
* Computes elapsed time from create_date to now and writes unit_amount.
|
|
36
|
+
* After this call, the entry has unit_amount > 0 (closed).
|
|
37
|
+
*
|
|
38
|
+
* @param client - Authenticated OdooClient
|
|
39
|
+
* @param timesheetId - ID of the timesheet entry to stop (must have unit_amount = 0)
|
|
40
|
+
* @returns The updated timesheet entry with duration filled in
|
|
41
|
+
*
|
|
42
|
+
* @throws OdooValidationError if the entry already has a duration
|
|
43
|
+
*/
|
|
44
|
+
export declare function stopTimer(client: OdooClient, timesheetId: number): Promise<TimesheetEntry>;
|
|
45
|
+
/**
|
|
46
|
+
* Find running timers for an employee.
|
|
47
|
+
*
|
|
48
|
+
* Running timers are timesheet entries with unit_amount = 0.
|
|
49
|
+
*
|
|
50
|
+
* @param client - Authenticated OdooClient
|
|
51
|
+
* @param employeeId - Employee ID (omit for current user's employee)
|
|
52
|
+
* @returns Array of timesheet entries with unit_amount = 0
|
|
53
|
+
*/
|
|
54
|
+
export declare function getRunningTimers(client: OdooClient, employeeId?: number): Promise<TimesheetEntry[]>;
|
|
55
|
+
/**
|
|
56
|
+
* Log a completed timesheet entry (no timer, just hours).
|
|
57
|
+
*
|
|
58
|
+
* Creates an account.analytic.line with unit_amount already set.
|
|
59
|
+
*
|
|
60
|
+
* @param client - Authenticated OdooClient
|
|
61
|
+
* @param options - Time log options
|
|
62
|
+
* @returns The created timesheet entry
|
|
63
|
+
*
|
|
64
|
+
* @throws OdooValidationError if required fields missing or hours <= 0
|
|
65
|
+
*/
|
|
66
|
+
export declare function logTime(client: OdooClient, options: LogTimeOptions): Promise<TimesheetEntry>;
|
|
67
|
+
/**
|
|
68
|
+
* List timesheet entries with optional filters.
|
|
69
|
+
*
|
|
70
|
+
* @param client - Authenticated OdooClient
|
|
71
|
+
* @param options - Filter and pagination options
|
|
72
|
+
* @returns Array of timesheet entries
|
|
73
|
+
*/
|
|
74
|
+
export declare function listTimesheets(client: OdooClient, options?: TimesheetListOptions): Promise<TimesheetEntry[]>;
|
|
75
|
+
//# sourceMappingURL=functions.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"functions.d.ts","sourceRoot":"","sources":["../../../src/services/timesheets/functions.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAGH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAG3D,OAAO,KAAK,EACV,cAAc,EACd,iBAAiB,EACjB,cAAc,EACd,oBAAoB,EACrB,MAAM,SAAS,CAAC;AAsBjB;;;;;;;;;;;GAWG;AACH,wBAAsB,UAAU,CAC9B,MAAM,EAAE,UAAU,EAClB,OAAO,EAAE,iBAAiB,GACzB,OAAO,CAAC,cAAc,CAAC,CAiCzB;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,SAAS,CAAC,MAAM,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC,CA2ChG;AAED;;;;;;;;GAQG;AACH,wBAAsB,gBAAgB,CACpC,MAAM,EAAE,UAAU,EAClB,UAAU,CAAC,EAAE,MAAM,GAClB,OAAO,CAAC,cAAc,EAAE,CAAC,CAgB3B;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,OAAO,CAC3B,MAAM,EAAE,UAAU,EAClB,OAAO,EAAE,cAAc,GACtB,OAAO,CAAC,cAAc,CAAC,CAkCzB;AAED;;;;;;GAMG;AACH,wBAAsB,cAAc,CAClC,MAAM,EAAE,UAAU,EAClB,OAAO,GAAE,oBAAyB,GACjC,OAAO,CAAC,cAAc,EAAE,CAAC,CAmC3B"}
|
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Timesheet standalone functions — timer start/stop and time logging.
|
|
4
|
+
*
|
|
5
|
+
* Timer concept in Odoo timesheets is simple:
|
|
6
|
+
* - A running clock = account.analytic.line with unit_amount = 0 (no duration)
|
|
7
|
+
* - A stopped clock = account.analytic.line with unit_amount > 0 (duration filled)
|
|
8
|
+
*
|
|
9
|
+
* This is standard hr_timesheet behavior. The OCA module
|
|
10
|
+
* `project_timesheet_time_control` adds UI buttons for this workflow,
|
|
11
|
+
* but the data model needs nothing beyond the base module.
|
|
12
|
+
*
|
|
13
|
+
* We use create_date to compute elapsed time when stopping a timer.
|
|
14
|
+
*
|
|
15
|
+
* @see https://github.com/odoo/odoo/blob/17.0/addons/hr_timesheet/models/account_analytic_line.py
|
|
16
|
+
* @see https://github.com/OCA/project/tree/17.0/project_timesheet_time_control
|
|
17
|
+
*/
|
|
18
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
19
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
20
|
+
};
|
|
21
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
22
|
+
exports.startTimer = startTimer;
|
|
23
|
+
exports.stopTimer = stopTimer;
|
|
24
|
+
exports.getRunningTimers = getRunningTimers;
|
|
25
|
+
exports.logTime = logTime;
|
|
26
|
+
exports.listTimesheets = listTimesheets;
|
|
27
|
+
const debug_1 = __importDefault(require("debug"));
|
|
28
|
+
const errors_1 = require("../../types/errors");
|
|
29
|
+
const functions_1 = require("../attendance/functions");
|
|
30
|
+
const log = (0, debug_1.default)('odoo-client:timesheets');
|
|
31
|
+
/** Fields we always fetch for timesheet entries. */
|
|
32
|
+
const TIMESHEET_FIELDS = [
|
|
33
|
+
'name',
|
|
34
|
+
'date',
|
|
35
|
+
'unit_amount',
|
|
36
|
+
'project_id',
|
|
37
|
+
'task_id',
|
|
38
|
+
'employee_id',
|
|
39
|
+
'create_date',
|
|
40
|
+
];
|
|
41
|
+
/**
|
|
42
|
+
* Get the current date as YYYY-MM-DD.
|
|
43
|
+
*/
|
|
44
|
+
function today() {
|
|
45
|
+
return new Date().toISOString().split('T')[0];
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Start a timesheet timer — creates a line with no duration.
|
|
49
|
+
*
|
|
50
|
+
* An entry with unit_amount = 0 represents a running clock.
|
|
51
|
+
* Call stopTimer() to compute elapsed time and fill in the duration.
|
|
52
|
+
*
|
|
53
|
+
* @param client - Authenticated OdooClient
|
|
54
|
+
* @param options - Timer options (description, projectId, optional taskId/employeeId)
|
|
55
|
+
* @returns The created timesheet entry (unit_amount = 0)
|
|
56
|
+
*
|
|
57
|
+
* @throws OdooValidationError if description or projectId missing
|
|
58
|
+
*/
|
|
59
|
+
async function startTimer(client, options) {
|
|
60
|
+
if (!options.description?.trim()) {
|
|
61
|
+
throw new errors_1.OdooValidationError('Timesheet description is required. Describe the work being done.');
|
|
62
|
+
}
|
|
63
|
+
if (!options.projectId) {
|
|
64
|
+
throw new errors_1.OdooValidationError('Project ID is required for timesheet entries. ' +
|
|
65
|
+
'The project must have allow_timesheets = true.');
|
|
66
|
+
}
|
|
67
|
+
const empId = await (0, functions_1.resolveEmployeeId)(client, options.employeeId);
|
|
68
|
+
log('Starting timer for employee %d on project %d', empId, options.projectId);
|
|
69
|
+
const values = {
|
|
70
|
+
name: options.description.trim(),
|
|
71
|
+
project_id: options.projectId,
|
|
72
|
+
employee_id: empId,
|
|
73
|
+
unit_amount: 0,
|
|
74
|
+
date: today(),
|
|
75
|
+
};
|
|
76
|
+
if (options.taskId) {
|
|
77
|
+
values.task_id = options.taskId;
|
|
78
|
+
}
|
|
79
|
+
const id = await client.create('account.analytic.line', values);
|
|
80
|
+
log('Created timesheet entry %d with unit_amount=0 (running)', id);
|
|
81
|
+
const [entry] = await client.read('account.analytic.line', id, TIMESHEET_FIELDS);
|
|
82
|
+
return entry;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Stop a running timesheet timer.
|
|
86
|
+
*
|
|
87
|
+
* Computes elapsed time from create_date to now and writes unit_amount.
|
|
88
|
+
* After this call, the entry has unit_amount > 0 (closed).
|
|
89
|
+
*
|
|
90
|
+
* @param client - Authenticated OdooClient
|
|
91
|
+
* @param timesheetId - ID of the timesheet entry to stop (must have unit_amount = 0)
|
|
92
|
+
* @returns The updated timesheet entry with duration filled in
|
|
93
|
+
*
|
|
94
|
+
* @throws OdooValidationError if the entry already has a duration
|
|
95
|
+
*/
|
|
96
|
+
async function stopTimer(client, timesheetId) {
|
|
97
|
+
log('Stopping timer on entry %d', timesheetId);
|
|
98
|
+
const [entry] = await client.read('account.analytic.line', timesheetId, TIMESHEET_FIELDS);
|
|
99
|
+
if (entry.unit_amount !== 0) {
|
|
100
|
+
throw new errors_1.OdooValidationError(`Timesheet entry ${timesheetId} is not a running timer ` +
|
|
101
|
+
`(unit_amount = ${entry.unit_amount}). ` +
|
|
102
|
+
'Only entries with unit_amount = 0 can be stopped.');
|
|
103
|
+
}
|
|
104
|
+
// Compute elapsed time from create_date
|
|
105
|
+
const createDate = entry.create_date;
|
|
106
|
+
if (!createDate) {
|
|
107
|
+
throw new errors_1.OdooValidationError(`Cannot determine start time for entry ${timesheetId}: create_date not available.`);
|
|
108
|
+
}
|
|
109
|
+
const startMs = new Date(createDate.replace(' ', 'T') + 'Z').getTime();
|
|
110
|
+
const nowMs = Date.now();
|
|
111
|
+
const elapsedHours = Math.max(0, (nowMs - startMs) / (1000 * 60 * 60));
|
|
112
|
+
// Round to 2 decimal places, minimum 0.01 (36s) to avoid staying at 0 (= "running")
|
|
113
|
+
const roundedHours = Math.max(0.01, Math.round(elapsedHours * 100) / 100);
|
|
114
|
+
await client.write('account.analytic.line', timesheetId, {
|
|
115
|
+
unit_amount: roundedHours,
|
|
116
|
+
});
|
|
117
|
+
log('Timer stopped on entry %d: %.2f hours (from %s)', timesheetId, roundedHours, createDate);
|
|
118
|
+
const [updated] = await client.read('account.analytic.line', timesheetId, TIMESHEET_FIELDS);
|
|
119
|
+
return updated;
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Find running timers for an employee.
|
|
123
|
+
*
|
|
124
|
+
* Running timers are timesheet entries with unit_amount = 0.
|
|
125
|
+
*
|
|
126
|
+
* @param client - Authenticated OdooClient
|
|
127
|
+
* @param employeeId - Employee ID (omit for current user's employee)
|
|
128
|
+
* @returns Array of timesheet entries with unit_amount = 0
|
|
129
|
+
*/
|
|
130
|
+
async function getRunningTimers(client, employeeId) {
|
|
131
|
+
const empId = await (0, functions_1.resolveEmployeeId)(client, employeeId);
|
|
132
|
+
log('Looking for running timers for employee %d', empId);
|
|
133
|
+
return client.searchRead('account.analytic.line', [
|
|
134
|
+
['employee_id', '=', empId],
|
|
135
|
+
['unit_amount', '=', 0],
|
|
136
|
+
['project_id', '!=', false],
|
|
137
|
+
], {
|
|
138
|
+
fields: TIMESHEET_FIELDS,
|
|
139
|
+
order: 'create_date desc',
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Log a completed timesheet entry (no timer, just hours).
|
|
144
|
+
*
|
|
145
|
+
* Creates an account.analytic.line with unit_amount already set.
|
|
146
|
+
*
|
|
147
|
+
* @param client - Authenticated OdooClient
|
|
148
|
+
* @param options - Time log options
|
|
149
|
+
* @returns The created timesheet entry
|
|
150
|
+
*
|
|
151
|
+
* @throws OdooValidationError if required fields missing or hours <= 0
|
|
152
|
+
*/
|
|
153
|
+
async function logTime(client, options) {
|
|
154
|
+
if (!options.description?.trim()) {
|
|
155
|
+
throw new errors_1.OdooValidationError('Timesheet description is required. Describe the work done.');
|
|
156
|
+
}
|
|
157
|
+
if (!options.projectId) {
|
|
158
|
+
throw new errors_1.OdooValidationError('Project ID is required for timesheet entries.');
|
|
159
|
+
}
|
|
160
|
+
if (!options.hours || options.hours <= 0) {
|
|
161
|
+
throw new errors_1.OdooValidationError(`Hours must be greater than 0 (got: ${options.hours}). ` +
|
|
162
|
+
'Use startTimer() for entries where duration is unknown.');
|
|
163
|
+
}
|
|
164
|
+
const empId = await (0, functions_1.resolveEmployeeId)(client, options.employeeId);
|
|
165
|
+
log('Logging %f hours for employee %d on project %d', options.hours, empId, options.projectId);
|
|
166
|
+
const values = {
|
|
167
|
+
name: options.description.trim(),
|
|
168
|
+
project_id: options.projectId,
|
|
169
|
+
employee_id: empId,
|
|
170
|
+
unit_amount: options.hours,
|
|
171
|
+
date: options.date ?? today(),
|
|
172
|
+
};
|
|
173
|
+
if (options.taskId) {
|
|
174
|
+
values.task_id = options.taskId;
|
|
175
|
+
}
|
|
176
|
+
const id = await client.create('account.analytic.line', values);
|
|
177
|
+
log('Logged timesheet entry %d: %f hours', id, options.hours);
|
|
178
|
+
const [entry] = await client.read('account.analytic.line', id, TIMESHEET_FIELDS);
|
|
179
|
+
return entry;
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* List timesheet entries with optional filters.
|
|
183
|
+
*
|
|
184
|
+
* @param client - Authenticated OdooClient
|
|
185
|
+
* @param options - Filter and pagination options
|
|
186
|
+
* @returns Array of timesheet entries
|
|
187
|
+
*/
|
|
188
|
+
async function listTimesheets(client, options = {}) {
|
|
189
|
+
const domain = [];
|
|
190
|
+
if (options.employeeId) {
|
|
191
|
+
domain.push(['employee_id', '=', options.employeeId]);
|
|
192
|
+
}
|
|
193
|
+
if (options.projectId) {
|
|
194
|
+
domain.push(['project_id', '=', options.projectId]);
|
|
195
|
+
}
|
|
196
|
+
if (options.taskId) {
|
|
197
|
+
domain.push(['task_id', '=', options.taskId]);
|
|
198
|
+
}
|
|
199
|
+
if (options.dateFrom) {
|
|
200
|
+
domain.push(['date', '>=', options.dateFrom]);
|
|
201
|
+
}
|
|
202
|
+
if (options.dateTo) {
|
|
203
|
+
domain.push(['date', '<=', options.dateTo]);
|
|
204
|
+
}
|
|
205
|
+
if (options.runningOnly) {
|
|
206
|
+
domain.push(['unit_amount', '=', 0]);
|
|
207
|
+
}
|
|
208
|
+
// Ensure we only get timesheet lines (not generic analytic lines)
|
|
209
|
+
if (!options.projectId) {
|
|
210
|
+
domain.push(['project_id', '!=', false]);
|
|
211
|
+
}
|
|
212
|
+
log('Listing timesheets with domain: %o', domain);
|
|
213
|
+
return client.searchRead('account.analytic.line', domain, {
|
|
214
|
+
fields: TIMESHEET_FIELDS,
|
|
215
|
+
limit: options.limit,
|
|
216
|
+
offset: options.offset,
|
|
217
|
+
order: options.order ?? 'date desc, id desc',
|
|
218
|
+
});
|
|
219
|
+
}
|
|
220
|
+
//# sourceMappingURL=functions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"functions.js","sourceRoot":"","sources":["../../../src/services/timesheets/functions.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export { TimesheetsService } from './timesheets-service';
|
|
2
|
+
export { startTimer, stopTimer, getRunningTimers, logTime, listTimesheets } from './functions';
|
|
3
|
+
export type { TimesheetEntry, TimerStartOptions, LogTimeOptions, TimesheetListOptions, } from './types';
|
|
4
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/services/timesheets/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AACzD,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,gBAAgB,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC/F,YAAY,EACV,cAAc,EACd,iBAAiB,EACjB,cAAc,EACd,oBAAoB,GACrB,MAAM,SAAS,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.listTimesheets = exports.logTime = exports.getRunningTimers = exports.stopTimer = exports.startTimer = exports.TimesheetsService = void 0;
|
|
4
|
+
var timesheets_service_1 = require("./timesheets-service");
|
|
5
|
+
Object.defineProperty(exports, "TimesheetsService", { enumerable: true, get: function () { return timesheets_service_1.TimesheetsService; } });
|
|
6
|
+
var functions_1 = require("./functions");
|
|
7
|
+
Object.defineProperty(exports, "startTimer", { enumerable: true, get: function () { return functions_1.startTimer; } });
|
|
8
|
+
Object.defineProperty(exports, "stopTimer", { enumerable: true, get: function () { return functions_1.stopTimer; } });
|
|
9
|
+
Object.defineProperty(exports, "getRunningTimers", { enumerable: true, get: function () { return functions_1.getRunningTimers; } });
|
|
10
|
+
Object.defineProperty(exports, "logTime", { enumerable: true, get: function () { return functions_1.logTime; } });
|
|
11
|
+
Object.defineProperty(exports, "listTimesheets", { enumerable: true, get: function () { return functions_1.listTimesheets; } });
|
|
12
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/services/timesheets/index.ts"],"names":[],"mappings":";;;AAAA,2DAAyD;AAAhD,uHAAA,iBAAiB,OAAA;AAC1B,yCAA+F;AAAtF,uGAAA,UAAU,OAAA;AAAE,sGAAA,SAAS,OAAA;AAAE,6GAAA,gBAAgB,OAAA;AAAE,oGAAA,OAAO,OAAA;AAAE,2GAAA,cAAc,OAAA"}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Timesheets service — the typed interface exposed via `client.timesheets.*`
|
|
3
|
+
*
|
|
4
|
+
* Delegates to standalone functions in functions.ts.
|
|
5
|
+
*
|
|
6
|
+
* Timer concept: unit_amount = 0 means running, unit_amount > 0 means closed.
|
|
7
|
+
* This is standard hr_timesheet behavior — no extra modules needed.
|
|
8
|
+
*
|
|
9
|
+
* Requires the `hr_timesheet` module to be installed.
|
|
10
|
+
*
|
|
11
|
+
* @see https://github.com/odoo/odoo/blob/17.0/addons/hr_timesheet/models/account_analytic_line.py
|
|
12
|
+
*/
|
|
13
|
+
import type { OdooClient } from '../../client/odoo-client';
|
|
14
|
+
import type { TimesheetEntry, TimerStartOptions, LogTimeOptions, TimesheetListOptions } from './types';
|
|
15
|
+
/**
|
|
16
|
+
* Timesheets service for managing time tracking on projects and tasks.
|
|
17
|
+
*
|
|
18
|
+
* Access via `client.timesheets` — never instantiate directly.
|
|
19
|
+
*
|
|
20
|
+
* Two workflows:
|
|
21
|
+
* 1. **Timer-based**: startTimer() → work → stopTimer() (duration auto-computed)
|
|
22
|
+
* 2. **Manual**: logTime() with known hours (e.g., logging past work)
|
|
23
|
+
*
|
|
24
|
+
* All methods accept an optional employeeId. When omitted, the current
|
|
25
|
+
* user's linked hr.employee record is used automatically.
|
|
26
|
+
*/
|
|
27
|
+
export declare class TimesheetsService {
|
|
28
|
+
private client;
|
|
29
|
+
/** @internal */
|
|
30
|
+
constructor(client: OdooClient);
|
|
31
|
+
/**
|
|
32
|
+
* Start a timesheet timer.
|
|
33
|
+
*
|
|
34
|
+
* Creates a timesheet entry and starts the clock. Duration is tracked
|
|
35
|
+
* automatically until stopTimer() is called.
|
|
36
|
+
*
|
|
37
|
+
* @param options - Description, projectId, optional taskId/employeeId
|
|
38
|
+
* @returns The created timesheet entry with timer running
|
|
39
|
+
*
|
|
40
|
+
* @example
|
|
41
|
+
* ```typescript
|
|
42
|
+
* const entry = await client.timesheets.startTimer({
|
|
43
|
+
* description: 'Implementing login feature',
|
|
44
|
+
* projectId: 5,
|
|
45
|
+
* taskId: 42,
|
|
46
|
+
* });
|
|
47
|
+
* console.log(`Timer started: ${entry.id}`);
|
|
48
|
+
* ```
|
|
49
|
+
*/
|
|
50
|
+
startTimer(options: TimerStartOptions): Promise<TimesheetEntry>;
|
|
51
|
+
/**
|
|
52
|
+
* Stop a running timesheet timer.
|
|
53
|
+
*
|
|
54
|
+
* Computes the elapsed time and saves it to the entry's unit_amount.
|
|
55
|
+
*
|
|
56
|
+
* @param timesheetId - ID of the timesheet entry with a running timer
|
|
57
|
+
* @returns The updated entry with hours filled in
|
|
58
|
+
* @throws OdooValidationError if no running timer on this entry
|
|
59
|
+
*
|
|
60
|
+
* @example
|
|
61
|
+
* ```typescript
|
|
62
|
+
* const entry = await client.timesheets.stopTimer(123);
|
|
63
|
+
* console.log(`Logged ${entry.unit_amount.toFixed(2)} hours`);
|
|
64
|
+
* ```
|
|
65
|
+
*/
|
|
66
|
+
stopTimer(timesheetId: number): Promise<TimesheetEntry>;
|
|
67
|
+
/**
|
|
68
|
+
* Find all running timers for an employee.
|
|
69
|
+
*
|
|
70
|
+
* @param employeeId - Employee ID (omit for current user's employee)
|
|
71
|
+
* @returns Array of entries with running timers (usually 0 or 1)
|
|
72
|
+
*
|
|
73
|
+
* @example
|
|
74
|
+
* ```typescript
|
|
75
|
+
* const running = await client.timesheets.getRunningTimers();
|
|
76
|
+
* if (running.length > 0) {
|
|
77
|
+
* console.log(`Timer running since ${running[0].timer_start}`);
|
|
78
|
+
* }
|
|
79
|
+
* ```
|
|
80
|
+
*/
|
|
81
|
+
getRunningTimers(employeeId?: number): Promise<TimesheetEntry[]>;
|
|
82
|
+
/**
|
|
83
|
+
* Log a completed timesheet entry with known hours.
|
|
84
|
+
*
|
|
85
|
+
* Use this when you know the duration (no timer needed).
|
|
86
|
+
*
|
|
87
|
+
* @param options - Description, projectId, hours, optional taskId/date/employeeId
|
|
88
|
+
* @returns The created timesheet entry
|
|
89
|
+
*
|
|
90
|
+
* @example
|
|
91
|
+
* ```typescript
|
|
92
|
+
* const entry = await client.timesheets.logTime({
|
|
93
|
+
* description: 'Code review for PR #42',
|
|
94
|
+
* projectId: 5,
|
|
95
|
+
* taskId: 42,
|
|
96
|
+
* hours: 1.5,
|
|
97
|
+
* });
|
|
98
|
+
* ```
|
|
99
|
+
*/
|
|
100
|
+
logTime(options: LogTimeOptions): Promise<TimesheetEntry>;
|
|
101
|
+
/**
|
|
102
|
+
* List timesheet entries with optional filters.
|
|
103
|
+
*
|
|
104
|
+
* @param options - Filter by employee, project, task, date range, etc.
|
|
105
|
+
* @returns Array of timesheet entries
|
|
106
|
+
*
|
|
107
|
+
* @example
|
|
108
|
+
* ```typescript
|
|
109
|
+
* // This week's timesheets
|
|
110
|
+
* const entries = await client.timesheets.list({
|
|
111
|
+
* dateFrom: '2026-02-09',
|
|
112
|
+
* dateTo: '2026-02-15',
|
|
113
|
+
* employeeId: 42,
|
|
114
|
+
* });
|
|
115
|
+
* const total = entries.reduce((sum, e) => sum + e.unit_amount, 0);
|
|
116
|
+
* console.log(`Total: ${total.toFixed(2)} hours`);
|
|
117
|
+
* ```
|
|
118
|
+
*/
|
|
119
|
+
list(options?: TimesheetListOptions): Promise<TimesheetEntry[]>;
|
|
120
|
+
}
|
|
121
|
+
//# sourceMappingURL=timesheets-service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"timesheets-service.d.ts","sourceRoot":"","sources":["../../../src/services/timesheets/timesheets-service.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAC3D,OAAO,KAAK,EACV,cAAc,EACd,iBAAiB,EACjB,cAAc,EACd,oBAAoB,EACrB,MAAM,SAAS,CAAC;AASjB;;;;;;;;;;;GAWG;AACH,qBAAa,iBAAiB;IAEhB,OAAO,CAAC,MAAM;IAD1B,gBAAgB;gBACI,MAAM,EAAE,UAAU;IAEtC;;;;;;;;;;;;;;;;;;OAkBG;IACG,UAAU,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,cAAc,CAAC;IAIrE;;;;;;;;;;;;;;OAcG;IACG,SAAS,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;IAI7D;;;;;;;;;;;;;OAaG;IACG,gBAAgB,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC;IAItE;;;;;;;;;;;;;;;;;OAiBG;IACG,OAAO,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,cAAc,CAAC;IAI/D;;;;;;;;;;;;;;;;;OAiBG;IACG,IAAI,CAAC,OAAO,CAAC,EAAE,oBAAoB,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC;CAGtE"}
|