From 889eb3a54e021b83418d8224ca99a1d5fc4ff4a9 Mon Sep 17 00:00:00 2001 From: Duncan Dewhurst Date: Mon, 13 Nov 2023 10:48:23 +1300 Subject: [PATCH 1/7] project-schema: Add Organization.beneficialOwners --- docs/_static/i18n.csv | 41 ++- docs/examples/blank.json | 23 ++ docs/examples/example.json | 23 ++ docs/reference/codelists.md | 7 + docs/reference/schema.md | 7 +- manage.py | 45 ++- schema/project-level/codelists/country.csv | 251 ++++++++++++++++ schema/project-level/project-schema.json | 325 ++++++++++++++++++++- 8 files changed, 701 insertions(+), 21 deletions(-) create mode 100644 schema/project-level/codelists/country.csv diff --git a/docs/_static/i18n.csv b/docs/_static/i18n.csv index 45a581b6..0d82e86e 100644 --- a/docs/_static/i18n.csv +++ b/docs/_static/i18n.csv @@ -140,10 +140,49 @@ parties/contactPoint/telephone,Telephone,True, parties/contactPoint/faxNumber,Fax number,True, parties/contactPoint/url,URL,False, parties/roles,Party roles,False, +parties/beneficialOwners,Beneficial owners,False, +parties/beneficialOwners,Person,False, +parties/beneficialOwners/id,ID,True, +parties/beneficialOwners/name,Name,True, +parties/beneficialOwners/identifier,Identifier,False, +parties/beneficialOwners/identifier,Identifier,False, +parties/beneficialOwners/identifier/scheme,Scheme,True, +parties/beneficialOwners/identifier/id,ID,True, +parties/beneficialOwners/identifier/legalName,Legal Name,True, +parties/beneficialOwners/identifier/uri,URI,False, +parties/beneficialOwners/nationalities,Nationalities,False, +parties/beneficialOwners/address,Address,False, +parties/beneficialOwners/address,Address,False, +parties/beneficialOwners/address/streetAddress,Street address,True, +parties/beneficialOwners/address/locality,Locality,True, +parties/beneficialOwners/address/region,Region,True, +parties/beneficialOwners/address/postalCode,Postal code,True, +parties/beneficialOwners/address/countryName,Country name,True, +parties/beneficialOwners/email,Email,False, +parties/beneficialOwners/faxNumber,Fax number,True, +parties/beneficialOwners/telephone,Telephone,True, +parties/beneficialOwners/jobTitle,Job title,True, parties/people,People,False, parties/people,Person,False, -parties/people/id,Identifier,True, +parties/people/id,ID,True, parties/people/name,Name,True, +parties/people/identifier,Identifier,False, +parties/people/identifier,Identifier,False, +parties/people/identifier/scheme,Scheme,True, +parties/people/identifier/id,ID,True, +parties/people/identifier/legalName,Legal Name,True, +parties/people/identifier/uri,URI,False, +parties/people/nationalities,Nationalities,False, +parties/people/address,Address,False, +parties/people/address,Address,False, +parties/people/address/streetAddress,Street address,True, +parties/people/address/locality,Locality,True, +parties/people/address/region,Region,True, +parties/people/address/postalCode,Postal code,True, +parties/people/address/countryName,Country name,True, +parties/people/email,Email,False, +parties/people/faxNumber,Fax number,True, +parties/people/telephone,Telephone,True, parties/people/jobTitle,Job title,True, publicAuthority,Public authority,False, publicAuthority,Organization reference,False, diff --git a/docs/examples/blank.json b/docs/examples/blank.json index 488b17a2..959870f3 100644 --- a/docs/examples/blank.json +++ b/docs/examples/blank.json @@ -165,6 +165,29 @@ "name": "", "jobTitle": "" } + ], + "beneficialOwners": [ + { + "id": "string", + "name": "string", + "identifier": { + "scheme": "string", + "id": "string" + }, + "nationalities": [ + "string" + ], + "address": { + "streetAddress": "string", + "locality": "string", + "region": "string", + "postalCode": "string", + "countryName": "string" + }, + "email": "string", + "faxNumber": "string", + "telephone": "string" + } ] } ], diff --git a/docs/examples/example.json b/docs/examples/example.json index 0e501ca7..328e16cd 100644 --- a/docs/examples/example.json +++ b/docs/examples/example.json @@ -312,6 +312,29 @@ "roles": [ "supplier", "tenderer" + ], + "beneficialOwners": [ + { + "id": "1", + "name": "Juan Perez", + "identifier": { + "scheme": "PRY-IDCARD", + "id": "12345" + }, + "nationalities": [ + "PY" + ], + "address": { + "streetAddress": "Avenida Eusebio Ayala 1347", + "locality": "Asunción", + "region": "Gran Asunción", + "postalCode": "1001", + "countryName": "Paraguay" + }, + "email": "jperez@example.com", + "faxNumber": "+595210000001", + "telephone": "+595210000000" + } ] }, { diff --git a/docs/reference/codelists.md b/docs/reference/codelists.md index f1246301..acc262b0 100644 --- a/docs/reference/codelists.md +++ b/docs/reference/codelists.md @@ -67,6 +67,13 @@ Projects with a `status` of 'completed' may be displayed in a list of archived p :file: ../../build/current_lang/codelists/milestoneType.csv ``` +### country + +```{csv-table-no-translate} +:header-rows: 1 +:file: ../../build/current_lang/codelists/country.csv +``` + ## Open codelists ### DocumentType diff --git a/docs/reference/schema.md b/docs/reference/schema.md index 23e72b19..9f92ce4b 100644 --- a/docs/reference/schema.md +++ b/docs/reference/schema.md @@ -456,7 +456,7 @@ Each `Organization` has the following fields: ```{jsonschema} ../../build/current_lang/project-schema.json :pointer: /definitions/Organization -:collapse: name,id,identifier,additionalIdentifiers,address,contactPoint,roles,people +:collapse: name,id,identifier,additionalIdentifiers,address,contactPoint,roles,beneficialOwners,people :addtargets: ``` @@ -574,6 +574,7 @@ When working with data, users ought to be aware that addresses might not always This sub-schema is referenced by the following properties: * [`Location/address`](project-schema.json,/definitions/Location,address) * [`Organization/address`](project-schema.json,/definitions/Organization,address) +* [`Person/address`](project-schema.json,/definitions/Person,address) Each `Address` has the following fields: @@ -734,6 +735,7 @@ For example, if identifying a company in Colombia, look up its identifier in the This sub-schema is referenced by the following properties: * [`Organization/identifier`](project-schema.json,/definitions/Organization,identifier) * [`Organization/additionalIdentifiers`](project-schema.json,/definitions/Organization,additionalIdentifiers) +* [`Person/identifier`](project-schema.json,/definitions/Person,identifier) Each `Identifier` has the following fields: @@ -891,6 +893,7 @@ Use this object when you need to disclose the details of people associated with, ``` This sub-schema is referenced by the following properties: +* [`Organization/beneficialOwners`](project-schema.json,/definitions/Organization,beneficialOwners) * [`Organization/people`](project-schema.json,/definitions/Organization,people) Each `Person` has the following fields: @@ -901,7 +904,7 @@ Each `Person` has the following fields: ```{jsonschema} ../../build/current_lang/project-schema.json :pointer: /definitions/Person -:collapse: id,name,jobTitle +:collapse: id,name,identifier,nationalities,address,email,faxNumber,telephone,jobTitle :addtargets: ``` diff --git a/manage.py b/manage.py index 781437cb..10bd0cf6 100755 --- a/manage.py +++ b/manage.py @@ -334,21 +334,32 @@ def update_sub_schema_reference(schema): ]) # Paths that don't appear in the example data at all - paths_to_skip = ['forecasts/0/observations/0/value', 'metrics/0/observations/0/value'] + paths_to_skip = ['forecasts/0/observations/0/value', + 'metrics/0/observations/0/value', + 'parties/0/beneficialOwners/0', + 'parties/0/people/0/address', + 'parties/0/people/0/identifier'] # Add examples definition["references"] = get_definition_references(schema, defn) for ref in definition["references"]: - if ref[0] not in schema['definitions'] and '/'.join(ref) not in paths_to_skip: - if ref[-1] == '0': - ref.pop(-1) + if ref[0] not in schema['definitions']: + skip = False - definition["content"].extend([ - "```{jsoninclude} ../../docs/examples/example.json\n", - f":jsonpointer: /projects/0/{'/'.join(ref)}\n", - f":title: {'/'.join(ref)}\n", - "```\n\n" - ]) + for path_to_skip in paths_to_skip: + if path_to_skip == '/'.join(ref)[:len(path_to_skip)]: + skip = True + + if not skip: + if ref[-1] == '0': + ref.pop(-1) + + definition["content"].extend([ + "```{jsoninclude} ../../docs/examples/example.json\n", + f":jsonpointer: /projects/0/{'/'.join(ref)}\n", + f":title: {'/'.join(ref)}\n", + "```\n\n" + ]) definition["content"].extend([ "````\n\n", @@ -453,7 +464,8 @@ 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', 'transaction_milestones': 'master'}) + builder = ProfileBuilder('1__1__5', + {'budget': 'master', 'transaction_milestones': 'master', 'beneficialOwners': 'master'}) ppp_schema = get(f'{ppp_base_url}release-schema.json').json() ppp_schema = builder.patched_release_schema(schema=ppp_schema) @@ -474,6 +486,7 @@ def copy_element(name, replacements=None, root='definitions'): 'relatedProjectScheme.csv', 'relatedProject.csv', 'classificationScheme.csv', + 'country.csv', } ocds_codelists = { 'currency.csv', @@ -499,7 +512,6 @@ def copy_element(name, replacements=None, root='definitions'): 'LinkedRelease', # Similar to linked release in OCDS 'Modification', 'RelatedProject', # Similar to relatedProcess in OCDS - 'Person', 'SimpleIdentifier', } ocds_definitions = { @@ -519,6 +531,7 @@ def copy_element(name, replacements=None, root='definitions'): 'Transaction', 'Milestone', 'MilestoneReference', + 'Person', } compare(schema['definitions'], infra_definitions, ocds_definitions, 'schema/project-level/project-schema.json#/definitions', 'definitions') @@ -750,6 +763,14 @@ def copy_element(name, replacements=None, root='definitions'): # 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 + copy_element('Person') + schema['definitions']['Person']['properties']['jobTitle'] = { + "title": "Job title", + "description": "The job title of the person (for example, Financial Manager).", + "type": "string", + "minLength": 1 + } + remove_null_and_pattern_properties(schema) remove_integer_identifier_types(schema) remove_deprecated_properties(schema) diff --git a/schema/project-level/codelists/country.csv b/schema/project-level/codelists/country.csv new file mode 100644 index 00000000..67670fcd --- /dev/null +++ b/schema/project-level/codelists/country.csv @@ -0,0 +1,251 @@ +Code,Title +AD,Andorra +AE,United Arab Emirates +AF,Afghanistan +AG,Antigua and Barbuda +AI,Anguilla +AL,Albania +AM,Armenia +AO,Angola +AQ,Antarctica +AR,Argentina +AS,American Samoa +AT,Austria +AU,Australia +AW,Aruba +AX,Åland Islands +AZ,Azerbaijan +BA,Bosnia and Herzegovina +BB,Barbados +BD,Bangladesh +BE,Belgium +BF,Burkina Faso +BG,Bulgaria +BH,Bahrain +BI,Burundi +BJ,Benin +BL,Saint Barthélemy +BM,Bermuda +BN,Brunei Darussalam +BO,Bolivia (Plurinational State of) +BQ,"Bonaire, Sint Eustatius and Saba" +BR,Brazil +BS,Bahamas +BT,Bhutan +BV,Bouvet Island +BW,Botswana +BY,Belarus +BZ,Belize +CA,Canada +CC,Cocos (Keeling) Islands +CD,Congo (the Democratic Republic of the) +CF,Central African Republic +CG,Congo +CH,Switzerland +CI,Côte d'Ivoire +CK,Cook Islands +CL,Chile +CM,Cameroon +CN,China +CO,Colombia +CR,Costa Rica +CU,Cuba +CV,Cabo Verde +CW,Curaçao +CX,Christmas Island +CY,Cyprus +CZ,Czechia +DE,Germany +DJ,Djibouti +DK,Denmark +DM,Dominica +DO,Dominican Republic +DZ,Algeria +EC,Ecuador +EE,Estonia +EG,Egypt +EH,Western Sahara +ER,Eritrea +ES,Spain +ET,Ethiopia +FI,Finland +FJ,Fiji +FK,Falkland Islands [Malvinas] +FM,Micronesia (Federated States of) +FO,Faroe Islands +FR,France +GA,Gabon +GB,United Kingdom of Great Britain and Northern Ireland +GD,Grenada +GE,Georgia +GF,French Guiana +GG,Guernsey +GH,Ghana +GI,Gibraltar +GL,Greenland +GM,Gambia +GN,Guinea +GP,Guadeloupe +GQ,Equatorial Guinea +GR,Greece +GS,South Georgia and the South Sandwich Islands +GT,Guatemala +GU,Guam +GW,Guinea-Bissau +GY,Guyana +HK,Hong Kong +HM,Heard Island and McDonald Islands +HN,Honduras +HR,Croatia +HT,Haiti +HU,Hungary +ID,Indonesia +IE,Ireland +IL,Israel +IM,Isle of Man +IN,India +IO,British Indian Ocean Territory +IQ,Iraq +IR,Iran (Islamic Republic of) +IS,Iceland +IT,Italy +JE,Jersey +JM,Jamaica +JO,Jordan +JP,Japan +KE,Kenya +KG,Kyrgyzstan +KH,Cambodia +KI,Kiribati +KM,Comoros +KN,Saint Kitts and Nevis +KP,Korea (the Democratic People's Republic of) +KR,Korea (the Republic of) +KW,Kuwait +KY,Cayman Islands +KZ,Kazakhstan +LA,Lao People's Democratic Republic +LB,Lebanon +LC,Saint Lucia +LI,Liechtenstein +LK,Sri Lanka +LR,Liberia +LS,Lesotho +LT,Lithuania +LU,Luxembourg +LV,Latvia +LY,Libya +MA,Morocco +MC,Monaco +MD,Moldova (the Republic of) +ME,Montenegro +MF,Saint Martin (French part) +MG,Madagascar +MH,Marshall Islands +MK,North Macedonia +ML,Mali +MM,Myanmar +MN,Mongolia +MO,Macao +MP,Northern Mariana Islands +MQ,Martinique +MR,Mauritania +MS,Montserrat +MT,Malta +MU,Mauritius +MV,Maldives +MW,Malawi +MX,Mexico +MY,Malaysia +MZ,Mozambique +NA,Namibia +NC,New Caledonia +NE,Niger +NF,Norfolk Island +NG,Nigeria +NI,Nicaragua +NL,Netherlands +NO,Norway +NP,Nepal +NR,Nauru +NU,Niue +NZ,New Zealand +OM,Oman +PA,Panama +PE,Peru +PF,French Polynesia +PG,Papua New Guinea +PH,Philippines +PK,Pakistan +PL,Poland +PM,Saint Pierre and Miquelon +PN,Pitcairn +PR,Puerto Rico +PS,"Palestine, State of" +PT,Portugal +PW,Palau +PY,Paraguay +QA,Qatar +RE,Réunion +RO,Romania +RS,Serbia +RU,Russian Federation +RW,Rwanda +SA,Saudi Arabia +SB,Solomon Islands +SC,Seychelles +SD,Sudan +SE,Sweden +SG,Singapore +SH,"Saint Helena, Ascension and Tristan da Cunha" +SI,Slovenia +SJ,Svalbard and Jan Mayen +SK,Slovakia +SL,Sierra Leone +SM,San Marino +SN,Senegal +SO,Somalia +SR,Suriname +SS,South Sudan +ST,Sao Tome and Principe +SV,El Salvador +SX,Sint Maarten (Dutch part) +SY,Syrian Arab Republic +SZ,Eswatini +TC,Turks and Caicos Islands +TD,Chad +TF,French Southern Territories +TG,Togo +TH,Thailand +TJ,Tajikistan +TK,Tokelau +TL,Timor-Leste +TM,Turkmenistan +TN,Tunisia +TO,Tonga +TR,Turkey +TT,Trinidad and Tobago +TV,Tuvalu +TW,Taiwan (Province of China) +TZ,"Tanzania, the United Republic of" +UA,Ukraine +UG,Uganda +UM,United States Minor Outlying Islands +US,United States of America +UY,Uruguay +UZ,Uzbekistan +VA,Holy See +VC,Saint Vincent and the Grenadines +VE,Venezuela (Bolivarian Republic of) +VG,Virgin Islands (British) +VI,Virgin Islands (U.S.) +VN,Viet Nam +VU,Vanuatu +WF,Wallis and Futuna +WS,Samoa +XK,Kosovo +YE,Yemen +YT,Mayotte +ZA,South Africa +ZM,Zambia +ZW,Zimbabwe diff --git a/schema/project-level/project-schema.json b/schema/project-level/project-schema.json index 31606722..88c485db 100644 --- a/schema/project-level/project-schema.json +++ b/schema/project-level/project-schema.json @@ -1244,6 +1244,16 @@ "uniqueItems": true, "minItems": 1 }, + "beneficialOwners": { + "title": "Beneficial owners", + "description": "The beneficial owners of the organization.", + "type": "array", + "items": { + "$ref": "#/definitions/Person" + }, + "uniqueItems": true, + "minItems": 1 + }, "people": { "title": "People", "description": "People associated with, representing, or working on behalf of this organization in respect of this project.", @@ -1773,17 +1783,323 @@ "title": "Person", "description": "A natural person.", "type": "object", + "required": [ + "id" + ], "properties": { "id": { - "title": "Identifier", - "description": "A local identifier for this person.", + "title": "ID", + "description": "A local identifier for the person.", "type": "string", "minLength": 1 }, "name": { "title": "Name", "description": "The full name of the person.", - "type": "string", + "type": [ + "string" + ], + "minLength": 1 + }, + "identifier": { + "title": "Identifier", + "description": "An official identifier for the person. The scheme should follow the pattern {JURISDICTION}-{TYPE}, where JURISDICTION is a three-letter, uppercase ISO 3166-1 alpha-3 country code, and TYPE is one of \"PASSPORT\", \"TAXID\" or \"IDCARD\".", + "$ref": "#/definitions/Identifier" + }, + "nationalities": { + "title": "Nationalities", + "description": "The nationalities of the person, from the closed country codelist.", + "type": [ + "array" + ], + "items": { + "type": "string", + "enum": [ + "AD", + "AE", + "AF", + "AG", + "AI", + "AL", + "AM", + "AO", + "AQ", + "AR", + "AS", + "AT", + "AU", + "AW", + "AX", + "AZ", + "BA", + "BB", + "BD", + "BE", + "BF", + "BG", + "BH", + "BI", + "BJ", + "BL", + "BM", + "BN", + "BO", + "BQ", + "BR", + "BS", + "BT", + "BV", + "BW", + "BY", + "BZ", + "CA", + "CC", + "CD", + "CF", + "CG", + "CH", + "CI", + "CK", + "CL", + "CM", + "CN", + "CO", + "CR", + "CU", + "CV", + "CW", + "CX", + "CY", + "CZ", + "DE", + "DJ", + "DK", + "DM", + "DO", + "DZ", + "EC", + "EE", + "EG", + "EH", + "ER", + "ES", + "ET", + "FI", + "FJ", + "FK", + "FM", + "FO", + "FR", + "GA", + "GB", + "GD", + "GE", + "GF", + "GG", + "GH", + "GI", + "GL", + "GM", + "GN", + "GP", + "GQ", + "GR", + "GS", + "GT", + "GU", + "GW", + "GY", + "HK", + "HM", + "HN", + "HR", + "HT", + "HU", + "ID", + "IE", + "IL", + "IM", + "IN", + "IO", + "IQ", + "IR", + "IS", + "IT", + "JE", + "JM", + "JO", + "JP", + "KE", + "KG", + "KH", + "KI", + "KM", + "KN", + "KP", + "KR", + "KW", + "KY", + "KZ", + "LA", + "LB", + "LC", + "LI", + "LK", + "LR", + "LS", + "LT", + "LU", + "LV", + "LY", + "MA", + "MC", + "MD", + "ME", + "MF", + "MG", + "MH", + "MK", + "ML", + "MM", + "MN", + "MO", + "MP", + "MQ", + "MR", + "MS", + "MT", + "MU", + "MV", + "MW", + "MX", + "MY", + "MZ", + "NA", + "NC", + "NE", + "NF", + "NG", + "NI", + "NL", + "NO", + "NP", + "NR", + "NU", + "NZ", + "OM", + "PA", + "PE", + "PF", + "PG", + "PH", + "PK", + "PL", + "PM", + "PN", + "PR", + "PS", + "PT", + "PW", + "PY", + "QA", + "RE", + "RO", + "RS", + "RU", + "RW", + "SA", + "SB", + "SC", + "SD", + "SE", + "SG", + "SH", + "SI", + "SJ", + "SK", + "SL", + "SM", + "SN", + "SO", + "SR", + "SS", + "ST", + "SV", + "SX", + "SY", + "SZ", + "TC", + "TD", + "TF", + "TG", + "TH", + "TJ", + "TK", + "TL", + "TM", + "TN", + "TO", + "TR", + "TT", + "TV", + "TW", + "TZ", + "UA", + "UG", + "UM", + "US", + "UY", + "UZ", + "VA", + "VC", + "VE", + "VG", + "VI", + "VN", + "VU", + "WF", + "WS", + "XK", + "YE", + "YT", + "ZA", + "ZM", + "ZW" + ] + }, + "codelist": "country.csv", + "openCodelist": false, + "uniqueItems": true, + "minItems": 1 + }, + "address": { + "title": "Address", + "description": "The address of the person.", + "$ref": "#/definitions/Address" + }, + "email": { + "title": "Email", + "description": "The e-mail address of the person.", + "type": [ + "string" + ], + "format": "email", + "minLength": 1 + }, + "faxNumber": { + "title": "Fax number", + "description": "The fax number of the person. This must include the international dialing code.", + "type": [ + "string" + ], + "minLength": 1 + }, + "telephone": { + "title": "Telephone", + "description": "The telephone number of the person. This must include the international dialing code.", + "type": [ + "string" + ], "minLength": 1 }, "jobTitle": { @@ -1793,9 +2109,6 @@ "minLength": 1 } }, - "required": [ - "id" - ], "minProperties": 1 }, "Transaction": { From ef102e7cb48aeb44377baffc1dc4139cc09eea9f Mon Sep 17 00:00:00 2001 From: Duncan Dewhurst Date: Mon, 13 Nov 2023 10:49:37 +1300 Subject: [PATCH 2/7] Update changelog --- docs/reference/changelog.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/reference/changelog.md b/docs/reference/changelog.md index ff4f09f9..2a85ac1d 100644 --- a/docs/reference/changelog.md +++ b/docs/reference/changelog.md @@ -28,6 +28,7 @@ * `.transactions` * `.milestones` * `ContractingProcesses.milestones` +* [#427](https://github.com/open-contracting/infrastructure/pull/427) - add `Organization.beneficialOwners` ### Codelists @@ -38,6 +39,7 @@ * milestoneType * milestoneStatus * milestoneCode +* [#427](https://github.com/open-contracting/infrastructure/pull/427) - add country codelist. ### Other From a912ad10d33beb870069f96999418a427cd791fd Mon Sep 17 00:00:00 2001 From: Duncan Dewhurst Date: Mon, 13 Nov 2023 10:51:30 +1300 Subject: [PATCH 3/7] .github/workflows/spellcheck.yml: Add currency exceptions --- .github/workflows/spellcheck.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/spellcheck.yml b/.github/workflows/spellcheck.yml index 86e5fabe..a8f9dd0d 100644 --- a/.github/workflows/spellcheck.yml +++ b/.github/workflows/spellcheck.yml @@ -10,4 +10,4 @@ jobs: with: python-version: '3.10' - run: pip install codespell - - run: codespell -S .git,docson,locale,currency.csv -L tne,zar . + - run: codespell -S .git,docson,locale,currency.csv -L tne,zar,fo,nam . From 11df32585aefa6068d1bb3c2913a4d7766905ab7 Mon Sep 17 00:00:00 2001 From: Duncan Dewhurst Date: Mon, 13 Nov 2023 11:04:53 +1300 Subject: [PATCH 4/7] mapping/sustainability.yaml: Update beneficial ownership --- docs/cost/ids/sustainability.md | 82 ++++++++++++++++++++++----------- mapping/sustainability.yaml | 29 +++++++++++- 2 files changed, 83 insertions(+), 28 deletions(-) diff --git a/docs/cost/ids/sustainability.md b/docs/cost/ids/sustainability.md index d89df18e..3a4b2879 100644 --- a/docs/cost/ids/sustainability.md +++ b/docs/cost/ids/sustainability.md @@ -1466,38 +1466,45 @@ 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 +- 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 +- 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" + "title": "Grant disbursement", "status": "met", "dueDate": "2023-07-01T00:00:00Z", "dateMet": "2023-08-01T00:00:00Z", @@ -2876,9 +2883,32 @@ Disclose the beneficial owners of the contractors and suppliers appointed in the :columns: 8 OC4IDS mapping ^^^ -Use modelling from OCDS Beneficial Owners extension -```json +For each beneficial owner: +- Get the `Organization` in `.parties` that represents the contractor or supplier. +- Add a `Person` object to the organization's `.beneficialOwners` array. +- Set the person's: + - `.id` incrementally + - `.name` to the beneficial owner's name + - `.identifier` to the beneficial owner's identifier +```json +{ + "parties": [ + { + "id": "1", + "beneficialOwners": [ + { + "id": "1", + "name": "Juan Perez", + "identifier": { + "scheme": "PRY-IDCARD", + "id": "12345" + } + } + ] + } + ] +} ``` ```` diff --git a/mapping/sustainability.yaml b/mapping/sustainability.yaml index f11e6f83..b90c333a 100644 --- a/mapping/sustainability.yaml +++ b/mapping/sustainability.yaml @@ -1758,8 +1758,33 @@ module: Institutional indicator: Access to information disclosure format: Disclose the beneficial owners of the contractors and suppliers appointed in the project (E.g. \[name, identifier\]). - mapping: Use modelling from OCDS Beneficial Owners extension - example: '' + mapping: |- + For each beneficial owner: + + - Get the `Organization` in `.parties` that represents the contractor or supplier. + - Add a `Person` object to the organization's `.beneficialOwners` array. + - Set the person's: + - `.id` incrementally + - `.name` to the beneficial owner's name + - `.identifier` to the beneficial owner's identifier + example: |- + { + "parties": [ + { + "id": "1", + "beneficialOwners": [ + { + "id": "1", + "name": "Juan Perez", + "identifier": { + "scheme": "PRY-IDCARD", + "id": "12345" + } + } + ] + } + ] + } - id: '5.6' title: Sustainability criteria module: Institutional From f23f1865ebc1c3527f19ce2e9c3194ac6d711cf1 Mon Sep 17 00:00:00 2001 From: Duncan Dewhurst Date: Mon, 13 Nov 2023 14:11:08 +1300 Subject: [PATCH 5/7] Update .github/workflows/spellcheck.yml Co-authored-by: James McKinney <26463+jpmckinney@users.noreply.github.com> --- .github/workflows/spellcheck.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/spellcheck.yml b/.github/workflows/spellcheck.yml index a8f9dd0d..989c9bd4 100644 --- a/.github/workflows/spellcheck.yml +++ b/.github/workflows/spellcheck.yml @@ -10,4 +10,4 @@ jobs: with: python-version: '3.10' - run: pip install codespell - - run: codespell -S .git,docson,locale,currency.csv -L tne,zar,fo,nam . + - run: codespell -S .git,docson,locale,country.csv,currency.csv -L fo,tne,zar . From 29cb3e0cce565b00e0e4e2ab82178bc68a2bbebe Mon Sep 17 00:00:00 2001 From: Duncan Dewhurst Date: Mon, 13 Nov 2023 14:13:07 +1300 Subject: [PATCH 6/7] docs/reference/changelog.md: Copy edit --- docs/reference/changelog.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/reference/changelog.md b/docs/reference/changelog.md index 2a85ac1d..e8a9fd42 100644 --- a/docs/reference/changelog.md +++ b/docs/reference/changelog.md @@ -33,13 +33,13 @@ ### 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 -* [#427](https://github.com/open-contracting/infrastructure/pull/427) - add country codelist. +* add codelists: + * [#369](https://github.com/open-contracting/infrastructure/pull/369) - classificationScheme + * [#427](https://github.com/open-contracting/infrastructure/pull/427) - country + * [#426](https://github.com/open-contracting/infrastructure/pull/426) - milestoneType + * [#426](https://github.com/open-contracting/infrastructure/pull/426) - milestoneStatus + * [#426](https://github.com/open-contracting/infrastructure/pull/426) - milestoneCode ### Other From 8e0209c5b89af57b62ab60127837b7f68399e3f9 Mon Sep 17 00:00:00 2001 From: Duncan Dewhurst Date: Mon, 13 Nov 2023 14:16:05 +1300 Subject: [PATCH 7/7] manage.py (pre-commit): Improve clarity of paths_to_skip logic --- manage.py | 27 ++++++++++----------------- 1 file changed, 10 insertions(+), 17 deletions(-) diff --git a/manage.py b/manage.py index 10bd0cf6..bfc7990c 100755 --- a/manage.py +++ b/manage.py @@ -343,23 +343,16 @@ def update_sub_schema_reference(schema): # Add examples definition["references"] = get_definition_references(schema, defn) for ref in definition["references"]: - if ref[0] not in schema['definitions']: - skip = False - - for path_to_skip in paths_to_skip: - if path_to_skip == '/'.join(ref)[:len(path_to_skip)]: - skip = True - - if not skip: - if ref[-1] == '0': - ref.pop(-1) - - definition["content"].extend([ - "```{jsoninclude} ../../docs/examples/example.json\n", - f":jsonpointer: /projects/0/{'/'.join(ref)}\n", - f":title: {'/'.join(ref)}\n", - "```\n\n" - ]) + if ref[0] not in schema['definitions'] and not any(p == '/'.join(ref)[:len(p)] for p in paths_to_skip): + if ref[-1] == '0': + ref.pop(-1) + + definition["content"].extend([ + "```{jsoninclude} ../../docs/examples/example.json\n", + f":jsonpointer: /projects/0/{'/'.join(ref)}\n", + f":title: {'/'.join(ref)}\n", + "```\n\n" + ]) definition["content"].extend([ "````\n\n",