Compare commits

..

15 commits

Author SHA1 Message Date
Frederik Jaeckel
34ef3a5bca rearrange book-now button, fix translation 2024-11-05 09:22:06 +01:00
Frederik Jaeckel
52cfda485a add confirm to book-now-button 2024-09-29 21:28:41 +02:00
=Frederik Jaeckel
7504c676e7 add notify 2024-09-28 20:42:32 +02:00
=Frederik Jaeckel
321aeb827d add button 'execute booking now' 2024-09-28 18:30:43 +02:00
=Frederik Jaeckel
181f7405d6 recurrence: add last-day-of-month 2024-09-27 23:24:48 +02:00
Frederik Jaeckel
18f194caa5 Use 'irrulecontext' to add 'user_id' to context of ir.rule 2024-07-19 16:22:53 +02:00
Frederik Jaeckel
c296db125f update gitignore 2024-07-19 16:22:45 +02:00
Frederik Jaeckel
a84b672250 Add option to rule to move date of occurence to working day 2024-06-03 23:37:26 +02:00
Frederik Jaeckel
e76ec5792c config: new field 'holidays_info' to show generated holidays in config-form 2024-06-02 10:27:15 +02:00
Frederik Jaeckel
b54a8d678f config: compute holidays + test 2024-06-01 23:37:06 +02:00
Frederik Jaeckel
3c65390284 config: allow setting of holidays for each user 2024-06-01 13:33:45 +02:00
Frederik Jaeckel
b5994996de New field 'move_event' for moving occurence-date if not a business day 2024-06-01 13:31:55 +02:00
Frederik Jaeckel
e7bd95ff31 field 'nextrun_link' --> 'nextrun_date', add default-order 2024-03-11 12:50:00 +01:00
Frederik Jaeckel
e1502cae53 add placeholder 'rate' 2024-03-10 22:21:00 +01:00
Frederik Jaeckel
08534047fb fix permissions 2024-03-10 07:45:24 +01:00
9 changed files with 250 additions and 36 deletions

View file

@ -14,26 +14,6 @@ Requires
Changes
=======
*7.0.6 - 19.07.2024*
*7.0.0 - 24.02.2024*
- updt: optimize check of permissions
*7.0.5 - 08.06.2024*
- add: re-arrange date of occurence to working day
*7.0.4 - 11.03.2024*
- add: default-order for table
*7.0.3 - 10.03.2024*
- new placeholder 'rate' for description of booking
*7.0.2 - 10.03.2024*
- fix permissions
*7.0.1 - 09.03.2024*
- works
- init

View file

@ -3,6 +3,18 @@ msgid ""
msgstr "Content-Type: text/plain; charset=utf-8\n"
##############
# ir.message #
##############
msgctxt "model:ir.message,text:msg_title_notify"
msgid "Cashbook Scheduled Booking"
msgstr "Kassenbuch geplante Buchung"
msgctxt "model:ir.message,text:msg_text_notify"
msgid "The following transaction was generated: %(bname)s"
msgstr "Die folgende Buchung wurde erzeugt: %(bname)s"
###########
# ir.cron #
###########
@ -35,6 +47,22 @@ msgid "Scheduled Bookings"
msgstr "geplante Buchungen"
###################
# ir.model.button #
###################
msgctxt "model:ir.model.button,string:book_now_button2"
msgid "Execute Booking Now"
msgstr "Buchung jetzt ausführen"
msgctxt "model:ir.model.button,help:book_now_button2"
msgid "The planned booking is brought forward and executed now. The next posting is then scheduled regularly for the following execution."
msgstr "Die geplante Buchung wird vorgezogen und jetzt ausgeführt. Die nächste Buchung wird dann regulär für die nachfolgende Ausführung geplant."
msgctxt "model:ir.model.button,confirm:book_now_button2"
msgid "The booking is now being made. Continue?"
msgstr "Die Buchung wird nun durchgeführt. Fortsetzen?"
#################
# ir.rule.group #
#################
@ -366,6 +394,22 @@ msgctxt "help:cashbook.planner,move_event:"
msgid "If the date of execution falls on a weekend or holiday, it can be moved to a business day."
msgstr "Wenn das Datum der Ausführung auf ein Wochenende oder Feiertag fällt, kann es auf einen Geschäftstag verschoben werden."
msgctxt "field:cashbook.planner,last_day_of_month:"
msgid "Last day of the month"
msgstr "letzer Tag des Monats"
msgctxt "help:cashbook.planner,last_day_of_month:"
msgid "The booking is made on the last day of the month."
msgstr "Die Buchung wird am letzten Tag des Monats ausgeführt."
msgctxt "field:cashbook.planner,notify_bycron:"
msgid "Notify"
msgstr "Benachrichtigen"
msgctxt "help:cashbook.planner,notify_bycron:"
msgid "A notification will appear in the web browser when the booking has been created."
msgstr "Es wird eine Benachrichtigung im Webbrowser angezeigt wenn die Buchung erstellt wurde."
############################
# cashbook.planner.nextrun #

