diff --git a/manage.py b/manage.py index 23ea5f66..01117bb7 100755 --- a/manage.py +++ b/manage.py @@ -4,7 +4,7 @@ import re import sys import warnings -from collections import defaultdict +from collections import defaultdict, OrderedDict from copy import deepcopy from io import StringIO from pathlib import Path @@ -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,8 @@ def copy_element(name, replacements=None, root='definitions'): 'partyRole.csv', 'releaseTag.csv', 'unitClassificationScheme.csv', + 'milestoneType.csv', + 'milestoneStatus.csv', } compare([path.name for path in codelists_dir.iterdir()], infra_codelists, ocds_codelists, 'schema/project-level/codelists', 'codelists') @@ -496,6 +499,7 @@ def copy_element(name, replacements=None, root='definitions'): 'Modification', 'RelatedProject', # Similar to relatedProcess in OCDS 'Person', + 'SimpleIdentifier', } ocds_definitions = { 'Period', @@ -512,6 +516,7 @@ def copy_element(name, replacements=None, root='definitions'): 'Metric', 'Observation', 'Transaction', + 'Milestone' } compare(schema['definitions'], infra_definitions, ocds_definitions, 'schema/project-level/project-schema.json#/definitions', 'definitions') @@ -630,12 +635,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 +657,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 +698,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 +728,16 @@ 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_null_and_pattern_properties(schema) remove_integer_identifier_types(schema) 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..62ad4a7e 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" ], @@ -1844,6 +1876,108 @@ "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 + }, + "documents": { + "title": "Documents", + "description": "List of documents associated with this milestone (Deprecated in 1.1).", + "type": "array", + "items": { + "$ref": "#/definitions/Document" + }, + "uniqueItems": true, + "minItems": 1 + } + }, + "minProperties": 1 } }, "minProperties": 1