TIP: You can type at any time to perform a new search.
Sales Timesheet
sale_timesheet · odoo/odoo
- Repository
- odoo/odoo · module folder
- Module version
- 0.1.0
- Category
- Sales/Sales
- Folder size
- 5.35 MB
- License
- LGPL-3
- Application
- No
- Auto-installable
- Yes
- Website
- None
- Last tracking update
- 2026-08-16 22:12:28
- Authors
- Odoo S.A.
- Maintainers
- Odoo S.A.
- Committers
- Xavier Morel, Raphael Collet, Thibault Delavallée, Stéphane Bidoul, Odoo Translation Bot, Lucas Perais (lpe), Yannick Tivisse, Julien Castiaux, Victor Feyens, Andrea Grazioso (agr-odoo), Paul Morelle, Julien Mougenot, svs-odoo, Prakash Prajapati, Tiffany Chang (tic), Gorash, Mathieu Duckerts-Antoine, William Braeckman, william-andre, Audric Onockx (auon), Renaud Thiry, Vincent Larcin, Louis Wicket (wil), alsh-odoo, Victor Piryns (pivi), Pierre-Yves Dufays, Levi Siuzdak (sile), Dylan Kiss (dyki), Antoine Boonen, Xavier Bol (xbo), Brieuc-brd, rajh-odoo, Youssef Bashandy, bary, Maxime de Neuville, suth-odoo, kcv-odoo, Tanguy Quéguineur, nihp-odoo, aamo-odoo, thle-odoo, Mathieu Coutant, Patricia Daloze (pda), guce, Pierre Pulinckx (PIPU), Kawtar Drissi El Bouzaidi (kdeb), David Van Droogenbroeck (DROD), Mohammad Abdulmoneim (abdu), Pierre Pulinckx, Bastien PIERRE, Michaël Mattiello, K Theja (kthe), Mahdi Alijani (malj), bona-odoo, Krzysztof Magusiak (krma), Maeva De Keyser (MDEK), Harrison Hutton, nsirjacobs, mjvi-odoo, bhra-odoo, defl, mohannedah, Quentin Colla (qucol), Amr Elkhatieb, Maxime de Neuville (mane), YoussefM890, damrOdoo, Merlin Guillaume, Abdelouahab Laaroussi (abla), Farah (ahmfa), ksin-odoo, chpa-odoo, Dhruvkumar Nagar
- Odoo dependencies
- Python dependencies
- None
- System dependencies
- None
- Required by
- project_task_analytic_propagation, sale_order_update_timesheet_price, sale_timesheet_invoice_link, sale_timesheet_line_exclude, sale_timesheet_margin, sale_timesheet_timeline, spreadsheet_dashboard_sale_timesheet, test_main_flows
- Description
Allows to sell timesheets in your sales order ============================================= This module set the right product on all timesheet lines according to the order/contract you work on. This allows to have real delivered quantities in sales orders.
Code Analysis ⓘ
Views touched (45)
| XML ID | Name | Model | Type | Status |
|---|---|---|---|---|
account_invoice_view_form_inherit_sale_timesheet |
account.invoice.form.inherit.timesheet | account.move | form | Inherits account.view_move_form |
hr_timesheet_line_form_inherit |
account.analytic.line.form.inherit | account.analytic.line | form | Inherits hr_timesheet.hr_timesheet_line_form |
hr_timesheet_line_tree_inherit |
account.analytic.line.list.inherit | account.analytic.line | list | Inherits hr_timesheet.hr_timesheet_line_tree |
hr_timesheet_report_search_sale_timesheet |
timesheets.analysis.report.search | timesheets.analysis.report | search | Inherits sale_timesheet.timesheet_view_search |
portal_invoice_page_inherit |
portal_invoice_page_inherit | ir.ui.view | qweb | Inherits account.portal_invoice_page |
portal_my_task_inherit |
portal_my_task_inherit | ir.ui.view | qweb | Inherits project.portal_my_task |
portal_my_timesheets_inherit |
portal_my_timesheets_inherit | ir.ui.view | qweb | Inherits hr_timesheet.portal_my_timesheets |
portal_timesheet_table_inherit |
portal_timesheet_table_inherit | ir.ui.view | qweb | Inherits hr_timesheet.portal_timesheet_table |
product_template_view_search_sale_timesheet |
product.template.search.timesheet | product.template | search | Inherits product.product_template_search_view |
project_project_view_form |
project.project.form.inherit | project.project | form | Inherits hr_timesheet.project_invoice_form |
project_project_view_kanban_inherit_sale_timesheet |
project.project.kanban.inherit.sale.timesheet | project.project | kanban | Inherits hr_timesheet.view_project_kanban_inherited |
project_project_view_kanban_inherit_sale_timesheet_so_button |
project.project.kanban.inherit.sale.timesheet.so.button | project.project | kanban | Inherits project.view_project_kanban |
project_sharing_inherit_project_task_view_form |
project.task.form.inherit.timesheet | project.task | form | Inherits hr_timesheet.project_sharing_inherit_project_task_view_form |
project_task_view_form_inherit_sale_timesheet |
project.task.form.inherit.timesheet | project.task | form | Inherits project.view_task_form2 |
project_task_view_search_inherit_sale_timesheet |
project.task.view.search.inherit | project.task | search | Inherits hr_timesheet.project_task_view_search |
report_timesheet_account_move |
report_timesheet_account_move | ir.ui.view | qweb | New |
report_timesheet_sale_order |
report_timesheet_sale_order | ir.ui.view | qweb | New |
res_config_settings_view_form |
res.config.settings.view.form.inherit.sale.timesheet | res.config.settings | form | Inherits hr_timesheet.res_config_settings_view_form |
sale_advance_payment_inv_timesheet_view_form |
sale_timesheet.sale.advance.payment.inv.view.form | sale.advance.payment.inv | form | Inherits sale.view_sale_advance_payment_inv |
sale_order_portal_content_inherit |
sale_order_portal_content_inherit | ir.ui.view | qweb | Inherits sale.sale_order_portal_template |
timesheet_sale_page |
timesheet_sale_page | ir.ui.view | qweb | New |
timesheet_view_search |
account.analytic.line.search | account.analytic.line | search | Inherits hr_timesheet.hr_timesheet_line_search |
timesheete_analysis_report_form |
timesheets.analysis.report.form | timesheets.analysis.report | form | Inherits hr_timesheet.timesheets_analysis_report_form |
timesheets_analysis_report_graph_inherit |
timesheets.analysis.report.graph | timesheets.analysis.report | graph | Inherits hr_timesheet.timesheets_analysis_report_pivot_employee |
timesheets_analysis_report_graph_invoice_type |
timesheets.analysis.report.graph | timesheets.analysis.report | graph | New |
timesheets_analysis_report_graph_project_inherit |
timesheets.analysis.report.graph.project | timesheets.analysis.report | graph | Inherits hr_timesheet.timesheets_analysis_report_graph_project |
timesheets_analysis_report_graph_task_inherit |
timesheets.analysis.report.graph.task | timesheets.analysis.report | graph | Inherits hr_timesheet.timesheets_analysis_report_graph_task |
timesheets_analysis_report_graph_timesheet_grid |
timesheets.analysis.report.graph | timesheets.analysis.report | graph | Inherits hr_timesheet.timesheets_analysis_report_graph_employee |
timesheets_analysis_report_list_inherited |
timesheets.analysis.report.list.inherited | timesheets.analysis.report | list | Inherits hr_timesheet.timesheets_analysis_report_list |
timesheets_analysis_report_pivot_inherit |
timesheets.analysis.report.pivot | timesheets.analysis.report | pivot | Inherits hr_timesheet.timesheets_analysis_report_pivot_employee |
timesheets_analysis_report_pivot_invoice_type |
timesheets.analysis.report.pivot | timesheets.analysis.report | pivot | New |
timesheets_analysis_report_pivot_project_inherit |
timesheets.analysis.report.pivot.project | timesheets.analysis.report | pivot | Inherits hr_timesheet.timesheets_analysis_report_pivot_project |
timesheets_analysis_report_pivot_task_inherit |
timesheets.analysis.report.pivot.task | timesheets.analysis.report | pivot | Inherits hr_timesheet.timesheets_analysis_report_pivot_task |
view_calendar_account_analytic_line |
account.analytic.line.calendar | account.analytic.line | calendar | Inherits hr_timesheet.view_calendar_account_analytic_line |
view_calendar_account_analytic_line_multi_create |
account.analytic.line.calendar.multi_create | account.analytic.line | calendar | Inherits hr_timesheet.view_calendar_account_analytic_line_multi_create |
view_hr_timesheet_line_graph_employee_per_date |
account.analytic.line.graph.employee.per.date | account.analytic.line | graph | New |
view_hr_timesheet_line_graph_invoice_employee |
account.analytic.line.graph.invoice.employee | account.analytic.line | graph | Inherits view_hr_timesheet_line_graph_employee_per_date |
view_hr_timesheet_line_pivot_billing_rate |
account.analytic.line.pivot.billing.rate | account.analytic.line | pivot | New |
view_hr_timesheet_line_pivot_inherited |
account.analytic.line.pivot | account.analytic.line | pivot | Inherits hr_timesheet.view_hr_timesheet_line_pivot |
view_order_form_inherit_sale_timesheet |
sale.order.form.sale.timesheet | sale.order | form | Inherits sale_project.view_order_form_inherit_sale_project |
view_product_timesheet_form |
product.template.timesheet.form | product.template | form | Inherits sale.product_template_form_view |
view_task_project_user_fsm_graph_base_inherited |
report.project.task.user.fsm.graph.base.inherited | report.project.task.user | graph | Inherits project.view_task_project_user_fsm_graph_base |
view_task_project_user_fsm_pivot_base_inherited |
report.project.task.user.fsm.pivot.base.inherited | report.project.task.user | pivot | Inherits project.view_task_project_user_fsm_pivot_base |
view_task_project_user_pivot_inherited |
report.project.task.user.pivot.inherited | report.project.task.user | pivot | Inherits project.view_task_project_user_pivot |
view_task_tree2_inherited |
project.task.list.inherited | project.task | list | Inherits hr_timesheet.view_task_tree2_inherited |
HTTP endpoints (2)
| Route(s) | Handler | Auth | Type | Methods | Flags |
|---|---|---|---|---|---|
/my/tasks/<task_id>/orders/invoices, /my/tasks/<task_id>/orders/invoices/page/<int:page> |
PortalProjectAccount.portal_my_tasks_invoices |
user | http | ALL | website |
| (inherited route override) | SaleTimesheetCustomerPortal.portal_my_timesheets |
inherited | http | ALL |
Models touched (16)
New fields (8)
-
allow_billableBooleanrelated='project_id.allow_billable' -
commercial_partner_idMany2one → res.partnercompute='_compute_commercial_partner' args: 'res.partner' -
is_so_line_editedBooleanargs: 'Is Sales Order Item Manually Edited' -
order_idMany2oneindex=Truereadonly=Truerelated='so_line.order_id'store=True -
sale_order_stateSelectionrelated='order_id.state' -
so_lineMany2onecompute='_compute_so_line'domain=_domain_so_linefalsy_value_label='Non-billable'help='Sales order item to which the time spent will be added in order to be invoiced to your customer. Remove the sales order item for the timesheet entry to be non-billable.'readonly=Falsestore=True -
timesheet_invoice_idMany2one → account.movecopy=Falsehelp='Invoice created from the timesheet'index='btree_not_null'readonly=Truestring='Invoice' args: 'account.move' -
timesheet_invoice_typeSelectioncompute='_compute_timesheet_invoice_type'compute_sudo=Truereadonly=Truestore=Truestring='Billable Type' args: TIMESHEET_INVOICE_TYPES
-
action_invoice_from_timesheet(self) -
action_sale_order_from_timesheet(self) -
write(self, vals)
New fields (4)
-
timesheet_countIntegercompute='_compute_timesheet_count'compute_sudo=Trueexport_string_translation=False args: 'Number of timesheets' -
timesheet_encode_uom_idMany2one → uom.uomexport_string_translation=Falserelated='company_id.timesheet_encode_uom_id' args: 'uom.uom' -
timesheet_idsOne2many → account.analytic.linecopy=Falseexport_string_translation=Falsereadonly=Truestring='Timesheets' args: 'account.analytic.line', 'timesheet_invoice_id' -
timesheet_total_durationIntegercompute='_compute_timesheet_total_duration'compute_sudo=Truehelp='Total recorded duration, expressed in the encoding UoM, and rounded to the unit' args: 'Timesheet Total Duration'
-
action_post(self) -
action_view_timesheet(self)
New fields (0)
No new fields.
Public methods (1)-
unlink(self)
New fields (0)
No new fields.
Public methods (1)-
reverse_moves(self, is_modify=False)
New fields (0)
No new fields.
Public methods (1)-
default_get(self, fields)@api.model
New fields (0)
No new fields.
Public methods (1)-
write(self, vals)
New fields (5)
-
project_idMany2onedomain="['|', ('company_id', '=', False), '&', ('company_id', '=?', company_id), ('company_id', '=', current_company_id), ('allow_billable', '=', True), ('pricing_type', '=', 'task_rate'), ('allow_timesheets', 'in', [service_policy == 'delivered_timesheet', True]), ('is_template', '=', False)]" -
project_template_idMany2onedomain="['|', ('company_id', '=', False), '&', ('company_id', '=?', company_id), ('company_id', '=', current_company_id), ('allow_billable', '=', True), ('allow_timesheets', 'in', [service_policy == 'delivered_timesheet', True]), ('is_template', '=', True)]" -
service_typeSelectionondelete={'timesheet': 'set manual'}selection_add=[('timesheet', 'Timesheets on project (one fare per SO/Project)')] -
service_upsell_thresholdFloatdefault=1help='Percentage of time delivered compared to the prepaid amount that must be reached for the upselling opportunity activity to be triggered.' args: 'Threshold' -
service_upsell_threshold_ratioCharcompute='_compute_service_upsell_threshold_ratio'export_string_translation=False
-
write(self, vals)
New fields (7)
-
allocated_hoursFloat -
billing_typeSelectioncompute='_compute_billing_type'default='not_billable'readonly=Falserequired=Trueselection=[('not_billable', 'not billable'), ('manually', 'billed manually')]store=True -
partner_idMany2onecompute='_compute_partner_id'readonly=Falsestore=True -
pricing_typeSelectioncompute='_compute_pricing_type'default='task_rate'help='The task rate is perfect if you would like to bill different services to different customers at different rates. The fixed rate is perfect if you bill a service at a fixed rate per hour or day worked regardless of the employee who performed it. The employee rate is preferable if your employees deliver the same service at a different rate. For instance, junior and senior consultants would deliver the same service (= consultancy), but at a different rate because of their level of seniority.'search='_search_pricing_type'string='Pricing' args: [('task_rate', 'Task rate'), ('fixed_rate', 'Project rate'), ('employee_rate', 'Employee rate')] -
sale_line_employee_idsOne2many → project.sale.line.employee.mapcopy=Falseexport_string_translation=Falsehelp="Sales order item that will be selected by default on the timesheets of the corresponding employee. It bypasses the sales order item defined on the project and the task, and can be modified on each timesheet entry if necessary. In other words, it defines the rate at which an employee's time is billed based on their expertise, skills or experience, for instance.\nIf you would like to bill the same service at a different rate, you need to create two separate sales order items as each sales order item can only have a single unit price at a time.\nYou can also define the hourly company cost of your employees for their timesheets on this project specifically. It will bypass the timesheet cost set on the employee." args: 'project.sale.line.employee.map', 'project_id', 'Sale line/Employee map' -
timesheet_product_idMany2one → product.productcheck_company=Truecompute='_compute_timesheet_product_id'default=_default_timesheet_product_iddomain="[\n ('type', '=', 'service'),\n ('invoice_policy', '=', 'delivery'),\n ('service_type', '=', 'timesheet'),\n ]"help='Service that will be used by default when invoicing the time spent on a task. It can be modified on each task individually by selecting a specific sales order item.'readonly=Falsestore=Truestring='Timesheet Product' args: 'product.product' -
warning_employee_rateBooleancompute='_compute_warning_employee_rate'compute_sudo=Trueexport_string_translation=False
-
action_billable_time_button(self) -
action_profitability_items(self, section_name, domain=None, res_id=False) -
action_project_timesheets(self) -
action_view_timesheet(self) -
default_get(self, fields)@api.modelPre-fill timesheet product as "Time" data product when creating new project allowing billable tasks by default. -
get_panel_data(self) -
write(self, vals)
New fields (13)
-
company_idMany2one → res.companyexport_string_translation=Falserelated='project_id.company_id'string='Company' args: 'res.company' -
costMonetarycompute='_compute_cost'currency_field='cost_currency_id'help="This cost overrides the employee's default employee hourly wage in employee's HR Settings"readonly=Falsestore=True -
cost_currency_idMany2one → res.currencyexport_string_translation=Falsereadonly=Truerelated='employee_id.currency_id'string='Cost Currency' args: 'res.currency' -
currency_idMany2one → res.currencycompute='_compute_currency_id'readonly=Falsestore=Truestring='Currency' args: 'res.currency' -
display_costMonetarycompute='_compute_display_cost'currency_field='cost_currency_id'groups='project.group_project_manager,hr.group_hr_user'inverse='_inverse_display_cost'string='Hourly Cost' -
employee_idMany2one → hr.employeedomain="[('id', 'not in', existing_employee_ids)]"required=True args: 'hr.employee', 'Employee' -
existing_employee_idsMany2many → hr.employeecompute='_compute_existing_employee_ids'compute_sudo=Trueexport_string_translation=False args: 'hr.employee' -
is_cost_changedBooleancompute='_compute_is_cost_changed'export_string_translation=Falsestore=True args: 'Is Cost Manually Changed' -
partner_idMany2oneexport_string_translation=Falserelated='project_id.partner_id' -
price_unitFloatcompute='_compute_price_unit'readonly=Truestore=True args: 'Unit Price' -
project_idMany2one → project.projectdomain=[('is_template', '=', False)]index=Truerequired=True args: 'project.project', 'Project' -
sale_line_idMany2one → sale.order.linecompute='_compute_sale_line_id'domain=<expr>readonly=Falsestore=True args: 'sale.order.line', 'Sales Order Item' -
sale_order_idMany2oneexport_string_translation=Falserelated='project_id.sale_order_id'
-
create(self, vals_list)@api.model_create_multi -
write(self, vals)
New fields (8)
-
has_multi_solBooleancompute='_compute_has_multi_sol'compute_sudo=True -
is_project_map_emptyBooleancompute='_compute_is_project_map_empty' args: 'Is Project map empty' -
last_sol_of_customerMany2one → sale.order.linecompute='_compute_last_sol_of_customer' args: 'sale.order.line' -
pricing_typeSelectionrelated='project_id.pricing_type' -
remaining_hours_availableBooleanrelated='sale_line_id.remaining_hours_available' -
remaining_hours_soFloatcompute='_compute_remaining_hours_so'compute_sudo=Truesearch='_search_remaining_hours_so' args: 'Time Remaining on SO' -
sale_order_idMany2onedomain="['|', '|', ('partner_id', '=', partner_id), ('partner_id.commercial_partner_id.id', 'parent_of', partner_id), ('partner_id', 'parent_of', partner_id)]" -
timesheet_product_idMany2onerelated='project_id.timesheet_product_id'
-
TASK_PORTAL_READABLE_FIELDS(self)@property
New fields (1)
-
remaining_hours_soFloatgroups='hr_timesheet.group_hr_timesheet_user'readonly=True args: 'Time Remaining on SO'
No public methods.
New fields (1)
-
invoice_policyBooleanhelp='Timesheets taken when invoicing time spent'string='Invoice Policy'
No public methods.
New fields (3)
-
date_end_invoice_timesheetDatehelp='Only timesheets not yet invoiced (and validated, if applicable) from this period will be invoiced. If the period is not indicated, all timesheets not yet invoiced (and validated, if applicable) will be invoiced without distinction.'string='End Date' -
date_start_invoice_timesheetDatehelp='Only timesheets not yet invoiced (and validated, if applicable) from this period will be invoiced. If the period is not indicated, all timesheets not yet invoiced (and validated, if applicable) will be invoiced without distinction.'string='Start Date' -
invoicing_timesheet_enabledBooleancompute='_compute_invoicing_timesheet_enabled'export_string_translation=Falsestore=True
No public methods.
New fields (4)
-
show_hours_recorded_buttonBooleancompute='_compute_show_hours_recorded_button'compute_sudo=Trueexport_string_translation=Falsegroups='hr_timesheet.group_hr_timesheet_user' -
timesheet_countFloatcompute='_compute_timesheet_count'export_string_translation=Falsegroups='hr_timesheet.group_hr_timesheet_user'string='Timesheet activities' -
timesheet_encode_uom_idMany2one → uom.uomexport_string_translation=Falserelated='company_id.timesheet_encode_uom_id' args: 'uom.uom' -
timesheet_total_durationIntegercompute='_compute_timesheet_total_duration'compute_sudo=Trueexport_string_translation=Falsegroups='hr_timesheet.group_hr_timesheet_user'help='Total recorded duration, expressed in the encoding UoM, and rounded to the unit' args: 'Timesheet Total Duration'
-
action_view_timesheet(self) -
create(self, vals_list)@api.model_create_multi
New fields (6)
-
analytic_line_idsOne2manydomain=[('project_id', '=', False)] -
has_displayed_warning_upsellBooleancopy=Falseexport_string_translation=False args: 'Has Displayed Warning Upsell' -
qty_delivered_methodSelectionselection_add=[('timesheet', 'Timesheets')] -
remaining_hoursFloatcompute='_compute_remaining_hours'compute_sudo=Truestore=True args: 'Time Remaining on SO' -
remaining_hours_availableBooleancompute='_compute_remaining_hours_available'compute_sudo=True -
timesheet_idsOne2many → account.analytic.linedomain=[('project_id', '!=', False)]export_string_translation=Falsestring='Timesheets' args: 'account.analytic.line', 'so_line'
No public methods.
New fields (8)
-
billable_timeFloathelp='Number of hours/days linked to a SOL.'readonly=True args: 'Billable Time' -
marginMonetarycurrency_field='currency_id'help='Timesheets revenues minus the costs'readonly=True args: 'Margin' -
non_billable_timeFloathelp='Number of hours/days not linked to a SOL.'readonly=True args: 'Non-billable Time' -
order_idMany2one → sale.orderreadonly=Truestring='Sales Order' args: 'sale.order' -
so_lineMany2one → sale.order.linereadonly=Truestring='Sales Order Item' args: 'sale.order.line' -
timesheet_invoice_idMany2one → account.movehelp='Invoice created from the timesheet'readonly=Truestring='Invoice' args: 'account.move' -
timesheet_invoice_typeSelectionreadonly=Truestring='Billable Type' args: TIMESHEET_INVOICE_TYPES -
timesheet_revenuesMonetarycurrency_field='currency_id'help='Number of hours spent multiplied by the unit price per hour/day.'readonly=True args: 'Timesheet Revenues'
No public methods.
Loading…
Loading…
Loading…
Loading…
Loading…
Loading…
Loading…
Loading…
Loading…
Loading…