cleanup: remove Test API buttons from sales invoice, add filterable badges in journal entry

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Ali 2026-04-01 19:10:29 +04:00
parent c561371a16
commit cdb6739308
3 changed files with 3 additions and 257 deletions

View File

@ -4307,133 +4307,3 @@ def refresh_token_from_asan_login():
'success': False,
'message': str(e)
}
@frappe.whitelist()
def test_product_groups_api(product_type="service"):
"""Test API request to get product groups from e-taxes
Args:
product_type: Type of products to fetch - "service" or "good"
"""
# Записываем активность
record_etaxes_activity()
# Получаем токен из настроек
asan_login_settings = get_default_asan_login()
if not asan_login_settings.get('found'):
return {
'success': False,
'message': 'No Asan Login settings found. Please configure authentication first.'
}
token = asan_login_settings.get('main_token')
if not token:
return {
'success': False,
'message': 'No authentication token found. Please authenticate first.'
}
# Валидация типа продукта
if product_type not in ['service', 'good']:
product_type = 'service'
# URL для запроса
url = f"https://new.e-taxes.gov.az/api/po/dictionary/public/v1/productGroups/find?queryText=&type={product_type}&scope=ALL"
# Заголовки запроса
headers = {
"Accept": "application/json, text/plain, */*",
"Content-Type": "application/json",
"Cache-Control": "no-cache",
"x-authorization": f"Bearer {token}"
}
try:
# Выполняем GET запрос
response = requests.get(url, headers=headers, timeout=30)
# Проверяем статус код 500
if response.status_code == 500:
frappe.log_error(f"[TEST_PRODUCT_GROUPS] Server error 500", "E-Taxes Server Error")
return {
'success': False,
'error': 'server_error',
'message': 'Service temporarily unavailable. Please try again in a few minutes.',
'status_code': 500
}
# Проверяем статус код 401
if response.status_code == 401:
frappe.log_error(f"[TEST_PRODUCT_GROUPS] Unauthorized 401", "E-Taxes Auth Error")
return {
'success': False,
'error': 'unauthorized',
'message': 'Authentication required. Please login again.',
'status_code': 401
}
# Проверяем успешность запроса
response.raise_for_status()
# Получаем JSON данные
data = response.json()
# Логируем успешный ответ
frappe.log_error(
f"[TEST_PRODUCT_GROUPS] Success: received {len(data) if isinstance(data, list) else 'data'} items for type={product_type}",
"E-Taxes Test API Success"
)
return {
'success': True,
'message': f'Successfully retrieved product groups (type: {product_type})',
'data': data,
'count': len(data) if isinstance(data, list) else None,
'product_type': product_type
}
except requests.exceptions.HTTPError as e:
frappe.log_error(
f"[TEST_PRODUCT_GROUPS] HTTP error: {e.response.status_code} - {str(e)}",
"E-Taxes Test API Error"
)
if e.response.status_code == 401:
return {
'success': False,
'error': 'unauthorized',
'message': 'Authentication required. Please login again.',
'status_code': 401
}
elif e.response.status_code == 500:
return {
'success': False,
'error': 'server_error',
'message': 'Service temporarily unavailable. Please try again in a few minutes.',
'status_code': 500
}
return {
'success': False,
'error': 'http_error',
'message': f'HTTP Error: {str(e)}'
}
except requests.exceptions.Timeout:
frappe.log_error(f"[TEST_PRODUCT_GROUPS] Request timeout", "E-Taxes Test API Error")
return {
'success': False,
'error': 'timeout',
'message': 'Request timeout. Please try again.'
}
except Exception as e:
frappe.log_error(
f"[TEST_PRODUCT_GROUPS] Unexpected error: {str(e)}\n{frappe.get_traceback()}",
"E-Taxes Test API Error"
)
return {
'success': False,
'error': 'unknown_error',
'message': f'An error occurred: {str(e)}'
}

View File

