added eqm codes to items and etaxes items

This commit is contained in:
Ali 2025-09-22 20:57:36 +04:00
parent 6df36695db
commit 0896971525
3 changed files with 124 additions and 18 deletions

View File

@ -669,7 +669,7 @@ def match_similar_items():
@frappe.whitelist()
def create_unmapped_items(settings_name):
"""Creating items for unmapped elements from E-Taxes settings table"""
"""Creating items for unmapped elements from E-Taxes settings table with EQM Code support"""
# Записываем активность
record_etaxes_activity()
@ -693,12 +693,13 @@ def create_unmapped_items(settings_name):
"message": "No unmapped items in table to create"
}
# Batch load E-Taxes Items
# Batch load E-Taxes Items с EQM кодом
etaxes_items_data = frappe.get_all('E-Taxes Item',
filters={'name': ['in', unmapped_etaxes_items]},
fields=['name', 'etaxes_item_name', 'etaxes_item_code',
'etaxes_product_group_code', 'etaxes_product_group_name',
'is_service_item', 'is_from_purchase', 'is_from_sales'])
'is_service_item', 'is_from_purchase', 'is_from_sales',
'eqm_code']) # НОВОЕ: Добавляем eqm_code
# Build mapping settings dict
mapping_settings = {}
@ -724,6 +725,8 @@ def create_unmapped_items(settings_name):
# Check for custom fields once
product_group_code_field_exists = frappe.db.exists('Custom Field', {'dt': 'Item', 'fieldname': 'etaxes_product_group_code'})
product_group_name_field_exists = frappe.db.exists('Custom Field', {'dt': 'Item', 'fieldname': 'etaxes_product_group_name'})
eqm_code_field_exists = frappe.db.exists('Custom Field', {'dt': 'Item', 'fieldname': 'eqm_code'}) # НОВОЕ: Проверяем поле eqm_code
product_group_name_field_length = 140
if product_group_name_field_exists:
custom_field = frappe.get_doc('Custom Field', {'dt': 'Item', 'fieldname': 'etaxes_product_group_name'})
@ -815,6 +818,11 @@ def create_unmapped_items(settings_name):
product_group_name = product_group_name[:product_group_name_field_length]
item_doc.etaxes_product_group_name = product_group_name
# НОВОЕ: Добавляем EQM код если поле существует и код есть
if eqm_code_field_exists and etaxes_item_data.eqm_code:
item_doc.eqm_code = etaxes_item_data.eqm_code
frappe.log_error(f"Added EQM Code {etaxes_item_data.eqm_code} to item {item_doc.item_name}", "EQM Code Transfer")
# Add tax template
tax_template = individual_settings.get('item_tax_template') or settings_doc.default_item_tax_template
if tax_template and frappe.db.exists('Item Tax Template', tax_template):
@ -840,6 +848,7 @@ def create_unmapped_items(settings_name):
created_count += 1
except Exception as e:
frappe.log_error(f"Error creating item for {etaxes_item_data.etaxes_item_name}: {str(e)}", "Create Item Error")
error_count += 1
# Save settings
@ -859,7 +868,7 @@ def create_unmapped_items(settings_name):
"success": False,
"message": "An unknown error occurred, please try again in a few minutes."
}
@frappe.whitelist()
def create_purchase_invoice_from_order(purchase_order_name):
"""Создает Purchase Invoice из Purchase Order используя стандартную функцию ERPNext"""
@ -2082,7 +2091,7 @@ def refresh_item_mappings_display(settings_name):
@frappe.whitelist()
def process_single_invoice_for_items(token, invoice_id, source_type='purchase'):
"""Processing a single invoice for item extraction with name length handling"""
"""Processing a single invoice for item extraction with EQM Code assignment"""
# Записываем активность
record_etaxes_activity()
@ -2176,6 +2185,39 @@ def process_single_invoice_for_items(token, invoice_id, source_type='purchase'):
product_group_name = product_group_name[:1000]
frappe.log_error(f"Product group name truncated for item {item_name}: original length {len(product_group.get('name', {}).get('az', ''))}", "Product Group Name Truncation")
# НОВОЕ: Поиск EQM Code по коду группы товаров - возвращаем name для Link поля
eqm_code = None
if product_group_code:
try:
frappe.log_error(f"[EQM DEBUG] Searching for product_group_code: '{product_group_code}'", "EQM Code Search")
# Ищем запись и получаем и name, и eqm_name
eqm_record = frappe.db.sql("""
SELECT name, eqm_name
FROM `tabEQM Codes`
WHERE eqm_name LIKE %s
LIMIT 1
""", (f"{product_group_code} -%",), as_dict=True)
frappe.log_error(f"[EQM DEBUG] SQL search result: {eqm_record}", "EQM Code Search")
if eqm_record:
# ИСПРАВЛЕНИЕ: Сохраняем name (ID записи) для Link поля, а не eqm_name
eqm_code = eqm_record[0].get('name') # Изменено с eqm_name на name
frappe.log_error(f"[EQM DEBUG] Found EQM Code ID: '{eqm_code}' (description: '{eqm_record[0].get('eqm_name')}') for product group '{product_group_code}' in item {item_name}", "EQM Code Assignment")
else:
frappe.log_error(f"[EQM DEBUG] EQM Code not found for product group '{product_group_code}' in item {item_name}", "EQM Code Not Found")
except Exception as e:
frappe.log_error(f"[EQM DEBUG] Error searching EQM Code for '{product_group_code}': {str(e)}", "EQM Code Search Error")
# Логируем финальное значение
frappe.log_error(f"[EQM DEBUG] Final eqm_code ID to save: '{eqm_code}' for item {item_name}", "EQM Code Final")
# Логируем финальное значение
frappe.log_error(f"[EQM DEBUG] Final eqm_code value to save: '{eqm_code}' for item {item_name}", "EQM Code Final")
# Определяем, является ли товар услугой
is_service = 1 if product_group_type == 'service' else 0
@ -2192,7 +2234,8 @@ def process_single_invoice_for_items(token, invoice_id, source_type='purchase'):
'source_invoice': serial_number,
'is_from_purchase': is_from_purchase,
'is_from_sales': is_from_sales,
'status': 'New'
'status': 'New',
'eqm_code': eqm_code # НОВОЕ: Добавляем EQM код
}
# Создаём записи для уникальных товаров
@ -2235,7 +2278,7 @@ def process_single_invoice_for_items(token, invoice_id, source_type='purchase'):
'success': False,
'message': "An unknown error occurred processing this invoice"
}
@frappe.whitelist()
def process_single_invoice_for_units(token, invoice_id, source_type='purchase'):
"""Processing a single invoice for unit extraction with progress support"""
@ -3798,7 +3841,7 @@ def process_single_invoice_for_reference_data(token, invoice_id, source_type='pu
@frappe.whitelist()
def create_reference_data_from_single_invoice(invoice_details, source_type):
"""Создает все 4 типа доктайпов из одного инвойса - оптимизированная версия"""
"""Создает все 4 типа доктайпов из одного инвойса с EQM кодами - оптимизированная версия"""
try:
stats = {
'items_created': 0,
@ -3816,7 +3859,7 @@ def create_reference_data_from_single_invoice(invoice_details, source_type):
sender = invoice_details.get('sender', {})
receiver = invoice_details.get('receiver', {})
# === СОЗДАНИЕ ТОВАРОВ ===
# === СОЗДАНИЕ ТОВАРОВ С EQM КОДАМИ ===
processed_items = set()
for item in items:
item_name = item.get('productName', '').strip()
@ -3859,6 +3902,38 @@ def create_reference_data_from_single_invoice(invoice_details, source_type):
if len(product_group_name) > 1000:
product_group_name = product_group_name[:1000]
# НОВОЕ: Поиск EQM Code по коду группы товаров - возвращаем name для Link поля
eqm_code = None
if product_group_code:
try:
frappe.log_error(f"[EQM DEBUG] Searching for product_group_code: '{product_group_code}'", "EQM Code Search")
# Ищем запись и получаем и name, и eqm_name
eqm_record = frappe.db.sql("""
SELECT name, eqm_name
FROM `tabEQM Codes`
WHERE eqm_name LIKE %s
LIMIT 1
""", (f"{product_group_code} -%",), as_dict=True)
frappe.log_error(f"[EQM DEBUG] SQL search result: {eqm_record}", "EQM Code Search")
if eqm_record:
# ИСПРАВЛЕНИЕ: Сохраняем name (ID записи) для Link поля, а не eqm_name
eqm_code = eqm_record[0].get('name') # Изменено с eqm_name на name
frappe.log_error(f"[EQM DEBUG] Found EQM Code ID: '{eqm_code}' (description: '{eqm_record[0].get('eqm_name')}') for product group '{product_group_code}' in item {item_name}", "EQM Code Assignment")
else:
frappe.log_error(f"[EQM DEBUG] EQM Code not found for product group '{product_group_code}' in item {item_name}", "EQM Code Not Found")
except Exception as e:
frappe.log_error(f"[EQM DEBUG] Error searching EQM Code for '{product_group_code}': {str(e)}", "EQM Code Search Error")
# Логируем финальное значение
frappe.log_error(f"[EQM DEBUG] Final eqm_code ID to save: '{eqm_code}' for item {item_name}", "EQM Code Final")
# Логируем финальное значение
frappe.log_error(f"[EQM DEBUG] Final eqm_code value to save: '{eqm_code}' for item {item_name}", "EQM Code Final")
# Определяем, является ли товар услугой
is_service = 1 if product_group_type == 'service' else 0
@ -3866,7 +3941,8 @@ def create_reference_data_from_single_invoice(invoice_details, source_type):
is_from_purchase = 1 if source_type == 'purchase' else 0
is_from_sales = 1 if source_type == 'sales' else 0
doc = frappe.get_doc({
# Создаем документ с EQM кодом
doc_data = {
'doctype': 'E-Taxes Item',
'etaxes_item_name': item_name,
'etaxes_item_code': item_code,
@ -3880,7 +3956,13 @@ def create_reference_data_from_single_invoice(invoice_details, source_type):
'is_from_purchase': is_from_purchase,
'is_from_sales': is_from_sales,
'status': 'New'
})
}
# НОВОЕ: Добавляем EQM код если найден
if eqm_code:
doc_data['eqm_code'] = eqm_code
doc = frappe.get_doc(doc_data)
doc.insert(ignore_permissions=True, ignore_if_duplicate=True)
stats['items_created'] += 1
@ -4018,7 +4100,7 @@ def create_reference_data_from_single_invoice(invoice_details, source_type):
'success': False,
'message': str(e)
}
# ===== НОВЫЕ PYTHON ФУНКЦИИ =====
@frappe.whitelist()

View File

@ -9,6 +9,7 @@
"etaxes_item_code",
"etaxes_unit",
"etaxes_price",
"eqm_code",
"product_group_section",
"etaxes_product_group_code",
"etaxes_product_group_name",
@ -156,11 +157,17 @@
"label": "Tax Template",
"options": "Item Tax Template",
"read_only": 1
},
{
"fieldname": "eqm_code",
"fieldtype": "Link",
"label": "EQM Code",
"options": "EQM Codes"
}
],
"index_web_pages_for_search": 1,
"links": [],
"modified": "2025-07-16 20:19:56.319865",
"modified": "2025-09-22 17:32:18.795605",
"modified_by": "Administrator",
"module": "Invoice Az",
"name": "E-Taxes Item",

