invoice_az/CLAUDE.md

297 lines
14 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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