@ -1422,9 +1422,9 @@ frappe.listview_settings['Journal Entry'] = {
formatters: {
expense_income_type: function(value) {
if (value === 'Income') {
return '<span class="indicator-pill green">' + value + '</span>';
return '<span class="filterable indicator-pill green" data-filter="expense_income_type,=,Income">' + value + '</span>';
} else if (value === 'Expense') {
return '<span class="indicator-pill red">' + value + '</span>';
return '<span class="filterable indicator-pill red" data-filter="expense_income_type,=,Expense">' + value + '</span>';
}
return value || '';
},
@ -1432,7 +1432,7 @@ frappe.listview_settings['Journal Entry'] = {
etaxes_document_type: function(value, field, doc) {
// Show blue badge "ƏDV" only for documents loaded from e-taxes
if (value === 'ədv' && (doc.loaded_from_etaxes === 1 || doc.loaded_from_etaxes === '1')) {
return '<span class="indicator-pill blue" title="' + __('VAT Operation from E-Taxes') + '">ƏDV</span>';
return '<span class="filterable indicator-pill blue" data-filter="etaxes_document_type,=,ədv" title="' + __('VAT Operation from E-Taxes') + '">ƏDV</span>';
}
return '';
}

View File

@ -1490,15 +1490,6 @@ frappe.ui.form.on('Sales Invoice', {
* Add E-Taxes buttons based on current status
*/
function add_etaxes_buttons(frm) {
// Add test buttons - always visible
frm.add_custom_button(__('Test API - Services'), function() {
test_product_groups_api(frm, 'service');
}, __('E-Taxes'));
frm.add_custom_button(__('Test API - Goods'), function() {
test_product_groups_api(frm, 'good');
}, __('E-Taxes'));
// Status: Sent and Signed - show indicator and details button
if (frm.doc.etaxes_send_status === 'Sent and Signed') {
frm.page.set_indicator(__('Sent to E-Taxes'), 'green');
@ -2108,121 +2099,6 @@ function show_etaxes_details(frm) {
});
}
/**
* Test Product Groups API function
* @param {object} frm - The form object
* @param {string} productType - Type of products to fetch ('service' or 'good')
*/
function test_product_groups_api(frm, productType) {
productType = productType || 'service';
const typeLabel = productType === 'service' ? __('Services') : __('Goods');
// Show loading dialog
ETaxes.dialogs.showLoading(
__('Testing API'),
__('Requesting {0} from E-Taxes...', [typeLabel]),
__('Please wait')
);
// Call backend API
frappe.call({
method: 'invoice_az.api.test_product_groups_api',
args: {
product_type: productType
},
callback: function(r) {
if (r.message && r.message.success) {
// Success
const count = r.message.count || 0;
const data = r.message.data || [];
ETaxes.dialogs.setSuccess(
__('API Test Successful'),
__('Received {0} product groups ({1})', [count, typeLabel]),
function() {
// Show detailed results
let html = '<div style="max-height: 400px; overflow-y: auto;">';
html += '<div style="margin-bottom: 10px; padding: 8px; background: #e8f5e9; border-radius: 4px;">';
html += '<strong>Type:</strong> ' + typeLabel + ' | <strong>Count:</strong> ' + count;
html += '</div>';
if (Array.isArray(data) && data.length > 0) {
html += '<table class="table table-bordered">';
html += '<thead><tr><th>Code</th><th>Name</th><th>Type</th></tr></thead>';
html += '<tbody>';
data.slice(0, 10).forEach(function(item) {
html += '<tr>';
html += '<td>' + (item.code || '-') + '</td>';
html += '<td>' + (item.name || '-') + '</td>';
html += '<td>' + (item.type || '-') + '</td>';
html += '</tr>';
});
html += '</tbody></table>';
if (data.length > 10) {
html += '<p style="text-align: center; color: #888;">Showing first 10 of ' + data.length + ' items</p>';
}
} else if (typeof data === 'object') {
html += '<pre style="background: #f5f5f5; padding: 10px; border-radius: 4px;">';
html += JSON.stringify(data, null, 2);
html += '</pre>';
} else {
html += '<p>No data received</p>';
}
html += '</div>';
frappe.msgprint({
title: __('Product Groups Data - {0}', [typeLabel]),
indicator: 'green',
message: html
});
}
);
} else {
// Error
const errorMsg = r.message ? r.message.message : __('Unknown error occurred');
ETaxes.dialogs.setError(
__('API Test Failed'),
errorMsg
);
}
},
error: function(r) {
let errorMsg = __('Failed to communicate with E-Taxes service.');
// Try to extract actual error message
if (r && r.responseText) {
try {
const errorData = JSON.parse(r.responseText);
if (errorData.exc) {
const excMatch = errorData.exc.match(/Exception: (.+)/);
if (excMatch) {
errorMsg = excMatch[1];
} else {
const lines = errorData.exc.split('\n');
errorMsg = lines[lines.length - 1] || errorData.exc.substring(0, 200);
}
} else if (errorData.message) {
errorMsg = errorData.message;
}
} catch (e) {
errorMsg = r.responseText.substring(0, 300);
}
} else if (r && r.statusText) {
errorMsg = r.statusText;
}
ETaxes.dialogs.setError(
__('Error'),
errorMsg
);
}
});
}
/**
* List view settings
*/