package pkg import ( "context" "fmt" "github.com/jackc/pgtype" "github.com/jackc/pgx/v4" ) var ( oidCache = make(map[string]uint32) ) type CustomerTaxDetails struct { BusinessName string VATIN string Address string City string Province string PostalCode string CountryCode string } func (src CustomerTaxDetails) EncodeBinary(ci *pgtype.ConnInfo, buf []byte) ([]byte, error) { typeName := "tax_details" dt, ok := ci.DataTypeForName(typeName) if !ok { return nil, fmt.Errorf("unable to find oid for type name %v", typeName) } values := []interface{}{ src.BusinessName, src.VATIN, src.Address, src.City, src.Province, src.PostalCode, src.CountryCode, } ct := pgtype.NewValue(dt.Value).(pgtype.ValueTranscoder) if err := ct.Set(values); err != nil { return nil, err } return ct.EncodeBinary(ci, buf) } type NewInvoiceProductArray []*invoiceProductForm func (src NewInvoiceProductArray) EncodeBinary(ci *pgtype.ConnInfo, buf []byte) ([]byte, error) { typeName := "new_invoice_product[]" dt, ok := ci.DataTypeForName(typeName) if !ok { return nil, fmt.Errorf("unable to find oid for type name %v", typeName) } var values [][]interface{} for _, form := range src { var productId interface{} = form.ProductId.Val if form.ProductId.Val == "" { productId = nil } values = append(values, []interface{}{ productId, form.Name.Val, form.Description.Val, form.Price.Val, form.Quantity.Val, form.Discount.Float64() / 100.0, form.Tax.Selected, }) } array := pgtype.NewValue(dt.Value).(pgtype.ValueTranscoder) if err := array.Set(values); err != nil { return nil, err } return array.EncodeBinary(ci, buf) } type EditedInvoiceProductArray []*invoiceProductForm func (src EditedInvoiceProductArray) EncodeBinary(ci *pgtype.ConnInfo, buf []byte) ([]byte, error) { typeName := "edited_invoice_product[]" dt, ok := ci.DataTypeForName(typeName) if !ok { return nil, fmt.Errorf("unable to find oid for type name %v", typeName) } var values [][]interface{} for _, form := range src { values = append(values, []interface{}{ form.InvoiceProductId.IntegerOrNil(), form.ProductId.IntegerOrNil(), form.Name.Val, form.Description.Val, form.Price.Val, form.Quantity.Val, form.Discount.Float64() / 100.0, form.Tax.Selected, }) } array := pgtype.NewValue(dt.Value).(pgtype.ValueTranscoder) if err := array.Set(values); err != nil { return nil, err } return array.EncodeBinary(ci, buf) } type NewQuoteProductArray []*quoteProductForm func (src NewQuoteProductArray) EncodeBinary(ci *pgtype.ConnInfo, buf []byte) ([]byte, error) { typeName := "new_quote_product[]" dt, ok := ci.DataTypeForName(typeName) if !ok { return nil, fmt.Errorf("unable to find oid for type name %v", typeName) } var values [][]interface{} for _, form := range src { var productId interface{} = form.ProductId.Val if form.ProductId.Val == "" { productId = nil } values = append(values, []interface{}{ productId, form.Name.Val, form.Description.Val, form.Price.Val, form.Quantity.Val, form.Discount.Float64() / 100.0, form.Tax.Selected, }) } array := pgtype.NewValue(dt.Value).(pgtype.ValueTranscoder) if err := array.Set(values); err != nil { return nil, err } return array.EncodeBinary(ci, buf) } type EditedQuoteProductArray []*quoteProductForm func (src EditedQuoteProductArray) EncodeBinary(ci *pgtype.ConnInfo, buf []byte) ([]byte, error) { typeName := "edited_quote_product[]" dt, ok := ci.DataTypeForName(typeName) if !ok { return nil, fmt.Errorf("unable to find oid for type name %v", typeName) } var values [][]interface{} for _, form := range src { values = append(values, []interface{}{ form.QuoteProductId.IntegerOrNil(), form.ProductId.IntegerOrNil(), form.Name.Val, form.Description.Val, form.Price.Val, form.Quantity.Val, form.Discount.Float64() / 100.0, form.Tax.Selected, }) } array := pgtype.NewValue(dt.Value).(pgtype.ValueTranscoder) if err := array.Set(values); err != nil { return nil, err } return array.EncodeBinary(ci, buf) } func registerPgTypes(ctx context.Context, conn *pgx.Conn) error { if _, err := conn.Exec(ctx, "set role to admin"); err != nil { return err } tagNameOID, err := registerPgType(ctx, conn, &pgtype.Text{}, "tag_name") if err != nil { return err } tagNameArray := pgtype.NewArrayType("tag_name[]", tagNameOID, func() pgtype.ValueTranscoder { return &pgtype.Text{} }) if _, err := registerPgType(ctx, conn, tagNameArray, tagNameArray.TypeName()); err != nil { return err } discountRateOID, err := registerPgType(ctx, conn, &pgtype.Numeric{}, "discount_rate") if err != nil { return err } newInvoiceProduct, err := pgtype.NewCompositeType( "new_invoice_product", []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 } newInvoiceProductOID, err := registerPgType(ctx, conn, newInvoiceProduct, newInvoiceProduct.TypeName()) if err != nil { return err } newInvoiceProductArray := pgtype.NewArrayType("new_invoice_product[]", newInvoiceProductOID, func() pgtype.ValueTranscoder { value := newInvoiceProduct.NewTypeValue() return value.(pgtype.ValueTranscoder) }) _, err = registerPgType(ctx, conn, newInvoiceProductArray, newInvoiceProductArray.TypeName()) if err != nil { return err } editedInvoiceProduct, err := pgtype.NewCompositeType( "edited_invoice_product", []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 } editedInvoiceProductOID, err := registerPgType(ctx, conn, editedInvoiceProduct, editedInvoiceProduct.TypeName()) if err != nil { return err } editedInvoiceProductArray := pgtype.NewArrayType("edited_invoice_product[]", editedInvoiceProductOID, func() pgtype.ValueTranscoder { value := editedInvoiceProduct.NewTypeValue() return value.(pgtype.ValueTranscoder) }) _, err = registerPgType(ctx, conn, editedInvoiceProductArray, editedInvoiceProductArray.TypeName()) if err != nil { return err } newQuoteProduct, err := pgtype.NewCompositeType( "new_quote_product", []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 } newQuoteProductOID, err := registerPgType(ctx, conn, newQuoteProduct, newQuoteProduct.TypeName()) if err != nil { return err } newQuoteProductArray := pgtype.NewArrayType("new_quote_product[]", newQuoteProductOID, func() pgtype.ValueTranscoder { value := newQuoteProduct.NewTypeValue() return value.(pgtype.ValueTranscoder) }) _, err = registerPgType(ctx, conn, newQuoteProductArray, newQuoteProductArray.TypeName()) if err != nil { return err } editedQuoteProduct, err := pgtype.NewCompositeType( "edited_quote_product", []pgtype.CompositeTypeField{ {"quote_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 } editedQuoteProductOID, err := registerPgType(ctx, conn, editedQuoteProduct, editedQuoteProduct.TypeName()) if err != nil { return err } editedQuoteProductArray := pgtype.NewArrayType("edited_quote_product[]", editedQuoteProductOID, func() pgtype.ValueTranscoder { value := editedQuoteProduct.NewTypeValue() return value.(pgtype.ValueTranscoder) }) _, err = registerPgType(ctx, conn, editedQuoteProductArray, editedQuoteProductArray.TypeName()) if err != nil { return err } countryCodeOID, err := registerPgType(ctx, conn, &pgtype.Text{}, "country_code") if err != nil { return err } taxDetailsType, err := pgtype.NewCompositeType( "tax_details", []pgtype.CompositeTypeField{ {"business_name", pgtype.TextOID}, {"vatin", pgtype.TextOID}, {"address", pgtype.TextOID}, {"city", pgtype.TextOID}, {"province", pgtype.TextOID}, {"postal_code", pgtype.TextOID}, {"discount_rate", countryCodeOID}, }, conn.ConnInfo(), ) if err != nil { return err } _, err = registerPgType(ctx, conn, taxDetailsType, taxDetailsType.TypeName()) if err != nil { return err } _, err = conn.Exec(ctx, "reset role") return err } func registerPgType(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 }