bug fixes

This commit is contained in:
Ali 2026-02-13 17:14:14 +04:00
parent 0fd5399b7f
commit 7969b96d87
5 changed files with 491 additions and 272 deletions

View File

@ -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() @frappe.whitelist()
def create_employees_from_amas(asan_login_name, employees, company, create_designation=0): def create_employees_from_amas(asan_login_name, employees, company, create_designation=0):
""" """

View File

@ -520,14 +520,6 @@ function show_employee_selection(listview, asan_login_name, organization_name, e
fieldtype: 'Section Break', fieldtype: 'Section Break',
label: __('Settings') label: __('Settings')
}, },
{
fieldname: 'company',
fieldtype: 'Link',
label: __('Company'),
options: 'Company',
reqd: 1,
default: default_company
},
{ {
fieldname: 'create_designation', fieldname: 'create_designation',
fieldtype: 'Check', fieldtype: 'Check',
@ -568,7 +560,7 @@ function show_employee_selection(listview, asan_login_name, organization_name, e
} }
d.hide(); 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_label: __('Cancel'),
secondary_action: function() { d.hide(); } secondary_action: function() { d.hide(); }
@ -594,56 +586,190 @@ 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) { 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( frappe.show_progress(
__('Loading from ƏMAS'), __('Loading from ƏMAS'),
0, current_index - 1,
selected_employees.length, total_to_process,
__('Fetching employee details...') __('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({ frappe.call({
method: 'invoice_az.amas_api.create_employees_from_amas', method: 'invoice_az.amas_api.create_single_employee_from_amas',
args: { args: {
asan_login_name: asan_login_name, asan_login_name: asan_login_name,
employees: selected_employees, emp_data: emp_data,
company: company, company: company,
create_designation: create_designation ? 1 : 0 create_designation: create_designation ? 1 : 0
}, },
freeze: true,
freeze_message: __('Creating employees from ƏMAS...'),
callback: function(r) { callback: function(r) {
frappe.hide_progress(); if (r.message && r.message.success) {
if (!r.message || !r.message.success) { // Success - increment counters
// Check for CSRF error - need to reconnect if (r.message.action === 'created') {
if (r.message && r.message.csrf_error) { created_count++;
show_amas_reconnect_dialog(asan_login_name, function() { frappe.show_alert({
// Retry after successful reconnection message: __('Created: ') + r.message.full_name,
create_employees(listview, asan_login_name, selected_employees, company, create_designation); indicator: 'green'
}); }, 2);
return; } else if (r.message.action === 'updated') {
updated_count++;
frappe.show_alert({
message: __('Updated: ') + r.message.full_name,
indicator: 'blue'
}, 2);
}
} else {
// Error
error_count++;
const error_msg = r.message ? r.message.message : 'Unknown error';
errors.push(error_msg);
frappe.show_alert({
message: __('Error: ') + (r.message ? r.message.full_name : emp_name),
indicator: 'red'
}, 3);
} }
frappe.msgprint({ // Continue with next employee after short delay (like E-Taxes)
title: __('Error'), setTimeout(function() {
indicator: 'red', process_employees_one_by_one(
message: r.message ? r.message.message : __('Failed to create employees') 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);
}
}); });
return;
} }
const res = r.message; // Show final summary (like E-Taxes)
const total = res.created_count + res.updated_count + res.error_count; function show_import_summary(total, created_count, updated_count, error_count, errors) {
if (error_count === 0) {
if (res.error_count === 0) {
let msg = __('All ') + total + __(' employees were processed successfully.'); let msg = __('All ') + total + __(' employees were processed successfully.');
if (res.created_count > 0) { if (created_count > 0) {
msg += '<br>' + __('Created: ') + '<strong>' + res.created_count + '</strong>'; msg += '<br>' + __('Created: ') + '<strong>' + created_count + '</strong>';
} }
if (res.updated_count > 0) { if (updated_count > 0) {
msg += '<br>' + __('Updated: ') + '<strong>' + res.updated_count + '</strong>'; msg += '<br>' + __('Updated: ') + '<strong>' + updated_count + '</strong>';
} }
frappe.msgprint({ frappe.msgprint({
@ -653,34 +779,33 @@ function create_employees(listview, asan_login_name, selected_employees, company
}); });
} else { } else {
let msg = '<div style="margin-bottom: 15px;">'; let msg = '<div style="margin-bottom: 15px;">';
if (res.created_count > 0) { if (created_count > 0) {
msg += __('Successfully created: ') + '<strong>' + res.created_count + '</strong><br>'; msg += __('Successfully created: ') + '<strong>' + created_count + '</strong><br>';
} }
if (res.updated_count > 0) { if (updated_count > 0) {
msg += __('Updated: ') + '<strong>' + res.updated_count + '</strong><br>'; msg += __('Updated: ') + '<strong>' + updated_count + '</strong><br>';
} }
msg += __('Failed: ') + '<strong>' + res.error_count + '</strong>'; msg += __('Failed: ') + '<strong>' + error_count + '</strong>';
msg += '</div>'; msg += '</div>';
if (res.errors && res.errors.length > 0) { if (errors && errors.length > 0) {
msg += '<div style="max-height: 200px; overflow-y: auto;">'; msg += '<div style="max-height: 200px; overflow-y: auto;">';
msg += '<ul style="color: red; font-size: 12px; margin: 0; padding-left: 20px;">'; msg += '<ul style="color: red; font-size: 12px; margin: 0; padding-left: 20px;">';
res.errors.forEach(function(err) { errors.slice(0, 10).forEach(function(err) {
msg += '<li>' + frappe.utils.escape_html(err) + '</li>'; msg += '<li>' + frappe.utils.escape_html(err) + '</li>';
}); });
if (errors.length > 10) {
msg += '<li><em>... and ' + (errors.length - 10) + ' more errors</em></li>';
}
msg += '</ul></div>'; msg += '</ul></div>';
} }
frappe.msgprint({ frappe.msgprint({
title: res.created_count > 0 ? __('Import Completed with Errors') : __('Import Failed'), title: created_count > 0 ? __('Import Completed with Errors') : __('Import Failed'),
indicator: res.created_count > 0 ? 'orange' : 'red', indicator: created_count > 0 ? 'orange' : 'red',
message: msg message: msg
}); });
} }
listview.refresh();
}
});
} }
// Show reconnection dialog for ƏMAS when token expires (CSRF error) // Show reconnection dialog for ƏMAS when token expires (CSRF error)

