Skip to content

MngCreateManualCashierDeposit

Creates a manual Cashier deposit transaction with provider = "manual" and source = 1.

When process_now = 1, Cashier starts the OP_BALANCE_IN operation through Core::SetBalance with TR_REASON_CASHIER_DEPOSIT. It durably stores the transaction as processing_ledger and a pending balance-operation record before submission. The command may return while the ledger result is still pending; the transaction later becomes credited or credit_failed after the matching trade result is confirmed committed in the separate trading database. Cashier and trading records are not committed in one cross-database transaction.

Access

The command accepts manager, admin, dealer, and CRM manager sessions. Effective access is resolved from the enabled staff manager record: a super admin may process without CRM finance flags; otherwise the manager needs CRM access, and an ordinary CRM manager needs the finance permissions below. A brand-scoped CRM admin bypasses the operation-specific finance flag.

Role Required permissions
SESSION_CRM_ADMIN access_crm = 1; no additional finance permission flags required for a brand admin
SESSION_CRM_MANAGER access_crm = 1, set_finance = 1; process_now = 1 additionally requires approve_finance = 1
SESSION_MANAGER, SESSION_ADMIN, SESSION_DEALER Super-admin managers are allowed; other callers need CRM access and the required finance permission

The manager record must exist and be enabled. CRM managers remain constrained by customer/account scope, including brand and desk. CRM admins bypass these manual-method permission/scope checks, but not business checks: customer deposit/withdrawal gates, account availability and transaction processing rules still apply. The backend uses the resolved staff manager id for audit/processing. Checks run inside the handler, including direct Moleculer calls; they are not only router metadata.

Request Parameters

Name Type Required Description
login int Yes Trading account login
amount double Yes Deposit amount, at least 0.01
currency string Yes Transaction currency, 1–8 characters; must match account group currency
customer_id int No Positive customer id. Defaults to account-linked customer, which must match the account
method string No Manual method marker, max 64 characters
provider_payment_id string No External/manual reference, max 128 characters
idempotency_key string No Customer-scoped duplicate-detection key, max 128 characters; duplicate keys are rejected and do not replay the original transaction
comment string No Manager comment, max 512 characters
metadata_json string No Metadata string stored as supplied; this command does not parse it as JSON
owner_manager_id int No Nonnegative owner id: the manager the transaction counts towards in statistics. 0 or omitted falls back to the customer assigned_manager_id
process_now int No 0 (default) to leave pending, 1 to start account credit immediately

Response

Returns the complete transaction object. Its 28 fields are described in MngGetCashierTransaction.

With process_now = 0, the new transaction has status 0 (created) and no balance operation. With process_now = 1, it can return in status 11 (processing_ledger) while the asynchronous ledger result is pending, or in a final status if the result is already available and its matching trade commit has been acknowledged in the separate trading database. The Cashier and trading databases do not share one atomic transaction.

Response example (process_now = 0)

{
  "transaction": {
    "id": 481,
    "customer_id": 95,
    "login": 2000009,
    "type": 0,
    "provider": "manual",
    "method": "bank_transfer",
    "provider_config_id": 0,
    "provider_payment_id": "",
    "amount": 100.0,
    "currency": "EUR",
    "account_currency": "EUR",
    "converted_amount": 100.0,
    "conversion_rate": 1.0,
    "status": 0,
    "failure_reason": "",
    "idempotency_key": "dep-manual-001",
    "comment": "Manual bank deposit",
    "metadata_json": "{}",
    "source": 1,
    "approved_by": 0,
    "approved_time": 0,
    "processed_by": 0,
    "processed_time": 0,
    "reject_reason": "",
    "created_time": 1790580000,
    "updated_time": 1790580000,
    "attributed_manager_id": 0,
    "owner_manager_id": 12
  }
}

Errors

Code Error Description
400 CURRENCY_CONVERSION_REQUIRED Currency does not match account group currency
400 INVALID_DATA Missing or invalid request field, including amount below 0.01 or overlong text
400 ACCOUNT_NOT_AVAILABLE Account does not exist or is disabled
400 GROUP_NOT_AVAILABLE Account group does not exist or is disabled
403 RET_NOT_ENOUGH_RIGHTS Caller lacks required CRM finance permission or customer/account scope
403 DEPOSIT_NOT_ALLOWED Deposits are disabled for this customer
403 PERMISSION_DENIED Account is not linked to the specified customer
404 CUSTOMER_NOT_FOUND Account has no linked customer or customer was not found
409 RET_ERR_DUPLICATE Customer-scoped idempotency key was already used; original transaction is not replayed
400 INVALID_MANAGER owner_manager_id does not name an existing, enabled manager with CRM access in the customer's brand. Message: Manager does not exist, is disabled, has no CRM access or belongs to another brand
400 RET_ERR_PARAMS Invalid manual-processing state or balance request when process_now = 1
5xx RET_TECH_PROBLEM Durable transaction/finance state could not be written; response includes the transaction if it was already created

If immediate processing returns a server error after the durable operation was created, the response includes the existing transaction. Its status may be 11; inspect that transaction and its linked balance operations before any follow-up. Cashier does not resubmit an unresolved intent after restart. A RET_TECH_PROBLEM while persisting the intent means submission has not begun.

Transaction Owner

owner_manager_id names the Owner of the transaction, the manager it counts towards in the money columns of MngGetManagersCustomerStatsByFilter. It is written once at creation and never changes; MngUpdateCashierTransaction does not accept it.

A non-zero value must name a manager that exists, is enabled, has access_crm = 1, is not the service recovery account, and belongs to the same brand as the customer. Otherwise the command answers 400 INVALID_MANAGER.

When the field is omitted or 0, the Owner becomes the manager the customer is assigned to, assigned_manager_id. A customer assigned to nobody yields owner_manager_id = 0.

Candidates for the field are enabled managers with access_crm = 1 in the customer's brand, which can be listed with MngGetManagersByFilter. That command is not available to CRM sessions, so a CRM interface has to obtain the list through a BackOffice session.

The returned transaction already carries the resolved owner_manager_id, alongside attributed_manager_id, which records the manager the customer was assigned to when the transaction was created. See Transaction Ownership.

Request Example

{
  "command": "MngCreateManualCashierDeposit",
  "extID": "1",
  "data": {
    "login": 2000009,
    "amount": 100.0,
    "currency": "EUR",
    "comment": "Manual bank deposit",
    "owner_manager_id": 12,
    "process_now": 1
  }
}