diff --git a/docs/_static/i18n.csv b/docs/_static/i18n.csv index d644ce56..45a581b6 100644 --- a/docs/_static/i18n.csv +++ b/docs/_static/i18n.csv @@ -71,7 +71,6 @@ budget/budgetBreakdown/amount,Amount,False, budget/budgetBreakdown/amount,Value,False, budget/budgetBreakdown/amount/amount,Amount,False, budget/budgetBreakdown/amount/currency,Currency,False, -budget/budgetBreakdown/approvalDate,Approval date,False, budget/budgetBreakdown/uri,Linked budget information,False, budget/budgetBreakdown/period,Budget period,False, budget/budgetBreakdown/period,Period,False, @@ -79,10 +78,11 @@ budget/budgetBreakdown/period/startDate,Start date,False, budget/budgetBreakdown/period/endDate,End date,False, budget/budgetBreakdown/period/maxExtentDate,Maximum extent,False, budget/budgetBreakdown/period/durationInDays,Duration (days),False, -budget/budgetBreakdown/sourceParty,Source party,False, +budget/budgetBreakdown/sourceParty,Source organization,False, budget/budgetBreakdown/sourceParty,Organization reference,False, budget/budgetBreakdown/sourceParty/name,Organization name,True, budget/budgetBreakdown/sourceParty/id,Organization ID,True, +budget/budgetBreakdown/approvalDate,Approval date,False, forecasts,Forecasts,False, forecasts,Metric,False, forecasts/id,Identifier,False, @@ -275,6 +275,21 @@ contractingProcesses/summary/transactions/payee,Organization reference,False, contractingProcesses/summary/transactions/payee/name,Organization name,True, contractingProcesses/summary/transactions/payee/id,Organization ID,True, contractingProcesses/summary/transactions/uri,Linked spending information,False, +contractingProcesses/summary/transactions/relatedImplementationMilestone,Related implementation milestone,False, +contractingProcesses/summary/transactions/relatedImplementationMilestone,Milestone Reference,False, +contractingProcesses/summary/transactions/relatedImplementationMilestone/id,Milestone ID,True, +contractingProcesses/summary/transactions/relatedImplementationMilestone/title,Milestone title,True, +contractingProcesses/summary/milestones,Milestones,False, +contractingProcesses/summary/milestones,Milestone,False, +contractingProcesses/summary/milestones/id,ID,True, +contractingProcesses/summary/milestones/title,Title,True, +contractingProcesses/summary/milestones/type,Milestone type,False, +contractingProcesses/summary/milestones/description,Description,True, +contractingProcesses/summary/milestones/code,Milestone code,False, +contractingProcesses/summary/milestones/dueDate,Due date,False, +contractingProcesses/summary/milestones/dateMet,Date met,False, +contractingProcesses/summary/milestones/dateModified,Date modified,False, +contractingProcesses/summary/milestones/status,Status,False, contractingProcesses/releases,Linked releases,False, contractingProcesses/releases,Release,False, contractingProcesses/releases/id,ID,True, @@ -307,6 +322,39 @@ metrics/observations/unit/id,ID,True, metrics/observations/unit/uri,URI,False, metrics/observations/dimensions,Dimensions,False, metrics/observations/notes,Notes,True, +transactions,Transactions,False, +transactions,Transaction information,False, +transactions/id,ID,True, +transactions/source,Data source,False, +transactions/date,Date,False, +transactions/value,Value,False, +transactions/value,Value,False, +transactions/value/amount,Amount,False, +transactions/value/currency,Currency,False, +transactions/payer,Payer,False, +transactions/payer,Organization reference,False, +transactions/payer/name,Organization name,True, +transactions/payer/id,Organization ID,True, +transactions/payee,Payee,False, +transactions/payee,Organization reference,False, +transactions/payee/name,Organization name,True, +transactions/payee/id,Organization ID,True, +transactions/uri,Linked spending information,False, +transactions/relatedImplementationMilestone,Related implementation milestone,False, +transactions/relatedImplementationMilestone,Milestone Reference,False, +transactions/relatedImplementationMilestone/id,Milestone ID,True, +transactions/relatedImplementationMilestone/title,Milestone title,True, +milestones,Milestones,False, +milestones,Milestone,False, +milestones/id,ID,True, +milestones/title,Title,True, +milestones/type,Milestone type,False, +milestones/description,Description,True, +milestones/code,Milestone code,False, +milestones/dueDate,Due date,False, +milestones/dateMet,Date met,False, +milestones/dateModified,Date modified,False, +milestones/status,Status,False, completion,Completion,False, completion/endDate,End date,False, completion/endDateDetails,End date details,True, diff --git a/docs/cost/common.md b/docs/cost/common.md index c50c54a4..0faff9b3 100644 --- a/docs/cost/common.md +++ b/docs/cost/common.md @@ -17,3 +17,8 @@ Add a `Document` object to the `contractingProcesses.summary.documents` array an * Set its `.id` incrementally * Set its `.url` to a direct link to the document * Set its `.title` to the title of the document + +## Add an organization + +* Add an `Organization` object to the `.parties` array and set its `.name` to the name of the organization. +* If you collect organization identifiers, set `.identifier` according to the [identifier reference](../reference/schema.md#identifier) and set `.id` to {identifier.scheme}-{identifier.id}(-{department-identifier}). Otherwise, set `.id` incrementally. diff --git a/docs/cost/ids/sustainability.md b/docs/cost/ids/sustainability.md index fee65d6c..9993e321 100644 --- a/docs/cost/ids/sustainability.md +++ b/docs/cost/ids/sustainability.md @@ -1464,9 +1464,73 @@ Disbursements dates according to financial agreement versus actual disbursements :columns: 8 OC4IDS mapping ^^^ - +For each planned disbursement: + +* If the disbursement relates to a contracting processes, for example a payment from a funder to a supplier or subcontractor of a supplier, get the `ContractingProcess` in the `.contractingProcesses` array to which the disbursement relates and add a `Milestone` object to its `.summary.milestones` array. Otherwise, if the disbursement relates to the project, for example a payment from a funder to the public authority, add a `Milestone` object to the project-level `.milestones` array. +* Set the milestone's: + * `.id` incrementally + * `.status` to 'scheduled' + * `.dueDate` to the date on which the disbursement is planned to occur + * `.type` to 'payment' + * `.value` to the amount and currency of the planned disbursement + +For each actual disbursement: + +* If the disbursement relates to a contracting processes, for example a payment from a funder to a supplier or subcontractor of a supplier, get the `ContractingProcess` in the `.contractingProcesses` array to which the disbursement relates and add a `Transaction` object to its `.summary.transactions` array. Otherwise, if the disbursement relates to the project, for example a payment from a funder to the public authority, add a `Transaction` object to the project-level `.transactions` array. +* Set the transaction's: + * `.id` incrementally + * `.date` to the date of the disbursement + * `.value` to the amount and currency of the disbursement + +* Get the `Organization` in `.parties` that represents the payer. If none exists yet, [add an organization](../common.md#add-an-organization) for the payer: + * Add 'payer' to the organization's `.roles` array + * Set the transaction's `.payer` to the `.id` and `.name` of the organization +* Get the `Organization` in `.parties` that represents the payee. If none exists yet, [add an organization](../common.md#add-an-organization) for the payee: + * Add 'payee' to the organization's `.roles` array. + * Set the transaction's `.payee` to the `.id` and `.name` of the organization +* Get the `Milestone` in `.milestones` that represents that planned disbursement: + * Set its `.status` to 'met' + * Set its `.dateMet` to the date of the disbursement + * Set the transaction's `.relatedImplementationMilestone` to the `.id` and `.title` of the milestone ```json - +{ + "milestones": [ + { + "id": "1", + "title": "Grant disbursement" + "status": "met", + "dueDate": "2023-07-01T00:00:00Z", + "dateMet": "2023-08-01T00:00:00Z", + "type": "payment", + "value": { + "amount": 5000000, + "currency": "USD" + } + } + ], + "transactions": [ + { + "id": "1", + "date": "2023-08-01T00:00:00Z", + "value": { + "amount": 5000000, + "currency": "USD" + }, + "payer": { + "id": "1", + "name": "United Nations Development Programme" + }, + "payee": { + "id": "2", + "name": "Ministry of works" + }, + "relatedImplementationMilestone": { + "id": "1", + "title": "Grant disbursement" + } + } + ] +} ``` ```` diff --git a/docs/examples/blank.json b/docs/examples/blank.json index 4b5c512e..488b17a2 100644 --- a/docs/examples/blank.json +++ b/docs/examples/blank.json @@ -309,6 +309,23 @@ }, "uri": "string" } + ], + "milestones": [ + { + "id": "string", + "title": "string", + "type": "string from milestoneType codelist", + "description": "string", + "code": "string from milestoneCode codelist", + "dueDate": "string", + "dateMet": "string", + "dateModified": "string", + "status": "string from milestoneStatus codelist", + "relatedImplementationMilestone": { + "id": "string", + "title": "title" + } + } ] }, "releases": [ @@ -352,6 +369,43 @@ ] } ], + "transactions": [ + { + "id": "", + "source": "string", + "date": "string", + "value": { + "amount": "number", + "currency": "string from currency codelist" + }, + "payer": { + "name": "string", + "id": "" + }, + "payee": { + "name": "string", + "id": "" + }, + "uri": "string" + } + ], + "milestones": [ + { + "id": "string", + "title": "string", + "type": "string from milestoneType codelist", + "description": "string", + "code": "string from milestoneCode codelist", + "dueDate": "string", + "dateMet": "string", + "dateModified": "string", + "status": "string from milestoneStatus codelist", + "relatedImplementationMilestone": { + "id": "string", + "title": "title" + } + } + ], "completion": { "endDate": "", "endDateDetails": "", diff --git a/docs/examples/example.json b/docs/examples/example.json index 53233856..0e501ca7 100644 --- a/docs/examples/example.json +++ b/docs/examples/example.json @@ -200,7 +200,8 @@ "procuringEntity", "buyer", "publicAuthority", - "funder" + "funder", + "payee" ], "people": [ { @@ -344,6 +345,11 @@ "jobTitle": "Commercial Contract Officer" } ] + }, + { + "id": "1", + "name": "United Nations Development Programme", + "roles": "payer" } ], "publicAuthority": { @@ -549,6 +555,20 @@ "amount": 35250000, "currency": "GBP" }, + "milestones": [ + { + "id": "1", + "title": "Construction payment", + "status": "met", + "dueDate": "2017-08-07T00:00:00Z", + "dateMet": "2017-08-07T00:00:00Z", + "type": "payment", + "value": { + "amount": 1950000, + "currency": "GBP" + } + } + ], "transactions": [ { "id": "ocds-a1b1c1-c9b14c18-adc8-11e6-9901-0019b9f3037b-00001-1", @@ -566,7 +586,11 @@ "name": "Concrete Motorways Construction", "id": "GB-COH-33333333" }, - "uri": "https://openspending.org/motorways-uk-spending/transaction/xyz123" + "uri": "https://openspending.org/motorways-uk-spending/transaction/xyz123", + "relatedImplementationMilestone": { + "id": "1", + "title": "Construction payment" + } } ], "documents": [ @@ -889,6 +913,42 @@ ] } ], + "milestones": [ + { + "id": "1", + "title": "Grant disbursement", + "status": "met", + "dueDate": "2016-01-01T00:00:00Z", + "dateMet": "2016-01-01T00:00:00Z", + "type": "payment", + "value": { + "amount": 5000000, + "currency": "GBP" + } + } + ], + "transactions": [ + { + "id": "1", + "date": "2016-01-01T00:00:00Z", + "value": { + "amount": 5000000, + "currency": "GBP" + }, + "payer": { + "id": "1", + "name": "United Nations Development Programme" + }, + "payee": { + "id": "GB-GOR-XX1234", + "name": "Motorways UK" + }, + "relatedImplementationMilestone": { + "id": "1", + "title": "Grant disbursement" + } + } + ], "completion": { "endDate": "2018-12-10T00:00:00Z", "endDateDetails": "Construction was delayed due to excavation problems when a watercourse was damaged.", diff --git a/docs/reference/changelog.md b/docs/reference/changelog.md index 3d1a076f..22cddd09 100644 --- a/docs/reference/changelog.md +++ b/docs/reference/changelog.md @@ -24,12 +24,20 @@ * [#379](https://github.com/open-contracting/infrastructure/pull/379) - add `contractingProcesses.summary.tender.datePublished`. * [#378](https://github.com/open-contracting/infrastructure/pull/378) - clarify semantics of `additionalClassifications`. * [#390](https://github.com/open-contracting/infrastructure/pull/390) - add `identifiers`. +* [#426](https://github.com/open-contracting/infrastructure/pull/426) - add fields: + * `.transactions` + * `.milestones` + * `ContractingProcesses.milestones` ### Codelists * [#355](https://github.com/open-contracting/infrastructure/pull/355) - use correct normative and non-normative keywords codelist descriptions. * [#369](https://github.com/open-contracting/infrastructure/pull/369) - add classification scheme codelist. * [#377](https://github.com/open-contracting/infrastructure/pull/377) - clarify business logic in contractingProcessStatus codelist. +* [#426](https://github.com/open-contracting/infrastructure/pull/426) - add codelists: + * milestoneType + * milestoneStatus + * milestoneCode ### Other diff --git a/docs/reference/codelists.md b/docs/reference/codelists.md index 9e1a260d..f1246301 100644 --- a/docs/reference/codelists.md +++ b/docs/reference/codelists.md @@ -25,6 +25,8 @@ OC4IDS reuses some codelists from the Open Contracting Data Standard and its ext * [Organization identifier scheme](https://standard.open-contracting.org/1.1/en/schema/codelists/#organization-identifier-scheme) * [Release tag](https://standard.open-contracting.org/1.1/en/schema/codelists/#release-tag) * [Unit classification scheme](https://standard.open-contracting.org/1.1/en/schema/codelists/#unit-classification-scheme) +* [Milestone status](https://standard.open-contracting.org/1.1/en/schema/codelists/#milestone-status) +* [Milestone code](https://standard.open-contracting.org/profiles/ppp/latest/en/reference/codelists/#milestonecode) ## Closed codelists @@ -58,6 +60,13 @@ Projects with a `status` of 'completed' may be displayed in a list of archived p :file: ../../build/current_lang/codelists/projectType.csv ``` +### MilestoneType + +```{csv-table-no-translate} +:header-rows: 1 +:file: ../../build/current_lang/codelists/milestoneType.csv +``` + ## Open codelists ### DocumentType diff --git a/docs/reference/schema.md b/docs/reference/schema.md index b4fe3c15..23e72b19 100644 --- a/docs/reference/schema.md +++ b/docs/reference/schema.md @@ -110,7 +110,7 @@ Each `ContractingProcessSummary` has the following fields: ```{jsonschema} ../../build/current_lang/project-schema.json :pointer: /definitions/ContractingProcessSummary -:collapse: ocid,externalReference,nature,title,description,status,suppliers,contractValue,contractPeriod,finalValue,documents,modifications,transactions +:collapse: ocid,externalReference,nature,title,description,status,suppliers,contractValue,contractPeriod,finalValue,documents,modifications,transactions,milestones :addtargets: ``` @@ -424,6 +424,11 @@ Each `Value` has the following fields: :title: contractingProcesses/0/summary/transactions/0/value ``` +```{jsoninclude} ../../docs/examples/example.json +:jsonpointer: /projects/0/transactions/0/value +:title: transactions/0/value +``` + ```{jsoninclude} ../../docs/examples/example.json :jsonpointer: /projects/0/completion/finalValue :title: completion/finalValue @@ -541,6 +546,16 @@ Each `OrganizationReference` has the following fields: :title: contractingProcesses/0/summary/transactions/0/payee ``` +```{jsoninclude} ../../docs/examples/example.json +:jsonpointer: /projects/0/transactions/0/payer +:title: transactions/0/payer +``` + +```{jsoninclude} ../../docs/examples/example.json +:jsonpointer: /projects/0/transactions/0/payee +:title: transactions/0/payee +``` + ```` ````` @@ -645,7 +660,7 @@ Each `BudgetBreakdown` has the following fields: ```{jsonschema} ../../build/current_lang/project-schema.json :pointer: /definitions/BudgetBreakdown -:collapse: id,description,amount,approvalDate,uri,period,sourceParty +:collapse: id,description,amount,uri,period,sourceParty,approvalDate :addtargets: ``` @@ -913,6 +928,7 @@ A spending transaction related to a contracting process. ``` This sub-schema is referenced by the following properties: +* [`transactions`](project-schema.json,,transactions) * [`ContractingProcessSummary/transactions`](project-schema.json,/definitions/ContractingProcessSummary,transactions) Each `Transaction` has the following fields: @@ -923,7 +939,7 @@ Each `Transaction` has the following fields: ```{jsonschema} ../../build/current_lang/project-schema.json :pointer: /definitions/Transaction -:collapse: id,source,date,value,payer,payee,uri +:collapse: id,source,date,value,payer,payee,uri,relatedImplementationMilestone :addtargets: ``` @@ -936,6 +952,11 @@ Each `Transaction` has the following fields: :title: contractingProcesses/0/summary/transactions ``` +```{jsoninclude} ../../docs/examples/example.json +:jsonpointer: /projects/0/transactions +:title: transactions +``` + ```` ````` @@ -974,3 +995,84 @@ Each `SimpleIdentifier` has the following fields: ```` ````` + +### Milestone + +`Milestone` is defined as: + +```{field-description} ../../build/current_lang/project-schema.json /definitions/Milestone +``` + +This sub-schema is referenced by the following properties: +* [`milestones`](project-schema.json,,milestones) +* [`ContractingProcessSummary/milestones`](project-schema.json,/definitions/ContractingProcessSummary,milestones) + +Each `Milestone` has the following fields: + +`````{tab-set} + +````{tab-item} Schema + +```{jsonschema} ../../build/current_lang/project-schema.json +:pointer: /definitions/Milestone +:collapse: id,title,type,description,code,dueDate,dateMet,dateModified,status +:addtargets: +``` + +```` + +````{tab-item} Examples + +```{jsoninclude} ../../docs/examples/example.json +:jsonpointer: /projects/0/contractingProcesses/0/summary/milestones +:title: contractingProcesses/0/summary/milestones +``` + +```{jsoninclude} ../../docs/examples/example.json +:jsonpointer: /projects/0/milestones +:title: milestones +``` + +```` + +````` + +### MilestoneReference + +`MilestoneReference` is defined as: + +```{field-description} ../../build/current_lang/project-schema.json /definitions/MilestoneReference +``` + +This sub-schema is referenced by the following properties: +* [`Transaction/relatedImplementationMilestone`](project-schema.json,/definitions/Transaction,relatedImplementationMilestone) + +Each `MilestoneReference` has the following fields: + +`````{tab-set} + +````{tab-item} Schema + +```{jsonschema} ../../build/current_lang/project-schema.json +:pointer: /definitions/MilestoneReference +:collapse: id,title +:addtargets: +``` + +```` + +````{tab-item} Examples + +```{jsoninclude} ../../docs/examples/example.json +:jsonpointer: /projects/0/contractingProcesses/0/summary/transactions/0/relatedImplementationMilestone +:title: contractingProcesses/0/summary/transactions/0/relatedImplementationMilestone +``` + +```{jsoninclude} ../../docs/examples/example.json +:jsonpointer: /projects/0/transactions/0/relatedImplementationMilestone +:title: transactions/0/relatedImplementationMilestone +``` + +```` + +````` diff --git a/manage.py b/manage.py index 23ea5f66..072ce46e 100755 --- a/manage.py +++ b/manage.py @@ -4,7 +4,7 @@ import re import sys import warnings -from collections import defaultdict +from collections import OrderedDict, defaultdict from copy import deepcopy from io import StringIO from pathlib import Path @@ -453,7 +453,7 @@ def copy_element(name, replacements=None, root='definitions'): ocds_base_url = 'https://standard.open-contracting.org/1.1/en/' - builder = ProfileBuilder('1__1__5', {'budget': 'master'}) + builder = ProfileBuilder('1__1__5', {'budget': 'master', 'transaction_milestones': 'master'}) ppp_schema = get(f'{ppp_base_url}release-schema.json').json() ppp_schema = builder.patched_release_schema(schema=ppp_schema) @@ -473,6 +473,7 @@ def copy_element(name, replacements=None, root='definitions'): 'projectType.csv', 'relatedProjectScheme.csv', 'relatedProject.csv', + 'classificationScheme.csv', } ocds_codelists = { 'currency.csv', @@ -485,6 +486,9 @@ def copy_element(name, replacements=None, root='definitions'): 'partyRole.csv', 'releaseTag.csv', 'unitClassificationScheme.csv', + 'milestoneType.csv', + 'milestoneStatus.csv', + 'milestoneCode.csv', } compare([path.name for path in codelists_dir.iterdir()], infra_codelists, ocds_codelists, 'schema/project-level/codelists', 'codelists') @@ -496,6 +500,7 @@ def copy_element(name, replacements=None, root='definitions'): 'Modification', 'RelatedProject', # Similar to relatedProcess in OCDS 'Person', + 'SimpleIdentifier', } ocds_definitions = { 'Period', @@ -512,6 +517,8 @@ def copy_element(name, replacements=None, root='definitions'): 'Metric', 'Observation', 'Transaction', + 'Milestone', + 'MilestoneReference', } compare(schema['definitions'], infra_definitions, ocds_definitions, 'schema/project-level/project-schema.json#/definitions', 'definitions') @@ -630,12 +637,11 @@ def copy_element(name, replacements=None, root='definitions'): }) copy_element('Classification', { - # Remove line item classifications from the definition. - ('properties', 'scheme', 'description'): lambda s: s[:s.index(' For line item classifications,')], + # Replace line item classification scheme codelist with classification scheme codelist + ('properties', 'scheme', 'description'): lambda s: s.replace('. For line item classifications, this uses the open [itemClassificationScheme](https://standard.open-contracting.org/1.1/en/schema/codelists/#item-classification-scheme) codelist.', ', using the open [classificationScheme](https://standard.open-contracting.org/infrastructure/{{version}}/{{lang}}/reference/codelists/#classificationscheme) codelist.'), # noqa: E501 }) - # Remove the `itemClassificationScheme.csv` codelist. - del schema['definitions']['Classification']['properties']['scheme']['codelist'] - del schema['definitions']['Classification']['properties']['scheme']['openCodelist'] + # Replace line item classification scheme codelist with classification scheme codelist + schema['definitions']['Classification']['properties']['scheme']['codelist'] = 'classificationScheme.csv' copy_element('Location') # Original from ocds_location_extension: "The location where activity related to this tender, contract or license will be delivered, or will take place. A location can be described by either a geometry (point location, line or polygon), or a gazetteer entry, or both." # noqa: E501 @@ -653,6 +659,7 @@ def copy_element(name, replacements=None, root='definitions'): 'description': 'A physical address where works will take place.', '$ref': '#/definitions/Address', } + schema['definitions']['Location']['properties'] = OrderedDict(schema['definitions']['Location']['properties']) schema['definitions']['Location']['properties'].move_to_end('id', last=False) schema['definitions']['Location']['required'] = ['id'] @@ -693,7 +700,13 @@ def copy_element(name, replacements=None, root='definitions'): ('properties', 'name', 'description'): lambda s: s.replace('contracting process', 'project'), }) - copy_element('BudgetBreakdown') + copy_element('BudgetBreakdown', { + # Refer to project instead of contracting process + ('properties', 'amount', 'description'): lambda s: s.replace('contracting process', 'project',) + }) + # Add approval date + schema['definitions']['BudgetBreakdown']['properties']['approvalDate'] = deepcopy(schema['properties']['budget']['properties']['approvalDate']) # noqa: E501 + schema['definitions']['BudgetBreakdown']['properties']['approvalDate']['description'] = "The date on which this budget entry was approved. Where documentary evidence for this exists, it may be included among the project documents with `.documentType` set to 'budgetApproval'." # noqa: E501 copy_element('Document', { # Link to infrastructure codelist instead of PPP codelist @@ -717,6 +730,25 @@ def copy_element(name, replacements=None, root='definitions'): del schema['definitions']['Observation']['properties']['relatedImplementationMilestone'] copy_element('Transaction') + # Original from standard: "A spending transaction related to the contracting process. Draws upon the data models of the [Fiscal Data Package](https://frictionlessdata.io/specs/fiscal-data-package/) and the [International Aid Transparency Initiative](http://iatistandard.org/activity-standard/iati-activities/iati-activity/transaction/) and should be used to cross-reference to more detailed information held using a Fiscal Data Package, IATI file, or to provide enough information to allow a user to manually or automatically cross-reference with some other published source of transactional spending data." # noqa: E501 + schema['definitions']['Transaction']['description'] = "A financial transaction related to a project or contracting process. Draws upon the data models of the Fiscal Data Package and the International Aid Transparency Initiative and should be used to cross-reference to more detailed information held using a Fiscal Data Package, IATI file, or to provide enough information to allow a user to manually or automatically cross-reference with some other published source of transactional data." # noqa: E501 + + copy_element('Milestone') + # Original from standard: "The milestone block can be used to represent a wide variety of events in the lifetime of a contracting process." # noqa: E501 + schema['definitions']['Milestone']['description'] = "An event in the lifetime of a project or contracting process." # noqa: E501 + # Original from standard: "A local identifier for this milestone, unique within this block. This field is used to keep track of multiple revisions of a milestone through the compilation from release to record mechanism." # noqa: E501 + schema['definitions']['Milestone']['properties']['id']['description'] = "A local identifier for this milestone, unique within this block." # noqa: E501 + # Original from standard: "Milestone codes can be used to track specific events that take place for a particular kind of contracting process. For example, a code of 'approvalLetter' can be used to allow applications to understand this milestone represents the date an approvalLetter is due or signed." # noqa: E501 + schema['definitions']['Milestone']['properties']['code']['description'] = "Milestone codes can be used to track specific events that take place for a particular kind of project or contracting process. For example, a code of 'approvalLetter' can be used to allow applications to understand this milestone represents the date an approvalLetter is due or signed." # noqa: E501 + # Remove deprecated milestone documents field + del schema['definitions']['Milestone']['properties']['documents'] + + copy_element('MilestoneReference', { + # Remove reference to release, add reference to project. + ('properties', 'id', 'description'): lambda s: s.replace(' described elsewhere in a release about this contracting process.', " in this project or contracting process's `.milestones`."), # noqa: E501 + }) + # Original from standard: "The title of the milestone being referenced, this must match the title of a milestone described elsewhere in a release about this contracting process." # noqa: E501 + schema['definitions']['MilestoneReference']['properties']['title']['description'] = "The title of the milestone being referenced, this must match the title of a milestone in this project or contracting process's `.milestones`." # noqa: E501 remove_null_and_pattern_properties(schema) remove_integer_identifier_types(schema) diff --git a/mapping/sustainability.yaml b/mapping/sustainability.yaml index dc3e9b12..2769e530 100644 --- a/mapping/sustainability.yaml +++ b/mapping/sustainability.yaml @@ -808,8 +808,81 @@ module: Climate finance indicator: Efficiency disclosure format: Disbursements dates according to financial agreement versus actual disbursements dates \[value, currency, date\] - mapping: '' - example: '' + mapping: |- + For each planned disbursement: + + - If the disbursement relates to a contracting processes, for example a payment from a funder to a supplier or subcontractor of a supplier, get the `ContractingProcess` in the `.contractingProcesses` array to which the disbursement relates and add a `Milestone` object to its `.summary.milestones` array. Otherwise, if the disbursement relates to the project, for example a payment from a funder to the public authority, add a `Milestone` object to the project-level `.milestones` array. + - Set the milestone's: + - `.id` incrementally + - `.status` to 'scheduled' + - `.dueDate` to the date on which the disbursement is planned to occur + - `.type` to 'payment' + - `.value` to the amount and currency of the planned disbursement + + For each actual disbursement: + + - If the disbursement relates to a contracting processes, for example a payment from a funder to a supplier or subcontractor of a supplier, get the `ContractingProcess` in the `.contractingProcesses` array to which the disbursement relates and add a `Transaction` object to its `.summary.transactions` array. Otherwise, if the disbursement relates to the project, for example a payment from a funder to the public authority, add a `Transaction` object to the project-level `.transactions` array. + + - Set the transaction's: + + - `.id` incrementally + - `.date` to the date of the disbursement + - `.value` to the amount and currency of the disbursement + + - Get the `Organization` in `.parties` that represents the payer. If none exists yet, [add an organization](../common.md#add-an-organization) for the payer: + + - Add 'payer' to the organization's `.roles` array + - Set the transaction's `.payer` to the `.id` and `.name` of the organization + + - Get the `Organization` in `.parties` that represents the payee. If none exists yet, [add an organization](../common.md#add-an-organization) for the payee: + + - Add 'payee' to the organization's `.roles` array. + - Set the transaction's `.payee` to the `.id` and `.name` of the organization + + - Get the `Milestone` in `.milestones` that represents that planned disbursement: + + - Set its `.status` to 'met' + - Set its `.dateMet` to the date of the disbursement + - Set the transaction's `.relatedImplementationMilestone` to the `.id` and `.title` of the milestone + example: |- + { + "milestones": [ + { + "id": "1", + "title": "Grant disbursement", + "status": "met", + "dueDate": "2023-07-01T00:00:00Z", + "dateMet": "2023-08-01T00:00:00Z", + "type": "payment", + "value": { + "amount": 5000000, + "currency": "USD" + } + } + ], + "transactions": [ + { + "id": "1", + "date": "2023-08-01T00:00:00Z", + "value": { + "amount": 5000000, + "currency": "USD" + }, + "payer": { + "id": "1", + "name": "United Nations Development Programme" + }, + "payee": { + "id": "2", + "name": "Ministry of works" + }, + "relatedImplementationMilestone": { + "id": "1", + "title": "Grant disbursement" + } + } + ] + } - id: '3.21' title: Type of project monitoring module: Climate finance diff --git a/schema/project-level/codelists/milestoneCode.csv b/schema/project-level/codelists/milestoneCode.csv new file mode 100644 index 00000000..b566d08b --- /dev/null +++ b/schema/project-level/codelists/milestoneCode.csv @@ -0,0 +1,10 @@ +Code,Title,Description,Extension +projectApproval,Project approval,The dates of approvals from relevant authorities.,OCDS for PPPs Extension +commercialClose,Commercial close,"In a financing, the point at which the commercial documentation has been executed but before conditions precedent have been satisfied or waived; before financial close.",OCDS for PPPs Extension +financialClose,Financial close,"In a financing, the point at which the documentation has been executed and conditions precedent have been satisfied or waived. Drawdowns become permissible after this point.",OCDS for PPPs Extension +commencement,Commencement of construction or development,The date of commencement of construction or development,OCDS for PPPs Extension +completion,Completion of construction of development,The date of completion of construction or development,OCDS for PPPs Extension +commissioning,Commissioning,The testing and inspection of the completed works to verify that the works are ready for commercial operation.,OCDS for PPPs Extension +enquiryPeriodStart,Enquiry period start,"For processes with multiple enquiry periods, the start date of a period during which enquiries can be made and responded to which is not provided in the tender/enquiryPeriod block. Sometimes known as clarification periods.",OCDS for PPPs Extension +enquiryPeriodEnd,Enquiry period end,"For processes with multiple enquiry periods, the end date of a period during which enquiries can be made and responded to which is not provided in the tender/enquiryPeriod block. Sometimes known as clarification periods.",OCDS for PPPs Extension +draftFinalTender,Submission of draft final tender,"For competitive dialogue processes, the deadline for submission of draft final tenders",OCDS for PPPs Extension diff --git a/schema/project-level/codelists/milestoneStatus.csv b/schema/project-level/codelists/milestoneStatus.csv new file mode 100644 index 00000000..ea288709 --- /dev/null +++ b/schema/project-level/codelists/milestoneStatus.csv @@ -0,0 +1,5 @@ +Code,Title,Description,Extension +scheduled,Scheduled,This milestone has been scheduled for the date in milestone.dueDate. Progress towards the milestone has not yet been evaluated as of milestone.dateModified.,OCDS Core +met,Met,This milestone has been achieved. The date on which it was met should be placed in the milestone.dateMet field.,OCDS Core +notMet,Not met,This milestone had not been met at the date it was last reviewed (see milestone.dateModified).,OCDS Core +partiallyMet,Partially met,This milestone was judged to have been partially met at the date it was last reviewed (see milestone.dateModified).,OCDS Core diff --git a/schema/project-level/codelists/milestoneType.csv b/schema/project-level/codelists/milestoneType.csv new file mode 100644 index 00000000..06e077b0 --- /dev/null +++ b/schema/project-level/codelists/milestoneType.csv @@ -0,0 +1,11 @@ +Code,Title,Description,Extension +preProcurement,Pre-procurement milestones,"For events during the planning or pre-procurement phase of a process, such as the preparation of key studies.",OCDS Core +approval,Approval milestones,For events such as the sign-off of a contract or project.,OCDS Core +engagement,Engagement milestones,"For engagement milestones, such as a public hearing.",OCDS Core +assessment,Assessment milestones,"For assessment and adjudication milestones, such as the meeting date of a committee.",OCDS Core +delivery,Delivery milestones,"For delivery milestones, such as the date when a good or service is to be provided.",OCDS Core +reporting,Reporting milestones,"For reporting milestones, such as when key reports are to be provided.",OCDS Core +financing,Financing milestones,"For events related to the funding of the project or contracting process. In public-private partnerships, such events might include, for example, planned payments and equity transfers.",OCDS Core +payment,Payment milestones,"For payment milestones, such as the date when a payment is expected to be made to a supplier. If the `status` of a project or contracting process's payment milestone is 'met', then the contract ought to have an entry for the payment under its `.transactions`.",OCDS Core +procurement,Procurement,"Events taking place during the procurement which are not captured by fields in core OCDS, such as additional enquiry periods or draft tender submissions in a competitive dialogue process",OCDS for PPPs Extension +contractClose,Contract close,Events such as commercial and financial close,OCDS for PPPs Extension diff --git a/schema/project-level/project-schema.json b/schema/project-level/project-schema.json index dbad6ad6..31606722 100644 --- a/schema/project-level/project-schema.json +++ b/schema/project-level/project-schema.json @@ -225,6 +225,26 @@ "uniqueItems": true, "minItems": 1 }, + "transactions": { + "title": "Transactions", + "description": "Financial transactions related to this project. For example, a disbursement from a funder to the project company. Transactions related to a contracting process, like a disbursement from a funder to a supplier, should be recorded in the contracting process summary's `.transactions.`", + "type": "array", + "items": { + "$ref": "#/definitions/Transaction" + }, + "minItems": 1, + "uniqueItems": true + }, + "milestones": { + "title": "Milestones", + "description": "Milestones associated with this project.", + "type": "array", + "items": { + "$ref": "#/definitions/Milestone" + }, + "minItems": 1, + "uniqueItems": true + }, "completion": { "title": "Completion", "description": "This information is provided at project completion, and reflects the final timing and values relating to the project. The reason for any variation (not already explained) between the anticipated project scope, period and value should be detailed.", @@ -270,7 +290,7 @@ }, "language": { "title": "Language", - "description": "The default language of the data using either two-letter [ISO639-1](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes), or extended [BCP47 language tags](https://www.w3.org/International/articles/language-tags/). The use of lowercase two-letter codes from [ISO639-1](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes) is recommended.", + "description": "The default language of the data using either two-letter [ISO639-1](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes), or extended [BCP47 language tags](http://www.w3.org/International/articles/language-tags/). The use of lowercase two-letter codes from [ISO639-1](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes) is recommended.", "type": [ "string" ], @@ -490,6 +510,16 @@ }, "uniqueItems": true, "minItems": 1 + }, + "milestones": { + "title": "Milestones", + "description": "Milestones associated with this contracting process.", + "type": "array", + "items": { + "$ref": "#/definitions/Milestone" + }, + "minItems": 1, + "uniqueItems": true } }, "minProperties": 1 @@ -682,7 +712,9 @@ "scheme": { "title": "Scheme", "description": "The scheme or codelist from which the classification code is taken, using the open [classificationScheme](https://standard.open-contracting.org/infrastructure/{{version}}/{{lang}}/reference/codelists/#classificationscheme) codelist.", - "type": "string", + "type": [ + "string" + ], "codelist": "classificationScheme.csv", "openCodelist": true, "minLength": 1 @@ -735,11 +767,11 @@ "geometry": { "type": "object", "title": "Geometry", - "description": "We follow the [GeoJSON standard](https://geojson.org/) to express basic location information, using longitude, latitude, and optional elevation values in the [WGS84](https://en.wikipedia.org/wiki/World_Geodetic_System) (EPSG:4326) projection. A point location can be identified by geocoding a delivery address. For concession licenses, or other contracts covering a polygon location which is not contained in a known gazetteer, polygon and multi-polygon can be used.", + "description": "We follow the [GeoJSON standard](http://geojson.org/) to express basic location information, using longitude, latitude, and optional elevation values in the [WGS84](https://en.wikipedia.org/wiki/World_Geodetic_System) (EPSG:4326) projection. A point location can be identified by geocoding a delivery address. For concession licenses, or other contracts covering a polygon location which is not contained in a known gazetteer, polygon and multi-polygon can be used.", "properties": { "type": { "title": "Type", - "description": "The type of [GeoJSON Geometry Objects](https://geojson.org/geojson-spec.html#geometry-objects) being provided. To provide longitude, latitude, and optional elevation, use 'Point', and enter an array of [longitude, latitude] or [longitude, latitude, elevation] as the value of the coordinates field: e.g. [-122.085, 37.42].", + "description": "The type of [GeoJSON Geometry Objects](http://geojson.org/geojson-spec.html#geometry-objects) being provided. To provide longitude, latitude, and optional elevation, use 'Point', and enter an array of [longitude, latitude] or [longitude, latitude, elevation] as the value of the coordinates field: e.g. [-122.085, 37.42].", "type": [ "string" ], @@ -1344,9 +1376,9 @@ "minProperties": 1 }, "BudgetBreakdown": { - "type": "object", "title": "Detailed budget breakdown", "description": "This section allows a detailed budget breakdown to be expressed, covering multiple budget sources and multiple periods", + "type": "object", "required": [ "id" ], @@ -1367,15 +1399,9 @@ }, "amount": { "title": "Amount", - "description": "The value of the budget line item.", + "description": "The value of the budget line item. A positive amount means the source organization funds the project. A negative amount means the project pays the source organization.", "$ref": "#/definitions/Value" }, - "approvalDate": { - "title": "Approval date", - "description": "The date on which this budget entry was approved. Where documentary evidence for this exists, it may be included among the project documents with `.documentType` set to 'budgetApproval'.", - "type": "string", - "format": "date-time" - }, "uri": { "title": "Linked budget information", "description": "A URI pointing directly to a machine-readable information about this budget entry.", @@ -1385,14 +1411,20 @@ "format": "uri" }, "period": { - "$ref": "#/definitions/Period", "title": "Budget period", - "description": "The period covered by this budget entry." + "description": "The period covered by this budget entry.", + "$ref": "#/definitions/Period" }, "sourceParty": { - "$ref": "#/definitions/OrganizationReference", - "title": "Source party", - "description": "An organization reference, linking to the entry in the `parties` section describing the organization providing the funds for this part of the budget. The party must have the 'funder' role. If the budget amount is positive, this indicates a flow of resources from the party to the contracting process. If the budget amount is negative, it indicates a payment from the contracting process to this party." + "title": "Source organization", + "description": "The organization providing the funds for this budget entry. The corresponding entry in the `parties` array must have 'sourceParty' in its `roles` array.", + "$ref": "#/definitions/OrganizationReference" + }, + "approvalDate": { + "title": "Approval date", + "description": "The date on which this budget entry was approved. Where documentary evidence for this exists, it may be included among the project documents with `.documentType` set to 'budgetApproval'.", + "type": "string", + "format": "date-time" } }, "minProperties": 1 @@ -1463,7 +1495,7 @@ }, "format": { "title": "Format", - "description": "The format of the document, using the open [IANA Media Types](https://www.iana.org/assignments/media-types/) codelist (see the values in the 'Template' column), or using the 'offline/print' code if the described document is published offline. For example, web pages have a format of 'text/html'.", + "description": "The format of the document, using the open [IANA Media Types](http://www.iana.org/assignments/media-types/) codelist (see the values in the 'Template' column), or using the 'offline/print' code if the described document is published offline. For example, web pages have a format of 'text/html'.", "type": [ "string" ], @@ -1471,7 +1503,7 @@ }, "language": { "title": "Language", - "description": "The language of the linked document using either two-letter [ISO639-1](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes), or extended [BCP47 language tags](https://www.w3.org/International/articles/language-tags/). The use of lowercase two-letter codes from [ISO639-1](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes) is recommended unless there is a clear user need for distinguishing the language subtype.", + "description": "The language of the linked document using either two-letter [ISO639-1](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes), or extended [BCP47 language tags](http://www.w3.org/International/articles/language-tags/). The use of lowercase two-letter codes from [ISO639-1](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes) is recommended unless there is a clear user need for distinguishing the language subtype.", "type": [ "string" ], @@ -1542,7 +1574,7 @@ }, "uri": { "title": "URI", - "description": "A URI to identify the organization, such as those provided by [Open Corporates](https://opencorporates.com) or some other relevant URI provider. This is not for listing the website of the organization: that can be done through the URL field of the Organization contact point.", + "description": "A URI to identify the organization, such as those provided by [Open Corporates](http://www.opencorporates.com) or some other relevant URI provider. This is not for listing the website of the organization: that can be done through the URL field of the Organization contact point.", "type": [ "string" ], @@ -1769,7 +1801,7 @@ "Transaction": { "type": "object", "title": "Transaction information", - "description": "A spending transaction related to the contracting process. Draws upon the data models of the [Fiscal Data Package](https://frictionlessdata.io/specs/fiscal-data-package/) and the [International Aid Transparency Initiative](https://iatistandard.org/activity-standard/iati-activities/iati-activity/transaction/) and should be used to cross-reference to more detailed information held using a Fiscal Data Package, IATI file, or to provide enough information to allow a user to manually or automatically cross-reference with some other published source of transactional spending data.", + "description": "A financial transaction related to a project or contracting process. Draws upon the data models of the Fiscal Data Package and the International Aid Transparency Initiative and should be used to cross-reference to more detailed information held using a Fiscal Data Package, IATI file, or to provide enough information to allow a user to manually or automatically cross-reference with some other published source of transactional data.", "required": [ "id" ], @@ -1818,6 +1850,11 @@ "string" ], "format": "uri" + }, + "relatedImplementationMilestone": { + "title": "Related implementation milestone", + "description": "A link to the milestone in the implementation section of OCDS to which this transaction relates.", + "$ref": "#/definitions/MilestoneReference" } }, "minProperties": 1 @@ -1844,6 +1881,123 @@ "id" ], "minProperties": 1 + }, + "Milestone": { + "title": "Milestone", + "description": "An event in the lifetime of a project or contracting process.", + "type": "object", + "required": [ + "id" + ], + "properties": { + "id": { + "title": "ID", + "description": "A local identifier for this milestone, unique within this block.", + "type": "string", + "minLength": 1 + }, + "title": { + "title": "Title", + "description": "Milestone title", + "type": [ + "string" + ], + "minLength": 1 + }, + "type": { + "title": "Milestone type", + "description": "The nature of the milestone, using the open [milestoneType](https://standard.open-contracting.org/profiles/ppp/latest/en/reference/codelists/#milestonetype) codelist.", + "type": [ + "string" + ], + "codelist": "milestoneType.csv", + "openCodelist": true, + "minLength": 1 + }, + "description": { + "title": "Description", + "description": "A description of the milestone.", + "type": [ + "string" + ], + "minLength": 1 + }, + "code": { + "title": "Milestone code", + "description": "Milestone codes can be used to track specific events that take place for a particular kind of project or contracting process. For example, a code of 'approvalLetter' can be used to allow applications to understand this milestone represents the date an approvalLetter is due or signed.", + "type": [ + "string" + ], + "codelist": "milestoneCode.csv", + "openCodelist": true, + "minLength": 1 + }, + "dueDate": { + "title": "Due date", + "description": "The date the milestone is due.", + "type": [ + "string" + ], + "format": "date-time" + }, + "dateMet": { + "format": "date-time", + "title": "Date met", + "description": "The date on which the milestone was met.", + "type": [ + "string" + ] + }, + "dateModified": { + "title": "Date modified", + "description": "The date the milestone was last reviewed or modified and the status was altered or confirmed to still be correct.", + "type": [ + "string" + ], + "format": "date-time" + }, + "status": { + "title": "Status", + "description": "The status that was realized on the date provided in `dateModified`, from the closed [milestoneStatus](https://standard.open-contracting.org/1.1/en/schema/codelists/#milestone-status) codelist.", + "type": [ + "string" + ], + "enum": [ + "scheduled", + "met", + "notMet", + "partiallyMet" + ], + "codelist": "milestoneStatus.csv", + "openCodelist": false + } + }, + "minProperties": 1 + }, + "MilestoneReference": { + "type": "object", + "title": "Milestone Reference", + "description": "A block used to reference a milestone, including the ID and title of the milestone being referenced.", + "required": [ + "id" + ], + "properties": { + "id": { + "title": "Milestone ID", + "description": "The ID of the milestone being referenced, this must match the ID of a milestone in this project or contracting process's `.milestones`.", + "type": "string", + "minLength": 1 + }, + "title": { + "title": "Milestone title", + "description": "The title of the milestone being referenced, this must match the title of a milestone in this project or contracting process's `.milestones`.", + "type": [ + "string" + ], + "minLength": 1 + } + }, + "minProperties": 1 } }, "minProperties": 1