ebarimtv3

package module
v1.0.9 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 20, 2026 License: MIT Imports: 12 Imported by: 0

README ΒΆ

🧾 ebarimt-pos3-go

Go Report Card Go Version GORM

Ebarimt POS 3.0 Golang Implementation SDK - A comprehensive Go library for integrating with the Ebarimt POS 3.0 system.

✨ Features

  • πŸš€ Complete POS 3.0 API implementation
  • πŸ›‘οΈ Type-safe Go structures for all API requests and responses
  • ⚑ Comprehensive error handling
  • πŸ” Built-in authentication and security features
  • βœ… Extensive test coverage
  • πŸ’Ύ GORM integration for database operations

πŸ“¦ Installation

go get github.com/batorgil-it/ebarimt-pos3-go

πŸš€ Quick Start

package main

import (
    "github.com/batorgil-it/ebarimt-pos3-go"
    "gorm.io/gorm"
)

func main() {
    // Initialize the client with required parameters
    client := ebarimtv3.New(ebarimtv3.Input{
        Endpoint:    "https://example.ebarimt.mn",
        PosNo:       "YOUR_POS_NUMBER",
        MerchantTin: "YOUR_MERCHANT_TIN",
        // Optional parameters
        DB:       nil, // Your GORM DB instance if you want to store receipts
        MailHost: "",  // SMTP host for email notifications
        MailPort: 0,   // SMTP port for email notifications
    })

    // Create a receipt
    response, err := client.Create(models.CreateInputModel{
        // Add your receipt details here
    })
    if err != nil {
        // Handle error
    }
    // Use the response
    fmt.Printf("Receipt created: %+v\n", response)
}

πŸ“š Documentation

For detailed documentation and examples, please visit our documentation.

πŸ“ Project Structure

ebarimt-pos3-go/
β”œβ”€β”€ πŸ“‚ constants/     # Constant definitions
β”œβ”€β”€ πŸ“‚ files/        # File handling utilities
β”œβ”€β”€ πŸ“‚ pos3/         # Core POS 3.0 implementation
β”œβ”€β”€ πŸ“‚ services/     # Service layer implementations
β”œβ”€β”€ πŸ“‚ structs/      # Data structures
β”œβ”€β”€ πŸ“‚ tests/        # Test files
└── πŸ“‚ utils/        # Utility functions

βš™οΈ Requirements

  • πŸ”· Go 1.23.5 or higher
  • πŸ”· GORM v1.25.12
  • πŸ”· Other dependencies as specified in go.mod

🀝 Contributing

We welcome contributions! Please feel free to submit a Pull Request. For major changes, please open an issue first to discuss what you would like to change.

  1. 🍴 Fork the repository
  2. 🌿 Create your feature branch (git checkout -b feature/AmazingFeature)
  3. πŸ’Ύ Commit your changes (git commit -m 'Add some AmazingFeature')
  4. πŸ“€ Push to the branch (git push origin feature/AmazingFeature)
  5. πŸ”„ Open a Pull Request

πŸ§ͺ Testing

Run the test suite:

go test ./...

πŸ“„ License

This project is licensed under the MIT License - see the LICENSE file for details.

πŸ’¬ Support

For support, please open an issue in the GitHub repository or contact our support team.

πŸ™ Acknowledgments

  • πŸ‘₯ Thanks to all contributors who have helped shape this project
  • 🌟 Special thanks to the Ebarimt team for their support and documentation

πŸ”’ Security

For security concerns, please email security@techpartners.asia or open a security advisory in the GitHub repository.

Get latest tag

git describe --tags --abbrev=0

Documentation ΒΆ

Index ΒΆ

Constants ΒΆ

This section is empty.

Variables ΒΆ

View Source
var ErrPluginRegistered = errors.New("plugin already registered")

ErrPluginRegistered is returned by Use when a plugin with the same name is already stored in the registry.

Functions ΒΆ

This section is empty.

Types ΒΆ

type EbarimtClient ΒΆ

