1747 lines
78 KiB
JavaScript
1747 lines
78 KiB
JavaScript
/**
|
||
* Company DocType Enhancement for E-Taxes Integration
|
||
* Adds functionality to fetch company profile data from E-Taxes
|
||
*/
|
||
|
||
frappe.ui.form.on('Company', {
|
||
refresh: function(frm) {
|
||
// Add E-Taxes profile button
|
||
frm.add_custom_button(__('Get E-Taxes Profile'), function() {
|
||
ETaxesCompany.checkAuthAndFetchProfile(frm);
|
||
}, __('E-Taxes'));
|
||
|
||
// Add Set Main Activity button
|
||
frm.add_custom_button(__('Set Main Activity'), function() {
|
||
ETaxesCompany.showMainActivitySelector(frm);
|
||
}, __('E-Taxes'));
|
||
|
||
// Make declaration default fields always editable
|
||
ETaxesCompany.enableDeclarationDefaultFields(frm);
|
||
|
||
// Check gambling activity on refresh
|
||
ETaxesCompany.checkGamblingActivity(frm);
|
||
},
|
||
|
||
main_activity: function(frm) {
|
||
if (frm.doc.main_activity) {
|
||
ETaxesCompany.validateMainActivity(frm);
|
||
ETaxesCompany.checkGamblingActivity(frm);
|
||
}
|
||
},
|
||
|
||
'mdssüzrə': function(frm) {
|
||
ETaxesCompany.saveDeclarationDefaults(frm);
|
||
},
|
||
|
||
'icbaritibbisığortaüzrə': function(frm) {
|
||
ETaxesCompany.saveDeclarationDefaults(frm);
|
||
},
|
||
|
||
'işsizlikdənsığortaüzrə': function(frm) {
|
||
ETaxesCompany.saveDeclarationDefaults(frm);
|
||
},
|
||
|
||
seller: function(frm) {
|
||
ETaxesCompany.handleGamblingFieldChange(frm, 'seller');
|
||
},
|
||
|
||
organizer: function(frm) {
|
||
ETaxesCompany.handleGamblingFieldChange(frm, 'organizer');
|
||
}
|
||
});
|
||
|
||
// ======= ETAXES COMPANY MODULE =======
|
||
window.ETaxesCompany = {
|
||
// Хранение ссылки на текущий загрузочный диалог
|
||
currentLoadingDialog: null,
|
||
|
||
// Кэш для справочников
|
||
_dictionaryCache: {
|
||
taxAuthorities: null,
|
||
propertyTypes: null
|
||
},
|
||
|
||
// Gambling activity codes
|
||
gamblingActivityCodes: ['92000', '9200003', '9200004', '9200001', '9200002', '9200005'],
|
||
|
||
/**
|
||
* Check and manage gambling activity fields
|
||
*/
|
||
checkGamblingActivity: function(frm) {
|
||
const mainActivity = frm.doc.main_activity;
|
||
const isGamblingActivity = ETaxesCompany.gamblingActivityCodes.includes(mainActivity);
|
||
|
||
if (isGamblingActivity) {
|
||
let needsUpdate = false;
|
||
if (!frm.doc.seller && !frm.doc.organizer) {
|
||
frm.doc.seller = 1;
|
||
frm.doc.organizer = 1;
|
||
needsUpdate = true;
|
||
}
|
||
|
||
frm.set_df_property('seller', 'read_only', 0);
|
||
frm.set_df_property('organizer', 'read_only', 0);
|
||
frm.set_df_property('seller', 'hidden', 0);
|
||
frm.set_df_property('organizer', 'hidden', 0);
|
||
frm.refresh_field('seller');
|
||
frm.refresh_field('organizer');
|
||
|
||
if (needsUpdate) {
|
||
frappe.show_alert(__('Gambling activity detected. Seller and Organizer flags enabled.'), 'blue');
|
||
}
|
||
} else {
|
||
frm.set_df_property('seller', 'read_only', 1);
|
||
frm.set_df_property('organizer', 'read_only', 1);
|
||
|
||
let needsUpdate = false;
|
||
if (frm.doc.seller || frm.doc.organizer) {
|
||
frm.doc.seller = 0;
|
||
frm.doc.organizer = 0;
|
||
needsUpdate = true;
|
||
}
|
||
|
||
frm.refresh_field('seller');
|
||
frm.refresh_field('organizer');
|
||
|
||
if (needsUpdate) {
|
||
frappe.show_alert(__('Non-gambling activity. Seller and Organizer flags disabled.'), 'blue');
|
||
}
|
||
}
|
||
},
|
||
|
||
/**
|
||
* Handle gambling field changes
|
||
*/
|
||
handleGamblingFieldChange: function(frm, fieldName) {
|
||
const mainActivity = frm.doc.main_activity;
|
||
const isGamblingActivity = ETaxesCompany.gamblingActivityCodes.includes(mainActivity);
|
||
|
||
if (!isGamblingActivity) {
|
||
frm.doc[fieldName] = 0;
|
||
frm.refresh_field(fieldName);
|
||
frappe.msgprint(__('Seller and Organizer flags can only be set for gambling activities.'));
|
||
return;
|
||
}
|
||
|
||
if (!frm.doc.seller && !frm.doc.organizer) {
|
||
frm.doc[fieldName] = 1;
|
||
frm.refresh_field(fieldName);
|
||
frappe.msgprint(__('At least one of Seller or Organizer must be checked for gambling activities.'));
|
||
return;
|
||
}
|
||
|
||
ETaxesCompany.performForcedSave(frm, {
|
||
[fieldName]: frm.doc[fieldName] ? 1 : 0
|
||
});
|
||
},
|
||
|
||
/**
|
||
* Perform forced save for gambling fields
|
||
*/
|
||
performForcedSave: function(frm, fieldUpdates, callback) {
|
||
frappe.call({
|
||
method: 'taxes_az.company_etaxes.force_update_gambling_fields',
|
||
args: {
|
||
company_name: frm.doc.name,
|
||
field_updates: fieldUpdates
|
||
},
|
||
callback: function(r) {
|
||
if (r.message && r.message.success) {
|
||
frm.doc.__unsaved = 0;
|
||
frm.doc.__islocal = 0;
|
||
if (callback) callback(true);
|
||
} else {
|
||
if (callback) callback(false);
|
||
}
|
||
},
|
||
error: function(r) {
|
||
if (callback) callback(false);
|
||
}
|
||
});
|
||
},
|
||
|
||
/**
|
||
* Validate main activity exists in system
|
||
*/
|
||
validateMainActivity: function(frm) {
|
||
const activityCode = frm.doc.main_activity;
|
||
if (!activityCode) return;
|
||
|
||
frappe.call({
|
||
method: 'frappe.client.get_value',
|
||
args: {
|
||
doctype: 'Main type of activity',
|
||
fieldname: ['name'],
|
||
filters: {name: activityCode}
|
||
},
|
||
callback: function(r) {
|
||
if (!r.message) {
|
||
frappe.show_alert(__('Activity code not found in system'), 'orange');
|
||
}
|
||
}
|
||
});
|
||
},
|
||
|
||
/**
|
||
* Show main activity selector dialog
|
||
*/
|
||
showMainActivitySelector: function(frm) {
|
||
const dialog = new frappe.ui.Dialog({
|
||
title: __('Select Main Activity'),
|
||
fields: [{
|
||
fieldname: 'main_activity',
|
||
fieldtype: 'Link',
|
||
label: __('Main Activity Code'),
|
||
options: 'Main type of activity',
|
||
reqd: 1
|
||
}],
|
||
primary_action_label: __('Update'),
|
||
primary_action: function(values) {
|
||
if (values.main_activity) {
|
||
ETaxesCompany.forceUpdateMainActivity(frm, values.main_activity);
|
||
dialog.hide();
|
||
}
|
||
}
|
||
});
|
||
|
||
if (frm.doc.main_activity) {
|
||
dialog.set_value('main_activity', frm.doc.main_activity);
|
||
}
|
||
dialog.show();
|
||
},
|
||
|
||
/**
|
||
* Force update main activity
|
||
*/
|
||
forceUpdateMainActivity: function(frm, activityCode) {
|
||
frappe.call({
|
||
method: 'taxes_az.company_etaxes.force_update_single_field',
|
||
args: {
|
||
company_name: frm.doc.name,
|
||
field_name: 'main_activity',
|
||
field_value: activityCode
|
||
},
|
||
callback: function(r) {
|
||
if (r.message && r.message.success) {
|
||
frm.set_value('main_activity', activityCode);
|
||
frm.reload_doc();
|
||
} else {
|
||
frappe.msgprint(__('Failed to update main activity'));
|
||
}
|
||
}
|
||
});
|
||
},
|
||
|
||
/**
|
||
* Make declaration default fields editable regardless of docstatus
|
||
*/
|
||
enableDeclarationDefaultFields: function(frm) {
|
||
['mdssüzrə', 'icbaritibbisığortaüzrə', 'işsizlikdənsığortaüzrə'].forEach(function(fieldname) {
|
||
frm.set_df_property(fieldname, 'read_only', 0);
|
||
});
|
||
frm.refresh_fields(['mdssüzrə', 'icbaritibbisığortaüzrə', 'işsizlikdənsığortaüzrə']);
|
||
},
|
||
|
||
/**
|
||
* Auto-save declaration default fields via direct DB update (bypasses submit state)
|
||
*/
|
||
saveDeclarationDefaults: function(frm) {
|
||
frappe.call({
|
||
method: 'taxes_az.company_etaxes.force_update_declaration_defaults',
|
||
args: {
|
||
company_name: frm.doc.name,
|
||
mdss: frm.doc['mdssüzrə'] || '',
|
||
icbari: frm.doc['icbaritibbisığortaüzrə'] || '',
|
||
issizlik: frm.doc['işsizlikdənsığortaüzrə'] || ''
|
||
},
|
||
callback: function(r) {
|
||
if (r.message && r.message.success) {
|
||
frm.doc.__unsaved = 0;
|
||
if (frm.doc.docstatus === 1) {
|
||
frm.page.set_indicator(__('Submitted'), 'blue');
|
||
} else {
|
||
frm.page.clear_indicator();
|
||
}
|
||
frappe.show_alert({ message: __('Saved'), indicator: 'green' }, 2);
|
||
} else {
|
||
frappe.show_alert({ message: __('Save failed'), indicator: 'red' }, 3);
|
||
}
|
||
}
|
||
});
|
||
},
|
||
|
||
/**
|
||
* Check authentication and fetch profile with inline re-authentication
|
||
*/
|
||
checkAuthAndFetchProfile: function(frm) {
|
||
// Check if ETaxes common module is available
|
||
if (typeof ETaxes !== 'undefined' && ETaxes.auth) {
|
||
// Use ETaxes common authentication system
|
||
ETaxes.auth.checkAndProcess(function() {
|
||
ETaxesCompany.fetchProfile(frm);
|
||
});
|
||
} else {
|
||
// Fallback to simple token validity check
|
||
frappe.call({
|
||
method: 'taxes_az.auth.check_token_validity',
|
||
callback: function(r) {
|
||
if (r.message && r.message.valid) {
|
||
ETaxesCompany.fetchProfile(frm);
|
||
} else {
|
||
ETaxesCompany.handleAuthenticationRequired(frm);
|
||
}
|
||
},
|
||
error: function() {
|
||
frappe.msgprint(__('Error checking authentication status'));
|
||
}
|
||
});
|
||
}
|
||
},
|
||
|
||
/**
|
||
* Handle authentication required with inline process
|
||
*/
|
||
handleAuthenticationRequired: function(frm) {
|
||
frappe.confirm(
|
||
__('E-Taxes authentication is required. Would you like to authenticate now?'),
|
||
function() {
|
||
ETaxesCompany.startInlineAuthentication(frm);
|
||
},
|
||
function() {
|
||
frappe.show_alert({
|
||
message: __('Authentication cancelled'),
|
||
indicator: 'red'
|
||
}, 3);
|
||
}
|
||
);
|
||
},
|
||
|
||
/**
|
||
* Start inline authentication process
|
||
*/
|
||
startInlineAuthentication: function(frm) {
|
||
// Show loading dialog
|
||
ETaxesCompany.currentLoadingDialog = new frappe.ui.Dialog({
|
||
title: __('E-Taxes Authentication'),
|
||
indicator: 'blue',
|
||
fields: [
|
||
{
|
||
fieldname: 'loading_html',
|
||
fieldtype: 'HTML',
|
||
options: ETaxesCompany._getAuthLoadingHTML(__('Starting Authentication'), __('Getting Asan Login settings...'))
|
||
}
|
||
],
|
||
primary_action_label: __('Cancel'),
|
||
primary_action: function() {
|
||
ETaxesCompany._hideLoadingDialog();
|
||
}
|
||
});
|
||
|
||
ETaxesCompany.currentLoadingDialog.show();
|
||
|
||
// Get default login settings
|
||
frappe.call({
|
||
method: 'taxes_az.auth.get_default_asan_login',
|
||
callback: function(r) {
|
||
if (r.message && r.message.found) {
|
||
const asanLoginName = r.message.name;
|
||
|
||
// Update loading message
|
||
ETaxesCompany._updateLoadingDialog(ETaxesCompany.currentLoadingDialog,
|
||
__('Sending authentication request...'),
|
||
__('This will send a request to your Asan Imza mobile app'));
|
||
|
||
// Start authentication
|
||
frappe.call({
|
||
method: 'taxes_az.auth.handle_authentication',
|
||
args: { 'asan_login_name': asanLoginName },
|
||
callback: function(authR) {
|
||
if (authR.message && authR.message.success) {
|
||
const bearerToken = authR.message.bearer_token;
|
||
|
||
// Show verification code if available
|
||
if (authR.message.verification_code) {
|
||
ETaxesCompany._showVerificationCode(ETaxesCompany.currentLoadingDialog, authR.message.verification_code);
|
||
}
|
||
|
||
ETaxesCompany._updateLoadingDialog(ETaxesCompany.currentLoadingDialog,
|
||
__('Waiting for confirmation on your phone'),
|
||
__('Please check your phone and confirm the authentication request'));
|
||
|
||
// Start polling
|
||
ETaxesCompany.pollAuthStatus(ETaxesCompany.currentLoadingDialog, asanLoginName, bearerToken, function(success) {
|
||
if (success) {
|
||
ETaxesCompany.completeAuthentication(ETaxesCompany.currentLoadingDialog, asanLoginName, function() {
|
||
ETaxesCompany._hideLoadingDialog();
|
||
ETaxesCompany.fetchProfile(frm);
|
||
});
|
||
} else {
|
||
ETaxesCompany._setDialogError(ETaxesCompany.currentLoadingDialog,
|
||
__('Authentication Failed'),
|
||
__('Could not authenticate with Asan Imza'));
|
||
}
|
||
});
|
||
} else {
|
||
ETaxesCompany._setDialogError(ETaxesCompany.currentLoadingDialog,
|
||
__('Authentication Error'),
|
||
authR.message ? authR.message.message : __('Authentication request failed'));
|
||
}
|
||
},
|
||
error: function() {
|
||
ETaxesCompany._setDialogError(ETaxesCompany.currentLoadingDialog,
|
||
__('Network Error'),
|
||
__('Failed to start authentication process'));
|
||
}
|
||
});
|
||
} else {
|
||
ETaxesCompany._setDialogError(ETaxesCompany.currentLoadingDialog,
|
||
__('No Asan Login Settings'),
|
||
__('Please configure Asan Login settings first'));
|
||
}
|
||
},
|
||
error: function() {
|
||
ETaxesCompany._setDialogError(ETaxesCompany.currentLoadingDialog,
|
||
__('Error'),
|
||
__('Failed to get authentication settings'));
|
||
}
|
||
});
|
||
},
|
||
|
||
/**
|
||
* Poll authentication status
|
||
*/
|
||
pollAuthStatus: function(dialog, asanLoginName, bearerToken, callback) {
|
||
let attempts = 0;
|
||
const maxAttempts = 20;
|
||
const pollInterval = 6000; // 6 seconds
|
||
|
||
function pollStep() {
|
||
if (attempts >= maxAttempts) {
|
||
ETaxesCompany._setDialogError(dialog,
|
||
__('Authentication Timeout'),
|
||
__('The authentication request has timed out. Please try again.'));
|
||
callback(false);
|
||
return;
|
||
}
|
||
|
||
attempts++;
|
||
|
||
ETaxesCompany._updateLoadingDialog(dialog,
|
||
__('Waiting for confirmation on your phone'),
|
||
__('Please check your phone and confirm the authentication request') +
|
||
' (' + attempts + '/' + maxAttempts + ')');
|
||
|
||
frappe.call({
|
||
method: 'taxes_az.auth.poll_auth_status',
|
||
args: {
|
||
'asan_login_name': asanLoginName,
|
||
'bearer_token': bearerToken
|
||
},
|
||
callback: function(r) {
|
||
if (r.message && r.message.success) {
|
||
if (r.message.authenticated) {
|
||
ETaxesCompany._setDialogSuccess(dialog,
|
||
__('Authentication Successful'),
|
||
__('You are now authenticated with Asan Imza'));
|
||
|
||
setTimeout(() => callback(true), 1000);
|
||
} else {
|
||
setTimeout(pollStep, pollInterval);
|
||
}
|
||
} else {
|
||
ETaxesCompany._setDialogError(dialog,
|
||
__('Authentication Error'),
|
||
r.message ? r.message.message : __('An unknown error occurred'));
|
||
callback(false);
|
||
}
|
||
},
|
||
error: function() {
|
||
setTimeout(pollStep, pollInterval);
|
||
}
|
||
});
|
||
}
|
||
|
||
pollStep();
|
||
},
|
||
|
||
/**
|
||
* Complete authentication process
|
||
*/
|
||
completeAuthentication: function(dialog, asanLoginName, callback) {
|
||
ETaxesCompany._updateLoadingDialog(dialog,
|
||
__('Completing Authentication'),
|
||
__('Getting certificates and selecting taxpayer...'));
|
||
|
||
frappe.call({
|
||
method: 'taxes_az.auth.get_auth_certificates',
|
||
args: { 'asan_login_name': asanLoginName },
|
||
callback: function(certR) {
|
||
if (certR.message && certR.message.success) {
|
||
// Try to use existing certificate or select first available
|
||
frappe.call({
|
||
method: 'frappe.client.get',
|
||
args: {
|
||
doctype: 'Asan Login',
|
||
name: asanLoginName
|
||
},
|
||
callback: function(r) {
|
||
if (r.message && r.message.selected_certificate_json) {
|
||
// Use existing certificate
|
||
const certData = JSON.parse(r.message.selected_certificate_json);
|
||
const certName = r.message.selected_certificate;
|
||
|
||
ETaxesCompany.selectCertificateAndTaxpayer(dialog, asanLoginName, certData, certName, callback);
|
||
} else if (certR.message.certificates && certR.message.certificates.length > 0) {
|
||
// Use first available certificate
|
||
const cert = certR.message.certificates[0];
|
||
let certName = '';
|
||
|
||
if (cert.taxpayerType === 'individual' && cert.individualInfo) {
|
||
certName = `${cert.individualInfo.name} (${cert.individualInfo.fin})`;
|
||
} else if (cert.legalInfo) {
|
||
certName = `${cert.legalInfo.name} (${cert.legalInfo.voen || cert.legalInfo.tin})`;
|
||
} else {
|
||
certName = 'Certificate 1';
|
||
}
|
||
|
||
ETaxesCompany.selectCertificateAndTaxpayer(dialog, asanLoginName, cert, certName, callback);
|
||
} else {
|
||
ETaxesCompany._setDialogError(dialog,
|
||
__('No Certificates'),
|
||
__('No certificates found for this account'));
|
||
}
|
||
}
|
||
});
|
||
} else {
|
||
ETaxesCompany._setDialogError(dialog,
|
||
__('Error'),
|
||
certR.message ? certR.message.message : __('Failed to get certificates'));
|
||
}
|
||
}
|
||
});
|
||
},
|
||
|
||
/**
|
||
* Select certificate and taxpayer
|
||
*/
|
||
selectCertificateAndTaxpayer: function(dialog, asanLoginName, certData, certName, callback) {
|
||
ETaxesCompany._updateLoadingDialog(dialog,
|
||
__('Selecting certificate'),
|
||
certName);
|
||
|
||
frappe.call({
|
||
method: 'taxes_az.auth.select_certificate',
|
||
args: {
|
||
'asan_login_name': asanLoginName,
|
||
'certificate_data': certData,
|
||
'certificate_name': certName
|
||
},
|
||
callback: function(r) {
|
||
if (r.message && r.message.success) {
|
||
ETaxesCompany._updateLoadingDialog(dialog,
|
||
__('Selecting taxpayer'),
|
||
__('Using certificate: ') + certName);
|
||
|
||
frappe.call({
|
||
method: 'taxes_az.auth.select_taxpayer',
|
||
args: { 'asan_login_name': asanLoginName },
|
||
callback: function(r) {
|
||
if (r.message && r.message.success) {
|
||
ETaxesCompany._setDialogSuccess(dialog,
|
||
__('Authentication Complete'),
|
||
__('You can now access E-Taxes services'));
|
||
|
||
setTimeout(callback, 1000);
|
||
} else {
|
||
ETaxesCompany._setDialogError(dialog,
|
||
__('Error'),
|
||
r.message ? r.message.message : __('Failed to select taxpayer'));
|
||
}
|
||
}
|
||
});
|
||
} else {
|
||
ETaxesCompany._setDialogError(dialog,
|
||
__('Error'),
|
||
r.message ? r.message.message : __('Failed to select certificate'));
|
||
}
|
||
}
|
||
});
|
||
},
|
||
|
||
/**
|
||
* Fetch company profile from E-Taxes
|
||
*/
|
||
fetchProfile: function(frm) {
|
||
frappe.call({
|
||
method: 'taxes_az.company_etaxes.get_company_profile',
|
||
callback: function(r) {
|
||
ETaxesCompany._handleProfileResponse(r, frm);
|
||
},
|
||
error: function(xhr, status, error) {
|
||
frappe.msgprint({
|
||
title: __('Network Error'),
|
||
message: __('Failed to connect to server: {0}', [error || 'Unknown error']),
|
||
indicator: 'red'
|
||
});
|
||
}
|
||
});
|
||
},
|
||
|
||
/**
|
||
* Общая функция для скрытия загрузочного диалога
|
||
*/
|
||
_hideLoadingDialog: function() {
|
||
if (ETaxesCompany.currentLoadingDialog) {
|
||
try {
|
||
ETaxesCompany.currentLoadingDialog.hide();
|
||
} catch (e) {
|
||
console.error('Error hiding loading dialog:', e);
|
||
}
|
||
ETaxesCompany.currentLoadingDialog = null;
|
||
}
|
||
},
|
||
|
||
/**
|
||
* Handle profile response
|
||
*/
|
||
_handleProfileResponse: function(r, frm) {
|
||
if (r.message && r.message.success) {
|
||
ETaxesCompany.showProfileDialog(r.message.data, frm);
|
||
} else if (r.message && r.message.error === 'unauthorized') {
|
||
frappe.confirm(
|
||
__('Your E-Taxes session has expired. Would you like to authenticate again?'),
|
||
function() {
|
||
ETaxesCompany.startInlineAuthentication(frm);
|
||
},
|
||
function() {
|
||
frappe.show_alert({
|
||
message: __('Authentication cancelled'),
|
||
indicator: 'red'
|
||
}, 3);
|
||
}
|
||
);
|
||
} else if (r.message && r.message.error === 'server_error') {
|
||
frappe.msgprint({
|
||
title: __('Server Error'),
|
||
message: __('E-Taxes service is temporarily unavailable. Please try again in a few minutes.'),
|
||
indicator: 'orange'
|
||
});
|
||
} else {
|
||
frappe.msgprint({
|
||
title: __('Error'),
|
||
message: r.message ? r.message.message : __('An error occurred while fetching profile data'),
|
||
indicator: 'red'
|
||
});
|
||
}
|
||
},
|
||
|
||
/**
|
||
* Show enhanced profile dialog with automatic parsing
|
||
*/
|
||
showProfileDialog: function(profileData, frm) {
|
||
const profile = profileData.profile || profileData;
|
||
const parsedInfo = ETaxesCompany._formatParsedProfileHTML(profile);
|
||
|
||
const dialog = new frappe.ui.Dialog({
|
||
title: __('E-Taxes Company Profile'),
|
||
size: 'large',
|
||
fields: [
|
||
{
|
||
fieldname: 'parsed_info',
|
||
fieldtype: 'HTML',
|
||
label: __('Company Information')
|
||
}
|
||
],
|
||
primary_action_label: __('Update Company Fields'),
|
||
primary_action: function() {
|
||
dialog.hide(); // Hide dialog before starting update
|
||
ETaxesCompany.updateCompanyFromProfile(profileData, frm);
|
||
}
|
||
});
|
||
|
||
// Set parsed information HTML
|
||
dialog.fields_dict.parsed_info.$wrapper.html(parsedInfo);
|
||
|
||
dialog.show();
|
||
},
|
||
|
||
/**
|
||
* Получить справочник налоговых органов
|
||
*/
|
||
_getTaxAuthorities: function() {
|
||
return new Promise((resolve, reject) => {
|
||
// Проверяем кэш
|
||
if (ETaxesCompany._dictionaryCache.taxAuthorities) {
|
||
resolve(ETaxesCompany._dictionaryCache.taxAuthorities);
|
||
return;
|
||
}
|
||
|
||
// Запрашиваем справочник через Python API
|
||
frappe.call({
|
||
method: 'taxes_az.company_etaxes.get_tax_authorities',
|
||
callback: function(r) {
|
||
if (r.message && r.message.success) {
|
||
// Извлекаем массив authorities из data
|
||
const authoritiesArray = r.message.data.authorities || r.message.data;
|
||
ETaxesCompany._dictionaryCache.taxAuthorities = authoritiesArray;
|
||
resolve(authoritiesArray);
|
||
} else {
|
||
reject(r.message ? r.message.message : 'Failed to load tax authorities');
|
||
}
|
||
},
|
||
error: function() {
|
||
reject('Failed to load tax authorities');
|
||
}
|
||
});
|
||
});
|
||
},
|
||
|
||
/**
|
||
* Получить справочник типов собственности
|
||
*/
|
||
_getPropertyTypes: function() {
|
||
return new Promise((resolve, reject) => {
|
||
// Проверяем кэш
|
||
if (ETaxesCompany._dictionaryCache.propertyTypes) {
|
||
let cachedData = ETaxesCompany._dictionaryCache.propertyTypes;
|
||
|
||
// Исправляем структуру кэша если данные вложены неправильно
|
||
if (Array.isArray(cachedData) && cachedData.length === 1 && Array.isArray(cachedData[0])) {
|
||
cachedData = cachedData[0];
|
||
ETaxesCompany._dictionaryCache.propertyTypes = cachedData;
|
||
}
|
||
|
||
resolve(cachedData);
|
||
return;
|
||
}
|
||
|
||
// Запрашиваем справочник через Python API
|
||
frappe.call({
|
||
method: 'taxes_az.company_etaxes.get_property_types',
|
||
callback: function(r) {
|
||
if (r.message && r.message.success) {
|
||
const propertyTypesData = r.message.data;
|
||
let propertyTypesArray = [];
|
||
|
||
if (Array.isArray(propertyTypesData)) {
|
||
propertyTypesArray = propertyTypesData;
|
||
} else if (typeof propertyTypesData === 'object' && propertyTypesData !== null) {
|
||
// Преобразуем объект в массив
|
||
propertyTypesArray = Object.values(propertyTypesData);
|
||
}
|
||
|
||
ETaxesCompany._dictionaryCache.propertyTypes = propertyTypesArray;
|
||
resolve(propertyTypesArray);
|
||
} else {
|
||
reject(r.message ? r.message.message : 'Failed to load property types');
|
||
}
|
||
},
|
||
error: function() {
|
||
reject('Failed to load property types');
|
||
}
|
||
});
|
||
});
|
||
},
|
||
|
||
/**
|
||
* Найти название налогового органа по коду
|
||
*/
|
||
_getTaxAuthorityName: function(code) {
|
||
return new Promise((resolve) => {
|
||
ETaxesCompany._getTaxAuthorities().then((authorities) => {
|
||
if (authorities && Array.isArray(authorities)) {
|
||
const authority = authorities.find(auth => auth.code === code);
|
||
if (authority && authority.name && authority.name.az) {
|
||
resolve(authority.name.az);
|
||
} else if (authority && authority.name && typeof authority.name === 'string') {
|
||
resolve(authority.name);
|
||
} else {
|
||
resolve(code);
|
||
}
|
||
} else {
|
||
resolve(code);
|
||
}
|
||
}).catch(() => {
|
||
resolve(code);
|
||
});
|
||
});
|
||
},
|
||
|
||
/**
|
||
* Найти название типа собственности по коду
|
||
*/
|
||
_getPropertyTypeName: function(code) {
|
||
return new Promise((resolve) => {
|
||
ETaxesCompany._getPropertyTypes().then((propertyTypes) => {
|
||
let dataToSearch = propertyTypes;
|
||
|
||
// Дополнительная проверка структуры данных
|
||
if (Array.isArray(propertyTypes) && propertyTypes.length === 1 && Array.isArray(propertyTypes[0])) {
|
||
dataToSearch = propertyTypes[0];
|
||
}
|
||
|
||
if (dataToSearch && Array.isArray(dataToSearch)) {
|
||
const propertyType = dataToSearch.find(prop => prop.code === code);
|
||
if (propertyType && propertyType.name && propertyType.name.az) {
|
||
resolve(propertyType.name.az);
|
||
} else if (propertyType && propertyType.name && typeof propertyType.name === 'string') {
|
||
resolve(propertyType.name);
|
||
} else {
|
||
resolve(code);
|
||
}
|
||
} else {
|
||
resolve(code);
|
||
}
|
||
}).catch(() => {
|
||
resolve(code);
|
||
});
|
||
});
|
||
},
|
||
|
||
/**
|
||
* Parse profile data and extract field mappings
|
||
*/
|
||
_parseProfileData: function(profile, frm) {
|
||
const updates = [];
|
||
|
||
// Helper function to add update if value is different
|
||
function addUpdate(fieldname, newValue, label, oldValue) {
|
||
// Специальная обработка для checkbox полей
|
||
if (typeof newValue === 'boolean' || fieldname.includes('is_') || fieldname.includes('has_') || fieldname.includes('special_tax_regime')) {
|
||
// Преобразуем оба значения к boolean для корректного сравнения
|
||
const newBool = Boolean(newValue);
|
||
const oldBool = Boolean(oldValue);
|
||
|
||
// Сравниваем как boolean
|
||
if (newBool !== oldBool) {
|
||
updates.push({
|
||
fieldname: fieldname,
|
||
newValue: newBool ? '1' : '0',
|
||
oldValue: oldBool ? '1' : '0',
|
||
label: label
|
||
});
|
||
}
|
||
} else {
|
||
// Для остальных полей - обычная логика
|
||
if (newValue !== null && newValue !== undefined && newValue !== oldValue) {
|
||
newValue = String(newValue).trim();
|
||
if (newValue !== '' && newValue !== String(oldValue || '').trim()) {
|
||
updates.push({
|
||
fieldname: fieldname,
|
||
newValue: newValue,
|
||
oldValue: oldValue || '',
|
||
label: label
|
||
});
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
// Helper function to format date from YYYYMMDD to YYYY-MM-DD
|
||
function formatDate(dateStr) {
|
||
if (!dateStr || dateStr.length !== 8) return null;
|
||
const year = dateStr.substring(0, 4);
|
||
const month = dateStr.substring(4, 6);
|
||
const day = dateStr.substring(6, 8);
|
||
return `${year}-${month}-${day}`;
|
||
}
|
||
|
||
// BASIC COMPANY INFORMATION
|
||
// Tax ID mapping (TIN)
|
||
if (profile.tin) {
|
||
addUpdate('tax_id', profile.tin, __('Tax ID'), frm.doc.tax_id);
|
||
}
|
||
|
||
// Registration Number mapping
|
||
if (profile.stateRegistrationDocumentNumber) {
|
||
addUpdate('registration_details', profile.stateRegistrationDocumentNumber, __('Registration Details'), frm.doc.registration_details);
|
||
}
|
||
|
||
// Phone mapping - prefer mobile over landline
|
||
const mobilePhone = profile.mobilePhoneNumber || ETaxesCompany._extractPhoneNumber(profile, 'mobile');
|
||
const landlinePhone = profile.landlinePhoneNumber || ETaxesCompany._extractPhoneNumber(profile, 'landline');
|
||
|
||
if (mobilePhone) {
|
||
addUpdate('phone_no', mobilePhone, __('Phone'), frm.doc.phone_no);
|
||
} else if (landlinePhone) {
|
||
addUpdate('phone_no', landlinePhone, __('Phone'), frm.doc.phone_no);
|
||
}
|
||
|
||
// Store both phones in dedicated fields
|
||
if (mobilePhone) {
|
||
addUpdate('mobile_phone', mobilePhone, __('Mobile Phone'), frm.doc.mobile_phone);
|
||
}
|
||
if (landlinePhone) {
|
||
addUpdate('landline_phone', landlinePhone, __('Landline Phone'), frm.doc.landline_phone);
|
||
}
|
||
|
||
// Email mapping
|
||
if (profile.email) {
|
||
addUpdate('email', profile.email, __('Email'), frm.doc.email);
|
||
}
|
||
|
||
// Registration Date mapping
|
||
if (profile.taxpayerRegistrationDate) {
|
||
const regDate = moment(profile.taxpayerRegistrationDate).format('YYYY-MM-DD');
|
||
addUpdate('date_of_establishment', regDate, __('Date of Establishment'), frm.doc.date_of_establishment);
|
||
}
|
||
|
||
// State Registration Document Issued Date
|
||
if (profile.stateRegistrationDocumentIssuedDate) {
|
||
const issuedDate = moment(profile.stateRegistrationDocumentIssuedDate).format('YYYY-MM-DD');
|
||
addUpdate('state_registration_document_issued_date', issuedDate, __('State Registration Document Issued Date'), frm.doc.state_registration_document_issued_date);
|
||
}
|
||
|
||
// Domain mapping (if available)
|
||
if (profile.mainActivity) {
|
||
addUpdate('domain', profile.mainActivity, __('Domain'), frm.doc.domain);
|
||
}
|
||
|
||
// MANAGEMENT INFORMATION
|
||
// Director Name from E-Taxes
|
||
if (profile.companyDirectorName) {
|
||
addUpdate('director_name_etaxes', profile.companyDirectorName, __('Director Name (E-Taxes)'), frm.doc.director_name_etaxes);
|
||
}
|
||
|
||
// Director PIN
|
||
if (profile.pin) {
|
||
addUpdate('director_pin', profile.pin, __('Director PIN'), frm.doc.director_pin);
|
||
}
|
||
|
||
// BUSINESS ACTIVITIES
|
||
// Main Activity mapping
|
||
if (profile.mainActivity) {
|
||
addUpdate('main_activity', profile.mainActivity, __('Main Activity'), frm.doc.main_activity);
|
||
}
|
||
|
||
// Legal Form Code
|
||
if (profile.legalFormCode) {
|
||
addUpdate('legal_form_code', profile.legalFormCode, __('Legal Form Code'), frm.doc.legal_form_code);
|
||
}
|
||
|
||
// TAX INFORMATION
|
||
// Taxation System mapping
|
||
if (profile.taxRate) {
|
||
let taxationSystem = '';
|
||
if (profile.taxRate === 'ƏDV' || profile.taxRate === 'VAT' || profile.taxRate === '18%') {
|
||
taxationSystem = '18% Value-added tax';
|
||
} else if (profile.taxRate === '0%' || profile.taxRate === 'ƏDV 0%') {
|
||
taxationSystem = '0% Value-added tax';
|
||
} else {
|
||
taxationSystem = profile.taxRate;
|
||
}
|
||
addUpdate('taxation_system', taxationSystem, __('Taxation System'), frm.doc.taxation_system);
|
||
}
|
||
|
||
// Business Classification mapping
|
||
if (profile.criteriaOfBusinessEntity) {
|
||
let businessClassification = '';
|
||
|
||
switch (profile.criteriaOfBusinessEntity.toLowerCase()) {
|
||
case 'micro':
|
||
businessClassification = 'Micro Entrepreneur';
|
||
break;
|
||
case 'small':
|
||
businessClassification = 'Small Entrepreneur';
|
||
break;
|
||
case 'middle':
|
||
case 'medium':
|
||
businessClassification = 'Medium Entrepreneur';
|
||
break;
|
||
case 'big':
|
||
case 'large':
|
||
businessClassification = 'Big Entrepreneur';
|
||
break;
|
||
default:
|
||
businessClassification = profile.criteriaOfBusinessEntity + ' Entrepreneur';
|
||
}
|
||
|
||
addUpdate('business_classification', businessClassification, __('Business Classification'), frm.doc.business_classification);
|
||
}
|
||
|
||
// State Registration Authority
|
||
if (profile.stateRegistrationName) {
|
||
addUpdate('state_registration_authority', profile.stateRegistrationName, __('State Registration Authority'), frm.doc.state_registration_authority);
|
||
}
|
||
|
||
// Taxpayer Activity Group
|
||
if (profile.activityGroup) {
|
||
addUpdate('taxpayer_activity_group', profile.activityGroup, __('Taxpayer Activity Group'), frm.doc.taxpayer_activity_group);
|
||
}
|
||
|
||
// Special Tax Regime
|
||
if (profile.specialTaxRegime !== undefined) {
|
||
addUpdate('special_tax_regime', profile.specialTaxRegime, __('Special Tax Regime'), frm.doc.special_tax_regime);
|
||
}
|
||
|
||
// TIN Type
|
||
if (profile.tinType) {
|
||
addUpdate('tin_type', profile.tinType, __('TIN Type'), frm.doc.tin_type);
|
||
}
|
||
|
||
// Is Risky
|
||
if (profile.isRisky !== undefined) {
|
||
addUpdate('is_risky_taxpayer', profile.isRisky, __('Is Risky Taxpayer'), frm.doc.is_risky_taxpayer);
|
||
}
|
||
|
||
// Sport Betting Operator
|
||
if (profile.sportBettingOperator !== undefined) {
|
||
addUpdate('is_sport_betting_operator', profile.sportBettingOperator, __('Sport Betting Operator'), frm.doc.is_sport_betting_operator);
|
||
}
|
||
|
||
// Has Active Production Object
|
||
if (profile.hasActiveProductionObject !== undefined) {
|
||
addUpdate('has_active_production_object', profile.hasActiveProductionObject, __('Has Active Production Object'), frm.doc.has_active_production_object);
|
||
}
|
||
|
||
// Tax System Type
|
||
if (profile.taxSystemType) {
|
||
addUpdate('tax_system_type', profile.taxSystemType, __('Tax System Type'), frm.doc.tax_system_type);
|
||
}
|
||
|
||
// Is Taxpayer in Cancellation Process
|
||
if (profile.isTaxPayerInCancellationProcess !== undefined) {
|
||
addUpdate('is_taxpayer_in_cancellation_process', profile.isTaxPayerInCancellationProcess, __('Is Taxpayer in Cancellation Process'), frm.doc.is_taxpayer_in_cancellation_process);
|
||
}
|
||
|
||
// Is Chief of Any Legal Entity
|
||
if (profile.isChiefOfAnyLegalEntity !== undefined) {
|
||
addUpdate('is_chief_of_any_legal_entity', profile.isChiefOfAnyLegalEntity, __('Is Chief of Any Legal Entity'), frm.doc.is_chief_of_any_legal_entity);
|
||
}
|
||
|
||
// VAT INFORMATION
|
||
if (profile.vatInfo && typeof profile.vatInfo === 'object') {
|
||
// VAT Registration Date
|
||
if (profile.vatInfo.prOperationTableOperationDate) {
|
||
const vatRegDate = formatDate(profile.vatInfo.prOperationTableOperationDate);
|
||
if (vatRegDate) {
|
||
addUpdate('vat_registration_date', vatRegDate, __('VAT Registration Date'), frm.doc.vat_registration_date);
|
||
}
|
||
}
|
||
|
||
// VAT Certificate Number
|
||
if (profile.vatInfo.recDocumentDocumentNumber) {
|
||
addUpdate('vat_certificate_number', profile.vatInfo.recDocumentDocumentNumber, __('VAT Certificate Number'), frm.doc.vat_certificate_number);
|
||
}
|
||
|
||
// VAT Certificate Date
|
||
if (profile.vatInfo.prVatOperationsRegDate) {
|
||
const vatCertDate = formatDate(profile.vatInfo.prVatOperationsRegDate);
|
||
if (vatCertDate) {
|
||
addUpdate('vat_certificate_date', vatCertDate, __('VAT Certificate Date'), frm.doc.vat_certificate_date);
|
||
}
|
||
}
|
||
}
|
||
|
||
// ORGANIZATIONAL STRUCTURE
|
||
// Parent Organization
|
||
if (profile.headOrganizationName && Array.isArray(profile.headOrganizationName) && profile.headOrganizationName.length > 0) {
|
||
const parentOrgText = profile.headOrganizationName.join(', ');
|
||
addUpdate('parent_organization', parentOrgText, __('Parent Organization'), frm.doc.parent_organization);
|
||
}
|
||
|
||
// Parent Organization TIN
|
||
if (profile.headOrganizationTin) {
|
||
addUpdate('parent_organization_tin', profile.headOrganizationTin, __('Parent Organization TIN'), frm.doc.parent_organization_tin);
|
||
}
|
||
|
||
// Employee Count
|
||
if (profile.employeeData && profile.employeeData.employeeCount !== undefined) {
|
||
addUpdate('employee_count', profile.employeeData.employeeCount, __('Employee Count'), frm.doc.employee_count);
|
||
}
|
||
|
||
// REGISTRATION DATES
|
||
// Suspension Dates
|
||
if (profile.suspensionStartDate) {
|
||
const suspStartDate = moment(profile.suspensionStartDate).format('YYYY-MM-DD');
|
||
addUpdate('suspension_start_date', suspStartDate, __('Suspension Start Date'), frm.doc.suspension_start_date);
|
||
}
|
||
|
||
if (profile.suspensionEndDate) {
|
||
const suspEndDate = moment(profile.suspensionEndDate).format('YYYY-MM-DD');
|
||
addUpdate('suspension_end_date', suspEndDate, __('Suspension End Date'), frm.doc.suspension_end_date);
|
||
}
|
||
|
||
// Liquidation Date
|
||
if (profile.liquidationDate) {
|
||
const liqDate = moment(profile.liquidationDate).format('YYYY-MM-DD');
|
||
addUpdate('liquidation_date', liqDate, __('Liquidation Date'), frm.doc.liquidation_date);
|
||
}
|
||
|
||
// ADDRESS INFORMATION
|
||
// Legal Address Full
|
||
if (profile.legalAddress) {
|
||
addUpdate('legal_address_full', profile.legalAddress, __('Legal Address (Full)'), frm.doc.legal_address_full);
|
||
}
|
||
|
||
// Actual Address Full
|
||
if (profile.actualAddress) {
|
||
addUpdate('actual_address_full', profile.actualAddress, __('Actual Address (Full)'), frm.doc.actual_address_full);
|
||
}
|
||
|
||
// Address for Mail
|
||
if (profile.addressForMail) {
|
||
addUpdate('address_for_mail', profile.addressForMail, __('Address for Mail'), frm.doc.address_for_mail);
|
||
}
|
||
|
||
// Legal Address Details
|
||
if (profile.legalAddressObject && typeof profile.legalAddressObject === 'object') {
|
||
if (profile.legalAddressObject.postcode) {
|
||
addUpdate('legal_address_postcode', profile.legalAddressObject.postcode, __('Legal Address Postcode'), frm.doc.legal_address_postcode);
|
||
}
|
||
if (profile.legalAddressObject.region) {
|
||
addUpdate('legal_address_region', profile.legalAddressObject.region, __('Legal Address Region'), frm.doc.legal_address_region);
|
||
}
|
||
if (profile.legalAddressObject.locality) {
|
||
addUpdate('legal_address_locality', profile.legalAddressObject.locality, __('Legal Address Locality'), frm.doc.legal_address_locality);
|
||
}
|
||
if (profile.legalAddressObject.street) {
|
||
addUpdate('legal_address_street', profile.legalAddressObject.street, __('Legal Address Street'), frm.doc.legal_address_street);
|
||
}
|
||
if (profile.legalAddressObject.houseNumber) {
|
||
addUpdate('legal_address_house', profile.legalAddressObject.houseNumber, __('Legal Address House Number'), frm.doc.legal_address_house);
|
||
}
|
||
if (profile.legalAddressObject.roomNumber) {
|
||
addUpdate('legal_address_room', profile.legalAddressObject.roomNumber, __('Legal Address Room Number'), frm.doc.legal_address_room);
|
||
}
|
||
}
|
||
|
||
// TAX SYSTEMS LIST
|
||
if (profile.taxSystems && Array.isArray(profile.taxSystems) && profile.taxSystems.length > 0) {
|
||
const taxSystemsList = profile.taxSystems.join(', ');
|
||
addUpdate('tax_systems_list', taxSystemsList, __('Tax Systems List'), frm.doc.tax_systems_list);
|
||
}
|
||
|
||
// EMPLOYER INFORMATION
|
||
if (profile.employer && typeof profile.employer === 'object') {
|
||
if (profile.employer.name) {
|
||
addUpdate('employer_name', profile.employer.name, __('Employer Name'), frm.doc.employer_name);
|
||
}
|
||
if (profile.employer.position) {
|
||
addUpdate('employer_position', profile.employer.position, __('Employer Position'), frm.doc.employer_position);
|
||
}
|
||
}
|
||
|
||
return updates;
|
||
},
|
||
|
||
updateCompanyFromProfile: function(profileData, frm) {
|
||
try {
|
||
const profile = profileData.profile || profileData;
|
||
const updates = ETaxesCompany._parseProfileData(profile, frm);
|
||
|
||
const hasAdditionalActivities = profile.additionalActivityCodes && Array.isArray(profile.additionalActivityCodes) && profile.additionalActivityCodes.length > 0;
|
||
const hasAffiliates = (profile.affiliatesNames && profile.affiliatesNames.length > 0) || (profile.affiliatesTins && profile.affiliatesTins.length > 0);
|
||
const hasDictionaryFields = profile.taxAuthorityCode || profile.propertyType;
|
||
|
||
if (updates.length > 0 || hasAdditionalActivities || hasAffiliates || hasDictionaryFields) {
|
||
let confirmMessage = '';
|
||
|
||
if (updates.length > 0) {
|
||
confirmMessage = __('The following company fields will be updated with data from E-Taxes:') + '<br><br>';
|
||
let changesList = '<ul style="text-align: left; margin: 10px 0;">';
|
||
updates.forEach(update => {
|
||
changesList += `<li><strong>${update.label}:</strong> ${update.oldValue || __('(empty)')} → ${update.newValue}</li>`;
|
||
});
|
||
changesList += '</ul>';
|
||
confirmMessage += changesList;
|
||
}
|
||
|
||
let additionalInfo = '';
|
||
if (hasAdditionalActivities) {
|
||
additionalInfo += `<br><strong>${__('Additional activities to be added')}:</strong> ${profile.additionalActivityCodes.length} ${__('activities')}`;
|
||
additionalInfo += '<br><small>' + profile.additionalActivityCodes.join(', ') + '</small>';
|
||
}
|
||
if (hasAffiliates) {
|
||
const affiliateCount = Math.max(
|
||
(profile.affiliatesNames || []).length,
|
||
(profile.affiliatesTins || []).length
|
||
);
|
||
additionalInfo += `<br><strong>${__('Affiliate organizations to be added')}:</strong> ${affiliateCount} ${__('organizations')}`;
|
||
}
|
||
|
||
if (!confirmMessage && additionalInfo) {
|
||
confirmMessage = __('The following data will be updated:');
|
||
}
|
||
|
||
confirmMessage += additionalInfo;
|
||
confirmMessage += '<br><br>' + __('Continue?');
|
||
|
||
frappe.confirm(
|
||
confirmMessage,
|
||
function() {
|
||
// Показываем индикатор загрузки
|
||
frappe.show_alert({
|
||
message: __('Updating company data...'),
|
||
indicator: 'blue'
|
||
});
|
||
|
||
// Собираем все обновления полей
|
||
let allUpdates = {};
|
||
updates.forEach(update => {
|
||
allUpdates[update.fieldname] = update.newValue;
|
||
});
|
||
|
||
// Обрабатываем справочники
|
||
let promises = [];
|
||
|
||
if (profile.taxAuthorityCode) {
|
||
promises.push(
|
||
ETaxesCompany._getTaxAuthorityName(profile.taxAuthorityCode).then((authorityName) => {
|
||
allUpdates['tax_authority'] = authorityName;
|
||
})
|
||
);
|
||
}
|
||
|
||
if (profile.propertyType) {
|
||
promises.push(
|
||
ETaxesCompany._getPropertyTypeName(profile.propertyType).then((propertyTypeName) => {
|
||
allUpdates['property_type'] = propertyTypeName;
|
||
})
|
||
);
|
||
}
|
||
|
||
Promise.all(promises).then(() => {
|
||
// Подготавливаем данные для отправки
|
||
const updateData = {
|
||
company_name: frm.doc.name,
|
||
field_updates: JSON.stringify(allUpdates),
|
||
additional_activities: JSON.stringify(hasAdditionalActivities ? profile.additionalActivityCodes : []),
|
||
affiliate_names: JSON.stringify(hasAffiliates ? (profile.affiliatesNames || []) : []),
|
||
affiliate_tins: JSON.stringify(hasAffiliates ? (profile.affiliatesTins || []) : [])
|
||
};
|
||
|
||
console.log('Sending update data:', updateData);
|
||
|
||
// Вызываем серверный метод для форсированного обновления
|
||
frappe.call({
|
||
method: 'taxes_az.company_etaxes.force_update_company',
|
||
args: updateData,
|
||
callback: function(r) {
|
||
console.log('Update response:', r);
|
||
|
||
if (r.message && r.message.success) {
|
||
// Перезагружаем форму
|
||
frm.reload_doc();
|
||
|
||
let successMessage = __('Company data successfully updated from E-Taxes profile');
|
||
if (r.message.additional_activities_added > 0) {
|
||
successMessage += '<br>' + __('Added {0} additional activities', [r.message.additional_activities_added]);
|
||
}
|
||
if (r.message.affiliates_added > 0) {
|
||
successMessage += '<br>' + __('Added {0} affiliate organizations', [r.message.affiliates_added]);
|
||
}
|
||
|
||
frappe.show_alert({
|
||
message: successMessage,
|
||
indicator: 'green'
|
||
}, 5);
|
||
} else {
|
||
frappe.msgprint({
|
||
title: __('Update Error'),
|
||
message: r.message ? r.message.message : __('Error updating company data'),
|
||
indicator: 'red'
|
||
});
|
||
}
|
||
},
|
||
error: function(r) {
|
||
console.error('Update error:', r);
|
||
frappe.msgprint({
|
||
title: __('Server Error'),
|
||
message: __('Server error during update. Please check the error logs.'),
|
||
indicator: 'red'
|
||
});
|
||
}
|
||
});
|
||
}).catch(error => {
|
||
console.error('Error processing dictionaries:', error);
|
||
frappe.msgprint({
|
||
title: __('Processing Error'),
|
||
message: __('Error processing dictionary data: {0}', [error]),
|
||
indicator: 'red'
|
||
});
|
||
});
|
||
},
|
||
function() {
|
||
frappe.show_alert({
|
||
message: __('Update cancelled'),
|
||
indicator: 'blue'
|
||
}, 3);
|
||
}
|
||
);
|
||
} else {
|
||
frappe.show_alert({
|
||
message: __('No new data to update'),
|
||
indicator: 'blue'
|
||
}, 3);
|
||
}
|
||
|
||
} catch (e) {
|
||
console.error('Error parsing profile data:', e);
|
||
frappe.show_alert({
|
||
message: __('Error parsing profile data: {0}', [e.message]),
|
||
indicator: 'red'
|
||
}, 5);
|
||
}
|
||
},
|
||
|
||
/**
|
||
* Extract best phone number from profile
|
||
*/
|
||
_extractPhoneNumber: function(profile, preferredType = null) {
|
||
// If preferredType is specified, try to get that type first
|
||
if (preferredType === 'mobile' && profile.mobilePhoneNumber) {
|
||
return profile.mobilePhoneNumber;
|
||
}
|
||
if (preferredType === 'landline' && profile.landlinePhoneNumber) {
|
||
return profile.landlinePhoneNumber;
|
||
}
|
||
|
||
// Priority: mobile > landline > contacts mobile > contacts home
|
||
if (profile.mobilePhoneNumber) {
|
||
return profile.mobilePhoneNumber;
|
||
}
|
||
|
||
if (profile.landlinePhoneNumber) {
|
||
return profile.landlinePhoneNumber;
|
||
}
|
||
|
||
// Check contacts array
|
||
if (profile.contacts && Array.isArray(profile.contacts)) {
|
||
// Look for mobile first
|
||
const mobileContact = profile.contacts.find(c => c.type === 'mobile' && c.contact);
|
||
if (mobileContact) {
|
||
return mobileContact.prefix ? `${mobileContact.prefix}${mobileContact.contact}` : mobileContact.contact;
|
||
}
|
||
|
||
// Then home phone
|
||
const phoneContact = profile.contacts.find(c => c.type === 'homePhone' && c.contact);
|
||
if (phoneContact) {
|
||
return phoneContact.prefix ? `${phoneContact.prefix}${phoneContact.contact}` : phoneContact.contact;
|
||
}
|
||
}
|
||
|
||
return null;
|
||
},
|
||
|
||
/**
|
||
* Format VAT Info object as readable text
|
||
*/
|
||
_formatVatInfo: function(vatInfo) {
|
||
if (!vatInfo || typeof vatInfo !== 'object') {
|
||
return vatInfo;
|
||
}
|
||
|
||
let formatted = '';
|
||
if (vatInfo.recDocumentDocumentNumber) {
|
||
formatted += __('Document No') + ': ' + vatInfo.recDocumentDocumentNumber;
|
||
}
|
||
if (vatInfo.prVatOperationsRegDate) {
|
||
if (formatted) formatted += '<br>';
|
||
formatted += __('Registration Date') + ': ' + vatInfo.prVatOperationsRegDate;
|
||
}
|
||
if (vatInfo.prOperationTableOperationDate) {
|
||
if (formatted) formatted += '<br>';
|
||
formatted += __('Operation Date') + ': ' + vatInfo.prOperationTableOperationDate;
|
||
}
|
||
|
||
return formatted || JSON.stringify(vatInfo);
|
||
},
|
||
|
||
/**
|
||
* Format parsed profile data as HTML
|
||
*/
|
||
_formatParsedProfileHTML: function(profile) {
|
||
let html = '<div class="etaxes-profile-info">';
|
||
|
||
try {
|
||
// Basic Company Information
|
||
html += '<div class="section"><h5>' + __('Company Information') + '</h5>';
|
||
html += '<table class="table table-bordered table-sm profile-table">';
|
||
|
||
if (profile.companyName) {
|
||
html += `<tr><td><strong>${__('Company Name')}</strong></td><td class="text-content">${profile.companyName}</td></tr>`;
|
||
}
|
||
if (profile.tin) {
|
||
html += `<tr><td><strong>${__('TIN')}</strong></td><td class="text-content">${profile.tin}</td></tr>`;
|
||
}
|
||
if (profile.pin) {
|
||
html += `<tr><td><strong>${__('PIN')}</strong></td><td class="text-content">${profile.pin}</td></tr>`;
|
||
}
|
||
if (profile.stateRegistrationDocumentNumber) {
|
||
html += `<tr><td><strong>${__('Registration Number')}</strong></td><td class="text-content">${profile.stateRegistrationDocumentNumber}</td></tr>`;
|
||
}
|
||
if (profile.taxpayerRegistrationDate) {
|
||
const regDate = moment(profile.taxpayerRegistrationDate).format('DD.MM.YYYY');
|
||
html += `<tr><td><strong>${__('Registration Date')}</strong></td><td class="text-content">${regDate}</td></tr>`;
|
||
}
|
||
if (profile.stateRegistrationDocumentIssuedDate) {
|
||
const issuedDate = moment(profile.stateRegistrationDocumentIssuedDate).format('DD.MM.YYYY');
|
||
html += `<tr><td><strong>${__('State Registration Document Issued Date')}</strong></td><td class="text-content">${issuedDate}</td></tr>`;
|
||
}
|
||
if (profile.taxpayerStatus) {
|
||
const statusText = profile.taxpayerStatus === 'A' ? __('Active') : profile.taxpayerStatus;
|
||
html += `<tr><td><strong>${__('Status')}</strong></td><td class="text-content">${statusText}</td></tr>`;
|
||
}
|
||
if (profile.legalFormCode) {
|
||
html += `<tr><td><strong>${__('Legal Form Code')}</strong></td><td class="text-content">${profile.legalFormCode}</td></tr>`;
|
||
}
|
||
if (profile.tinType) {
|
||
html += `<tr><td><strong>${__('TIN Type')}</strong></td><td class="text-content">${profile.tinType}</td></tr>`;
|
||
}
|
||
|
||
html += '</table></div>';
|
||
|
||
// Contact Information
|
||
html += '<div class="section"><h5>' + __('Contact Information') + '</h5>';
|
||
html += '<table class="table table-bordered table-sm profile-table">';
|
||
|
||
if (profile.mobilePhoneNumber) {
|
||
html += `<tr><td><strong>${__('Mobile Phone')}</strong></td><td class="text-content">${profile.mobilePhoneNumber}</td></tr>`;
|
||
}
|
||
if (profile.landlinePhoneNumber) {
|
||
html += `<tr><td><strong>${__('Landline Phone')}</strong></td><td class="text-content">${profile.landlinePhoneNumber}</td></tr>`;
|
||
}
|
||
if (profile.email) {
|
||
html += `<tr><td><strong>${__('Email')}</strong></td><td class="text-content">${profile.email}</td></tr>`;
|
||
}
|
||
if (profile.legalAddress) {
|
||
html += `<tr><td><strong>${__('Legal Address')}</strong></td><td class="text-content">${profile.legalAddress}</td></tr>`;
|
||
}
|
||
if (profile.actualAddress) {
|
||
html += `<tr><td><strong>${__('Actual Address')}</strong></td><td class="text-content">${profile.actualAddress}</td></tr>`;
|
||
}
|
||
if (profile.addressForMail) {
|
||
html += `<tr><td><strong>${__('Address for Mail')}</strong></td><td class="text-content">${profile.addressForMail}</td></tr>`;
|
||
}
|
||
|
||
// Legal Address Details
|
||
if (profile.legalAddressObject && typeof profile.legalAddressObject === 'object') {
|
||
const addr = profile.legalAddressObject;
|
||
if (addr.postcode || addr.region || addr.locality || addr.street || addr.houseNumber || addr.roomNumber) {
|
||
html += `<tr><td colspan="2"><strong>${__('Legal Address Details')}</strong></td></tr>`;
|
||
if (addr.postcode) html += `<tr><td>${__('Postcode')}</td><td class="text-content">${addr.postcode}</td></tr>`;
|
||
if (addr.region) html += `<tr><td>${__('Region')}</td><td class="text-content">${addr.region}</td></tr>`;
|
||
if (addr.locality) html += `<tr><td>${__('Locality')}</td><td class="text-content">${addr.locality}</td></tr>`;
|
||
if (addr.street) html += `<tr><td>${__('Street')}</td><td class="text-content">${addr.street}</td></tr>`;
|
||
if (addr.houseNumber) html += `<tr><td>${__('House Number')}</td><td class="text-content">${addr.houseNumber}</td></tr>`;
|
||
if (addr.roomNumber) html += `<tr><td>${__('Room Number')}</td><td class="text-content">${addr.roomNumber}</td></tr>`;
|
||
}
|
||
}
|
||
|
||
html += '</table></div>';
|
||
|
||
// Business Information
|
||
html += '<div class="section"><h5>' + __('Business Information') + '</h5>';
|
||
html += '<table class="table table-bordered table-sm profile-table">';
|
||
|
||
if (profile.mainActivity) {
|
||
html += `<tr><td><strong>${__('Main Activity Code')}</strong></td><td class="text-content">${profile.mainActivity}</td></tr>`;
|
||
}
|
||
if (profile.additionalActivityCodes && profile.additionalActivityCodes.length > 0) {
|
||
html += `<tr><td><strong>${__('Additional Activity Codes')}</strong></td><td class="text-content">${profile.additionalActivityCodes.join(', ')}</td></tr>`;
|
||
}
|
||
if (profile.criteriaOfBusinessEntity) {
|
||
html += `<tr><td><strong>${__('Business Entity Criteria')}</strong></td><td class="text-content">${profile.criteriaOfBusinessEntity}</td></tr>`;
|
||
}
|
||
if (profile.activityGroup) {
|
||
html += `<tr><td><strong>${__('Activity Group')}</strong></td><td class="text-content">${profile.activityGroup}</td></tr>`;
|
||
}
|
||
if (profile.sportBettingOperator !== undefined) {
|
||
html += `<tr><td><strong>${__('Sport Betting Operator')}</strong></td><td class="text-content">${profile.sportBettingOperator ? __('Yes') : __('No')}</td></tr>`;
|
||
}
|
||
if (profile.hasActiveProductionObject !== undefined) {
|
||
html += `<tr><td><strong>${__('Has Active Production Object')}</strong></td><td class="text-content">${profile.hasActiveProductionObject ? __('Yes') : __('No')}</td></tr>`;
|
||
}
|
||
|
||
html += '</table></div>';
|
||
|
||
// Tax Information
|
||
html += '<div class="section"><h5>' + __('Tax Information') + '</h5>';
|
||
html += '<table class="table table-bordered table-sm profile-table">';
|
||
|
||
if (profile.taxRate) {
|
||
html += `<tr><td><strong>${__('Tax Rate')}</strong></td><td class="text-content">${profile.taxRate}</td></tr>`;
|
||
}
|
||
if (profile.specialTaxRegime !== undefined) {
|
||
html += `<tr><td><strong>${__('Special Tax Regime')}</strong></td><td class="text-content">${profile.specialTaxRegime ? __('Yes') : __('No')}</td></tr>`;
|
||
}
|
||
if (profile.taxAuthorityCode) {
|
||
html += `<tr><td><strong>${__('Tax Authority Code')}</strong></td><td class="text-content">${profile.taxAuthorityCode}</td></tr>`;
|
||
}
|
||
if (profile.propertyType) {
|
||
html += `<tr><td><strong>${__('Property Type')}</strong></td><td class="text-content">${profile.propertyType}</td></tr>`;
|
||
}
|
||
if (profile.taxSystemType) {
|
||
html += `<tr><td><strong>${__('Tax System Type')}</strong></td><td class="text-content">${profile.taxSystemType}</td></tr>`;
|
||
}
|
||
if (profile.taxSystems && profile.taxSystems.length > 0) {
|
||
html += `<tr><td><strong>${__('Tax Systems')}</strong></td><td class="text-content">${profile.taxSystems.join(', ')}</td></tr>`;
|
||
}
|
||
if (profile.isRisky !== undefined) {
|
||
html += `<tr><td><strong>${__('Is Risky Taxpayer')}</strong></td><td class="text-content">${profile.isRisky ? __('Yes') : __('No')}</td></tr>`;
|
||
}
|
||
if (profile.isTaxPayerInCancellationProcess !== undefined) {
|
||
html += `<tr><td><strong>${__('In Cancellation Process')}</strong></td><td class="text-content">${profile.isTaxPayerInCancellationProcess ? __('Yes') : __('No')}</td></tr>`;
|
||
}
|
||
if (profile.vatInfo) {
|
||
const formattedVat = ETaxesCompany._formatVatInfo(profile.vatInfo);
|
||
html += `<tr><td><strong>${__('VAT Info')}</strong></td><td class="text-content">${formattedVat}</td></tr>`;
|
||
}
|
||
|
||
html += '</table></div>';
|
||
|
||
// Organizational Structure
|
||
html += '<div class="section"><h5>' + __('Organizational Structure') + '</h5>';
|
||
html += '<table class="table table-bordered table-sm profile-table">';
|
||
|
||
if (profile.headOrganizationName && profile.headOrganizationName.length > 0) {
|
||
html += `<tr><td><strong>${__('Parent Organization')}</strong></td><td class="text-content">${profile.headOrganizationName.join(', ')}</td></tr>`;
|
||
}
|
||
if (profile.headOrganizationTin) {
|
||
html += `<tr><td><strong>${__('Parent Organization TIN')}</strong></td><td class="text-content">${profile.headOrganizationTin}</td></tr>`;
|
||
}
|
||
if (profile.affiliatesNames && profile.affiliatesNames.length > 0) {
|
||
const affiliatesText = profile.affiliatesNames.join(', ');
|
||
html += `<tr><td><strong>${__('Affiliate Organizations')}</strong></td><td class="text-content">${affiliatesText}</td></tr>`;
|
||
}
|
||
if (profile.affiliatesTins && profile.affiliatesTins.length > 0) {
|
||
const affiliatesTinsText = profile.affiliatesTins.join(', ');
|
||
html += `<tr><td><strong>${__('Affiliate Organizations TINs')}</strong></td><td class="text-content">${affiliatesTinsText}</td></tr>`;
|
||
}
|
||
|
||
html += '</table></div>';
|
||
|
||
// Management Information
|
||
html += '<div class="section"><h5>' + __('Management Information') + '</h5>';
|
||
html += '<table class="table table-bordered table-sm profile-table">';
|
||
|
||
if (profile.companyDirectorName) {
|
||
html += `<tr><td><strong>${__('Director Name')}</strong></td><td class="text-content">${profile.companyDirectorName}</td></tr>`;
|
||
}
|
||
if (profile.chief) {
|
||
const chiefName = `${profile.chief.name || ''} ${profile.chief.surname || ''} ${profile.chief.middleName || ''}`.trim();
|
||
if (chiefName) {
|
||
html += `<tr><td><strong>${__('Chief')}</strong></td><td class="text-content">${chiefName}</td></tr>`;
|
||
}
|
||
if (profile.chief.pin) {
|
||
html += `<tr><td><strong>${__('Chief PIN')}</strong></td><td class="text-content">${profile.chief.pin}</td></tr>`;
|
||
}
|
||
}
|
||
if (profile.employer && profile.employer.name) {
|
||
html += `<tr><td><strong>${__('Employer')}</strong></td><td class="text-content">${profile.employer.name}</td></tr>`;
|
||
if (profile.employer.position) {
|
||
html += `<tr><td><strong>${__('Employer Position')}</strong></td><td class="text-content">${profile.employer.position}</td></tr>`;
|
||
}
|
||
}
|
||
if (profile.isChiefOfAnyLegalEntity !== undefined) {
|
||
html += `<tr><td><strong>${__('Is Chief of Any Legal Entity')}</strong></td><td class="text-content">${profile.isChiefOfAnyLegalEntity ? __('Yes') : __('No')}</td></tr>`;
|
||
}
|
||
if (profile.employeeData && profile.employeeData.employeeCount !== undefined) {
|
||
html += `<tr><td><strong>${__('Employee Count')}</strong></td><td class="text-content">${profile.employeeData.employeeCount}</td></tr>`;
|
||
}
|
||
|
||
html += '</table></div>';
|
||
|
||
// Important Dates
|
||
if (profile.suspensionStartDate || profile.suspensionEndDate || profile.liquidationDate) {
|
||
html += '<div class="section"><h5>' + __('Important Dates') + '</h5>';
|
||
html += '<table class="table table-bordered table-sm profile-table">';
|
||
|
||
if (profile.suspensionStartDate) {
|
||
const suspStartDate = moment(profile.suspensionStartDate).format('DD.MM.YYYY');
|
||
html += `<tr><td><strong>${__('Suspension Start Date')}</strong></td><td class="text-content">${suspStartDate}</td></tr>`;
|
||
}
|
||
if (profile.suspensionEndDate) {
|
||
const suspEndDate = moment(profile.suspensionEndDate).format('DD.MM.YYYY');
|
||
html += `<tr><td><strong>${__('Suspension End Date')}</strong></td><td class="text-content">${suspEndDate}</td></tr>`;
|
||
}
|
||
if (profile.liquidationDate) {
|
||
const liqDate = moment(profile.liquidationDate).format('DD.MM.YYYY');
|
||
html += `<tr><td><strong>${__('Liquidation Date')}</strong></td><td class="text-content">${liqDate}</td></tr>`;
|
||
}
|
||
|
||
html += '</table></div>';
|
||
}
|
||
|
||
// Certificates Information (if any)
|
||
if (profile.certificates && profile.certificates.length > 0) {
|
||
html += '<div class="section"><h5>' + __('Certificates') + '</h5>';
|
||
html += '<table class="table table-bordered table-sm profile-table">';
|
||
|
||
profile.certificates.forEach((cert, index) => {
|
||
html += `<tr><td colspan="2"><strong>${__('Certificate')} ${index + 1}</strong></td></tr>`;
|
||
if (cert.taxpayerType) {
|
||
html += `<tr><td>${__('Type')}</td><td class="text-content">${cert.taxpayerType}</td></tr>`;
|
||
}
|
||
if (cert.legalInfo) {
|
||
if (cert.legalInfo.tin) html += `<tr><td>${__('TIN')}</td><td class="text-content">${cert.legalInfo.tin}</td></tr>`;
|
||
if (cert.legalInfo.name) html += `<tr><td>${__('Name')}</td><td class="text-content">${cert.legalInfo.name}</td></tr>`;
|
||
}
|
||
if (cert.individualInfo) {
|
||
if (cert.individualInfo.fin) html += `<tr><td>${__('FIN')}</td><td class="text-content">${cert.individualInfo.fin}</td></tr>`;
|
||
if (cert.individualInfo.name) html += `<tr><td>${__('Name')}</td><td class="text-content">${cert.individualInfo.name}</td></tr>`;
|
||
}
|
||
if (cert.position) {
|
||
html += `<tr><td>${__('Position')}</td><td class="text-content">${cert.position}</td></tr>`;
|
||
}
|
||
if (cert.hasAccess !== undefined) {
|
||
html += `<tr><td>${__('Has Access')}</td><td class="text-content">${cert.hasAccess ? __('Yes') : __('No')}</td></tr>`;
|
||
}
|
||
if (cert.liquidated !== undefined) {
|
||
html += `<tr><td>${__('Liquidated')}</td><td class="text-content">${cert.liquidated ? __('Yes') : __('No')}</td></tr>`;
|
||
}
|
||
});
|
||
|
||
html += '</table></div>';
|
||
}
|
||
|
||
} catch (e) {
|
||
html += '<div class="alert alert-warning">' + __('Unable to parse profile data: {0}', [e.message]) + '</div>';
|
||
}
|
||
|
||
html += '</div>';
|
||
|
||
// CSS остается тем же
|
||
html = `
|
||
<style>
|
||
.etaxes-profile-info {
|
||
color: var(--text-color, #333);
|
||
background: var(--bg-color, #fff);
|
||
max-width: 100%;
|
||
overflow-x: auto;
|
||
}
|
||
.etaxes-profile-info .section {
|
||
margin-bottom: 20px;
|
||
}
|
||
.etaxes-profile-info h5 {
|
||
color: var(--primary-color, #5e64ff);
|
||
margin-bottom: 10px;
|
||
font-weight: 600;
|
||
}
|
||
.etaxes-profile-info .profile-table {
|
||
background: var(--bg-color, #fff);
|
||
border: 1px solid var(--border-color, #dee2e6);
|
||
color: var(--text-color, #333);
|
||
width: 100%;
|
||
table-layout: auto;
|
||
max-width: 100%;
|
||
}
|
||
.etaxes-profile-info .profile-table td {
|
||
padding: 8px 12px;
|
||
border: 1px solid var(--border-color, #dee2e6);
|
||
color: var(--text-color, #333);
|
||
word-wrap: break-word;
|
||
word-break: break-word;
|
||
vertical-align: top;
|
||
white-space: normal;
|
||
}
|
||
.etaxes-profile-info .profile-table td:first-child {
|
||
width: 180px;
|
||
background: var(--control-bg-color, #f8f9fa);
|
||
font-weight: 500;
|
||
color: var(--text-color, #333);
|
||
min-width: 150px;
|
||
}
|
||
.etaxes-profile-info .profile-table td.text-content {
|
||
background: var(--bg-color, #fff);
|
||
color: var(--text-color, #333);
|
||
white-space: normal;
|
||
word-wrap: break-word;
|
||
}
|
||
@media (prefers-color-scheme: dark) {
|
||
.etaxes-profile-info {
|
||
color: #e4e6ea;
|
||
background: #2b2d42;
|
||
}
|
||
.etaxes-profile-info .profile-table {
|
||
background: #2b2d42;
|
||
border-color: #495057;
|
||
color: #e4e6ea;
|
||
}
|
||
.etaxes-profile-info .profile-table td {
|
||
border-color: #495057;
|
||
color: #e4e6ea;
|
||
}
|
||
.etaxes-profile-info .profile-table td:first-child {
|
||
background: #3a3d5c;
|
||
color: #e4e6ea;
|
||
}
|
||
.etaxes-profile-info .profile-table td.text-content {
|
||
background: #2b2d42;
|
||
color: #e4e6ea;
|
||
}
|
||
}
|
||
</style>
|
||
` + html;
|
||
|
||
return html;
|
||
},
|
||
|
||
/**
|
||
* Helper functions for authentication dialogs
|
||
*/
|
||
_getAuthLoadingHTML: function(title, message) {
|
||
return `
|
||
<div class="text-center">
|
||
<div class="loading-animation" style="display: inline-block; width: 64px; height: 64px;">
|
||
<div style="width: 64px; height: 64px; border: 6px solid #4e73df; border-radius: 50%; border-color: #4e73df transparent #4e73df transparent; animation: lds-dual-ring 1.2s linear infinite;"></div>
|
||
</div>
|
||
<style>
|
||
@keyframes lds-dual-ring {
|
||
0% { transform: rotate(0deg); }
|
||
100% { transform: rotate(360deg); }
|
||
}
|
||
</style>
|
||
<div class="mt-3" id="auth_status_message">
|
||
<h4 id="auth_loading_title">${title || __('Please wait...')}</h4>
|
||
<p id="auth_loading_message">${message || __('The operation may take some time')}</p>
|
||
</div>
|
||
<div id="auth_verification_code_container" style="display:none; margin-top: 15px;">
|
||
<div style="background: #f8f9fa; padding: 10px; display: inline-block; border-radius: 5px; font-size: 24px; font-weight: bold; letter-spacing: 2px; color: #333; border: 1px solid #ddd;">
|
||
<span id="auth_verification_code">----</span>
|
||
</div>
|
||
<p style="margin-top: 5px; font-size: 12px; color: #666;">Verification Code</p>
|
||
</div>
|
||
</div>
|
||
`;
|
||
},
|
||
|
||
_updateLoadingDialog: function(dialog, title, message) {
|
||
if (title) $('#auth_loading_title').text(title);
|
||
if (message) $('#auth_loading_message').text(message);
|
||
},
|
||
|
||
_showVerificationCode: function(dialog, code) {
|
||
if (code) {
|
||
$('#auth_verification_code').text(code);
|
||
$('#auth_verification_code_container').show();
|
||
}
|
||
},
|
||
|
||
_setDialogSuccess: function(dialog, title, message) {
|
||
dialog.$wrapper.find('.loading-animation').html(`
|
||
<div style="width: 64px; height: 64px; display: flex; align-items: center; justify-content: center;">
|
||
<i class="fa fa-check" style="font-size: 48px; color: #5cb85c;"></i>
|
||
</div>
|
||
`);
|
||
|
||
$('#auth_loading_title').text(title);
|
||
$('#auth_loading_message').text(message);
|
||
$('#auth_verification_code_container').hide();
|
||
},
|
||
|
||
_setDialogError: function(dialog, title, message) {
|
||
dialog.$wrapper.find('.loading-animation').html(`
|
||
<div style="width: 64px; height: 64px; display: flex; align-items: center; justify-content: center;">
|
||
<i class="fa fa-times" style="font-size: 48px; color: #d9534f;"></i>
|
||
</div>
|
||
`);
|
||
|
||
$('#auth_loading_title').text(title);
|
||
$('#auth_loading_message').text(message);
|
||
$('#auth_verification_code_container').hide();
|
||
|
||
dialog.set_primary_action(__('Close'), () => dialog.hide());
|
||
}
|
||
}; |