diff --git a/README.md b/README.md index 8b9aa33..da9247f 100644 --- a/README.md +++ b/README.md @@ -15,15 +15,15 @@ Once a specific document is generated for signing or publication the content is { "data": { "type": "extract-preview", - }, - "relationships": { - "treatment": { - "data": { - "id": "{{treatmentUuid}}", - "type": "behandeling-van-agendapunt" + "relationships": { + "treatment": { + "data": { + "id": "{{treatmentUuid}}", + "type": "behandeling-van-agendapunt" + } } } - } + } } ``` ## creating a signed document diff --git a/models/custom-vote.js b/models/custom-vote.js new file mode 100644 index 0000000..83debdd --- /dev/null +++ b/models/custom-vote.js @@ -0,0 +1,50 @@ +import { prefixMap } from '../support/prefixes'; +// @ts-ignore +import { sparqlEscapeUri, query } from 'mu'; + +export default class CustomVote { + static async findAll({ treatmentUri }) { + try { + const result = await query(` + ${prefixMap.get('besluit').toSparqlString()} + ${prefixMap.get('schema').toSparqlString()} + ${prefixMap.get('ext').toSparqlString()} + ${prefixMap.get('pav').toSparqlString()} + ${prefixMap.get('gn').toSparqlString()} + SELECT DISTINCT * WHERE { + ${sparqlEscapeUri(treatmentUri)} a besluit:BehandelingVanAgendapunt; + gn:heeftAangepasteStemming ?uri. + ?uri a gn:AangepasteStemming; + schema:position ?position; + ext:votingDocument ?documentContainer. + ?documentContainer pav:hasCurrentVersion ?editorDocument . + ?editorDocument ext:editorDocumentContent ?content; + ext:editorDocumentContext ?context. + }ORDER BY ASC(?position) + `); + return result.results.bindings.map((binding) => + CustomVote.fromBinding(binding) + ); + } catch (e) { + console.log(e); + throw `failed to fetch custom votes for treatment ${treatmentUri}`; + } + } + + static fromBinding({ uri, position, content, context }) { + return new CustomVote({ + uri: uri.value, + position: position.value, + content: content.value, + context: context.value, + }); + } + + constructor({ uri, position, content, context }) { + this.type = 'customVote'; + this.uri = uri; + this.position = position; + this.content = content; + this.context = context; + } +} diff --git a/models/vote.js b/models/standard-vote.js similarity index 96% rename from models/vote.js rename to models/standard-vote.js index 445fd0c..0b6cc71 100644 --- a/models/vote.js +++ b/models/standard-vote.js @@ -4,7 +4,7 @@ import { sparqlEscapeUri, query } from 'mu'; import { whoVotesBasedOnClassifcationMap } from '../support/classification-utils'; import { sortMandatees } from '../support/query-utils'; -export default class Vote { +export default class StandardVote { static async findAll({ treatmentUri }) { try { const result = await query(` @@ -31,11 +31,11 @@ export default class Vote { } ORDER BY ASC(?position) `); return result.results.bindings.map((binding) => - Vote.fromBinding(binding) + StandardVote.fromBinding(binding) ); } catch (e) { console.log(e); - throw `failed to fetch votes for treatment ${treatmentUri}`; + throw `failed to fetch standard votes for treatment ${treatmentUri}`; } } @@ -50,7 +50,7 @@ export default class Vote { position, adminBodyClassification, }) { - return new Vote({ + return new StandardVote({ uri: uri.value, subject: subject.value, result: result.value, @@ -79,6 +79,7 @@ export default class Vote { position, adminBodyClassification, }) { + this.type = 'standardVote'; this.uri = uri; this.subject = subject; this.result = result; diff --git a/models/versioned-notulen.js b/models/versioned-notulen.js index ec504ef..155a732 100644 --- a/models/versioned-notulen.js +++ b/models/versioned-notulen.js @@ -30,8 +30,6 @@ export default class VersionedNotulen { const bindings = r.results.bindings; if (bindings.length > 0) { const binding = bindings[0]; - - console.log(binding); const fileUri = bindings.fileUri?.value; let html; if (fileUri) { diff --git a/support/besluit-exporter.js b/support/besluit-exporter.js index 3d17a77..3a5b3b8 100644 --- a/support/besluit-exporter.js +++ b/support/besluit-exporter.js @@ -9,7 +9,8 @@ import { prefixes } from './prefixes'; import Meeting from '../models/meeting'; import Treatment from '../models/treatment'; import Decision from '../models/decision'; -import Vote from '../models/vote'; +import StandardVote from '../models/standard-vote'; +import CustomVote from '../models/custom-vote'; export async function buildBesluitenLijstForMeetingId(meetingUuid) { const meeting = await Meeting.find(meetingUuid); @@ -40,7 +41,12 @@ async function addDecisionsToTreatment(treatment) { } async function addVotesToTreatment(treatment) { - const votes = await Vote.findAll({ treatmentUri: treatment.uri }); + const standardVotes = await StandardVote.findAll({ + treatmentUri: treatment.uri, + }); + const customVotes = await CustomVote.findAll({ treatmentUri: treatment.uri }); + const votes = [...standardVotes, ...customVotes]; + votes.sort((a, b) => a.position - b.position); if (votes.length > 0) { // this makes it easier to check if there are votes in the template treatment.votes = votes; diff --git a/support/extract-utils.js b/support/extract-utils.js index 7acf0c9..1d52c69 100644 --- a/support/extract-utils.js +++ b/support/extract-utils.js @@ -1,7 +1,8 @@ import Treatment from '../models/treatment'; import AgendaPoint from '../models/agendapoint'; import Meeting from '../models/meeting'; -import Vote from '../models/vote'; +import StandardVote from '../models/standard-vote'; +import CustomVote from '../models/custom-vote'; import Decision from '../models/decision'; // @ts-ignore import { query, sparqlEscapeUri, update } from 'mu'; @@ -120,10 +121,19 @@ export async function buildExtractDataForTreatment( participantCache = buildParticipantCache(participationList); } } - const votes = await Vote.findAll({ treatmentUri: treatment.uri }); + const standardVotes = await StandardVote.findAll({ + treatmentUri: treatment.uri, + }); + const customVotes = await CustomVote.findAll({ treatmentUri: treatment.uri }); + const votes = [...standardVotes, ...customVotes]; + votes.sort((a, b) => a.position - b.position); if (participationList && participationList.present.length > 0) { // only try fetching voters if people were present - await Promise.all(votes.map((vote) => vote.fetchVoters(participantCache))); + await Promise.all( + votes.map((vote) => + vote.type === 'customVote' ? vote : vote.fetchVoters(participantCache) + ) + ); } let content; if (isPublic) { diff --git a/support/prefixes.js b/support/prefixes.js index 8d1f4e4..ec6617c 100644 --- a/support/prefixes.js +++ b/support/prefixes.js @@ -68,7 +68,8 @@ const prefixMap = new Map([ ["notulen", new Prefix("notulen", "http://lblod.data.gift/vocabularies/notulen/")], ["nfo", new Prefix("nfo", "http://www.semanticdesktop.org/ontologies/2007/03/22/nfo#")], ["nie", new Prefix("nie", "http://www.semanticdesktop.org/ontologies/2007/01/19/nie#")], - ["dbpedia", new Prefix("dbpedia", "http://dbpedia.org/ontology/")] + ["dbpedia", new Prefix("dbpedia", "http://dbpedia.org/ontology/")], + ["gn", new Prefix("gn", "http://data.lblod.info/vocabularies/gelinktnotuleren/")] ]); export { prefixes, prefixMap }; diff --git a/support/setup-handlebars.js b/support/setup-handlebars.js index 8c11570..04066ac 100644 --- a/support/setup-handlebars.js +++ b/support/setup-handlebars.js @@ -48,4 +48,8 @@ function registerHelpers() { Handlebars.registerHelper('inc', (value) => { return parseInt(value) + 1; }); + + Handlebars.registerHelper('eq', (variable, value) => { + return variable === value; + }); } diff --git a/support/templates/partials/treatment.hbs b/support/templates/partials/treatment.hbs index b314017..89bc382 100644 --- a/support/templates/partials/treatment.hbs +++ b/support/templates/partials/treatment.hbs @@ -48,50 +48,57 @@
- {{#if this.isSecret}} - {{this.whoVotesPhrase}} geheim - {{else}} - {{this.whoVotesPhrase}} openbaar - {{/if}} -
-{{this.subject}}
- {{> mandateeList mandatees=this.attendees property="besluit:heeftAanwezige" title="Aanwezigen tijdens de stemming" includeRole=false}} - {{> mandateeList mandatees=this.voters property="besluit:heeftStemmer" title="Effectieve stemmers" includeRole=false}} - {{#if this.isUnanimous}} - - - - {{#unless this.geheim}} - {{> mandateeList mandatees=this.positiveVoters property="besluit:heeftVoorstander" title="Voorstanders" includeRole=false hideText=true}} - {{> mandateeList mandatees=this.negativeVoters property="besluit:heeftTegenstander" title="Tegenstanders" includeRole=false hideText=true}} - {{> mandateeList mandatees=this.abstentionVoters property="besluit:heeftOnthouders" title="Onthoudingen, blanco of ongeldig" includeRole=false hideText=true}} - {{/unless}} -{{this.result}}, met eenparigheid van stemmen
- {{else}} -- Totaal aantal voorstanders: - {{this.positiveVotes}} -
-- Totaal aantal tegenstanders: - {{this.negativeVotes}} -
-- Totaal aantal onthoudingen, blanco of ongeldig: - {{this.abstentionVotes}} -
- {{#unless this.geheim}} - {{> mandateeList mandatees=this.positiveVoters property="besluit:heeftVoorstander" title="Voorstanders" includeRole=false}} - {{> mandateeList mandatees=this.negativeVoters property="besluit:heeftTegenstander" title="Tegenstanders" includeRole=false}} - {{> mandateeList mandatees=this.abstentionVoters property="besluit:heeftOnthouders" title="Onthoudingen, blanco of ongeldig" includeRole=false}} - {{/unless}} -Met als gevolg,
-{{this.result}}
+ {{#if (eq this.type "standardVote")}} ++ {{#if this.isSecret}} + {{this.whoVotesPhrase}} geheim + {{else}} + {{this.whoVotesPhrase}} openbaar + {{/if}} +
+{{this.subject}}
+ {{> mandateeList mandatees=this.attendees property="besluit:heeftAanwezige" title="Aanwezigen tijdens de stemming" includeRole=false}} + {{> mandateeList mandatees=this.voters property="besluit:heeftStemmer" title="Effectieve stemmers" includeRole=false}} + {{#if this.isUnanimous}} + + + + {{#unless this.geheim}} + {{> mandateeList mandatees=this.positiveVoters property="besluit:heeftVoorstander" title="Voorstanders" includeRole=false hideText=true}} + {{> mandateeList mandatees=this.negativeVoters property="besluit:heeftTegenstander" title="Tegenstanders" includeRole=false hideText=true}} + {{> mandateeList mandatees=this.abstentionVoters property="besluit:heeftOnthouders" title="Onthoudingen, blanco of ongeldig" includeRole=false hideText=true}} + {{/unless}} +{{this.result}}, met eenparigheid van stemmen
+ {{else}} ++ Totaal aantal voorstanders: + {{this.positiveVotes}} +
++ Totaal aantal tegenstanders: + {{this.negativeVotes}} +
++ Totaal aantal onthoudingen, blanco of ongeldig: + {{this.abstentionVotes}} +
+ {{#unless this.geheim}} + {{> mandateeList mandatees=this.positiveVoters property="besluit:heeftVoorstander" title="Voorstanders" includeRole=false}} + {{> mandateeList mandatees=this.negativeVoters property="besluit:heeftTegenstander" title="Tegenstanders" includeRole=false}} + {{> mandateeList mandatees=this.abstentionVoters property="besluit:heeftOnthouders" title="Onthoudingen, blanco of ongeldig" includeRole=false}} + {{/unless}} +Met als gevolg,
+{{this.result}}
+ {{/if}} + +