# CLAUDE.md This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. ## Overview Invoice Az is a Frappe application that integrates with Azerbaijan's e-taxes.gov.az system for: - Downloading and importing purchase invoices from e-taxes - Downloading and importing sales invoices from e-taxes - Sending sales invoices to e-taxes with ASAN Imza signing - Importing VAT Account operations and creating Journal Entries - Managing authentication via ASAN Login with automatic token renewal ## ⚠️ CRITICAL RULES FOR E-TAXES INTEGRATION ⚠️ **READ THIS BEFORE IMPLEMENTING ANY E-TAXES API CALLS!** ### 1. Authentication Pattern (MANDATORY) **❌ WRONG - Direct API call:** ```javascript function my_function(frm) { frappe.call({ method: 'invoice_az.my_api.some_method', // ... this will fail with "Authentication expired" }); } ``` **✅ CORRECT - Always wrap with authentication check:** ```javascript function my_function(frm) { ETaxes.auth.checkAndProcess(function() { // Your code here - only runs after auth is verified frappe.call({ method: 'invoice_az.my_api.some_method', // ... works correctly }); }); } ``` **Why?** `ETaxes.auth.checkAndProcess()` does: 1. Checks if token is still valid 2. If expired → prompts user to login via ASAN Imza 3. Only after successful auth → executes your callback 4. Prevents "Authentication expired" errors ### 2. ETaxes Module Inclusion (MANDATORY) **⚠️ ETaxes is NOT a global module!** It must be defined in EACH JavaScript file that uses it. **❌ WRONG - Assuming ETaxes exists:** ```javascript // my_custom_form.js frappe.ui.form.on('My DocType', { refresh: function(frm) { ETaxes.auth.checkAndProcess(function() { // ERROR: ETaxes is not defined }); } }); ``` **✅ CORRECT - Include ETaxes module at the top of your JS file:** Copy the entire ETaxes module from `sales_invoice.js` (lines 1-564) to the **beginning** of your JS file: ```javascript // ======= COPY THIS ENTIRE BLOCK ======= // From sales_invoice.js lines 1-564: const ETaxes = { PROGRESS_UPDATE_DELAY: 50, AUTH_POLL_INTERVAL: 6000, AUTH_MAX_ATTEMPTS: 20, // ... (full module definition) }; ETaxes.utils = { /* ... */ }; ETaxes.dialogs = { /* ... */ }; ETaxes.auth = { /* ... */ }; // ======= END COPY ======= // Now your code can use ETaxes: frappe.ui.form.on('My DocType', { refresh: function(frm) { ETaxes.auth.checkAndProcess(function() { // ✅ Works correctly }); } }); ``` **Files that need ETaxes module:** - ✅ `sales_invoice.js` - has it (564 lines) - ✅ `purchase_order.js` - has it - ✅ `supplier.js` - has it (after fix) - ❌ Any new JS file - **MUST include it!** ### 3. Backend API Pattern (MANDATORY) **All backend functions that call E-Taxes API MUST follow this pattern:** ```python import frappe import requests from invoice_az.auth import record_etaxes_activity, get_default_asan_login @frappe.whitelist() def my_etaxes_function(doc_name): """My E-Taxes API function""" try: # Step 1: ALWAYS record activity (for token renewal) record_etaxes_activity() # Step 2: Get document doc = frappe.get_doc("My DocType", doc_name) # Step 3: Validate (business logic checks) validation = validate_my_document(doc) if not validation.get("valid"): return { "success": False, "message": validation.get("message") } # Step 4: Get authentication token asan_login = get_default_asan_login() if not asan_login.get("found") or not asan_login.get("main_token"): return { "success": False, "message": "E-Taxes authentication not found. Please login via ASAN." } token = asan_login.get("main_token") # Step 5: Build headers with token headers = DEFAULT_HEADERS.copy() headers["x-authorization"] = f"Bearer {token}" # Step 6: Make API request response = requests.post( "https://new.e-taxes.gov.az/api/...", data=json.dumps(payload), headers=headers, timeout=60 ) # Step 7: Handle common errors if response.status_code == 401: return { "success": False, "message": "Authentication expired. Please login again." } if response.status_code == 500: return { "success": False, "message": "E-Taxes service error. Please try again later." } if response.status_code == 404: return { "success": False, "message": "Resource not found." } response.raise_for_status() # Step 8: Process response result = response.json() # Step 9: Return success return { "success": True, "data": result } except requests.exceptions.RequestException as e: frappe.log_error( f"Network error: {str(e)}", "E-Taxes API Error" ) return { "success": False, "message": f"Network error: {str(e)}" } except Exception as e: frappe.log_error( f"Unexpected error: {str(e)}\n{frappe.get_traceback()}", "E-Taxes API Error" ) return { "success": False, "message": f"Error: {str(e)}" } ``` **Key points:** 1. `@frappe.whitelist()` - ALWAYS required for frontend calls 2. `record_etaxes_activity()` - ALWAYS first (enables token auto-renewal) 3. `get_default_asan_login()` - Get token 4. `headers["x-authorization"] = f"Bearer {token}"` - Required for auth 5. Handle 401, 500, 404 errors explicitly 6. ALWAYS return `{"success": bool, "message": str}` format 7. ALWAYS use try-except with proper error logging ### 4. Constants and URLs **Base URL:** ```python BASE_URL = "https://new.e-taxes.gov.az" ``` **Common endpoints:** - Auth: `/api/po/auth/public/v1/*` - Invoices: `/api/po/invoice/public/v2/invoice` - Sign: `/api/po/invoice/public/v1/invoice/sign/withAsanImza` - Serial: `/api/po/invoice/public/v1/generateSerialNumber/defaultInvoice` - Agricultural Serial: `/api/po/invoice/public/v1/act/generateSerialNumber/agriculturalProductsAct` - Metal Scrap Serial: `/api/po/invoice/public/v1/act/generateSerialNumber/metalProductsAct` - Tire Disposal Serial: `/api/po/invoice/public/v1/act/generateSerialNumber/tireProductsForDisposalAct` - Plastic Disposal Serial: `/api/po/invoice/public/v1/act/generateSerialNumber/plasticProductsForDisposalAct` - Rawhide Supply Serial: `/api/po/invoice/public/v1/act/generateSerialNumber/rawhideSupply` - Other Product Receipt Serial: `/api/po/invoice/public/v1/act/generateSerialNumber/otherProductReceiptAct` - All Acts: `/api/po/invoice/public/v1/act` - Remove Drafts: `/api/po/invoice/public/v1/common/removeDrafts` - VAT Operations: `/api/po/vatacc/public/v1/operation/find.outbox` - Taxpayer by FIN: `/api/po/profile/public/v1/taxpayer/findByFinAndPassport` **Standard headers:** ```python DEFAULT_HEADERS = { "Accept": "application/json, text/plain, */*", "Accept-Language": "en-US,en;q=0.9", "Content-Type": "application/json", "Cache-Control": "no-cache", "Pragma": "no-cache" } ``` ### 5. Error Handling **HTTP Status Codes:** - `200` - Success - `401` - Token expired → Show "Please login again" - `404` - Resource not found - `500` - E-Taxes server error → Show "Try again later" **Always check in this order:** ```python if response.status_code == 401: return {"success": False, "message": "Authentication expired. Please login again."} if response.status_code == 500: return {"success": False, "message": "E-Taxes service error. Please try again later."} if response.status_code == 404: return {"success": False, "message": "Not found"} response.raise_for_status() # For other errors ``` ### 6. Frontend Button Pattern **Always show buttons conditionally:** ```javascript frappe.ui.form.on('My DocType', { refresh: function(frm) { // Only for submitted documents if (frm.doc.docstatus === 1) { add_etaxes_buttons(frm); } } }); function add_etaxes_buttons(frm) { // Check status and show appropriate buttons if (frm.doc.etaxes_status === 'Sent and Signed') { frm.add_custom_button(__('View Details'), function() { // Show details }, __('E-Taxes')); } else if (frm.doc.etaxes_status === 'Created, not signed') { frm.add_custom_button(__('Sign with ASAN Imza'), function() { // Sign document }, __('E-Taxes')); } else { frm.add_custom_button(__('Send to E-Taxes'), function() { // Send to E-Taxes }, __('E-Taxes')); } } ``` ### 7. Build Process **After modifying JavaScript files:** ```bash # Build assets cd /home/frappe/frappe-bench bench build --app invoice_az # Clear cache bench --site site1 clear-cache ``` **After modifying Python files:** ```bash # Just clear cache (no build needed) bench --site site1 clear-cache ``` ### 8. Common Mistakes to Avoid ❌ **Don't do this:** 1. Call E-Taxes API without `ETaxes.auth.checkAndProcess()` 2. Forget to include ETaxes module in new JS files 3. Skip `record_etaxes_activity()` in backend functions 4. Forget to handle 401/500/404 errors 5. Use `app_include_js` in hooks.py (doesn't work for doctype-specific code) 6. Make API calls without Bearer token in headers ✅ **Always do this:** 1. Wrap ALL E-Taxes operations in `ETaxes.auth.checkAndProcess()` 2. Copy ETaxes module (564 lines) to every new JS file 3. Call `record_etaxes_activity()` first in every API function 4. Handle 401, 500, 404 explicitly 5. Return consistent `{success, message}` format 6. Add `x-authorization: Bearer {token}` header 7. Build assets after JS changes ### 9. Example Files to Reference **Backend (Python):** - ✅ `send_sales_api.py` - Perfect example of all patterns - ✅ `send_purchase_api.py` - Agricultural act example - ✅ `supplier_api.py` - Simple API call example - ✅ `auth.py` - Authentication implementation **Frontend (JavaScript):** - ✅ `sales_invoice.js` - Complete ETaxes module (lines 1-564) - ✅ `purchase_invoice.js` - Button patterns - ✅ `supplier.js` - Minimal working example **When in doubt:** Look at `send_sales_api.py` + `sales_invoice.js` - they contain all correct patterns! ## Development Commands ### Linting and Code Quality ```bash # Run ruff for Python linting ruff check invoice_az/ # Run ruff format ruff format invoice_az/ # Run pre-commit hooks (includes ruff, eslint, prettier, pyupgrade) pre-commit run --all-files ``` ### Testing ```bash # Run unit tests for a specific doctype bench run-tests --app invoice_az --doctype "E-Taxes Item" # Run all tests for the app bench run-tests --app invoice_az ``` ### Development ```bash # Clear cache after making changes bench clear-cache # Restart workers after API changes bench restart # Watch logs bench --site [site-name] console ``` ## Architecture ### Core Modules 1. **Authentication Module** (`invoice_az/auth.py`) - ASAN Login integration for Azerbaijan government authentication - Token management with automatic renewal every 4 minutes via cron job - Activity tracking to prevent unnecessary token renewals - Retry logic with exponential backoff for failed requests - Token validity checking and automatic refresh on 401 errors - Full authentication flow: start auth → poll status → get certificates → select taxpayer - Key functions: `renew_token()`, `get_auth_token()`, `check_auth_status()`, `get_certificates()`, `choose_taxpayer()`, `check_token_validity()`, `handle_unauthorized_request()`, `handle_authentication()`, `poll_auth_status()`, `select_certificate()`, `select_taxpayer()` 2. **Purchase API** (`invoice_az/api.py`) - Download and import purchase invoices from e-taxes - Party, item, and unit mapping system - Separate Customer and Supplier mapping systems - Create Purchase Orders and Purchase Invoices - E-Taxes Purchase tracking records - Reference data management (sync items, units, parties from e-taxes) - Batch invoice processing for loading reference data - Auto-matching for items, units, customers, suppliers by name similarity 3. **Sales Import API** (`invoice_az/sales_api.py`) - Download and import sales invoices from e-taxes outbox - Customer mapping system (separate from suppliers) - Create Sales Orders and Sales Invoices - E-Taxes Sales tracking records - Azerbaijani character normalization for matching 4. **Sales Send API** (`invoice_az/send_sales_api.py`) - Send Sales Invoices to e-taxes system - Two-step workflow: create draft, then sign with ASAN Imza - Generate serial numbers from e-taxes - Build invoice payload with product codes and VAT fields - E-Taxes Sales Outbox tracking - Cancel/remove draft invoices functionality - Retry signing for failed/pending invoices - Get customer objects by TIN for delivery address selection 5. **VAT Operations API** (`invoice_az/vat_api.py`) - Import VAT Account operations from e-taxes - Import all operations (both income and expense types) - Create Journal Entries with configurable account mappings - VAT Account Mappings by operation type and expense/income type (Sub uçot hesabı → Sub uçot hesabı, Sub uçot hesabı → Büdcə, etc.) - Classification Code support - allows specific account mappings per tax code with priority: - Priority 1: Mapping with matching operation_type + expense_income + classification_code - Priority 2: Default mapping with matching operation_type + expense_income (empty classification_code) - Required mapping configuration - operation fails with error if mapping not found - Smart party assignment: adds Customer/Supplier only for Receivable/Payable accounts - Customer lookup by TIN - E-Taxes VAT Operations tracking - Key functions: `get_accounts_for_operation_type()`, `find_account_by_number()`, `create_journal_entry_from_vat_operation()`, `map_operation_type()` 6. **VAT Operations Hooks** (`invoice_az/vat_operations.py`) - Delete related E-Taxes VAT Operations when Journal Entry is deleted/cancelled ### Document Integration (hooks.py) **Extended Doctypes:** - Purchase Order - import from e-taxes, delete hooks - Purchase Invoice - import from e-taxes - Sales Order - import from e-taxes, delete hooks - Sales Invoice - send to e-taxes, delete hooks - Journal Entry - import VAT operations, delete hooks - E-Taxes Settings - on_update hook to sync mapped statuses **Client-side Scripts (`invoice_az/client/`):** - `purchase_order.js` - E-taxes import buttons and dialogs - `purchase_invoice.js` - E-taxes import functionality - `sales_order.js` - E-taxes import buttons and dialogs - `sales_invoice.js` - Send to e-taxes, sign document, retry signing, cancel buttons - `journal_entry.js` - VAT operations import functionality with operation type display - `e_taxes_items_list.js` - Sync items from e-taxes - `e_taxes_suppliers_list.js` - Sync suppliers from e-taxes - `e_taxes_customers_list.js` - Sync customers from e-taxes - `e_taxes_unit_list.js` - Sync units from e-taxes - `etaxes_common.js` - Shared utilities ### Database Schema **Authentication:** - **Asan Login** - Stores ASAN credentials, tokens, certificates, auth status **Settings:** - **E-Taxes Settings** - Global settings, status mappings, item/party/customer/supplier/VAT account mappings **E-Taxes Entities (cached from e-taxes):** - **E-Taxes Item** - Products/services from e-taxes with EQM codes - **E-Taxes Parties** - All parties (legacy, for purchases) - **E-Taxes Suppliers** - Supplier companies for purchases - **E-Taxes Customers** - Customer companies for sales - **E-Taxes Unit** - Units of measurement - **E-Taxes Item Group** - Product group codes (fixtures) - **Classification code** - Tax classification codes from e-taxes (code and description) **Mapping Tables:** - **E-Taxes Item Mapping** - Links ERPNext Items to e-taxes items - **E-Taxes Party Mapping** - Links ERPNext parties to e-taxes parties (legacy) - **E-Taxes Supplier Mappings** - Links ERPNext Suppliers to e-taxes suppliers - **E-Taxes Customer Mappings** - Links ERPNext Customers to e-taxes customers - **E-Taxes Unit Mapping** - Links ERPNext UOM to e-taxes units - **E-Taxes VAT Account Mapping** - Maps VAT operation types to Chart of Accounts (debit/credit), with expense/income type and optional classification code filtering **Tracking Records:** - **E-Taxes Purchase** - Tracks imported purchase documents - **E-Taxes Sales** - Tracks imported sales documents (from e-taxes) - **E-Taxes Sales Outbox** - Tracks sent sales invoices (to e-taxes) - **E-Taxes VAT Operations** - Tracks imported VAT operations ### Key Features - **Token Renewal**: Automatic token renewal via scheduler (every 4 minutes) with activity check - **Token Validity Check**: Verify token validity before API calls, auto-refresh on 401 errors - **Activity Tracking**: Records user activity to optimize token renewals - **Entity Mapping**: Maps ERPNext items, parties, suppliers, customers, and units to e-taxes equivalents - **Auto-Matching**: Automatic matching of items, units, customers, suppliers by name similarity - **Bulk Operations**: Support for syncing multiple entities at once - **Batch Processing**: Load reference data from invoices in batches - **Error Handling**: Comprehensive error logging and user-friendly error messages - **Azerbaijani Support**: Character normalization for Ə, Ü, Ö, Ğ, İ, Ç, Ş characters - **Two-step Signing**: Create draft invoice, then sign with ASAN Imza - **Retry Signing**: Retry signing for failed/pending invoices - **VAT Import**: Import VAT account operations as Journal Entries with configurable account mappings - **VAT Account Mappings**: Configure debit/credit accounts by operation type and expense/income type (Sub uçot hesabı → Sub uçot hesabı, Sub uçot hesabı → Büdcə, etc.) - **Smart Party Assignment**: Automatically adds party (Customer/Supplier) only for Receivable/Payable accounts ### API Endpoints (E-Taxes) **Base URL:** `https://new.e-taxes.gov.az` - `/api/po/auth/public/v1/*` - Authentication endpoints - `/api/po/invoice/public/v2/invoice/find.inbox` - Purchase invoices - `/api/po/invoice/public/v2/invoice/find.outbox` - Sales invoices (sent) - `/api/po/invoice/public/v2/invoice` - Create invoice - `/api/po/invoice/public/v1/invoice/sign/withAsanImza` - Sign invoice - `/api/po/invoice/public/v1/generateSerialNumber/defaultInvoice` - Generate serial - `/api/po/invoice/public/v1/common/removeDrafts` - Remove draft invoices - `/api/po/vatacc/public/v1/operation/find.outbox` - VAT operations - `/api/po/profile/public/v1/taxpayer/{tin}/object/find` - Customer objects - `/api/po/dictionary/public/v1/productGroups/find` - Product groups dictionary ### Fixtures - **E-Taxes Item Group** - Pre-populated product group codes ### Install Hooks - `after_install` and `after_migrate` both call `setup_token_renewal()` to ensure scheduler is configured ### Security Considerations - All API endpoints are whitelisted with `@frappe.whitelist()` - Token storage uses Frappe's password field type - Activity tracking prevents unnecessary API calls - Retry logic includes exponential backoff to prevent API flooding - Automatic token refresh on 401 errors ### Important Files - `invoice_az/hooks.py` - App configuration, event hooks, scheduler setup, and fixtures (~310 lines) - `invoice_az/auth.py` - Authentication and token management (~970 lines) - `invoice_az/api.py` - Purchase invoice API and reference data management (~4460 lines) - `invoice_az/sales_api.py` - Sales invoice import API (~890 lines) - `invoice_az/send_sales_api.py` - Sales invoice send API (~1060 lines) - `invoice_az/vat_api.py` - VAT operations import API (~620 lines) - `invoice_az/vat_operations.py` - VAT operations hooks (~40 lines) - `invoice_az/client/*.js` - Client-side functionality for UI enhancements - `invoice_az/invoice_az/doctype/*/` - Custom doctype definitions - `invoice_az/fixtures/e_taxes_item_group.json` - Item group fixtures ### Workflow: Importing Purchases 1. User opens Purchase Order/Invoice list 2. Clicks "Import from E-Taxes" button 3. System fetches invoices from e-taxes inbox 4. User selects invoice to import 5. System validates mappings (items, suppliers, units) 6. Creates Purchase Order with items 7. Creates E-Taxes Purchase tracking record ### Workflow: Importing Sales (from E-Taxes) 1. User opens Sales Order list 2. Clicks "Import from E-Taxes" button 3. System fetches invoices from e-taxes outbox 4. User selects invoice to import 5. System validates mappings (items, customers, units) 6. Creates Sales Order and Sales Invoice 7. Creates E-Taxes Sales tracking record ### Workflow: Sending Sales Invoice to E-Taxes 1. User creates and submits Sales Invoice 2. Fills customer_object_name field (required for delivery address) 3. Clicks "Send to E-Taxes" button 4. System generates serial number 5. Creates draft invoice on e-taxes 6. User clicks "Sign Document" button 7. System signs with ASAN Imza 8. E-Taxes Sales Outbox record updated **Retry/Cancel:** - If signing fails, user can click "Retry Signing" button - User can cancel draft invoice using "Cancel on E-Taxes" button ### Workflow: Sending Purchase Acts to E-Taxes Supported act types for Purchase Invoices with Individual suppliers: 1. **Agricultural Products Act** - For agricultural goods (kind: "agriculturalProductsAct") - Tax types: "Tax Free" (0%) or "Taxable" (5%) - Endpoint: `/api/po/invoice/public/v1/act/generateSerialNumber/agriculturalProductsAct` 2. **Metal Scrap Reception Act** - For ferrous/non-ferrous metal scrap (kind: "metalProductsAct") - Tax types: Only "Taxable" (5%) - tax-free items not allowed - Validation: All items must have tax_type = "Taxable" - Endpoint: `/api/po/invoice/public/v1/act/generateSerialNumber/metalProductsAct` 3. **Tire Products For Disposal Act** - For tire disposal operations (kind: "tireProductsForDisposalAct") - Tax types: Only "Taxable" (5%) - tax-free items not allowed - Validation: All items must have tax_type = "Taxable" - Endpoint: `/api/po/invoice/public/v1/act/generateSerialNumber/tireProductsForDisposalAct` 4. **Plastic Products For Disposal Act** - For plastic disposal operations (kind: "plasticProductsForDisposalAct") - Tax types: Only "Taxable" (5%) - tax-free items not allowed - Validation: All items must have tax_type = "Taxable" - Endpoint: `/api/po/invoice/public/v1/act/generateSerialNumber/plasticProductsForDisposalAct` 5. **Rawhide Supply** - For rawhide supply operations (kind: "rawhideSupply") - Tax types: Only "Taxable" (5%) - tax-free items not allowed - Validation: All items must have tax_type = "Taxable" - Endpoint: `/api/po/invoice/public/v1/act/generateSerialNumber/rawhideSupply` 6. **Other Product Receipt Act** - For other product receipts (kind: "otherProductReceiptAct") - Tax types: "Tax Free" (0%) or "Taxable" (5%) - both allowed - Validation: No tax type restrictions (same as Agricultural) - Endpoint: `/api/po/invoice/public/v1/act/generateSerialNumber/otherProductReceiptAct` **Workflow:** 1. User creates and submits Purchase Invoice 2. Selects Individual supplier (with FIN, passport, DOB) 3. Checks `purchase_type` checkbox to enable act fields 4. Selects `act_kind` (one of 6 available types) 5. Adds items with product_group_code and tax_type 6. Clicks "Send Act to E-Taxes" button (button text changes based on act_kind) 7. System generates serial number from appropriate endpoint 8. Creates draft act on e-taxes 9. User clicks "Sign Act with ASAN Imza" button 10. System signs with ASAN Imza 11. E-Taxes Purchase Outbox record updated **Retry/Cancel:** - If signing fails, user can click "Retry Signing" button - User can cancel draft act using "Cancel Act on E-Taxes" button ### Workflow: Importing VAT Operations 1. User opens Journal Entry list 2. Clicks "Import VAT from E-Taxes" button 3. Selects date range 4. System fetches all VAT operations (both income and expense types) 5. System shows operation selection dialog with columns: - Date, TIN, Name, Operation Type, Classification Code, Amount 6. Creates Journal Entries using account mappings: - API returns technical operation types (SUB_TO_SUB, etc.) which are mapped to Azerbaijani names - API returns taxCodeInfo with code (e.g., "114117") and description - Looks up mapping in E-Taxes Settings with priority: - First: operation_type + classification_code (if taxCodeInfo.code exists) - Second: operation_type + empty classification_code (default mapping) - If mapping not found, operation fails with error (shown in error log) - Automatically adds party (Customer) only if account type is Receivable/Payable - Supports different debit/credit accounts for different operation types and classification codes 7. Creates E-Taxes VAT Operations tracking records **VAT Account Mapping Configuration:** - Configure in E-Taxes Settings > VAT Account Mappings tab - Each mapping specifies: operation type, expense/income type (required), classification code (optional), debit account, credit account - Expense/Income field: Select "Expense" or "Income" to distinguish between expense and income operations - Classification Code field links to Classification code doctype - Uniqueness: Each combination of operation_type + expense_income + classification_code must be unique - Priority logic: - System determines expense/income type from API data (income > 0 → Income, expense > 0 → Expense) - If classification_code is set: mapping applies only to operations with matching taxCodeInfo.code - If classification_code is empty: mapping is default for this operation type - System searches with priority: specific classification_code first, then default (empty) - All searches include expense_income filter - Supported operation types: - Sub uçot hesabı → Sub uçot hesabı (SUB_TO_SUB in API) - Naməlum → digər Sub hesab (UNKNOWN_TO_OTHER_SUB in API) - Cari → Sub uçot hesabı (CURRENT_TO_SUB in API) - Cari → Naməlum (CURRENT_TO_UNKNOWN in API) - Sub uçot hesabı → İdxal (SUB_TO_IMPORT in API) - Naməlum → İdxal (UNKNOWN_TO_IMPORT in API) - Sub uçot hesabı → Büdcə (SUB_TO_BUDGET and AUTO in API) - Naməlum → Büdcə (UNKNOWN_TO_BUDGET in API) **Note:** AUTO operation types from API are automatically mapped to "Sub uçot hesabı → Büdcə" (SUB_TO_BUDGET).