View File

@ -71,21 +71,15 @@ scheduler_events = {
def after_install(): def after_install():
"""Run installation tasks""" """Run installation tasks"""
from invoice_az.auth import setup_token_renewal from invoice_az.auth import setup_token_renewal
from invoice_az.install import after_install as install_custom_fields
setup_token_renewal() setup_token_renewal()
install_custom_fields()
def after_migrate(): def after_migrate():
"""Run migration tasks""" """Run migration tasks"""
from invoice_az.auth import setup_token_renewal 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() setup_token_renewal()
create_journal_entry_custom_fields()
create_supplier_custom_fields()
create_employee_amas_fields()
# Fixtures for master data # Fixtures for master data
# ------------------------ # ------------------------

View File

@ -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': '<div id="amas_contract_data">Loading...</div>'
},
# ===== 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': '<div id="amas_position_data">Loading...</div>'
},
# ===== 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': '<div id="amas_salary_data">Loading...</div>'
},
# ===== 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': '<div id="amas_schedule_data">Loading...</div>'
},
# ===== 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': '<div id="amas_personal_data">Loading...</div>'
},
# ===== 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': '<div id="amas_documents_data">Loading...</div>'
},
# ===== 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': '<div id="amas_integration_data">Loading...</div>'
}
]
}
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")

View File

@ -4,17 +4,6 @@
frappe.ui.form.on('Amas Employees', { frappe.ui.form.on('Amas Employees', {
refresh: function(frm) { refresh: function(frm) {
// Form view - show employee details // Form view - show employee details
if (!frm.is_new()) { // Raw data is hidden and can be viewed if needed in customization
// 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: `<pre style="max-height: 400px; overflow: auto;">${frm.doc.raw_data}</pre>`,
wide: true
});
});
}
}
} }
}); });