opencost 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- opencost/__init__.py +100 -0
- opencost/_common.py +9 -0
- opencost/_contract.py +103 -0
- opencost/_institution.py +59 -0
- opencost/_invoice.py +218 -0
- opencost/_publication.py +274 -0
- opencost/_types.py +85 -0
- opencost/_validators.py +37 -0
- opencost/xml/__init__.py +19 -0
- opencost/xml/_common.py +3 -0
- opencost/xml/_deserialize.py +139 -0
- opencost/xml/_serialize.py +104 -0
- opencost-0.1.0.dist-info/METADATA +186 -0
- opencost-0.1.0.dist-info/RECORD +15 -0
- opencost-0.1.0.dist-info/WHEEL +4 -0
opencost/__init__.py
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
"""Pydantic models for the openCost metadata schema, with XML (de)serialization.
|
|
2
|
+
|
|
3
|
+
openCost (https://github.com/opencost-de/opencost) is a metadata schema for
|
|
4
|
+
the financial side of scholarly publishing: article-level cost data
|
|
5
|
+
(``publication``) and contracts / transformative agreements (``contract``).
|
|
6
|
+
|
|
7
|
+
>>> from opencost import Data, PublicationType, from_xml, to_xml
|
|
8
|
+
>>> xml = to_xml(Data(publication=[...])) # models -> openCost XML
|
|
9
|
+
>>> data = from_xml('<data xmlns="https://opencost.de">…</data>') # XML -> models
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
from ._types import NonEmptyString as NonEmptyString
|
|
13
|
+
from ._types import Currency as Currency
|
|
14
|
+
from ._types import DateFormat as DateFormat
|
|
15
|
+
from ._types import ContractCostType as ContractCostType
|
|
16
|
+
from ._types import PublicationCostType as PublicationCostType
|
|
17
|
+
from ._common import Data as Data
|
|
18
|
+
from ._contract import ContractType as ContractType
|
|
19
|
+
from ._contract import ContractPrimaryIdentifier as ContractPrimaryIdentifier
|
|
20
|
+
from ._contract import ContractPrimaryIdentifierType as ContractPrimaryIdentifierType
|
|
21
|
+
from ._contract import ContractSecondaryIdType as ContractSecondaryIdType
|
|
22
|
+
from ._contract import ContractSecondaryIdTypeEnum as ContractSecondaryIdTypeEnum
|
|
23
|
+
from ._contract import ContractSecondaryIdentifiersType as ContractSecondaryIdentifiersType
|
|
24
|
+
from ._contract import ParticipationType as ParticipationType
|
|
25
|
+
from ._invoice import PublicationInvoiceType as PublicationInvoiceType
|
|
26
|
+
from ._invoice import PublicationAmountPaidType as PublicationAmountPaidType
|
|
27
|
+
from ._invoice import PublicationAmountsPaid as PublicationAmountsPaid
|
|
28
|
+
from ._invoice import AmountInvoice as AmountInvoice
|
|
29
|
+
from ._invoice import Dates as Dates
|
|
30
|
+
from ._invoice import ContractCostDataType as ContractCostDataType
|
|
31
|
+
from ._invoice import ContractAmountPaidType as ContractAmountPaidType
|
|
32
|
+
from ._invoice import ContractAmountsPaid as ContractAmountsPaid
|
|
33
|
+
from ._invoice import ContractInvoiceType as ContractInvoiceType
|
|
34
|
+
from ._invoice import ContractInvoicePeriodType as ContractInvoicePeriodType
|
|
35
|
+
from ._invoice import ContractInvoiceGroupType as ContractInvoiceGroupType
|
|
36
|
+
from ._institution import InstitutionType as InstitutionType
|
|
37
|
+
from ._institution import InstitutionId as InstitutionId
|
|
38
|
+
from ._institution import InstitutionIdType as InstitutionIdType
|
|
39
|
+
from ._institution import InstitutionName as InstitutionName
|
|
40
|
+
from ._institution import InstitutionNameType as InstitutionNameType
|
|
41
|
+
from ._publication import PublicationType as PublicationType
|
|
42
|
+
from ._publication import PublicationPrimaryIdentifier as PublicationPrimaryIdentifier
|
|
43
|
+
from ._publication import PublicationSecondaryIdType as PublicationSecondaryIdType
|
|
44
|
+
from ._publication import PublicationSecondaryIdTypeEnum as PublicationSecondaryIdTypeEnum
|
|
45
|
+
from ._publication import PublicationSecondaryIdentifiers as PublicationSecondaryIdentifiers
|
|
46
|
+
from ._publication import BibliographicInformation as BibliographicInformation
|
|
47
|
+
from ._publication import CoarPublicationType as CoarPublicationType
|
|
48
|
+
from ._publication import PublicationCostDataType as PublicationCostDataType
|
|
49
|
+
from ._publication import PartOfContractType as PartOfContractType
|
|
50
|
+
from ._validators import EitherFieldMixin as EitherFieldMixin
|
|
51
|
+
from ._validators import OpenCostModel as OpenCostModel
|
|
52
|
+
from .xml import NAMESPACE as NAMESPACE
|
|
53
|
+
from .xml import from_xml as from_xml
|
|
54
|
+
from .xml import to_xml as to_xml
|
|
55
|
+
|
|
56
|
+
__all__ = [
|
|
57
|
+
"NonEmptyString",
|
|
58
|
+
"Currency",
|
|
59
|
+
"DateFormat",
|
|
60
|
+
"ContractCostType",
|
|
61
|
+
"PublicationCostType",
|
|
62
|
+
"Data",
|
|
63
|
+
"ContractType",
|
|
64
|
+
"ContractPrimaryIdentifier",
|
|
65
|
+
"ContractPrimaryIdentifierType",
|
|
66
|
+
"ContractSecondaryIdType",
|
|
67
|
+
"ContractSecondaryIdTypeEnum",
|
|
68
|
+
"ContractSecondaryIdentifiersType",
|
|
69
|
+
"ParticipationType",
|
|
70
|
+
"PublicationInvoiceType",
|
|
71
|
+
"PublicationAmountPaidType",
|
|
72
|
+
"PublicationAmountsPaid",
|
|
73
|
+
"AmountInvoice",
|
|
74
|
+
"Dates",
|
|
75
|
+
"ContractCostDataType",
|
|
76
|
+
"ContractAmountPaidType",
|
|
77
|
+
"ContractAmountsPaid",
|
|
78
|
+
"ContractInvoiceType",
|
|
79
|
+
"ContractInvoicePeriodType",
|
|
80
|
+
"ContractInvoiceGroupType",
|
|
81
|
+
"InstitutionType",
|
|
82
|
+
"InstitutionId",
|
|
83
|
+
"InstitutionIdType",
|
|
84
|
+
"InstitutionName",
|
|
85
|
+
"InstitutionNameType",
|
|
86
|
+
"PublicationType",
|
|
87
|
+
"PublicationPrimaryIdentifier",
|
|
88
|
+
"PublicationSecondaryIdType",
|
|
89
|
+
"PublicationSecondaryIdTypeEnum",
|
|
90
|
+
"PublicationSecondaryIdentifiers",
|
|
91
|
+
"BibliographicInformation",
|
|
92
|
+
"CoarPublicationType",
|
|
93
|
+
"PartOfContractType",
|
|
94
|
+
"PublicationCostDataType",
|
|
95
|
+
"EitherFieldMixin",
|
|
96
|
+
"OpenCostModel",
|
|
97
|
+
"NAMESPACE",
|
|
98
|
+
"from_xml",
|
|
99
|
+
"to_xml",
|
|
100
|
+
]
|
opencost/_common.py
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
from ._contract import ContractType
|
|
2
|
+
from ._publication import PublicationType
|
|
3
|
+
from ._validators import EitherFieldMixin
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class Data(EitherFieldMixin):
|
|
7
|
+
either_fields = ("publication", "contract")
|
|
8
|
+
publication: list[PublicationType] | None = None
|
|
9
|
+
contract: list[ContractType] | None = None
|
opencost/_contract.py
ADDED
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
# Field descriptions and notes are taken from the openCost documentation
|
|
2
|
+
# (doc/README.md of https://github.com/opencost-de/opencost), GPL-3.0-or-later,
|
|
3
|
+
# vendored as submodule vendor/opencost @ af6d257.
|
|
4
|
+
from enum import Enum
|
|
5
|
+
from typing import Annotated
|
|
6
|
+
|
|
7
|
+
from pydantic import Field
|
|
8
|
+
|
|
9
|
+
from ._institution import InstitutionType
|
|
10
|
+
from ._invoice import ContractCostDataType
|
|
11
|
+
from ._types import DateFormat, NonEmptyString
|
|
12
|
+
from ._validators import OpenCostModel
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class ContractPrimaryIdentifierType(Enum):
|
|
16
|
+
"""Contract primary identifier scheme (§5.1).
|
|
17
|
+
|
|
18
|
+
Currently only ESAC is accepted.
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
ESAC = "ESAC"
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class ContractPrimaryIdentifier(OpenCostModel):
|
|
25
|
+
"""Persistent, global identifier for the contract (§5).
|
|
26
|
+
|
|
27
|
+
Currently only an ESAC ID is accepted
|
|
28
|
+
(https://esac-initiative.org/about/transformative-agreements/agreement-registry/).
|
|
29
|
+
"""
|
|
30
|
+
|
|
31
|
+
value: NonEmptyString = Field(description="ESAC agreement id of the contract.")
|
|
32
|
+
type: ContractPrimaryIdentifierType = Field(
|
|
33
|
+
description="Identifier scheme; currently only `ESAC`."
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
class ContractSecondaryIdTypeEnum(Enum):
|
|
38
|
+
"""Contract secondary identifier scheme (§6.1.1)."""
|
|
39
|
+
|
|
40
|
+
oai = "oai"
|
|
41
|
+
ezb = "ezb"
|
|
42
|
+
local = "local"
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
class ContractSecondaryIdType(OpenCostModel):
|
|
46
|
+
"""Secondary identifier for the contract (§6.1)."""
|
|
47
|
+
|
|
48
|
+
value: NonEmptyString = Field(description="Identifier value.")
|
|
49
|
+
type: ContractSecondaryIdTypeEnum = Field(description="Identifier scheme of `value`.")
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
class ContractSecondaryIdentifiersType(OpenCostModel):
|
|
53
|
+
"""Contains additional, optional identifiers for the contract (§6)."""
|
|
54
|
+
|
|
55
|
+
id: Annotated[
|
|
56
|
+
list[ContractSecondaryIdType],
|
|
57
|
+
Field(min_length=1, description="Additional (persistent) identifiers."),
|
|
58
|
+
]
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
class ParticipationType(OpenCostModel):
|
|
62
|
+
"""Contains information on the dates an institution joined and left a
|
|
63
|
+
contract (§4)."""
|
|
64
|
+
|
|
65
|
+
to: DateFormat = Field(
|
|
66
|
+
description="The date when the institution left the contract. Not to "
|
|
67
|
+
"be confused with the end date of the agreement itself, which may be "
|
|
68
|
+
"later."
|
|
69
|
+
)
|
|
70
|
+
from_: DateFormat = Field(
|
|
71
|
+
...,
|
|
72
|
+
alias="from",
|
|
73
|
+
description="The date when the institution joined the contract. Not "
|
|
74
|
+
"to be confused with the start date of the agreement itself, which "
|
|
75
|
+
"may be earlier.",
|
|
76
|
+
)
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
class ContractType(OpenCostModel):
|
|
80
|
+
"""Top-level element, corresponds to a contract for which costs are to be
|
|
81
|
+
recorded (§1).
|
|
82
|
+
|
|
83
|
+
Examples of such contracts are transformative agreements and memberships.
|
|
84
|
+
"""
|
|
85
|
+
|
|
86
|
+
contract_name: NonEmptyString = Field(description="A human-readable label for the contract.")
|
|
87
|
+
institution: InstitutionType = Field(
|
|
88
|
+
description="Contains information to identify the institution taking part in the contract."
|
|
89
|
+
)
|
|
90
|
+
participation: ParticipationType = Field(
|
|
91
|
+
description="The dates the institution joined and left the contract."
|
|
92
|
+
)
|
|
93
|
+
primary_identifier: ContractPrimaryIdentifier = Field(
|
|
94
|
+
description="Persistent, global identifier for the contract; "
|
|
95
|
+
"currently only an ESAC ID is accepted."
|
|
96
|
+
)
|
|
97
|
+
secondary_identifiers: ContractSecondaryIdentifiersType | None = Field(
|
|
98
|
+
default=None,
|
|
99
|
+
description="Additional, optional identifiers for the contract.",
|
|
100
|
+
)
|
|
101
|
+
cost_data: ContractCostDataType = Field(
|
|
102
|
+
description="Aggregates payments related to this contract."
|
|
103
|
+
)
|
opencost/_institution.py
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# Field descriptions and notes are taken from the openCost documentation
|
|
2
|
+
# (doc/README.md of https://github.com/opencost-de/opencost), GPL-3.0-or-later,
|
|
3
|
+
# vendored as submodule vendor/opencost @ af6d257.
|
|
4
|
+
from enum import Enum
|
|
5
|
+
|
|
6
|
+
from pydantic import Field
|
|
7
|
+
|
|
8
|
+
from ._types import NonEmptyString
|
|
9
|
+
from ._validators import EitherFieldMixin, OpenCostModel
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class InstitutionIdType(Enum):
|
|
13
|
+
"""Identifier scheme an institution can be referenced by."""
|
|
14
|
+
|
|
15
|
+
ror = "ror"
|
|
16
|
+
isni = "isni"
|
|
17
|
+
ringold = "ringold"
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class InstitutionId(OpenCostModel):
|
|
21
|
+
"""Contains persistent identifiers for an institution (§4.1, §3.1)."""
|
|
22
|
+
|
|
23
|
+
value: NonEmptyString = Field(description="Institution identifier value, e.g. a ROR id.")
|
|
24
|
+
type: InstitutionIdType = Field(description="Identifier scheme of `value`.")
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class InstitutionNameType(Enum):
|
|
28
|
+
"""Whether the name is given in full or abbreviated."""
|
|
29
|
+
|
|
30
|
+
full = "full"
|
|
31
|
+
short = "short"
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
class InstitutionName(OpenCostModel):
|
|
35
|
+
"""Human-readable institution name (§4.2, §3.2)."""
|
|
36
|
+
|
|
37
|
+
value: NonEmptyString = Field(description="Name of the institution.")
|
|
38
|
+
type: InstitutionNameType = Field(description="`full` or `short` name form.")
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
class InstitutionType(EitherFieldMixin):
|
|
42
|
+
"""Contains information to identify the institution.
|
|
43
|
+
|
|
44
|
+
Either `id` (persistent identifiers) or `name` (human-readable) must be
|
|
45
|
+
given.
|
|
46
|
+
"""
|
|
47
|
+
|
|
48
|
+
either_fields = ("name", "id")
|
|
49
|
+
name: list[InstitutionName] | None = Field(
|
|
50
|
+
default=None,
|
|
51
|
+
description=(
|
|
52
|
+
"The names are meant to be human-readable. Either this element or "
|
|
53
|
+
"the institution's `id` is required."
|
|
54
|
+
),
|
|
55
|
+
)
|
|
56
|
+
id: list[InstitutionId] | None = Field(
|
|
57
|
+
default=None,
|
|
58
|
+
description="Either this element or the institution's `name` is required.",
|
|
59
|
+
)
|
opencost/_invoice.py
ADDED
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
# Field descriptions and notes are taken from the openCost documentation
|
|
2
|
+
# (doc/README.md of https://github.com/opencost-de/opencost), GPL-3.0-or-later,
|
|
3
|
+
# vendored as submodule vendor/opencost @ af6d257.
|
|
4
|
+
from decimal import Decimal
|
|
5
|
+
from typing import Annotated
|
|
6
|
+
|
|
7
|
+
from pydantic import Field
|
|
8
|
+
|
|
9
|
+
from ._types import ContractCostType, Currency, DateFormat, NonEmptyString, PublicationCostType
|
|
10
|
+
from ._validators import EitherFieldMixin, OpenCostModel
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class PublicationAmountPaidType(OpenCostModel):
|
|
14
|
+
"""A single amount paid by the institution (§7.2.5.1).
|
|
15
|
+
|
|
16
|
+
Usually corresponding to an item on the invoice.
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
currency: Currency = Field(description="ISO 4217 currency code of the `amount_paid`.")
|
|
20
|
+
amount: Decimal = Field(
|
|
21
|
+
description="Amount of the `amount_paid`. Net monetary value. "
|
|
22
|
+
"Negative or zero values are valid to denote reimbursements or "
|
|
23
|
+
"Diamond OA models."
|
|
24
|
+
)
|
|
25
|
+
cost_type: PublicationCostType = Field(
|
|
26
|
+
description="Describes the object/purpose of the payment. If the VAT "
|
|
27
|
+
"cannot be subdivided specifically for the individual cost types, but "
|
|
28
|
+
"only for the total amount of the invoice, a separate entry with the "
|
|
29
|
+
"`cost_type` `vat` is possible here instead of the `vat` field "
|
|
30
|
+
"(7.2.5.1.4)."
|
|
31
|
+
)
|
|
32
|
+
vat: Decimal | None = Field(
|
|
33
|
+
default=None,
|
|
34
|
+
description="Vat of the `amount_paid`. State in the same currency as "
|
|
35
|
+
"`amount`. Must be specified and assigned according to the individual "
|
|
36
|
+
"cost type; if a differentiated specification is not possible, use a "
|
|
37
|
+
"separate entry with `cost_type` `vat` (7.2.5.1.3).",
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
class PublicationAmountsPaid(OpenCostModel):
|
|
42
|
+
"""Contains all itemized amounts paid corresponding to one invoice (§7.2.5)."""
|
|
43
|
+
|
|
44
|
+
amount_paid: Annotated[
|
|
45
|
+
list[PublicationAmountPaidType],
|
|
46
|
+
Field(min_length=1, description="The itemized amounts paid."),
|
|
47
|
+
]
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
class AmountInvoice(OpenCostModel):
|
|
51
|
+
"""Contains the total price as stated on the invoice (§7.2.4, §7.1.3.4)."""
|
|
52
|
+
|
|
53
|
+
currency: Currency = Field(
|
|
54
|
+
description="ISO 4217 currency code of the total amount as stated on the invoice."
|
|
55
|
+
)
|
|
56
|
+
amount: Decimal = Field(
|
|
57
|
+
description="Total amount as stated on the invoice. Net monetary value."
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
class Dates(EitherFieldMixin):
|
|
62
|
+
"""Contains different payment-related dates (§7.2.3).
|
|
63
|
+
|
|
64
|
+
At least one of `invoice` or `paid` must be given.
|
|
65
|
+
"""
|
|
66
|
+
|
|
67
|
+
either_fields = ("invoice", "paid")
|
|
68
|
+
|
|
69
|
+
invoice: DateFormat | None = Field(
|
|
70
|
+
default=None,
|
|
71
|
+
description="Invoice date. Either this element or the date `paid` is required.",
|
|
72
|
+
)
|
|
73
|
+
paid: DateFormat | None = Field(
|
|
74
|
+
default=None,
|
|
75
|
+
description="Date of payment. Either this element or the invoice date is required.",
|
|
76
|
+
)
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
class PublicationInvoiceType(OpenCostModel):
|
|
80
|
+
"""Encapsulates payment information, meant to correspond to a real-world
|
|
81
|
+
invoice (§7.2)."""
|
|
82
|
+
|
|
83
|
+
amount_invoice: AmountInvoice | None = Field(
|
|
84
|
+
default=None,
|
|
85
|
+
description="The total price as stated on the invoice.",
|
|
86
|
+
)
|
|
87
|
+
invoice_number: NonEmptyString | None = Field(
|
|
88
|
+
default=None,
|
|
89
|
+
description="Optional invoice number. As mentioned on the invoice.",
|
|
90
|
+
)
|
|
91
|
+
amounts_paid: PublicationAmountsPaid = Field(
|
|
92
|
+
description="All itemized amounts paid corresponding to this invoice."
|
|
93
|
+
)
|
|
94
|
+
dates: Dates = Field(description="Payment-related dates of this invoice.")
|
|
95
|
+
creditor: NonEmptyString | None = Field(
|
|
96
|
+
default=None,
|
|
97
|
+
description="Payment receiver as mentioned on the invoice. Might not "
|
|
98
|
+
"be the actual publisher, but also e.g. a service provider from "
|
|
99
|
+
"another publisher.",
|
|
100
|
+
)
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
class ContractAmountPaidType(OpenCostModel):
|
|
104
|
+
"""An amount paid by the institution (§7.1.3.5.1).
|
|
105
|
+
|
|
106
|
+
Usually corresponding to an item on the invoice.
|
|
107
|
+
"""
|
|
108
|
+
|
|
109
|
+
currency: Currency = Field(description="ISO 4217 currency code of the `amount_paid`.")
|
|
110
|
+
amount: Decimal = Field(
|
|
111
|
+
description="Amount of the `amount_paid`. Net monetary value. "
|
|
112
|
+
"Negative or zero values are valid to denote reimbursements."
|
|
113
|
+
)
|
|
114
|
+
cost_type: ContractCostType = Field(
|
|
115
|
+
description="Describes the object/purpose of the payment. If the VAT "
|
|
116
|
+
"cannot be subdivided specifically for the individual cost types, but "
|
|
117
|
+
"only for the total amount of the invoice, a separate entry with the "
|
|
118
|
+
"`cost_type` `vat` is possible here instead of the `vat` field "
|
|
119
|
+
"(7.1.3.5.1.4)."
|
|
120
|
+
)
|
|
121
|
+
vat: Decimal | None = Field(
|
|
122
|
+
default=None,
|
|
123
|
+
description="Vat of the `amount_paid`. State in the same currency as "
|
|
124
|
+
"`amount`. Must be specified and assigned according to the individual "
|
|
125
|
+
"cost type; if a differentiated specification is not possible, use a "
|
|
126
|
+
"separate entry with `cost_type` `vat` (7.1.3.5.1.3).",
|
|
127
|
+
)
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
class ContractAmountsPaid(OpenCostModel):
|
|
131
|
+
"""Contains all itemized amounts paid corresponding to one invoice of a
|
|
132
|
+
contract (§7.1.3.5)."""
|
|
133
|
+
|
|
134
|
+
amount_paid: Annotated[
|
|
135
|
+
list[ContractAmountPaidType],
|
|
136
|
+
Field(min_length=1, description="The itemized amounts paid."),
|
|
137
|
+
]
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
class ContractInvoiceType(OpenCostModel):
|
|
141
|
+
"""Encapsulates payment information for a contract, meant to correspond to
|
|
142
|
+
a real-world invoice (§7.1.3)."""
|
|
143
|
+
|
|
144
|
+
amount_invoice: AmountInvoice | None = Field(
|
|
145
|
+
default=None,
|
|
146
|
+
description="The total price as stated on the invoice for the contract.",
|
|
147
|
+
)
|
|
148
|
+
invoice_number: NonEmptyString | None = Field(
|
|
149
|
+
default=None,
|
|
150
|
+
description="Optional invoice number. As mentioned on the invoice.",
|
|
151
|
+
)
|
|
152
|
+
creditor: NonEmptyString | None = Field(
|
|
153
|
+
default=None,
|
|
154
|
+
description="Payment receiver as mentioned on the invoice. Might not "
|
|
155
|
+
"be the actual publisher, but also e.g. a service provider.",
|
|
156
|
+
)
|
|
157
|
+
dates: Dates = Field(description="Payment-related dates of this invoice.")
|
|
158
|
+
amounts_paid: ContractAmountsPaid = Field(
|
|
159
|
+
description="All itemized amounts paid corresponding to this invoice."
|
|
160
|
+
)
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
class ContractInvoicePeriodType(OpenCostModel):
|
|
164
|
+
"""Identifies the time frame an invoice refers to (§7.1.2)."""
|
|
165
|
+
|
|
166
|
+
from_: DateFormat = Field(
|
|
167
|
+
...,
|
|
168
|
+
alias="from",
|
|
169
|
+
description="Start date of the time frame the invoice refers to. Can "
|
|
170
|
+
"be different to an institution's contract accession "
|
|
171
|
+
"(`participation // from`) if multiple invoices have been issued over "
|
|
172
|
+
"the total contract duration.",
|
|
173
|
+
)
|
|
174
|
+
to: DateFormat = Field(
|
|
175
|
+
description="End date of the time frame the invoice refers to. Can be "
|
|
176
|
+
"different to an institution's contract termination "
|
|
177
|
+
"(`participation // to`) if multiple invoices have been issued over "
|
|
178
|
+
"the total contract duration."
|
|
179
|
+
)
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
class ContractInvoiceGroupType(OpenCostModel):
|
|
183
|
+
"""Contains all invoices that belong to a billing period within a contract
|
|
184
|
+
(§7.1).
|
|
185
|
+
|
|
186
|
+
Such a contract phase is limited by a time period (`invoices_period`) to
|
|
187
|
+
which a respective invoice can be assigned.
|
|
188
|
+
"""
|
|
189
|
+
|
|
190
|
+
group_id: NonEmptyString = Field(
|
|
191
|
+
description="An id to uniquely name and identify the `invoice_group`. "
|
|
192
|
+
"Necessary to link not only from an individual publication to the "
|
|
193
|
+
"global contract but also to a specific invoice and contract period: "
|
|
194
|
+
"relates cost data for an `opencost:publication` to this contract via "
|
|
195
|
+
"the `opencost:part_of_contract` element. Generating a `uuid` or "
|
|
196
|
+
"using another type of unique identifier is recommended."
|
|
197
|
+
)
|
|
198
|
+
invoices_period: ContractInvoicePeriodType = Field(
|
|
199
|
+
description="Identifies the time frame the invoices in this group refer to."
|
|
200
|
+
)
|
|
201
|
+
invoice: list[ContractInvoiceType] | None = Field(
|
|
202
|
+
default=None,
|
|
203
|
+
description="The invoices belonging to this billing period.",
|
|
204
|
+
)
|
|
205
|
+
|
|
206
|
+
|
|
207
|
+
class ContractCostDataType(OpenCostModel):
|
|
208
|
+
"""Aggregates payments related to a contract (§7, contract).
|
|
209
|
+
|
|
210
|
+
The `invoice` elements can be combined into one or more common
|
|
211
|
+
`invoice_group` elements referring to a shared `invoices_period` of the
|
|
212
|
+
contract concerned.
|
|
213
|
+
"""
|
|
214
|
+
|
|
215
|
+
invoice_group: Annotated[
|
|
216
|
+
list[ContractInvoiceGroupType],
|
|
217
|
+
Field(min_length=1, description="The billing periods of the contract."),
|
|
218
|
+
]
|