fixed a lot of bugs, optimized code and a lot more
This commit is contained in:
parent
994917ffbc
commit
b24e35071d
File diff suppressed because it is too large
Load Diff
|
|
@ -575,9 +575,9 @@ function show_certificate_selector(certificates, asan_login_name, callback) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Function to display the invoice filter dialog
|
|
||||||
function show_invoice_filter_dialog() {
|
function show_invoice_filter_dialog() {
|
||||||
// Get previous year for start date and current date for end date
|
// Get previous year for start date and current date for end date
|
||||||
|
const minDate = moment("2020-01-01", "YYYY-MM-DD"); // Minimum date - January 1st, 2020
|
||||||
const prevYear = moment().subtract(1, 'year').year();
|
const prevYear = moment().subtract(1, 'year').year();
|
||||||
const startDate = prevYear + "-01-01"; // January 1st of previous year
|
const startDate = prevYear + "-01-01"; // January 1st of previous year
|
||||||
const endDate = moment().format('YYYY-MM-DD'); // Today
|
const endDate = moment().format('YYYY-MM-DD'); // Today
|
||||||
|
|
@ -602,24 +602,29 @@ function show_invoice_filter_dialog() {
|
||||||
fieldtype: 'Date',
|
fieldtype: 'Date',
|
||||||
label: __('To Date'),
|
label: __('To Date'),
|
||||||
default: endDate
|
default: endDate
|
||||||
},
|
|
||||||
{
|
|
||||||
fieldname: 'options_section',
|
|
||||||
fieldtype: 'Section Break',
|
|
||||||
label: __('Options')
|
|
||||||
},
|
|
||||||
{
|
|
||||||
fieldname: 'maxCount',
|
|
||||||
fieldtype: 'Int',
|
|
||||||
label: __('Maximum Number of Invoices'),
|
|
||||||
default: 200,
|
|
||||||
reqd: true
|
|
||||||
}
|
}
|
||||||
|
// Убираем фильтр по максимальному количеству инвойсов, т.к. загружаем все через пагинацию
|
||||||
],
|
],
|
||||||
primary_action_label: __('Load Items'),
|
primary_action_label: __('Load Items'),
|
||||||
primary_action: function() {
|
primary_action: function() {
|
||||||
var values = d.get_values();
|
var values = d.get_values();
|
||||||
|
|
||||||
|
// Validate date range
|
||||||
|
const fromDateMoment = moment(values.creationDateFrom, "YYYY-MM-DD");
|
||||||
|
const toDateMoment = moment(values.creationDateTo, "YYYY-MM-DD");
|
||||||
|
const todayMoment = moment();
|
||||||
|
|
||||||
|
// Check if the dates are within the allowed range
|
||||||
|
if (fromDateMoment.isBefore(minDate)) {
|
||||||
|
frappe.msgprint(__('From Date cannot be earlier than January 1, 2020'));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (toDateMoment.isAfter(todayMoment)) {
|
||||||
|
frappe.msgprint(__('To Date cannot be later than today'));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Close dialog
|
// Close dialog
|
||||||
d.hide();
|
d.hide();
|
||||||
|
|
||||||
|
|
@ -634,28 +639,79 @@ function show_invoice_filter_dialog() {
|
||||||
`${fromDate} - ${toDate}`
|
`${fromDate} - ${toDate}`
|
||||||
);
|
);
|
||||||
|
|
||||||
// Load items
|
// Начинаем загрузку с пагинацией
|
||||||
|
load_items_with_pagination(fromDate, toDate, 0, {
|
||||||
|
created_count: 0,
|
||||||
|
skipped_count: 0,
|
||||||
|
failed_count: 0,
|
||||||
|
total_invoices: 0
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
d.show();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Функция для загрузки элементов с поддержкой пагинации
|
||||||
|
function load_items_with_pagination(fromDate, toDate, offset = 0, accumulated_data = null) {
|
||||||
|
// Используем фиксированный размер партии
|
||||||
|
const maxCount = 200;
|
||||||
|
|
||||||
|
// Обновляем сообщение о загрузке с информацией о текущей партии
|
||||||
|
if (offset > 0) {
|
||||||
|
update_loading_message(
|
||||||
|
__('Loading items from E-Taxes (batch {0})', [(offset / maxCount) + 1]),
|
||||||
|
__('Processing invoices starting from {0}...', [offset])
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Загружаем элементы из E-Taxes
|
||||||
frappe.call({
|
frappe.call({
|
||||||
method: 'invoice_az.api.load_items_from_invoices',
|
method: 'invoice_az.api.load_items_from_invoices',
|
||||||
args: {
|
args: {
|
||||||
'date_from': fromDate,
|
'date_from': fromDate,
|
||||||
'date_to': toDate,
|
'date_to': toDate,
|
||||||
'max_count': values.maxCount || 200
|
'max_count': maxCount, // Всегда используем фиксированный размер
|
||||||
|
'offset': offset // Указываем текущее смещение
|
||||||
},
|
},
|
||||||
callback: function(r) {
|
callback: function(r) {
|
||||||
if (r.message && r.message.success) {
|
if (r.message && r.message.success) {
|
||||||
|
// Обновляем накопленные данные
|
||||||
|
accumulated_data.created_count += r.message.created_count || 0;
|
||||||
|
accumulated_data.skipped_count += r.message.skipped_count || 0;
|
||||||
|
accumulated_data.failed_count += r.message.failed_count || 0;
|
||||||
|
accumulated_data.total_invoices += r.message.total_invoices || 0;
|
||||||
|
|
||||||
|
// Проверяем, есть ли еще данные для загрузки
|
||||||
|
let hasMore = r.message.hasMore || false;
|
||||||
|
|
||||||
|
if (hasMore) {
|
||||||
|
// Если есть еще данные, увеличиваем смещение и загружаем следующую партию
|
||||||
|
let newOffset = offset + maxCount;
|
||||||
|
|
||||||
|
// Показываем промежуточный результат
|
||||||
|
update_loading_message(
|
||||||
|
__('Loaded {0} items so far...', [accumulated_data.created_count]),
|
||||||
|
__('Loading more data...')
|
||||||
|
);
|
||||||
|
|
||||||
|
// Рекурсивно вызываем функцию для следующей партии
|
||||||
|
load_items_with_pagination(fromDate, toDate, newOffset, accumulated_data);
|
||||||
|
} else {
|
||||||
|
// Если больше нет данных, показываем итоговый результат
|
||||||
set_loading_success(
|
set_loading_success(
|
||||||
__('Items Loaded Successfully'),
|
__('Items Loaded Successfully'),
|
||||||
__('Created {0} unique items. Skipped {1} duplicates.',
|
__('Created {0} unique items. Skipped {1} duplicates.',
|
||||||
[r.message.created_count, r.message.skipped_count || 0]),
|
[accumulated_data.created_count, accumulated_data.skipped_count]),
|
||||||
function() {
|
function() {
|
||||||
// Refresh list
|
// Refresh list
|
||||||
cur_list.refresh();
|
cur_list.refresh();
|
||||||
},
|
},
|
||||||
2000 // Автоматически закроется через 2 секунды
|
2000 // Автоматически закроется через 2 секунды
|
||||||
);
|
);
|
||||||
} else if (r.message && r.message.unauthorized) {
|
}
|
||||||
// Если ошибка авторизации, запускаем процесс авторизации заново
|
} else if (r.message && r.message.error === 'unauthorized') {
|
||||||
|
// Если ошибка авторизации, предлагаем авторизоваться заново
|
||||||
set_loading_error(
|
set_loading_error(
|
||||||
__('Authentication Required'),
|
__('Authentication Required'),
|
||||||
__('Your session has expired. Please authenticate again.'),
|
__('Your session has expired. Please authenticate again.'),
|
||||||
|
|
@ -666,7 +722,7 @@ function show_invoice_filter_dialog() {
|
||||||
loading_dialog.set_primary_action(__('Authenticate'), function() {
|
loading_dialog.set_primary_action(__('Authenticate'), function() {
|
||||||
hide_loading_dialog();
|
hide_loading_dialog();
|
||||||
|
|
||||||
// Запускаем процесс авторизации и после него повторяем загрузку
|
// Запускаем процесс аутентификации и после него повторяем загрузку
|
||||||
check_and_process_token(function() {
|
check_and_process_token(function() {
|
||||||
show_invoice_filter_dialog();
|
show_invoice_filter_dialog();
|
||||||
});
|
});
|
||||||
|
|
@ -682,10 +738,12 @@ function show_invoice_filter_dialog() {
|
||||||
r.message ? r.message.message : __('An error occurred while loading items')
|
r.message ? r.message.message : __('An error occurred while loading items')
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
error: function(xhr, status, error) {
|
||||||
|
set_loading_error(
|
||||||
|
__('Network Error'),
|
||||||
|
__('Failed to connect to server: ') + (error || 'Unknown error')
|
||||||
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
d.show();
|
|
||||||
}
|
}
|
||||||
|
|
@ -571,8 +571,10 @@ function show_certificate_selector(certificates, asan_login_name, callback) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Function to display the invoice filter dialog
|
// Function to display the invoice filter dialog
|
||||||
|
// Function to display the invoice filter dialog for partners
|
||||||
function show_invoice_filter_dialog() {
|
function show_invoice_filter_dialog() {
|
||||||
// Get previous year for start date and current date for end date
|
// Get previous year for start date and current date for end date
|
||||||
|
const minDate = moment("2020-01-01", "YYYY-MM-DD"); // Minimum date - January 1st, 2020
|
||||||
const prevYear = moment().subtract(1, 'year').year();
|
const prevYear = moment().subtract(1, 'year').year();
|
||||||
const startDate = prevYear + "-01-01"; // January 1st of previous year
|
const startDate = prevYear + "-01-01"; // January 1st of previous year
|
||||||
const endDate = moment().format('YYYY-MM-DD'); // Today
|
const endDate = moment().format('YYYY-MM-DD'); // Today
|
||||||
|
|
@ -597,24 +599,29 @@ function show_invoice_filter_dialog() {
|
||||||
fieldtype: 'Date',
|
fieldtype: 'Date',
|
||||||
label: __('To Date'),
|
label: __('To Date'),
|
||||||
default: endDate
|
default: endDate
|
||||||
},
|
|
||||||
{
|
|
||||||
fieldname: 'options_section',
|
|
||||||
fieldtype: 'Section Break',
|
|
||||||
label: __('Options')
|
|
||||||
},
|
|
||||||
{
|
|
||||||
fieldname: 'maxCount',
|
|
||||||
fieldtype: 'Int',
|
|
||||||
label: __('Maximum Number of Invoices'),
|
|
||||||
default: 200,
|
|
||||||
reqd: true
|
|
||||||
}
|
}
|
||||||
|
// Убраем фильтр по максимальному количеству инвойсов, т.к. загружаем все через пагинацию
|
||||||
],
|
],
|
||||||
primary_action_label: __('Load Parties'),
|
primary_action_label: __('Load Parties'),
|
||||||
primary_action: function() {
|
primary_action: function() {
|
||||||
var values = d.get_values();
|
var values = d.get_values();
|
||||||
|
|
||||||
|
// Validate date range
|
||||||
|
const fromDateMoment = moment(values.creationDateFrom, "YYYY-MM-DD");
|
||||||
|
const toDateMoment = moment(values.creationDateTo, "YYYY-MM-DD");
|
||||||
|
const todayMoment = moment();
|
||||||
|
|
||||||
|
// Check if the dates are within the allowed range
|
||||||
|
if (fromDateMoment.isBefore(minDate)) {
|
||||||
|
frappe.msgprint(__('From Date cannot be earlier than January 1, 2020'));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (toDateMoment.isAfter(todayMoment)) {
|
||||||
|
frappe.msgprint(__('To Date cannot be later than today'));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Close dialog
|
// Close dialog
|
||||||
d.hide();
|
d.hide();
|
||||||
|
|
||||||
|
|
@ -629,27 +636,73 @@ function show_invoice_filter_dialog() {
|
||||||
`${fromDate} - ${toDate}`
|
`${fromDate} - ${toDate}`
|
||||||
);
|
);
|
||||||
|
|
||||||
// Load parties
|
// Начинаем загрузку с пагинацией
|
||||||
|
load_parties_with_pagination(fromDate, toDate, 0, {
|
||||||
|
created_count: 0,
|
||||||
|
skipped_count: 0,
|
||||||
|
failed_count: 0,
|
||||||
|
total_invoices: 0,
|
||||||
|
unique_parties: 0
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
d.show();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Функция для загрузки партнеров с поддержкой пагинации
|
||||||
|
function load_parties_with_pagination(fromDate, toDate, offset = 0, accumulated_data = null) {
|
||||||
|
// Используем фиксированный размер партии
|
||||||
|
const maxCount = 200;
|
||||||
|
|
||||||
|
// Загружаем партнеров из E-Taxes
|
||||||
frappe.call({
|
frappe.call({
|
||||||
method: 'invoice_az.api.load_parties_from_invoices',
|
method: 'invoice_az.api.load_parties_from_invoices',
|
||||||
args: {
|
args: {
|
||||||
'date_from': fromDate,
|
'date_from': fromDate,
|
||||||
'date_to': toDate,
|
'date_to': toDate,
|
||||||
'max_count': values.maxCount || 200
|
'max_count': maxCount, // Всегда используем фиксированный размер
|
||||||
|
'offset': offset // Указываем текущее смещение
|
||||||
},
|
},
|
||||||
callback: function(r) {
|
callback: function(r) {
|
||||||
if (r.message && r.message.success) {
|
if (r.message && r.message.success) {
|
||||||
|
// Обновляем накопленные данные
|
||||||
|
accumulated_data.created_count += r.message.created_count || 0;
|
||||||
|
accumulated_data.skipped_count += r.message.skipped_count || 0;
|
||||||
|
accumulated_data.failed_count += r.message.failed_count || 0;
|
||||||
|
accumulated_data.total_invoices += r.message.total_invoices || 0;
|
||||||
|
accumulated_data.unique_parties += r.message.unique_parties || 0;
|
||||||
|
|
||||||
|
// Проверяем, есть ли еще данные для загрузки
|
||||||
|
let hasMore = r.message.hasMore || false;
|
||||||
|
|
||||||
|
if (hasMore) {
|
||||||
|
// Если есть еще данные, увеличиваем смещение и загружаем следующую партию
|
||||||
|
let newOffset = offset + maxCount;
|
||||||
|
|
||||||
|
// Обновляем сообщение о загрузке
|
||||||
|
update_loading_message(
|
||||||
|
__('Processing invoices...'),
|
||||||
|
__('Loaded {0} parties so far, loading more...', [accumulated_data.created_count])
|
||||||
|
);
|
||||||
|
|
||||||
|
// Рекурсивно вызываем функцию для следующей партии
|
||||||
|
load_parties_with_pagination(fromDate, toDate, newOffset, accumulated_data);
|
||||||
|
} else {
|
||||||
|
// Если больше нет данных, показываем итоговый результат
|
||||||
set_loading_success(
|
set_loading_success(
|
||||||
__('Parties Loaded Successfully'),
|
__('Parties Loaded Successfully'),
|
||||||
__('Created {0} unique parties. Skipped {1} duplicates.',
|
__('Created {0} unique parties. Skipped {1} duplicates.',
|
||||||
[r.message.created_count, r.message.skipped_count || 0]),
|
[accumulated_data.created_count, accumulated_data.skipped_count]),
|
||||||
function() {
|
function() {
|
||||||
// Refresh list
|
// Refresh list
|
||||||
cur_list.refresh();
|
cur_list.refresh();
|
||||||
}
|
},
|
||||||
|
2000 // Автоматически закроется через 2 секунды
|
||||||
);
|
);
|
||||||
} else if (r.message && r.message.unauthorized) {
|
}
|
||||||
// Если ошибка авторизации, запускаем процесс авторизации заново
|
} else if (r.message && r.message.error === 'unauthorized') {
|
||||||
|
// Если ошибка авторизации, предлагаем авторизоваться заново
|
||||||
set_loading_error(
|
set_loading_error(
|
||||||
__('Authentication Required'),
|
__('Authentication Required'),
|
||||||
__('Your session has expired. Please authenticate again.'),
|
__('Your session has expired. Please authenticate again.'),
|
||||||
|
|
@ -676,10 +729,12 @@ function show_invoice_filter_dialog() {
|
||||||
r.message ? r.message.message : __('An error occurred while loading parties')
|
r.message ? r.message.message : __('An error occurred while loading parties')
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
error: function(xhr, status, error) {
|
||||||
|
set_loading_error(
|
||||||
|
__('Network Error'),
|
||||||
|
__('Failed to connect to server: ') + (error || 'Unknown error')
|
||||||
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
d.show();
|
|
||||||
}
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -23,6 +23,17 @@ doc_events = {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
scheduler_events = {
|
||||||
|
"cron": {
|
||||||
|
"*/4 * * * *": [
|
||||||
|
"invoice_az.api.renew_token"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
after_install = "invoice_az.api.setup_token_renewal"
|
||||||
|
after_migrate = "invoice_az.api.setup_token_renewal"
|
||||||
|
|
||||||
# Apps
|
# Apps
|
||||||
# ------------------
|
# ------------------
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@
|
||||||
"bearer_token",
|
"bearer_token",
|
||||||
"auth_status",
|
"auth_status",
|
||||||
"verification_code",
|
"verification_code",
|
||||||
|
"last_activity_time",
|
||||||
"column_break_1",
|
"column_break_1",
|
||||||
"is_default",
|
"is_default",
|
||||||
"certificates_section",
|
"certificates_section",
|
||||||
|
|
@ -108,9 +109,7 @@
|
||||||
"description": "Primary token for all API operations",
|
"description": "Primary token for all API operations",
|
||||||
"fieldname": "main_token",
|
"fieldname": "main_token",
|
||||||
"fieldtype": "Small Text",
|
"fieldtype": "Small Text",
|
||||||
"hidden": 1,
|
"label": "Main Token"
|
||||||
"label": "Main Token",
|
|
||||||
"read_only": 1
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "choose_taxpayer_response",
|
"fieldname": "choose_taxpayer_response",
|
||||||
|
|
@ -124,11 +123,16 @@
|
||||||
"fieldname": "verification_code",
|
"fieldname": "verification_code",
|
||||||
"fieldtype": "Data",
|
"fieldtype": "Data",
|
||||||
"label": "Verification Code"
|
"label": "Verification Code"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "last_activity_time",
|
||||||
|
"fieldtype": "Datetime",
|
||||||
|
"label": "Last Activity Time"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"index_web_pages_for_search": 1,
|
"index_web_pages_for_search": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2025-05-13 14:13:35.366465",
|
"modified": "2025-05-21 14:13:47.059215",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Invoice Az",
|
"module": "Invoice Az",
|
||||||
"name": "Asan Login",
|
"name": "Asan Login",
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue