Added bulk edit, all english, and every doctype of invoice az is read-only
This commit is contained in:
parent
905cfeac0c
commit
994917ffbc
File diff suppressed because it is too large
Load Diff
|
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
frappe.ui.form.on('Purchase Order', {
|
frappe.ui.form.on('Purchase Order', {
|
||||||
refresh: function(frm) {
|
refresh: function(frm) {
|
||||||
// Проверяем, установлена ли галочка is_taxes_doc
|
// Проверяем, установлена ли галочка is_taxes_doc
|
||||||
|
|
@ -7,7 +6,7 @@ frappe.ui.form.on('Purchase Order', {
|
||||||
frm.set_read_only(true);
|
frm.set_read_only(true);
|
||||||
|
|
||||||
// Альтернативно, можно добавить визуальное предупреждение
|
// Альтернативно, можно добавить визуальное предупреждение
|
||||||
frm.page.set_indicator(__('Налоговый документ'), 'blue');
|
frm.page.set_indicator(__('Tax Document'), 'blue');
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
@ -42,7 +41,7 @@ frappe.listview_settings['Purchase Order'] = {
|
||||||
// Добавляем кнопку в верхнее меню списка
|
// Добавляем кнопку в верхнее меню списка
|
||||||
onload: function(listview) {
|
onload: function(listview) {
|
||||||
// Добавляем кнопку для импорта из E-Taxes
|
// Добавляем кнопку для импорта из E-Taxes
|
||||||
listview.page.add_menu_item(__('Импорт из E-Taxes'), function() {
|
listview.page.add_menu_item(__('Import from E-Taxes'), function() {
|
||||||
show_etaxes_import_dialog_for_list();
|
show_etaxes_import_dialog_for_list();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -58,7 +57,7 @@ var cancel_loading = false;
|
||||||
function show_loading_dialog(message, show_progress = false) {
|
function show_loading_dialog(message, show_progress = false) {
|
||||||
if (!loading_dialog) {
|
if (!loading_dialog) {
|
||||||
loading_dialog = new frappe.ui.Dialog({
|
loading_dialog = new frappe.ui.Dialog({
|
||||||
title: __('Загрузка'),
|
title: __('Loading'),
|
||||||
fields: [
|
fields: [
|
||||||
{
|
{
|
||||||
fieldname: 'status_html',
|
fieldname: 'status_html',
|
||||||
|
|
@ -100,8 +99,8 @@ function show_loading_dialog(message, show_progress = false) {
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
<div class="mt-3" id="status_message">
|
<div class="mt-3" id="status_message">
|
||||||
<h4>${message || __('Пожалуйста, подождите...')}</h4>
|
<h4>${message || __('Please wait...')}</h4>
|
||||||
<p>${__('Операция может занять некоторое время')}</p>
|
<p>${__('The operation may take some time')}</p>
|
||||||
</div>
|
</div>
|
||||||
<!-- Блок для отображения кода верификации -->
|
<!-- Блок для отображения кода верификации -->
|
||||||
<div id="verification_code_container" style="display:none; margin-top: 15px;">
|
<div id="verification_code_container" style="display:none; margin-top: 15px;">
|
||||||
|
|
@ -121,18 +120,18 @@ function show_loading_dialog(message, show_progress = false) {
|
||||||
`
|
`
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
primary_action_label: __('Отмена'),
|
primary_action_label: __('Cancel'),
|
||||||
primary_action: function() {
|
primary_action: function() {
|
||||||
cancel_loading = true;
|
cancel_loading = true;
|
||||||
loading_dialog.$wrapper.find('.primary-action').prop('disabled', true);
|
loading_dialog.$wrapper.find('.primary-action').prop('disabled', true);
|
||||||
loading_dialog.$wrapper.find('.primary-action').html(__('Отмена в процессе...'));
|
loading_dialog.$wrapper.find('.primary-action').html(__('Cancelling...'));
|
||||||
$('#status_message p').text(__('Отмена загрузки. Уже загруженные инвойсы сохранятся.'));
|
$('#status_message p').text(__('Cancelling the loading. Already loaded invoices will be saved.'));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
// Обновляем сообщение
|
// Обновляем сообщение
|
||||||
$('#status_message h4').text(message || __('Пожалуйста, подождите...'));
|
$('#status_message h4').text(message || __('Please wait...'));
|
||||||
$('#status_message p').text(__('Операция может занять некоторое время'));
|
$('#status_message p').text(__('The operation may take some time'));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Показываем или скрываем прогресс-бар
|
// Показываем или скрываем прогресс-бар
|
||||||
|
|
@ -156,7 +155,7 @@ function update_progress(current, total) {
|
||||||
if (loading_dialog) {
|
if (loading_dialog) {
|
||||||
var percent = Math.round((current / total) * 100);
|
var percent = Math.round((current / total) * 100);
|
||||||
$('#progress_bar_fill').css('width', percent + '%');
|
$('#progress_bar_fill').css('width', percent + '%');
|
||||||
$('#progress_text').text(current + ' из ' + total + ' (' + percent + '%)');
|
$('#progress_text').text(current + ' of ' + total + ' (' + percent + '%)');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -667,34 +666,34 @@ function show_etaxes_import_dialog(frm) {
|
||||||
check_token_before_api_call(function() {
|
check_token_before_api_call(function() {
|
||||||
// Создаем диалог для выбора периода и склада
|
// Создаем диалог для выбора периода и склада
|
||||||
var d = new frappe.ui.Dialog({
|
var d = new frappe.ui.Dialog({
|
||||||
title: __('Импорт счета-фактуры из E-Taxes'),
|
title: __('Import invoice from E-Taxes'),
|
||||||
fields: [
|
fields: [
|
||||||
{
|
{
|
||||||
fieldname: 'date_range_section',
|
fieldname: 'date_range_section',
|
||||||
fieldtype: 'Section Break',
|
fieldtype: 'Section Break',
|
||||||
label: __('Период')
|
label: __('Period')
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
fieldname: 'creationDateFrom',
|
fieldname: 'creationDateFrom',
|
||||||
fieldtype: 'Date',
|
fieldtype: 'Date',
|
||||||
label: __('Дата с'),
|
label: __('Date from'),
|
||||||
default: moment().subtract(1, 'month').format('YYYY-MM-DD')
|
default: moment().subtract(1, 'month').format('YYYY-MM-DD')
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
fieldname: 'creationDateTo',
|
fieldname: 'creationDateTo',
|
||||||
fieldtype: 'Date',
|
fieldtype: 'Date',
|
||||||
label: __('Дата по'),
|
label: __('Date to'),
|
||||||
default: moment().format('YYYY-MM-DD')
|
default: moment().format('YYYY-MM-DD')
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
fieldname: 'settings_section',
|
fieldname: 'settings_section',
|
||||||
fieldtype: 'Section Break',
|
fieldtype: 'Section Break',
|
||||||
label: __('Настройки')
|
label: __('Settings')
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
fieldname: 'warehouse',
|
fieldname: 'warehouse',
|
||||||
fieldtype: 'Link',
|
fieldtype: 'Link',
|
||||||
label: __('Склад по умолчанию'),
|
label: __('Default warehouse'),
|
||||||
options: 'Warehouse',
|
options: 'Warehouse',
|
||||||
reqd: true,
|
reqd: true,
|
||||||
get_query: function() {
|
get_query: function() {
|
||||||
|
|
@ -707,7 +706,7 @@ function show_etaxes_import_dialog(frm) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
primary_action_label: __('Поиск'),
|
primary_action_label: __('Search'),
|
||||||
primary_action: function() {
|
primary_action: function() {
|
||||||
var values = d.get_values();
|
var values = d.get_values();
|
||||||
|
|
||||||
|
|
@ -718,16 +717,16 @@ function show_etaxes_import_dialog(frm) {
|
||||||
|
|
||||||
if (!warehouse) {
|
if (!warehouse) {
|
||||||
frappe.msgprint({
|
frappe.msgprint({
|
||||||
title: __('Внимание'),
|
title: __('Warning'),
|
||||||
indicator: 'orange',
|
indicator: 'orange',
|
||||||
message: __('Пожалуйста, выберите склад по умолчанию')
|
message: __('Please select a default warehouse')
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Закрываем диалог
|
// Закрываем диалог
|
||||||
d.hide();
|
d.hide();
|
||||||
show_loading_dialog(__('Загрузка счетов-фактур...'));
|
show_loading_dialog(__('Loading invoices...'));
|
||||||
|
|
||||||
// Загружаем счета-фактуры
|
// Загружаем счета-фактуры
|
||||||
load_etaxes_invoices(frm, fromDate, toDate, warehouse);
|
load_etaxes_invoices(frm, fromDate, toDate, warehouse);
|
||||||
|
|
@ -744,34 +743,34 @@ function show_etaxes_import_dialog_for_list() {
|
||||||
check_token_before_api_call(function() {
|
check_token_before_api_call(function() {
|
||||||
// Создаем диалог для выбора периода и склада
|
// Создаем диалог для выбора периода и склада
|
||||||
var d = new frappe.ui.Dialog({
|
var d = new frappe.ui.Dialog({
|
||||||
title: __('Импорт счета-фактуры из E-Taxes'),
|
title: __('Import invoice from E-Taxes'),
|
||||||
fields: [
|
fields: [
|
||||||
{
|
{
|
||||||
fieldname: 'date_range_section',
|
fieldname: 'date_range_section',
|
||||||
fieldtype: 'Section Break',
|
fieldtype: 'Section Break',
|
||||||
label: __('Период')
|
label: __('Period')
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
fieldname: 'creationDateFrom',
|
fieldname: 'creationDateFrom',
|
||||||
fieldtype: 'Date',
|
fieldtype: 'Date',
|
||||||
label: __('Дата с'),
|
label: __('Date from'),
|
||||||
default: moment().subtract(1, 'month').format('YYYY-MM-DD')
|
default: moment().subtract(1, 'month').format('YYYY-MM-DD')
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
fieldname: 'creationDateTo',
|
fieldname: 'creationDateTo',
|
||||||
fieldtype: 'Date',
|
fieldtype: 'Date',
|
||||||
label: __('Дата по'),
|
label: __('Date to'),
|
||||||
default: moment().format('YYYY-MM-DD')
|
default: moment().format('YYYY-MM-DD')
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
fieldname: 'settings_section',
|
fieldname: 'settings_section',
|
||||||
fieldtype: 'Section Break',
|
fieldtype: 'Section Break',
|
||||||
label: __('Настройки')
|
label: __('Settings')
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
fieldname: 'warehouse',
|
fieldname: 'warehouse',
|
||||||
fieldtype: 'Link',
|
fieldtype: 'Link',
|
||||||
label: __('Склад по умолчанию'),
|
label: __('Default warehouse'),
|
||||||
options: 'Warehouse',
|
options: 'Warehouse',
|
||||||
reqd: true,
|
reqd: true,
|
||||||
get_query: function() {
|
get_query: function() {
|
||||||
|
|
@ -784,7 +783,7 @@ function show_etaxes_import_dialog_for_list() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
primary_action_label: __('Поиск'),
|
primary_action_label: __('Search'),
|
||||||
primary_action: function() {
|
primary_action: function() {
|
||||||
var values = d.get_values();
|
var values = d.get_values();
|
||||||
|
|
||||||
|
|
@ -795,16 +794,16 @@ function show_etaxes_import_dialog_for_list() {
|
||||||
|
|
||||||
if (!warehouse) {
|
if (!warehouse) {
|
||||||
frappe.msgprint({
|
frappe.msgprint({
|
||||||
title: __('Внимание'),
|
title: __('Warning'),
|
||||||
indicator: 'orange',
|
indicator: 'orange',
|
||||||
message: __('Пожалуйста, выберите склад по умолчанию')
|
message: __('Please select a default warehouse')
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Закрываем диалог
|
// Закрываем диалог
|
||||||
d.hide();
|
d.hide();
|
||||||
show_loading_dialog(__('Загрузка счетов-фактур...'));
|
show_loading_dialog(__('Loading invoices...'));
|
||||||
|
|
||||||
// Загружаем счета-фактуры
|
// Загружаем счета-фактуры
|
||||||
load_etaxes_invoices(null, fromDate, toDate, warehouse);
|
load_etaxes_invoices(null, fromDate, toDate, warehouse);
|
||||||
|
|
@ -836,9 +835,9 @@ function load_etaxes_invoices(frm, fromDate, toDate, warehouse) {
|
||||||
if (!main_token) {
|
if (!main_token) {
|
||||||
hide_loading_dialog();
|
hide_loading_dialog();
|
||||||
frappe.msgprint({
|
frappe.msgprint({
|
||||||
title: __('Ошибка авторизации'),
|
title: __('Authentication Error'),
|
||||||
indicator: 'red',
|
indicator: 'red',
|
||||||
message: __('Не найден токен авторизации. Пожалуйста, завершите процесс авторизации в настройках E-Taxes.')
|
message: __('Authentication token not found. Please complete the authentication process in E-Taxes settings.')
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -866,8 +865,8 @@ function load_etaxes_invoices(frm, fromDate, toDate, warehouse) {
|
||||||
if (invoices.length > 0) {
|
if (invoices.length > 0) {
|
||||||
// Показываем диалог загрузки для проверки дубликатов
|
// Показываем диалог загрузки для проверки дубликатов
|
||||||
update_loading_message(
|
update_loading_message(
|
||||||
__('Проверка на дубликаты...'),
|
__('Checking for duplicates...'),
|
||||||
__('Фильтрация уже импортированных счетов-фактур')
|
__('Filtering already imported invoices')
|
||||||
);
|
);
|
||||||
|
|
||||||
// Получаем список уже импортированных инвойсов из E-Taxes Purchase
|
// Получаем список уже импортированных инвойсов из E-Taxes Purchase
|
||||||
|
|
@ -922,19 +921,19 @@ function load_etaxes_invoices(frm, fromDate, toDate, warehouse) {
|
||||||
show_invoice_selection_dialog(frm, filteredInvoices, main_token, warehouse);
|
show_invoice_selection_dialog(frm, filteredInvoices, main_token, warehouse);
|
||||||
} else {
|
} else {
|
||||||
frappe.msgprint({
|
frappe.msgprint({
|
||||||
title: __('Информация'),
|
title: __('Information'),
|
||||||
indicator: 'blue',
|
indicator: 'blue',
|
||||||
message: __('За указанный период не найдено новых счетов-фактур (все ' +
|
message: __('No new invoices found for the specified period (all ' +
|
||||||
invoices.length + ' уже импортированы)')
|
invoices.length + ' are already imported)')
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error("Error processing purchase data:", e);
|
console.error("Error processing purchase data:", e);
|
||||||
hide_loading_dialog();
|
hide_loading_dialog();
|
||||||
frappe.msgprint({
|
frappe.msgprint({
|
||||||
title: __('Ошибка'),
|
title: __('Error'),
|
||||||
indicator: 'red',
|
indicator: 'red',
|
||||||
message: __('Произошла ошибка при обработке данных: ') + e.message
|
message: __('An error occurred while processing data: ') + e.message
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
@ -946,7 +945,7 @@ function load_etaxes_invoices(frm, fromDate, toDate, warehouse) {
|
||||||
show_invoice_selection_dialog(frm, invoices, main_token, warehouse);
|
show_invoice_selection_dialog(frm, invoices, main_token, warehouse);
|
||||||
|
|
||||||
frappe.show_alert({
|
frappe.show_alert({
|
||||||
message: __('Не удалось выполнить проверку дубликатов. Показаны все инвойсы.'),
|
message: __('Failed to check for duplicates. Showing all invoices.'),
|
||||||
indicator: 'orange'
|
indicator: 'orange'
|
||||||
}, 5);
|
}, 5);
|
||||||
}
|
}
|
||||||
|
|
@ -956,9 +955,9 @@ function load_etaxes_invoices(frm, fromDate, toDate, warehouse) {
|
||||||
hide_loading_dialog();
|
hide_loading_dialog();
|
||||||
|
|
||||||
frappe.msgprint({
|
frappe.msgprint({
|
||||||
title: __('Информация'),
|
title: __('Information'),
|
||||||
indicator: 'blue',
|
indicator: 'blue',
|
||||||
message: __('За указанный период не найдено счетов-фактур')
|
message: __('No invoices found for the specified period')
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} else if (r.message && r.message.error === 'unauthorized') {
|
} else if (r.message && r.message.error === 'unauthorized') {
|
||||||
|
|
@ -987,9 +986,9 @@ function load_etaxes_invoices(frm, fromDate, toDate, warehouse) {
|
||||||
hide_loading_dialog();
|
hide_loading_dialog();
|
||||||
|
|
||||||
frappe.msgprint({
|
frappe.msgprint({
|
||||||
title: __('Ошибка'),
|
title: __('Error'),
|
||||||
indicator: 'red',
|
indicator: 'red',
|
||||||
message: r.message ? r.message.message : __('Ошибка загрузки счетов-фактур')
|
message: r.message ? r.message.message : __('Error loading invoices')
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
@ -997,18 +996,18 @@ function load_etaxes_invoices(frm, fromDate, toDate, warehouse) {
|
||||||
console.error("Error fetching invoices:", error);
|
console.error("Error fetching invoices:", error);
|
||||||
hide_loading_dialog();
|
hide_loading_dialog();
|
||||||
frappe.msgprint({
|
frappe.msgprint({
|
||||||
title: __('Ошибка сети'),
|
title: __('Network Error'),
|
||||||
indicator: 'red',
|
indicator: 'red',
|
||||||
message: __('Ошибка при получении данных с сервера: ') + (error || 'Unknown error')
|
message: __('Error fetching data from server: ') + (error || 'Unknown error')
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
hide_loading_dialog();
|
hide_loading_dialog();
|
||||||
frappe.msgprint({
|
frappe.msgprint({
|
||||||
title: __('Ошибка'),
|
title: __('Error'),
|
||||||
indicator: 'red',
|
indicator: 'red',
|
||||||
message: __('Не найдены настройки авторизации E-Taxes')
|
message: __('E-Taxes authentication settings not found')
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
@ -1016,9 +1015,9 @@ function load_etaxes_invoices(frm, fromDate, toDate, warehouse) {
|
||||||
console.error("Error fetching Asan login settings:", error);
|
console.error("Error fetching Asan login settings:", error);
|
||||||
hide_loading_dialog();
|
hide_loading_dialog();
|
||||||
frappe.msgprint({
|
frappe.msgprint({
|
||||||
title: __('Ошибка сети'),
|
title: __('Network Error'),
|
||||||
indicator: 'red',
|
indicator: 'red',
|
||||||
message: __('Ошибка при получении настроек авторизации: ') + (error || 'Unknown error')
|
message: __('Error fetching authentication settings: ') + (error || 'Unknown error')
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
@ -1030,10 +1029,10 @@ function show_invoice_selection_dialog(frm, invoices, token, warehouse) {
|
||||||
var invoice_table = '<div style="max-height: 500px; overflow-y: auto;"><table class="table table-bordered etaxes-invoices-table">';
|
var invoice_table = '<div style="max-height: 500px; overflow-y: auto;"><table class="table table-bordered etaxes-invoices-table">';
|
||||||
invoice_table += '<thead><tr>' +
|
invoice_table += '<thead><tr>' +
|
||||||
'<th style="width: 30px;"><input type="checkbox" class="select-all-invoices"></th>' +
|
'<th style="width: 30px;"><input type="checkbox" class="select-all-invoices"></th>' +
|
||||||
'<th>' + __('Номер') + '</th>' +
|
'<th>' + __('Number') + '</th>' +
|
||||||
'<th>' + __('Дата') + '</th>' +
|
'<th>' + __('Date') + '</th>' +
|
||||||
'<th>' + __('Поставщик') + '</th>' +
|
'<th>' + __('Supplier') + '</th>' +
|
||||||
'<th>' + __('Сумма') + '</th>' +
|
'<th>' + __('Amount') + '</th>' +
|
||||||
'</tr></thead><tbody>';
|
'</tr></thead><tbody>';
|
||||||
|
|
||||||
invoices.forEach(function(invoice) {
|
invoices.forEach(function(invoice) {
|
||||||
|
|
@ -1063,12 +1062,12 @@ function show_invoice_selection_dialog(frm, invoices, token, warehouse) {
|
||||||
|
|
||||||
// Информация о количестве найденных инвойсов
|
// Информация о количестве найденных инвойсов
|
||||||
let info_message = '<div class="alert alert-info">' +
|
let info_message = '<div class="alert alert-info">' +
|
||||||
__('Найдено новых счетов-фактур: ') + invoices.length +
|
__('New invoices found: ') + invoices.length +
|
||||||
'</div>';
|
'</div>';
|
||||||
|
|
||||||
// Создаем диалог
|
// Создаем диалог
|
||||||
var d = new frappe.ui.Dialog({
|
var d = new frappe.ui.Dialog({
|
||||||
title: __('Выбор счета-фактуры'),
|
title: __('Select invoice'),
|
||||||
fields: [
|
fields: [
|
||||||
{
|
{
|
||||||
fieldname: 'info_html',
|
fieldname: 'info_html',
|
||||||
|
|
@ -1084,10 +1083,10 @@ function show_invoice_selection_dialog(frm, invoices, token, warehouse) {
|
||||||
fieldname: 'warehouse_display',
|
fieldname: 'warehouse_display',
|
||||||
fieldtype: 'HTML',
|
fieldtype: 'HTML',
|
||||||
options: '<div class="row"><div class="col-xs-12"><div class="alert alert-info">' +
|
options: '<div class="row"><div class="col-xs-12"><div class="alert alert-info">' +
|
||||||
__('Выбранный склад: ') + '<strong>' + warehouse + '</strong></div></div></div>'
|
__('Selected warehouse: ') + '<strong>' + warehouse + '</strong></div></div></div>'
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
primary_action_label: __('Загрузить выбранные'),
|
primary_action_label: __('Load selected'),
|
||||||
primary_action: function() {
|
primary_action: function() {
|
||||||
// Получаем выбранные инвойсы
|
// Получаем выбранные инвойсы
|
||||||
var selected_invoice_ids = [];
|
var selected_invoice_ids = [];
|
||||||
|
|
@ -1097,9 +1096,9 @@ function show_invoice_selection_dialog(frm, invoices, token, warehouse) {
|
||||||
|
|
||||||
if (selected_invoice_ids.length === 0) {
|
if (selected_invoice_ids.length === 0) {
|
||||||
frappe.msgprint({
|
frappe.msgprint({
|
||||||
title: __('Внимание'),
|
title: __('Warning'),
|
||||||
indicator: 'orange',
|
indicator: 'orange',
|
||||||
message: __('Не выбрано ни одного счета-фактуры')
|
message: __('No invoices selected')
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -1109,13 +1108,13 @@ function show_invoice_selection_dialog(frm, invoices, token, warehouse) {
|
||||||
|
|
||||||
// Загружаем выбранные инвойсы последовательно
|
// Загружаем выбранные инвойсы последовательно
|
||||||
// Показываем диалог с прогрессом
|
// Показываем диалог с прогрессом
|
||||||
show_loading_dialog(__('Загрузка инвойсов...'), true);
|
show_loading_dialog(__('Loading invoices...'), true);
|
||||||
update_progress(0, selected_invoice_ids.length);
|
update_progress(0, selected_invoice_ids.length);
|
||||||
|
|
||||||
// Загружаем выбранные инвойсы последовательно
|
// Загружаем выбранные инвойсы последовательно
|
||||||
load_selected_invoices(frm, selected_invoice_ids, token, warehouse, 0);
|
load_selected_invoices(frm, selected_invoice_ids, token, warehouse, 0);
|
||||||
},
|
},
|
||||||
secondary_action_label: __('Отмена'),
|
secondary_action_label: __('Cancel'),
|
||||||
secondary_action: function() {
|
secondary_action: function() {
|
||||||
d.hide();
|
d.hide();
|
||||||
}
|
}
|
||||||
|
|
@ -1137,8 +1136,8 @@ function load_selected_invoices(frm, invoice_ids, token, warehouse, processed_co
|
||||||
// Если был запрос на отмену, показываем соответствующее сообщение
|
// Если был запрос на отмену, показываем соответствующее сообщение
|
||||||
if (cancel_loading) {
|
if (cancel_loading) {
|
||||||
set_loading_success(
|
set_loading_success(
|
||||||
__('Загрузка отменена'),
|
__('Loading cancelled'),
|
||||||
__('Загружено ' + processed_count + ' инвойсов из ' + (processed_count + invoice_ids.length)),
|
__('Loaded ' + processed_count + ' invoices out of ' + (processed_count + invoice_ids.length)),
|
||||||
function() {
|
function() {
|
||||||
if (frm) {
|
if (frm) {
|
||||||
frm.reload_doc();
|
frm.reload_doc();
|
||||||
|
|
@ -1150,8 +1149,8 @@ function load_selected_invoices(frm, invoice_ids, token, warehouse, processed_co
|
||||||
} else {
|
} else {
|
||||||
// Все успешно загружено
|
// Все успешно загружено
|
||||||
set_loading_success(
|
set_loading_success(
|
||||||
__('Загрузка завершена'),
|
__('Loading completed'),
|
||||||
__('Загружено ' + processed_count + ' инвойсов'),
|
__('Loaded ' + processed_count + ' invoices'),
|
||||||
function() {
|
function() {
|
||||||
if (frm) {
|
if (frm) {
|
||||||
frm.reload_doc();
|
frm.reload_doc();
|
||||||
|
|
@ -1172,8 +1171,8 @@ function load_selected_invoices(frm, invoice_ids, token, warehouse, processed_co
|
||||||
|
|
||||||
// Обновляем текст загрузки
|
// Обновляем текст загрузки
|
||||||
update_loading_message(
|
update_loading_message(
|
||||||
__('Загрузка инвойса (' + (processed_count + 1) + ' из ' + (processed_count + invoice_ids.length + 1) + ')'),
|
__('Loading invoice (' + (processed_count + 1) + ' of ' + (processed_count + invoice_ids.length + 1) + ')'),
|
||||||
__('Получение данных счета-фактуры...')
|
__('Getting invoice data...')
|
||||||
);
|
);
|
||||||
|
|
||||||
// Получаем детали счета-фактуры
|
// Получаем детали счета-фактуры
|
||||||
|
|
@ -1199,8 +1198,8 @@ function load_selected_invoices(frm, invoice_ids, token, warehouse, processed_co
|
||||||
let total = r.message.totalAmount || r.message.amount || 0;
|
let total = r.message.totalAmount || r.message.amount || 0;
|
||||||
|
|
||||||
update_loading_message(
|
update_loading_message(
|
||||||
__('Загрузка инвойса (' + (processed_count + 1) + ' из ' + (processed_count + invoice_ids.length + 1) + ')'),
|
__('Loading invoice (' + (processed_count + 1) + ' of ' + (processed_count + invoice_ids.length + 1) + ')'),
|
||||||
__('Импорт данных инвойса: ') + serialNumber
|
__('Importing invoice data: ') + serialNumber
|
||||||
);
|
);
|
||||||
|
|
||||||
// Импортируем данные инвойса с указанием даты и склада
|
// Импортируем данные инвойса с указанием даты и склада
|
||||||
|
|
@ -1222,7 +1221,7 @@ function load_selected_invoices(frm, invoice_ids, token, warehouse, processed_co
|
||||||
if (import_r.message && import_r.message.success) {
|
if (import_r.message && import_r.message.success) {
|
||||||
// Показываем уведомление об успешном импорте
|
// Показываем уведомление об успешном импорте
|
||||||
frappe.show_alert({
|
frappe.show_alert({
|
||||||
message: __('Инвойс успешно импортирован: ') + serialNumber,
|
message: __('Invoice successfully imported: ') + serialNumber,
|
||||||
indicator: 'green'
|
indicator: 'green'
|
||||||
}, 3);
|
}, 3);
|
||||||
|
|
||||||
|
|
@ -1268,7 +1267,7 @@ function load_selected_invoices(frm, invoice_ids, token, warehouse, processed_co
|
||||||
} else {
|
} else {
|
||||||
// Обрабатываем ошибку создания E-Taxes Purchase
|
// Обрабатываем ошибку создания E-Taxes Purchase
|
||||||
frappe.show_alert({
|
frappe.show_alert({
|
||||||
message: __('Ошибка при создании E-Taxes Purchase'),
|
message: __('Error creating E-Taxes Purchase'),
|
||||||
indicator: 'red'
|
indicator: 'red'
|
||||||
}, 3);
|
}, 3);
|
||||||
|
|
||||||
|
|
@ -1295,13 +1294,13 @@ function load_selected_invoices(frm, invoice_ids, token, warehouse, processed_co
|
||||||
|
|
||||||
// Останавливаем загрузку, так как требуется вмешательство пользователя
|
// Останавливаем загрузку, так как требуется вмешательство пользователя
|
||||||
frappe.msgprint({
|
frappe.msgprint({
|
||||||
title: __('Импорт остановлен'),
|
title: __('Import stopped'),
|
||||||
indicator: 'red',
|
indicator: 'red',
|
||||||
message: __('Для продолжения необходимо создать недостающие сопоставления')
|
message: __('To continue, you need to create missing mappings')
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
frappe.show_alert({
|
frappe.show_alert({
|
||||||
message: __('Ошибка импорта: ') + serialNumber,
|
message: __('Import error: ') + serialNumber,
|
||||||
indicator: 'red'
|
indicator: 'red'
|
||||||
}, 3);
|
}, 3);
|
||||||
|
|
||||||
|
|
@ -1327,7 +1326,7 @@ function load_selected_invoices(frm, invoice_ids, token, warehouse, processed_co
|
||||||
callback: function(login_r) {
|
callback: function(login_r) {
|
||||||
if (login_r.message && login_r.message.found && login_r.message.main_token) {
|
if (login_r.message && login_r.message.found && login_r.message.main_token) {
|
||||||
// Показываем диалог с прогрессом снова
|
// Показываем диалог с прогрессом снова
|
||||||
show_loading_dialog(__('Возобновление загрузки инвойсов...'), true);
|
show_loading_dialog(__('Resuming invoice loading...'), true);
|
||||||
update_progress(processed_count, processed_count + invoice_ids.length + 1);
|
update_progress(processed_count, processed_count + invoice_ids.length + 1);
|
||||||
|
|
||||||
// Возвращаем текущий инвойс в начало списка
|
// Возвращаем текущий инвойс в начало списка
|
||||||
|
|
@ -1337,9 +1336,9 @@ function load_selected_invoices(frm, invoice_ids, token, warehouse, processed_co
|
||||||
load_selected_invoices(frm, invoice_ids, login_r.message.main_token, warehouse, processed_count);
|
load_selected_invoices(frm, invoice_ids, login_r.message.main_token, warehouse, processed_count);
|
||||||
} else {
|
} else {
|
||||||
frappe.msgprint({
|
frappe.msgprint({
|
||||||
title: __('Ошибка'),
|
title: __('Error'),
|
||||||
indicator: 'red',
|
indicator: 'red',
|
||||||
message: __('Не удалось получить токен после авторизации')
|
message: __('Failed to get token after authentication')
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1356,7 +1355,7 @@ function load_selected_invoices(frm, invoice_ids, token, warehouse, processed_co
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
frappe.show_alert({
|
frappe.show_alert({
|
||||||
message: __('Ошибка загрузки данных инвойса'),
|
message: __('Error loading invoice data'),
|
||||||
indicator: 'red'
|
indicator: 'red'
|
||||||
}, 3);
|
}, 3);
|
||||||
|
|
||||||
|
|
@ -1373,12 +1372,12 @@ function load_selected_invoices(frm, invoice_ids, token, warehouse, processed_co
|
||||||
function show_unmatched_items_dialog(invoice_data, unmatched_items) {
|
function show_unmatched_items_dialog(invoice_data, unmatched_items) {
|
||||||
// Создаем таблицу с несопоставленными товарами
|
// Создаем таблицу с несопоставленными товарами
|
||||||
var items_table = '<div class="text-center mb-3">' +
|
var items_table = '<div class="text-center mb-3">' +
|
||||||
'<p>' + __('Для завершения импорта необходимо создать сопоставления для следующих товаров:') + '</p>' +
|
'<p>' + __('To complete the import, you need to create mappings for the following items:') + '</p>' +
|
||||||
'</div>' +
|
'</div>' +
|
||||||
'<div style="max-height: 300px; overflow-y: auto;"><table class="table table-bordered">';
|
'<div style="max-height: 300px; overflow-y: auto;"><table class="table table-bordered">';
|
||||||
items_table += '<thead><tr>' +
|
items_table += '<thead><tr>' +
|
||||||
'<th>' + __('Название') + '</th>' +
|
'<th>' + __('Name') + '</th>' +
|
||||||
'<th>' + __('Код') + '</th>' +
|
'<th>' + __('Code') + '</th>' +
|
||||||
'</tr></thead><tbody>';
|
'</tr></thead><tbody>';
|
||||||
|
|
||||||
unmatched_items.forEach(function(item) {
|
unmatched_items.forEach(function(item) {
|
||||||
|
|
@ -1392,7 +1391,7 @@ function show_unmatched_items_dialog(invoice_data, unmatched_items) {
|
||||||
|
|
||||||
// Создаем диалог
|
// Создаем диалог
|
||||||
var d = new frappe.ui.Dialog({
|
var d = new frappe.ui.Dialog({
|
||||||
title: __('Несопоставленные товары'),
|
title: __('Unmapped items'),
|
||||||
fields: [
|
fields: [
|
||||||
{
|
{
|
||||||
fieldname: 'items_html',
|
fieldname: 'items_html',
|
||||||
|
|
@ -1400,14 +1399,14 @@ function show_unmatched_items_dialog(invoice_data, unmatched_items) {
|
||||||
options: items_table
|
options: items_table
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
primary_action_label: __('Перейти к настройкам'),
|
primary_action_label: __('Go to settings'),
|
||||||
primary_action: function() {
|
primary_action: function() {
|
||||||
d.hide();
|
d.hide();
|
||||||
|
|
||||||
// Переходим к настройкам E-Taxes
|
// Переходим к настройкам E-Taxes
|
||||||
frappe.set_route('Form', 'E-Taxes Settings');
|
frappe.set_route('Form', 'E-Taxes Settings');
|
||||||
},
|
},
|
||||||
secondary_action_label: __('Отмена'),
|
secondary_action_label: __('Cancel'),
|
||||||
secondary_action: function() {
|
secondary_action: function() {
|
||||||
d.hide();
|
d.hide();
|
||||||
}
|
}
|
||||||
|
|
@ -1420,22 +1419,22 @@ function show_unmatched_items_dialog(invoice_data, unmatched_items) {
|
||||||
function show_unmatched_parties_dialog(invoice_data, unmatched_parties) {
|
function show_unmatched_parties_dialog(invoice_data, unmatched_parties) {
|
||||||
// Создаем таблицу с несопоставленными контрагентами
|
// Создаем таблицу с несопоставленными контрагентами
|
||||||
var parties_table = '<div class="text-center mb-3">' +
|
var parties_table = '<div class="text-center mb-3">' +
|
||||||
'<p>' + __('Для завершения импорта необходимо создать сопоставления для следующих контрагентов:') + '</p>' +
|
'<p>' + __('To complete the import, you need to create mappings for the following partners:') + '</p>' +
|
||||||
'</div>' +
|
'</div>' +
|
||||||
'<div style="max-height: 300px; overflow-y: auto;"><table class="table table-bordered">';
|
'<div style="max-height: 300px; overflow-y: auto;"><table class="table table-bordered">';
|
||||||
parties_table += '<thead><tr>' +
|
parties_table += '<thead><tr>' +
|
||||||
'<th>' + __('Название') + '</th>' +
|
'<th>' + __('Name') + '</th>' +
|
||||||
'<th>' + __('ИНН/VOEN') + '</th>' +
|
'<th>' + __('TIN/VOEN') + '</th>' +
|
||||||
'<th>' + __('Тип') + '</th>' +
|
'<th>' + __('Type') + '</th>' +
|
||||||
'</tr></thead><tbody>';
|
'</tr></thead><tbody>';
|
||||||
|
|
||||||
unmatched_parties.forEach(function(party) {
|
unmatched_parties.forEach(function(party) {
|
||||||
// Преобразуем тип контрагента для отображения
|
// Преобразуем тип контрагента для отображения
|
||||||
let partyTypeDisplay = '';
|
let partyTypeDisplay = '';
|
||||||
if (party.type === 'Sender') {
|
if (party.type === 'Sender') {
|
||||||
partyTypeDisplay = 'Поставщик (Sender)';
|
partyTypeDisplay = 'Supplier (Sender)';
|
||||||
} else if (party.type === 'Receiver') {
|
} else if (party.type === 'Receiver') {
|
||||||
partyTypeDisplay = 'Клиент (Receiver)';
|
partyTypeDisplay = 'Customer (Receiver)';
|
||||||
} else {
|
} else {
|
||||||
partyTypeDisplay = party.type || '';
|
partyTypeDisplay = party.type || '';
|
||||||
}
|
}
|
||||||
|
|
@ -1451,7 +1450,7 @@ function show_unmatched_parties_dialog(invoice_data, unmatched_parties) {
|
||||||
|
|
||||||
// Создаем диалог
|
// Создаем диалог
|
||||||
var d = new frappe.ui.Dialog({
|
var d = new frappe.ui.Dialog({
|
||||||
title: __('Несопоставленные контрагенты'),
|
title: __('Unmapped partners'),
|
||||||
fields: [
|
fields: [
|
||||||
{
|
{
|
||||||
fieldname: 'parties_html',
|
fieldname: 'parties_html',
|
||||||
|
|
@ -1459,14 +1458,14 @@ function show_unmatched_parties_dialog(invoice_data, unmatched_parties) {
|
||||||
options: parties_table
|
options: parties_table
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
primary_action_label: __('Перейти к настройкам'),
|
primary_action_label: __('Go to settings'),
|
||||||
primary_action: function() {
|
primary_action: function() {
|
||||||
d.hide();
|
d.hide();
|
||||||
|
|
||||||
// Переходим к настройкам E-Taxes
|
// Переходим к настройкам E-Taxes
|
||||||
frappe.set_route('Form', 'E-Taxes Settings');
|
frappe.set_route('Form', 'E-Taxes Settings');
|
||||||
},
|
},
|
||||||
secondary_action_label: __('Отмена'),
|
secondary_action_label: __('Cancel'),
|
||||||
secondary_action: function() {
|
secondary_action: function() {
|
||||||
d.hide();
|
d.hide();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,11 +4,23 @@ frappe.form.link_formatters['E-Taxes Item'] = function(value, doc) {
|
||||||
|
|
||||||
frappe.ui.form.on('E-Taxes Settings', {
|
frappe.ui.form.on('E-Taxes Settings', {
|
||||||
refresh: function(frm) {
|
refresh: function(frm) {
|
||||||
|
|
||||||
|
|
||||||
|
frm.fields_dict['item_mappings'].grid.add_custom_button(__('Bulk Edit'), function() {
|
||||||
|
bulk_edit_table(frm, 'item_mappings');
|
||||||
|
});
|
||||||
|
|
||||||
|
// Добавляем кнопку "Bulk Edit" для табличной части party_mappings
|
||||||
|
frm.fields_dict['party_mappings'].grid.add_custom_button(__('Bulk Edit'), function() {
|
||||||
|
bulk_edit_table(frm, 'party_mappings');
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
// Кнопка для сопоставления товаров по похожему названию
|
// Кнопка для сопоставления товаров по похожему названию
|
||||||
frm.add_custom_button(__('Сопоставить товары по похожему названию'), function() {
|
frm.add_custom_button(__('Match items by similar name'), function() {
|
||||||
if(frm.is_dirty()) {
|
if(frm.is_dirty()) {
|
||||||
frappe.confirm(
|
frappe.confirm(
|
||||||
__('Документ содержит несохраненные изменения. Сохранить перед выполнением операции?'),
|
__('Document contains unsaved changes. Save before performing the operation?'),
|
||||||
function() {
|
function() {
|
||||||
// Если "Да", сохраняем и выполняем действие
|
// Если "Да", сохраняем и выполняем действие
|
||||||
frm.save().then(function() {
|
frm.save().then(function() {
|
||||||
|
|
@ -18,7 +30,7 @@ frappe.ui.form.on('E-Taxes Settings', {
|
||||||
function() {
|
function() {
|
||||||
// Если "Нет", не делаем ничего
|
// Если "Нет", не делаем ничего
|
||||||
frappe.show_alert({
|
frappe.show_alert({
|
||||||
message: __('Операция отменена. Сначала сохраните документ.'),
|
message: __('Operation canceled. Please save the document first.'),
|
||||||
indicator: 'red'
|
indicator: 'red'
|
||||||
}, 5);
|
}, 5);
|
||||||
}
|
}
|
||||||
|
|
@ -30,10 +42,10 @@ frappe.ui.form.on('E-Taxes Settings', {
|
||||||
|
|
||||||
function match_similar_items() {
|
function match_similar_items() {
|
||||||
frappe.confirm(
|
frappe.confirm(
|
||||||
__('Эта операция автоматически сопоставит несопоставленные товары с похожими названиями. Продолжить?'),
|
__('This operation will automatically match unmapped items with similar names. Continue?'),
|
||||||
function() {
|
function() {
|
||||||
frappe.show_alert({
|
frappe.show_alert({
|
||||||
message: __('Выполняется сопоставление товаров...'),
|
message: __('Matching items...'),
|
||||||
indicator: 'blue'
|
indicator: 'blue'
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -42,16 +54,16 @@ frappe.ui.form.on('E-Taxes Settings', {
|
||||||
callback: function(r) {
|
callback: function(r) {
|
||||||
if (r.message && r.message.success) {
|
if (r.message && r.message.success) {
|
||||||
frappe.show_alert({
|
frappe.show_alert({
|
||||||
message: __('Сопоставлено {0} из {1} товаров',
|
message: __('Matched {0} of {1} items',
|
||||||
[r.message.matched_count, r.message.total_processed]),
|
[r.message.matched_count, r.message.total_processed]),
|
||||||
indicator: 'green'
|
indicator: 'green'
|
||||||
}, 5);
|
}, 5);
|
||||||
frm.reload_doc();
|
frm.reload_doc();
|
||||||
} else {
|
} else {
|
||||||
frappe.msgprint({
|
frappe.msgprint({
|
||||||
title: __('Ошибка'),
|
title: __('Error'),
|
||||||
indicator: 'red',
|
indicator: 'red',
|
||||||
message: r.message ? r.message.message : __('Ошибка сопоставления товаров')
|
message: r.message ? r.message.message : __('Error matching items')
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -59,13 +71,13 @@ frappe.ui.form.on('E-Taxes Settings', {
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}, __('Товары'));
|
}, __('Items'));
|
||||||
|
|
||||||
// Кнопка для создания товаров-соответствий
|
// Кнопка для создания товаров-соответствий
|
||||||
frm.add_custom_button(__('Создать товары-соответствия'), function() {
|
frm.add_custom_button(__('Create matching items'), function() {
|
||||||
if(frm.is_dirty()) {
|
if(frm.is_dirty()) {
|
||||||
frappe.confirm(
|
frappe.confirm(
|
||||||
__('Документ содержит несохраненные изменения. Сохранить перед выполнением операции?'),
|
__('Document contains unsaved changes. Save before performing the operation?'),
|
||||||
function() {
|
function() {
|
||||||
// Если "Да", сохраняем и выполняем действие
|
// Если "Да", сохраняем и выполняем действие
|
||||||
frm.save().then(function() {
|
frm.save().then(function() {
|
||||||
|
|
@ -75,7 +87,7 @@ frappe.ui.form.on('E-Taxes Settings', {
|
||||||
function() {
|
function() {
|
||||||
// Если "Нет", не делаем ничего
|
// Если "Нет", не делаем ничего
|
||||||
frappe.show_alert({
|
frappe.show_alert({
|
||||||
message: __('Операция отменена. Сначала сохраните документ.'),
|
message: __('Operation canceled. Please save the document first.'),
|
||||||
indicator: 'red'
|
indicator: 'red'
|
||||||
}, 5);
|
}, 5);
|
||||||
}
|
}
|
||||||
|
|
@ -87,11 +99,11 @@ frappe.ui.form.on('E-Taxes Settings', {
|
||||||
|
|
||||||
function create_unmapped_items() {
|
function create_unmapped_items() {
|
||||||
frappe.confirm(
|
frappe.confirm(
|
||||||
__('<div style="color: red; font-weight: bold;">ВНИМАНИЕ! Это действие создаст новые товары в системе для всех несопоставленных элементов!</div><p>Это действие необратимо. Вы уверены?</p>'),
|
__('<div style="color: red; font-weight: bold;">WARNING! This action will create new items in the system for all unmapped elements!</div><p>This action is irreversible. Are you sure?</p>'),
|
||||||
function() {
|
function() {
|
||||||
// Дополнительное подтверждение
|
// Дополнительное подтверждение
|
||||||
frappe.confirm(
|
frappe.confirm(
|
||||||
__('Вы действительно уверены, что хотите создать новые товары? Это нельзя будет отменить.'),
|
__('Are you really sure you want to create new items? This cannot be undone.'),
|
||||||
function() {
|
function() {
|
||||||
frappe.call({
|
frappe.call({
|
||||||
method: 'invoice_az.api.create_unmapped_items',
|
method: 'invoice_az.api.create_unmapped_items',
|
||||||
|
|
@ -101,15 +113,15 @@ frappe.ui.form.on('E-Taxes Settings', {
|
||||||
callback: function(r) {
|
callback: function(r) {
|
||||||
if (r.message && r.message.success) {
|
if (r.message && r.message.success) {
|
||||||
frappe.show_alert({
|
frappe.show_alert({
|
||||||
message: __('Создано {0} новых товаров', [r.message.created_count]),
|
message: __('Created {0} new items', [r.message.created_count]),
|
||||||
indicator: 'green'
|
indicator: 'green'
|
||||||
}, 5);
|
}, 5);
|
||||||
frm.reload_doc();
|
frm.reload_doc();
|
||||||
} else {
|
} else {
|
||||||
frappe.msgprint({
|
frappe.msgprint({
|
||||||
title: __('Ошибка'),
|
title: __('Error'),
|
||||||
indicator: 'red',
|
indicator: 'red',
|
||||||
message: r.message ? r.message.message : __('Ошибка создания товаров')
|
message: r.message ? r.message.message : __('Error creating items')
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -119,13 +131,13 @@ frappe.ui.form.on('E-Taxes Settings', {
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}, __('Товары'));
|
}, __('Items'));
|
||||||
|
|
||||||
// Кнопка для добавления несопоставленных товаров в таблицу
|
// Кнопка для добавления несопоставленных товаров в таблицу
|
||||||
frm.add_custom_button(__('Добавить несопоставленные товары'), function() {
|
frm.add_custom_button(__('Add unmapped items'), function() {
|
||||||
if(frm.is_dirty()) {
|
if(frm.is_dirty()) {
|
||||||
frappe.confirm(
|
frappe.confirm(
|
||||||
__('Документ содержит несохраненные изменения. Сохранить перед выполнением операции?'),
|
__('Document contains unsaved changes. Save before performing the operation?'),
|
||||||
function() {
|
function() {
|
||||||
// Если "Да", сохраняем и выполняем действие
|
// Если "Да", сохраняем и выполняем действие
|
||||||
frm.save().then(function() {
|
frm.save().then(function() {
|
||||||
|
|
@ -135,7 +147,7 @@ frappe.ui.form.on('E-Taxes Settings', {
|
||||||
function() {
|
function() {
|
||||||
// Если "Нет", не делаем ничего
|
// Если "Нет", не делаем ничего
|
||||||
frappe.show_alert({
|
frappe.show_alert({
|
||||||
message: __('Операция отменена. Сначала сохраните документ.'),
|
message: __('Operation canceled. Please save the document first.'),
|
||||||
indicator: 'red'
|
indicator: 'red'
|
||||||
}, 5);
|
}, 5);
|
||||||
}
|
}
|
||||||
|
|
@ -170,32 +182,32 @@ frappe.ui.form.on('E-Taxes Settings', {
|
||||||
});
|
});
|
||||||
frm.refresh_field('item_mappings');
|
frm.refresh_field('item_mappings');
|
||||||
frappe.show_alert({
|
frappe.show_alert({
|
||||||
message: __('Добавлено {0} несопоставленных товаров', [r.message.items.length]),
|
message: __('Added {0} unmapped items', [r.message.items.length]),
|
||||||
indicator: 'green'
|
indicator: 'green'
|
||||||
}, 5);
|
}, 5);
|
||||||
} else {
|
} else {
|
||||||
frappe.show_alert({
|
frappe.show_alert({
|
||||||
message: __('Нет несопоставленных товаров'),
|
message: __('No unmapped items'),
|
||||||
indicator: 'blue'
|
indicator: 'blue'
|
||||||
}, 5);
|
}, 5);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
frappe.msgprint({
|
frappe.msgprint({
|
||||||
title: __('Ошибка'),
|
title: __('Error'),
|
||||||
indicator: 'red',
|
indicator: 'red',
|
||||||
message: r.message ? r.message.message : __('Ошибка получения товаров')
|
message: r.message ? r.message.message : __('Error retrieving items')
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}, __('Товары'));
|
}, __('Items'));
|
||||||
|
|
||||||
// Аналогичные кнопки для контрагентов
|
// Аналогичные кнопки для контрагентов
|
||||||
frm.add_custom_button(__('Сопоставить контрагентов по похожему названию'), function() {
|
frm.add_custom_button(__('Match partners by similar name'), function() {
|
||||||
if(frm.is_dirty()) {
|
if(frm.is_dirty()) {
|
||||||
frappe.confirm(
|
frappe.confirm(
|
||||||
__('Документ содержит несохраненные изменения. Сохранить перед выполнением операции?'),
|
__('Document contains unsaved changes. Save before performing the operation?'),
|
||||||
function() {
|
function() {
|
||||||
// Если "Да", сохраняем и выполняем действие
|
// Если "Да", сохраняем и выполняем действие
|
||||||
frm.save().then(function() {
|
frm.save().then(function() {
|
||||||
|
|
@ -205,7 +217,7 @@ frappe.ui.form.on('E-Taxes Settings', {
|
||||||
function() {
|
function() {
|
||||||
// Если "Нет", не делаем ничего
|
// Если "Нет", не делаем ничего
|
||||||
frappe.show_alert({
|
frappe.show_alert({
|
||||||
message: __('Операция отменена. Сначала сохраните документ.'),
|
message: __('Operation canceled. Please save the document first.'),
|
||||||
indicator: 'red'
|
indicator: 'red'
|
||||||
}, 5);
|
}, 5);
|
||||||
}
|
}
|
||||||
|
|
@ -217,10 +229,10 @@ frappe.ui.form.on('E-Taxes Settings', {
|
||||||
|
|
||||||
function match_similar_parties() {
|
function match_similar_parties() {
|
||||||
frappe.confirm(
|
frappe.confirm(
|
||||||
__('Эта операция автоматически сопоставит несопоставленных контрагентов с похожими названиями. Продолжить?'),
|
__('This operation will automatically match unmapped partners with similar names. Continue?'),
|
||||||
function() {
|
function() {
|
||||||
frappe.show_alert({
|
frappe.show_alert({
|
||||||
message: __('Выполняется сопоставление контрагентов...'),
|
message: __('Matching partners...'),
|
||||||
indicator: 'blue'
|
indicator: 'blue'
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -229,16 +241,16 @@ frappe.ui.form.on('E-Taxes Settings', {
|
||||||
callback: function(r) {
|
callback: function(r) {
|
||||||
if (r.message && r.message.success) {
|
if (r.message && r.message.success) {
|
||||||
frappe.show_alert({
|
frappe.show_alert({
|
||||||
message: __('Сопоставлено {0} из {1} контрагентов',
|
message: __('Matched {0} of {1} partners',
|
||||||
[r.message.matched_count, r.message.total_processed]),
|
[r.message.matched_count, r.message.total_processed]),
|
||||||
indicator: 'green'
|
indicator: 'green'
|
||||||
}, 5);
|
}, 5);
|
||||||
frm.reload_doc();
|
frm.reload_doc();
|
||||||
} else {
|
} else {
|
||||||
frappe.msgprint({
|
frappe.msgprint({
|
||||||
title: __('Ошибка'),
|
title: __('Error'),
|
||||||
indicator: 'red',
|
indicator: 'red',
|
||||||
message: r.message ? r.message.message : __('Ошибка сопоставления контрагентов')
|
message: r.message ? r.message.message : __('Error matching partners')
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -246,12 +258,12 @@ frappe.ui.form.on('E-Taxes Settings', {
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}, __('Контрагенты'));
|
}, __('Partners'));
|
||||||
|
|
||||||
frm.add_custom_button(__('Создать контрагенты-соответствия'), function() {
|
frm.add_custom_button(__('Create matching partners'), function() {
|
||||||
if(frm.is_dirty()) {
|
if(frm.is_dirty()) {
|
||||||
frappe.confirm(
|
frappe.confirm(
|
||||||
__('Документ содержит несохраненные изменения. Сохранить перед выполнением операции?'),
|
__('Document contains unsaved changes. Save before performing the operation?'),
|
||||||
function() {
|
function() {
|
||||||
// Если "Да", сохраняем и выполняем действие
|
// Если "Да", сохраняем и выполняем действие
|
||||||
frm.save().then(function() {
|
frm.save().then(function() {
|
||||||
|
|
@ -261,7 +273,7 @@ frappe.ui.form.on('E-Taxes Settings', {
|
||||||
function() {
|
function() {
|
||||||
// Если "Нет", не делаем ничего
|
// Если "Нет", не делаем ничего
|
||||||
frappe.show_alert({
|
frappe.show_alert({
|
||||||
message: __('Операция отменена. Сначала сохраните документ.'),
|
message: __('Operation canceled. Please save the document first.'),
|
||||||
indicator: 'red'
|
indicator: 'red'
|
||||||
}, 5);
|
}, 5);
|
||||||
}
|
}
|
||||||
|
|
@ -273,11 +285,11 @@ frappe.ui.form.on('E-Taxes Settings', {
|
||||||
|
|
||||||
function create_unmapped_parties() {
|
function create_unmapped_parties() {
|
||||||
frappe.confirm(
|
frappe.confirm(
|
||||||
__('<div style="color: red; font-weight: bold;">ВНИМАНИЕ! Это действие создаст новых контрагентов в системе для всех несопоставленных элементов!</div><p>Это действие необратимо. Вы уверены?</p>'),
|
__('<div style="color: red; font-weight: bold;">WARNING! This action will create new partners in the system for all unmapped elements!</div><p>This action is irreversible. Are you sure?</p>'),
|
||||||
function() {
|
function() {
|
||||||
// Дополнительное подтверждение
|
// Дополнительное подтверждение
|
||||||
frappe.confirm(
|
frappe.confirm(
|
||||||
__('Вы действительно уверены, что хотите создать новых контрагентов? Это нельзя будет отменить.'),
|
__('Are you really sure you want to create new partners? This cannot be undone.'),
|
||||||
function() {
|
function() {
|
||||||
frappe.call({
|
frappe.call({
|
||||||
method: 'invoice_az.api.create_unmapped_parties',
|
method: 'invoice_az.api.create_unmapped_parties',
|
||||||
|
|
@ -287,15 +299,15 @@ frappe.ui.form.on('E-Taxes Settings', {
|
||||||
callback: function(r) {
|
callback: function(r) {
|
||||||
if (r.message && r.message.success) {
|
if (r.message && r.message.success) {
|
||||||
frappe.show_alert({
|
frappe.show_alert({
|
||||||
message: __('Создано {0} новых контрагентов', [r.message.created_count]),
|
message: __('Created {0} new partners', [r.message.created_count]),
|
||||||
indicator: 'green'
|
indicator: 'green'
|
||||||
}, 5);
|
}, 5);
|
||||||
frm.reload_doc();
|
frm.reload_doc();
|
||||||
} else {
|
} else {
|
||||||
frappe.msgprint({
|
frappe.msgprint({
|
||||||
title: __('Ошибка'),
|
title: __('Error'),
|
||||||
indicator: 'red',
|
indicator: 'red',
|
||||||
message: r.message ? r.message.message : __('Ошибка создания контрагентов')
|
message: r.message ? r.message.message : __('Error creating partners')
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -305,12 +317,12 @@ frappe.ui.form.on('E-Taxes Settings', {
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}, __('Контрагенты'));
|
}, __('Partners'));
|
||||||
|
|
||||||
frm.add_custom_button(__('Добавить несопоставленных контрагентов'), function() {
|
frm.add_custom_button(__('Add unmapped partners'), function() {
|
||||||
if(frm.is_dirty()) {
|
if(frm.is_dirty()) {
|
||||||
frappe.confirm(
|
frappe.confirm(
|
||||||
__('Документ содержит несохраненные изменения. Сохранить перед выполнением операции?'),
|
__('Document contains unsaved changes. Save before performing the operation?'),
|
||||||
function() {
|
function() {
|
||||||
// Если "Да", сохраняем и выполняем действие
|
// Если "Да", сохраняем и выполняем действие
|
||||||
frm.save().then(function() {
|
frm.save().then(function() {
|
||||||
|
|
@ -320,7 +332,7 @@ frappe.ui.form.on('E-Taxes Settings', {
|
||||||
function() {
|
function() {
|
||||||
// Если "Нет", не делаем ничего
|
// Если "Нет", не делаем ничего
|
||||||
frappe.show_alert({
|
frappe.show_alert({
|
||||||
message: __('Операция отменена. Сначала сохраните документ.'),
|
message: __('Operation canceled. Please save the document first.'),
|
||||||
indicator: 'red'
|
indicator: 'red'
|
||||||
}, 5);
|
}, 5);
|
||||||
}
|
}
|
||||||
|
|
@ -366,25 +378,166 @@ frappe.ui.form.on('E-Taxes Settings', {
|
||||||
});
|
});
|
||||||
frm.refresh_field('party_mappings');
|
frm.refresh_field('party_mappings');
|
||||||
frappe.show_alert({
|
frappe.show_alert({
|
||||||
message: __('Добавлено {0} несопоставленных контрагентов', [r.message.parties.length]),
|
message: __('Added {0} unmapped partners', [r.message.parties.length]),
|
||||||
indicator: 'green'
|
indicator: 'green'
|
||||||
}, 5);
|
}, 5);
|
||||||
} else {
|
} else {
|
||||||
frappe.show_alert({
|
frappe.show_alert({
|
||||||
message: __('Нет несопоставленных контрагентов'),
|
message: __('No unmapped partners'),
|
||||||
indicator: 'blue'
|
indicator: 'blue'
|
||||||
}, 5);
|
}, 5);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
frappe.msgprint({
|
frappe.msgprint({
|
||||||
title: __('Ошибка'),
|
title: __('Error'),
|
||||||
indicator: 'red',
|
indicator: 'red',
|
||||||
message: r.message ? r.message.message : __('Ошибка получения контрагентов')
|
message: r.message ? r.message.message : __('Error retrieving partners')
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}, __('Контрагенты'));
|
}, __('Partners'));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function bulk_edit_table(frm, table_field) {
|
||||||
|
// Получаем выбранные строки
|
||||||
|
const selected_rows = frm.fields_dict[table_field].grid.get_selected_children();
|
||||||
|
|
||||||
|
if (selected_rows.length === 0) {
|
||||||
|
frappe.msgprint(__("No rows selected. Please select rows to edit."));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Получаем метаданные дочернего doctype
|
||||||
|
const child_doctype = selected_rows[0].doctype;
|
||||||
|
const meta = frappe.get_meta(child_doctype);
|
||||||
|
|
||||||
|
// Формируем список полей для редактирования
|
||||||
|
const field_options = [];
|
||||||
|
const field_map = {};
|
||||||
|
|
||||||
|
meta.fields.forEach(df => {
|
||||||
|
// Исключаем служебные поля и поля только для чтения
|
||||||
|
if (!['Section Break', 'Column Break', 'Tab Break', 'HTML', 'Table', 'Button'].includes(df.fieldtype) &&
|
||||||
|
!df.read_only && !df.hidden) {
|
||||||
|
field_options.push({
|
||||||
|
label: __(df.label || frappe.model.unscrub(df.fieldname)),
|
||||||
|
value: df.fieldname
|
||||||
|
});
|
||||||
|
field_map[df.fieldname] = df;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Создаем диалог
|
||||||
|
const d = new frappe.ui.Dialog({
|
||||||
|
title: __("Bulk Edit Selected Rows"),
|
||||||
|
fields: [
|
||||||
|
{
|
||||||
|
label: __("Field to Edit"),
|
||||||
|
fieldname: "field_to_edit",
|
||||||
|
fieldtype: "Select",
|
||||||
|
options: field_options,
|
||||||
|
reqd: 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldname: "value_section",
|
||||||
|
fieldtype: "Section Break",
|
||||||
|
label: __("New Value"),
|
||||||
|
collapsible: 0,
|
||||||
|
hidden: 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldname: "value_container",
|
||||||
|
fieldtype: "HTML",
|
||||||
|
options: '<div id="value_field_container"></div>'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
primary_action_label: __("Apply"),
|
||||||
|
primary_action: function() {
|
||||||
|
// Получаем выбранное поле и значение
|
||||||
|
const field_name = d.get_value("field_to_edit");
|
||||||
|
|
||||||
|
// Если не выбрано поле
|
||||||
|
if (!field_name || !d.new_value_field) {
|
||||||
|
frappe.msgprint(__("Please select a field and enter a value."));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Получаем новое значение из динамического поля
|
||||||
|
const new_value = d.new_value_field.get_value();
|
||||||
|
|
||||||
|
// Проверяем, что значение введено
|
||||||
|
if (new_value === undefined || new_value === null || new_value === "") {
|
||||||
|
frappe.msgprint(__("Please enter a new value."));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Применяем изменения
|
||||||
|
frappe.show_alert({
|
||||||
|
message: __("Updating rows..."),
|
||||||
|
indicator: 'blue'
|
||||||
|
});
|
||||||
|
|
||||||
|
let count = 0;
|
||||||
|
const total = selected_rows.length;
|
||||||
|
const promises = [];
|
||||||
|
|
||||||
|
selected_rows.forEach(row => {
|
||||||
|
promises.push(
|
||||||
|
frappe.model.set_value(row.doctype, row.name, field_name, new_value)
|
||||||
|
.then(() => {
|
||||||
|
count++;
|
||||||
|
})
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
Promise.all(promises).then(() => {
|
||||||
|
frm.refresh_field(table_field);
|
||||||
|
frappe.show_alert({
|
||||||
|
message: __("Updated {0} rows", [count]),
|
||||||
|
indicator: 'green'
|
||||||
|
}, 5);
|
||||||
|
|
||||||
|
d.hide();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Обработчик изменения поля
|
||||||
|
d.fields_dict.field_to_edit.$input.on('change', function() {
|
||||||
|
const field_name = d.get_value("field_to_edit");
|
||||||
|
const field_def = field_map[field_name];
|
||||||
|
|
||||||
|
if (!field_def) return;
|
||||||
|
|
||||||
|
// Показываем секцию для нового значения
|
||||||
|
d.set_df_property("value_section", "hidden", 0);
|
||||||
|
|
||||||
|
// Удаляем предыдущее поле, если оно было
|
||||||
|
if (d.new_value_field) {
|
||||||
|
d.new_value_field.$wrapper.remove();
|
||||||
|
delete d.new_value_field;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Создаем новое поле нужного типа
|
||||||
|
const value_container = d.fields_dict.value_container.$wrapper.find("#value_field_container");
|
||||||
|
|
||||||
|
d.new_value_field = frappe.ui.form.make_control({
|
||||||
|
df: {
|
||||||
|
label: __("New Value for {0}", [__(field_def.label || frappe.model.unscrub(field_def.fieldname))]),
|
||||||
|
fieldname: "new_value",
|
||||||
|
fieldtype: field_def.fieldtype,
|
||||||
|
options: field_def.options || "",
|
||||||
|
reqd: 1
|
||||||
|
},
|
||||||
|
parent: value_container,
|
||||||
|
render_input: true
|
||||||
|
});
|
||||||
|
|
||||||
|
d.new_value_field.refresh();
|
||||||
|
});
|
||||||
|
|
||||||
|
d.show();
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue