/* * SPDX-FileCopyrightText: 2023 jordi fita mas * SPDX-License-Identifier: AGPL-3.0-only */ package database import ( "context" "github.com/jackc/pgtype" "github.com/jackc/pgx/v4" ) const ( CheckedInGuestTypeName = "checked_in_guest" OptionUnitsTypeName = "option_units" RedsysRequestTypeName = "redsys_request" RedsysResponseTypeName = "redsys_response" RedsysSignedRequestTypeName = "redsys_signed_request" ) var ( oidCache = make(map[string]uint32) ) func registerTypes(ctx context.Context, connString string) error { conn, err := pgx.Connect(ctx, connString) if err != nil { return err } defer conn.Close(context.Background()) if _, err := conn.Exec(ctx, "set role to guest"); err != nil { return err } if _, err := conn.Exec(ctx, searchPathQuery); err != nil { return err } if err := registerConnectionTypes(ctx, conn); err != nil { return err } return nil } func registerConnectionTypes(ctx context.Context, conn *pgx.Conn) error { uriOID, err := registerType(ctx, conn, &pgtype.Text{}, "uri") if err != nil { return err } discountRateOID, err := registerType(ctx, conn, &pgtype.Numeric{}, "discount_rate") if err != nil { return err } redsysRequestType, err := pgtype.NewCompositeType( RedsysRequestTypeName, []pgtype.CompositeTypeField{ {"transaction_type", pgtype.Int4OID}, {"amount", pgtype.TextOID}, {"order_number", pgtype.TextOID}, {"product", pgtype.TextOID}, {"card_holder", pgtype.TextOID}, {"success_uri", uriOID}, {"failure_uri", uriOID}, {"notification_uri", uriOID}, {"lang_tag", pgtype.TextOID}, }, conn.ConnInfo(), ) if err != nil { return err } if _, err = registerType(ctx, conn, redsysRequestType, redsysRequestType.TypeName()); err != nil { return err } redsysResponseType, err := pgtype.NewCompositeType( RedsysResponseTypeName, []pgtype.CompositeTypeField{ {"merchant_code", pgtype.TextOID}, {"terminal_number", pgtype.Int4OID}, {"response_code", pgtype.Int4OID}, {"date_time", pgtype.TimestampOID}, {"secure_payment", pgtype.BoolOID}, {"transaction_type", pgtype.Int4OID}, {"amount", pgtype.TextOID}, {"currency_code", pgtype.TextOID}, {"order_number", pgtype.TextOID}, {"authorization_code", pgtype.TextOID}, {"error_code", pgtype.TextOID}, }, conn.ConnInfo(), ) if err != nil { return err } if _, err = registerType(ctx, conn, redsysResponseType, redsysResponseType.TypeName()); err != nil { return err } redsysSignedRequestType, err := pgtype.NewCompositeType( RedsysSignedRequestTypeName, []pgtype.CompositeTypeField{ {"merchant_parameters", pgtype.TextOID}, {"signature", pgtype.TextOID}, {"signature_version", pgtype.TextOID}, }, conn.ConnInfo(), ) if err != nil { return err } if _, err = registerType(ctx, conn, redsysSignedRequestType, redsysSignedRequestType.TypeName()); err != nil { return err } optionUnitsType, err := pgtype.NewCompositeType( OptionUnitsTypeName, []pgtype.CompositeTypeField{ {"option_id", pgtype.Int4OID}, {"units", pgtype.Int4OID}, }, conn.ConnInfo(), ) if err != nil { return err } if _, err = registerType(ctx, conn, optionUnitsType, optionUnitsType.TypeName()); err != nil { return err } checkedInGuestType, err := pgtype.NewCompositeType( CheckedInGuestTypeName, []pgtype.CompositeTypeField{ {"id_document_type_id", pgtype.VarcharOID}, {"id_document_number", pgtype.TextOID}, {"id_document_issue_date", pgtype.DateOID}, {"given_name", pgtype.TextOID}, {"first_surname", pgtype.TextOID}, {"second_surname", pgtype.TextOID}, {"sex_id", pgtype.VarcharOID}, {"birthdate", pgtype.DateOID}, {"country_code", pgtype.TextOID}, {"phone", pgtype.TextOID}, {"address", pgtype.TextOID}, }, conn.ConnInfo(), ) if err != nil { return err } if _, err = registerType(ctx, conn, checkedInGuestType, checkedInGuestType.TypeName()); err != nil { return err } newInvoiceProductType, err := pgtype.NewCompositeType( NewInvoiceProductTypeName, []pgtype.CompositeTypeField{ {"product_id", pgtype.Int4OID}, {"name", pgtype.TextOID}, {"description", pgtype.TextOID}, {"price", pgtype.TextOID}, {"quantity", pgtype.Int4OID}, {"discount_rate", discountRateOID}, {"tax", pgtype.Int4ArrayOID}, }, conn.ConnInfo(), ) if err != nil { return err } if _, err = registerType(ctx, conn, newInvoiceProductType, newInvoiceProductType.TypeName()); err != nil { return err } editedInvoiceProductType, err := pgtype.NewCompositeType( EditedInvoiceProductTypeName, []pgtype.CompositeTypeField{ {"invoice_product_id", pgtype.Int4OID}, {"product_id", pgtype.Int4OID}, {"name", pgtype.TextOID}, {"description", pgtype.TextOID}, {"price", pgtype.TextOID}, {"quantity", pgtype.Int4OID}, {"discount_rate", discountRateOID}, {"tax", pgtype.Int4ArrayOID}, }, conn.ConnInfo(), ) if err != nil { return err } if _, err = registerType(ctx, conn, editedInvoiceProductType, editedInvoiceProductType.TypeName()); err != nil { return err } return nil } func registerType(ctx context.Context, conn *pgx.Conn, value pgtype.Value, name string) (oid uint32, err error) { var found bool if oid, found = oidCache[name]; !found { if err = conn.QueryRow(ctx, "select $1::regtype::oid", name).Scan(&oid); err != nil { return } oidCache[name] = oid } conn.ConnInfo().RegisterDataType(pgtype.DataType{Value: value, Name: name, OID: oid}) return }