invoice_az/CLAUDE.md

14 KiB
Raw Blame History

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

Development Commands

Linting and Code Quality

# 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

# 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

# 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: 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).