type EbarimtClient struct {
	// Low-level POS 3.0 HTTP client (shared across clones).
	// Embedded so all pos3.Pos3 methods (GetInfo, GetTinInfo, …) are promoted
	// directly onto EbarimtClient.  Access the interface value itself via
	// e.Pos3 when you need to call a method without triggering any override.
	pos3.Pos3

	// Optional integrations β€” shared, not mutated after construction.
	DB           *gorm.DB
	MailHost     string
	MailPort     string
	MailFrom     string
	MailSubject  string
	MailPassword string
	MailUser     string
	TemplatePath string

	// Per-operation fields.  Non-nil only during an active operation on a
	// clone created by withStatement(); nil on the "root" client.
	Statement *Statement
	Error     error
	// contains filtered or unexported fields
}

EbarimtClient is the main SDK entry point. In addition to embedding the low-level pos3.Pos3 HTTP client it now carries a plugin registry and an ordered callback pipeline so that third-party plugins can hook into every operation without forking the SDK.

Shared state (Pos3, DB, mail config, plugins, callbacks) lives directly on the struct. Per-operation state is isolated in a Statement that is created fresh for each operation via withStatement().

func New ΒΆ

func New(input Input) (*EbarimtClient, error)

New constructs an EbarimtClient, initialises the callback pipeline with the built-in default callbacks, and registers any plugins supplied via Input.Plugins.

func (*EbarimtClient) AddError ΒΆ added in v1.0.8

func (e *EbarimtClient) AddError(err error)

AddError records the first non-nil error on the client context. Subsequent callbacks check e.Error != nil and skip their work when it is set.

func (*EbarimtClient) CalculateTotals ΒΆ

CalculateTotals computes VAT totals for a set of line items without making any network calls.

func (*EbarimtClient) Callback ΒΆ added in v1.0.8

func (e *EbarimtClient) Callback() *callbacks

Callback returns the callback registry so that plugins (and callers) can register, remove, or replace hooks on any operation processor.

func (*EbarimtClient) Create ΒΆ

Create builds receipt(s) from the given model and sends them to the POS endpoint. Internally it runs the "create" callback chain so plugins can hook before and after each step.

func (*EbarimtClient) InitializeDB ΒΆ added in v1.0.9

func (e *EbarimtClient) InitializeDB() error

func (*EbarimtClient) RunApproveQr ΒΆ added in v1.0.8

RunApproveQr executes the approveQr callback chain. Statement.Params: structs.ApproveQrRequest.

func (*EbarimtClient) RunAuth ΒΆ added in v1.0.8

func (e *EbarimtClient) RunAuth() error

RunAuth executes the auth callback chain, which fetches (or returns the cached) bearer token. Useful when a plugin needs to trace the authentication call as a distinct span.

func (*EbarimtClient) RunBankAccounts ΒΆ added in v1.0.8

func (e *EbarimtClient) RunBankAccounts(tin string) ([]structs.BankAccountData, error)

RunBankAccounts executes the bankAccounts callback chain. Statement.Params: string (tin).

func (*EbarimtClient) RunConsumerInfo ΒΆ added in v1.0.8

func (e *EbarimtClient) RunConsumerInfo(regNo string) (*structs.ConsumerInfoResponse, error)

RunConsumerInfo executes the consumerInfo callback chain. Statement.Params: string (regNo).

func (*EbarimtClient) RunForiegnerCustomerNoInfo ΒΆ added in v1.0.8

func (e *EbarimtClient) RunForiegnerCustomerNoInfo(loginName string) (*structs.ForiegnerInfoResponse, error)

RunForiegnerCustomerNoInfo executes the foriegnerCustomerNoInfo callback chain. Statement.Params: string (loginName).

func (*EbarimtClient) RunForiegnerInfoRegister ΒΆ added in v1.0.8

func (e *EbarimtClient) RunForiegnerInfoRegister(passportNo string, body structs.ForiegnerInfoRequest) (*structs.ForiegnerInfoResponse, error)

RunForiegnerInfoRegister executes the foriegnerInfoRegister callback chain. Statement.Params: ForiegnerInfoRegisterParams{PassportNo, Body}.

func (*EbarimtClient) RunForiegnerPassportInfo ΒΆ added in v1.0.8

