Skip to content

Commit

Permalink
Merge pull request #1583 from laws-africa/partial-commencement
Browse files Browse the repository at this point in the history
Partial commencements
  • Loading branch information
goose-life authored Oct 23, 2023
2 parents fb9f2f2 + 27eafba commit b809222
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 193 deletions.
2 changes: 2 additions & 0 deletions peachjam/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -652,6 +652,8 @@ class LegislationAdmin(ImportExportMixin, DocumentAdmin):
fieldsets = copy.deepcopy(DocumentAdmin.fieldsets)
fieldsets[0][1]["fields"].extend(["nature"])
fieldsets[3][1]["fields"].extend(["metadata_json"])
fieldsets[3][1]["fields"].extend(["commencements_json"])
fieldsets[3][1]["fields"].extend(["timeline_json"])
fieldsets[2][1]["classes"] = ("collapse",)
fieldsets[4][1]["fields"].extend(["parent_work"])
readonly_fields = ["parent_work"] + list(DocumentAdmin.readonly_fields)
Expand Down
113 changes: 32 additions & 81 deletions peachjam/templates/peachjam/_timeline_events.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,91 +4,42 @@ <h4>
{% trans 'History of this document' %}
</h4>
<div class="vertical-timeline ms-5 mt-4">
{% if timeline %}
{% for entry in timeline %}
<div class="vertical-timeline__item">
<div class="card mb-3">
<div class="card-header">
<h5 class="mb-0">
{{ entry.date|parse_string_date|date:"d F Y" }}
{% if entry.date == current_object_date %}
<span class="badge rounded-pill bg-primary">{% trans 'this version' %}</span>
{% endif %}
{% if entry.contains_unapplied_amendment %}
<span class="badge rounded-pill bg-secondary">{% trans 'amendment not yet applied' %}</span>
{% endif %}
</h5>
</div>
<div class="card-body">
{% for event in entry.events %}
<div>
{% if event.type == "publication" %}
{% if event.link_url %}
<a href="{{ event.link_url }}">{{ event.description }}</a>
{% else %}
{{ event.description }}
{% endif %}
{% else %}
{{ event.description }}
{% if event.by_frbr_uri %}<a href="{{ event.by_frbr_uri }}">{{ event.by_title }}</a>{% endif %}
{% endif %}
{% if event.note %}<p>{{ event.note }}</p>{% endif %}
</div>
{% endfor %}
{% if entry.date != current_object_date and entry.expression_frbr_uri %}
<a class="btn btn-outline-primary mt-2"
href="{{ entry.expression_frbr_uri }}">{% trans 'Read this version' %}</a>
{% for entry in timeline %}
<div class="vertical-timeline__item">
<div class="card mb-3">
<div class="card-header">
<h5 class="mb-0">
{{ entry.date|parse_string_date|date:"d F Y" }}
{% if entry.date == current_object_date %}
<span class="badge rounded-pill bg-primary">{% trans 'this version' %}</span>
{% endif %}
{% if entry.contains_unapplied_amendment %}
<span class="badge rounded-pill bg-secondary">{% trans 'amendment not yet applied' %}</span>
{% endif %}
</div>
</h5>
</div>
</div>
{% endfor %}
{% else %}
{# TODO: get rid of timeline_events once all Legislation objects have been re-ingested #}
{% for history_item in timeline_events %}
<div class="vertical-timeline__item">
<div class="card mb-3">
<div class="card-header">
<h5 class="mb-0">
{{ history_item.date|parse_string_date|date:"d F Y" }}
{% if history_item.date == current_object_date %}
<span class="badge rounded-pill bg-primary">{% trans 'this version' %}</span>
{% endif %}
{% for event in history_item.events %}
{% if event.unapplied_amendment %}
<span class="badge rounded-pill bg-secondary">{% trans 'amendment not yet applied' %}</span>
{% endif %}
{% endfor %}
</h5>
</div>
<div class="card-body">
{% for event in history_item.events %}
<div>
{% if event.event == "amendment" %}
{% trans 'Amended by' %}
<a href="{{ event.amending_uri }}"><i>{{ event.amending_title }}</i></a>
{% elif event.event == "assent" %}
{% trans 'Assented to' %}.
{% elif event.event == "commencement" %}
{% trans 'Commences' %}.
{% elif event.event == "publication" %}
{% trans 'Published in' %}
<a href="{{ event.publication_url }}">{{ event.publication_name }} {% trans 'number' %} {{ event.publication_number }}</a>
{% elif event.event == "repeal" %}
{% trans 'Repealed by' %}
<a href="{{ event.repealing_uri }}"><i>{{ event.repealing_title }}</i></a>
<div class="card-body">
{% for event in entry.events %}
<div>
{% if event.type == "publication" %}
{% if event.link_url %}
<a href="{{ event.link_url }}">{{ event.description }}</a>
{% else %}
{{ event.description }}
{% endif %}
</div>
{% endfor %}
{% if history_item.date != current_object_date %}
{% if history_item.expression_frbr_uri %}
<a class="btn btn-outline-primary mt-2"
href="{{ history_item.expression_frbr_uri }}">{% trans 'Read this version' %}</a>
{% else %}
{{ event.description }}
{% if event.by_frbr_uri %}<a href="{{ event.by_frbr_uri }}">{{ event.by_title }}</a>{% endif %}
{% endif %}
{% endif %}
</div>
{% if event.note %}<p>{{ event.note }}</p>{% endif %}
</div>
{% endfor %}
{% if entry.date != current_object_date and entry.expression_frbr_uri %}
<a class="btn btn-outline-primary mt-2"
href="{{ entry.expression_frbr_uri }}">{% trans 'Read this version' %}</a>
{% endif %}
</div>
</div>
{% endfor %}
{% endif %}
</div>
{% endfor %}
</div>
134 changes: 22 additions & 112 deletions peachjam/views/legislation.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
from datetime import datetime, timedelta
from itertools import groupby

from django.contrib import messages
from django.template.defaultfilters import date as format_date
Expand Down Expand Up @@ -30,8 +29,6 @@ def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context["current_object_date"] = self.object.date.strftime("%Y-%m-%d")
context["timeline"] = self.get_timeline()
# TODO: get rid of timeline_events once all Legislation objects have been re-ingested
context["timeline_events"] = self.get_timeline_events()
context["friendly_type"] = self.get_friendly_type()
context["notices"] = self.get_notices()
context["child_documents"] = self.get_child_documents()
Expand All @@ -41,7 +38,7 @@ def get_notices(self):
notices = super().get_notices()
repeal = self.get_repeal_info()
friendly_type = self.get_friendly_type()
commenced = self.get_commencement_info()
commenced, commenced_in_full = self.get_commencement_info()

if self.object.metadata_json.get("disclaimer"):
notices.append(
Expand Down Expand Up @@ -74,13 +71,28 @@ def get_notices(self):
notices.append(
{
"type": messages.WARNING,
"html": _("This %(friendly_type)s will commence on %(date)s.")
"html": _(
"This %(friendly_type)s will come into force on %(date)s."
)
% {
"friendly_type": friendly_type,
"date": format_date(latest_commencement_date, "j F Y"),
},
}
)
# don't overwhelm users with commencement notices -- only add this if
# it is commenced in general, AND there isn't also a future commencement
elif not commenced_in_full:
notices.append(
{
"type": messages.WARNING,
"html": _(
"This %(friendly_type)s has not yet come into force in full."
" See the Document detail tab for more information."
)
% {"friendly_type": friendly_type},
}
)

else:
notices.append(
Expand Down Expand Up @@ -187,7 +199,11 @@ def get_work_amendments(self):
return self.object.metadata_json.get("work_amendments", None)

def get_commencement_info(self):
return self.object.metadata_json.get("commenced", None)
"""Returns commenced, commenced_in_full.
commenced_in_full defaults to True.
"""
data = self.object.metadata_json
return data.get("commenced"), data.get("commenced_in_full", True)

def get_latest_commencement_date(self):
commencement_dates = [
Expand Down Expand Up @@ -259,112 +275,6 @@ def get_timeline(self):

return timeline

def get_timeline_events(self):
events = []
work = self.object.metadata_json

assent_date = self.object.metadata_json.get("assent_date", None)
if assent_date:
events.append(
{
"date": work.get("assent_date"),
"event": "assent",
}
)

publication_date = self.object.metadata_json.get("publication_date", None)
if publication_date:
api_url = "https://api.laws.africa/v2/"
commons_url = "https://commons.laws.africa/"
publication_url = (work.get("publication_document") or {}).get("url")
if publication_url and api_url in publication_url:
publication_url = publication_url.replace(api_url, commons_url)

events.append(
{
"date": publication_date,
"event": "publication",
"publication_name": work.get("publication_name"),
"publication_number": work.get("publication_number"),
"publication_url": publication_url,
}
)

commencement_date = self.object.metadata_json.get("commencement_date", None)
if commencement_date:
events.append(
{
"date": commencement_date,
"event": "commencement",
"friendly_type": work.get("type_name"),
}
)

points_in_time = self.get_points_in_time()

amendments = self.get_work_amendments()
if amendments:
point_in_time_dates = [
point_in_time["date"] for point_in_time in points_in_time
]
latest_expression_date = (
max(point_in_time_dates)
if point_in_time_dates
else self.object.date.strftime("%Y-%m-%d")
)

events.extend(
[
{
"date": amendment.get("date"),
"event": "amendment",
"amending_title": amendment.get("amending_title"),
"amending_uri": amendment.get("amending_uri"),
"unapplied_amendment": bool(
amendment.get("date") not in point_in_time_dates
and amendment.get("date") > latest_expression_date
),
}
for amendment in amendments
]
)

repeal = self.get_repeal_info()
if repeal:
events.append(
{
"date": repeal.get("date"),
"event": "repeal",
"repealing_title": repeal.get("repealing_title"),
"repealing_uri": repeal.get("repealing_uri"),
}
)

events.sort(key=lambda event: event["date"])
events = [
{
"date": date,
"events": list(group),
}
for date, group in groupby(events, lambda event: event["date"])
]

# fold in links to expressions corresponding to each event date (if any)
expressions = {
point_in_time["date"]: point_in_time["expressions"][0]
for point_in_time in points_in_time
}
for event in events:
for e in event["events"]:
del e["date"]
uri = expressions.get(event["date"], {}).get("expression_frbr_uri")
if uri:
event["expression_frbr_uri"] = uri

events.sort(key=lambda event: event["date"], reverse=True)

return events

def get_child_documents(self):
docs = (
self.model.objects.filter(parent_work=self.object.work)
Expand Down

0 comments on commit b809222

Please sign in to comment.