View file

@ -2,6 +2,14 @@
msgid ""
msgstr "Content-Type: text/plain; charset=utf-8\n"
msgctxt "model:ir.message,text:msg_title_notify"
msgid "Cashbook Scheduled Booking"
msgstr "Cashbook Scheduled Booking"
msgctxt "model:ir.message,text:msg_text_notify"
msgid "The following transaction was generated: %(bname)s"
msgstr "The following transaction was generated: %(bname)s"
msgctxt "selection:ir.cron,method:"
msgid "Execute scheduled bookings"
msgstr "Execute scheduled bookings"
@ -18,6 +26,18 @@ msgctxt "model:ir.action,name:act_planner_view"
msgid "Scheduled Bookings"
msgstr "Scheduled Bookings"
msgctxt "model:ir.model.button,string:book_now_button2"
msgid "Execute Booking Now"
msgstr "Execute Booking Now"
msgctxt "model:ir.model.button,help:book_now_button2"
msgid "The planned booking is brought forward and executed now. The next posting is then scheduled regularly for the following execution."
msgstr "The planned booking is brought forward and executed now. The next posting is then scheduled regularly for the following execution."
msgctxt "model:ir.model.button,confirm:book_now_button2"
msgid "The booking is now being made. Continue?"
msgstr "The booking is now being made. Continue?"
msgctxt "model:ir.rule.group,name:rg_planner_admin"
msgid "Administrators: scheduled bookings read/write"
msgstr "Administrators: scheduled bookings read/write"
@ -338,6 +358,22 @@ msgctxt "help:cashbook.planner,move_event:"
msgid "If the date of execution falls on a weekend or holiday, it can be moved to a business day."
msgstr "If the date of execution falls on a weekend or holiday, it can be moved to a business day."
msgctxt "field:cashbook.planner,last_day_of_month:"
msgid "Last day of the month"
msgstr "Last day of the month"
msgctxt "help:cashbook.planner,last_day_of_month:"
msgid "The booking is made on the last day of the month."
msgstr "The booking is made on the last day of the month."
msgctxt "field:cashbook.planner,notify_bycron:"
msgid "Notify"
msgstr "Notify"
msgctxt "help:cashbook.planner,notify_bycron:"
msgid "A notification will appear in the web browser when the booking has been created."
msgstr "A notification will appear in the web browser when the booking has been created."
msgctxt "model:cashbook.planner.nextrun,name:"
msgid "Next Execution Date"
msgstr "Next Execution Date"
@ -374,3 +410,7 @@ msgctxt "view:cashbook.line:"
msgid "Scheduled Bookings"
msgstr "Scheduled Bookings"
msgctxt "field:cashbook.line,planners:"
msgid "Scheduled Bookings"
msgstr "Scheduled Bookings"

16
message.xml Normal file
View file

