diff --git a/codegen/pkg/builder/transform.go b/codegen/pkg/builder/transform.go index 5167a1b..b9ff6c5 100644 --- a/codegen/pkg/builder/transform.go +++ b/codegen/pkg/builder/transform.go @@ -229,7 +229,8 @@ func (b *Builder) generateSchemaComponents(name string, spec *base.Schema) []Wri types = append(types, additionalTypes...) types = append(types, object) case spec.OneOf != nil: - object := createOneOf(spec, name) + object, additionalTypes := b.createOneOf(spec, name) + types = append(types, additionalTypes...) types = append(types, object) case spec.AnyOf != nil: slog.Warn("AnyOf not supported, falling back to 'inteface{}'", @@ -295,7 +296,8 @@ func (b *Builder) genSchema(sp *base.SchemaProxy, name string) (string, []Writab types = append(types, object) return name, types case schema.OneOf != nil: - object := createOneOf(schema, name) + object, additionalTypes := b.createOneOf(schema, name) + types = append(types, additionalTypes...) types = append(types, object) return name, types case schema.AnyOf != nil: @@ -506,16 +508,31 @@ func (b *Builder) createAllOf(schema *base.Schema, name string) (*ClassDeclarati }, types } -// createOneOf creates a type declaration for `oneOf` schema. -func createOneOf(schema *base.Schema, name string) *ClassDeclaration { - // TODO: implement `func (v *{{name}}) AsXXX() (XXX, error) { ... }` - // that allows converting one of from `json.RawMessage` to possible variants. +// createOneOf creates a union declaration for `oneOf` schema and emits any +// additional inline branch types needed by the union. +func (b *Builder) createOneOf(schema *base.Schema, name string) (*OneOfDeclaration, []Writable) { + types := make([]Writable, 0) + options := make([]string, 0, len(schema.OneOf)) - return &ClassDeclaration{ - Description: schemaDoc(name, schema), - Name: name, - Type: "json.RawMessage", + for i, option := range schema.OneOf { + optionName := oneOfOptionName(name, i, option.Schema()) + typeName, additionalTypes := b.genSchema(option, optionName) + types = append(types, additionalTypes...) + options = append(options, typeName) } + + return &OneOfDeclaration{ + Name: name, + Options: uniqueFunc(options, func(option string) string { return option }), + }, types +} + +func oneOfOptionName(name string, index int, schema *base.Schema) string { + if schema != nil && schema.Title != "" { + return name + strcase.ToCamel(schema.Title) + } + + return fmt.Sprintf("%sOption%d", name, index+1) } func uniqueFields(fields []Property) []Property { diff --git a/openapi.json b/openapi.json index 8eee23e..375884e 100755 --- a/openapi.json +++ b/openapi.json @@ -7606,6 +7606,7 @@ "apple pay", "google pay", "paypal", + "twint", "na" ], "title": "Entry Mode" @@ -7828,7 +7829,14 @@ "description": "List of hyperlinks for accessing related resources.", "type": "array", "items": { - "$ref": "#/components/schemas/Link" + "oneOf": [ + { + "$ref": "#/components/schemas/Link" + }, + { + "$ref": "#/components/schemas/LinkRefund" + } + ] } }, "events": { @@ -7930,6 +7938,30 @@ "minimum": 0, "title": "Latitude" }, + "LinkRefund": { + "description": "Hypermedia link including allowed minimum and maximum refund amounts.", + "allOf": [ + { + "$ref": "#/components/schemas/Link" + }, + { + "type": "object", + "properties": { + "min_amount": { + "description": "Minimum allowed amount for the refund.", + "type": "number", + "format": "float" + }, + "max_amount": { + "description": "Maximum allowed amount for the refund.", + "type": "number", + "format": "float" + } + } + } + ], + "title": "Link Refund" + }, "Lon": { "description": "Longitude value from the coordinates of the payment location (as received from the payment terminal reader).", "type": "number", @@ -10382,6 +10414,7 @@ "APPLE_PAY", "GOOGLE_PAY", "PAYPAL", + "TWINT", "NONE", "CHIP", "MANUAL_ENTRY", diff --git a/sumup/transactions/__init__.py b/sumup/transactions/__init__.py index 7d398a0..ca4a469 100755 --- a/sumup/transactions/__init__.py +++ b/sumup/transactions/__init__.py @@ -26,6 +26,7 @@ HorizontalAccuracy, Lat, Link, + LinkRefund, Lon, PaymentType, Problem, @@ -66,6 +67,7 @@ "HorizontalAccuracy", "Lat", "Link", + "LinkRefund", "Lon", "PaymentType", "Problem", diff --git a/sumup/types/__init__.py b/sumup/types/__init__.py index 21633f4..c791cdf 100755 --- a/sumup/types/__init__.py +++ b/sumup/types/__init__.py @@ -984,6 +984,7 @@ class CardResponse(pydantic.BaseModel): "qr code pix", "satispay", "sofort", + "twint", ], str, ] @@ -2159,6 +2160,7 @@ class ElvCardAccount(pydantic.BaseModel): "QR_CODE_PIX", "SATISPAY", "SOFORT", + "TWINT", ], str, ] @@ -2393,6 +2395,38 @@ class Link(pydantic.BaseModel): """ +class LinkRefund(pydantic.BaseModel): + """ + Hypermedia link including allowed minimum and maximum refund amounts. + """ + + href: typing.Optional[str] = None + """ + URL for accessing the related resource. + Format: uri + """ + + max_amount: typing.Optional[float] = None + """ + Maximum allowed amount for the refund. + """ + + min_amount: typing.Optional[float] = None + """ + Minimum allowed amount for the refund. + """ + + rel: typing.Optional[str] = None + """ + Specifies the relation to the current resource. + """ + + type: typing.Optional[str] = None + """ + Specifies the media type of the related resource. + """ + + class Person(pydantic.BaseModel): """ Person is a schema definition. @@ -4269,6 +4303,8 @@ class TransactionFullVatRate(pydantic.BaseModel): str, ] +TransactionFullLink = typing.Union[Link, LinkRefund] + class TransactionFullLocation(pydantic.BaseModel): """ @@ -4385,7 +4421,7 @@ class TransactionFull(pydantic.BaseModel): Max: 90 """ - links: typing.Optional[list[Link]] = None + links: typing.Optional[list[TransactionFullLink]] = None """ List of hyperlinks for accessing related resources. """