View File

@ -18,13 +18,30 @@ def get_active_settings():
return frappe.get_doc('E-Taxes Settings', settings_list[0].name)
def record_etaxes_activity():
"""Record E-Taxes API activity to optimize token renewal"""
@frappe.whitelist()
def record_etaxes_activity(asan_login_name=None):
"""Записывает время последней активности с e-taxes напрямую"""
try:
frappe.cache().set_value("etaxes_last_activity", frappe.utils.now(), expires_in_sec=3600)
# Если имя не указано, получаем дефолтный профиль
if not asan_login_name:
default_settings = frappe.get_all(
"Asan Login",
filters={"is_default": 1},
fields=["name"],
limit=1
)
if not default_settings:
return
asan_login_name = default_settings[0].name
# Обновляем поле last_activity_time напрямую через БД
frappe.db.set_value("Asan Login", asan_login_name, "last_activity_time", now_datetime(), update_modified=False)
frappe.db.commit()
except Exception as e:
# Don't fail the whole operation if activity recording fails
frappe.log_error(f"Error recording E-Taxes activity: {str(e)}", "E-Taxes Activity Recording")
frappe.log_error(f"Error recording activity: {str(e)}", "Activity Recording Error")
@frappe.whitelist()
def get_sales_invoices(token, filters=None):