@ -0,0 +1,16 @@
<?xml version="1.0"?>
<!-- This file is part of the cashbook-planner from m-ds for Tryton.
The COPYRIGHT file at the top level of this repository contains the
full copyright notices and license terms. -->
<tryton>
<data>
<record model="ir.message" id="msg_title_notify">
<field name="text">Cashbook Scheduled Booking</field>
</record>
<record model="ir.message" id="msg_text_notify">
<field name="text">The following transaction was generated: %(bname)s</field>
</record>
</data>
</tryton>

View file

@ -14,6 +14,7 @@ from trytond.pool import Pool
from trytond.report import Report
from trytond.i18n import gettext
from trytond.pyson import Eval, Bool, If, And
from trytond.bus import notify
from trytond.modules.currency.fields import Monetary
from trytond.modules.cashbook.book import sel_state_book
from trytond.modules.cashbook.line import sel_bookingtype as sel_bookingtype_cb
@ -91,7 +92,14 @@ class ScheduledBooking(DeactivableMixin, ModelSQL, ModelView):
[('monthday', '>=', 1), ('monthday', '<=', 31)],
('monthday', '=', None))],
depends=['weekday', 'frequ'],
states={'required': COND_MONTHDAY, 'invisible': ~COND_MONTHDAY})
states={
'required': And(COND_MONTHDAY, ~Eval('last_day_of_month', False)),
'invisible': ~And(
COND_MONTHDAY, ~Eval('last_day_of_month', False))})
last_day_of_month = fields.Boolean(
string='Last day of the month', depends=['weekday', 'frequ'],
help='The booking is made on the last day of the month.',
states={'invisible': ~COND_MONTHDAY})
interval = fields.Integer(
string='Interval', required=True,
help='Select an interval to run the rule on every n-th date.',
@ -110,6 +118,9 @@ class ScheduledBooking(DeactivableMixin, ModelSQL, ModelView):
string='If no business day', required=True, selection=SEL_MOVE_EVENT,
help='If the date of execution falls on a weekend or holiday, ' +
'it can be moved to a business day.')
notify_bycron = fields.Boolean(
string='Notify', help='A notification will appear in the web ' +
'browser when the booking has been created.')
bookingtype = fields.Selection(
string='Type', selection=sel_bookingtype, required=True,
@ -180,8 +191,10 @@ class ScheduledBooking(DeactivableMixin, ModelSQL, ModelView):
Index(
t,
(t.end_date, Index.Range(order='ASC')),
where=t.end_date != DEF_NONE),
})
where=t.end_date != DEF_NONE)})
cls._buttons.update({
'book_now': {'readonly': ~Eval('active', False)},
})
def get_rec_name(self, name=None):
""" get formatted name of record
@ -263,6 +276,8 @@ class ScheduledBooking(DeactivableMixin, ModelSQL, ModelView):
count = 5
count = 1 if count < 1 else 100 if count > 100 else count
last_day_of_month = params.get(
'last_day_of_month', self.last_day_of_month)
end_date = params.get('end_date', self.end_date)
frequ = pfrequ[params.get('frequ', self.frequ)]
@ -283,6 +298,18 @@ class ScheduledBooking(DeactivableMixin, ModelSQL, ModelView):
interval = 1
interval = 1 if interval < 1 else 10 if interval > 10 else interval
# last-day-of-month: set date short before end of month,
# then compute move result to end of month
updt_lastday = False
if last_day_of_month and (frequ == MONTHLY) and not pweekday:
monthday = 28
updt_lastday = True
lastday_valid = last_day_of_month and (
frequ == MONTHLY) and (pweekday is None)
assert (lastday_valid or not last_day_of_month), \
('last-day-of-month can only be used with frequ=month ' +
'and weekday=99.')
assert (monthday is None) or (pweekday is None), \
"weekday and monthday cannot be used together"
@ -297,7 +324,12 @@ class ScheduledBooking(DeactivableMixin, ModelSQL, ModelView):
for x in dtrule:
if (query_date and (x.date() >= query_date)) or \
(query_date is None):
x_date = get_moved_date(x.date(), move_event)
x_date = x.date()
if updt_lastday:
x_date = (
(x_date + timedelta(days=5)).replace(day=1) -
timedelta(days=1))
x_date = get_moved_date(x_date, move_event)
# if date was re-arranged backwards and we are before
# query_date - skip it
@ -368,7 +400,7 @@ class ScheduledBooking(DeactivableMixin, ModelSQL, ModelView):
@fields.depends(
'start_date', 'end_date', 'frequ', 'weekday', 'monthday',
'interval', 'setpos', 'move_event')
'interval', 'setpos', 'move_event', 'last_day_of_month')
def on_change_with_nextdates(self, name=None):
""" Calculates the next 5 appointments based on the configured rule,
returns a formatted date list
@ -401,7 +433,8 @@ class ScheduledBooking(DeactivableMixin, ModelSQL, ModelView):
'weekday': self.weekday,
'monthday': self.monthday,
'interval': self.interval,
'setpos': self.setpos}
'setpos': self.setpos,
'last_day_of_month': self.last_day_of_month}
)])
@fields.depends('cashbook', '_parent_cashbook.owner')
@ -428,26 +461,33 @@ class ScheduledBooking(DeactivableMixin, ModelSQL, ModelView):
elif self.bookingtype in ['mvin', 'mvout']:
self.category = None
@fields.depends('frequ', 'setpos', 'weekday', 'monthday')
@fields.depends(
'frequ', 'setpos', 'weekday', 'monthday', 'last_day_of_month')
def on_change_frequ(self):
""" update fields
"""
if self.frequ and self.frequ == 'month':
if self.weekday:
if self.weekday == '99':
if self.monthday is None:
self.monthday = 1
if self.last_day_of_month:
self.monthday = None
else:
if self.monthday is None:
self.monthday = 1
self.setpos = None
else:
if self.setpos is None:
self.setpos = 1
self.monthday = None
self.last_day_of_month = False
else:
self.setpos = None
self.monthday = None
self.weekday = '99'
self.last_day_of_month = False
@fields.depends('frequ', 'setpos', 'weekday', 'monthday')
@fields.depends(
'frequ', 'setpos', 'weekday', 'monthday', 'last_day_of_month')
def on_change_weekday(self):
""" clear day-of-month if weekday is used
"""
@ -546,6 +586,15 @@ class ScheduledBooking(DeactivableMixin, ModelSQL, ModelView):
"""
return 1
@classmethod
def default_last_day_of_month(cls):
""" get default for last-day-of-month
Returns:
boolean: False
"""
return False
@classmethod
def default_frequ(cls):
""" get default for frequency
@ -569,6 +618,15 @@ class ScheduledBooking(DeactivableMixin, ModelSQL, ModelView):
IrDate = Pool().get('ir.date')
return IrDate.today()
@classmethod
def default_notify_bycron(cls):
""" get False as default
Returns:
boolean: False
"""
return False
@classmethod
def fill_placeholder(cls, linedata):
""" replace placeholder in description
@ -687,6 +745,20 @@ class ScheduledBooking(DeactivableMixin, ModelSQL, ModelView):
if to_write:
NextRun.write(*to_write)
@classmethod
@ModelView.button
def book_now(cls, records):
""" run planned booking now
"""
to_work = [x for x in records if x.active and x.nextrun_date]
cls.run_booking(to_work)
for record in to_work:
if record.active:
cls.update_next_occurence(
[record],
query_date=record.nextrun_date + timedelta(days=1))
@classmethod
def create(cls, vlist):
""" update nextrun-records on create of planner-records
@ -784,11 +856,27 @@ class ScheduledBooking(DeactivableMixin, ModelSQL, ModelView):
else:
to_create.append(line)
to_notify = []
if to_create_check:
lines = Line.create(to_create_check)
Line.wfcheck(lines)
to_notify.extend([
x for x in lines
if x.planners[0].notify_bycron])
if to_create:
Line.create(to_create)
lines = Line.create(to_create)
to_notify.extend([
x for x in lines
if x.planners[0].notify_bycron])
for line in to_notify:
notify(
title=gettext('cashbook_planner.msg_title_notify'),
body=gettext(
'cashbook_planner.msg_text_notify',
bname=line.rec_name),
user=line.cashbook.owner.id)
@classmethod
def cronjob(cls):

