diff --git a/invoice_az/amas_api.py b/invoice_az/amas_api.py index 9ceaae8..040b49f 100644 --- a/invoice_az/amas_api.py +++ b/invoice_az/amas_api.py @@ -1650,6 +1650,294 @@ def create_single_employee_from_amas(asan_login_name, employee_data, company, cr } +@frappe.whitelist() +def create_single_employee_from_amas(asan_login_name, emp_data, company, create_designation=0): + """ + Create/update a SINGLE Employee record from ƏMAS data. + This is called from frontend in a loop for progress bar updates. + + Args: + asan_login_name: Asan Login name + emp_data: Single employee data dict from ƏMAS API + company: Company name + create_designation: 1/0 to create designation if not found + + Returns: + { + "success": True/False, + "action": "created"/"updated"/"error", + "employee_name": "...", + "full_name": "...", + "message": "..." + } + """ + try: + if isinstance(emp_data, str): + emp_data = json.loads(emp_data) + + create_designation = int(create_designation) + + if not company: + return {"success": False, "message": "Company is required"} + + doc = frappe.get_doc("Asan Login", asan_login_name) + organization_name = doc.amas_account_name + organization_voen = doc.amas_account_number + + # Status mapping + status_map = { + "qüvvədədir": "Active", + "aktiv": "Active", + "active": "Active", + "ləğv edilib": "Left", + "xitam": "Left", + "terminated": "Left", + "dayandırılıb": "Suspended", + "suspended": "Suspended", + } + + doc_oid = emp_data.get("doc_oid") + doc_no = emp_data.get("doc_no") + doc_type = emp_data.get("doc_type", "docType_47") + + # Fetch detail data for complete employee information + detail_data = None + full_name = str(emp_data.get("full_name") or "").strip() + + if doc_oid: + detail_result = get_employee_detail(asan_login_name, doc_oid, doc_no, doc_type) + if detail_result.get('success'): + detail_data = detail_result.get('data') + + # Get FIN from detail or list data + fin = None + if detail_data and 'EmasContractsEnt' in detail_data and isinstance(detail_data.get('EmasContractsEnt'), list) and len(detail_data['EmasContractsEnt']) > 0: + fin = detail_data['EmasContractsEnt'][0].get('pin') + # Also update full_name from detail data if available + if 'iamasBean' in detail_data and detail_data.get('iamasBean'): + person = detail_data['iamasBean'] + name = person.get('name', '') + surname = person.get('surname', '') + full_name = f"{name} {surname}".strip() + + if not fin: + fin = emp_data.get("identification_number") + + if not fin: + return { + "success": False, + "action": "error", + "full_name": full_name, + "message": f"{full_name}: No identification_number" + } + + fin = str(fin).strip() + + # 1. Save/update Amas Employees record + amas_existing = None + if doc_oid: + amas_existing = frappe.db.exists("Amas Employees", {"doc_oid": str(doc_oid)}) + if not amas_existing: + amas_existing = frappe.db.exists( + "Amas Employees", + {"identification_number": fin, "organization_voen": organization_voen} + ) + + if amas_existing: + amas_doc = frappe.get_doc("Amas Employees", amas_existing) + update_employee_from_data(amas_doc, emp_data) + if detail_data: + update_employee_from_detail_data(amas_doc, detail_data) + if not amas_doc.identification_number: + amas_doc.identification_number = fin + amas_doc.save(ignore_permissions=True) + else: + amas_doc = frappe.new_doc("Amas Employees") + amas_doc.asan_login = asan_login_name + amas_doc.organization_name = organization_name + amas_doc.organization_voen = organization_voen + amas_doc.identification_number = fin + update_employee_from_data(amas_doc, emp_data) + if detail_data: + update_employee_from_detail_data(amas_doc, detail_data) + if not amas_doc.identification_number: + amas_doc.identification_number = fin + amas_doc.insert(ignore_permissions=True) + + # 2. Create/update Employee record + existing_employee = frappe.db.exists("Employee", {"passport_number": fin}) + + # Split full_name into first/last + name_parts = full_name.split() if full_name else [] + first_name = name_parts[0] if name_parts else "?" + last_name = " ".join(name_parts[1:]) if len(name_parts) > 1 else "" + + # Parse dates from detail data if available, otherwise from list data + dob = None + doj = None + contract_end = None + + if detail_data: + if 'iamasBean' in detail_data and detail_data.get('iamasBean'): + dob = parse_amas_date(detail_data['iamasBean'].get('birthDate')) + if 'EmasContractDetailsEnt' in detail_data and isinstance(detail_data.get('EmasContractDetailsEnt'), list) and len(detail_data['EmasContractDetailsEnt']) > 0: + details = detail_data['EmasContractDetailsEnt'][0] + doj = parse_amas_date(details.get('beginDate')) + contract_end = parse_amas_date(details.get('endDate')) + else: + dob = parse_amas_date(emp_data.get("birthday")) + doj = parse_amas_date(emp_data.get("begin_date")) + contract_end = parse_amas_date(emp_data.get("end_date")) + + # Map status + raw_status = "" + if detail_data and 'EmasContractsEnt' in detail_data and isinstance(detail_data.get('EmasContractsEnt'), list) and len(detail_data['EmasContractsEnt']) > 0: + raw_status = str(detail_data['EmasContractsEnt'][0].get('contractStatus') or "").strip().lower() + else: + raw_status = str(emp_data.get("contract_status") or "").strip().lower() + status = status_map.get(raw_status, "Active") + + # Parse salary + salary = None + if detail_data and 'EmasContractDetailsEnt' in detail_data and isinstance(detail_data.get('EmasContractDetailsEnt'), list) and len(detail_data['EmasContractDetailsEnt']) > 0: + raw_salary = detail_data['EmasContractDetailsEnt'][0].get('monthlySalary') + else: + raw_salary = emp_data.get("monthly_salary") + + if raw_salary: + try: + salary = float(str(raw_salary).replace(",", ".").replace(" ", "")) + except (ValueError, TypeError): + pass + + # Resolve designation + position_text = None + if detail_data and 'staffData' in detail_data and detail_data.get('staffData'): + position_text = detail_data['staffData'].get('positionText') + else: + position_text = emp_data.get("work_position_text") + + designation = resolve_designation(position_text, create_designation) + + # Extract additional fields from amas_doc + middle_name = amas_doc.father_name if hasattr(amas_doc, 'father_name') else None + gender = map_gender(amas_doc.gender if hasattr(amas_doc, 'gender') else None) + cell_number = amas_doc.contact_phone if hasattr(amas_doc, 'contact_phone') else None + personal_email = amas_doc.contact_email if hasattr(amas_doc, 'contact_email') else None + marital_status_mapped = map_marital_status(amas_doc.marital_status if hasattr(amas_doc, 'marital_status') else None) + blood_group_mapped = map_blood_group(amas_doc.blood_type if hasattr(amas_doc, 'blood_type') else None) + date_of_issue = parse_amas_date(amas_doc.document_issue_date if hasattr(amas_doc, 'document_issue_date') else None) + valid_upto = parse_amas_date(amas_doc.document_expiry_date if hasattr(amas_doc, 'document_expiry_date') else None) + place_of_issue = amas_doc.document_issued_by if hasattr(amas_doc, 'document_issued_by') else None + current_address = build_full_address( + amas_doc.personal_address if hasattr(amas_doc, 'personal_address') else None, + amas_doc.personal_city if hasattr(amas_doc, 'personal_city') else None, + amas_doc.personal_district if hasattr(amas_doc, 'personal_district') else None + ) + + if existing_employee: + emp = frappe.get_doc("Employee", existing_employee) + emp.first_name = first_name + if middle_name: + emp.middle_name = middle_name + emp.last_name = last_name + emp.employee_name = full_name or first_name + emp.gender = gender + if dob: + emp.date_of_birth = dob + if doj: + emp.date_of_joining = doj + if contract_end: + emp.contract_end_date = contract_end + if salary is not None: + emp.ctc = salary + if designation: + emp.designation = designation + if cell_number: + emp.cell_number = cell_number + if personal_email: + emp.personal_email = personal_email + if marital_status_mapped: + emp.marital_status = marital_status_mapped + if blood_group_mapped: + emp.blood_group = blood_group_mapped + if date_of_issue: + emp.date_of_issue = date_of_issue + if valid_upto: + emp.valid_upto = valid_upto + if place_of_issue: + emp.place_of_issue = place_of_issue + if current_address: + emp.current_address = current_address + emp.save(ignore_permissions=True) + action = "updated" + else: + emp = frappe.new_doc("Employee") + emp.first_name = first_name + if middle_name: + emp.middle_name = middle_name + emp.last_name = last_name + emp.company = company + emp.passport_number = fin + emp.date_of_birth = dob or "2000-01-01" + emp.date_of_joining = doj or frappe.utils.today() + emp.gender = gender + emp.status = status + if contract_end: + emp.contract_end_date = contract_end + if salary is not None: + emp.ctc = salary + if designation: + emp.designation = designation + if cell_number: + emp.cell_number = cell_number + if personal_email: + emp.personal_email = personal_email + if marital_status_mapped: + emp.marital_status = marital_status_mapped + if blood_group_mapped: + emp.blood_group = blood_group_mapped + if date_of_issue: + emp.date_of_issue = date_of_issue + if valid_upto: + emp.valid_upto = valid_upto + if place_of_issue: + emp.place_of_issue = place_of_issue + if current_address: + emp.current_address = current_address + emp.insert(ignore_permissions=True) + action = "created" + + # Link Amas Employees → Employee + amas_doc.employee = emp.name + amas_doc.save(ignore_permissions=True) + + frappe.db.commit() + + return { + "success": True, + "action": action, + "employee_name": emp.name, + "full_name": full_name, + "message": f"{action.capitalize()}: {full_name}" + } + + except Exception as e: + fin_val = emp_data.get("identification_number", "?") if isinstance(emp_data, dict) else "?" + name_val = emp_data.get("full_name", "?") if isinstance(emp_data, dict) else "?" + error_msg = f"{name_val} ({fin_val}): {str(e)}" + frappe.log_error( + f"{error_msg}\n{frappe.get_traceback()}", + "EMAS Single Employee Create Error" + ) + return { + "success": False, + "action": "error", + "full_name": name_val, + "message": error_msg + } + + @frappe.whitelist() def create_employees_from_amas(asan_login_name, employees, company, create_designation=0): """ diff --git a/invoice_az/client/employee.js b/invoice_az/client/employee.js index 1efec6f..37cc260 100644 --- a/invoice_az/client/employee.js +++ b/invoice_az/client/employee.js @@ -520,14 +520,6 @@ function show_employee_selection(listview, asan_login_name, organization_name, e fieldtype: 'Section Break', label: __('Settings') }, - { - fieldname: 'company', - fieldtype: 'Link', - label: __('Company'), - options: 'Company', - reqd: 1, - default: default_company - }, { fieldname: 'create_designation', fieldtype: 'Check', @@ -568,7 +560,7 @@ function show_employee_selection(listview, asan_login_name, organization_name, e } d.hide(); - create_employees(listview, asan_login_name, selected_employees, values.company, values.create_designation); + create_employees(listview, asan_login_name, selected_employees, default_company, values.create_designation); }, secondary_action_label: __('Cancel'), secondary_action: function() { d.hide(); } @@ -594,95 +586,228 @@ function show_employee_selection(listview, asan_login_name, organization_name, e }); } -// Step 5: Create employees via backend +// Step 5: Create employees via backend - ONE BY ONE like E-Taxes function create_employees(listview, asan_login_name, selected_employees, company, create_designation) { - // Show progress indicator + // Initialize counters + window.amas_employees_to_process = selected_employees.length; + window.amas_cancel_loading = false; + + // Start processing + process_employees_one_by_one( + listview, + asan_login_name, + selected_employees, + company, + create_designation, + 0, // created_count + 0, // updated_count + 0, // error_count + [], // errors + 0 // current_index + ); +} + +// Process employees one by one (like E-Taxes loadSelectedInvoices) +function process_employees_one_by_one(listview, asan_login_name, employees_queue, company, create_designation, + created_count, updated_count, error_count, errors, current_index) { + // Check if finished + if (employees_queue.length === 0) { + frappe.hide_progress(); + $(document).off('progress-cancel.loading_amas_employees'); + + const total = created_count + updated_count + error_count; + show_import_summary(total, created_count, updated_count, error_count, errors); + + window.amas_employees_to_process = null; + listview.refresh(); + return; + } + + // Check if cancelled + if (window.amas_cancel_loading) { + employees_queue = []; + frappe.hide_progress(); + $(document).off('progress-cancel.loading_amas_employees'); + + const total = created_count + updated_count + error_count; + frappe.show_alert({ + message: __('Import cancelled. Processed ') + total + __(' employees.'), + indicator: 'orange' + }, 5); + + listview.refresh(); + return; + } + + // Take first employee from queue + const emp_data = employees_queue.shift(); + const is_last = employees_queue.length === 0; + const total_to_process = window.amas_employees_to_process || (created_count + updated_count + error_count + employees_queue.length + 1); + + current_index++; + + // Show progress frappe.show_progress( __('Loading from ƏMAS'), - 0, - selected_employees.length, - __('Fetching employee details...') + current_index - 1, + total_to_process, + __('Processing employee ') + current_index + __(' of ') + total_to_process, + null, + true ); + // Setup cancel handler + $(document).off('progress-cancel.loading_amas_employees'); + $(document).on('progress-cancel.loading_amas_employees', function() { + window.amas_cancel_loading = true; + frappe.show_alert({ + message: __('Cancelling import... Finishing current employee.'), + indicator: 'orange' + }, 3); + frappe.hide_progress(); + }); + + // Get employee name for progress message + const emp_name = emp_data.full_name || emp_data.identification_number || 'Employee'; + + // Update progress with employee name + frappe.show_progress( + __('Loading from ƏMAS'), + current_index - 1, + total_to_process, + __('Processing: ') + emp_name + ); + + // Create/update single employee frappe.call({ - method: 'invoice_az.amas_api.create_employees_from_amas', + method: 'invoice_az.amas_api.create_single_employee_from_amas', args: { asan_login_name: asan_login_name, - employees: selected_employees, + emp_data: emp_data, company: company, create_designation: create_designation ? 1 : 0 }, - freeze: true, - freeze_message: __('Creating employees from ƏMAS...'), callback: function(r) { - frappe.hide_progress(); - if (!r.message || !r.message.success) { - // Check for CSRF error - need to reconnect - if (r.message && r.message.csrf_error) { - show_amas_reconnect_dialog(asan_login_name, function() { - // Retry after successful reconnection - create_employees(listview, asan_login_name, selected_employees, company, create_designation); - }); - return; + if (r.message && r.message.success) { + // Success - increment counters + if (r.message.action === 'created') { + created_count++; + frappe.show_alert({ + message: __('Created: ') + r.message.full_name, + indicator: 'green' + }, 2); + } else if (r.message.action === 'updated') { + updated_count++; + frappe.show_alert({ + message: __('Updated: ') + r.message.full_name, + indicator: 'blue' + }, 2); } - - frappe.msgprint({ - title: __('Error'), - indicator: 'red', - message: r.message ? r.message.message : __('Failed to create employees') - }); - return; - } - - const res = r.message; - const total = res.created_count + res.updated_count + res.error_count; - - if (res.error_count === 0) { - let msg = __('All ') + total + __(' employees were processed successfully.'); - if (res.created_count > 0) { - msg += '
' + __('Created: ') + '' + res.created_count + ''; - } - if (res.updated_count > 0) { - msg += '
' + __('Updated: ') + '' + res.updated_count + ''; - } - - frappe.msgprint({ - title: __('Import Completed Successfully'), - indicator: 'green', - message: msg - }); } else { - let msg = '
'; - if (res.created_count > 0) { - msg += __('Successfully created: ') + '' + res.created_count + '
'; - } - if (res.updated_count > 0) { - msg += __('Updated: ') + '' + res.updated_count + '
'; - } - msg += __('Failed: ') + '' + res.error_count + ''; - msg += '
'; + // Error + error_count++; + const error_msg = r.message ? r.message.message : 'Unknown error'; + errors.push(error_msg); - if (res.errors && res.errors.length > 0) { - msg += '
'; - msg += '
'; - } - - frappe.msgprint({ - title: res.created_count > 0 ? __('Import Completed with Errors') : __('Import Failed'), - indicator: res.created_count > 0 ? 'orange' : 'red', - message: msg - }); + frappe.show_alert({ + message: __('Error: ') + (r.message ? r.message.full_name : emp_name), + indicator: 'red' + }, 3); } - listview.refresh(); + // Continue with next employee after short delay (like E-Taxes) + setTimeout(function() { + process_employees_one_by_one( + listview, + asan_login_name, + employees_queue, + company, + create_designation, + created_count, + updated_count, + error_count, + errors, + current_index + ); + }, 50); // 50ms delay like E-Taxes PROGRESS_UPDATE_DELAY + }, + error: function(xhr, status, error) { + // Network error + error_count++; + const error_msg = emp_name + ': Network error - ' + (error || 'Unknown error'); + errors.push(error_msg); + + frappe.show_alert({ + message: __('Network error: ') + emp_name, + indicator: 'red' + }, 3); + + // Continue with next employee + setTimeout(function() { + process_employees_one_by_one( + listview, + asan_login_name, + employees_queue, + company, + create_designation, + created_count, + updated_count, + error_count, + errors, + current_index + ); + }, 50); } }); } +// Show final summary (like E-Taxes) +function show_import_summary(total, created_count, updated_count, error_count, errors) { + if (error_count === 0) { + let msg = __('All ') + total + __(' employees were processed successfully.'); + if (created_count > 0) { + msg += '
' + __('Created: ') + '' + created_count + ''; + } + if (updated_count > 0) { + msg += '
' + __('Updated: ') + '' + updated_count + ''; + } + + frappe.msgprint({ + title: __('Import Completed Successfully'), + indicator: 'green', + message: msg + }); + } else { + let msg = '
'; + if (created_count > 0) { + msg += __('Successfully created: ') + '' + created_count + '
'; + } + if (updated_count > 0) { + msg += __('Updated: ') + '' + updated_count + '
'; + } + msg += __('Failed: ') + '' + error_count + ''; + msg += '
'; + + if (errors && errors.length > 0) { + msg += '
'; + msg += '
'; + } + + frappe.msgprint({ + title: created_count > 0 ? __('Import Completed with Errors') : __('Import Failed'), + indicator: created_count > 0 ? 'orange' : 'red', + message: msg + }); + } +} + // Show reconnection dialog for ƏMAS when token expires (CSRF error) function show_amas_reconnect_dialog(asan_login_name, retry_callback) { const d = new frappe.ui.Dialog({ diff --git a/invoice_az/hooks.py b/invoice_az/hooks.py index 1a78f51..7e393e3 100644 --- a/invoice_az/hooks.py +++ b/invoice_az/hooks.py @@ -71,21 +71,15 @@ scheduler_events = { def after_install(): """Run installation tasks""" from invoice_az.auth import setup_token_renewal - from invoice_az.install import after_install as install_custom_fields setup_token_renewal() - install_custom_fields() def after_migrate(): """Run migration tasks""" from invoice_az.auth import setup_token_renewal - from invoice_az.install import create_journal_entry_custom_fields, create_supplier_custom_fields, create_employee_amas_fields setup_token_renewal() - create_journal_entry_custom_fields() - create_supplier_custom_fields() - create_employee_amas_fields() # Fixtures for master data # ------------------------ diff --git a/invoice_az/install.py b/invoice_az/install.py deleted file mode 100644 index e1dffeb..0000000 --- a/invoice_az/install.py +++ /dev/null @@ -1,177 +0,0 @@ -"""Installation hooks for Invoice Az app""" - -import frappe -from frappe.custom.doctype.custom_field.custom_field import create_custom_fields - - -def after_install(): - """Run after app installation""" - create_journal_entry_custom_fields() - create_supplier_custom_fields() - create_employee_amas_fields() - - -def create_journal_entry_custom_fields(): - """Custom fields for Journal Entry are now defined in jey_erp/custom_fields.py""" - # Just clear cache - fields are created by jey_erp - frappe.clear_cache(doctype='Journal Entry') - frappe.logger().info("Journal Entry cache cleared") - - -def create_supplier_custom_fields(): - """Create custom fields for Supplier doctype""" - - custom_fields = { - 'Supplier': [ - { - 'fieldname': 'patronimyc', - 'label': 'Patronymic (Father\'s Name)', - 'fieldtype': 'Data', - 'insert_after': 'first_name_individual', - 'depends_on': 'eval:doc.supplier_type=="Individual"' - } - ] - } - - frappe.logger().info("Creating/updating custom fields for Supplier") - create_custom_fields(custom_fields, update=True) - - # Clear cache for Supplier - frappe.clear_cache(doctype='Supplier') - frappe.logger().info("Custom fields created/updated successfully for Supplier") - - -def create_employee_amas_fields(): - """Create custom fields for Employee doctype to display AMAS data - - This creates only the essential link field and HTML containers. - The AMAS data is displayed dynamically via JavaScript from the linked Amas Employees record. - This approach avoids MySQL's 65KB row size limit. - """ - - custom_fields = { - 'Employee': [ - # AMAS Employee Link (essential field) - { - 'fieldname': 'custom_amas_employee', - 'fieldtype': 'Link', - 'label': 'AMAS Employee Record', - 'options': 'Amas Employees', - 'read_only': 1, - 'insert_after': 'profile_tab' - }, - - # Main AMAS Data Tab - { - 'fieldname': 'amas_data_tab', - 'fieldtype': 'Tab Break', - 'label': 'AMAS Data', - 'depends_on': 'eval:doc.custom_amas_employee' - }, - - # ===== SUB TAB 1: Contract ===== - { - 'fieldname': 'amas_contract_tab', - 'fieldtype': 'Tab Break', - 'label': 'Contract', - 'js_parent_subtab': 'AMAS Data' - }, - { - 'fieldname': 'amas_contract_html', - 'fieldtype': 'HTML', - 'label': 'Contract Information', - 'options': '
Loading...
' - }, - - # ===== SUB TAB 2: Position & Activity ===== - { - 'fieldname': 'amas_position_tab', - 'fieldtype': 'Tab Break', - 'label': 'Position & Activity', - 'js_parent_subtab': 'AMAS Data' - }, - { - 'fieldname': 'amas_position_html', - 'fieldtype': 'HTML', - 'label': 'Position Information', - 'options': '
Loading...
' - }, - - # ===== SUB TAB 3: Salary & Compensation ===== - { - 'fieldname': 'amas_salary_tab', - 'fieldtype': 'Tab Break', - 'label': 'Salary & Compensation', - 'js_parent_subtab': 'AMAS Data' - }, - { - 'fieldname': 'amas_salary_html', - 'fieldtype': 'HTML', - 'label': 'Salary Information', - 'options': '
Loading...
' - }, - - # ===== SUB TAB 4: Work Schedule & Vacation ===== - { - 'fieldname': 'amas_schedule_tab', - 'fieldtype': 'Tab Break', - 'label': 'Work Schedule & Vacation', - 'js_parent_subtab': 'AMAS Data' - }, - { - 'fieldname': 'amas_schedule_html', - 'fieldtype': 'HTML', - 'label': 'Schedule Information', - 'options': '
Loading...
' - }, - - # ===== SUB TAB 5: Personal & Education ===== - { - 'fieldname': 'amas_personal_tab', - 'fieldtype': 'Tab Break', - 'label': 'Personal & Education', - 'js_parent_subtab': 'AMAS Data' - }, - { - 'fieldname': 'amas_personal_html', - 'fieldtype': 'HTML', - 'label': 'Personal Information', - 'options': '
Loading...
' - }, - - # ===== SUB TAB 6: Documents & Metadata ===== - { - 'fieldname': 'amas_documents_tab', - 'fieldtype': 'Tab Break', - 'label': 'Documents & Metadata', - 'js_parent_subtab': 'AMAS Data' - }, - { - 'fieldname': 'amas_documents_html', - 'fieldtype': 'HTML', - 'label': 'Document Information', - 'options': '
Loading...
' - }, - - # ===== SUB TAB 7: AMAS Integration ===== - { - 'fieldname': 'amas_integration_tab', - 'fieldtype': 'Tab Break', - 'label': 'AMAS Integration', - 'js_parent_subtab': 'AMAS Data' - }, - { - 'fieldname': 'amas_integration_html', - 'fieldtype': 'HTML', - 'label': 'Integration Information', - 'options': '
Loading...
' - } - ] - } - - frappe.logger().info("Creating/updating custom AMAS fields for Employee") - create_custom_fields(custom_fields, update=True) - - # Clear cache for Employee - frappe.clear_cache(doctype='Employee') - frappe.logger().info("Custom AMAS fields created/updated successfully for Employee") diff --git a/invoice_az/invoice_az/doctype/amas_employees/amas_employees.js b/invoice_az/invoice_az/doctype/amas_employees/amas_employees.js index 4d04d83..4c2eebe 100644 --- a/invoice_az/invoice_az/doctype/amas_employees/amas_employees.js +++ b/invoice_az/invoice_az/doctype/amas_employees/amas_employees.js @@ -4,17 +4,6 @@ frappe.ui.form.on('Amas Employees', { refresh: function(frm) { // Form view - show employee details - if (!frm.is_new()) { - // Add button to view raw data if needed - if (frm.doc.raw_data) { - frm.add_custom_button(__('View Raw Data'), function() { - frappe.msgprint({ - title: __('Raw Data from ƏMAS'), - message: `
${frm.doc.raw_data}
`, - wide: true - }); - }); - } - } + // Raw data is hidden and can be viewed if needed in customization } });