diff --git a/addons/sale_timesheet/models/account_move.py b/addons/sale_timesheet/models/account_move.py
index 5c4d8ea925b..74317a663e5 100644
--- a/addons/sale_timesheet/models/account_move.py
+++ b/addons/sale_timesheet/models/account_move.py
@@ -43,21 +43,23 @@ class AccountMove(models.Model):
}
}
- def _link_timesheets_to_invoice(self, date=None):
- """ Search timesheets and link this timesheets to the invoice
+ def _link_timesheets_to_invoice(self, start_date=None, end_date=None):
+ """ Search timesheets from given period and link this timesheets to the invoice
When we create an invoice from a sale order, we need to
link the timesheets in this sale order to the invoice.
Then, we can know which timesheets are invoiced in the sale order.
- :param date: All timesheets on task before or equals this date
- in the sale order are invoiced.
+ :param start_date: the start date of the period
+ :param end_date: the end date of the period
"""
for line in self.filtered(lambda i: i.move_type == 'out_invoice' and i.state == 'draft').invoice_line_ids:
sale_line_delivery = line.sale_line_ids.filtered(lambda sol: sol.product_id.invoice_policy == 'delivery' and sol.product_id.service_type == 'timesheet')
if sale_line_delivery:
domain = line._timesheet_domain_get_invoiced_lines(sale_line_delivery)
- if date:
- domain = expression.AND([domain, [('date', '<=', date)]])
+ if start_date:
+ domain = expression.AND([domain, [('date', '>=', start_date)]])
+ if end_date:
+ domain = expression.AND([domain, [('date', '<=', end_date)]])
timesheets = self.env['account.analytic.line'].sudo().search(domain)
timesheets.write({'timesheet_invoice_id': line.move_id.id})
diff --git a/addons/sale_timesheet/models/sale_order.py b/addons/sale_timesheet/models/sale_order.py
index bcc5859899f..2fbf310a615 100644
--- a/addons/sale_timesheet/models/sale_order.py
+++ b/addons/sale_timesheet/models/sale_order.py
@@ -60,14 +60,15 @@ class SaleOrder(models.Model):
action = {'type': 'ir.actions.act_window_close'}
return action
- def _create_invoices(self, grouped=False, final=False, date=None):
+ def _create_invoices(self, grouped=False, final=False, start_date=None, end_date=None):
""" Override the _create_invoice method in sale.order model in sale module
Add new parameter in this method, to invoice sale.order with a date. This date is used in sale_make_invoice_advance_inv into this module.
- :param date
+ :param start_date: the start date of the period
+ :param end_date: the end date of the period
:return {account.move}: the invoices created
"""
moves = super(SaleOrder, self)._create_invoices(grouped, final)
- moves._link_timesheets_to_invoice(date)
+ moves._link_timesheets_to_invoice(start_date, end_date)
return moves
class SaleOrderLine(models.Model):
@@ -115,22 +116,26 @@ class SaleOrderLine(models.Model):
project.write({'allow_timesheets': True})
return project
- def _recompute_qty_to_invoice(self, date):
+ def _recompute_qty_to_invoice(self, start_date, end_date):
""" Recompute the qty_to_invoice field for product containing timesheets
- Search the existed timesheets up the given date in parameter.
+ Search the existed timesheets between the given period in parameter.
Retrieve the unit_amount of this timesheet and then recompute
the qty_to_invoice for each current product.
- :param date: date to search timesheets before this date.
+ :param start_date: the start date of the period
+ :param end_date: the end date of the period
"""
lines_by_timesheet = self.filtered(lambda sol: sol.product_id._is_delivered_timesheet())
domain = lines_by_timesheet._timesheet_compute_delivered_quantity_domain()
domain = expression.AND([domain, [
- ('date', '<=', date),
'|',
('timesheet_invoice_id', '=', False),
('timesheet_invoice_id.state', '=', 'cancel')]])
+ if start_date:
+ domain = expression.AND([domain, [('date', '>=', start_date)]])
+ if end_date:
+ domain = expression.AND([domain, [('date', '<=', end_date)]])
mapping = lines_by_timesheet.sudo()._get_delivered_quantity_by_analytic(domain)
for line in lines_by_timesheet:
diff --git a/addons/sale_timesheet/tests/test_sale_timesheet.py b/addons/sale_timesheet/tests/test_sale_timesheet.py
index 80947e41fbf..28c8a50abe3 100644
--- a/addons/sale_timesheet/tests/test_sale_timesheet.py
+++ b/addons/sale_timesheet/tests/test_sale_timesheet.py
@@ -467,22 +467,24 @@ class TestSaleTimesheet(TestCommonSaleTimesheet):
# invoice SO
wizard = self.env['sale.advance.payment.inv'].with_context(self.context).create({
'advance_payment_method': 'delivered',
- 'date_invoice_timesheet': today - timedelta(days=10)
+ 'date_start_invoice_timesheet': today - timedelta(days=16),
+ 'date_end_invoice_timesheet': today - timedelta(days=10)
})
- self.assertTrue(wizard.invoicing_timesheet_enabled, 'The "date_invoice_timesheet" field should be visible in the wizard because a product in sale order has service_policy to "Timesheet on Task"')
+ self.assertTrue(wizard.invoicing_timesheet_enabled, 'The "date_start_invoice_timesheet" and "date_end_invoice_timesheet" field should be visible in the wizard because a product in sale order has service_policy to "Timesheet on Task"')
with self.assertRaises(UserError):
wizard.create_invoices()
- self.assertFalse(sale_order.invoice_ids, 'Normally, no invoice will be created created because the timesheet logged is after the date defined in date_invoice_timesheet field')
+ self.assertFalse(sale_order.invoice_ids, 'Normally, no invoice will be created because the timesheet logged is after the period defined in date_start_invoice_timesheet and date_end_invoice_timesheet field')
wizard.write({
- 'date_invoice_timesheet': today - timedelta(days=6)
+ 'date_start_invoice_timesheet': today - timedelta(days=10),
+ 'date_end_invoice_timesheet': today - timedelta(days=6)
})
wizard.create_invoices()
- self.assertTrue(sale_order.invoice_ids, 'One invoice should be created because the timesheet logged is before or equal to the date defined in wizard')
+ self.assertTrue(sale_order.invoice_ids, 'One invoice should be created because the timesheet logged is between the period defined in wizard')
invoice = sale_order.invoice_ids[0]
self.assertEqual(so_line_deliver_global_project.qty_invoiced, timesheet1.unit_amount)
@@ -491,17 +493,19 @@ class TestSaleTimesheet(TestCommonSaleTimesheet):
invoice.action_post()
wizard.write({
- 'date_invoice_timesheet': today - timedelta(days=4)
+ 'date_start_invoice_timesheet': today - timedelta(days=16),
+ 'date_end_invoice_timesheet': today - timedelta(days=4)
})
wizard.create_invoices()
self.assertEqual(len(sale_order.invoice_ids), 2)
invoice2 = sale_order.invoice_ids[-1]
- self.assertEqual(so_line_deliver_global_project.qty_invoiced, timesheet1.unit_amount + timesheet3.unit_amount, "The last invoice done should have the quantity of the timesheet 3, because the date this timesheet is the only one before the 'date_invoice_timesheet' field in the wizard.")
+ self.assertEqual(so_line_deliver_global_project.qty_invoiced, timesheet1.unit_amount + timesheet3.unit_amount, "The last invoice done should have the quantity of the timesheet 3, because the date this timesheet is the only one before the 'date_end_invoice_timesheet' field in the wizard.")
wizard.write({
- 'date_invoice_timesheet': today
+ 'date_start_invoice_timesheet': today - timedelta(days=4),
+ 'date_end_invoice_timesheet': today
})
wizard.create_invoices()
@@ -565,7 +569,8 @@ class TestSaleTimesheet(TestCommonSaleTimesheet):
}
wizard = self.env['sale.advance.payment.inv'].with_context(self.context).create({
'advance_payment_method': 'delivered',
- 'date_invoice_timesheet': today
+ 'date_start_invoice_timesheet': today - timedelta(days=4),
+ 'date_end_invoice_timesheet': today
})
wizard.create_invoices()
diff --git a/addons/sale_timesheet/wizard/sale_make_invoice_advance.py b/addons/sale_timesheet/wizard/sale_make_invoice_advance.py
index a1d1fc8dd52..24faf0b34c1 100644
--- a/addons/sale_timesheet/wizard/sale_make_invoice_advance.py
+++ b/addons/sale_timesheet/wizard/sale_make_invoice_advance.py
@@ -16,18 +16,19 @@ class SaleAdvancePaymentInv(models.TransientModel):
product_ids = order_lines.mapped('product_id').filtered(lambda p: p._is_delivered_timesheet())
return bool(product_ids)
- date_invoice_timesheet = fields.Date(
- string='Invoice Timesheets Up To This Date',
- default=fields.Date.context_today,
- required=False,
- help="Only timesheets not yet invoiced (and validated, if applicable) up to this date included will be invoiced. If no date is indicated, all timesheets not yet invoiced (and validated, if applicable) will be invoiced without distinction.")
+ date_start_invoice_timesheet = fields.Date(
+ string='Start Date',
+ help="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.")
+ date_end_invoice_timesheet = fields.Date(
+ string='End Date',
+ help="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.")
invoicing_timesheet_enabled = fields.Boolean(default=_default_invoicing_timesheet_enabled)
def create_invoices(self):
""" Override method from sale/wizard/sale_make_invoice_advance.py
When the user want to invoice the timesheets to the SO
- up to a specific date then we need to recompute the
+ up to a specific period then we need to recompute the
qty_to_invoice for each product_id in sale.order.line,
before creating the invoice.
"""
@@ -36,10 +37,10 @@ class SaleAdvancePaymentInv(models.TransientModel):
)
if self.advance_payment_method == 'delivered' and self.invoicing_timesheet_enabled:
- if self.date_invoice_timesheet:
- sale_orders.mapped('order_line')._recompute_qty_to_invoice(self.date_invoice_timesheet)
+ if self.date_start_invoice_timesheet or self.date_end_invoice_timesheet:
+ sale_orders.mapped('order_line')._recompute_qty_to_invoice(self.date_start_invoice_timesheet, self.date_end_invoice_timesheet)
- sale_orders._create_invoices(final=self.deduct_down_payments, date=self.date_invoice_timesheet)
+ sale_orders._create_invoices(final=self.deduct_down_payments, start_date=self.date_start_invoice_timesheet, end_date=self.date_end_invoice_timesheet)
if self._context.get('open_invoices', False):
return sale_orders.action_view_invoice()
diff --git a/addons/sale_timesheet/wizard/sale_make_invoice_advance_views.xml b/addons/sale_timesheet/wizard/sale_make_invoice_advance_views.xml
index 27915ff0496..bf1d33fd9cf 100644
--- a/addons/sale_timesheet/wizard/sale_make_invoice_advance_views.xml
+++ b/addons/sale_timesheet/wizard/sale_make_invoice_advance_views.xml
@@ -6,16 +6,19 @@
-
+
+