View file

@ -157,5 +157,18 @@ full copyright notices and license terms. -->
<field name="rule_group" ref="rg_planner_companies"/>
</record>
<!-- button -->
<record model="ir.model.button" id="book_now_button2">
<field name="name">book_now</field>
<field name="string">Execute Booking Now</field>
<field name="confirm">The booking is now being made. Continue?</field>
<field name="help">The planned booking is brought forward and executed now. The next posting is then scheduled regularly for the following execution.</field>
<field name="model" search="[('model', '=', 'cashbook.planner')]"/>
</record>
<record model="ir.model.button-res.group" id="book_now_button2-group_planner">
<field name="button" ref="book_now_button2"/>
<field name="group" ref="group_planner"/>
</record>
</data>
</tryton>

View file

@ -245,6 +245,17 @@ class PlannerTestCase(object):
[date(2022, 5, 11), date(2022, 6, 8), date(2022, 7, 13),
date(2022, 8, 10), date(2022, 9, 14), date(2022, 10, 12)])
# last day of month
self.assertEqual(
job._compute_dates_by_rrule(
query_date=date(2022, 5, 1), count=6,
params={
'weekday': '99', 'end_date': None, 'frequ': 'month',
'interval': 1, 'setpos': None, 'monthday': None,
'last_day_of_month': True}),
[date(2022, 5, 31), date(2022, 6, 30), date(2022, 7, 31),
date(2022, 8, 31), date(2022, 9, 30), date(2022, 10, 31)])
# set up holidays
cfg1 = Config(
holidays='01-01;05-01;easter:+1;easter:-2;ascension;whitsun:+1')
@ -377,6 +388,23 @@ class PlannerTestCase(object):
'setpos': 5, 'monthday': None, 'weekday': '2',
'end_date': None}])
@with_transaction()
def test_planner_run_booking_now(self):
""" create job, press button 'booknow'
"""
Planner = Pool().get('cashbook.planner')
job = self.prep_create_job()
self.assertEqual(
job.rec_name, "Job 1|Book 1|Exp|Cat1|05/01/2022|usd0.00")
self.assertEqual(
job._compute_dates_by_rrule(
count=1, query_date=date(2022, 5, 1)), [
date(2022, 5, 1)])
Planner.book_now([job])
self.assertEqual(
job.rec_name, "Job 1|Book 1|Exp|Cat1|06/01/2022|usd0.00")
@with_transaction()
def test_planner_create_update_nextrun(self):
""" create job, check nextrun-record

View file

@ -1,10 +1,11 @@
[tryton]
version=7.0.6
version=7.0.0
depends:
cashbook
extras_depend:
cashbook_investment
xml:
message.xml
group.xml
planner.xml
nextrun.xml

View file

@ -12,8 +12,9 @@ full copyright notices and license terms. -->
<label name="active"/>
<field name="active"/>
<label name="nextrun_date" colspan="5"/>
<label name="nextrun_date" colspan="3"/>
<field name="nextrun_date"/>
<button colspan="2" name="book_now"/>
<notebook colspan="6">
<page id="rrule" col="6" string="Recurrence Rule">
@ -34,6 +35,8 @@ full copyright notices and license terms. -->
<field name="weekday"/>
<label name="monthday"/>
<field name="monthday"/>
<label name="last_day_of_month"/>
<field name="last_day_of_month"/>
<label name="move_event"/>
<field name="move_event"/>
@ -58,7 +61,8 @@ full copyright notices and license terms. -->
<label name="wfcheck"/>
<field name="wfcheck"/>
<newline/>
<label name="notify_bycron"/>
<field name="notify_bycron"/>
<separator name="subject" colspan="4" string="Booking text"/>
<field name="subject" colspan="4"/>