hesabixWCPlugin/assets/js/hesabix.js

1875 lines
87 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* Hesabix Admin JavaScript
*
* @package Hesabix
* @author Mohammad Rezai
* @author URI https://pirouz.xyz
* @since 1.0.0
*/
jQuery(function($) {
'use strict';
const HesabixAdmin = {
jalaliMonths: ['فروردین', 'اردیبهشت', 'خرداد', 'تیر', 'مرداد', 'شهریور', 'مهر', 'آبان', 'آذر', 'دی', 'بهمن', 'اسفند'],
gregorianToJalali: function(gy, gm, gd) {
const g_d_m = [0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334];
let jy = (gy <= 1600) ? 0 : 979;
gy -= (gy <= 1600) ? 621 : 1600;
let gy2 = (gm > 2) ? (gy + 1) : gy;
let days = (365 * gy) + parseInt((gy2 + 3) / 4) - parseInt((gy2 + 99) / 100) + parseInt((gy2 + 399) / 400) - 80 + gd + g_d_m[gm - 1];
jy += 33 * parseInt(days / 12053);
days %= 12053;
jy += 4 * parseInt(days / 1461);
days %= 1461;
jy += parseInt((days - 1) / 365);
if (days > 365) days = (days - 1) % 365;
let jm = (days < 186) ? 1 + parseInt(days / 31) : 7 + parseInt((days - 186) / 30);
let jd = 1 + ((days < 186) ? (days % 31) : ((days - 186) % 30));
return [jy, jm, jd];
},
jalaliToGregorian: function(jy, jm, jd) {
let gy = (jy <= 979) ? 621 : 1600;
jy -= (jy <= 979) ? 0 : 979;
let gy2 = (jm > 2) ? (jy + 1) : jy;
let days = (365 * jy) + parseInt((jy + 3) / 4) - parseInt((jy + 99) / 100) + parseInt((jy + 399) / 400) + 80 + jd + ((jm < 7) ? (jm - 1) * 31 : ((jm - 7) * 30) + 186);
gy += 400 * parseInt(days / 146097);
days %= 146097;
if (days > 36524) {
gy += 100 * parseInt(--days / 36524);
days %= 36524;
if (days >= 365) days++;
}
gy += 4 * parseInt(days / 1461);
days %= 1461;
if (days > 365) {
gy += parseInt((days - 1) / 365);
days = (days - 1) % 365;
}
let gd = days + 1;
let sal_a = [0, 31, ((gy % 4 == 0 && gy % 100 != 0) || (gy % 400 == 0)) ? 29 : 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
let gm;
for (gm = 0; gm < 13 && gd > sal_a[gm]; gm++) gd -= sal_a[gm];
return [gy, gm, gd];
},
formatJalaliDate: function(date) {
const jalali = this.gregorianToJalali(date.getFullYear(), date.getMonth() + 1, date.getDate());
const monthName = this.jalaliMonths[jalali[1] - 1];
return `${jalali[2]} ${monthName} ${jalali[0]}`;
},
formatJalaliDateShort: function(date) {
const jalali = this.gregorianToJalali(date.getFullYear(), date.getMonth() + 1, date.getDate());
return `${jalali[0]}/${String(jalali[1]).padStart(2, '0')}/${String(jalali[2]).padStart(2, '0')}`;
},
jalaliDateToGregorian: function(jalaliString) {
const parts = jalaliString.split('/');
if (parts.length !== 3) return null;
const jy = parseInt(parts[0]);
const jm = parseInt(parts[1]);
const jd = parseInt(parts[2]);
if (isNaN(jy) || isNaN(jm) || isNaN(jd)) return null;
const gregorian = this.jalaliToGregorian(jy, jm, jd);
return new Date(gregorian[0], gregorian[1] - 1, gregorian[2]);
},
init: function() {
this.initHomeStats();
this.initUpdateChecker();
this.initExportImport();
this.initSyncOperations();
this.initProductOperations();
this.initSettingsOperations();
this.initApiOperations();
this.initTabSystem();
this.initStatusSelector();
this.initFreightSwitch();
this.initCustomApiAddress();
},
initHomeStats: function() {
if ($('#hesabix-stats-container').length > 0) {
this.loadHomeStats();
}
},
initUpdateChecker: function() {
if (document.querySelectorAll('#hesabix-check-update').length > 0) {
setTimeout(() => this.checkHesabixUpdate(), 1000);
}
},
loadHomeStats: function() {
const $iconContainer = $('#hesabix-home-connection-card .hesabix-feature-icon');
$iconContainer.find('svg').remove();
if ($iconContainer.find('.hesabix-spinner-small').length === 0) {
$iconContainer.append('<span class="hesabix-spinner-small" style="display:inline-block;vertical-align:middle;"></span>');
}
$.ajax({
url: ajaxurl,
type: 'POST',
data: {
action: 'admin_get_home_stats',
nonce: hesabix_ajax.nonce
},
success: (response) => {
if (response.success) {
this.renderStats(response.data);
} else {
this.showStatsError();
}
},
error: () => this.showStatsError()
});
},
renderStats: function(data) {
$('#hesabix-home-products-count').text(data.products_count);
$('#hesabix-home-products-label').text(data.products_label);
$('#hesabix-home-customers-count').text(data.customers_count);
$('#hesabix-home-customers-label').text(data.customers_label);
$('#hesabix-home-orders-count').text(data.orders_count);
$('#hesabix-home-orders-label').text(data.orders_label);
const $iconContainer = $('#hesabix-home-connection-card .hesabix-feature-icon');
$iconContainer.find('.hesabix-spinner-small').remove();
if ($iconContainer.find('svg').length === 0) {
$iconContainer.append('<svg width="40" height="40" viewBox="0 0 24 24" fill="currentColor"><path id="hesabix-home-connection-icon" d="" /></svg>');
}
const connectionClass = data.is_connected ? 'connected' : 'not-connected';
$('#hesabix-home-connection-card').removeClass('connected not-connected').addClass(connectionClass);
const connectionIcon = data.is_connected ?
'M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z' :
'M12 2C6.47 2 2 6.47 2 12s4.47 10 10 10 10-4.47 10-10S17.53 2 12 2zm5 13.59L15.59 17 12 13.41 8.41 17 7 15.59 10.59 12 7 8.41 8.41 7 12 10.59 15.59 7 17 8.41 13.41 12 17 15.59z';
$('#hesabix-home-connection-icon').attr('d', connectionIcon);
$('#hesabix-home-connection-text').text(data.connected_text);
$('#hesabix-home-status-label').text(data.status_label);
},
showStatsError: function() {
$('#hesabix-home-products-count').html('<span style="color:#dc3545">خطا</span>');
$('#hesabix-home-products-label').text('محصولات');
$('#hesabix-home-customers-count').html('<span style="color:#dc3545">خطا</span>');
$('#hesabix-home-customers-label').text('مشتریان');
$('#hesabix-home-orders-count').html('<span style="color:#dc3545">خطا</span>');
$('#hesabix-home-orders-label').text('سفارشات');
$('#hesabix-home-connection-card').removeClass('connected not-connected');
$('#hesabix-home-connection-icon').attr('d', '');
$('#hesabix-home-connection-text').html('<span style="color:#dc3545">خطا</span>');
$('#hesabix-home-status-label').text('وضعیت اتصال');
},
checkHesabixUpdate: function() {
const updateButtons = document.querySelectorAll('#hesabix-check-update');
updateButtons.forEach(el => {
const btn = $(el);
btn.prop('disabled', true);
btn.find('.update-text').hide();
btn.find('.update-loading').show();
});
$.ajax({
url: ajaxurl,
type: 'POST',
data: {
action: 'admin_check_for_updates',
nonce: hesabix_ajax.nonce
},
success: (response) => {
if (response.success) {
this.showUpdateResult(response.data);
} else {
this.showUpdateError(response.message);
}
},
error: () => this.showUpdateError('خطا در بررسی بروزرسانی'),
complete: () => {
updateButtons.forEach(el => {
const btn = $(el);
btn.prop('disabled', false);
btn.find('.update-text').show();
btn.find('.update-loading').hide();
});
}
});
},
showUpdateResult: function(data) {
const updateButtons = document.querySelectorAll('#hesabix-check-update');
updateButtons.forEach(el => {
const btn = $(el);
if (data.is_update_available) {
btn.removeClass('hesabix-update-badge').addClass('hesabix-badge warning');
btn.html(`
<span class="update-text">
<svg width="14" height="14" viewBox="0 0 24 24" fill="currentColor" style="margin-left: 5px;">
<path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z"/>
</svg>
نسخه جدید ${data.latest_version} موجود است
</span>
`);
btn.attr('onclick', `window.open('${data.download_url}', '_blank')`);
this.showUpdateNotification(data);
} else {
btn.removeClass('hesabix-update-badge').addClass('hesabix-badge status');
btn.html(`
<span class="update-text">
<svg width="14" height="14" viewBox="0 0 24 24" fill="currentColor" style="margin-left: 5px;">
<path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z"/>
</svg>
نسخه فعلی بروز است
</span>
`);
btn.removeAttr('onclick');
}
});
},
showUpdateError: function(message) {
const updateButtons = document.querySelectorAll('#hesabix-check-update');
updateButtons.forEach(el => {
const btn = $(el);
btn.removeClass('hesabix-update-badge').addClass('hesabix-badge danger');
btn.html(`
<span class="update-text">
<svg width="14" height="14" viewBox="0 0 24 24" fill="currentColor" style="margin-left: 5px;">
<path d="M12 2C6.47 2 2 6.47 2 12s4.47 10 10 10 10-4.47 10-10S17.53 2 12 2zm5 13.59L15.59 17 12 13.41 8.41 17 7 15.59 10.59 12 7 8.41 8.41 7 12 10.59 15.59 7 17 8.41 13.41 12 17 15.59z"/>
</svg>
${message}
</span>
`);
btn.removeAttr('onclick');
});
},
showUpdateNotification: function(data) {
const notification = $(`
<div class="hesabix-update-notification" style="
position: fixed;
top: 20px;
right: 20px;
background: white;
border-radius: 10px;
padding: 20px;
box-shadow: 0 4px 20px rgba(0,0,0,0.15);
z-index: 9999;
max-width: 400px;
border-left: 4px solid #ffc107;
">
<div style="display: flex; align-items: center; justify-content: space-between; margin-bottom: 15px;">
<h4 style="margin: 0; color: #333;">نسخه جدید موجود است!</h4>
<button class="hesabix-notification-close" style="
background: none;
border: none;
font-size: 18px;
cursor: pointer;
color: #666;
">&times;</button>
</div>
<p style="margin: 0 0 15px 0; color: #666;">
نسخه ${data.latest_version} از پلاگین حسابیکس منتشر شده است.
نسخه فعلی شما: ${data.current_version}
</p>
<div style="display: flex; gap: 10px;">
<button onclick="window.open('${data.download_url}', '_blank')" class="hesabix-btn hesabix-btn-warning" style="flex: 1;">
دانلود نسخه جدید
</button>
<button class="hesabix-notification-close hesabix-btn hesabix-btn-secondary" style="flex: 1;">
بستن
</button>
</div>
</div>
`);
notification.find('.hesabix-notification-close').on('click', () => {
notification.fadeOut(() => notification.remove());
});
$('body').append(notification);
setTimeout(() => {
notification.fadeOut(() => notification.remove());
}, 10000);
},
initExportImport: function() {
this.initExportProducts();
this.initImportProducts();
this.initExportOpeningQuantity();
this.initExportCustomers();
},
initExportProducts: function() {
$('#hesabix_export_products').submit((e) => {
e.preventDefault();
const $btn = $('#hesabix-export-product-submit');
$btn.attr('disabled', 'disabled').removeClass('button-primary')
.html('<i class="ofwc-spinner"></i> خروج محصولات...');
$('#exportProductsProgress').show();
$('#exportProductsProgressBar').css('width', '0%').attr('aria-valuenow', 0);
this.exportProducts(1, 1, 1, 0);
});
},
exportProducts: function(batch, totalBatch, total, updateCount) {
$.post(ajaxurl, {
action: 'adminExportProducts',
batch: batch,
totalBatch: totalBatch,
total: total,
updateCount: updateCount
}, (response) => {
if (response !== 'failed') {
const res = JSON.parse(response);
res.batch = parseInt(res.batch);
if (res.batch < res.totalBatch) {
const progress = Math.round((res.batch * 100) / res.totalBatch);
$('#exportProductsProgressBar').css('width', progress + '%').attr('aria-valuenow', progress);
this.exportProducts(res.batch + 1, res.totalBatch, res.total, res.updateCount);
} else {
$('#exportProductsProgressBar').css('width', '100%').attr('aria-valuenow', 100);
setTimeout(() => top.location.replace(res.redirectUrl), 1000);
}
} else {
alert('خطا در استخراج محصولات');
}
});
},
initImportProducts: function() {
$('#hesabix_import_products').submit((e) => {
e.preventDefault();
const $btn = $('#hesabix-import-product-submit');
$btn.attr('disabled', 'disabled').removeClass('button-primary')
.html('<i class="ofwc-spinner"></i> در حال ورود کالاها از حسابیکس, لطفاً صبر کنید...');
$('#importProductsProgress').show();
$('#importProductsProgressBar').css('width', '0%').attr('aria-valuenow', 0);
this.importProducts(1, 1, 1, 0);
});
},
importProducts: function(batch, totalBatch, total, updateCount) {
$.post(ajaxurl, {
action: 'adminImportProducts',
batch: batch,
totalBatch: totalBatch,
total: total,
updateCount: updateCount
}, (response) => {
if (response !== 'failed') {
const res = JSON.parse(response);
res.batch = parseInt(res.batch);
if (res.batch < res.totalBatch) {
const progress = Math.round((res.batch * 100) / res.totalBatch);
$('#importProductsProgressBar').css('width', progress + '%').attr('aria-valuenow', progress);
this.importProducts(res.batch + 1, res.totalBatch, res.total, res.updateCount);
} else {
$('#importProductsProgressBar').css('width', '100%').attr('aria-valuenow', 100);
setTimeout(() => top.location.replace(res.redirectUrl), 1000);
}
} else {
alert('خطا در وارد کردن محصولات');
}
});
},
initExportOpeningQuantity: function() {
$('#hesabix_export_products_opening_quantity').submit((e) => {
e.preventDefault();
const $btn = $('#hesabix-export-product-opening-quantity-submit');
$btn.attr('disabled', 'disabled').removeClass('button-primary')
.html('<i class="ofwc-spinner"></i> استخراج موجودی اول دوره...');
$('#exportProductsOpeningQuantityProgress').show();
$('#exportProductsOpeningQuantityProgressBar').css('width', '0%').attr('aria-valuenow', 0);
this.exportProductsOpeningQuantity(1, 1, 1);
});
},
exportProductsOpeningQuantity: function(batch, totalBatch, total) {
$.post(ajaxurl, {
action: 'adminExportProductsOpeningQuantity',
batch: batch,
totalBatch: totalBatch,
total: total
}, (response) => {
if (response !== 'failed') {
const res = JSON.parse(response);
res.batch = parseInt(res.batch);
if (res.batch < res.totalBatch) {
const progress = Math.round((res.batch * 100) / res.totalBatch);
$('#exportProductsOpeningQuantityProgressBar').css('width', progress + '%').attr('aria-valuenow', progress);
this.exportProductsOpeningQuantity(res.batch + 1, res.totalBatch, res.total);
} else {
$('#exportProductsOpeningQuantityProgressBar').css('width', '100%').attr('aria-valuenow', 100);
setTimeout(() => top.location.replace(res.redirectUrl), 1000);
}
} else {
alert('خطا در استخراج موجودی اول دوره');
}
});
},
initExportCustomers: function() {
$('#hesabix_export_customers').submit((e) => {
e.preventDefault();
const $btn = $('#hesabix-export-customer-submit');
$btn.attr('disabled', 'disabled').removeClass('button-primary')
.html('<i class="ofwc-spinner"></i> خروجی مشتریان، لطفاً صبر کنید...');
$('#exportCustomersProgress').show();
$('#exportCustomersProgressBar').css('width', '0%').attr('aria-valuenow', 0);
this.exportCustomers(1, 1, 1, 0);
});
},
exportCustomers: function(batch, totalBatch, total, updateCount) {
$.post(ajaxurl, {
action: 'adminExportCustomers',
batch: batch,
totalBatch: totalBatch,
total: total,
updateCount: updateCount
}, (response) => {
if (response !== 'failed') {
const res = JSON.parse(response);
res.batch = parseInt(res.batch);
if (res.batch < res.totalBatch) {
const progress = Math.round((res.batch * 100) / res.totalBatch);
$('#exportCustomersProgressBar').css('width', progress + '%').attr('aria-valuenow', progress);
this.exportCustomers(res.batch + 1, res.totalBatch, res.total, res.updateCount);
} else {
$('#exportCustomersProgressBar').css('width', '100%').attr('aria-valuenow', 100);
setTimeout(() => top.location.replace(res.redirectUrl), 1000);
}
} else {
alert('خطا در استخراج مشتریان');
}
});
},
initSyncOperations: function() {
this.initSyncChanges();
this.initSyncProducts();
this.initSyncOrders();
this.initUpdateCustomers();
this.initUpdateProducts();
this.initUpdateWcProducts();
this.initUpdateProductsWithFilter();
},
initSyncChanges: function() {
$('#hesabix_sync_changes').submit((e) => {
e.preventDefault();
const $btn = $('#hesabix-sync-changes-submit');
const $btnText = $btn.find('.sync-changes-text');
let $btnLoading = $btn.find('.sync-changes-loading');
if ($btnLoading.length === 0) {
$btn.append('<span class="sync-changes-loading" style="display:inline-block;vertical-align:middle;margin-right:6px;"><span class="hesabix-spinner-small" style="display:inline-block;vertical-align:middle;"></span></span>');
$btnLoading = $btn.find('.sync-changes-loading');
}
$btn.attr('disabled', 'disabled');
$btnText.hide();
$btnLoading.show();
$('#hesabix-sync-overlay').fadeIn(300);
$.post(ajaxurl, { action: 'adminSyncChanges' }, () => {
$('#hesabix-sync-overlay').fadeOut(300);
$btn.removeAttr('disabled');
$btnLoading.hide();
$btnText.show();
this.loadSyncStats();
this.showSyncMessage('success', 'همگام‌سازی تغییرات با موفقیت انجام شد.');
});
});
},
initSyncProducts: function() {
$('#hesabix_sync_products').submit((e) => {
e.preventDefault();
const $btn = $('#hesabix-sync-products-submit');
const $btnText = $btn.find('.sync-products-text');
let $btnLoading = $btn.find('.sync-products-loading');
if ($btnLoading.length === 0) {
$btn.append('<span class="sync-products-loading" style="display:inline-block;vertical-align:middle;margin-right:6px;"><span class="hesabix-spinner-small" style="display:inline-block;vertical-align:middle;"></span></span>');
$btnLoading = $btn.find('.sync-products-loading');
}
$btn.attr('disabled', 'disabled');
$btnText.hide();
$btnLoading.show();
$('#hesabix-sync-overlay').fadeIn(300);
$.post(ajaxurl, {
action: 'admin_sync_products',
batch: 1,
totalBatch: 1,
total: 1,
nonce: hesabix_ajax.nonce
}, (response) => {
if (typeof response === 'string') {
try { response = JSON.parse(response); } catch (e) { }
}
$('#hesabix-sync-overlay').fadeOut(300);
$btn.removeAttr('disabled');
$btnLoading.hide();
$btnText.show();
this.loadSyncStats();
if (response && response.success) {
this.showSyncMessage('success', response.message || 'همگام‌سازی قیمت و موجودی با موفقیت انجام شد.');
} else {
this.showSyncMessage('error', (response && response.message) ? response.message : 'خطا در همگام‌سازی قیمت و موجودی');
}
});
});
},
initSyncOrders: function() {
$('#hesabix_sync_orders').submit((e) => {
e.preventDefault();
const $btn = $('#hesabix-sync-orders-submit');
const $btnText = $btn.find('.sync-orders-text');
let $btnLoading = $btn.find('.sync-orders-loading');
if ($btnLoading.length === 0) {
$btn.append('<span class="sync-orders-loading" style="display:inline-block;vertical-align:middle;margin-right:6px;"><span class="hesabix-spinner-small" style="display:inline-block;vertical-align:middle;"></span></span>');
$btnLoading = $btn.find('.sync-orders-loading');
}
$btn.attr('disabled', 'disabled');
$btnText.hide();
$btnLoading.show();
$('#hesabix-sync-overlay').fadeIn(300);
const date = $('#hesabix_sync_order_date').val();
const endDate = $('#hesabix_sync_order_end_date').val();
$.post(ajaxurl, {
action: 'admin_sync_orders',
date: date,
endDate: endDate,
batch: 1,
totalBatch: 1,
total: 1,
updateCount: 0
}, (response) => {
if (typeof response === 'string') {
try { response = JSON.parse(response); } catch (e) { }
}
$('#hesabix-sync-overlay').fadeOut(300);
$btn.removeAttr('disabled');
$btnLoading.hide();
$btnText.show();
this.loadSyncStats();
if (response && response.success) {
this.showSyncMessage('success', response.message || 'همگام‌سازی سفارشات با موفقیت انجام شد.');
} else {
this.showSyncMessage('error', (response && response.message) ? response.message : 'خطا در همگام‌سازی سفارشات');
}
});
});
},
initUpdateCustomers: function() {
$('#hesabix_update_customers').submit((e) => {
e.preventDefault();
const $btn = $('#hesabix-update-customers-submit');
const $btnText = $btn.find('.update-customers-text');
let $btnLoading = $btn.find('.update-customers-loading');
if ($btnLoading.length === 0) {
$btn.append('<span class="update-customers-loading" style="display:inline-block;vertical-align:middle;margin-right:6px;"><span class="hesabix-spinner-small" style="display:inline-block;vertical-align:middle;"></span></span>');
$btnLoading = $btn.find('.update-customers-loading');
}
$btn.attr('disabled', 'disabled');
$btnText.hide();
$btnLoading.show();
$('#hesabix-sync-overlay').fadeIn(300);
$.post(ajaxurl, {
action: 'hesabix_update_customers',
nonce: hesabix_ajax.nonce
}, (response) => {
if (typeof response === 'string') {
try { response = JSON.parse(response); } catch (e) { }
}
$('#hesabix-sync-overlay').fadeOut(300);
$btn.removeAttr('disabled');
$btnLoading.hide();
$btnText.show();
this.loadSyncStats();
if (response && response.success) {
this.showSyncMessage('success', response.data.message || 'بروزرسانی مشتریان حسابیکس با موفقیت انجام شد.');
} else {
this.showSyncMessage('error', (response && response.data && response.data.message) ? response.data.message : 'خطا در بروزرسانی مشتریان حسابیکس');
}
});
});
},
initUpdateProducts: function() {
$('#hesabix_update_products').submit((e) => {
e.preventDefault();
const $btn = $('#hesabix-update-products-submit');
const $btnText = $btn.find('.update-products-text');
let $btnLoading = $btn.find('.update-products-loading');
if ($btnLoading.length === 0) {
$btn.append('<span class="update-products-loading" style="display:inline-block;vertical-align:middle;margin-right:6px;"><span class="hesabix-spinner-small" style="display:inline-block;vertical-align:middle;"></span></span>');
$btnLoading = $btn.find('.update-products-loading');
}
$btn.attr('disabled', 'disabled');
$btnText.hide();
$('#hesabix-sync-overlay').fadeIn(300);
$('#updateProductsProgress').show();
$('#updateProductsProgressBar').css('width', '0%').attr('aria-valuenow', 0);
this.updateProductsAjax(1, 1, 1);
});
},
initUpdateWcProducts: function() {
$('#hesabix_update_wc_products').submit((e) => {
e.preventDefault();
const $btn = $('#hesabix-update-wc-products-submit');
const $btnText = $btn.find('.update-wc-products-text');
let $btnLoading = $btn.find('.update-wc-products-loading');
if ($btnLoading.length === 0) {
$btn.append('<span class="update-wc-products-loading" style="display:inline-block;vertical-align:middle;margin-right:6px;"><span class="hesabix-spinner-small" style="display:inline-block;vertical-align:middle;"></span></span>');
$btnLoading = $btn.find('.update-wc-products-loading');
}
$btn.attr('disabled', 'disabled');
$btnText.hide();
$('#hesabix-sync-overlay').fadeIn(300);
$('#updateWcProductsProgress').show();
$('#updateWcProductsProgressBar').css('width', '0%').attr('aria-valuenow', 0);
this.updateWcProductsAjax(1, 1, 1);
});
},
updateWcProductsAjax: function(batch, totalBatch, total) {
$.ajax({
url: ajaxurl,
type: 'POST',
data: {
action: 'admin_update_wc_products',
nonce: hesabix_ajax.nonce,
batch: batch,
totalBatch: totalBatch,
total: total
},
success: (response) => {
if (typeof response === 'string') {
try { response = JSON.parse(response); } catch (e) { }
}
if (response && response.success) {
this.loadSyncStats();
$('#hesabix-sync-overlay').fadeOut(300);
this.showSyncMessage('success', response.message || 'بروزرسانی محصولات ووکامرس با موفقیت انجام شد.');
} else {
$('#hesabix-sync-overlay').fadeOut(300);
this.showSyncMessage('error', (response && response.message) ? response.message : 'خطا در بروزرسانی محصولات ووکامرس');
}
const $btn = $('#hesabix-update-wc-products-submit');
const $btnText = $btn.find('.update-wc-products-text');
const $btnLoading = $btn.find('.update-wc-products-loading');
$btn.removeAttr('disabled');
$btnLoading.hide();
$btnText.show();
$('#updateWcProductsProgress').hide();
},
error: (response) => console.log(response)
});
},
updateProductsAjax: function(batch, totalBatch, total) {
$.post(ajaxurl, {
action: 'admin_update_products',
batch: batch,
totalBatch: totalBatch,
total: total
}, (response) => {
if (typeof response === 'string') {
try { response = JSON.parse(response); } catch (e) { }
}
if (response && response.success) {
this.loadSyncStats();
$('#hesabix-sync-overlay').fadeOut(300);
this.showSyncMessage('success', response.message || 'بروزرسانی محصولات با موفقیت انجام شد.');
} else {
$('#hesabix-sync-overlay').fadeOut(300);
this.showSyncMessage('error', (response && response.message) ? response.message : 'خطا در بروزرسانی محصولات');
}
const $btn = $('#hesabix-update-products-submit');
const $btnText = $btn.find('.update-products-text');
const $btnLoading = $btn.find('.update-products-loading');
$btn.removeAttr('disabled');
$btnLoading.hide();
$btnText.show();
$('#updateProductsProgress').hide();
});
},
initUpdateProductsWithFilter: function() {
$('#hesabix_update_products_with_filter').submit((e) => {
e.preventDefault();
const submitButton = $('#hesabix-update-products-with-filter-submit');
const offset = document.getElementById("hesabix-update-products-offset").value;
const rpp = document.getElementById("hesabix-update-products-rpp").value;
submitButton.removeClass('button-primary')
.html('<i class="ofwc-spinner"></i> بروزرسانی محصولات لطفا صبر کنید...')
.attr('disabled', 'disabled');
this.updateProductsWithFilter(offset, rpp);
});
},
updateProductsWithFilter: function(offset, rpp) {
if (offset && rpp) {
$.post(ajaxurl, {
action: 'adminUpdateProductsWithFilter',
offset: offset,
rpp: rpp
}, (response) => {
if (response !== 'failed') {
const res = JSON.parse(response);
if (!res.error) {
top.location.replace(res.redirectUrl);
}
} else {
alert('خطا در بروزرسانی محصولات');
}
});
} else {
alert('فیلد ها را به درستی وارد نمایید');
const submitButton = $('#hesabix-update-products-with-filter-submit');
submitButton.addClass('button-primary')
.html('بروزرسانی محصولات در حسابیکس بر اساس فروشگاه در بازه ID مشخص شده')
.removeAttr('disabled');
}
},
showSyncMessage: function(type, message) {
$('.hesabix-sync-message').remove();
const messageClass = type === 'success' ? 'hesabix-alert-success' : 'hesabix-alert-danger';
const messageHtml = '<div class="hesabix-sync-message hesabix-alert ' + messageClass + ' hesabix-fade-in" style="margin-bottom:18px;margin-top:18px;">' +
'<svg width="20" height="20" viewBox="0 0 24 24" fill="currentColor" style="vertical-align: middle; margin-left: 8px;">' +
'<path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z" />' +
'</svg>' + message + '</div>';
const $title = $(".hesabix-tab-page-title:contains('همگام‌سازی اطلاعات')");
if ($title.length) {
$title.before(messageHtml);
$('html, body').animate({ scrollTop: $title.offset().top - 300 }, 500);
} else {
$('body').prepend(messageHtml);
$('html, body').animate({ scrollTop: 0 }, 500);
}
},
loadSyncStats: function() {
$.ajax({
url: ajaxurl,
type: 'POST',
data: {
action: 'hesabix_get_sync_stats_ajax',
nonce: hesabix_ajax.nonce
},
success: (response) => {
if (response.success && response.data) {
$('#sync-store-products-count').html(response.data.storeProductsCount);
$('#sync-hesabix-products-count').html(response.data.hesabixProductsCount);
$('#sync-linked-products-count').html(response.data.linkedProductsCount);
} else {
$('#sync-store-products-count, #sync-hesabix-products-count, #sync-linked-products-count').html('ارور');
}
},
error: () => {
$('#sync-store-products-count, #sync-hesabix-products-count, #sync-linked-products-count').html('ارور');
}
});
},
initProductOperations: function() {
this.initInvoiceSubmission();
this.initProductItemOperations();
this.initPluginDataOperations();
},
initInvoiceSubmission: function() {
$(".btn-submit-invoice").on("click", function() {
const orderId = $(this).attr("data-order-id");
const btnEl = $('.btn-submit-invoice[data-order-id=' + orderId + ']');
btnEl.attr('aria-disabled', true).addClass('disabled').html('ثبت فاکتور...');
HesabixAdmin.submitInvoice(orderId);
});
},
submitInvoice: function(orderId) {
$.post(ajaxurl, {
action: 'adminSubmitInvoice',
orderId: orderId
}, (response) => {
if (response !== 'failed') {
location.reload();
} else {
alert('خطا در ثبت فاکتور');
}
});
},
initProductItemOperations: function() {
$(".hesabix-item-save").on('click', function() {
const productId = $("#panel_product_data_hesabix").data('product-id');
const attributeId = $(this).data('id');
const code = $("#hesabix-item-" + attributeId).val();
$.post(ajaxurl, {
action: 'adminChangeProductCode',
productId: productId,
attributeId: attributeId,
code: code
}, (response) => {
$(this).prop('disabled', false);
if (response !== 'failed') {
const res = JSON.parse(response);
alert(res.error ? res.message : 'کد کالای متصل با موفقیت تغییر کرد.');
if (productId === attributeId) {
$("#hesabix_hesabix_item_code_0").val(code);
} else {
$("#hesabix_hesabix_item_code_" + attributeId).val(code);
}
} else {
alert('خطا در هنگام تغییر کد کالای متصل.');
}
});
$(this).prop('disabled', true);
});
$(".hesabix-item-delete-link").on('click', function() {
const productId = $("#panel_product_data_hesabix").data('product-id');
const attributeId = $(this).data('id');
$.post(ajaxurl, {
action: 'adminDeleteProductLink',
productId: productId,
attributeId: attributeId
}, (response) => {
$(this).prop('disabled', false);
if (response !== 'failed') {
const res = JSON.parse(response);
$("#hesabix-item-" + attributeId).val('');
if (productId === attributeId) {
$("#hesabix_hesabix_item_code_0").val('');
} else {
$("#hesabix_hesabix_item_code_" + attributeId).val('');
}
setTimeout(() => {
alert(res.error ? res.message : 'ارتباط محصول با موفقیت حذف شد');
}, 100);
} else {
alert('خطا در هنگام حذف ارتباط');
}
});
$(this).prop('disabled', true);
});
$(".hesabix-item-update").on('click', function() {
const productId = $("#panel_product_data_hesabix").data('product-id');
const attributeId = $(this).data('id');
$.post(ajaxurl, {
action: 'adminUpdateProduct',
productId: productId,
attributeId: attributeId
}, (response) => {
$(this).prop('disabled', false);
if (response !== 'failed') {
const res = JSON.parse(response);
if (res.newPrice != null) {
$("#hesabix-item-price-" + attributeId).text(res.newPrice);
}
if (res.newQuantity != null) {
$("#hesabix-item-quantity-" + attributeId).text(res.newQuantity);
}
if (res.error) {
alert(res.message);
}
} else {
alert('خطا در هنگام بروزرسانی محصول');
}
});
$(this).prop('disabled', true);
});
$("#hesabix-item-save-all").on('click', function() {
const productId = $("#panel_product_data_hesabix").data('product-id');
const itemsCode = $(".hesabix-item-code");
const itemsData = [];
for (let i = 0; i < itemsCode.length; i++) {
const item = itemsCode[i];
const attributeId = $(item).data('id');
const code = $(item).val();
itemsData.push({ attributeId: attributeId, code: code });
}
$.post(ajaxurl, {
action: 'adminChangeProductsCode',
productId: productId,
itemsData: itemsData
}, (response) => {
$(this).prop('disabled', false);
if (response !== 'failed') {
const res = JSON.parse(response);
alert(res.error ? res.message : 'کد کالاهای متصل با موفقیت تغییر کرد.');
location.reload();
} else {
alert('خطا در هنگام تغییر کد کالاهای متصل');
}
});
$(this).prop('disabled', true);
});
$("#hesabix-item-delete-link-all").on('click', function() {
const productId = $("#panel_product_data_hesabix").data('product-id');
$.post(ajaxurl, {
action: 'adminDeleteProductsLink',
productId: productId
}, (response) => {
$(this).prop('disabled', false);
if (response !== 'failed') {
const res = JSON.parse(response);
const itemsCode = $(".hesabix-item-code");
for (let i = 0; i < itemsCode.length; i++) {
const item = itemsCode[i];
$(item).val('');
}
$('[id^="hesabix_hesabix_item_code_"]').val('');
setTimeout(() => {
alert(res.error ? res.message : 'ارتباط محصولات با موفقیت حذف شد.');
}, 100);
} else {
alert('خطا در هنگام حذف ارتباط');
}
});
$(this).prop('disabled', true);
});
$("#hesabix-item-update-all").on('click', function() {
const productId = $("#panel_product_data_hesabix").data('product-id');
$.post(ajaxurl, {
action: 'adminUpdateProductAndVariations',
productId: productId
}, (response) => {
$(this).prop('disabled', false);
if (response !== 'failed') {
const res = JSON.parse(response);
if (res.error) {
alert(res.message);
return;
}
for (let i = 0; i < res.newData.length; i++) {
if (res.newData[i].newPrice != null) {
$("#hesabix-item-price-" + res.newData[i].attributeId).text(res.newData[i].newPrice);
}
if (res.newData[i].newQuantity != null) {
$("#hesabix-item-quantity-" + res.newData[i].attributeId).text(res.newData[i].newQuantity);
}
}
} else {
alert('خطا در هنگام بروزرسانی محصول');
}
});
$(this).prop('disabled', true);
});
},
initPluginDataOperations: function() {
$('#hesabix-clear-plugin-data').click(function() {
if (confirm('هشدار: با انجام این عملیات کلیه اطلاعات افزونه شامل روابط بین کالاها، مشتریان و فاکتور ها و همینطور تنظیمات افزونه حذف می گردد. آیا از انجام این عملیات مطمئن هستید؟')) {
$(this).addClass('disabled').html('حذف دیتای افزونه...');
$.post(ajaxurl, { action: 'adminClearPluginData' }, (response) => {
$(this).removeClass('disabled').html('حذف دیتای افزونه');
if (response !== 'failed') {
alert('دیتای افزونه با موفقیت حذف شد.');
} else {
alert('خطا در هنگام حذف دیتای افزونه.');
}
});
}
});
$('#hesabix-install-plugin-data').click(function() {
if (confirm('با انجام این عملیات جدول افزونه در دیتابیس وردپرس ایجاد و تنظیمات پیش فرض افزونه تنظیم می گردد. آیا از انجام این عملیات مطمئن هستید؟')) {
$(this).addClass('disabled').html('نصب دیتای افزونه...');
$.post(ajaxurl, { action: 'adminInstallPluginData' }, (response) => {
$(this).removeClass('disabled').html('نصب دیتای افزونه');
if (response !== 'failed') {
alert('دیتای افزونه با موفقیت نصب شد.');
} else {
alert('خطا در هنگام نصب دیتای افزونه.');
}
});
}
});
},
initSettingsOperations: function() {
this.initApiKeyChange();
this.initAdditionalFields();
},
initApiKeyChange: function() {
let oldApiKey = '';
$("#changeBusinessWarning").hide();
$("#hesabix_account_api").focusin(function() {
oldApiKey = $("#hesabix_account_api").val();
});
$("#hesabix_account_api").focusout(function() {
const newApiKey = $("#hesabix_account_api").val();
if (oldApiKey != '' && oldApiKey != newApiKey) {
$("#changeBusinessWarning").show();
}
});
},
initAdditionalFields: function() {
const radio = $('input:radio[name="addFieldsRadio"]');
const radioChecked = $('input:radio[name="addFieldsRadio"]:checked');
const textInput = $('.contact_text_input');
if (radioChecked.val() === '2') {
textInput.prop("disabled", false);
} else {
textInput.prop("disabled", true);
}
$(radio).on('click', function() {
if ($(this).val() === '2') {
textInput.prop("disabled", false);
} else {
textInput.prop("disabled", true);
}
});
},
initApiOperations: function() {
$(document).ready(() => {
$(document).on('click', '#save-api-settings', (e) => {
e.preventDefault();
this.saveApiSettings();
});
$(document).on('click', '#test-connection', (e) => {
e.preventDefault();
this.testApiConnection();
});
$('#hesabix_api_form').on('submit', (e) => {
e.preventDefault();
this.saveApiSettings();
});
});
},
saveApiSettings: function() {
const saveBtn = $('#save-api-settings');
const originalText = saveBtn.html();
saveBtn.addClass('loading').prop('disabled', true);
const formData = {
action: 'admin_save_api_settings',
nonce: hesabix_ajax.nonce,
api_key: $('#hesabix_account_api').val(),
api_address: $('#hesabix_api_address').val(),
custom_api_address: $('#hesabix_custom_api_address').val()
};
$.ajax({
url: ajaxurl,
type: 'POST',
data: formData,
success: (response) => {
if (response.success) {
this.showMessage('success', response.data.message);
} else {
this.showMessage('error', response.data.message || 'خطا در ذخیره تنظیمات');
}
},
error: () => this.showMessage('error', 'خطا در ارتباط با سرور'),
complete: () => {
saveBtn.removeClass('loading').prop('disabled', false).html(originalText);
}
});
},
testApiConnection: function() {
const testBtn = $('#test-connection');
const originalText = testBtn.html();
testBtn.addClass('loading').prop('disabled', true);
$.ajax({
url: ajaxurl,
type: 'POST',
data: {
action: 'admin_test_api_connection',
nonce: hesabix_ajax.nonce
},
success: (response) => {
if (response.success) {
this.showMessage('success', response.data.message);
} else {
this.showMessage('error', response.data.message || 'خطا در بررسی اتصال');
}
},
error: () => this.showMessage('error', 'خطا در ارتباط با سرور'),
complete: () => {
testBtn.removeClass('loading').prop('disabled', false).html(originalText);
}
});
},
showMessage: function(type, message) {
$('.hesabix-message').remove();
const messageClass = type === 'success' ? 'hesabix-alert-success' : 'hesabix-alert-danger';
const messageHtml = `
<div class="hesabix-message hesabix-alert ${messageClass}">
<div class="hesabix-alert-content">
<span>${message}</span>
</div>
</div>
`;
const form = $('#hesabix_api_form');
if (form.length > 0) {
form.before(messageHtml);
} else {
$('.hesabix-admin').prepend(messageHtml);
}
},
initTabSystem: function() {
const $tabs = $('.hesabix-tab');
const $tabContent = $('.hesabix-tab-content');
$tabs.on('click', (e) => {
e.preventDefault();
const $tab = $(e.currentTarget);
const tabName = $tab.attr('data-tab');
if (!$tab.hasClass('active')) {
$tabContent.html('<div class="hesabix-stats-loading"><div class="hesabix-spinner"></div><p>در حال بارگذاری...</p></div>');
$tabs.removeClass('active');
$tab.addClass('active');
$.ajax({
url: ajaxurl,
type: 'POST',
data: {
action: 'hesabix_load_tab_content',
tab: tabName,
nonce: hesabix_ajax.nonce
},
success: (response) => {
if (response.success) {
$tabContent.html(response.data.content);
this.initStatusSelector();
this.initFreightSwitch();
if (tabName === 'api') {
this.initCustomApiAddress();
}
$(document).trigger('hesabix_content_loaded');
this.initTabSpecificFunctions(tabName);
} else {
$tabContent.html('<div class="hesabix-alert hesabix-alert-danger">خطا در بارگذاری محتوا</div>');
}
},
error: () => {
$tabContent.html('<div class="hesabix-alert hesabix-alert-danger">خطا در بارگذاری محتوا</div>');
}
});
}
});
},
initTabSpecificFunctions: function(tabName) {
switch(tabName) {
case 'home':
this.loadHomeStats();
break;
case 'sync':
this.loadSyncStats();
this.initDateRangeSelector();
this.initSyncProducts();
this.initSyncOrders();
this.initUpdateCustomers();
this.initUpdateProducts();
this.initUpdateWcProducts();
break;
case 'extra':
this.initSaveExtraSettings();
break;
case 'catalog':
this.initSaveCatalogSettings();
break;
case 'invoice':
this.initSaveInvoiceSettings();
break;
case 'customers':
this.initSaveCustomersSettings();
this.initSaveCustomersFields();
break;
case 'logs':
this.initLogAjax();
break;
}
},
initStatusSelector: function() {
$('.hesabix-status-selector').each(function() {
const $container = $(this);
const $grid = $container.find('.hesabix-status-grid');
const $hiddenInput = $container.find('input[type="hidden"]');
function updateHiddenInput() {
const selectedValues = [];
$grid.find('.hesabix-status-item.selected input[type="checkbox"]').each(function() {
selectedValues.push($(this).val());
});
$hiddenInput.val(selectedValues.join(','));
}
$grid.on('click', '.hesabix-status-item', function(e) {
e.preventDefault();
const $item = $(this);
const $checkbox = $item.find('input[type="checkbox"]');
if ($item.hasClass('selected')) {
$item.removeClass('selected');
$checkbox.prop('checked', false);
} else {
$grid.find('.hesabix-status-item.selected').removeClass('selected');
$grid.find('input[type="checkbox"]').prop('checked', false);
$item.addClass('selected');
$checkbox.prop('checked', true);
}
updateHiddenInput();
});
updateHiddenInput();
});
},
initFreightSwitch: function() {
const $freightOptions = $('.hesabix-freight-option');
let $freightCodeField = $('tr.hesabix-freight-code-field');
if ($freightCodeField.length === 0) {
$freightCodeField = $('#hesabix_invoice_freight_code').closest('tr');
}
if ($freightCodeField.length === 0) {
$freightCodeField = $('tr').filter(function() {
return $(this).find('#hesabix_invoice_freight_code').length > 0;
});
}
$freightOptions.on('click', function() {
const $option = $(this);
const value = $option.data('value');
$freightOptions.removeClass('active');
$option.addClass('active');
$('#hesabix_invoice_freight').val(value);
const valueStr = String(value);
if (valueStr === '1') {
$freightCodeField.removeClass('hidden').addClass('required-field').css('display', 'table-row');
} else {
$freightCodeField.addClass('hidden').removeClass('required-field').css('display', 'none');
}
$option.animate({ scale: 0.95 }, 100).animate({ scale: 1 }, 100);
});
const initialValue = $('#hesabix_invoice_freight').val();
const initialValueStr = String(initialValue);
if (initialValueStr === '1') {
$freightCodeField.removeClass('hidden').addClass('required-field').css('display', 'table-row');
} else {
$freightCodeField.addClass('hidden').removeClass('required-field').css('display', 'none');
}
},
initCustomApiAddress: function() {
const apiAddressSelect = $('#hesabix_api_address');
const customAddressField = $('.custom-api-address-field');
function toggleCustomField() {
const selectedValue = apiAddressSelect.val();
if (selectedValue === 'custom') {
customAddressField.addClass('show');
} else {
customAddressField.removeClass('show');
}
}
toggleCustomField();
apiAddressSelect.on('change', toggleCustomField);
},
initSaveExtraSettings: function() {
$('#ajax-save-extra-settings').on('click', (e) => {
e.preventDefault();
const form = $('#hesabix_extra_form');
const formData = form.serialize();
const $btn = $('#ajax-save-extra-settings');
$btn.addClass('loading').prop('disabled', true);
$('#extra-settings-message').hide();
$.ajax({
url: ajaxurl,
type: 'POST',
data: formData + '&action=hesabix_save_extra_settings_ajax&nonce=' + hesabix_ajax.nonce,
success: (response) => {
$btn.removeClass('loading').prop('disabled', false);
const msg = response.success ?
'<div class="hesabix-alert hesabix-alert-success" style="margin-bottom:16px;">تنظیمات با موفقیت ذخیره شد.</div>' :
'<div class="hesabix-alert hesabix-alert-danger" style="margin-bottom:16px;">خطا در ذخیره تنظیمات!</div>';
$('#extra-settings-message').html(msg).fadeIn();
$('html, body').animate({ scrollTop: $('#extra-settings-message').offset().top }, 500);
},
error: () => {
$btn.removeClass('loading').prop('disabled', false);
const msg = '<div class="hesabix-alert hesabix-alert-danger" style="margin-bottom:16px;">خطا در ذخیره تنظیمات!</div>';
$('#extra-settings-message').html(msg).fadeIn();
$('html, body').animate({ scrollTop: $('#extra-settings-message').offset().top }, 500);
}
});
});
},
initSaveCatalogSettings: function() {
$('#ajax-save-catalog-settings').on('click', (e) => {
e.preventDefault();
const form = $('#hesabix_catalog_form');
const formData = form.serialize();
const $btn = $('#ajax-save-catalog-settings');
$btn.addClass('loading').prop('disabled', true);
$('#catalog-settings-message').hide();
$.ajax({
url: ajaxurl,
type: 'POST',
data: formData + '&action=hesabix_save_catalog_settings_ajax&nonce=' + hesabix_ajax.nonce,
success: (response) => {
$btn.removeClass('loading').prop('disabled', false);
const msg = response.success ?
'<div class="hesabix-alert hesabix-alert-success" style="margin-bottom:16px;">تنظیمات با موفقیت ذخیره شد.</div>' :
'<div class="hesabix-alert hesabix-alert-danger" style="margin-bottom:16px;">خطا در ذخیره تنظیمات!</div>';
$('#catalog-settings-message').html(msg).fadeIn();
$('html, body').animate({ scrollTop: 0 }, 500);
},
error: () => {
$btn.removeClass('loading').prop('disabled', false);
const msg = '<div class="hesabix-alert hesabix-alert-danger" style="margin-bottom:16px;">خطا در ذخیره تنظیمات!</div>';
$('#catalog-settings-message').html(msg).fadeIn();
$('html, body').animate({ scrollTop: 0 }, 500);
}
});
});
},
initSaveInvoiceSettings: function() {
$('#ajax-save-invoice-settings').on('click', (e) => {
e.preventDefault();
const form = $('#hesabix_invoice_form');
const formData = form.serialize();
const $btn = $('#ajax-save-invoice-settings');
$btn.addClass('loading').prop('disabled', true);
$('#invoice-settings-message').hide();
$.ajax({
url: ajaxurl,
type: 'POST',
data: formData + '&action=hesabix_save_invoice_settings_ajax&nonce=' + hesabix_ajax.nonce,
success: (response) => {
$btn.removeClass('loading').prop('disabled', false);
const msg = response.success ?
'<div class="hesabix-alert hesabix-alert-success" style="margin-bottom:16px;">تنظیمات با موفقیت ذخیره شد.</div>' :
'<div class="hesabix-alert hesabix-alert-danger" style="margin-bottom:16px;">خطا در ذخیره تنظیمات!</div>';
$('#invoice-settings-message').html(msg).fadeIn();
$('html, body').animate({ scrollTop: $('#invoice-settings-message').offset().top }, 500);
},
error: () => {
$btn.removeClass('loading').prop('disabled', false);
const msg = '<div class="hesabix-alert hesabix-alert-danger" style="margin-bottom:16px;">خطا در ذخیره تنظیمات!</div>';
$('#invoice-settings-message').html(msg).fadeIn();
$('html, body').animate({ scrollTop: $('#invoice-settings-message').offset().top }, 500);
}
});
});
},
initSaveCustomersSettings: function() {
$('#ajax-save-customers-settings').on('click', (e) => {
e.preventDefault();
const form = $('#hesabix_customers_form');
const formData = form.serialize();
const $btn = $('#ajax-save-customers-settings');
$btn.addClass('loading').prop('disabled', true);
$('#customers-settings-message').hide();
$.ajax({
url: ajaxurl,
type: 'POST',
data: formData + '&action=hesabix_save_customers_settings_ajax&nonce=' + hesabix_ajax.nonce,
success: (response) => {
$btn.removeClass('loading').prop('disabled', false);
const msg = response.success ?
'<div class="hesabix-alert hesabix-alert-success" style="margin-bottom:16px;">تنظیمات با موفقیت ذخیره شد.</div>' :
'<div class="hesabix-alert hesabix-alert-danger" style="margin-bottom:16px;">خطا در ذخیره تنظیمات!</div>';
$('#customers-settings-message').html(msg).fadeIn();
$('html, body').animate({ scrollTop: 0 }, 500);
},
error: () => {
$btn.removeClass('loading').prop('disabled', false);
const msg = '<div class="hesabix-alert hesabix-alert-danger" style="margin-bottom:16px;">خطا در ذخیره تنظیمات!</div>';
$('#customers-settings-message').html(msg).fadeIn();
$('html, body').animate({ scrollTop: 0 }, 500);
}
});
});
},
initSaveCustomersFields: function() {
$('input[name="addFieldsRadio"]').on('change', function() {
const selectedValue = $(this).val();
const $fieldsTable = $('.hesabix-table-container');
const $fieldInputs = $fieldsTable.find('input[type="checkbox"], input[type="text"]');
if (selectedValue === '2') {
$fieldInputs.prop('disabled', true);
$fieldsTable.addClass('disabled-fields');
} else {
$fieldInputs.prop('disabled', false);
$fieldsTable.removeClass('disabled-fields');
}
});
const currentSelection = $('input[name="addFieldsRadio"]:checked').val();
if (currentSelection === '2') {
const $fieldsTable = $('.hesabix-table-container');
const $fieldInputs = $fieldsTable.find('input[type="checkbox"], input[type="text"]');
$fieldInputs.prop('disabled', true);
$fieldsTable.addClass('disabled-fields');
}
$('#ajax-save-customers-fields').on('click', (e) => {
e.preventDefault();
const formData = new FormData();
const radioValue = $('input[name="addFieldsRadio"]:checked').val();
formData.append('addFieldsRadio', radioValue);
const nationalCodeCheck = $('#nationalCodeCheck').is(':checked') ? 'yes' : 'no';
const nationalCodeRequired = $('#nationalCodeRequired').is(':checked') ? 'yes' : 'no';
const nationalCode = $('#nationalCode').val();
formData.append('nationalCodeCheck', nationalCodeCheck);
formData.append('nationalCodeRequired', nationalCodeRequired);
formData.append('nationalCode', nationalCode);
const economicCodeCheck = $('#economicCodeCheck').is(':checked') ? 'yes' : 'no';
const economicCodeRequired = $('#economicCodeRequired').is(':checked') ? 'yes' : 'no';
const economicCode = $('#economicCode').val();
formData.append('economicCodeCheck', economicCodeCheck);
formData.append('economicCodeRequired', economicCodeRequired);
formData.append('economicCode', economicCode);
const registrationNumberCheck = $('#registrationNumberCheck').is(':checked') ? 'yes' : 'no';
const registrationNumberRequired = $('#registrationNumberRequired').is(':checked') ? 'yes' : 'no';
const registrationNumber = $('#registrationNumber').val();
formData.append('registrationNumberCheck', registrationNumberCheck);
formData.append('registrationNumberRequired', registrationNumberRequired);
formData.append('registrationNumber', registrationNumber);
const websiteCheck = $('#websiteCheck').is(':checked') ? 'yes' : 'no';
const websiteRequired = $('#websiteRequired').is(':checked') ? 'yes' : 'no';
const website = $('#website').val();
formData.append('websiteCheck', websiteCheck);
formData.append('websiteRequired', websiteRequired);
formData.append('website', website);
formData.append('action', 'hesabix_save_customers_fields_ajax');
formData.append('nonce', hesabix_ajax.nonce);
const $btn = $('#ajax-save-customers-fields');
$btn.addClass('loading').prop('disabled', true);
$('#customers-fields-message').hide();
$.ajax({
url: ajaxurl,
type: 'POST',
data: formData,
processData: false,
contentType: false,
success: (response) => {
$btn.removeClass('loading').prop('disabled', false);
const msg = response.success ?
'<div class="hesabix-alert hesabix-alert-success" style="margin-bottom:16px;">فیلدهای اضافی با موفقیت ذخیره شد.</div>' :
'<div class="hesabix-alert hesabix-alert-danger" style="margin-bottom:16px;">خطا در ذخیره فیلدهای اضافی!</div>';
$('#customers-fields-message').html(msg).fadeIn();
$('html, body').animate({ scrollTop: 0 }, 500);
},
error: () => {
$btn.removeClass('loading').prop('disabled', false);
const msg = '<div class="hesabix-alert hesabix-alert-danger" style="margin-bottom:16px;">خطا در ذخیره فیلدهای اضافی!</div>';
$('#customers-fields-message').html(msg).fadeIn();
$('html, body').animate({ scrollTop: 0 }, 500);
}
});
});
},
initLogAjax: function() {
this.initGetLogFile();
this.initDeleteLogFile();
this.initDeleteAllLogs();
},
initGetLogFile: function() {
$('#get-log-file').on('click', (e) => {
e.preventDefault();
const $btn = $(e.currentTarget);
const originalText = $btn.html();
$btn.prop('disabled', true).html('در حال بارگذاری...');
$.ajax({
url: ajaxurl,
type: 'POST',
data: {
action: 'hesabix_get_log_file_ajax',
nonce: hesabix_ajax.nonce
},
success: (response) => {
if (response.success) {
$('#log-content').html(response.data.content);
$('#log-modal').show();
} else {
alert('خطا در بارگذاری فایل لاگ');
}
},
error: () => alert('خطا در بارگذاری فایل لاگ'),
complete: () => {
$btn.prop('disabled', false).html(originalText);
}
});
});
},
initDeleteLogFile: function() {
$('#delete-log-file').on('click', (e) => {
e.preventDefault();
if (confirm('آیا از حذف فایل لاگ اطمینان دارید؟')) {
const $btn = $(e.currentTarget);
const originalText = $btn.html();
$btn.prop('disabled', true).html('در حال حذف...');
$.ajax({
url: ajaxurl,
type: 'POST',
data: {
action: 'hesabix_delete_log_file_ajax',
nonce: hesabix_ajax.nonce
},
success: (response) => {
if (response.success) {
alert('فایل لاگ با موفقیت حذف شد');
location.reload();
} else {
alert('خطا در حذف فایل لاگ');
}
},
error: () => alert('خطا در حذف فایل لاگ'),
complete: () => {
$btn.prop('disabled', false).html(originalText);
}
});
}
});
},
initDeleteAllLogs: function() {
$('#delete-all-logs').on('click', (e) => {
e.preventDefault();
if (confirm('آیا از حذف تمام فایل‌های لاگ اطمینان دارید؟')) {
const $btn = $(e.currentTarget);
const originalText = $btn.html();
$btn.prop('disabled', true).html('در حال حذف...');
$.ajax({
url: ajaxurl,
type: 'POST',
data: {
action: 'hesabix_delete_all_logs_ajax',
nonce: hesabix_ajax.nonce
},
success: (response) => {
if (response.success) {
alert('تمام فایل‌های لاگ با موفقیت حذف شدند');
location.reload();
} else {
alert('خطا در حذف فایل‌های لاگ');
}
},
error: () => alert('خطا در حذف فایل‌های لاگ'),
complete: () => {
$btn.prop('disabled', false).html(originalText);
}
});
}
});
},
initDateRangeSelector: function() {
const $form = $('#hesabix_sync_orders');
const $presetBtns = $('.hesabix-date-preset-btn');
const $customContainer = $('.hesabix-date-range-container');
const $selectedRange = $('.hesabix-selected-range');
const $rangeDisplay = $('#hesabix-range-display');
const $submitBtn = $('#hesabix-sync-orders-submit');
const $startDate = $('#hesabix_sync_order_date');
const $endDate = $('#hesabix_sync_order_end_date');
const $startDateJalali = $('#hesabix_sync_order_date_jalali');
const $endDateJalali = $('#hesabix_sync_order_end_date_jalali');
const $validationMsg = $('.hesabix-date-validation-message');
if ($startDate.length === 0 || $endDate.length === 0) return;
this.setPresetRange(7);
$presetBtns.filter('[data-days="7"]').addClass('active');
$presetBtns.on('click', (e) => {
e.preventDefault();
const $btn = $(e.currentTarget);
$presetBtns.removeClass('active');
$btn.addClass('active');
if ($btn.data('custom')) {
this.showCustomRange();
} else {
const days = parseInt($btn.data('days'));
this.setPresetRange(days);
this.hideCustomRange();
}
});
$startDateJalali.add($endDateJalali).on('input', (e) => {
const $input = $(e.target);
const value = $input.val();
if (value.length === 10 && /^\d{4}\/\d{2}\/\d{2}$/.test(value)) {
const gregorianDate = this.jalaliDateToGregorian(value);
if (gregorianDate) {
const isStartDate = $input.attr('id').includes('start');
const targetInput = isStartDate ? $startDate : $endDate;
targetInput.val(this.formatDateForInput(gregorianDate));
this.validateDateRange();
this.updateRangeDisplay();
}
}
});
$startDateJalali.add($endDateJalali).on('blur', (e) => {
const $input = $(e.target);
const value = $input.val();
if (value && !/^\d{4}\/\d{2}\/\d{2}$/.test(value)) {
$input.addClass('error');
} else {
$input.removeClass('error');
}
});
$form.on('submit', (e) => {
if (!this.validateDateRange()) {
e.preventDefault();
alert('Please select a valid date range before synchronizing orders.');
return false;
}
});
setTimeout(() => {
this.updateRangeDisplay();
this.showSelectedRange();
}, 100);
},
setPresetRange: function(days) {
const $startDate = $('#hesabix_sync_order_date');
const $endDate = $('#hesabix_sync_order_end_date');
const $startDateJalali = $('#hesabix_sync_order_date_jalali');
const $endDateJalali = $('#hesabix_sync_order_end_date_jalali');
const endDate = new Date();
const startDate = new Date();
startDate.setDate(endDate.getDate() - days);
$startDate.val(this.formatDateForInput(startDate));
$endDate.val(this.formatDateForInput(endDate));
$startDateJalali.val(this.formatJalaliDateShort(startDate));
$endDateJalali.val(this.formatJalaliDateShort(endDate));
this.updateRangeDisplay();
this.enableSubmitButton();
this.showSelectedRange();
},
showCustomRange: function() {
$('.hesabix-date-range-container').slideDown(300);
$('#hesabix_sync_order_date').focus();
this.validateDateRange();
},
hideCustomRange: function() {
$('.hesabix-date-range-container').slideUp(300);
this.clearValidation();
},
validateDateRange: function() {
const $startDate = $('#hesabix_sync_order_date');
const $endDate = $('#hesabix_sync_order_end_date');
const $startDateJalali = $('#hesabix_sync_order_date_jalali');
const $endDateJalali = $('#hesabix_sync_order_end_date_jalali');
const $validationMsg = $('.hesabix-date-validation-message');
const $submitBtn = $('#hesabix-sync-orders-submit');
const $selectedRange = $('.hesabix-selected-range');
const startVal = $startDate.val();
const endVal = $endDate.val();
if (!startVal || !endVal) {
this.disableSubmitButton();
this.hideSelectedRange();
return false;
}
const startDate = new Date(startVal);
const endDate = new Date(endVal);
if (startDate >= endDate) {
this.showValidationError();
this.disableSubmitButton();
this.hideSelectedRange();
return false;
}
this.clearValidation();
this.enableSubmitButton();
this.showSelectedRange();
return true;
},
showValidationError: function() {
const $startDate = $('#hesabix_sync_order_date');
const $endDate = $('#hesabix_sync_order_end_date');
const $startDateJalali = $('#hesabix_sync_order_date_jalali');
const $endDateJalali = $('#hesabix_sync_order_end_date_jalali');
const $validationMsg = $('.hesabix-date-validation-message');
$startDate.add($endDate).addClass('error');
$startDateJalali.add($endDateJalali).addClass('error');
$validationMsg.slideDown(200);
},
clearValidation: function() {
const $startDate = $('#hesabix_sync_order_date');
const $endDate = $('#hesabix_sync_order_end_date');
const $startDateJalali = $('#hesabix_sync_order_date_jalali');
const $endDateJalali = $('#hesabix_sync_order_end_date_jalali');
const $validationMsg = $('.hesabix-date-validation-message');
$startDate.add($endDate).removeClass('error');
$startDateJalali.add($endDateJalali).removeClass('error');
$validationMsg.slideUp(200);
},
updateRangeDisplay: function() {
const $startDate = $('#hesabix_sync_order_date');
const $endDate = $('#hesabix_sync_order_end_date');
const $rangeDisplay = $('#hesabix-range-display');
const startVal = $startDate.val();
const endVal = $endDate.val();
if (startVal && endVal) {
const startDate = new Date(startVal);
const endDate = new Date(endVal);
if (startDate < endDate) {
const formattedStart = this.formatDateForDisplay(startDate);
const formattedEnd = this.formatDateForDisplay(endDate);
const daysDiff = Math.ceil((endDate - startDate) / (1000 * 60 * 60 * 24));
$rangeDisplay.html(`${formattedStart} - ${formattedEnd} <span style="font-weight: normal; opacity: 0.8;">(${daysDiff} روز)</span>`);
}
}
},
showSelectedRange: function() {
const $selectedRange = $('.hesabix-selected-range');
if (!$selectedRange.is(':visible')) {
$selectedRange.slideDown(300);
}
},
hideSelectedRange: function() {
$('.hesabix-selected-range').slideUp(300);
},
enableSubmitButton: function() {
$('#hesabix-sync-orders-submit').prop('disabled', false).removeClass('disabled');
},
disableSubmitButton: function() {
$('#hesabix-sync-orders-submit').prop('disabled', true).addClass('disabled');
},
formatDateForInput: function(date) {
return date.getFullYear() + '-' +
String(date.getMonth() + 1).padStart(2, '0') + '-' +
String(date.getDate()).padStart(2, '0');
},
formatDateForDisplay: function(date) {
return this.formatJalaliDate(date);
}
};
window.loadHomeStats = HesabixAdmin.loadHomeStats.bind(HesabixAdmin);
window.checkHesabixUpdate = HesabixAdmin.checkHesabixUpdate.bind(HesabixAdmin);
window.loadSyncStats = HesabixAdmin.loadSyncStats.bind(HesabixAdmin);
window.hesabix_load_tab_content = HesabixAdmin.initTabSystem.bind(HesabixAdmin);
HesabixAdmin.init();
});
function hesabixTutorialJumpTo(time) {
const vidEl = document.getElementById('hesabix-tutorial-video');
vidEl.play();
vidEl.pause();
vidEl.currentTime = time;
vidEl.play();
}