func (e *EbarimtClient) RunForiegnerPassportInfo(fNumber, passportNo string) (*structs.ForiegnerInfoResponse, error)

RunForiegnerPassportInfo executes the foriegnerPassportInfo callback chain. Statement.Params: ForiegnerPassportInfoParams{FNumber, PassportNo}.

func (*EbarimtClient) RunGetBranchInfo ΒΆ added in v1.0.8

func (e *EbarimtClient) RunGetBranchInfo() (*structs.GetBranchInfoResponse, error)

RunGetBranchInfo executes the getBranchInfo callback chain. Statement.Params: nil.

func (*EbarimtClient) RunGetInfo ΒΆ added in v1.0.8

func (e *EbarimtClient) RunGetInfo(customerTin string) (*structs.GetInfoResponse, error)

RunGetInfo executes the getInfo callback chain. Statement.Params: string (customerTin).

func (*EbarimtClient) RunGetProfile ΒΆ added in v1.0.8

RunGetProfile executes the getProfile callback chain. Statement.Params: structs.GetProfileRequest.

func (*EbarimtClient) RunGetSalesListERP ΒΆ added in v1.0.8

RunGetSalesListERP executes the getSalesListERP callback chain. Statement.Params: structs.GetSalesListERPRequest. Result is in Statement.GetSalesTotalDataRes (shared type).

func (*EbarimtClient) RunGetSalesTotalData ΒΆ added in v1.0.8

RunGetSalesTotalData executes the getSalesTotalData callback chain. Statement.Params: structs.GetSalesTotalDataRequest.

func (*EbarimtClient) RunGetTinInfo ΒΆ added in v1.0.8

func (e *EbarimtClient) RunGetTinInfo(regNo string) (*structs.GetTinInfoResponse, error)

RunGetTinInfo executes the getTinInfo callback chain. Statement.Params: string (regNo).

func (*EbarimtClient) RunHTTPPosRequest ΒΆ added in v1.0.8

func (e *EbarimtClient) RunHTTPPosRequest(dest interface{}, body interface{}, api utils.API, ext string, headers []pos3.CustomHeader) error

RunHTTPPosRequest executes the low-level httpPosRequest callback chain and unmarshals the raw response bytes into dest. Useful for plugins or advanced callers that want to send arbitrary POS API requests with full tracing.

func (*EbarimtClient) RunHTTPRequest ΒΆ added in v1.0.8

func (e *EbarimtClient) RunHTTPRequest(dest interface{}, body interface{}, api utils.API, ext string, headers []pos3.CustomHeader) error

RunHTTPRequest executes the low-level httpRequest callback chain and unmarshals the raw response bytes into dest.

func (*EbarimtClient) RunInfo ΒΆ added in v1.0.8

func (e *EbarimtClient) RunInfo() (*structs.InfoResponse, error)

RunInfo executes the info β†’ httpPosRequest callback chain.

func (*EbarimtClient) RunReceiptDelete ΒΆ added in v1.0.8

func (e *EbarimtClient) RunReceiptDelete(req structs.ReceiptDeleteRequest) (*structs.Response, error)

RunReceiptDelete executes the receiptDelete β†’ httpPosRequest callback chain.

func (*EbarimtClient) RunReceiptSend ΒΆ added in v1.0.8

func (e *EbarimtClient) RunReceiptSend(req structs.ReceiptRequest) (*structs.ReceiptResponse, error)

RunReceiptSend executes the full receiptSend β†’ httpPosRequest callback chain for the given request. Callers outside of an active Create() operation should use this method so that plugins intercept the call.

Within the create callback chain, sendReceiptCallback calls the processors directly on the shared Statement to preserve context propagation.

func (*EbarimtClient) RunSaveOprMerchants ΒΆ added in v1.0.8

RunSaveOprMerchants executes the saveOprMerchants callback chain. Statement.Params: structs.SaveOprMerchantsRequest.

func (*EbarimtClient) RunSendData ΒΆ added in v1.0.8

func (e *EbarimtClient) RunSendData() (*structs.Response, error)

RunSendData executes the sendData β†’ httpPosRequest callback chain.

func (*EbarimtClient) Use ΒΆ added in v1.0.8

