In collective collectionfilter, I want to have some options, for example:
Within next 7 days
7--14 dayd
14--28 days
Any advice on how to do this?
My first thought is to have a cron job calculating duedate-today every day an updating all the content (and/or the index).
Are there any other ways of doing it?
Will 'history' be a problem (to many versions?/database size?)
Alternatively: Could it be done 'withing collective.collectionfilter itself, if so: any suggestions ??'
Just a rough idea:
Make a method which calculates the "due range value" of the context depending on your due date. Register this method as indexer on your type and define index/metadata in the catalog.
Create a cronjob that iters through your content and updates the catalog like this:
this udpates the catalog indexes withoug notify the modified event on the object (no history entry). I once found this somewhere in a Zope documentation but could not find it anymore. But I've used this just recently in a sync method of us and it still works.
UPDATE on suppress_notifyModified: a quick grep through Products.CMFCore shows, that this is some kind of "hidden hack" because the notify event is only fired if idxs is None. If you then provide an "unknown" index, you skip the modified event and it gets stripped later in the code.
@yurj the "index modifier" in the adapter is for modifying the input value for the catalog query. You cannot modify the "filteritems list" inside the adapter. To get the "range" values above you need to index them first in the catalog. To me it's more a indexing/updating problem than a collectionfilter problem.
Thanks for the answer:
I thought that a field with the same name as the index (name) had to be present for c.collectionfilter to 'work'. If so, I probably still have to update the field (value) ? If so, maybe I can make the field a calculated value (?)
Correct, but you do not have to make the "field" a calculated value. you only have to (re)calculate the catalog index/metadata (which, as you said correctly, has to have the same name in order to work with collectionfilter) with your needed due date range.
Example:
Today is 2023-08-04
Your content has due_date="2023-08-15"
Your indexer would calculates the due range value as let's say between_7_and_14_days ... this value can be translated via locales so that collectionfilter shows the human readable Between 7 and 14 days ... default behavior is translation via i18n_domain "collective.collectionfilter" ... you can use your own groupy_modifier adapter to translate to your needs.
if you recalc the index daily, the indexer logic should change the value on the 9th Aug to within_7_days and on 16th Aug to "overdue"
How about approaching this from a workflow perspective? I would research the tools that we already have to publish and retract documents based on publication date and expiration date. Your "due date" could be a "due status" that is assigned based on your criteria above.
Collectionfilter first fetches the catalog metadata with catalog.schema() and filters out any blacklisted ids. Then it iterates through them and looks for the index with the same id. If not present -> skip. So you do not need any content field but only catalog metadata/indexes for collectionfilter to work.
Index the date your want to compare to, then add an operation for each of the filter.
Add a collection page for each of the ranges. Or, if you have something like mosaic or Volto add a collection listing block (or something like that).
Or you can make a custom view which renders multiple collections on a single page.
ps I'm sorry for how confusing the relative dates stuff is.
You are absolutely right, I dont need a field (value).
I added the indexer so I dont have any problems with history / versions:
@indexer(IDexterityContainer) # ADJUST THIS!
def daysleftIndexer(obj):
"""Calculate and return the value for the indexer"""
due_date = obj.duedate or None
# difference between dates in timedelta
#if due_date != None:
if due_date:
delta = due_date - datetime.date.today()
if delta.days<1:
return '0 - Out of time'
if delta.days<=7:
return '1 – Less than 7'
if delta.days<=14:
return '2 - Less than 14'
return '3 - More than 15'
return None
All I need now is the cron job (alternatively a view that can be called 'each night.
UPDATE ( 07 aug. 2023): Slightly off topic: I remember that I did something similar, a long, long time ago ( for a job that was never finished).
An option is this
When adding a date, add TWO indexes
Index due_date_min
Index due_date_max
Using TWO collectionfilter portlets, it is now possible to get 'from 7 day to 13'
Both indexes needs to be a list of numbers, maybe KeyWord-index (cant remember exactly how, but know it is possible)