changeset b861d455d5b7 in modules/project_invoice:6.2 details: https://hg.tryton.org/modules/project_invoice?cmd=changeset&node=b861d455d5b7 description: Take into account up to date when computing invoice quantity
issue10836 review373811003 (grafted from 36f5c90fef9919986ea5d3a9d4fd1e9c60f3174b) diffstat: project.py | 37 ++++++++++++++++++--------- tests/scenario_project_invoice_timesheet.rst | 26 ++++++++++++++++++- 2 files changed, 49 insertions(+), 14 deletions(-) diffs (104 lines): diff -r 8a5a3e2f10d0 -r b861d455d5b7 project.py --- a/project.py Mon Nov 01 17:27:33 2021 +0100 +++ b/project.py Mon Nov 22 10:12:44 2021 +0100 @@ -250,19 +250,32 @@ cursor = Transaction().connection.cursor() line = TimesheetLine.__table__() + upto2tworks = defaultdict(list) + twork2work = {} + for work in works: + upto = work.invoice_timesheet_up_to + for timesheet_work in work.timesheet_works: + twork2work[timesheet_work.id] = work.id + upto2tworks[upto].append(timesheet_work.id) + durations = defaultdict(datetime.timedelta) - twork2work = {tw.id: w.id for w in works for tw in w.timesheet_works} - for sub_ids in grouped_slice(twork2work.keys()): - red_sql = reduce_ids(line.work, sub_ids) - cursor.execute(*line.select(line.work, Sum(line.duration), - where=red_sql & (line.invoice_line == Null), - group_by=line.work)) - for twork_id, duration in cursor: - if duration: - # SQLite uses float for SUM - if not isinstance(duration, datetime.timedelta): - duration = datetime.timedelta(seconds=duration) - durations[twork2work[twork_id]] += duration + query = line.select( + line.work, Sum(line.duration), + group_by=line.work) + for upto, tworks in upto2tworks.items(): + for sub_ids in grouped_slice(tworks): + query.where = (reduce_ids(line.work, sub_ids) + & (line.invoice_line == Null)) + if upto: + query.where &= (line.date <= upto) + cursor.execute(*query) + + for twork_id, duration in cursor: + if duration: + # SQLite uses float for SUM + if not isinstance(duration, datetime.timedelta): + duration = datetime.timedelta(seconds=duration) + durations[twork2work[twork_id]] += duration quantities = {} for work in works: diff -r 8a5a3e2f10d0 -r b861d455d5b7 tests/scenario_project_invoice_timesheet.rst --- a/tests/scenario_project_invoice_timesheet.rst Mon Nov 01 17:27:33 2021 +0100 +++ b/tests/scenario_project_invoice_timesheet.rst Mon Nov 22 10:12:44 2021 +0100 @@ -46,8 +46,9 @@ >>> project_invoice_user.login = 'project_invoice' >>> project_invoice_group, = Group.find([('name', '=', 'Project Invoice')]) >>> project_group, = Group.find([('name', '=', 'Project Administration')]) + >>> invoice_group, = Group.find([('name', '=', 'Account')]) >>> project_invoice_user.groups.extend( - ... [project_invoice_group, project_group]) + ... [project_invoice_group, project_group, invoice_group]) >>> project_invoice_user.save() Create chart of accounts:: @@ -160,8 +161,19 @@ >>> set_user(project_invoice_user) >>> project.click('invoice') >>> project.amount_to_invoice + Decimal('0.00') + >>> project.invoiced_amount + Decimal('60.00') + + >>> project.project_invoice_timesheet_up_to = today + >>> project.save() + >>> project.amount_to_invoice Decimal('40.00') - >>> project.invoiced_amount + + >>> set_user(project_invoice_user) + >>> Invoice = Model.get('account.invoice') + >>> invoice, = Invoice.find([]) + >>> invoice.total_amount Decimal('60.00') Invoice all project:: @@ -176,6 +188,11 @@ >>> project.invoiced_amount Decimal('100.00') + >>> set_user(project_invoice_user) + >>> _, invoice = Invoice.find([], order=[('id', 'ASC')]) + >>> invoice.total_amount + Decimal('40.00') + Create more timesheets:: >>> set_user(project_user) @@ -202,3 +219,8 @@ Decimal('0.00') >>> project.invoiced_amount Decimal('180.00') + + >>> set_user(project_invoice_user) + >>> _, _, invoice = Invoice.find([], order=[('id', 'ASC')]) + >>> invoice.total_amount + Decimal('80.00')