func (e *EbarimtClient) Use(p Plugin) error

Use registers a plugin. Initialize is called once; on success the plugin is stored under its name. Duplicate names return ErrPluginRegistered.

func (*EbarimtClient) WithContext ΒΆ added in v1.0.8

func (e *EbarimtClient) WithContext(ctx context.Context) *EbarimtClient

WithContext returns a shallow clone of the client that will use ctx as the base context for every subsequent operation. This mirrors GORM's db.WithContext(ctx) pattern and is the idiomatic way to attach a request-scoped context (e.g. an OpenTelemetry root span) to all SDK calls:

ctx, span := tracer.Start(req.Context(), "checkout")
defer span.End()
result, err := client.WithContext(ctx).Create(input)

type ForiegnerInfoRegisterParams ΒΆ added in v1.0.8

type ForiegnerInfoRegisterParams struct {
	PassportNo string
	Body       structs.ForiegnerInfoRequest
}

ForiegnerInfoRegisterParams is the Params type for RunForiegnerInfoRegister.

type ForiegnerPassportInfoParams ΒΆ added in v1.0.8

type ForiegnerPassportInfoParams struct {
	FNumber    string
	PassportNo string
}

ForiegnerPassportInfoParams is the Params type for RunForiegnerPassportInfo.

type HTTPStatement ΒΆ added in v1.0.8

type HTTPStatement struct {
	// APIDesc is the utils.API descriptor (Method, Url, DevUrl, IsAuth).
	APIDesc utils.API

	// Ext is the URL suffix appended to api.Url (e.g. a TIN query string).
	Ext string

	// ResolvedURL is the final URL after applying DevUrl/Ext.
	// Populated by pos3:http_pos_request / pos3:http_request.
	ResolvedURL string

	// Headers holds any custom request headers (e.g. X-API-KEY).
	Headers []pos3.CustomHeader

	// ReqBody is the JSON-serialised request body (nil for GET requests).
	ReqBody []byte

	// StatusCode is the HTTP response status code.
	StatusCode int

	// ResBody is the raw HTTP response body.
	ResBody []byte
}

HTTPStatement carries per-HTTP-call data for the httpPosRequest, httpRequest, and auth callback processors. It is attached to Statement.HTTP by the default callbacks before the processor chain runs, giving Before hooks full visibility into the outbound call and After hooks access to the response.

type Input ΒΆ

type Input struct {
	Endpoint    string
	PosNo       string
	MerchantTin string
	IsDev       bool

	// Optional integrations.
	DB           *gorm.DB // When set, receipts are persisted automatically.
	MailHost     string
	MailPort     string
	MailFrom     string
	MailSubject  string
	MailPassword string
	MailUser     string
	TemplatePath string

	// Plugins to register during construction (equivalent to GORM's
	// Config.Plugins map).  Use() can also be called after New().
	Plugins []Plugin
}

Input is the constructor configuration for New().

type Plugin ΒΆ added in v1.0.8

type Plugin interface {
	Name() string
	Initialize(*EbarimtClient) error
}

Plugin is the extension contract every plugin must satisfy. Name must be globally unique β€” it is used as the registry key. Initialize is called exactly once when the plugin is registered via Use().

type Processor ΒΆ added in v1.0.8

type Processor struct {
	// contains filtered or unexported fields
}

processor manages the ordered list of hooks for one operation.

func (*Processor) After ΒΆ added in v1.0.8

func (p *Processor) After(name string) *callback

After returns a callback builder that will insert the hook after the named hook.

func (*Processor) Before ΒΆ added in v1.0.8

func (p *Processor) Before(name string) *callback

Before returns a callback builder that will insert the hook before the named hook.

func (*Processor) Execute ΒΆ added in v1.0.8

func (p *Processor) Execute(e *EbarimtClient) *EbarimtClient

Execute runs the compiled hook chain. It stops early on the first error recorded via AddError.

func (*Processor) Match ΒΆ added in v1.0.8

func (p *Processor) Match(fn func(*EbarimtClient) bool) *callback

Match returns a callback builder whose hook is included in the chain only when fn returns true (evaluated once at registration time).

func (*Processor) Register ΒΆ added in v1.0.8

func (p *Processor) Register(name string, fn func(*EbarimtClient)) error

Register adds a named hook to this processor's chain.

func (*Processor) Remove ΒΆ added in v1.0.8

func (p *Processor) Remove(name string) error

Remove marks a named hook for removal from the compiled chain.

func (*Processor) Replace ΒΆ added in v1.0.8

func (p *Processor) Replace(name string, fn func(*EbarimtClient)) error

Replace substitutes the handler for an existing named hook.

type Statement ΒΆ added in v1.0.8

type Statement struct {
	// Context propagated from the caller. Defaults to context.Background().
	// Plugins that start OTEL spans write the enriched context back here so
	// that nested callbacks (e.g. httpPosRequest) pick up the parent span.
	Context context.Context

	// Operation is the human-readable name of the current operation
	// (e.g. "create", "get_info", "receipt_send").  Set by every Run* finisher
	// before the processor chain executes.  Used as the OTEL span name.
	Operation string

	// ── Generic operation input ──────────────────────────────────────────────
	//
	// Params holds the primary argument(s) for non-create operations.
	// The concrete type is documented on each Run* method; use a type switch
	// or type assertion in your plugin hooks.
	//
	// Multi-argument operations use a dedicated param struct:
	//   RunForiegnerPassportInfo β†’ ForiegnerPassportInfoParams
	//   RunForiegnerInfoRegister β†’ ForiegnerInfoRegisterParams
	Params interface{}

	CreateInput  *structs.CreateInputModel
	ReceiptItems map[constants.TaxType]structs.Receipt

	ReceiptRequest  *structs.ReceiptRequest
	ReceiptResponse *structs.ReceiptResponse

	DeleteRequest  *structs.ReceiptDeleteRequest
	DeleteResponse *structs.Response

	Response     *structs.Response
	InfoResponse *structs.InfoResponse

	BankAccountsRes []structs.BankAccountData

	GetInfoRes           *structs.GetInfoResponse
	GetTinInfoRes        *structs.GetTinInfoResponse
	GetBranchInfoRes     *structs.GetBranchInfoResponse
	GetSalesTotalDataRes *structs.GetSalesTotalDataResponse // also used by GetSalesListERP
	SaveOprMerchantsRes  *structs.SaveOprMerchantsResponse

	ConsumerInfoRes  *structs.ConsumerInfoResponse
	GetProfileRes    *structs.GetProfileResponse
	ApproveQrRes     *structs.ApproveQrResponse
	ForiegnerInfoRes *structs.ForiegnerInfoResponse // shared by all 3 foreigner methods

	// ── HTTP-level state (httpPosRequest / httpRequest / auth) ───────────────
	//
	// Set by the default callbacks before calling into pos3 and populated with
	// the response after the call.  Plugins use these fields in Before/After
	// hooks to instrument individual HTTP calls as child spans:
	//
	//   e.Callback().HTTPRequest().Before("pos3:http_request").
	//       Register("otel:http_start", func(e *EbarimtClient) {
	//           ctx, span := tracer.Start(e.Statement.Context, "http.get",
	//               trace.WithAttributes(
	//                   attribute.String("http.method", e.Statement.HTTP.APIDesc.Method),
	//                   attribute.String("http.url",    e.Statement.HTTP.ResolvedURL),
	//               ))
	//           e.Statement.Context = ctx
	//           e.Statement.Settings.Store("otel:span", span)
	//       })
	HTTP *HTTPStatement

	// ── Plugin-scoped key-value store ────────────────────────────────────────
	//
	//   e.Statement.Settings.Store("myplugin:key", value)
	//   if v, ok := e.Statement.Settings.Load("myplugin:key"); ok { … }
	Settings sync.Map
}

Statement holds per-operation data that flows through the callback chain.

Each public API call (Create, RunReceiptSend, RunGetInfo, …) shallow-clones the EbarimtClient and attaches a fresh Statement so that concurrent operations never share mutable state while all shared configuration (plugins, callbacks, the underlying POS connection) is reused without copying.

Directories ΒΆ

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL